aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulien Dramaix <julien.dramaix@gmail.com>2011-04-06 21:50:43 +0000
committerJulien Dramaix <julien.dramaix@gmail.com>2011-04-06 21:50:43 +0000
commit9ff9faa965f122c4674e861d52aab58102be8043 (patch)
treec7136621bb407fd6cfc2fafa580fe664e05f0fee
parenta4f38b526593af33fed27a92041413a7893eede9 (diff)
downloadgwtquery-9ff9faa965f122c4674e861d52aab58102be8043.tar.gz
gwtquery-9ff9faa965f122c4674e861d52aab58102be8043.zip
add closest methods !
-rw-r--r--gwtquery-core/src/main/java/com/google/gwt/query/client/GQuery.java145
-rw-r--r--gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryCoreTest.java55
2 files changed, 191 insertions, 9 deletions
diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/GQuery.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/GQuery.java
index 7bbf280f..1491ea11 100644
--- a/gwtquery-core/src/main/java/com/google/gwt/query/client/GQuery.java
+++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/GQuery.java
@@ -60,6 +60,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
+import java.util.Map;
/**
* GwtQuery is a GWT clone of the popular jQuery library.
@@ -121,6 +122,9 @@ public class GQuery implements Lazy<GQuery, LazyGQuery> {
private static DocumentStyleImpl styleImpl = GWT.create(DocumentStyleImpl.class);
private static Element windowData = null;
+
+ //Sizzle POS regex : usefull in some methods
+ private static final String POS_REGEX = ":(nth|eq|gt|lt|first|last|even|odd)(?:\\((\\d*)\\))?(?=[^\\-]|$)";
/**
* Create an empty GQuery object.
@@ -197,7 +201,7 @@ public class GQuery implements Lazy<GQuery, LazyGQuery> {
* reference to a plugin to be used.
*/
public static <T extends GQuery> T $(String selector, Class<T> plugin) {
- return $(selector, (Node) null, plugin);
+ return $(selector, document, plugin);
}
/**
@@ -216,7 +220,7 @@ public class GQuery implements Lazy<GQuery, LazyGQuery> {
: ctx.getOwnerDocument();
return $(cleanHtmlString(selectorOrHtml, doc));
}
- return new GQuery(select(selectorOrHtml, ctx)).setSelector(selectorOrHtml);
+ return new GQuery().select(selectorOrHtml, ctx);
}
/**
@@ -231,7 +235,7 @@ public class GQuery implements Lazy<GQuery, LazyGQuery> {
try {
if (plugins != null) {
T gquery = (T) plugins.get(plugin).init(
- new GQuery(select(selector, context))).setSelector(selector);
+ new GQuery().select(selector, context));
return gquery;
}
throw new RuntimeException("No plugin for class " + plugin);
@@ -348,7 +352,7 @@ public class GQuery implements Lazy<GQuery, LazyGQuery> {
n = n.getLastChild();
}
// TODO: add fixes for IE TBODY issue
- return $((NodeList<Element>) n.getChildNodes().cast()).as(Events).addLiveEvents();
+ return $((NodeList<Element>) n.getChildNodes().cast());
}
protected static <S> Object data(Element item, String name, S value) {
@@ -450,13 +454,18 @@ public class GQuery implements Lazy<GQuery, LazyGQuery> {
n.scrollIntoView()
}-*/;
- private static NodeList<Element> select(String selector, Node context) {
+ private GQuery select(String selector, Node context) {
if (engine == null) {
engine = new SelectorEngine();
}
NodeList<Element> n = engine.select(selector, context);
JsNodeArray res = copyNodeList(n);
- return res;
+
+ currentSelector = selector;
+ currentContext = context != null ? context : document;
+
+ return setArray(res);
+
}
private static native Element window() /*-{
@@ -464,6 +473,7 @@ public class GQuery implements Lazy<GQuery, LazyGQuery> {
}-*/;
protected String currentSelector;
+ protected Node currentContext;
private NodeList<Element> elements = JavaScriptObject.createArray().cast();
@@ -471,6 +481,8 @@ public class GQuery implements Lazy<GQuery, LazyGQuery> {
protected GQuery(GQuery gq) {
this(gq == null ? null : gq.get());
+ currentSelector = gq.getSelector();
+ currentContext = gq.getContext();
}
private GQuery() {
@@ -772,7 +784,7 @@ public class GQuery implements Lazy<GQuery, LazyGQuery> {
} else if (plugins != null) {
Plugin<?> p = plugins.get(plugin);
if (p != null) {
- return (T) p.init(this).setSelector(currentSelector);
+ return (T) p.init(this);
}
}
throw new RuntimeException("No plugin registered for class "
@@ -957,8 +969,120 @@ public class GQuery implements Lazy<GQuery, LazyGQuery> {
for (Element e : elements()) {
result.addNode(e.cloneNode(true));
}
- return new GQuery(result).as(Events).addLiveEvents();
+ GQuery ret = new GQuery(result);
+ ret.currentContext = currentContext;
+ ret.currentSelector = currentSelector;
+ return ret;
+ }
+
+ /**
+ * Get the first ancestor element that matches the selector (for each matched element), beginning at the
+ * current element and progressing up through the DOM tree.
+ *
+ * @param selector
+ * @return
+ */
+ public GQuery closest(String selector){
+ return closest(selector, null);
+ }
+
+ /**
+ * Returns a {@link Map} object as key a selector and as value the first ancestor elements matching this selectors, beginning at the
+ * first matched element and progressing up through the DOM. This method allows retrieving the list of closest ancestors matching
+ * many selectors and by reducing the number of DOM traversing.
+ *
+ * @param selector
+ * @return
+ */
+ public Map<String, Element> closest(String[] selectors){
+ return closest(selectors, null);
}
+
+ /**
+ * Returns a GQuery object containing the first ancestor elements matching each selectors, beginning at the
+ * first matched element and progressing up through the DOM tree until reach the <code>context</code> node..
+ * This method allows retrieving the list of closest ancestors matching many selectors and by reducing the number of DOM traversing.
+ *
+ * @param selector
+ * @return
+ */
+ public Map<String, Element> closest(String[] selectors, Node context){
+ Map<String, Element> results = new HashMap<String, Element>();
+
+ if (context == null){
+ context = currentContext;
+ }
+
+ Element first = get(0);
+
+ if (first != null && selectors != null && selectors.length > 0){
+
+ Map<String, GQuery> matches = new HashMap<String, GQuery>();
+
+ for (String selector : selectors){
+ if (!matches.containsKey(selector)){
+ matches.put(selector, selector.matches(POS_REGEX) ? $(selector, context) : null);
+ }
+ }
+
+ Element current = first;
+
+ while (current != null && current.getOwnerDocument() != null && current != context){
+ //for each selector, check if the current element match it.
+ for (String selector : matches.keySet()){
+ if (results.containsKey(selector)){
+ //first ancestors already found for this selector
+ continue;
+ }
+ GQuery pos = matches.get(selector);
+ boolean match = pos != null ? pos.index(current) > -1 : $(current).is(selector);
+ if (match){
+ results.put(selector, current);
+ }
+ }
+
+ current = current.getParentElement();
+ }
+
+
+ }
+
+ return results;
+ }
+
+ /**
+ * Get the first ancestor element that matches the selector (for each matched element), beginning at the
+ * current element and progressing up through the DOM tree until reach the <code>context</code> node.
+ *
+ * If no context is passed in then the context of the gQuery object will be used instead.
+ *
+ */
+ public GQuery closest(String selector, Node context){
+ assert selector != null;
+
+ if (context == null){
+ context = currentContext;
+ }
+
+ GQuery pos = selector.matches(POS_REGEX) ? $(selector, context) : null;
+ JsNodeArray result = JsNodeArray.create();
+
+ for (Element e : elements()){
+ Element current = e;
+ while (current != null && current.getOwnerDocument() != null && current != context){
+ boolean match = pos != null ? pos.index(current) > -1 : $(current).is(selector);
+ if (match){
+ result.addNode(current);
+ break;
+ }else{
+ current = current.getParentElement();
+ }
+ }
+ }
+
+ return $(unique(result));
+
+ }
/**
* Filter the set of elements to those that contain the specified text.
@@ -1524,6 +1648,10 @@ public class GQuery implements Lazy<GQuery, LazyGQuery> {
}
return null;
}
+
+ public Node getContext() {
+ return currentContext;
+ }
/**
* Return the previous set of matched elements prior to the last destructive
@@ -3277,6 +3405,7 @@ public class GQuery implements Lazy<GQuery, LazyGQuery> {
GQuery g = new GQuery(elts);
g.setPreviousObject(this);
g.setSelector(selector);
+ g.currentContext = currentContext;
return g;
}
diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryCoreTest.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryCoreTest.java
index b3f04364..278ab826 100644
--- a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryCoreTest.java
+++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryCoreTest.java
@@ -43,6 +43,7 @@ import com.google.gwt.user.client.ui.TextArea;
import junit.framework.Assert;
import java.util.List;
+import java.util.Map;
/**
* Test class for testing gwtquery-core api.
@@ -899,7 +900,7 @@ public class GQueryCoreTest extends GWTTestCase {
Button b2 = g.widget();
assertEquals(b1, b2);
- b2 = $("<button>Click-me</button>").appendTo(document).as(Widgets).button().widget();
+ b2 = $("<button>Click-me</button>").appendTo(document).as(Widgets).widget();
b2.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
$(b1).css("color", "red");
@@ -1163,5 +1164,57 @@ public class GQueryCoreTest extends GWTTestCase {
assertEquals(expectedHtml, $(e).html());
}
+
+ public void testClosestMethod(){
+ String html = "<div><p><div id='firstDiv'><p id='firstP'><span><input id='firstInput' type='text'></input></span></p></div></p></div>";
+ $(e).html(html);
+
+ GQuery closeP = $("input", e).closest("p,div");
+
+ assertEquals(1, closeP.length());
+ assertEquals("firstP", closeP.get(0).getId());
+
+ GQuery closeDiv = $("input", e).closest("div");
+
+ assertEquals(1, closeDiv.length());
+ assertEquals("firstDiv", closeDiv.get(0).getId());
+
+ GQuery closeInput = $("input", e).closest("input");
+
+ assertEquals(1, closeInput.length());
+ assertEquals("firstInput", closeInput.get(0).getId());
+
+ GQuery closeUnknown = $("input", e).closest("h1");
+
+ assertEquals(0, closeUnknown.length());
+
+ GQuery closePWithContext = $("input", e).closest("p,div",$("#firstDiv").get(0));
+
+ assertEquals(1, closePWithContext.length());
+ assertEquals("firstP", closePWithContext.get(0).getId());
+
+ GQuery closeDivWithContext = $("input", e).closest("div",$("#firstP").get(0));
+
+ assertEquals(0, closeDivWithContext.length());
+
+ }
+
+ public void testClosestMethodWithArrayOfString(){
+
+ String html = "<div id='mainDiv' class='test'><p><div id='firstDiv'><p id='firstP'><span><input id='firstInput' type='text'></input></span></p></div></p></div>";
+ $(e).html(html);
+
+ Map<String, Element> close = $("input", e).closest(new String[]{"p","div", ".test", "#unknown"});
+
+ assertEquals(3, close.size());
+ assertNotNull(close.get("p"));
+ assertEquals("firstP", close.get("p").getId());
+ assertNotNull(close.get("div"));
+ assertEquals("firstDiv", close.get("div").getId());
+ assertNotNull(close.get(".test"));
+ assertEquals("mainDiv", close.get(".test").getId());
+ assertNull(close.get("#unknown"));
+
+ }
}