diff options
author | Julien Dramaix <julien.dramaix@gmail.com> | 2011-04-06 21:50:43 +0000 |
---|---|---|
committer | Julien Dramaix <julien.dramaix@gmail.com> | 2011-04-06 21:50:43 +0000 |
commit | 9ff9faa965f122c4674e861d52aab58102be8043 (patch) | |
tree | c7136621bb407fd6cfc2fafa580fe664e05f0fee | |
parent | a4f38b526593af33fed27a92041413a7893eede9 (diff) | |
download | gwtquery-9ff9faa965f122c4674e861d52aab58102be8043.tar.gz gwtquery-9ff9faa965f122c4674e861d52aab58102be8043.zip |
add closest methods !
-rw-r--r-- | gwtquery-core/src/main/java/com/google/gwt/query/client/GQuery.java | 145 | ||||
-rw-r--r-- | gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryCoreTest.java | 55 |
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")); + + } } |