aboutsummaryrefslogtreecommitdiffstats
path: root/gwtquery-core
diff options
context:
space:
mode:
authorManuel Carrasco Moñino <manolo@apache.org>2014-12-06 13:36:10 +0100
committerManuel Carrasco Moñino <manolo@apache.org>2014-12-06 13:36:10 +0100
commit9fb01505bf41afa0063ac4d85b51f02ac6365b8f (patch)
tree99b25ea7b5460694fceb1cb8969bdb8b9f10882d /gwtquery-core
parent64dd253a2b1643c475b46b0284e5b37abec30684 (diff)
parent93ec3586adcbc1dcced6f7ac2ecb732975f1af6d (diff)
downloadgwtquery-9fb01505bf41afa0063ac4d85b51f02ac6365b8f.tar.gz
gwtquery-9fb01505bf41afa0063ac4d85b51f02ac6365b8f.zip
Merge pull request #311 from manolo/master
Faster implementation of filter.
Diffstat (limited to 'gwtquery-core')
-rw-r--r--gwtquery-core/src/main/java/com/google/gwt/query/Query.gwt.xml9
-rw-r--r--gwtquery-core/src/main/java/com/google/gwt/query/client/GQuery.java109
-rw-r--r--gwtquery-core/src/main/java/com/google/gwt/query/client/LazyGQuery.java17
-rw-r--r--gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngine.java68
-rw-r--r--gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/LazyEffects.java7
-rw-r--r--gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/LazyEvents.java1
-rw-r--r--gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryCoreTestGwt.java1
7 files changed, 153 insertions, 59 deletions
diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/Query.gwt.xml b/gwtquery-core/src/main/java/com/google/gwt/query/Query.gwt.xml
index 8ba4fc33..3ba5c445 100644
--- a/gwtquery-core/src/main/java/com/google/gwt/query/Query.gwt.xml
+++ b/gwtquery-core/src/main/java/com/google/gwt/query/Query.gwt.xml
@@ -16,10 +16,10 @@
<module>
<inherits name='com.google.gwt.user.User'/>
-
+
<source path="client"/>
<super-source path="super"/>
-
+
<!-- Browser flags -->
<generate-with class="com.google.gwt.query.rebind.BrowserGenerator">
<when-type-assignable class="com.google.gwt.query.client.Browser"/>
@@ -124,6 +124,11 @@
</any>
</replace-with>
+ <!-- GQuery uses GWT.create to create the selector engine so as it can be overriden by users -->
+ <replace-with class="com.google.gwt.query.client.impl.SelectorEngine">
+ <when-type-assignable class="com.google.gwt.query.client.impl.SelectorEngine"/>
+ </replace-with>
+
<!-- UI implementations -->
<replace-with class="com.google.gwt.query.client.plugins.UiPlugin.GQueryUiImpl">
<when-type-is class="com.google.gwt.query.client.plugins.UiPlugin.GQueryUiImpl" />
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 32a30e1f..b82a2a3c 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
@@ -13,12 +13,7 @@
*/
package com.google.gwt.query.client;
-import static com.google.gwt.query.client.plugins.QueuePlugin.*;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
+import static com.google.gwt.query.client.plugins.QueuePlugin.Queue;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
@@ -26,9 +21,19 @@ import com.google.gwt.core.client.JsArray;
import com.google.gwt.core.client.JsArrayMixed;
import com.google.gwt.core.client.JsArrayString;
import com.google.gwt.core.client.ScriptInjector;
-import com.google.gwt.dom.client.*;
+import com.google.gwt.dom.client.BodyElement;
+import com.google.gwt.dom.client.ButtonElement;
+import com.google.gwt.dom.client.Document;
+import com.google.gwt.dom.client.Element;
+import com.google.gwt.dom.client.InputElement;
+import com.google.gwt.dom.client.NativeEvent;
+import com.google.gwt.dom.client.Node;
+import com.google.gwt.dom.client.NodeList;
+import com.google.gwt.dom.client.OptionElement;
+import com.google.gwt.dom.client.SelectElement;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.dom.client.Style.HasCssName;
+import com.google.gwt.dom.client.TextAreaElement;
import com.google.gwt.query.client.css.CSS;
import com.google.gwt.query.client.css.HasCssValue;
import com.google.gwt.query.client.css.TakesCssValue;
@@ -60,6 +65,11 @@ import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.Widget;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
/**
* GwtQuery is a GWT clone of the popular jQuery library.
*/
@@ -764,11 +774,10 @@ public class GQuery implements Lazy<GQuery, LazyGQuery> {
return new Deferred();
}
- private static SelectorEngine getSelectorEngine() {
+ public static SelectorEngine getSelectorEngine() {
if (engine == null) {
- engine = new SelectorEngine();
+ engine = GWT.create(SelectorEngine.class);
}
-
return engine;
}
@@ -830,7 +839,7 @@ public class GQuery implements Lazy<GQuery, LazyGQuery> {
*/
public GQuery add(GQuery elementsToAdd) {
return pushStack(JsUtils.copyNodeList(nodeList, elementsToAdd.nodeList, true)
- .<JsNodeArray> cast(), "add", getSelector() + "," + elementsToAdd.getSelector());
+ .<JsNodeArray> cast(), "add", join(",", getSelector(), elementsToAdd.getSelector()));
}
/**
@@ -2255,53 +2264,46 @@ public class GQuery implements Lazy<GQuery, LazyGQuery> {
* false, then the element is removed - anything else and the element is kept.
*/
public GQuery filter(Predicate filterFn) {
- JsNodeArray result = JsNodeArray.create();
- int i = 0;
- for (Element e : elements) {
- if (filterFn.f(e, i++)) {
- result.addNode(e);
- }
- }
+ JsNodeArray result = getSelectorEngine().filter(nodeList, filterFn).cast();
return pushStack(result, "filter", currentSelector);
}
/**
* Removes all elements from the set of matched elements that do not pass the specified css
* expression. This method is used to narrow down the results of a search.
+ * By default it works for either detached and attached elements unless
+ * {@link SelectorEngine#filterDetached} is set to false.
*/
- // TODO performance bad...
public GQuery filter(String... filters) {
- if (filters.length == 0 || filters[0] == null) {
- return this;
- }
-
- JsNodeArray array = JsNodeArray.create();
-
- for (String f : filters) {
- for (Element e : elements) {
- boolean ghostParent = false;
- if (e == window || e.getNodeName() == null) {
- continue;
- }
- if (e.getParentNode() == null) {
- DOM.createDiv().appendChild(e);
- ghostParent = true;
- }
+ String selector = join(", ", filters);
+ JsNodeArray result = getSelectorEngine().filter(nodeList, selector).cast();
+ return pushStack(result, "filter", selector);
+ }
- for (Element c : $(f, e.getParentNode()).elements) {
- if (c == e) {
- array.addNode(c);
- break;
- }
- }
+ /**
+ * Removes all elements from the set of matched elements that do not pass the specified css
+ * expression. This method is used to narrow down the results of a search.
+ * Setting filterDetached parameter to true, means that we should consider detached elements
+ * as well which implies some performance penalty.
+ */
+ public GQuery filter(boolean filterDetached, String... filters) {
+ String selector = join(", ", filters);
+ JsNodeArray result = getSelectorEngine().filter(nodeList, selector, filterDetached).cast();
+ return pushStack(result, "filter", selector);
+ }
- if (ghostParent) {
- e.removeFromParent();
- }
- }
+ /**
+ * Removes all elements from the set of matched elements that do not pass the specified css
+ * expression. This method is used to narrow down the results of a search.
+ * Setting considerDetached parameter to true, means that we should consider detached elements
+ * as well which implies some performance penalties.
+ */
+ public GQuery filter(boolean filterDetached, String selector) {
+ if (selector.isEmpty()) {
+ return this;
}
-
- return pushStack(unique(array), "filter", filters[0]);
+ JsNodeArray result = getSelectorEngine().filter(nodeList, selector, filterDetached).cast();
+ return pushStack(result, "filter", selector);
}
/**
@@ -4674,10 +4676,7 @@ public class GQuery implements Lazy<GQuery, LazyGQuery> {
* $(...).val(new String[]{"value"});
*/
public GQuery val(String... values) {
- String value = values.length > 0 ? values[0] : "";
- for (int i = 1; i < values.length; i++) {
- value += "," + values[i];
- }
+ String value = join(",", values);
for (Element e : elements) {
String name = e.getNodeName();
if ("select".equalsIgnoreCase(name)) {
@@ -4977,4 +4976,12 @@ public class GQuery implements Lazy<GQuery, LazyGQuery> {
public GQuery wrapInner(String html) {
return wrapInner($(html));
}
+
+ private String join(String chr, String... values) {
+ String value = "";
+ for (int i = 0; i < values.length; i++) {
+ value += i > 0 ? chr + values[i] : values[i];
+ }
+ return value;
+ }
}
diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/LazyGQuery.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/LazyGQuery.java
index af506174..33b12731 100644
--- a/gwtquery-core/src/main/java/com/google/gwt/query/client/LazyGQuery.java
+++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/LazyGQuery.java
@@ -1015,10 +1015,27 @@ public interface LazyGQuery<T> extends LazyBase<T>{
/**
* Removes all elements from the set of matched elements that do not pass the specified css
* expression. This method is used to narrow down the results of a search.
+ * {@link #filterDetached} is set to false.
*/
LazyGQuery<T> filter(String... filters);
/**
+ * Removes all elements from the set of matched elements that do not pass the specified css
+ * expression. This method is used to narrow down the results of a search.
+ * Setting considerDetached parameter to true, means that we should consider detached elements
+ * as well which implies some performance penalties.
+ */
+ LazyGQuery<T> filter(boolean filterDetached, String... filters);
+
+ /**
+ * Removes all elements from the set of matched elements that do not pass the specified css
+ * expression. This method is used to narrow down the results of a search.
+ * Setting considerDetached parameter to true, means that we should consider detached elements
+ * as well which implies some performance penalties.
+ */
+ LazyGQuery<T> filter(boolean filterDetached, String selector);
+
+ /**
* Searches for all elements that match the specified css expression. This method is a good way to
* find additional descendant elements with which to process.
*
diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngine.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngine.java
index 0d565d0e..6b6d5921 100644
--- a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngine.java
+++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngine.java
@@ -15,11 +15,17 @@
*/
package com.google.gwt.query.client.impl;
+import static com.google.gwt.query.client.GQuery.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Node;
import com.google.gwt.dom.client.NodeList;
+import com.google.gwt.query.client.GQuery;
import com.google.gwt.query.client.Predicate;
import com.google.gwt.query.client.js.JsMap;
import com.google.gwt.query.client.js.JsNodeArray;
@@ -97,6 +103,13 @@ public class SelectorEngine implements HasSelector {
public final SelectorEngineImpl impl;
+ /**
+ * Set it to false if all your elements are attached to the DOM and you want to
+ * increase filter performance using {@link GQuery#getSelectorEngine()}
+ * method.
+ */
+ public boolean filterDetached = true;
+
protected Node root = Document.get();
public static final boolean hasQuerySelector = hasQuerySelectorAll();
@@ -155,6 +168,55 @@ public class SelectorEngine implements HasSelector {
return res;
}
+ public NodeList<Element> filter(NodeList<Element> nodes, String selector) {
+ return filter(nodes, selector, filterDetached);
+ }
+
+ public NodeList<Element> filter(NodeList<Element> nodes, String selector, boolean filterDetached) {
+ JsNodeArray res = JsNodeArray.create();
+ if (selector.isEmpty()){
+ return res;
+ }
+ Element ghostParent = null;
+ ArrayList<Node> parents = new ArrayList<Node>();
+ List<Node> elmList = new ArrayList<Node>();
+ for (int i = 0, l = nodes.getLength(); i < l; i++) {
+ Node e = nodes.getItem(i);
+ if (e == window || e == document || e.getNodeName() == null || "html".equalsIgnoreCase(e.getNodeName())) {
+ continue;
+ }
+ elmList.add(e);
+ if (filterDetached) {
+ Element p = e.getParentElement();
+ if (p == null) {
+ if (ghostParent == null) {
+ ghostParent = Document.get().createDivElement();
+ parents.add(ghostParent);
+ }
+ p = ghostParent;
+ p.appendChild(e);
+ } else if (!parents.contains(p)) {
+ parents.add(p);
+ }
+ } else if (parents.isEmpty()) {
+ parents.add(document);
+ }
+ }
+ for (Node e : parents) {
+ NodeList<Element> n = select(selector, e);
+ for (int i = 0, l = n.getLength(); i < l; i++) {
+ Element el = n.getItem(i);
+ if (elmList.remove(el)) {
+ res.addNode(el);
+ }
+ }
+ }
+ if (ghostParent != null) {
+ ghostParent.setInnerHTML(null);
+ }
+ return res;
+ }
+
// pseudo selectors which are computed by gquery in runtime
RegExp gQueryPseudo = RegExp.compile("(.*):((visible|hidden|selected|input|header)|((button|checkbox|file|hidden|image|password|radio|reset|submit|text)\\s*(,|$)))(.*)", "i");
// pseudo selectors which work in engine
@@ -223,12 +285,10 @@ public class SelectorEngine implements HasSelector {
*/
public static native boolean hasQuerySelectorAll() /*-{
return $doc.location.href.indexOf("_force_no_native") < 0 &&
- $doc.querySelectorAll &&
- /native/.test(String($doc.querySelectorAll)) ? true : false;
+ typeof $doc.querySelectorAll == 'function';
}-*/;
public static native boolean hasXpathEvaluate() /*-{
- return $doc.evaluate ? true : false;
+ return !!$doc.evaluate;
}-*/;
-
}
diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/LazyEffects.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/LazyEffects.java
index cf62be4f..f0af09b8 100644
--- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/LazyEffects.java
+++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/LazyEffects.java
@@ -363,6 +363,13 @@ public interface LazyEffects<T> extends LazyBase<T>{
LazyEffects<T> slideRight(int millisecs, Function... f);
/**
+ * Toggle the visibility of all matched elements by adjusting their height and firing an optional
+ * callback after completion. Only the height is adjusted for this animation, causing all matched
+ * elements to be hidden or shown in a "sliding" manner
+ */
+ LazyEffects<T> slideToggle(Function... f);
+
+ /**
* Toggle the visibility of all matched elements by adjusting their height and
* firing an optional callback after completion. Only the height is adjusted
* for this animation, causing all matched elements to be hidden or shown in a
diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/LazyEvents.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/LazyEvents.java
index dec30be8..081e1702 100644
--- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/LazyEvents.java
+++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/LazyEvents.java
@@ -16,7 +16,6 @@ import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.FormElement;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.Node;
-import com.google.gwt.event.dom.client.HasNativeEvent;
import com.google.gwt.query.client.Function;
import com.google.gwt.query.client.GQuery;
import com.google.gwt.query.client.js.JsUtils;
diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryCoreTestGwt.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryCoreTestGwt.java
index f4a4d963..763655da 100644
--- a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryCoreTestGwt.java
+++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryCoreTestGwt.java
@@ -877,7 +877,6 @@ public class GQueryCoreTestGwt extends GWTTestCase {
public void testShowHide() {
$(e).html(
"<p id='id1' style='display: inline'>Content 1</p><p id='id2'>Content 2</p><p id='id3'>Content 3</p>");
-
final GQuery sectA = $("#id1");
final GQuery sectB = $("#id2");
final GQuery sectC = $("#id3");