From 6fe60be38945aee128410c4fe234714e4d5b6976 Mon Sep 17 00:00:00 2001 From: Ray Cromwell Date: Fri, 1 May 2009 00:16:10 +0000 Subject: [PATCH] Checkstyle fixes. --- .../java/com/google/gwt/query/client/$.java | 19 +- .../gwt/query/client/DeferredGQuery.java | 32 +- .../com/google/gwt/query/client/Effects.java | 99 +- .../com/google/gwt/query/client/Events.java | 77 +- .../gwt/query/client/EventsListener.java | 97 +- .../com/google/gwt/query/client/Function.java | 15 + .../com/google/gwt/query/client/GQuery.java | 94 +- .../com/google/gwt/query/client/JSArray.java | 15 + .../com/google/gwt/query/client/Plugin.java | 16 + .../google/gwt/query/client/Predicate.java | 15 + .../google/gwt/query/client/Properties.java | 27 +- .../com/google/gwt/query/client/Regexp.java | 62 +- .../com/google/gwt/query/client/Selector.java | 15 + .../gwt/query/client/SelectorEngine.java | 52 +- .../google/gwt/query/client/Selectors.java | 15 + .../query/client/impl/DocumentStyleImpl.java | 37 +- .../client/impl/DocumentStyleImplIE.java | 69 +- .../query/client/impl/SelectorEngineImpl.java | 117 +- .../query/client/impl/SelectorEngineJS.java | 1224 +++++++++-------- .../query/client/impl/SelectorEngineJSIE.java | 23 +- .../client/impl/SelectorEngineNative.java | 15 + .../client/impl/SelectorEngineXPath.java | 383 +++--- .../query/rebind/SelectorGeneratorBase.java | 173 +-- .../gwt/query/rebind/SelectorGeneratorJS.java | 15 + .../rebind/SelectorGeneratorJSOptimal.java | 69 +- .../query/rebind/SelectorGeneratorNative.java | 15 + .../query/rebind/SelectorGeneratorXPath.java | 187 +-- .../gwt/query/client/GwtQueryCoreTest.java | 1097 +++++++-------- .../gwtquery/samples/client/MySelectors.java | 163 +-- 29 files changed, 2344 insertions(+), 1893 deletions(-) diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/$.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/$.java index 16487834..c57777dc 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/$.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/$.java @@ -1,3 +1,18 @@ +/* + * Copyright 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ package com.google.gwt.query.client; import com.google.gwt.dom.client.Element; @@ -64,14 +79,14 @@ public class $ { } /** - * Wrap a JSON object + * Wrap a JSON object. */ public static Properties $$(String properties) { return GQuery.$$(properties); } /** - * Registers a GQuery plugin + * Registers a GQuery plugin. * @param plugin * @param pluginFactory */ diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/DeferredGQuery.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/DeferredGQuery.java index 28bb99ec..1efc4acc 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/DeferredGQuery.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/DeferredGQuery.java @@ -1,3 +1,18 @@ +/* + * Copyright 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ package com.google.gwt.query.client; import com.google.gwt.dom.client.Node; @@ -10,24 +25,19 @@ import com.google.gwt.dom.client.NodeList; public interface DeferredGQuery { /** - * The selector which was compiled. - * @return + * Evaluate the compiled selector with the given DOM node as a context. + * Returns a NodeList as a result. */ - String getSelector(); + NodeList array(Node ctx); /** * Evaluate the compiled selector with the given DOM node as a context. * Returns the result as a GQuery object. - * @param ctx - * @return */ - GQuery eval(Node ctx); + GQuery eval(Node ctx); /** - * Evaluate the compiled selector with the given DOM node as a context. - * Returns a NodeList as a result. - * @param ctx - * @return + * The selector which was compiled. */ - NodeList array(Node ctx); + String getSelector(); } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/Effects.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/Effects.java index ac69eb6e..38c904ea 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/Effects.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/Effects.java @@ -1,17 +1,45 @@ +/* + * Copyright 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ package com.google.gwt.query.client; import com.google.gwt.animation.client.Animation; import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.NodeList; +/** + * Effects plugin for Gwt Query. + */ public class Effects extends GQuery { - static { - GQuery.registerPlugin(Effects.class, new EffectsPlugin()); + /** + * Used to register the plugin. + */ + private static class EffectsPlugin implements Plugin { + + public Effects init(GQuery gq) { + return new Effects(gq.get()); + } } public static final Class Effects = Effects.class; + static { + GQuery.registerPlugin(Effects.class, new EffectsPlugin()); + } + public Effects(Element element) { super(element); } @@ -24,43 +52,13 @@ public class Effects extends GQuery { super(list); } - public Effects hide() { - this.css("display", "none"); - return this; - } - - public Effects show() { - this.css("display", ""); - return this; - } - - public boolean visible() { - return !"none".equalsIgnoreCase(this.css("display")); - } - - public Effects toggle() { - for (Element e : elements()) { - Effects ef = new Effects(e); - if (ef.visible()) { - ef.hide(); - } else { - ef.show(); - } - } - return this; - } - - public Effects fadeOut() { + public Effects fadeIn() { Animation a = new Animation() { public void onCancel() { } public void onComplete() { - for (int i = 0; i < elements.getLength(); i++) { - elements.getItem(i).getStyle().setProperty("opacity", "0"); - elements.getItem(i).getStyle().setProperty("display", "none"); - } } public void onStart() { @@ -69,7 +67,7 @@ public class Effects extends GQuery { public void onUpdate(double progress) { for (int i = 0; i < elements.getLength(); i++) { elements.getItem(i).getStyle() - .setProperty("opacity", String.valueOf(1.0 - progress)); + .setProperty("opacity", String.valueOf(progress)); } } }; @@ -77,13 +75,17 @@ public class Effects extends GQuery { return this; } - public Effects fadeIn() { + public Effects fadeOut() { Animation a = new Animation() { public void onCancel() { } public void onComplete() { + for (int i = 0; i < elements.getLength(); i++) { + elements.getItem(i).getStyle().setProperty("opacity", "0"); + elements.getItem(i).getStyle().setProperty("display", "none"); + } } public void onStart() { @@ -92,7 +94,7 @@ public class Effects extends GQuery { public void onUpdate(double progress) { for (int i = 0; i < elements.getLength(); i++) { elements.getItem(i).getStyle() - .setProperty("opacity", String.valueOf(progress)); + .setProperty("opacity", String.valueOf(1.0 - progress)); } } }; @@ -100,10 +102,29 @@ public class Effects extends GQuery { return this; } - public static class EffectsPlugin implements Plugin { + public Effects hide() { + this.css("display", "none"); + return this; + } - public Effects init(GQuery gq) { - return new Effects(gq.get()); + public Effects show() { + this.css("display", ""); + return this; + } + + public Effects toggle() { + for (Element e : elements()) { + Effects ef = new Effects(e); + if (ef.visible()) { + ef.hide(); + } else { + ef.show(); + } } + return this; + } + + public boolean visible() { + return !"none".equalsIgnoreCase(this.css("display")); } } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/Events.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/Events.java index 14025ea9..245b9f7b 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/Events.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/Events.java @@ -1,3 +1,18 @@ +/* + * Copyright 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ package com.google.gwt.query.client; import com.google.gwt.dom.client.Element; @@ -5,10 +20,12 @@ import com.google.gwt.dom.client.NodeList; import com.google.gwt.user.client.Event; /** - * GQuery Plugin for handling and queuing browser events + * GQuery Plugin for handling and queuing browser events. */ public class Events extends GQuery { + public static final Class Events = Events.class; + static { GQuery.registerPlugin(Events.class, new Plugin() { public Events init(GQuery gq) { @@ -17,8 +34,6 @@ public class Events extends GQuery { }); } - public static final Class Events = Events.class; - public Events(Element element) { super(element); } @@ -75,17 +90,34 @@ public class Events extends GQuery { } /** - * Just a class with static methods for firing element events on demand + * Just a class with static methods for firing element events on demand. */ class FireEvents { - private native static Event createMouseEventImpl(String type) /*-{ - var event = $doc.createEvent('MouseEvents'); - event.initEvent(type, true, true); - return event; + public static void fire(Element element, int eventbits, int... keys) { + Event event = null; + + String type = getEventTypeStr(eventbits); + + if ((eventbits & Event.MOUSEEVENTS) != 0 + || (eventbits | Event.ONCLICK) == Event.ONCLICK) { + event = createMouseEventImpl(type); + } else if ((eventbits & Event.KEYEVENTS) != 0) { + event = createKeyEventImpl(type, keys[0]); + } else if ((eventbits & Event.FOCUSEVENTS) != 0) { + event = createHtmlEventImpl(type); + } + + dispatchEvent(element, event); + } + + private static native Event createHtmlEventImpl(String type) /*-{ + var event = $doc.createEvent('HTMLEvents'); + event.initEvent( type, true, true); + return event; }-*/; - private native static Event createKeyEventImpl(String type, int keycode) /*-{ + private static native Event createKeyEventImpl(String type, int keycode) /*-{ var event; if( $wnd.KeyEvent ) { event = $doc.createEvent('KeyEvents'); @@ -98,13 +130,13 @@ class FireEvents { return event; }-*/; - private native static Event createHtmlEventImpl(String type) /*-{ - var event = $doc.createEvent('HTMLEvents'); - event.initEvent( type, true, true); - return event; + private static native Event createMouseEventImpl(String type) /*-{ + var event = $doc.createEvent('MouseEvents'); + event.initEvent(type, true, true); + return event; }-*/; - private native static void dispatchEvent(Element elem, Event event) /*-{ + private static native void dispatchEvent(Element elem, Event event) /*-{ elem.dispatchEvent(event); if (event.type == 'focus' && elem.focus) elem.focus(); @@ -152,21 +184,4 @@ class FireEvents { return ""; } } - - public static void fire(Element element, int eventbits, int... keys) { - Event event = null; - - String type = getEventTypeStr(eventbits); - - if ((eventbits & Event.MOUSEEVENTS) != 0 - || (eventbits | Event.ONCLICK) == Event.ONCLICK) { - event = createMouseEventImpl(type); - } else if ((eventbits & Event.KEYEVENTS) != 0) { - event = createKeyEventImpl(type, keys[0]); - } else if ((eventbits & Event.FOCUSEVENTS) != 0) { - event = createHtmlEventImpl(type); - } - - dispatchEvent(element, event); - } } \ No newline at end of file diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/EventsListener.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/EventsListener.java index 37adcf60..ae089986 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/EventsListener.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/EventsListener.java @@ -1,3 +1,18 @@ +/* + * Copyright 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ package com.google.gwt.query.client; import com.google.gwt.user.client.EventListener; @@ -8,23 +23,26 @@ import com.google.gwt.dom.client.Element; import java.util.List; import java.util.ArrayList; - /** - * This class implements an event queue instance for one element. - * This queue instance is configured as the default event listener in GWT. - * - * The reference to this queue is stored as a uniq variable in the element's DOM - * - * The class takes care of calling the appropiate functions for each browser event - * and also calls sinkEvents methods. - * + * This class implements an event queue instance for one element. This queue + * instance is configured as the default event listener in GWT. + * + * The reference to this queue is stored as a uniq variable in the element's + * DOM + * + * The class takes care of calling the appropiate functions for each browser + * event and also calls sinkEvents methods. */ class EventsListener implements EventListener { - private class BindFunction { + private static class BindFunction { + int type; + Function function; + Object data; + int times = -1; BindFunction(int t, Function f, Object d) { @@ -38,10 +56,6 @@ class EventsListener implements EventListener { this.times = times; } - public boolean hasEventType(int etype) { - return (type | etype) == type; - } - public boolean fire(Event event) { if (times != 0) { times--; @@ -49,23 +63,33 @@ class EventsListener implements EventListener { } return true; } + + public boolean hasEventType(int etype) { + return (type | etype) == type; + } } - - private native static EventsListener getWidgetElementImpl( - Element elem) /*-{ + + public static EventsListener getInstance(Element e) { + EventsListener ret = getWidgetElementImpl(e); + return ret != null ? ret : new EventsListener(e); + } + + private static native EventsListener getWidgetElementImpl(Element elem) /*-{ return elem.__gqueryevent; }-*/; - private native static void setWidgetElementImpl(Element elem, EventsListener gqevent) /*-{ - elem.__gqueryevent = gqevent; + private static native void setFocusable(Element elem) /*-{ + elem.tabIndex = 0; }-*/; - private native static void setFocusable(Element elem) /*-{ - elem.tabIndex = 0; + private static native void setWidgetElementImpl(Element elem, + EventsListener gqevent) /*-{ + elem.__gqueryevent = gqevent; }-*/; + private List elementEvents + = new ArrayList(); - private List elementEvents = new ArrayList(); private Element element; private EventsListener(Element e) { @@ -74,22 +98,21 @@ class EventsListener implements EventListener { DOM.setEventListener((com.google.gwt.user.client.Element) e, this); } - public static EventsListener getInstance(Element e) { - EventsListener ret = getWidgetElementImpl(e); - return ret != null ? ret : new EventsListener(e); - } - - public void bind(int eventbits, final Object data, final Function function, int times) { + public void bind(int eventbits, final Object data, final Function function, + int times) { if (function == null) { unbind(eventbits); } else { - DOM.sinkEvents((com.google.gwt.user.client.Element) element, eventbits - | DOM.getEventsSunk((com.google.gwt.user.client.Element) element)); + DOM.sinkEvents((com.google.gwt.user.client.Element) element, + eventbits | DOM + .getEventsSunk((com.google.gwt.user.client.Element) element)); - if ((eventbits | Event.FOCUSEVENTS) == Event.FOCUSEVENTS) + if ((eventbits | Event.FOCUSEVENTS) == Event.FOCUSEVENTS) { setFocusable(element); + } - elementEvents.add(new EventsListener.BindFunction(eventbits, function, data, times)); + elementEvents.add( + new EventsListener.BindFunction(eventbits, function, data, times)); } } @@ -114,11 +137,13 @@ class EventsListener implements EventListener { } public void unbind(int eventbits) { - ArrayList newList = new ArrayList(); - for (EventsListener.BindFunction listener : elementEvents) - if (!listener.hasEventType(eventbits)) + ArrayList newList + = new ArrayList(); + for (EventsListener.BindFunction listener : elementEvents) { + if (!listener.hasEventType(eventbits)) { newList.add(listener); + } + } elementEvents = newList; } - } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/Function.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/Function.java index d9c093e3..44315e00 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/Function.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/Function.java @@ -1,3 +1,18 @@ +/* + * Copyright 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ package com.google.gwt.query.client; import com.google.gwt.dom.client.Element; 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 74cc5b85..b4b165a0 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 @@ -1,3 +1,18 @@ +/* + * Copyright 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ package com.google.gwt.query.client; import com.google.gwt.core.client.GWT; @@ -28,10 +43,13 @@ import java.util.List; import java.util.Map; /** - * + * Gwt Query is a GWT clone of the popular jQuery library. */ public class GQuery { + /** + * A POJO used to store the top/left CSS positioning values of an element. + */ public static class Offset { public int top; @@ -200,7 +218,6 @@ public class GQuery { } public static T $(T gq) { - return gq; } @@ -242,8 +259,8 @@ public class GQuery { Class plugin) { try { if (plugins != null) { - T gquery = (T) plugins.get(plugin) - .init(new GQuery(select(selector, context))); + T gquery = (T) plugins.get(plugin). + init(new GQuery(select(selector, context))); return gquery; } throw new RuntimeException("No plugin for class " + plugin); @@ -266,7 +283,7 @@ public class GQuery { } /** - * Wrap a JSON object + * Wrap a JSON object. */ public static Properties $$(String properties) { return Properties.create(properties); @@ -297,7 +314,7 @@ public class GQuery { } /** - * Copied from UIObject * + * Copied from UIObject. */ protected static void setStyleName(Element elem, String style, boolean add) { @@ -389,7 +406,7 @@ public class GQuery { protected NodeList elements = null; - private String selector; + private String currentSelector; private GQuery previousObject; @@ -844,7 +861,7 @@ public class GQuery { * Remove all child nodes from the set of matched elements. */ public GQuery empty() { - //TODO: add memory leak cleanup, remove event handlers, and + // TODO: add memory leak cleanup, remove event handlers, and // data caches for (Element e : elements()) { while (e.getFirstChild() != null) { @@ -928,7 +945,7 @@ public class GQuery { result.addNode(e); } } - return pushStack(result, "filter", selector); + return pushStack(result, "filter", currentSelector); } /** @@ -1014,7 +1031,7 @@ public class GQuery { * Return the selector representing the current set of matched elements. */ public String getSelector() { - return selector; + return currentSelector; } /** @@ -1064,13 +1081,13 @@ public class GQuery { * Get the current computed, pixel, height of the first matched element. */ public int height() { - return DOM - .getElementPropertyInt((com.google.gwt.user.client.Element) get(0), + return DOM. + getElementPropertyInt((com.google.gwt.user.client.Element) get(0), "offsetHeight"); } /** - * Make invisible all matched elements + * Make invisible all matched elements. */ public GQuery hide() { return $(as(Effects).hide()); @@ -1085,8 +1102,8 @@ public class GQuery { * function fires. */ public GQuery hover(Function fover, Function fout) { - return bind(Event.ONMOUSEOVER, null, fover) - .bind(Event.ONMOUSEOUT, null, fout); + return bind(Event.ONMOUSEOVER, null, fover). + bind(Event.ONMOUSEOUT, null, fout); } /** @@ -1107,7 +1124,7 @@ public class GQuery { } /** - * Find the index of the specified Element + * Find the index of the specified Element. */ public int index(Element element) { for (int i = 0; i < elements.getLength(); i++) { @@ -1389,11 +1406,11 @@ public class GQuery { * relative or absolute). This method only works with visible elements. */ public GQuery offsetParent() { - Element offParent = SelectorEngine - .or(elements.getItem(0).getOffsetParent(), Document.get().getBody()); + Element offParent = SelectorEngine. + or(elements.getItem(0).getOffsetParent(), Document.get().getBody()); while (offParent != null && !"body".equalsIgnoreCase(offParent.getTagName()) - && !"html".equalsIgnoreCase(offParent.getTagName()) && "static" - .equals(curCSS(offParent, "position"))) { + && !"html".equalsIgnoreCase(offParent.getTagName()) && "static". + equals(curCSS(offParent, "position"))) { offParent = offParent.getOffsetParent(); } return new GQuery(offParent); @@ -1617,7 +1634,7 @@ public class GQuery { */ public GQuery remove() { for (Element e : elements()) { - //TODO: cleanup event bindings + // TODO: cleanup event bindings removeData(e, null); if (e.getParentNode() != null) { e.getParentNode().removeChild(e); @@ -1794,7 +1811,7 @@ public class GQuery { } public void setSelector(String selector) { - this.selector = selector; + this.currentSelector = selector; } /** @@ -1856,8 +1873,8 @@ public class GQuery { * Return the text contained in the first matched element. */ public String text() { - String result=""; - for(Element e : elements()) { + String result = ""; + for (Element e : elements()) { result += e.getInnerText(); } return result; @@ -1914,14 +1931,14 @@ public class GQuery { } /** - * Produces a string representation of the matched elements + * Produces a string representation of the matched elements. */ public String toString() { return toString(false); } /** - * Produces a string representation of the matched elements + * Produces a string representation of the matched elements. */ public String toString(boolean pretty) { String r = ""; @@ -1939,7 +1956,7 @@ public class GQuery { } /** - * Removes all events that match the eventbits + * Removes all events that match the eventbits. */ public GQuery unbind(int eventbits) { return as(Events).unbind(eventbits); @@ -2001,8 +2018,8 @@ public class GQuery { } else if ("input".equalsIgnoreCase(name)) { InputElement ie = InputElement.as(e); String type = ie.getType(); - if ("radio".equalsIgnoreCase((type)) || "checkbox" - .equalsIgnoreCase(type)) { + if ("radio".equalsIgnoreCase((type)) || "checkbox". + equalsIgnoreCase(type)) { if ("checkbox".equalsIgnoreCase(type)) { for (String val : values) { if (ie.getValue().equals(val)) { @@ -2103,8 +2120,8 @@ public class GQuery { * Get the current computed, pixel, width of the first matched element. */ public int width() { - return DOM - .getElementPropertyInt((com.google.gwt.user.client.Element) get(0), + return DOM. + getElementPropertyInt((com.google.gwt.user.client.Element) get(0), "offsetWidth"); } @@ -2305,14 +2322,14 @@ public class GQuery { preWrap = ""; postWrap = "
"; } - //TODO: fix IE link tag serialization + // TODO: fix IE link tag serialization Element div = Document.get().createDivElement(); div.setInnerHTML(preWrap + elem + postWrap); Node n = div; while (wrapPos-- != 0) { n = n.getLastChild(); } - //TODO: add fixes for IE TBODY issue + // TODO: add fixes for IE TBODY issue return n.getChildNodes().cast(); } @@ -2336,9 +2353,10 @@ public class GQuery { private void dequeue(Element elem, String type) { Queue q = queue(elem, type, null); - Function f = q.dequeue(); if (q != null) { + Function f = q.dequeue(); + if (SelectorEngine.eq(type, "__FX")) { f = q.peek(0); } @@ -2356,8 +2374,10 @@ public class GQuery { for (Element e : elements()) { for (int i = 0; i < nodes.getLength(); i++) { Node n = nodes.getItem(i); - if(size() > 1) n=n.cloneNode(true); - + if (size() > 1) { + n = n.cloneNode(true); + } + switch (func) { case FUNC_PREPEND: e.insertBefore(n, e.getFirstChild()); @@ -2415,7 +2435,6 @@ public class GQuery { return Integer.parseInt(v); } } catch (NumberFormatException e) { - } return 0; } @@ -2461,7 +2480,6 @@ public class GQuery { private void replacequeue(Element elem, String type, Queue data) { if (elem != null) { type = type + "queue"; - Object q = (Queue) data(elem, type, null); data(elem, type, data); } } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/JSArray.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/JSArray.java index 87242f56..427b7d4f 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/JSArray.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/JSArray.java @@ -1,3 +1,18 @@ +/* + * Copyright 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ package com.google.gwt.query.client; import com.google.gwt.core.client.JavaScriptObject; diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/Plugin.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/Plugin.java index 64b92af6..4142403e 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/Plugin.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/Plugin.java @@ -1,7 +1,23 @@ +/* + * Copyright 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ package com.google.gwt.query.client; /** * A GQuery plugin. All GQuery plugins must implement this interface. + * @param the plugin class */ public interface Plugin { diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/Predicate.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/Predicate.java index 89d78f28..bc94f570 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/Predicate.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/Predicate.java @@ -1,3 +1,18 @@ +/* + * Copyright 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ package com.google.gwt.query.client; import com.google.gwt.dom.client.Element; diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/Properties.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/Properties.java index c2954a49..ab14f610 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/Properties.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/Properties.java @@ -1,3 +1,18 @@ +/* + * Copyright 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ package com.google.gwt.query.client; import com.google.gwt.core.client.JavaScriptObject; @@ -8,27 +23,27 @@ import com.google.gwt.core.client.JsArrayString; */ public class Properties extends JavaScriptObject { - protected Properties() { - } - public static Properties create(String properties) { String s = properties.replaceFirst("^[({]*(.*)[})]*$", "({$1})"); return (Properties) createImpl(s); } - public final native static JavaScriptObject createImpl(String properties) /*-{ + public final static native JavaScriptObject createImpl(String properties) /*-{ return eval(properties); }-*/; + protected Properties() { + } + public final native String get(String name) /*-{ return this[name]; }-*/; - public final native int getInt(String name) /*-{ + public final native float getFloat(String name) /*-{ return this[name]; }-*/; - public final native float getFloat(String name) /*-{ + public final native int getInt(String name) /*-{ return this[name]; }-*/; diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/Regexp.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/Regexp.java index 8a33ffd6..d22d5f33 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/Regexp.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/Regexp.java @@ -1,3 +1,18 @@ +/* + * Copyright 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ package com.google.gwt.query.client; import com.google.gwt.core.client.JavaScriptObject; @@ -7,6 +22,22 @@ import com.google.gwt.core.client.JavaScriptObject; */ public class Regexp { + public static native JavaScriptObject compile(String pat) /*-{ + return new RegExp(pat); + }-*/; + + public static native JavaScriptObject compileFlags(String pat, String flags) /*-{ + return new RegExp(pat, flags); + }-*/; + + public static JSArray match(String regexp, String flags, String string) { + return new Regexp(regexp, flags).match(string); + } + + private static native JSArray exec0(JavaScriptObject regexp, String str) /*-{ + return regexp.exec(str); + }-*/; + private final JavaScriptObject regexp; public Regexp(String pattern) { @@ -17,40 +48,23 @@ public class Regexp { this.regexp = compileFlags(pat, flags); } - public static native JavaScriptObject compile(String pat) /*-{ - return new RegExp(pat); - }-*/; - - public static native JavaScriptObject compileFlags(String pat, String flags) /*-{ - return new RegExp(pat, flags); - }-*/; - - public JSArray exec(String str) { - return exec0(regexp, str); - } - - - private static native JSArray exec0(JavaScriptObject regexp, String str) /*-{ - return regexp.exec(str); - }-*/; + public JSArray exec(String str) { + return exec0(regexp, str); + } public JSArray match(String currentRule) { return match0(regexp, currentRule); } - private native JSArray match0(JavaScriptObject regexp, String currentRule)/*-{ - return currentRule.match(regexp); - }-*/; - public boolean test(String rule) { return test0(regexp, rule); } + private native JSArray match0(JavaScriptObject regexp, String currentRule)/*-{ + return currentRule.match(regexp); + }-*/; + private native boolean test0(JavaScriptObject regexp, String rule) /*-{ return regexp.test(rule); }-*/; - - public static JSArray match(String regexp, String flags, String string) { - return new Regexp(regexp, flags).match(string); - } } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/Selector.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/Selector.java index 23eae98e..d4740d05 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/Selector.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/Selector.java @@ -1,3 +1,18 @@ +/* + * Copyright 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ package com.google.gwt.query.client; import java.lang.annotation.Target; diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/SelectorEngine.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/SelectorEngine.java index ebe36240..4bd1ccaa 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/SelectorEngine.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/SelectorEngine.java @@ -1,3 +1,18 @@ +/* + * Copyright 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ package com.google.gwt.query.client; import com.google.gwt.core.client.GWT; @@ -8,18 +23,11 @@ import com.google.gwt.dom.client.Node; import com.google.gwt.dom.client.NodeList; import com.google.gwt.query.client.impl.SelectorEngineImpl; - /** * Core Selector engine functions, and native JS utility functions. */ public class SelectorEngine { - private SelectorEngineImpl impl; - - public SelectorEngine() { - impl = (SelectorEngineImpl) GWT.create(SelectorEngineImpl.class); - } - public static native boolean eq(String s1, String s2) /*-{ return s1 == s2; }-*/; @@ -29,6 +37,14 @@ public class SelectorEngine { return ctx.getElementsByClassName(clazz); }-*/; + public static native Node getNextSibling(Node n) /*-{ + return n.nextSibling || null; + }-*/; + + public static native Node getPreviousSibling(Node n) /*-{ + return n.previousSibling || null; + }-*/; + public static native T or(T s1, T s2) /*-{ return s1 || s2; }-*/; @@ -42,10 +58,6 @@ public class SelectorEngine { return ctx.querySelectorAll(selector); }-*/; - public NodeList select(String selector, Node ctx) { - return impl.select(selector, ctx); - } - public static boolean truth(String a) { return GWT.isScript() ? truth0(a) : a != null && !"".equals(a); } @@ -76,6 +88,16 @@ public class SelectorEngine { return a; }-*/; + private SelectorEngineImpl impl; + + public SelectorEngine() { + impl = (SelectorEngineImpl) GWT.create(SelectorEngineImpl.class); + } + + public NodeList select(String selector, Node ctx) { + return impl.select(selector, ctx); + } + protected JSArray veryQuickId(Node context, String id) { JSArray r = JSArray.create(); if (context.getNodeType() == Node.DOCUMENT_NODE) { @@ -86,12 +108,4 @@ public class SelectorEngine { return r; } } - - public static native Node getNextSibling(Node n) /*-{ - return n.nextSibling || null; - }-*/; - - public static native Node getPreviousSibling(Node n) /*-{ - return n.previousSibling || null; - }-*/; } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/Selectors.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/Selectors.java index 062df40e..ffb517f3 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/Selectors.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/Selectors.java @@ -1,3 +1,18 @@ +/* + * Copyright 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ package com.google.gwt.query.client; /** diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/DocumentStyleImpl.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/DocumentStyleImpl.java index eb3aa74c..34d980ec 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/DocumentStyleImpl.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/DocumentStyleImpl.java @@ -1,3 +1,18 @@ +/* + * Copyright 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ package com.google.gwt.query.client.impl; import com.google.gwt.dom.client.Element; @@ -9,6 +24,15 @@ import com.google.gwt.query.client.GQuery; */ public class DocumentStyleImpl { + public String getCurrentStyle(Element elem, String name) { + name = hyphenize(name); + String propVal = getComputedStyle(elem, name, null); + if ("opacity".equals(name)) { + propVal = SelectorEngine.or(propVal, "1"); + } + return propVal; + } + public String getPropertyName(String name) { if ("float".equals(name)) { return "cssFloat"; @@ -20,22 +44,13 @@ public class DocumentStyleImpl { return GQuery.camelize(name); } - public String getCurrentStyle(Element elem, String name) { - name = hyphenize(name); - String propVal = getComputedStyle(elem, name, null); - if ("opacity".equals(name)) { - propVal = SelectorEngine.or(propVal, "1"); - } - return propVal; - } - protected native String hyphenize(String name) /*-{ return name.replace( /([A-Z])/g, "-$1" ).toLowerCase(); }-*/; private native String getComputedStyle(Element elem, String name, String pseudo) /*-{ - var cStyle = $doc.defaultView.getComputedStyle( elem, pseudo ); - return cStyle ? cStyle.getPropertyValue( name ) : null; + var cStyle = $doc.defaultView.getComputedStyle( elem, pseudo ); + return cStyle ? cStyle.getPropertyValue( name ) : null; }-*/; } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/DocumentStyleImplIE.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/DocumentStyleImplIE.java index 14450247..0606db6e 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/DocumentStyleImplIE.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/DocumentStyleImplIE.java @@ -1,3 +1,18 @@ +/* + * Copyright 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ package com.google.gwt.query.client.impl; import com.google.gwt.dom.client.Element; @@ -8,6 +23,15 @@ import com.google.gwt.query.client.SelectorEngine; */ public class DocumentStyleImplIE extends DocumentStyleImpl { + public String getCurrentStyle(Element elem, String name) { + name = hyphenize(name); + String propVal = getComputedStyle(elem, name, null); + if ("opacity".equals(name)) { + propVal = SelectorEngine.or(propVal, "1"); + } + return propVal; + } + public String getPropertyName(String name) { if ("float".equals(name)) { return "styleFloat"; @@ -19,38 +43,29 @@ public class DocumentStyleImplIE extends DocumentStyleImpl { return name; } - public String getCurrentStyle(Element elem, String name) { - name = hyphenize(name); - String propVal = getComputedStyle(elem, name, null); - if ("opacity".equals(name)) { - propVal = SelectorEngine.or(propVal, "1"); - } - return propVal; - } - // code lifted from jQuery private native String getComputedStyle(Element elem, String name, String pseudo) /*-{ var style = elem.style; var camelCase = name.replace(/\-(\w)/g, function(all, letter){ - return letter.toUpperCase(); - }); + return letter.toUpperCase(); + }); var ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ]; - // From the awesome hack by Dean Edwards - // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 - // If we're not dealing with a regular pixel number - // but a number that has a weird ending, we need to convert it to pixels - if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) { - // Remember the original values - var left = style.left, rsLeft = elem.runtimeStyle.left; - // Put in the new values to get a computed value out - elem.runtimeStyle.left = elem.currentStyle.left; - style.left = ret || 0; - ret = style.pixelLeft + "px"; - // Revert the changed values - style.left = left; - elem.runtimeStyle.left = rsLeft; - } - return ret; + // From the awesome hack by Dean Edwards + // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 + // If we're not dealing with a regular pixel number + // but a number that has a weird ending, we need to convert it to pixels + if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) { + // Remember the original values + var left = style.left, rsLeft = elem.runtimeStyle.left; + // Put in the new values to get a computed value out + elem.runtimeStyle.left = elem.currentStyle.left; + style.left = ret || 0; + ret = style.pixelLeft + "px"; + // Revert the changed values + style.left = left; + elem.runtimeStyle.left = rsLeft; + } + return ret; }-*/; } \ No newline at end of file diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineImpl.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineImpl.java index d42e7fa0..b2bcf23c 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineImpl.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineImpl.java @@ -1,3 +1,18 @@ +/* + * Copyright 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ package com.google.gwt.query.client.impl; import com.google.gwt.dom.client.Element; @@ -12,7 +27,56 @@ import com.google.gwt.query.client.SelectorEngine; */ public abstract class SelectorEngineImpl { - public abstract NodeList select(String selector, Node ctx); + /** + * Internal class. + */ + protected static class Sequence { + + public int start; + + public int max; + + public int add; + + public int modVal; + } + + /** + * Internal class. + */ + protected static class SplitRule { + + public String tag; + + public String id; + + public String allClasses; + + public String allAttr; + + public String allPseudos; + + public String tagRelation; + + public SplitRule(String tag, String id, String allClasses, String allAttr, + String allPseudos) { + this.tag = tag; + this.id = id; + this.allClasses = allClasses; + this.allAttr = allAttr; + this.allPseudos = allPseudos; + } + + public SplitRule(String tag, String id, String allClasses, String allAttr, + String allPseudos, String tagRelation) { + this.tag = tag; + this.id = id; + this.allClasses = allClasses; + this.allAttr = allAttr; + this.allPseudos = allPseudos; + this.tagRelation = tagRelation; + } + } protected static Sequence getSequence(String expression) { int start = 0, add = 2, max = -1, modVal = -1; @@ -59,48 +123,11 @@ public abstract class SelectorEngineImpl { return s; } - public static class Sequence { - - public int start; - - public int max; - - public int add; - - public int modVal; - } - - public static class SplitRule { - - public String tag; - - public String id; - - public String allClasses; - - public String allAttr; - - public String allPseudos; - - public String tagRelation; - - public SplitRule(String tag, String id, String allClasses, String allAttr, - String allPseudos) { - this.tag = tag; - this.id = id; - this.allClasses = allClasses; - this.allAttr = allAttr; - this.allPseudos = allPseudos; - } - - public SplitRule(String tag, String id, String allClasses, String allAttr, - String allPseudos, String tagRelation) { - this.tag = tag; - this.id = id; - this.allClasses = allClasses; - this.allAttr = allAttr; - this.allPseudos = allPseudos; - this.tagRelation = tagRelation; - } - } + /** + * Parse and execute a given selector expression given a context. + * @param selector the CSS selector expression + * @param ctx the DOM node to use as a context + * @return a list of matched nodes + */ + public abstract NodeList select(String selector, Node ctx); } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineJS.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineJS.java index 6c46e4d4..b18c2759 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineJS.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineJS.java @@ -1,689 +1,705 @@ +/* + * Copyright 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ package com.google.gwt.query.client.impl; 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.SelectorEngine; -import com.google.gwt.query.client.Regexp; import com.google.gwt.query.client.JSArray; +import com.google.gwt.query.client.Regexp; +import com.google.gwt.query.client.SelectorEngine; /** - * Runtime selector engine implementation with no-XPath/native support based - * on DOMAssistant. + * Runtime selector engine implementation with no-XPath/native support based on + * DOMAssistant. */ public class SelectorEngineJS extends SelectorEngineImpl { - private Regexp cssSelectorRegExp; - private Regexp selectorSplitRegExp; - private Regexp childOrSiblingRefRegExp; - - public SelectorEngineJS() { - selectorSplitRegExp = new Regexp("[^\\s]+", "g"); - childOrSiblingRefRegExp = new Regexp("^(>|\\+|~)$"); - cssSelectorRegExp = new Regexp( - "^(\\w+)?(#[\\w\\u00C0-\\uFFFF\\-\\_]+|(\\*))?((\\.[\\w\\u00C0-\\uFFFF\\-_]+)*)?((\\[\\w+(\\^|\\$|\\*|\\||~)?(=[\\w\\u00C0-\\uFFFF\\s\\-\\_\\.]+)?\\]+)*)?(((:\\w+[\\w\\-]*)(\\((odd|even|\\-?\\d*n?((\\+|\\-)\\d+)?|[\\w\\u00C0-\\uFFFF\\-_]+|((\\w*\\.[\\w\\u00C0-\\uFFFF\\-_]+)*)?|(\\[#?\\w+(\\^|\\$|\\*|\\||~)?=?[\\w\\u00C0-\\uFFFF\\s\\-\\_\\.]+\\]+)|(:\\w+[\\w\\-]*))\\))?)*)?"); + public static void clearAdded(JSArray a) { + for (int i = 0, len = a.size(); i < len; i++) { + clearAdded(a.getNode(i)); } + } - public static void clearAdded(JSArray a) { - for (int i = 0, len = a.size(); i < len; i++) { - clearAdded(a.getNode(i)); - } - } - - public static native void clearAdded(Node node) /*-{ + public static native void clearAdded(Node node) /*-{ node.added = null; }-*/; - public static native NodeList getElementsByClassName(String clazz, - Node ctx) /*-{ + public static native NodeList getElementsByClassName(String clazz, + Node ctx) /*-{ return ctx.getElementsByClassName(clazz); }-*/; - public static native boolean isAdded(Node prevRef) /*-{ + public static native boolean isAdded(Node prevRef) /*-{ return prevRef.added || false; }-*/; - public static native void setAdded(Node prevRef, boolean added) /*-{ + public static native void setAdded(Node prevRef, boolean added) /*-{ prevRef.added = added; }-*/; - public static native void setSkipTag(JSArray prevElem, boolean skip) /*-{ + public static native void setSkipTag(JSArray prevElem, boolean skip) /*-{ prevElem.skipTag = skip; }-*/; - private static String attrToRegExp(String attrVal, String op) { - if (SelectorEngine.eq("^", op)) { - return "^" + attrVal; - } - if (SelectorEngine.eq("$", op)) { - return attrVal + "$"; - } - if (SelectorEngine.eq("*", op)) { - return attrVal; - } - if (SelectorEngine.eq("|", op)) { - return "(^" + attrVal + "(\\-\\w+)*$)"; - } - if (SelectorEngine.eq("~", op)) { - return "\\b" + attrVal + "\\b"; - } - return SelectorEngine.truth(attrVal) ? "^" + attrVal + "$" : null; + private static String attrToRegExp(String attrVal, String op) { + if (SelectorEngine.eq("^", op)) { + return "^" + attrVal; } - - private static void clearChildElms(JSArray prevParents) { - for (int n = 0, nl = prevParents.size(); n < nl; n++) { - setHasChildElms(prevParents.getNode(n), false); - } + if (SelectorEngine.eq("$", op)) { + return attrVal + "$"; } - - protected String getAttr(Element current, String name) { - return current.getAttribute(name); + if (SelectorEngine.eq("*", op)) { + return attrVal; } - - private static void getDescendantNodes(JSArray matchingElms, - String nextTagStr, Node prevRef) { - NodeList children = getElementsByTagName(nextTagStr, prevRef); - for (int k = 0, klen = children.getLength(); k < klen; k++) { - Node child = children.getItem(k); - if (child.getParentNode() == prevRef) { - matchingElms.addNode(child); - } - } + if (SelectorEngine.eq("|", op)) { + return "(^" + attrVal + "(\\-\\w+)*$)"; } - - private JSArray getElementsByPseudo(JSArray previousMatch, String pseudoClass, - String pseudoValue) { - JSArray prevParents = JSArray.create(); - boolean previousDir = pseudoClass.startsWith("first") ? true : false; - JSArray matchingElms = JSArray.create(); - Node prev, next, previous; - if (SelectorEngine.eq("first-child", pseudoClass) || SelectorEngine - .eq("last-child", pseudoClass)) { - getFirstChildPseudo(previousMatch, previousDir, matchingElms); - } else if (SelectorEngine.eq("only-child", pseudoClass)) { - getOnlyChildPseudo(previousMatch, matchingElms); - } else if (SelectorEngine.eq("nth-child", pseudoClass)) { - matchingElms = getNthChildPseudo(previousMatch, pseudoValue, prevParents, - matchingElms); - } else if (SelectorEngine.eq("first-of-type", pseudoClass) || SelectorEngine - .eq("last-of-type", pseudoClass)) { - getFirstOfTypePseudo(previousMatch, previousDir, matchingElms); - } else if (SelectorEngine.eq("only-of-type", pseudoClass)) { - getOnlyOfTypePseudo(previousMatch, matchingElms); - } else if (SelectorEngine.eq("nth-of-type", pseudoClass)) { - matchingElms = getNthOfTypePseudo(previousMatch, pseudoValue, prevParents, - matchingElms); - } else if (SelectorEngine.eq("empty", pseudoClass)) { - getEmptyPseudo(previousMatch, matchingElms); - } else if (SelectorEngine.eq("enabled", pseudoClass)) { - getEnabledPseudo(previousMatch, matchingElms); - } else if (SelectorEngine.eq("disabled", pseudoClass)) { - getDisabledPseudo(previousMatch, matchingElms); - } else if (SelectorEngine.eq("checked", pseudoClass)) { - getCheckedPseudo(previousMatch, matchingElms); - } else if (SelectorEngine.eq("contains", pseudoClass)) { - getContainsPseudo(previousMatch, pseudoValue, matchingElms); - } else if (SelectorEngine.eq("not", pseudoClass)) { - matchingElms = getNotPseudo(previousMatch, pseudoValue, matchingElms); - } else { - getDefaultPseudo(previousMatch, pseudoClass, pseudoValue, matchingElms); - } - return matchingElms; + if (SelectorEngine.eq("~", op)) { + return "\\b" + attrVal + "\\b"; } + return SelectorEngine.truth(attrVal) ? "^" + attrVal + "$" : null; + } - private void getDefaultPseudo(JSArray previousMatch, String pseudoClass, - String pseudoValue, JSArray matchingElms) { - Node previous; - for (int w = 0, wlen = previousMatch.size(); w < wlen; w++) { - previous = previousMatch.getElement(w); - if (SelectorEngine - .eq(((Element) previous).getAttribute(pseudoClass), pseudoValue)) { - matchingElms.addNode(previous); - } - } - } + private static native boolean checked(Node previous) /*-{ + return previous.checked || false; + }-*/; - private JSArray getNotPseudo(JSArray previousMatch, String pseudoValue, - JSArray matchingElms) { - if (new Regexp("(:\\w+[\\w\\-]*)$").test(pseudoValue)) { - matchingElms = subtractArray(previousMatch, - getElementsByPseudo(previousMatch, pseudoValue.substring(1), "")); - } else { - pseudoValue = pseudoValue - .replace("^\\[#([\\w\\u00C0-\\uFFFF\\-\\_]+)\\]$", "[id=$1]"); - JSArray notTag = new Regexp("^(\\w+)").exec(pseudoValue); - JSArray notClass = new Regexp("^\\.([\\w\u00C0-\uFFFF\\-_]+)") - .exec(pseudoValue); - JSArray notAttr = new Regexp( - "\\[(\\w+)(\\^|\\$|\\*|\\||~)?=?([\\w\\u00C0-\\uFFFF\\s\\-_\\.]+)?\\]") - .exec(pseudoValue); - Regexp notRegExp = new Regexp( - "(^|\\s)" + (SelectorEngine.truth(notTag) ? notTag - .getStr(1) - : SelectorEngine.truth(notClass) ? notClass.getStr(1) : "") - + "(\\s|$)", "i"); - if (SelectorEngine.truth(notAttr)) { - String notAttribute = SelectorEngine.truth(notAttr.getStr(3)) ? notAttr - .getStr(3) - .replace("\\.", "\\.") : null; - String notMatchingAttrVal = attrToRegExp(notAttribute, - notAttr.getStr(2)); - notRegExp = new Regexp(notMatchingAttrVal, "i"); - } - for (int v = 0, vlen = previousMatch.size(); v < vlen; v++) { - Element notElm = previousMatch.getElement(v); - Element addElm = null; - if (SelectorEngine.truth(notTag) && !notRegExp - .test(notElm.getNodeName())) { - addElm = notElm; - } else if (SelectorEngine.truth(notClass) && !notRegExp - .test(notElm.getClassName())) { - addElm = notElm; - } else if (SelectorEngine.truth(notAttr)) { - String att = getAttr(notElm, notAttr.getStr(1)); - if (!SelectorEngine.truth(att) || !notRegExp.test(att)) { - addElm = notElm; - } - } - if (SelectorEngine.truth(addElm) && !isAdded(addElm)) { - setAdded(addElm, true); - matchingElms.addNode(addElm); - } - } - } - return matchingElms; + private static void clearChildElms(JSArray prevParents) { + for (int n = 0, nl = prevParents.size(); n < nl; n++) { + setHasChildElms(prevParents.getNode(n), false); } + } - private void getContainsPseudo(JSArray previousMatch, String pseudoValue, - JSArray matchingElms) { - Node previous; - for (int q = 0, qlen = previousMatch.size(); q < qlen; q++) { - previous = previousMatch.getNode(q); - if (!isAdded(previous)) { - if (((Element) previous).getInnerText().indexOf(pseudoValue) != -1) { - setAdded(previous, true); - matchingElms.addNode(previous); - } - } - } - } + private static native boolean enabled(Node node) /*-{ + return !node.disabled; + }-*/; - private void getCheckedPseudo(JSArray previousMatch, JSArray matchingElms) { - Node previous; - for (int q = 0, qlen = previousMatch.size(); q < qlen; q++) { - previous = previousMatch.getNode(q); - if (checked(previous)) { - matchingElms.addNode(previous); - } - } + private static void getDescendantNodes(JSArray matchingElms, + String nextTagStr, Node prevRef) { + NodeList children = getElementsByTagName(nextTagStr, prevRef); + for (int k = 0, klen = children.getLength(); k < klen; k++) { + Node child = children.getItem(k); + if (child.getParentNode() == prevRef) { + matchingElms.addNode(child); + } } - - private void getDisabledPseudo(JSArray previousMatch, JSArray matchingElms) { - Node previous; - for (int q = 0, qlen = previousMatch.size(); q < qlen; q++) { - previous = previousMatch.getNode(q); - if (!enabled(previous)) { - matchingElms.addNode(previous); - } - } + } + + private static NodeList getElementsByTagName(String tag, Node ctx) { + return ((Element) ctx).getElementsByTagName(tag); + } + + private static void getGeneralSiblingNodes(JSArray matchingElms, + JSArray nextTag, Regexp nextRegExp, Node prevRef) { + while ( + SelectorEngine.truth((prevRef = SelectorEngine.getNextSibling(prevRef))) + && !isAdded(prevRef)) { + if (!SelectorEngine.truth(nextTag) || nextRegExp + .test(prevRef.getNodeName())) { + setAdded(prevRef, true); + matchingElms.addNode(prevRef); + } } + } - private void getEnabledPseudo(JSArray previousMatch, JSArray matchingElms) { - Node previous; - for (int q = 0, qlen = previousMatch.size(); q < qlen; q++) { - previous = previousMatch.getNode(q); - if (enabled(previous)) { - matchingElms.addNode(previous); - } - } + private static void getSiblingNodes(JSArray matchingElms, JSArray nextTag, + Regexp nextRegExp, Node prevRef) { + while ( + SelectorEngine.truth(prevRef = SelectorEngine.getNextSibling(prevRef)) + && prevRef.getNodeType() != Node.ELEMENT_NODE) { } - - private void getEmptyPseudo(JSArray previousMatch, JSArray matchingElms) { - Node previous; - for (int q = 0, qlen = previousMatch.size(); q < qlen; q++) { - previous = previousMatch.getNode(q); - if (!previous.hasChildNodes()) { - matchingElms.addNode(previous); - } - } + if (SelectorEngine.truth(prevRef)) { + if (!SelectorEngine.truth(nextTag) || nextRegExp + .test(prevRef.getNodeName())) { + matchingElms.addNode(prevRef); + } } + } - private JSArray getNthOfTypePseudo(JSArray previousMatch, String pseudoValue, - JSArray prevParents, JSArray matchingElms) { - Node previous; - if (pseudoValue.startsWith("n")) { - matchingElms = previousMatch; - } else { - Sequence sequence = getSequence(pseudoValue); - if (sequence != null) { - for (int p = 0, plen = previousMatch.size(); p < plen; p++) { - previous = previousMatch.getNode(p); - Node prevParent = previous.getParentNode(); - if (!hasChildElms(prevParent)) { - int iteratorNext = sequence.start; - int childCount = 0; - Node childElm = prevParent.getFirstChild(); - while (SelectorEngine.truth(childElm) && (sequence.max < 0 - || iteratorNext <= sequence.max)) { - if (SelectorEngine - .eq(childElm.getNodeName(), previous.getNodeName())) { - if (++childCount == iteratorNext) { - matchingElms.addNode(childElm); - iteratorNext += sequence.add; - } - } - childElm = SelectorEngine.getNextSibling(childElm); - } - setHasChildElms(prevParent, true); - prevParents.addNode(prevParent); - } - } - clearChildElms(prevParents); - } - } - return matchingElms; - } + private static native boolean hasChildElms(Node prevParent) /*-{ + return prevParent.childElms || false; + }-*/; - private void getOnlyOfTypePseudo(JSArray previousMatch, - JSArray matchingElms) { - Node previous; - Node next; - Node prev; - Node oParent = null; - for (int o = 0, olen = previousMatch.size(); o < olen; o++) { - prev = next = previous = previousMatch.getNode(o); - Node prevParent = previous.getParentNode(); - if (prevParent != oParent) { - while ( - SelectorEngine.truth(prev = SelectorEngine.getPreviousSibling(prev)) - && !SelectorEngine - .eq(prev.getNodeName(), previous.getNodeName())) { - } - while (SelectorEngine.truth(next = SelectorEngine.getNextSibling(next)) - && !SelectorEngine.eq(next.getNodeName(), previous.getNodeName())) { - } - if (!SelectorEngine.truth(prev) && !SelectorEngine.truth(next)) { - matchingElms.addNode(previous); - } - oParent = prevParent; - } - } - } + private static native boolean isSkipped(JSArray prevElem) /*-{ + return prevElem.skipTag || false; + }-*/; - private void getFirstOfTypePseudo(JSArray previousMatch, boolean previousDir, - JSArray matchingElms) { - Node previous; - Node next; - for (int n = 0, nlen = previousMatch.size(); n < nlen; n++) { - next = previous = previousMatch.getNode(n); - - if (previousDir) { - while ( - SelectorEngine.truth(next = SelectorEngine.getPreviousSibling(next)) - && !SelectorEngine - .eq(next.getNodeName(), previous.getNodeName())) { - } - } else { - while (SelectorEngine.truth(next = SelectorEngine.getNextSibling(next)) - && !SelectorEngine.eq(next.getNodeName(), previous.getNodeName())) { - } - } + private static native void setHasChildElms(Node prevParent, boolean bool) /*-{ + prevParent.childElms = bool ? bool : null; + }-*/; - if (!SelectorEngine.truth(next)) { - matchingElms.addNode(previous); - } + private static native JSArray subtractArray(JSArray previousMatch, + JSArray elementsByPseudo) /*-{ + for (var i=0, src1; (src1=arr1[i]); i++) { + var found = false; + for (var j=0, src2; (src2=arr2[j]); j++) { + if (src2 === src1) { + found = true; + break; + } } - } + if (found) { + arr1.splice(i--, 1); + } + } + return arr; + }-*/; - private JSArray getNthChildPseudo(JSArray previousMatch, String pseudoValue, - JSArray prevParents, JSArray matchingElms) { - Node previous; - if (SelectorEngine.eq(pseudoValue, "n")) { - matchingElms = previousMatch; - } else { - Sequence sequence = getSequence(pseudoValue); - if (sequence != null) { - for (int l = 0, llen = previousMatch.size(); l < llen; l++) { - previous = previousMatch.getNode(l); - Node prevParent = previous.getParentNode(); - if (!hasChildElms(prevParent)) { - int iteratorNext = sequence.start; - int childCount = 0; - Node childElm = prevParent.getFirstChild(); - while (childElm != null && (sequence.max < 0 - || iteratorNext <= sequence.max)) { - if (childElm.getNodeType() == Node.ELEMENT_NODE) { - if (++childCount == iteratorNext) { - if (SelectorEngine - .eq(childElm.getNodeName(), previous.getNodeName())) { - matchingElms.addNode(childElm); - } - iteratorNext += sequence.add; - } - } - childElm = SelectorEngine.getNextSibling(childElm); - } - setHasChildElms(prevParent, true); - prevParents.addNode(prevParent); - } - } - clearChildElms(prevParents); + private Regexp cssSelectorRegExp; + + private Regexp selectorSplitRegExp; + + private Regexp childOrSiblingRefRegExp; + + public SelectorEngineJS() { + selectorSplitRegExp = new Regexp("[^\\s]+", "g"); + childOrSiblingRefRegExp = new Regexp("^(>|\\+|~)$"); + cssSelectorRegExp = new Regexp( + "^(\\w+)?(#[\\w\\u00C0-\\uFFFF\\-\\_]+|(\\*))?((\\.[\\w\\u00C0-\\uFFFF\\-_]+)*)?((\\[\\w+(\\^|\\$|\\*|\\||~)?(=[\\w\\u00C0-\\uFFFF\\s\\-\\_\\.]+)?\\]+)*)?(((:\\w+[\\w\\-]*)(\\((odd|even|\\-?\\d*n?((\\+|\\-)\\d+)?|[\\w\\u00C0-\\uFFFF\\-_]+|((\\w*\\.[\\w\\u00C0-\\uFFFF\\-_]+)*)?|(\\[#?\\w+(\\^|\\$|\\*|\\||~)?=?[\\w\\u00C0-\\uFFFF\\s\\-\\_\\.]+\\]+)|(:\\w+[\\w\\-]*))\\))?)*)?"); + } + + public NodeList select(String sel, Node ctx) { + String selectors[] = sel.replace("\\s*(,)\\s*", "$1").split(","); + boolean identical = false; + JSArray elm = JSArray.create(); + for (int a = 0, len = selectors.length; a < len; a++) { + if (a > 0) { + identical = false; + for (int b = 0, bl = a; b < bl; b++) { + if (SelectorEngine.eq(selectors[a], selectors[b])) { + identical = true; + break; + } + } + if (identical) { + continue; + } + } + String currentRule = selectors[a]; + JSArray cssSelectors = selectorSplitRegExp.match(currentRule); + JSArray prevElem = JSArray.create(ctx); + for (int i = 0, slen = cssSelectors.size(); i < slen; i++) { + JSArray matchingElms = JSArray.create(); + String rule = cssSelectors.getStr(i); + if (i > 0 && childOrSiblingRefRegExp.test(rule)) { + JSArray childOrSiblingRef = childOrSiblingRefRegExp.exec(rule); + if (SelectorEngine.truth(childOrSiblingRef)) { + JSArray nextTag = new Regexp("^\\w+") + .exec(cssSelectors.getStr(i + 1)); + Regexp nextRegExp = null; + String nextTagStr = null; + if (SelectorEngine.truth(nextTag)) { + nextTagStr = nextTag.getStr(0); + nextRegExp = new Regexp("(^|\\s)" + nextTagStr + "(\\s|$)", "i"); + } + for (int j = 0, jlen = prevElem.size(); j < jlen; j++) { + Node prevRef = prevElem.getNode(j); + String ref = childOrSiblingRef.getStr(0); + if (SelectorEngine.eq(">", ref)) { + getDescendantNodes(matchingElms, nextTagStr, prevRef); + } else if (SelectorEngine.eq("+", ref)) { + getSiblingNodes(matchingElms, nextTag, nextRegExp, prevRef); + } else if (SelectorEngine.eq("~", ref)) { + getGeneralSiblingNodes(matchingElms, nextTag, nextRegExp, + prevRef); + } + } + prevElem = matchingElms; + clearAdded(prevElem); + rule = cssSelectors.getStr(++i); + if (new Regexp("^\\w+$").test(rule)) { + continue; } + setSkipTag(prevElem, true); + } } - return matchingElms; - } - - private void getOnlyChildPseudo(JSArray previousMatch, JSArray matchingElms) { - Node previous; - Node next; - Node prev; - Node kParent = null; - for (int k = 0, klen = previousMatch.size(); k < klen; k++) { - prev = next = previous = previousMatch.getNode(k); - Node prevParent = previous.getParentNode(); - if (prevParent != kParent) { - while ( - SelectorEngine.truth(prev = SelectorEngine.getPreviousSibling(prev)) - && prev.getNodeType() != Node.ELEMENT_NODE) { + JSArray cssSelector = cssSelectorRegExp.exec(rule); + SplitRule splitRule = new SplitRule( + !SelectorEngine.truth(cssSelector.getStr(1)) || SelectorEngine + .eq(cssSelector.getStr(3), "*") ? "*" : cssSelector.getStr(1), + !SelectorEngine.eq(cssSelector.getStr(3), "*") ? cssSelector + .getStr(2) : null, cssSelector.getStr(4), cssSelector.getStr(6), + cssSelector.getStr(10)); + if (SelectorEngine.truth(splitRule.id)) { + Element domelem = Document.get() + .getElementById(splitRule.id.substring(1)); + if (SelectorEngine.truth(domelem)) { + matchingElms = JSArray.create(domelem); + } + prevElem = matchingElms; + } else if (SelectorEngine.truth(splitRule.tag) && !isSkipped( + prevElem)) { + if (i == 0 && matchingElms.size() == 0 && prevElem.size() == 1) { + prevElem = matchingElms = JSArray.create( + getElementsByTagName(splitRule.tag, prevElem.getNode(0))); + } else { + NodeList tagCollectionMatches; + for (int l = 0, ll = prevElem.size(); l < ll; l++) { + tagCollectionMatches = getElementsByTagName(splitRule.tag, + prevElem.getNode(l)); + for (int m = 0, mlen = tagCollectionMatches.getLength(); m < mlen; + m++) { + Node tagMatch = tagCollectionMatches.getItem(m); + + if (!isAdded(tagMatch)) { + setAdded(tagMatch, true); + matchingElms.addNode(tagMatch); } - while (SelectorEngine.truth(next = SelectorEngine.getNextSibling(next)) - && next.getNodeType() != Node.ELEMENT_NODE) { + } + } + prevElem = matchingElms; + clearAdded(prevElem); + } + if (matchingElms.size() == 0) { + break; + } + setSkipTag(prevElem, false); + if (SelectorEngine.truth(splitRule.allClasses)) { + String[] allClasses = splitRule.allClasses.replaceFirst("^\\.", "") + .split("\\."); + Regexp[] regExpClassNames = new Regexp[allClasses.length]; + for (int n = 0, nl = allClasses.length; n < nl; n++) { + regExpClassNames[n] = new Regexp( + "(^|\\s)" + allClasses[n] + "(\\s|$)"); + } + JSArray matchingClassElms = JSArray.create(); + for (int o = 0, olen = prevElem.size(); o < olen; o++) { + Element current = prevElem.getElement(o); + String elmClass = current.getClassName(); + boolean addElm = false; + if (SelectorEngine.truth(elmClass) && !isAdded(current)) { + for (int p = 0, pl = regExpClassNames.length; p < pl; p++) { + addElm = regExpClassNames[p].test(elmClass); + if (!addElm) { + break; + } } - if (!SelectorEngine.truth(prev) && !SelectorEngine.truth(next)) { - matchingElms.addNode(previous); + if (addElm) { + setAdded(current, true); + matchingClassElms.addNode(current); } - kParent = prevParent; + } } - } - } - - private void getFirstChildPseudo(JSArray previousMatch, boolean previousDir, - JSArray matchingElms) { - Node next; - Node previous; - for (int j = 0, jlen = previousMatch.size(); j < jlen; j++) { - previous = next = previousMatch.getElement(j); - if (previousDir) { - while (SelectorEngine - .truth((next = SelectorEngine.getPreviousSibling(next))) - && next.getNodeType() != Node.ELEMENT_NODE) { + clearAdded(prevElem); + prevElem = matchingElms = matchingClassElms; + } + if (SelectorEngine.truth(splitRule.allAttr)) { + JSArray allAttr = Regexp + .match("\\[[^\\]]+\\]", "g", splitRule.allAttr); + Regexp[] regExpAttributes = new Regexp[allAttr.size()]; + String[] regExpAttributesStr = new String[allAttr.size()]; + Regexp attributeMatchRegExp = new Regexp( + "(\\w+)(\\^|\\$|\\*|\\||~)?=?([\\w\u00C0-\uFFFF\\s\\-_\\.]+)?"); + for (int q = 0, ql = allAttr.size(); q < ql; q++) { + JSArray attributeMatch = attributeMatchRegExp + .exec(allAttr.getStr(q)); + String attributeValue = + SelectorEngine.truth(attributeMatch.getStr(3)) + ? attributeMatch.getStr(3).replaceAll("\\.", "\\.") + : null; + String attrVal = attrToRegExp(attributeValue, + (SelectorEngine.or(attributeMatch.getStr(2), null))); + regExpAttributes[q] = (SelectorEngine.truth(attrVal) ? new Regexp( + attrVal) : null); + regExpAttributesStr[q] = attributeMatch.getStr(1); + } + JSArray matchingAttributeElms = JSArray.create(); + + for (int r = 0, rlen = matchingElms.size(); r < rlen; r++) { + Element current = matchingElms.getElement(r); + boolean addElm = false; + for (int s = 0, sl = regExpAttributes.length, attributeRegExp; + s < sl; s++) { + addElm = false; + Regexp attributeRegExp2 = regExpAttributes[s]; + String currentAttr = getAttr(current, regExpAttributesStr[s]); + if (SelectorEngine.truth(currentAttr) + && currentAttr.length() != 0) { + if (attributeRegExp2 == null || attributeRegExp2 + .test(currentAttr)) { + addElm = true; + } } - } else { - while ( - SelectorEngine.truth((next = SelectorEngine.getNextSibling(next))) - && next.getNodeType() != Node.ELEMENT_NODE) { + if (!addElm) { + break; } + } + if (addElm) { + matchingAttributeElms.addNode(current); + } } - if (!SelectorEngine.truth(next)) { - matchingElms.addNode(previous); + prevElem = matchingElms = matchingAttributeElms; + } + if (SelectorEngine.truth(splitRule.allPseudos)) { + Regexp pseudoSplitRegExp = new Regexp( + ":(\\w[\\w\\-]*)(\\(([^\\)]+)\\))?"); + + JSArray allPseudos = Regexp + .match("(:\\w+[\\w\\-]*)(\\([^\\)]+\\))?", "g", + splitRule.allPseudos); + for (int t = 0, tl = allPseudos.size(); t < tl; t++) { + JSArray pseudo = pseudoSplitRegExp.match(allPseudos.getStr(t)); + String pseudoClass = SelectorEngine.truth(pseudo.getStr(1)) + ? pseudo.getStr(1).toLowerCase() : null; + String pseudoValue = SelectorEngine.truth(pseudo.getStr(3)) + ? pseudo.getStr(3) : null; + matchingElms = getElementsByPseudo(matchingElms, pseudoClass, + pseudoValue); + clearAdded(matchingElms); } + prevElem = matchingElms; + } } + } + elm.pushAll(prevElem); } - private static native boolean checked(Node previous) /*-{ - return previous.checked || false; - }-*/; + return elm; + } - private static native boolean enabled(Node node) /*-{ - return !node.disabled; - }-*/; + protected String getAttr(Element current, String name) { + return current.getAttribute(name); + } - private static NodeList getElementsByTagName(String tag, Node ctx) { - return ((Element) ctx).getElementsByTagName(tag); + private void getCheckedPseudo(JSArray previousMatch, JSArray matchingElms) { + Node previous; + for (int q = 0, qlen = previousMatch.size(); q < qlen; q++) { + previous = previousMatch.getNode(q); + if (checked(previous)) { + matchingElms.addNode(previous); + } } - - private static void getGeneralSiblingNodes(JSArray matchingElms, - JSArray nextTag, Regexp nextRegExp, Node prevRef) { - while ( - SelectorEngine.truth((prevRef = SelectorEngine.getNextSibling(prevRef))) - && !isAdded(prevRef)) { - if (!SelectorEngine.truth(nextTag) || nextRegExp - .test(prevRef.getNodeName())) { - setAdded(prevRef, true); - matchingElms.addNode(prevRef); - } + } + + private void getContainsPseudo(JSArray previousMatch, String pseudoValue, + JSArray matchingElms) { + Node previous; + for (int q = 0, qlen = previousMatch.size(); q < qlen; q++) { + previous = previousMatch.getNode(q); + if (!isAdded(previous)) { + if (((Element) previous).getInnerText().indexOf(pseudoValue) != -1) { + setAdded(previous, true); + matchingElms.addNode(previous); } + } } - - private static void getSiblingNodes(JSArray matchingElms, JSArray nextTag, - Regexp nextRegExp, Node prevRef) { - while ( - SelectorEngine.truth(prevRef = SelectorEngine.getNextSibling(prevRef)) - && prevRef.getNodeType() != Node.ELEMENT_NODE) { + } + + private void getDefaultPseudo(JSArray previousMatch, String pseudoClass, + String pseudoValue, JSArray matchingElms) { + Node previous; + for (int w = 0, wlen = previousMatch.size(); w < wlen; w++) { + previous = previousMatch.getElement(w); + if (SelectorEngine + .eq(((Element) previous).getAttribute(pseudoClass), pseudoValue)) { + matchingElms.addNode(previous); + } + } + } + + private void getDisabledPseudo(JSArray previousMatch, JSArray matchingElms) { + Node previous; + for (int q = 0, qlen = previousMatch.size(); q < qlen; q++) { + previous = previousMatch.getNode(q); + if (!enabled(previous)) { + matchingElms.addNode(previous); + } + } + } + + private JSArray getElementsByPseudo(JSArray previousMatch, String pseudoClass, + String pseudoValue) { + JSArray prevParents = JSArray.create(); + boolean previousDir = pseudoClass.startsWith("first") ? true : false; + JSArray matchingElms = JSArray.create(); + Node prev, next, previous; + if (SelectorEngine.eq("first-child", pseudoClass) || SelectorEngine + .eq("last-child", pseudoClass)) { + getFirstChildPseudo(previousMatch, previousDir, matchingElms); + } else if (SelectorEngine.eq("only-child", pseudoClass)) { + getOnlyChildPseudo(previousMatch, matchingElms); + } else if (SelectorEngine.eq("nth-child", pseudoClass)) { + matchingElms = getNthChildPseudo(previousMatch, pseudoValue, prevParents, + matchingElms); + } else if (SelectorEngine.eq("first-of-type", pseudoClass) || SelectorEngine + .eq("last-of-type", pseudoClass)) { + getFirstOfTypePseudo(previousMatch, previousDir, matchingElms); + } else if (SelectorEngine.eq("only-of-type", pseudoClass)) { + getOnlyOfTypePseudo(previousMatch, matchingElms); + } else if (SelectorEngine.eq("nth-of-type", pseudoClass)) { + matchingElms = getNthOfTypePseudo(previousMatch, pseudoValue, prevParents, + matchingElms); + } else if (SelectorEngine.eq("empty", pseudoClass)) { + getEmptyPseudo(previousMatch, matchingElms); + } else if (SelectorEngine.eq("enabled", pseudoClass)) { + getEnabledPseudo(previousMatch, matchingElms); + } else if (SelectorEngine.eq("disabled", pseudoClass)) { + getDisabledPseudo(previousMatch, matchingElms); + } else if (SelectorEngine.eq("checked", pseudoClass)) { + getCheckedPseudo(previousMatch, matchingElms); + } else if (SelectorEngine.eq("contains", pseudoClass)) { + getContainsPseudo(previousMatch, pseudoValue, matchingElms); + } else if (SelectorEngine.eq("not", pseudoClass)) { + matchingElms = getNotPseudo(previousMatch, pseudoValue, matchingElms); + } else { + getDefaultPseudo(previousMatch, pseudoClass, pseudoValue, matchingElms); + } + return matchingElms; + } + + private void getEmptyPseudo(JSArray previousMatch, JSArray matchingElms) { + Node previous; + for (int q = 0, qlen = previousMatch.size(); q < qlen; q++) { + previous = previousMatch.getNode(q); + if (!previous.hasChildNodes()) { + matchingElms.addNode(previous); + } + } + } + + private void getEnabledPseudo(JSArray previousMatch, JSArray matchingElms) { + Node previous; + for (int q = 0, qlen = previousMatch.size(); q < qlen; q++) { + previous = previousMatch.getNode(q); + if (enabled(previous)) { + matchingElms.addNode(previous); + } + } + } + + private void getFirstChildPseudo(JSArray previousMatch, boolean previousDir, + JSArray matchingElms) { + Node next; + Node previous; + for (int j = 0, jlen = previousMatch.size(); j < jlen; j++) { + previous = next = previousMatch.getElement(j); + if (previousDir) { + while (SelectorEngine + .truth((next = SelectorEngine.getPreviousSibling(next))) + && next.getNodeType() != Node.ELEMENT_NODE) { } - if (SelectorEngine.truth(prevRef)) { - if (!SelectorEngine.truth(nextTag) || nextRegExp - .test(prevRef.getNodeName())) { - matchingElms.addNode(prevRef); - } + } else { + while ( + SelectorEngine.truth((next = SelectorEngine.getNextSibling(next))) + && next.getNodeType() != Node.ELEMENT_NODE) { } + } + if (!SelectorEngine.truth(next)) { + matchingElms.addNode(previous); + } } + } - private static native boolean hasChildElms(Node prevParent) /*-{ - return prevParent.childElms || false; - }-*/; + private void getFirstOfTypePseudo(JSArray previousMatch, boolean previousDir, + JSArray matchingElms) { + Node previous; + Node next; + for (int n = 0, nlen = previousMatch.size(); n < nlen; n++) { + next = previous = previousMatch.getNode(n); - private static native boolean isSkipped(JSArray prevElem) /*-{ - return prevElem.skipTag || false; - }-*/; - - private static native void setHasChildElms(Node prevParent, boolean bool) /*-{ - prevParent.childElms = bool ? bool : null; - }-*/; + if (previousDir) { + while ( + SelectorEngine.truth(next = SelectorEngine.getPreviousSibling(next)) + && !SelectorEngine + .eq(next.getNodeName(), previous.getNodeName())) { + } + } else { + while (SelectorEngine.truth(next = SelectorEngine.getNextSibling(next)) + && !SelectorEngine.eq(next.getNodeName(), previous.getNodeName())) { + } + } - private static native JSArray subtractArray(JSArray previousMatch, - JSArray elementsByPseudo) /*-{ - for (var i=0, src1; (src1=arr1[i]); i++) { - var found = false; - for (var j=0, src2; (src2=arr2[j]); j++) { - if (src2 === src1) { - found = true; - break; + if (!SelectorEngine.truth(next)) { + matchingElms.addNode(previous); + } + } + } + + private JSArray getNotPseudo(JSArray previousMatch, String pseudoValue, + JSArray matchingElms) { + if (new Regexp("(:\\w+[\\w\\-]*)$").test(pseudoValue)) { + matchingElms = subtractArray(previousMatch, + getElementsByPseudo(previousMatch, pseudoValue.substring(1), "")); + } else { + pseudoValue = pseudoValue + .replace("^\\[#([\\w\\u00C0-\\uFFFF\\-\\_]+)\\]$", "[id=$1]"); + JSArray notTag = new Regexp("^(\\w+)").exec(pseudoValue); + JSArray notClass = new Regexp("^\\.([\\w\u00C0-\uFFFF\\-_]+)") + .exec(pseudoValue); + JSArray notAttr = new Regexp( + "\\[(\\w+)(\\^|\\$|\\*|\\||~)?=?([\\w\\u00C0-\\uFFFF\\s\\-_\\.]+)?\\]") + .exec(pseudoValue); + Regexp notRegExp = new Regexp("(^|\\s)" + + (SelectorEngine.truth(notTag) ? notTag.getStr(1) + : SelectorEngine.truth(notClass) ? notClass.getStr(1) : "") + + "(\\s|$)", "i"); + if (SelectorEngine.truth(notAttr)) { + String notAttribute = SelectorEngine.truth(notAttr.getStr(3)) ? notAttr + .getStr(3).replace("\\.", "\\.") : null; + String notMatchingAttrVal = attrToRegExp(notAttribute, + notAttr.getStr(2)); + notRegExp = new Regexp(notMatchingAttrVal, "i"); + } + for (int v = 0, vlen = previousMatch.size(); v < vlen; v++) { + Element notElm = previousMatch.getElement(v); + Element addElm = null; + if (SelectorEngine.truth(notTag) && !notRegExp + .test(notElm.getNodeName())) { + addElm = notElm; + } else if (SelectorEngine.truth(notClass) && !notRegExp + .test(notElm.getClassName())) { + addElm = notElm; + } else if (SelectorEngine.truth(notAttr)) { + String att = getAttr(notElm, notAttr.getStr(1)); + if (!SelectorEngine.truth(att) || !notRegExp.test(att)) { + addElm = notElm; } } - if (found) { - arr1.splice(i--, 1); + if (SelectorEngine.truth(addElm) && !isAdded(addElm)) { + setAdded(addElm, true); + matchingElms.addNode(addElm); } } - return arr; - }-*/; - - public NodeList select(String sel, Node ctx) { - String selectors[] = sel.replace("\\s*(,)\\s*", "$1").split(","); - boolean identical = false; - JSArray elm = JSArray.create(); - for (int a = 0, len = selectors.length; a < len; a++) { - if (a > 0) { - identical = false; - for (int b = 0, bl = a; b < bl; b++) { - if (SelectorEngine.eq(selectors[a], selectors[b])) { - identical = true; - break; - } - } - if (identical) { - continue; + } + return matchingElms; + } + + private JSArray getNthChildPseudo(JSArray previousMatch, String pseudoValue, + JSArray prevParents, JSArray matchingElms) { + Node previous; + if (SelectorEngine.eq(pseudoValue, "n")) { + matchingElms = previousMatch; + } else { + Sequence sequence = getSequence(pseudoValue); + if (sequence != null) { + for (int l = 0, llen = previousMatch.size(); l < llen; l++) { + previous = previousMatch.getNode(l); + Node prevParent = previous.getParentNode(); + if (!hasChildElms(prevParent)) { + int iteratorNext = sequence.start; + int childCount = 0; + Node childElm = prevParent.getFirstChild(); + while (childElm != null && (sequence.max < 0 + || iteratorNext <= sequence.max)) { + if (childElm.getNodeType() == Node.ELEMENT_NODE) { + if (++childCount == iteratorNext) { + if (SelectorEngine + .eq(childElm.getNodeName(), previous.getNodeName())) { + matchingElms.addNode(childElm); + } + iteratorNext += sequence.add; } + } + childElm = SelectorEngine.getNextSibling(childElm); } - String currentRule = selectors[a]; - JSArray cssSelectors = selectorSplitRegExp.match(currentRule); - JSArray prevElem = JSArray.create(ctx); - for (int i = 0, slen = cssSelectors.size(); i < slen; i++) { - JSArray matchingElms = JSArray.create(); - String rule = cssSelectors.getStr(i); - if (i > 0 && childOrSiblingRefRegExp.test(rule)) { - JSArray childOrSiblingRef = childOrSiblingRefRegExp.exec(rule); - if (SelectorEngine.truth(childOrSiblingRef)) { - JSArray nextTag = new Regexp("^\\w+") - .exec(cssSelectors.getStr(i + 1)); - Regexp nextRegExp = null; - String nextTagStr = null; - if (SelectorEngine.truth(nextTag)) { - nextTagStr = nextTag.getStr(0); - nextRegExp = new Regexp("(^|\\s)" + nextTagStr + "(\\s|$)", "i"); - } - for (int j = 0, jlen = prevElem.size(); j < jlen; j++) { - Node prevRef = prevElem.getNode(j); - String ref = childOrSiblingRef.getStr(0); - if (SelectorEngine.eq(">", ref)) { - getDescendantNodes(matchingElms, nextTagStr, prevRef); - } else if (SelectorEngine.eq("+", ref)) { - getSiblingNodes(matchingElms, nextTag, nextRegExp, prevRef); - } else if (SelectorEngine.eq("~", ref)) { - getGeneralSiblingNodes(matchingElms, nextTag, nextRegExp, - prevRef); - } - } - prevElem = matchingElms; - clearAdded(prevElem); - rule = cssSelectors.getStr(++i); - if (new Regexp("^\\w+$").test(rule)) { - continue; - } - setSkipTag(prevElem, true); - } - } - JSArray cssSelector = cssSelectorRegExp.exec(rule); - SplitRule splitRule = new SplitRule( - !SelectorEngine.truth(cssSelector.getStr(1)) || SelectorEngine - .eq(cssSelector.getStr(3), "*") ? "*" : cssSelector.getStr(1), - !SelectorEngine.eq(cssSelector.getStr(3), "*") ? cssSelector - .getStr(2) : null, cssSelector.getStr(4), cssSelector.getStr(6), - cssSelector.getStr(10)); - if (SelectorEngine.truth(splitRule.id)) { - Element domelem = Document.get() - .getElementById(splitRule.id.substring(1)); - if (SelectorEngine.truth(domelem)) { - matchingElms = JSArray.create(domelem); - } - prevElem = matchingElms; - } else if (SelectorEngine.truth(splitRule.tag) && !isSkipped(prevElem)) { - if (i == 0 && matchingElms.size() == 0 && prevElem.size() == 1) { - prevElem = matchingElms = JSArray.create( - getElementsByTagName(splitRule.tag, prevElem.getNode(0))); - } else { - NodeList tagCollectionMatches; - for (int l = 0, ll = prevElem.size(); l < ll; l++) { - tagCollectionMatches = getElementsByTagName(splitRule.tag, - prevElem.getNode(l)); - for (int m = 0, mlen = tagCollectionMatches.getLength(); m < mlen; - m++) { - Node tagMatch = tagCollectionMatches.getItem(m); - - if (!isAdded(tagMatch)) { - setAdded(tagMatch, true); - matchingElms.addNode(tagMatch); - } - } - } - prevElem = matchingElms; - clearAdded(prevElem); - } - if (matchingElms.size() == 0) { - break; - } - setSkipTag(prevElem, false); - if (SelectorEngine.truth(splitRule.allClasses)) { - String[] allClasses = splitRule.allClasses.replaceFirst("^\\.", "") - .split("\\."); - Regexp[] regExpClassNames = new Regexp[allClasses.length]; - for (int n = 0, nl = allClasses.length; n < nl; n++) { - regExpClassNames[n] = new Regexp( - "(^|\\s)" + allClasses[n] + "(\\s|$)"); - } - JSArray matchingClassElms = JSArray.create(); - for (int o = 0, olen = prevElem.size(); o < olen; o++) { - Element current = prevElem.getElement(o); - String elmClass = current.getClassName(); - boolean addElm = false; - if (SelectorEngine.truth(elmClass) && !isAdded(current)) { - for (int p = 0, pl = regExpClassNames.length; p < pl; p++) { - addElm = regExpClassNames[p].test(elmClass); - if (!addElm) { - break; - } - } - if (addElm) { - setAdded(current, true); - matchingClassElms.addNode(current); - } - } - } - clearAdded(prevElem); - prevElem = matchingElms = matchingClassElms; - } - if (SelectorEngine.truth(splitRule.allAttr)) { - JSArray allAttr = Regexp - .match("\\[[^\\]]+\\]", "g", splitRule.allAttr); - Regexp[] regExpAttributes = new Regexp[allAttr.size()]; - String[] regExpAttributesStr = new String[allAttr.size()]; - Regexp attributeMatchRegExp = new Regexp( - "(\\w+)(\\^|\\$|\\*|\\||~)?=?([\\w\u00C0-\uFFFF\\s\\-_\\.]+)?"); - for (int q = 0, ql = allAttr.size(); q < ql; q++) { - JSArray attributeMatch = attributeMatchRegExp - .exec(allAttr.getStr(q)); - String attributeValue = - SelectorEngine.truth(attributeMatch.getStr(3)) - ? attributeMatch.getStr(3).replaceAll("\\.", "\\.") - : null; - String attrVal = attrToRegExp(attributeValue, - (SelectorEngine.or(attributeMatch.getStr(2), null))); - regExpAttributes[q] = (SelectorEngine.truth(attrVal) ? new Regexp( - attrVal) : null); - regExpAttributesStr[q] = attributeMatch.getStr(1); - } - JSArray matchingAttributeElms = JSArray.create(); - - for (int r = 0, rlen = matchingElms.size(); r < rlen; r++) { - Element current = matchingElms.getElement(r); - boolean addElm = false; - for (int s = 0, sl = regExpAttributes.length, attributeRegExp; - s < sl; s++) { - addElm = false; - Regexp attributeRegExp2 = regExpAttributes[s]; - String currentAttr = getAttr(current, regExpAttributesStr[s]); - if (SelectorEngine.truth(currentAttr) - && currentAttr.length() != 0) { - if (attributeRegExp2 == null || attributeRegExp2 - .test(currentAttr)) { - addElm = true; - } - } - if (!addElm) { - break; - } - } - if (addElm) { - matchingAttributeElms.addNode(current); - } - } - prevElem = matchingElms = matchingAttributeElms; - } - if (SelectorEngine.truth(splitRule.allPseudos)) { - Regexp pseudoSplitRegExp = new Regexp( - ":(\\w[\\w\\-]*)(\\(([^\\)]+)\\))?"); - - JSArray allPseudos = Regexp.match( - "(:\\w+[\\w\\-]*)(\\([^\\)]+\\))?", "g", splitRule.allPseudos); - for (int t = 0, tl = allPseudos.size(); t < tl; t++) { - JSArray pseudo = pseudoSplitRegExp.match(allPseudos.getStr(t)); - String pseudoClass = SelectorEngine.truth(pseudo.getStr(1)) - ? pseudo.getStr(1) - .toLowerCase() : null; - String pseudoValue = SelectorEngine.truth(pseudo.getStr(3)) - ? pseudo.getStr(3) : null; - matchingElms = getElementsByPseudo(matchingElms, pseudoClass, - pseudoValue); - clearAdded(matchingElms); - } - prevElem = matchingElms; - } + setHasChildElms(prevParent, true); + prevParents.addNode(prevParent); + } + } + clearChildElms(prevParents); + } + } + return matchingElms; + } + + private JSArray getNthOfTypePseudo(JSArray previousMatch, String pseudoValue, + JSArray prevParents, JSArray matchingElms) { + Node previous; + if (pseudoValue.startsWith("n")) { + matchingElms = previousMatch; + } else { + Sequence sequence = getSequence(pseudoValue); + if (sequence != null) { + for (int p = 0, plen = previousMatch.size(); p < plen; p++) { + previous = previousMatch.getNode(p); + Node prevParent = previous.getParentNode(); + if (!hasChildElms(prevParent)) { + int iteratorNext = sequence.start; + int childCount = 0; + Node childElm = prevParent.getFirstChild(); + while (SelectorEngine.truth(childElm) && (sequence.max < 0 + || iteratorNext <= sequence.max)) { + if (SelectorEngine + .eq(childElm.getNodeName(), previous.getNodeName())) { + if (++childCount == iteratorNext) { + matchingElms.addNode(childElm); + iteratorNext += sequence.add; } + } + childElm = SelectorEngine.getNextSibling(childElm); } - elm.pushAll(prevElem); + setHasChildElms(prevParent, true); + prevParents.addNode(prevParent); + } } - - return elm; + clearChildElms(prevParents); + } + } + return matchingElms; + } + + private void getOnlyChildPseudo(JSArray previousMatch, JSArray matchingElms) { + Node previous; + Node next; + Node prev; + Node kParent = null; + for (int k = 0, klen = previousMatch.size(); k < klen; k++) { + prev = next = previous = previousMatch.getNode(k); + Node prevParent = previous.getParentNode(); + if (prevParent != kParent) { + while ( + SelectorEngine.truth(prev = SelectorEngine.getPreviousSibling(prev)) + && prev.getNodeType() != Node.ELEMENT_NODE) { + } + while (SelectorEngine.truth(next = SelectorEngine.getNextSibling(next)) + && next.getNodeType() != Node.ELEMENT_NODE) { + } + if (!SelectorEngine.truth(prev) && !SelectorEngine.truth(next)) { + matchingElms.addNode(previous); + } + kParent = prevParent; + } + } + } + + private void getOnlyOfTypePseudo(JSArray previousMatch, + JSArray matchingElms) { + Node previous; + Node next; + Node prev; + Node oParent = null; + for (int o = 0, olen = previousMatch.size(); o < olen; o++) { + prev = next = previous = previousMatch.getNode(o); + Node prevParent = previous.getParentNode(); + if (prevParent != oParent) { + while ( + SelectorEngine.truth(prev = SelectorEngine.getPreviousSibling(prev)) + && !SelectorEngine + .eq(prev.getNodeName(), previous.getNodeName())) { + } + while (SelectorEngine.truth(next = SelectorEngine.getNextSibling(next)) + && !SelectorEngine.eq(next.getNodeName(), previous.getNodeName())) { + } + if (!SelectorEngine.truth(prev) && !SelectorEngine.truth(next)) { + matchingElms.addNode(previous); + } + oParent = prevParent; + } } + } } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineJSIE.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineJSIE.java index e2a2cf16..be93619b 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineJSIE.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineJSIE.java @@ -3,19 +3,20 @@ package com.google.gwt.query.client.impl; import com.google.gwt.dom.client.Element; /** - * Runtime implementaton of non-XPath/native for IE that fixes some - * DOM operation incompatibilities. + * Runtime implementaton of non-XPath/native for IE that fixes some DOM + * operation incompatibilities. */ public class SelectorEngineJSIE extends SelectorEngineJS { - public native String getAttr(Element elm, String attr) /*-{ + + public native String getAttr(Element elm, String attr) /*-{ switch (attr) { - case "id": - return elm.id; - case "for": - return elm.htmlFor; - case "class": - return elm.className; - } - return elm.getAttribute(attr, 2); + case "id": + return elm.id; + case "for": + return elm.htmlFor; + case "class": + return elm.className; + } + return elm.getAttribute(attr, 2); }-*/; } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineNative.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineNative.java index 130142b2..6656aa8c 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineNative.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineNative.java @@ -1,3 +1,18 @@ +/* + * Copyright 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ package com.google.gwt.query.client.impl; import com.google.gwt.dom.client.Element; diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineXPath.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineXPath.java index 4fa316fc..dafed4e4 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineXPath.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineXPath.java @@ -1,3 +1,18 @@ +/* + * Copyright 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ package com.google.gwt.query.client.impl; import com.google.gwt.core.client.GWT; @@ -16,204 +31,206 @@ import static com.google.gwt.query.client.SelectorEngine.truth; * and delegates to document.evaluate(). */ public class SelectorEngineXPath extends SelectorEngineImpl { - private Regexp cssSelectorRegExp; - private Regexp selectorSplitRegExp; - private Regexp COMBINATOR; - public SelectorEngineXPath() { + private static String attrToXPath(String match, String p1, String p2, + String p3) { + if (eq("^", p2)) { + return "starts-with(@" + p1 + ", '" + p3 + "')"; } - - private void init() { - if (cssSelectorRegExp == null) { - cssSelectorRegExp = new Regexp( - "^(\\w+)?(#[\\w\\u00C0-\\uFFFF\\-\\_]+|(\\*))?((\\.[\\w\\u00C0-\\uFFFF\\-_]+)*)?((\\[\\w+(\\^|\\$|\\*|\\||~)?(=[\\w\\u00C0-\\uFFFF\\s\\-\\_\\.]+)?\\]+)*)?(((:\\w+[\\w\\-]*)(\\((odd|even|\\-?\\d*n?((\\+|\\-)\\d+)?|[\\w\\u00C0-\\uFFFF\\-_]+|((\\w*\\.[\\w\\u00C0-\\uFFFF\\-_]+)*)?|(\\[#?\\w+(\\^|\\$|\\*|\\||~)?=?[\\w\\u00C0-\\uFFFF\\s\\-\\_\\.]+\\]+)|(:\\w+[\\w\\-]*))\\))?)*)?(>|\\+|~)?"); - selectorSplitRegExp = new Regexp("[^\\s]+", "g"); - COMBINATOR = new Regexp("(>|\\+|~)"); - } + if (eq("$", p2)) { + return "substring(@" + p1 + ", (string-length(@" + p1 + ") - " + + (p3.length() - 1) + "), " + p3.length() + ") = '" + p3 + "'"; + } + if (eq("*", p2)) { + return "contains(concat(' ', @" + p1 + ", ' '), '" + p3 + "')"; } + if (eq("|", p2)) { + return "(@" + p1 + "='" + p3 + "' or starts-with(@" + p1 + ", '" + p3 + + "-'))"; + } + if (eq("~", p2)) { + return "contains(concat(' ', @" + p1 + ", ' '), ' " + p3 + " ')"; + } + return "@" + p1 + (truth(p3) ? "='" + p3 + "'" : ""); + } + private Regexp cssSelectorRegExp; - public NodeList select(String sel, Node ctx) { - init(); - String selectors[] = sel.replaceAll("\\s*(,)\\s*", "$1").split(","); - boolean identical = false; - JSArray elm = JSArray.create(); - for (int a = 0, len = selectors.length; a < len; a++) { - if (a > 0) { - identical = false; - for (int b = 0, bl = a; b < bl; b++) { - if (eq(selectors[a], selectors[b])) { - identical = true; - break; - } - } - if (identical) { - continue; - } - } - String currentRule = selectors[a]; - JSArray cssSelectors = selectorSplitRegExp.match(currentRule); - String xPathExpression = "."; - for (int i = 0, slen = cssSelectors.size(); i < slen; i++) { - String rule = cssSelectors.getStr(i); - JSArray cssSelector = cssSelectorRegExp.exec(rule); - SplitRule splitRule = new SplitRule(!truth(cssSelector.getStr(1)) || eq( - cssSelector.getStr(3), "*") ? "*" : cssSelector.getStr(1), - !eq(cssSelector.getStr(3), "*") ? cssSelector.getStr(2) : null, - cssSelector.getStr(4), cssSelector.getStr(6), - cssSelector.getStr(10), cssSelector.getStr(22)); - if (truth(splitRule.tagRelation)) { - if (eq(">", splitRule.tagRelation)) { - xPathExpression += "/child::"; - } else if (eq("+", splitRule.tagRelation)) { - xPathExpression += "/following-sibling::*[1]/self::"; - } else if (eq("~", splitRule.tagRelation)) { - xPathExpression += "/following-sibling::"; - } - } else { - xPathExpression += - (i > 0 && COMBINATOR.test(cssSelectors.getStr(i - 1))) - ? splitRule.tag : ("/descendant::" + splitRule.tag); - } - if (truth(splitRule.id)) { - xPathExpression += "[@id = '" + splitRule.id.replaceAll("^#", "") - + "']"; - } - if (truth(splitRule.allClasses)) { - xPathExpression += splitRule.allClasses.replaceAll( - "\\.([\\w\\u00C0-\\uFFFF\\-_]+)", - "[contains(concat(' ', @class, ' '), ' $1 ')]"); - } - if (truth(splitRule.allAttr)) { - GWT.log("AllAttr is " + splitRule.allAttr, null); - xPathExpression += replaceAttr( - SelectorEngine.or(splitRule.allAttr, "")); - } - if (truth(splitRule.allPseudos)) { - Regexp pseudoSplitRegExp = new Regexp( - ":(\\w[\\w\\-]*)(\\(([^\\)]+)\\))?"); - Regexp pseudoMatchRegExp = new Regexp( - "(:\\w+[\\w\\-]*)(\\([^\\)]+\\))?", "g"); - JSArray allPseudos = pseudoMatchRegExp.match(splitRule.allPseudos); - for (int k = 0, kl = allPseudos.size(); k < kl; k++) { - JSArray pseudo = pseudoSplitRegExp.match(allPseudos.getStr(k)); - String pseudoClass = truth(pseudo.getStr(1)) ? pseudo.getStr(1) - .toLowerCase() : null; - String pseudoValue = truth(pseudo.getStr(3)) ? pseudo.getStr(3) - : null; - String xpath = pseudoToXPath(splitRule.tag, pseudoClass, - pseudoValue); - if (xpath.length() > 0) { - xPathExpression += "[" + xpath + "]"; - } - } - } - } - SelectorEngine.xpathEvaluate(xPathExpression, ctx, elm); - } - return elm; - } + private Regexp selectorSplitRegExp; - private String pseudoToXPath(String tag, String pseudoClass, - String pseudoValue) { - String xpath = ""; - if (eq("first-child", pseudoClass)) { - xpath = "not(preceding-sibling::*)"; - } else if (eq("first-of-type", pseudoClass)) { - xpath = "not(preceding-sibling::" + tag + ")"; - } else if (eq("last-child", pseudoClass)) { - xpath = "not(following-sibling::*)"; - } else if (eq("last-of-type", pseudoClass)) { - xpath = "not(following-sibling::" + tag + ")"; - } else if (eq("only-child", pseudoClass)) { - xpath = "not(preceding-sibling::* or following-sibling::*)"; - } else if (eq("only-of-type", pseudoClass)) { - xpath = "not(preceding-sibling::" + tag + " or following-sibling::" + tag - + ")"; - } else if (eq("nth-child", pseudoClass)) { - if (!eq("n", pseudoClass)) { - Sequence sequence = getSequence(pseudoValue); - if (sequence != null) { - if (sequence.start == sequence.max) { - xpath = "count(preceding-sibling::*) = " + (sequence.start - 1); - } else { - xpath = "(count(preceding-sibling::*) + 1) mod " + sequence.add - + " = " + sequence.modVal + ((sequence.start > 1) ? - " and count(preceding-sibling::*) >= " + (sequence.start - 1) - : "") + ((sequence.max > 0) ? - " and count(preceding-sibling::*) <= " + (sequence.max - 1) - : ""); - } - } - } - } else if (eq("nth-of-type", pseudoClass)) { - if (!pseudoValue.startsWith("n")) { - Sequence sequence = getSequence(pseudoValue); - if (sequence != null) { - if (sequence.start == sequence.max) { - xpath = pseudoValue; - } else { - xpath = "position() mod " + sequence.add + " = " + sequence.modVal - + ((sequence.start > 1) ? " and position() >= " + sequence - .start : "") + ((sequence.max > 0) ? " and position() <= " - + sequence.max : ""); - } - } - } - } else if (eq("empty", pseudoClass)) { - xpath = "count(child::*) = 0 and string-length(text()) = 0"; - } else if (eq("contains", pseudoClass)) { - xpath = "contains(., '" + pseudoValue + "')"; - } else if (eq("enabled", pseudoClass)) { - xpath = "not(@disabled)"; - } else if (eq("disabled", pseudoClass)) { - xpath = "@disabled"; - } else if (eq("checked", pseudoClass)) { - xpath = "@checked='checked'"; // Doesn't work in Opera 9.24 - } else if (eq("not", pseudoClass)) { - if (new Regexp("^(:\\w+[\\w\\-]*)$").test(pseudoValue)) { - xpath = "not(" + pseudoToXPath(tag, pseudoValue.substring(1), "") + ")"; - } else { + private Regexp combinator; - pseudoValue = pseudoValue - .replaceFirst("^\\[#([\\w\\u00C0-\\uFFFF\\-\\_]+)\\]$", "[id=$1]"); - String notSelector = pseudoValue - .replaceFirst("^(\\w+)", "self::$1"); - notSelector = notSelector.replaceAll("^\\.([\\w\\u00C0-\\uFFFF\\-_]+)", - "contains(concat(' ', @class, ' '), ' $1 ')"); - notSelector = replaceAttr2(notSelector); - xpath = "not(" + notSelector + ")"; - } + public SelectorEngineXPath() { + } + + public NodeList select(String sel, Node ctx) { + init(); + String selectors[] = sel.replaceAll("\\s*(,)\\s*", "$1").split(","); + boolean identical = false; + JSArray elm = JSArray.create(); + for (int a = 0, len = selectors.length; a < len; a++) { + if (a > 0) { + identical = false; + for (int b = 0, bl = a; b < bl; b++) { + if (eq(selectors[a], selectors[b])) { + identical = true; + break; + } + } + if (identical) { + continue; + } + } + String currentRule = selectors[a]; + JSArray cssSelectors = selectorSplitRegExp.match(currentRule); + String xPathExpression = "."; + for (int i = 0, slen = cssSelectors.size(); i < slen; i++) { + String rule = cssSelectors.getStr(i); + JSArray cssSelector = cssSelectorRegExp.exec(rule); + SplitRule splitRule = new SplitRule( + !truth(cssSelector.getStr(1)) || eq(cssSelector.getStr(3), "*") + ? "*" : cssSelector.getStr(1), + !eq(cssSelector.getStr(3), "*") ? cssSelector.getStr(2) : null, + cssSelector.getStr(4), cssSelector.getStr(6), + cssSelector.getStr(10), cssSelector.getStr(22)); + if (truth(splitRule.tagRelation)) { + if (eq(">", splitRule.tagRelation)) { + xPathExpression += "/child::"; + } else if (eq("+", splitRule.tagRelation)) { + xPathExpression += "/following-sibling::*[1]/self::"; + } else if (eq("~", splitRule.tagRelation)) { + xPathExpression += "/following-sibling::"; + } } else { - xpath = "@" + pseudoClass + "='" + pseudoValue + "'"; + xPathExpression += + (i > 0 && combinator.test(cssSelectors.getStr(i - 1))) + ? splitRule.tag : ("/descendant::" + splitRule.tag); } - - return xpath; - } - - private static String attrToXPath(String match, String p1, String p2, - String p3) { - if (eq("^", p2)) { - return "starts-with(@" + p1 + ", '" + p3 + "')"; + if (truth(splitRule.id)) { + xPathExpression += "[@id = '" + splitRule.id.replaceAll("^#", "") + + "']"; } - if (eq("$", p2)) { - return "substring(@" + p1 + ", (string-length(@" + p1 + ") - " - + (p3.length() - 1) + "), " + p3.length() + ") = '" + p3 + "'"; + if (truth(splitRule.allClasses)) { + xPathExpression += splitRule.allClasses + .replaceAll("\\.([\\w\\u00C0-\\uFFFF\\-_]+)", + "[contains(concat(' ', @class, ' '), ' $1 ')]"); } - if (eq("*", p2)) { - return "contains(concat(' ', @" + p1 + ", ' '), '" + p3 + "')"; + if (truth(splitRule.allAttr)) { + GWT.log("AllAttr is " + splitRule.allAttr, null); + xPathExpression += replaceAttr( + SelectorEngine.or(splitRule.allAttr, "")); } - if (eq("|", p2)) { - return "(@" + p1 + "='" + p3 + "' or starts-with(@" + p1 + ", '" + p3 - + "-'))"; + if (truth(splitRule.allPseudos)) { + Regexp pseudoSplitRegExp = new Regexp( + ":(\\w[\\w\\-]*)(\\(([^\\)]+)\\))?"); + Regexp pseudoMatchRegExp = new Regexp( + "(:\\w+[\\w\\-]*)(\\([^\\)]+\\))?", "g"); + JSArray allPseudos = pseudoMatchRegExp.match(splitRule.allPseudos); + for (int k = 0, kl = allPseudos.size(); k < kl; k++) { + JSArray pseudo = pseudoSplitRegExp.match(allPseudos.getStr(k)); + String pseudoClass = truth(pseudo.getStr(1)) ? pseudo.getStr(1) + .toLowerCase() : null; + String pseudoValue = truth(pseudo.getStr(3)) ? pseudo.getStr(3) + : null; + String xpath = pseudoToXPath(splitRule.tag, pseudoClass, + pseudoValue); + if (xpath.length() > 0) { + xPathExpression += "[" + xpath + "]"; + } + } } - if (eq("~", p2)) { - return "contains(concat(' ', @" + p1 + ", ' '), ' " + p3 + " ')"; + } + SelectorEngine.xpathEvaluate(xPathExpression, ctx, elm); + } + return elm; + } + + private void init() { + if (cssSelectorRegExp == null) { + cssSelectorRegExp = new Regexp( + "^(\\w+)?(#[\\w\\u00C0-\\uFFFF\\-\\_]+|(\\*))?((\\.[\\w\\u00C0-\\uFFFF\\-_]+)*)?((\\[\\w+(\\^|\\$|\\*|\\||~)?(=[\\w\\u00C0-\\uFFFF\\s\\-\\_\\.]+)?\\]+)*)?(((:\\w+[\\w\\-]*)(\\((odd|even|\\-?\\d*n?((\\+|\\-)\\d+)?|[\\w\\u00C0-\\uFFFF\\-_]+|((\\w*\\.[\\w\\u00C0-\\uFFFF\\-_]+)*)?|(\\[#?\\w+(\\^|\\$|\\*|\\||~)?=?[\\w\\u00C0-\\uFFFF\\s\\-\\_\\.]+\\]+)|(:\\w+[\\w\\-]*))\\))?)*)?(>|\\+|~)?"); + selectorSplitRegExp = new Regexp("[^\\s]+", "g"); + combinator = new Regexp("(>|\\+|~)"); + } + } + + private String pseudoToXPath(String tag, String pseudoClass, + String pseudoValue) { + String xpath = ""; + if (eq("first-child", pseudoClass)) { + xpath = "not(preceding-sibling::*)"; + } else if (eq("first-of-type", pseudoClass)) { + xpath = "not(preceding-sibling::" + tag + ")"; + } else if (eq("last-child", pseudoClass)) { + xpath = "not(following-sibling::*)"; + } else if (eq("last-of-type", pseudoClass)) { + xpath = "not(following-sibling::" + tag + ")"; + } else if (eq("only-child", pseudoClass)) { + xpath = "not(preceding-sibling::* or following-sibling::*)"; + } else if (eq("only-of-type", pseudoClass)) { + xpath = "not(preceding-sibling::" + tag + " or following-sibling::" + tag + + ")"; + } else if (eq("nth-child", pseudoClass)) { + if (!eq("n", pseudoClass)) { + Sequence sequence = getSequence(pseudoValue); + if (sequence != null) { + if (sequence.start == sequence.max) { + xpath = "count(preceding-sibling::*) = " + (sequence.start - 1); + } else { + xpath = "(count(preceding-sibling::*) + 1) mod " + sequence.add + + " = " + sequence.modVal + + ((sequence.start > 1) ? " and count(preceding-sibling::*) >= " + + (sequence.start - 1) : "") + ((sequence.max > 0) ? + " and count(preceding-sibling::*) <= " + (sequence.max - 1) + : ""); + } } - return "@" + p1 + (truth(p3) ? "='" + p3 + "'" : ""); + } + } else if (eq("nth-of-type", pseudoClass)) { + if (!pseudoValue.startsWith("n")) { + Sequence sequence = getSequence(pseudoValue); + if (sequence != null) { + if (sequence.start == sequence.max) { + xpath = pseudoValue; + } else { + xpath = "position() mod " + sequence.add + " = " + sequence.modVal + + ((sequence.start > 1) ? " and position() >= " + sequence.start + : "") + ((sequence.max > 0) ? " and position() <= " + + sequence.max : ""); + } + } + } + } else if (eq("empty", pseudoClass)) { + xpath = "count(child::*) = 0 and string-length(text()) = 0"; + } else if (eq("contains", pseudoClass)) { + xpath = "contains(., '" + pseudoValue + "')"; + } else if (eq("enabled", pseudoClass)) { + xpath = "not(@disabled)"; + } else if (eq("disabled", pseudoClass)) { + xpath = "@disabled"; + } else if (eq("checked", pseudoClass)) { + xpath = "@checked='checked'"; // Doesn't work in Opera 9.24 + } else if (eq("not", pseudoClass)) { + if (new Regexp("^(:\\w+[\\w\\-]*)$").test(pseudoValue)) { + xpath = "not(" + pseudoToXPath(tag, pseudoValue.substring(1), "") + ")"; + } else { + + pseudoValue = pseudoValue + .replaceFirst("^\\[#([\\w\\u00C0-\\uFFFF\\-\\_]+)\\]$", "[id=$1]"); + String notSelector = pseudoValue.replaceFirst("^(\\w+)", "self::$1"); + notSelector = notSelector.replaceAll("^\\.([\\w\\u00C0-\\uFFFF\\-_]+)", + "contains(concat(' ', @class, ' '), ' $1 ')"); + notSelector = replaceAttr2(notSelector); + xpath = "not(" + notSelector + ")"; + } + } else { + xpath = "@" + pseudoClass + "='" + pseudoValue + "'"; } - private native String replaceAttr(String allAttr) /*-{ + return xpath; + } + + private native String replaceAttr(String allAttr) /*-{ if(!allAttr) return ""; return allAttr.replace(/(\w+)(\^|\$|\*|\||~)?=?([\w\u00C0-\uFFFF\s\-_\.]+)?/g, function(a,b,c,d) { @@ -222,7 +239,7 @@ public class SelectorEngineXPath extends SelectorEngineImpl { }-*/; - private native String replaceAttr2(String allAttr) /*-{ + private native String replaceAttr2(String allAttr) /*-{ if(!allAttr) return ""; return allAttr.replace(/\[(\w+)(\^|\$|\*|\||~)?=?([\w\u00C0-\uFFFF\s\-_\.]+)?\]/g, @com.google.gwt.query.client.impl.SelectorEngineXPath::attrToXPath(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)); }-*/; diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorBase.java b/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorBase.java index e19d9b4d..eeb90e2d 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorBase.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorBase.java @@ -1,3 +1,18 @@ +/* + * Copyright 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ package com.google.gwt.query.rebind; import com.google.gwt.core.ext.Generator; @@ -19,16 +34,16 @@ import java.io.PrintWriter; */ public abstract class SelectorGeneratorBase extends Generator { - private TreeLogger treeLogger; + protected JClassType nodeType = null; - protected JClassType NODE_TYPE = null; + private TreeLogger treeLogger; public String generate(TreeLogger treeLogger, GeneratorContext generatorContext, String requestedClass) throws UnableToCompleteException { this.treeLogger = treeLogger; TypeOracle oracle = generatorContext.getTypeOracle(); - NODE_TYPE = oracle.findType("com.google.gwt.dom.client.Node"); + nodeType = oracle.findType("com.google.gwt.dom.client.Node"); JClassType selectorType = oracle.findType(requestedClass); SourceWriter sw = getSourceWriter(treeLogger, generatorContext, @@ -46,60 +61,25 @@ public abstract class SelectorGeneratorBase extends Generator { + selectorType.getSimpleSourceName() + getImplSuffix(); } - protected String getImplSuffix() { - return "Impl"; - } - - // used by benchmark harness - private void genGetAllMethod(SourceWriter sw, JMethod[] methods, - TreeLogger treeLogger) { - sw.println("public DeferredGQuery[] getAllSelectors() {"); - sw.indent(); - sw.println( - "DeferredGQuery[] dg = new DeferredGQuery[" + (methods.length) + "];"); - int i = 0; - for (JMethod m : methods) { - Selector selectorAnnotation = m.getAnnotation(Selector.class); - if(selectorAnnotation == null) continue; - String selector = selectorAnnotation.value(); - - sw.println("dg[" + i + "]=new DeferredGQuery() {"); - sw.indent(); - sw.println( - "public String getSelector() { return \"" + selector + "\"; }"); - sw.println("public GQuery eval(Node ctx) { return " + wrapJS(m, m.getName() - + (m.getParameters().length == 0 ? "()" : "(ctx)")+"") + " ;}"); - sw.println("public NodeList array(Node ctx) { return "+("NodeList".equals(m.getReturnType().getSimpleSourceName()) ? - (m.getName() - + (m.getParameters().length == 0 ? "(); " : "(ctx); ")) : - "eval"+(m.getParameters().length == 0 ? "(null).get(); " : "(ctx).get(); "))+"}"); - - i++; - sw.outdent(); - sw.println("};"); - } - sw.println("return dg;"); - sw.outdent(); - sw.println("}"); - } - public void generateMethod(SourceWriter sw, JMethod method, TreeLogger logger) throws UnableToCompleteException { - Selector selectorAnnotation = method.getAnnotation(Selector.class); - if(selectorAnnotation == null) return; + Selector selectorAnnotation = method.getAnnotation(Selector.class); + if (selectorAnnotation == null) { + return; + } - String selector = selectorAnnotation.value(); JParameter[] params = method.getParameters(); sw.indent(); - String retType = method.getReturnType().getParameterizedQualifiedSourceName(); - sw.print("public final "+retType+" "+method.getName()); + String retType = method.getReturnType() + .getParameterizedQualifiedSourceName(); + sw.print("public final " + retType + " " + method.getName()); boolean hasContext = false; if (params.length == 0) { sw.print("()"); } else if (params.length == 1) { JClassType type = params[0].getType().isClassOrInterface(); - if (type != null && type.isAssignableTo(NODE_TYPE)) { + if (type != null && type.isAssignableTo(nodeType)) { sw.print("(Node root)"); hasContext = true; } @@ -110,19 +90,21 @@ public abstract class SelectorGeneratorBase extends Generator { // short circuit #foo if (sel != null && sel.value().matches("^#\\w+$")) { - sw.println("return "+wrap(method, "JSArray.create(((Document)" + (hasContext ? "root" : "(Node)Document.get()") - + ").getElementById(\"" + sel.value().substring(1) + "\"))")+";"); - } - // short circuit FOO - else if (sel != null && sel.value().matches("^\\w+$")) { - sw.println("return "+wrap(method, "JSArray.create(((Element)"+(hasContext ? "root" : "(Node)Document.get()") - + ").getElementsByTagName(\"" + sel.value() + "\"))")+";"); - } // short circuit .foo for browsers with native getElementsByClassName - else if (sel != null && sel.value().matches("^\\.\\w+$") + sw.println("return " + wrap(method, "JSArray.create(((Document)" + + (hasContext ? "root" : "(Node)Document.get()") + + ").getElementById(\"" + sel.value().substring(1) + "\"))") + ";"); + } else if (sel != null && sel.value().matches("^\\w+$")) { + // short circuit FOO + sw.println("return " + wrap(method, "JSArray.create(((Element)" + + (hasContext ? "root" : "(Node)Document.get()") + + ").getElementsByTagName(\"" + sel.value() + "\"))") + ";"); + } else if (sel != null && sel.value().matches("^\\.\\w+$") && hasGetElementsByClassName()) { - sw.println("return "+wrap(method, "JSArray.create(getElementsByClassName(\"" - + sel.value().substring(1) + "\", " + (hasContext ? "root" : "(Node)Document.get()") - + "))")+";"); + // short circuit .foo for browsers with native getElementsByClassName + sw.println("return " + wrap(method, + "JSArray.create(getElementsByClassName(\"" + sel.value().substring(1) + + "\", " + (hasContext ? "root" : "(Node)Document.get()") + "))") + + ";"); } else { generateMethodBody(sw, method, logger, hasContext); } @@ -131,17 +113,16 @@ public abstract class SelectorGeneratorBase extends Generator { sw.outdent(); } - protected boolean hasGetElementsByClassName() { - return false; - } - protected void debug(String s) { // System.err.println(s); treeLogger.log(TreeLogger.DEBUG, s, null); } - protected boolean notNull(String s) { - return s != null && !"".equals(s); + protected abstract void generateMethodBody(SourceWriter sw, JMethod method, + TreeLogger logger, boolean hasContext) throws UnableToCompleteException; + + protected String getImplSuffix() { + return "Impl"; } protected SourceWriter getSourceWriter(TreeLogger logger, @@ -166,26 +147,64 @@ public abstract class SelectorGeneratorBase extends Generator { return composerFactory.createSourceWriter(context, printWriter); } + protected boolean hasGetElementsByClassName() { + return false; + } + + protected boolean notNull(String s) { + return s != null && !"".equals(s); + } + protected String wrap(JMethod method, String expr) { - if("NodeList".equals(method.getReturnType().getSimpleSourceName())) { + if ("NodeList".equals(method.getReturnType().getSimpleSourceName())) { return expr; + } else { + return "new GQuery(" + expr + ")"; } - else { - return "new GQuery("+expr+")"; - } - } - + protected String wrapJS(JMethod method, String expr) { - if("GQuery".equals(method.getReturnType().getSimpleSourceName())) { + if ("GQuery".equals(method.getReturnType().getSimpleSourceName())) { return expr; + } else { + return "new GQuery(" + expr + ")"; } - else { - return "new GQuery("+expr+")"; + } + + // used by benchmark harness + private void genGetAllMethod(SourceWriter sw, JMethod[] methods, + TreeLogger treeLogger) { + sw.println("public DeferredGQuery[] getAllSelectors() {"); + sw.indent(); + sw.println( + "DeferredGQuery[] dg = new DeferredGQuery[" + (methods.length) + "];"); + int i = 0; + for (JMethod m : methods) { + Selector selectorAnnotation = m.getAnnotation(Selector.class); + if (selectorAnnotation == null) { + continue; + } + String selector = selectorAnnotation.value(); + + sw.println("dg[" + i + "]=new DeferredGQuery() {"); + sw.indent(); + sw.println( + "public String getSelector() { return \"" + selector + "\"; }"); + sw.println("public GQuery eval(Node ctx) { return " + wrapJS(m, + m.getName() + (m.getParameters().length == 0 ? "()" : "(ctx)") + "") + + " ;}"); + sw.println("public NodeList array(Node ctx) { return " + + ("NodeList".equals(m.getReturnType().getSimpleSourceName()) ? ( + m.getName() + (m.getParameters().length == 0 ? "(); " : "(ctx); ")) + : "eval" + (m.getParameters().length == 0 ? "(null).get(); " + : "(ctx).get(); ")) + "}"); + + i++; + sw.outdent(); + sw.println("};"); } - + sw.println("return dg;"); + sw.outdent(); + sw.println("}"); } - - protected abstract void generateMethodBody(SourceWriter sw, JMethod method, - TreeLogger logger, boolean hasContext) throws UnableToCompleteException; } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorJS.java b/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorJS.java index 67162e62..8e0b9c5e 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorJS.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorJS.java @@ -1,3 +1,18 @@ +/* + * Copyright 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ package com.google.gwt.query.rebind; import com.google.gwt.core.ext.TreeLogger; diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorJSOptimal.java b/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorJSOptimal.java index 782b2d61..442648ac 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorJSOptimal.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorJSOptimal.java @@ -1,22 +1,47 @@ +/* + * Copyright 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ package com.google.gwt.query.rebind; import com.google.gwt.core.ext.TreeLogger; import com.google.gwt.core.ext.UnableToCompleteException; import com.google.gwt.core.ext.typeinfo.JMethod; import com.google.gwt.user.rebind.SourceWriter; +import com.google.gwt.query.client.Selector; import java.util.regex.Pattern; -import com.google.gwt.query.client.Selector; /** * */ public class SelectorGeneratorJSOptimal extends SelectorGeneratorBase { - protected static Pattern nonSpace = Pattern.compile("\\S/"); + static class RuleMatcher { - private static final String trimReStr = "^\\s+|\\s+$"; + public Pattern re; + + public String fnTemplate; + + RuleMatcher(String pat, String fnT) { + this.re = Pattern.compile(pat); + this.fnTemplate = fnT; + } + } + + protected static Pattern nonSpace = Pattern.compile("\\S/"); protected static Pattern trimRe = Pattern.compile(trimReStr); @@ -32,25 +57,28 @@ public class SelectorGeneratorJSOptimal extends SelectorGeneratorBase { protected static Pattern nthRe2 = Pattern.compile("\\D"); - protected static RuleMatcher[] matchers = new RuleMatcher[]{new RuleMatcher( - "^\\.([a-zA-Z_0-9-]+)", "n = byClassName(n, null, \"{0}\");"), + protected static RuleMatcher[] matchers = new RuleMatcher[]{ + new RuleMatcher("^\\.([a-zA-Z_0-9-]+)", + "n = byClassName(n, null, \"{0}\");"), new RuleMatcher("^\\:([a-zA-Z_0-9-]+)(?:\\(((?:[^ >]*|.*?))\\))?", "n = byPseudo(n, \"{0}\", \"{1}\");"), new RuleMatcher( - "^(?:([\\[\\{])(?:@)?([a-zA-Z_0-9-]+)\\s?(?:(=|.=)\\s?['\"]?(.*?)[\"']?)?[\\]\\}])", - "n = byAttribute(n, \"{1}\", \"{3}\", \"{2}\", \"{0}\");"), + "^(?:([\\[\\{])(?:@)?([a-zA-Z_0-9-]+)\\s?(?:(=|.=)\\s?['\"]?(.*?)[\"']?)?[\\]\\}])", + "n = byAttribute(n, \"{1}\", \"{3}\", \"{2}\", \"{0}\");"), new RuleMatcher("^#([a-zA-Z_0-9-]+)", "n = byId(n, null, \"{0}\");")}; - protected String getImplSuffix() { - return "JS"+super.getImplSuffix(); - } + private static final String trimReStr = "^\\s+|\\s+$"; protected void generateMethodBody(SourceWriter sw, JMethod method, - TreeLogger treeLogger, boolean hasContext) throws UnableToCompleteException { + TreeLogger treeLogger, boolean hasContext) + throws UnableToCompleteException { String selector = method.getAnnotation(Selector.class).value(); - if(!hasContext) sw.println("Node root = Document.get();"); - - sw.println("return "+wrap(method, "new SelectorEngine().select(\""+selector+"\", root)")+";"); + if (!hasContext) { + sw.println("Node root = Document.get();"); + } + + sw.println("return " + wrap(method, + "new SelectorEngine().select(\"" + selector + "\", root)") + ";"); // sw.println("JSArray n = JSArray.create();"); // if(!hasContext) { // sw.println("Node root = Document.get();"); @@ -159,16 +187,7 @@ public class SelectorGeneratorJSOptimal extends SelectorGeneratorBase { // sw.println("return "+wrap(method, "nodup(n)")+";"); } - - static class RuleMatcher { - - public Pattern re; - - public String fnTemplate; - - RuleMatcher(String pat, String fnT) { - this.re = Pattern.compile(pat); - this.fnTemplate = fnT; - } + protected String getImplSuffix() { + return "JS" + super.getImplSuffix(); } } \ No newline at end of file diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorNative.java b/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorNative.java index 56880851..5ca3934b 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorNative.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorNative.java @@ -1,3 +1,18 @@ +/* + * Copyright 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ package com.google.gwt.query.rebind; import com.google.gwt.core.ext.TreeLogger; diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorXPath.java b/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorXPath.java index e38b6df1..266a2cbb 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorXPath.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorXPath.java @@ -1,3 +1,18 @@ +/* + * Copyright 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ package com.google.gwt.query.rebind; import com.google.gwt.core.ext.TreeLogger; @@ -16,13 +31,16 @@ import java.util.regex.Pattern; */ public class SelectorGeneratorXPath extends SelectorGeneratorBase { - private static Pattern cssSelectorRegExp = Pattern.compile( - "^(\\w+)?(#[a-zA-Z_0-9\u00C0-\uFFFF\\-\\_]+|(\\*))?((\\.[a-zA-Z_0-9\u00C0-\uFFFF\\-_]+)*)?((\\[\\w+(\\^|\\$|\\*|\\||~)?(=[a-zA-Z_0-9\u00C0-\uFFFF\\s\\-\\_\\.]+)?\\]+)*)?(((:\\w+[a-zA-Z_0-9\\-]*)(\\((odd|even|\\-?\\d*n?((\\+|\\-)\\d+)?|[a-zA-Z_0-9\u00C0-\uFFFF\\-_]+|((\\w*\\.[a-zA-Z_0-9\u00C0-\uFFFF\\-_]+)*)?|(\\[#?\\w+(\\^|\\$|\\*|\\||~)?=?[a-zA-Z_0-9\u00C0-\uFFFF\\s\\-\\_\\.]+\\]+)|(:\\w+[a-zA-Z_0-9\\-]*))\\))?)*)?(>|\\+|~)?"); + static class Sequence { - private static Pattern selectorSplitRegExp = Pattern - .compile("(?:\\[[^\\[]*\\]|\\(.*\\)|[^\\s\\+>~\\[\\(])+|[\\+>~]"); + public int start; - private String prefix = ""; + public int max; + + public int add; + + public int modVal; + } static class SplitRule { @@ -39,9 +57,13 @@ public class SelectorGeneratorXPath extends SelectorGeneratorBase { public String tagRelation; } - protected String getImplSuffix() { - return "XPath" + super.getImplSuffix(); - } + private static Pattern cssSelectorRegExp = Pattern.compile( + "^(\\w+)?(#[a-zA-Z_0-9\u00C0-\uFFFF\\-\\_]+|(\\*))?((\\.[a-zA-Z_0-9\u00C0-\uFFFF\\-_]+)*)?((\\[\\w+(\\^|\\$|\\*|\\||~)?(=[a-zA-Z_0-9\u00C0-\uFFFF\\s\\-\\_\\.]+)?\\]+)*)?(((:\\w+[a-zA-Z_0-9\\-]*)(\\((odd|even|\\-?\\d*n?((\\+|\\-)\\d+)?|[a-zA-Z_0-9\u00C0-\uFFFF\\-_]+|((\\w*\\.[a-zA-Z_0-9\u00C0-\uFFFF\\-_]+)*)?|(\\[#?\\w+(\\^|\\$|\\*|\\||~)?=?[a-zA-Z_0-9\u00C0-\uFFFF\\s\\-\\_\\.]+\\]+)|(:\\w+[a-zA-Z_0-9\\-]*))\\))?)*)?(>|\\+|~)?"); + + private static Pattern selectorSplitRegExp = Pattern + .compile("(?:\\[[^\\[]*\\]|\\(.*\\)|[^\\s\\+>~\\[\\(])+|[\\+>~]"); + + private String prefix = ""; protected void generateMethodBody(SourceWriter sw, JMethod method, TreeLogger treeLogger, boolean hasContext) @@ -151,76 +173,8 @@ public class SelectorGeneratorXPath extends SelectorGeneratorBase { + ";"); } - static class Sequence { - - public int start; - - public int max; - - public int add; - - public int modVal; - } - - private String pseudoToXPath(String tag, String pseudoClass, - String pseudoValue) { - tag = pseudoClass.matches(".*\\-child$") ? "*" : tag; - String xpath = ""; - String pseudo[] = pseudoClass.split("-"); - if ("first".equals(pseudo[0])) { - xpath = "not(preceding-sibling::" + tag + ")"; - } else if ("last".equals(pseudo[0])) { - xpath = "not(following-sibling::" + tag + ")"; - } else if ("only".equals(pseudo[0])) { - xpath = "not(preceding-sibling::" + tag + " or following-sibling::" + tag - + ")"; - } else if ("nth".equals(pseudo[0])) { - if (!pseudoValue.matches("^n$")) { - String position = - (("last".equals(pseudo[1])) ? "(count(following-sibling::" - : "(count(preceding-sibling::") + tag + ") + 1)"; - Sequence sequence = getSequence(pseudoValue); - if (sequence != null) { - if (sequence.start == sequence.max) { - xpath = position + " = " + sequence.start; - } else { - xpath = position + " mod " + sequence.add + " = " + sequence.modVal - + ((sequence.start > 1) ? " and " + position + " >= " - + sequence.start : "") + ((sequence.max > 0) ? " and " - + position + " <= " + sequence.max : ""); - } - } - } - } else if ("empty".equals(pseudo[0])) { - xpath = "count(child::*) = 0 and string-length(text()) = 0"; - } else if ("contains".equals(pseudo[0])) { - xpath = "contains(., '" + pseudoValue + "')"; - } else if ("enabled".equals(pseudo[0])) { - xpath = "not(@disabled)"; - } else if ("disabled".equals(pseudo[0])) { - xpath = "@disabled"; - } else if ("checked".equals(pseudo[0])) { - xpath = "@checked='checked'"; // Doesn't work in Opera 9.24 - } else if ("not".equals(pseudo[0])) { - if (pseudoValue.matches("^(:a-zA-Z_0-9+[a-zA-Z_0-9\\-]*)$")) { - xpath = "not(" + pseudoToXPath(tag, pseudoValue.substring(1), "") + ")"; - } else { - pseudoValue = pseudoValue - .replaceAll("^\\[#([a-zA-Z_0-9\u00C0-\uFFFF\\-\\_]+)\\]$", - "[id=$1]"); - String notSelector = pseudoValue - .replaceFirst("^(a-zA-Z_0-9+)", "self::$1"); - notSelector = notSelector - .replaceAll("^\\.([a-zA-Z_0-9\u00C0-\uFFFF\\-_]+)", - "contains(concat(' ', @class, ' '), ' $1 ')"); - notSelector = attrToXPath(notSelector, - "\\[(a-zA-Z_0-9+)(\\^|\\$|\\*|\\||~)?=?([a-zA-Z_0-9\u00C0-\uFFFF\\s\\-_\\.]+)?\\]"); - xpath = "not(" + notSelector + ")"; - } - } else { - xpath = "@" + pseudoClass + "='" + pseudoValue + "'"; - } - return xpath; + protected String getImplSuffix() { + return "XPath" + super.getImplSuffix(); } private String attrToXPath(String notSelector, String pattern) { @@ -262,6 +216,18 @@ public class SelectorGeneratorXPath extends SelectorGeneratorBase { return notSelector; } + private int getInt(String s, int i) { + try { + if (s.startsWith("+")) { + s = s.substring(1); + } + return Integer.parseInt(s); + } catch (Exception e) { + debug("error parsing Integer " + s); + return i; + } + } + private Sequence getSequence(String expression) { int start = 0, add = 2, max = -1, modVal = -1; Pattern expressionRegExp = Pattern.compile( @@ -305,15 +271,64 @@ public class SelectorGeneratorXPath extends SelectorGeneratorBase { return s; } - private int getInt(String s, int i) { - try { - if (s.startsWith("+")) { - s = s.substring(1); + private String pseudoToXPath(String tag, String pseudoClass, + String pseudoValue) { + tag = pseudoClass.matches(".*\\-child$") ? "*" : tag; + String xpath = ""; + String pseudo[] = pseudoClass.split("-"); + if ("first".equals(pseudo[0])) { + xpath = "not(preceding-sibling::" + tag + ")"; + } else if ("last".equals(pseudo[0])) { + xpath = "not(following-sibling::" + tag + ")"; + } else if ("only".equals(pseudo[0])) { + xpath = "not(preceding-sibling::" + tag + " or following-sibling::" + tag + + ")"; + } else if ("nth".equals(pseudo[0])) { + if (!pseudoValue.matches("^n$")) { + String position = + (("last".equals(pseudo[1])) ? "(count(following-sibling::" + : "(count(preceding-sibling::") + tag + ") + 1)"; + Sequence sequence = getSequence(pseudoValue); + if (sequence != null) { + if (sequence.start == sequence.max) { + xpath = position + " = " + sequence.start; + } else { + xpath = position + " mod " + sequence.add + " = " + sequence.modVal + + ((sequence.start > 1) ? " and " + position + " >= " + + sequence.start : "") + ((sequence.max > 0) ? " and " + + position + " <= " + sequence.max : ""); + } + } } - return Integer.parseInt(s); - } catch (Exception e) { - debug("error parsing Integer " + s); - return i; + } else if ("empty".equals(pseudo[0])) { + xpath = "count(child::*) = 0 and string-length(text()) = 0"; + } else if ("contains".equals(pseudo[0])) { + xpath = "contains(., '" + pseudoValue + "')"; + } else if ("enabled".equals(pseudo[0])) { + xpath = "not(@disabled)"; + } else if ("disabled".equals(pseudo[0])) { + xpath = "@disabled"; + } else if ("checked".equals(pseudo[0])) { + xpath = "@checked='checked'"; // Doesn't work in Opera 9.24 + } else if ("not".equals(pseudo[0])) { + if (pseudoValue.matches("^(:a-zA-Z_0-9+[a-zA-Z_0-9\\-]*)$")) { + xpath = "not(" + pseudoToXPath(tag, pseudoValue.substring(1), "") + ")"; + } else { + pseudoValue = pseudoValue + .replaceAll("^\\[#([a-zA-Z_0-9\u00C0-\uFFFF\\-\\_]+)\\]$", + "[id=$1]"); + String notSelector = pseudoValue + .replaceFirst("^(a-zA-Z_0-9+)", "self::$1"); + notSelector = notSelector + .replaceAll("^\\.([a-zA-Z_0-9\u00C0-\uFFFF\\-_]+)", + "contains(concat(' ', @class, ' '), ' $1 ')"); + notSelector = attrToXPath(notSelector, + "\\[(a-zA-Z_0-9+)(\\^|\\$|\\*|\\||~)?=?([a-zA-Z_0-9\u00C0-\uFFFF\\s\\-_\\.]+)?\\]"); + xpath = "not(" + notSelector + ")"; + } + } else { + xpath = "@" + pseudoClass + "='" + pseudoValue + "'"; } + return xpath; } } \ No newline at end of file diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/GwtQueryCoreTest.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/GwtQueryCoreTest.java index 13509b77..27ea88a3 100644 --- a/gwtquery-core/src/test/java/com/google/gwt/query/client/GwtQueryCoreTest.java +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/GwtQueryCoreTest.java @@ -1,13 +1,24 @@ +/* + * Copyright 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ package com.google.gwt.query.client; -import static com.google.gwt.query.client.GQuery.$; -import com.google.gwt.query.client.GQuery; -import com.google.gwt.query.client.Properties; -import com.google.gwt.query.client.Function; - import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.InputElement; import com.google.gwt.junit.client.GWTTestCase; +import static com.google.gwt.query.client.GQuery.$; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.ui.HTML; @@ -18,541 +29,551 @@ import com.google.gwt.user.client.ui.RootPanel; */ public class GwtQueryCoreTest extends GWTTestCase { - public String getModuleName() { - return "com.google.gwt.query.Query"; - } - - static HTML testPanel = null; - static Element e = null; - - public void gwtSetUp() { - if (e == null) { - testPanel = new HTML(); - RootPanel.get().add(testPanel); - e = testPanel.getElement(); - e.setId("tst"); - } else { - e.setInnerHTML(""); - } - } - - public void testBrowserStartUp() { - // just a test for seeing in eclipse that GWTTestCase internal browser is starting - assertTrue(true); - } - - public void testInnerMethods() { - String txt = "

I would like to say:

"; - - // Check that setHTML and getHTML works as GQuery html() - testPanel.setHTML(txt); - assertEquals(txt, testPanel.getHTML()); - assertEquals(txt, $(e).html()); - assertEquals(txt, $("#tst").html()); - $(e).html(""); - assertEquals("", $(e).html()); - $(e).html(txt); - assertEquals(txt, $(e).html()); - - // toString() - assertEquals(txt, $("p", e).toString()); - - // remove() - $("p", e).remove(); - assertEquals("", $(e).html()); - - // text() - String expected = "I would like to say: I would like to say: "; - $(e).html(txt + txt); - assertEquals(expected, $("p", e).text()); - - // empty() - expected = "

"; - $("p", e).empty(); - assertEquals(expected, $(e).html()); - } - - public void testAttributeMethods() { - - $(e).html("

Content

"); - GQuery gq = $("p", e); - - // attr() - assertEquals("a1", gq.attr("class")); - gq.attr("class", "b1 b2"); - - // hasClass() - assertTrue(gq.hasClass("b1")); - assertTrue(gq.hasClass("b2")); - - // addClass() - gq.addClass("c1", "c2"); - assertTrue(gq.hasClass("b1")); - assertTrue(gq.hasClass("b2")); - assertTrue(gq.hasClass("c1")); - assertTrue(gq.hasClass("c2")); - - // removeClass() - gq.removeClass("c2", "c1"); - assertTrue(gq.hasClass("b1")); - assertTrue(gq.hasClass("b2")); - assertFalse(gq.hasClass("c1")); - assertFalse(gq.hasClass("c2")); - - // css() - String content = "

Test Paragraph.

"; - $(e).html(content); - assertEquals("red", $("p", e).css("color")); - $("p", e).css("font-weight", "bold"); - assertEquals("bold", $("p", e).css("font-weight")); - - // css() properties - $(e).html("

Test Paragraph.

"); - $("p", e).css(Properties.create("color: 'red', 'font-weight': 'bold', background: 'blue'")); - assertEquals("red", $("p", e).css("color")); - assertEquals("bold", $("p", e).css("font-weight")); - assertEquals("blue", $("p", e).css("background-color")); - - // css() camelize and uppercase - $(e).html("

Test Paragraph.

"); - $("p", e).css(Properties.create("COLOR: 'red', 'FONT-WEIGHT': 'bold'")); - assertEquals("red", $("p", e).css("color")); - assertEquals("", $("p", e).css("background")); - - } - - public void testSliceMethods() { - String content = "

This is just a test.

So is this

"; - $(e).html(content); - - String expected = "

So is this

"; - assertEquals(1, $("p", e).eq(1).size()); - assertEquals(expected, $("p", e).eq(1).toString()); + static HTML testPanel = null; - expected = "

This is just a test.

"; - assertEquals(1, $("p", e).lt(1).size()); - assertEquals(expected, $("p", e).lt(1).toString()); + static Element e = null; - expected = "

So is this

"; - assertEquals(1, $("p", e).gt(0).size()); - assertEquals(expected, $("p", e).gt(0).toString()); + public String getModuleName() { + return "com.google.gwt.query.Query"; + } - assertEquals(2, $("p", e).slice(0, 2).size()); - assertEquals(2, $("p", e).slice(0, -1).size()); - assertEquals(0, $("p", e).slice(3, 2).size()); + public void gwtSetUp() { + if (e == null) { + testPanel = new HTML(); + RootPanel.get().add(testPanel); + e = testPanel.getElement(); + e.setId("tst"); + } else { + e.setInnerHTML(""); } - - public void testRelativeMethods() { - String content = "

Hello, how are you?

"; - String expected = "Hello"; - - // find() - $(e).html(content); - assertEquals(expected, $("p", e).find("span").toString()); - - // filter() - content = "

First

Hello

How are you?

"; - $(e).html(content); - expected = "

Hello

"; - assertEquals(expected, $("p", e).filter(".selected").toString()); - - // filter() - // Commented because GQuery doesn't support this syntax yet - // expected = "

Hello

"; - // assertEquals(expected, $("p", e).filter(".selected, :first").toString()); - - // not() - expected = "

First

How are you?

"; - assertEquals(2, $("p", e).not(".selected").size()); - assertEquals(expected, $("p", e).not(".selected").toString()); - assertEquals(2, $("p", e).not($(".selected")).size()); - assertEquals(expected, $("p", e).not($(".selected")).toString()); - assertEquals(2, $("p", e).not($(".selected").get(0)).size()); - assertEquals(expected, $("p", e).not($(".selected").get(0)).toString()); - - // add() - String added = "

Last

"; - expected = content + added; - assertEquals(4, $("p", e).add(added).size()); - assertEquals(expected, $("p", e).add(added).toString()); - - // parent() - expected = content = "

Hello

Hello

"; - $(e).html(content); - assertEquals(expected, $("p", e).parent().toString()); - - // parent() - content = "

Hello

Hello Again

"; - expected = "

Hello Again

"; - $(e).html(content); - assertEquals(expected, $("p", e).parent(".selected").toString()); - - // parents() - content = "

Hello

Hello Again
"; - $(e).html(content); - assertEquals(2, $("span", e).size()); - assertTrue(3 < $("span", e).parents().size()); - assertEquals(1, $("span", e).parents().filter("body").size()); - $("span", e).parents().filter("body").toString().contains(content); - - // is() - content = "
"; - $(e).html(content); - assertEquals(true, $("input[type=\"checkbox\"]", e).parent().is("form")); - - // is() - content = "

"; - $(e).html(content); - assertEquals(false, $("input[type='checkbox']", e).parent().is("form")); - - // next() - content = "

Hello

Hello Again

And Again
"; - String next1 = "

Hello Again

"; - String next2 = "
And Again
"; - $(e).html(content); - assertEquals(2, $("p", e).next().size()); - assertEquals(next1, $("p", e).next().get(0).getString()); - assertEquals(next2, $("p", e).next().get(1).getString()); - - // next() - content = "

Hello

Hello Again

And Again
"; - expected = "

Hello Again

"; - $(e).html(content); - assertEquals(1, $("p", e).next(".selected").size()); - assertEquals(expected, $("p", e).next(".selected").get(0).getString()); - - // prev() - content = "

Hello

Hello Again

And Again

"; - expected = "
Hello Again
"; - $(e).html(content); - assertEquals(1, $("p", e).prev().size()); - assertEquals(expected, $("p", e).prev().get(0).getString()); - - // prev() - content = "
Hello

Hello Again

And Again

"; - expected = "

Hello Again

"; - $(e).html(content); - assertEquals(2, $("p", e).prev().size()); - assertEquals(1, $("p", e).prev(".selected").size()); - assertEquals(expected, $("p", e).prev(".selected").get(0).getString()); - - // siblings() - content = "

Hello

Hello Again

And Again

"; - next1 = "

Hello

"; - next2 = "

And Again

"; - $(e).html(content); - assertEquals(2, $("div", e).siblings().size()); - assertEquals(next1, $("div", e).siblings().get(0).getString()); - assertEquals(next2, $("div", e).siblings().get(1).getString()); - - // siblings() - content = "
Hello

Hello Again

And Again

"; - expected = "

Hello Again

"; - $(e).html(content); - assertEquals(1, $("p", e).siblings(".selected").size()); - assertEquals(expected, $("p", e).siblings(".selected").get(0).getString()); - - // children() - content = "

Hello

Hello Again

And Again

"; - expected = "Hello Again"; - $(e).html(content); - assertEquals(expected, $("div", e).children().toString()); - - // children() - content = "
Hello

Hello Again

And Again

"; - expected = "

Hello Again

"; - $(e).html(content); - assertEquals(expected, $("div", e).children(".selected").toString()); - - // contains() - content = "

This is just a test.

So is this

"; - expected = "

This is just a test.

"; - $(e).html(content); - assertEquals(expected, $("p", e).contains("test").toString()); - } - - public void testModifyMethods() { - String p_txt = "

I would like to say:

"; - String b_txt = "Hello"; - - // append() - String expected = "

I would like to say: Hello

"; - $(e).html(p_txt); - $("p", e).append(b_txt); - assertEquals(expected, $(e).html()); - - // appendTo() - expected = "

I would like to say: Hello

"; - $(e).html(b_txt + p_txt); - $("b", e).appendTo($("p", e)); - assertEquals(expected, $(e).html()); - - // prepend() - expected = "

HelloI would like to say:

"; - $(e).html(p_txt); - $("p", e).prepend(b_txt); - assertEquals(expected, $(e).html()); - - // prependTo() - expected = "

HelloI would like to say:

"; - $(e).html(b_txt + p_txt); - $("b", e).prependTo($("p", e)); - assertEquals(expected, $(e).html()); - - // prependTo() - expected = "Hello

HelloI would like to say:

"; - $(e).html(b_txt + p_txt); - $("b", e).clone().prependTo($("p", e)); - assertEquals(expected, $(e).html()); - - // before() - expected = "Hello

I would like to say:

"; - $(e).html(p_txt); - $("p", e).before(b_txt); - assertEquals(expected, $(e).html()); - - // before() - expected = "Hello

I would like to say:

"; - $(e).html(p_txt + b_txt); - $("p", e).before($("b", e)); - assertEquals(expected, $(e).html()); - - // before() - expected = "Hello

I would like to say:

Hello"; - $(e).html(p_txt + b_txt); - $("p", e).before($("b", e).clone()); - assertEquals(expected, $(e).html()); - - // insertBefore() - expected = "Hello

I would like to say:

"; - $(e).html(p_txt + b_txt); - $("b", e).insertBefore($("p", e)); - assertEquals(expected, $(e).html()); - - // insertBefore() - expected = "Hello

I would like to say:

Hello"; - $(e).html(p_txt + b_txt); - $("b", e).clone().insertBefore($("p", e)); - assertEquals(expected, $(e).html()); - - // after() - expected = "

I would like to say:

Hello"; - $(e).html(p_txt); - $("p", e).after(b_txt); - assertEquals(expected, testPanel.getHTML()); - - // after() - expected = "

I would like to say:

Hello"; - $(e).html(b_txt + p_txt); - $("p", e).after($("b", e)); - assertEquals(expected, $(e).html()); - - // after() - expected = "Hello

I would like to say:

Hello"; - $(e).html(b_txt + p_txt); - $("p", e).after($("b", e).clone()); - assertEquals(expected, $(e).html()); - } - - public void testWrapMethod() { - String content = "

Test Paragraph.

Content
"; - - String expected = "
Content

Test Paragraph.

"; - $(e).html(content); - - $("p", e).wrap($("div", e).get(0)); - assertEquals(expected, $(e).html()); - - expected = "

Test Paragraph.

Content
"; - $(e).html(content); - $("*", e).wrap(""); - assertEquals(expected, $(e).html()); - } - - public void testInputValueMethods() { - // imput text - $(e).html(""); - GQuery gq = $("input", e); - assertEquals("", gq.val()); - gq.val("some value"); - assertEquals("some value", gq.val()); - - // select - $(e).html(""); - gq = $("select", e); - assertEquals("v2", gq.val()); - gq.val("v1"); - assertEquals("v1", gq.val()); - - // select multiple - $(e).html(""); - gq = $("select", e); - gq.val("v1","v3","invalid"); - assertEquals(2, gq.vals().length); - assertEquals("v1", gq.vals()[0]); - assertEquals("v3", gq.vals()[1]); - gq.val("v1"); - assertEquals(1, gq.vals().length); - assertEquals("v1", gq.val()); - - // input radio - $(e).html("12"); - gq = $("input", e); - assertEquals("v2", gq.val()); - gq.val("v1"); - assertEquals("v1", gq.val()); - gq.val("v2"); - assertEquals("v2", gq.val()); - - // input checkbox - $(e).html("12"); - gq = $("input", e); - assertEquals("", gq.val()); - gq.val("v1"); - assertEquals("v1", gq.val()); - } - - public void testEventsPlugin() { - $(e).html("

Content

"); - - // click - $("p", e).click(new Function() { - public void f(Element elem) { - $(elem).css("color", "red"); - } - }); - $("p", e).trigger(Event.ONCLICK); - assertEquals("red", $("p", e).css("color")); - - // unbind - $("p", e).css("color", ""); - $("p", e).unbind(Event.ONCLICK); - $("p", e).trigger(Event.ONCLICK); - assertEquals("rgb(0, 0, 0)", $("p", e).css("color")); - - // one - $("p", e).one(Event.ONCLICK, null, new Function() { - public void f(Element elem) { - $(elem).css("color", "red"); - } - }); - $("p", e).trigger(Event.ONCLICK); - assertEquals("red", $("p", e).css("color")); - $("p", e).css("color", ""); - $("p", e).trigger(Event.ONCLICK); - assertEquals("rgb(0, 0, 0)", $("p", e).css("color")); - - // hover (mouseover, mouseout) - $("p", e).hover(new Function() { - public void f(Element elem) { - $(elem).css("background-color", "yellow"); - } - }, new Function() { - public void f(Element elem) { - $(elem).css("background-color", ""); - } - }); - $("p", e).trigger(Event.ONMOUSEOVER); - assertEquals("yellow", $("p", e).css("background-color")); - $("p", e).trigger(Event.ONMOUSEOUT); - assertEquals("rgba(0, 0, 0, 0)", $("p", e).css("background-color")); - - // focus - $("p", e).focus(new Function() { - public void f(Element elem) { - $(elem).css("border", "1px dotted black"); - } - }); - $("p", e).trigger(Event.ONFOCUS); - assertEquals("1px dotted black", $("p", e).css("border")); - - // blur - $("p", e).blur(new Function() { - public void f(Element elem) { - $(elem).css("border", ""); - } - }); - $("p", e).trigger(Event.ONBLUR); - assertEquals("", $("p", e).css("border")); - - // keypressed - $(e).html(""); - $("input", e).keypressed(new Function() { - public boolean f(Event evnt) { - Element elem = evnt.getCurrentTarget(); - InputElement input = InputElement.as(elem); - input.setValue(input.getValue() + Character.toString((char) evnt.getKeyCode())); - return false; - } - }); - $("input", e).trigger(Event.ONFOCUS); - $("input", e).trigger(Event.ONKEYPRESS, 'a'); - assertEquals("a", InputElement.as($("input", e).get(0)).getValue()); - - } - - public void testEffectsPlugin() { - $(e).html("

Content 1

Content 2

Content 3

"); - - final GQuery sect_a = $("#id1"); - final GQuery sect_b = $("#id2"); - final GQuery sect_c = $("#id3"); - - // hide() - sect_a.hide(); - assertEquals("none", sect_a.css("display")); - - // show() - sect_b.show(); - assertEquals("", sect_b.css("display")); - - // toggle() - assertEquals("", sect_c.css("display")); - sect_c.toggle(); - assertEquals("none", sect_c.css("display")); - sect_c.toggle(); - assertEquals("", sect_c.css("display")); - - // fadeIn() & fadeOut() are tested with delayed assertions - sect_a.fadeIn(2000); - sect_b.fadeOut(2000); - - // Configure the max duration for this test - // If the test exceeds the timeout without calling finishTest() it will fail - delayTestFinish(2500); - - // Delayed assertions at different intervals - Timer timer_shortTime = new Timer() { - public void run() { - double o = Double.valueOf(sect_a.css("opacity")); - assertTrue(o > 0 && o < 0.5); - o = Double.valueOf(sect_b.css("opacity")); - assertTrue(o > 0.5 && o < 1); - } - }; - Timer timer_midTime = new Timer() { - public void run() { - assertEquals("", sect_a.css("display")); - assertEquals("", sect_b.css("display")); - double o = Double.valueOf(sect_a.css("opacity")); - assertTrue(o > 0.5 && o < 1); - o = Double.valueOf(sect_b.css("opacity")); - assertTrue(o > 0 && o < 0.5); - } - }; - Timer timer_longTime = new Timer() { - public void run() { - assertEquals("", sect_a.css("display")); - assertEquals("none", sect_b.css("display")); - // Last delayed assertion has to stop the test to avoid a timeout failure - finishTest(); - } - }; - // schedule the delayed assertions - timer_shortTime.schedule(200); - timer_midTime.schedule(1200); - timer_longTime.schedule(2200); - - } - + } + + public void testAttributeMethods() { + + $(e).html("

Content

"); + GQuery gq = $("p", e); + + // attr() + assertEquals("a1", gq.attr("class")); + gq.attr("class", "b1 b2"); + + // hasClass() + assertTrue(gq.hasClass("b1")); + assertTrue(gq.hasClass("b2")); + + // addClass() + gq.addClass("c1", "c2"); + assertTrue(gq.hasClass("b1")); + assertTrue(gq.hasClass("b2")); + assertTrue(gq.hasClass("c1")); + assertTrue(gq.hasClass("c2")); + + // removeClass() + gq.removeClass("c2", "c1"); + assertTrue(gq.hasClass("b1")); + assertTrue(gq.hasClass("b2")); + assertFalse(gq.hasClass("c1")); + assertFalse(gq.hasClass("c2")); + + // css() + String content = "

Test Paragraph.

"; + $(e).html(content); + assertEquals("red", $("p", e).css("color")); + $("p", e).css("font-weight", "bold"); + assertEquals("bold", $("p", e).css("font-weight")); + + // css() properties + $(e).html("

Test Paragraph.

"); + $("p", e).css(Properties.create( + "color: 'red', 'font-weight': 'bold', background: 'blue'")); + assertEquals("red", $("p", e).css("color")); + assertEquals("bold", $("p", e).css("font-weight")); + assertEquals("blue", $("p", e).css("background-color")); + + // css() camelize and uppercase + $(e).html("

Test Paragraph.

"); + $("p", e).css(Properties.create("COLOR: 'red', 'FONT-WEIGHT': 'bold'")); + assertEquals("red", $("p", e).css("color")); + assertEquals("", $("p", e).css("background")); + } + + public void testBrowserStartUp() { + // just a test for seeing in eclipse that GWTTestCase internal browser is starting + assertTrue(true); + } + + public void testEffectsPlugin() { + $(e).html( + "

Content 1

Content 2

Content 3

"); + + final GQuery sectA = $("#id1"); + final GQuery sectB = $("#id2"); + final GQuery sectC = $("#id3"); + + // hide() + sectA.hide(); + assertEquals("none", sectA.css("display")); + + // show() + sectB.show(); + assertEquals("", sectB.css("display")); + + // toggle() + assertEquals("", sectC.css("display")); + sectC.toggle(); + assertEquals("none", sectC.css("display")); + sectC.toggle(); + assertEquals("", sectC.css("display")); + + // fadeIn() & fadeOut() are tested with delayed assertions + sectA.fadeIn(2000); + sectB.fadeOut(2000); + + // Configure the max duration for this test + // If the test exceeds the timeout without calling finishTest() it will fail + delayTestFinish(2500); + + // Delayed assertions at different intervals + Timer timerShortTime = new Timer() { + public void run() { + double o = Double.valueOf(sectA.css("opacity")); + assertTrue(o > 0 && o < 0.5); + o = Double.valueOf(sectB.css("opacity")); + assertTrue(o > 0.5 && o < 1); + } + }; + Timer timerMidTime = new Timer() { + public void run() { + assertEquals("", sectA.css("display")); + assertEquals("", sectB.css("display")); + double o = Double.valueOf(sectA.css("opacity")); + assertTrue(o > 0.5 && o < 1); + o = Double.valueOf(sectB.css("opacity")); + assertTrue(o > 0 && o < 0.5); + } + }; + Timer timerLongTime = new Timer() { + public void run() { + assertEquals("", sectA.css("display")); + assertEquals("none", sectB.css("display")); + // Last delayed assertion has to stop the test to avoid a timeout failure + finishTest(); + } + }; + // schedule the delayed assertions + timerShortTime.schedule(200); + timerMidTime.schedule(1200); + timerLongTime.schedule(2200); + } + + public void testEventsPlugin() { + $(e).html("

Content

"); + + // click + $("p", e).click(new Function() { + public void f(Element elem) { + $(elem).css("color", "red"); + } + }); + $("p", e).trigger(Event.ONCLICK); + assertEquals("red", $("p", e).css("color")); + + // unbind + $("p", e).css("color", ""); + $("p", e).unbind(Event.ONCLICK); + $("p", e).trigger(Event.ONCLICK); + assertEquals("rgb(0, 0, 0)", $("p", e).css("color")); + + // one + $("p", e).one(Event.ONCLICK, null, new Function() { + public void f(Element elem) { + $(elem).css("color", "red"); + } + }); + $("p", e).trigger(Event.ONCLICK); + assertEquals("red", $("p", e).css("color")); + $("p", e).css("color", ""); + $("p", e).trigger(Event.ONCLICK); + assertEquals("rgb(0, 0, 0)", $("p", e).css("color")); + + // hover (mouseover, mouseout) + $("p", e).hover(new Function() { + public void f(Element elem) { + $(elem).css("background-color", "yellow"); + } + }, new Function() { + public void f(Element elem) { + $(elem).css("background-color", ""); + } + }); + $("p", e).trigger(Event.ONMOUSEOVER); + assertEquals("yellow", $("p", e).css("background-color")); + $("p", e).trigger(Event.ONMOUSEOUT); + assertEquals("rgba(0, 0, 0, 0)", $("p", e).css("background-color")); + + // focus + $("p", e).focus(new Function() { + public void f(Element elem) { + $(elem).css("border", "1px dotted black"); + } + }); + $("p", e).trigger(Event.ONFOCUS); + assertEquals("1px dotted black", $("p", e).css("border")); + + // blur + $("p", e).blur(new Function() { + public void f(Element elem) { + $(elem).css("border", ""); + } + }); + $("p", e).trigger(Event.ONBLUR); + assertEquals("", $("p", e).css("border")); + + // keypressed + $(e).html(""); + $("input", e).keypressed(new Function() { + public boolean f(Event evnt) { + Element elem = evnt.getCurrentTarget(); + InputElement input = InputElement.as(elem); + input.setValue( + input.getValue() + Character.toString((char) evnt.getKeyCode())); + return false; + } + }); + $("input", e).trigger(Event.ONFOCUS); + $("input", e).trigger(Event.ONKEYPRESS, 'a'); + assertEquals("a", InputElement.as($("input", e).get(0)).getValue()); + } + + public void testInnerMethods() { + String txt = "

I would like to say:

"; + + // Check that setHTML and getHTML works as GQuery html() + testPanel.setHTML(txt); + assertEquals(txt, testPanel.getHTML()); + assertEquals(txt, $(e).html()); + assertEquals(txt, $("#tst").html()); + $(e).html(""); + assertEquals("", $(e).html()); + $(e).html(txt); + assertEquals(txt, $(e).html()); + + // toString() + assertEquals(txt, $("p", e).toString()); + + // remove() + $("p", e).remove(); + assertEquals("", $(e).html()); + + // text() + String expected = "I would like to say: I would like to say: "; + $(e).html(txt + txt); + assertEquals(expected, $("p", e).text()); + + // empty() + expected = "

"; + $("p", e).empty(); + assertEquals(expected, $(e).html()); + } + + public void testInputValueMethods() { + // imput text + $(e).html(""); + GQuery gq = $("input", e); + assertEquals("", gq.val()); + gq.val("some value"); + assertEquals("some value", gq.val()); + + // select + $(e).html( + ""); + gq = $("select", e); + assertEquals("v2", gq.val()); + gq.val("v1"); + assertEquals("v1", gq.val()); + + // select multiple + $(e).html( + ""); + gq = $("select", e); + gq.val("v1", "v3", "invalid"); + assertEquals(2, gq.vals().length); + assertEquals("v1", gq.vals()[0]); + assertEquals("v3", gq.vals()[1]); + gq.val("v1"); + assertEquals(1, gq.vals().length); + assertEquals("v1", gq.val()); + + // input radio + $(e).html( + "12"); + gq = $("input", e); + assertEquals("v2", gq.val()); + gq.val("v1"); + assertEquals("v1", gq.val()); + gq.val("v2"); + assertEquals("v2", gq.val()); + + // input checkbox + $(e).html( + "12"); + gq = $("input", e); + assertEquals("", gq.val()); + gq.val("v1"); + assertEquals("v1", gq.val()); + } + + public void testModifyMethods() { + String pTxt = "

I would like to say:

"; + String bTxt = "Hello"; + + // append() + String expected = "

I would like to say: Hello

"; + $(e).html(pTxt); + $("p", e).append(bTxt); + assertEquals(expected, $(e).html()); + + // appendTo() + expected = "

I would like to say: Hello

"; + $(e).html(bTxt + pTxt); + $("b", e).appendTo($("p", e)); + assertEquals(expected, $(e).html()); + + // prepend() + expected = "

HelloI would like to say:

"; + $(e).html(pTxt); + $("p", e).prepend(bTxt); + assertEquals(expected, $(e).html()); + + // prependTo() + expected = "

HelloI would like to say:

"; + $(e).html(bTxt + pTxt); + $("b", e).prependTo($("p", e)); + assertEquals(expected, $(e).html()); + + // prependTo() + expected = "Hello

HelloI would like to say:

"; + $(e).html(bTxt + pTxt); + $("b", e).clone().prependTo($("p", e)); + assertEquals(expected, $(e).html()); + + // before() + expected = "Hello

I would like to say:

"; + $(e).html(pTxt); + $("p", e).before(bTxt); + assertEquals(expected, $(e).html()); + + // before() + expected = "Hello

I would like to say:

"; + $(e).html(pTxt + bTxt); + $("p", e).before($("b", e)); + assertEquals(expected, $(e).html()); + + // before() + expected = "Hello

I would like to say:

Hello"; + $(e).html(pTxt + bTxt); + $("p", e).before($("b", e).clone()); + assertEquals(expected, $(e).html()); + + // insertBefore() + expected = "Hello

I would like to say:

"; + $(e).html(pTxt + bTxt); + $("b", e).insertBefore($("p", e)); + assertEquals(expected, $(e).html()); + + // insertBefore() + expected = "Hello

I would like to say:

Hello"; + $(e).html(pTxt + bTxt); + $("b", e).clone().insertBefore($("p", e)); + assertEquals(expected, $(e).html()); + + // after() + expected = "

I would like to say:

Hello"; + $(e).html(pTxt); + $("p", e).after(bTxt); + assertEquals(expected, testPanel.getHTML()); + + // after() + expected = "

I would like to say:

Hello"; + $(e).html(bTxt + pTxt); + $("p", e).after($("b", e)); + assertEquals(expected, $(e).html()); + + // after() + expected = "Hello

I would like to say:

Hello"; + $(e).html(bTxt + pTxt); + $("p", e).after($("b", e).clone()); + assertEquals(expected, $(e).html()); + } + + public void testRelativeMethods() { + String content = "

Hello, how are you?

"; + String expected = "Hello"; + + // find() + $(e).html(content); + assertEquals(expected, $("p", e).find("span").toString()); + + // filter() + content = "

First

Hello

How are you?

"; + $(e).html(content); + expected = "

Hello

"; + assertEquals(expected, $("p", e).filter(".selected").toString()); + + // filter() + // Commented because GQuery doesn't support this syntax yet + // expected = "

Hello

"; + // assertEquals(expected, $("p", e).filter(".selected, :first").toString()); + + // not() + expected = "

First

How are you?

"; + assertEquals(2, $("p", e).not(".selected").size()); + assertEquals(expected, $("p", e).not(".selected").toString()); + assertEquals(2, $("p", e).not($(".selected")).size()); + assertEquals(expected, $("p", e).not($(".selected")).toString()); + assertEquals(2, $("p", e).not($(".selected").get(0)).size()); + assertEquals(expected, $("p", e).not($(".selected").get(0)).toString()); + + // add() + String added = "

Last

"; + expected = content + added; + assertEquals(4, $("p", e).add(added).size()); + assertEquals(expected, $("p", e).add(added).toString()); + + // parent() + expected = content = "

Hello

Hello

"; + $(e).html(content); + assertEquals(expected, $("p", e).parent().toString()); + + // parent() + content + = "

Hello

Hello Again

"; + expected = "

Hello Again

"; + $(e).html(content); + assertEquals(expected, $("p", e).parent(".selected").toString()); + + // parents() + content = "

Hello

Hello Again
"; + $(e).html(content); + assertEquals(2, $("span", e).size()); + assertTrue(3 < $("span", e).parents().size()); + assertEquals(1, $("span", e).parents().filter("body").size()); + $("span", e).parents().filter("body").toString().contains(content); + + // is() + content = "
"; + $(e).html(content); + assertEquals(true, $("input[type=\"checkbox\"]", e).parent().is("form")); + + // is() + content = "

"; + $(e).html(content); + assertEquals(false, $("input[type='checkbox']", e).parent().is("form")); + + // next() + content = "

Hello

Hello Again

And Again
"; + String next1 = "

Hello Again

"; + String next2 = "
And Again
"; + $(e).html(content); + assertEquals(2, $("p", e).next().size()); + assertEquals(next1, $("p", e).next().get(0).getString()); + assertEquals(next2, $("p", e).next().get(1).getString()); + + // next() + content + = "

Hello

Hello Again

And Again
"; + expected = "

Hello Again

"; + $(e).html(content); + assertEquals(1, $("p", e).next(".selected").size()); + assertEquals(expected, $("p", e).next(".selected").get(0).getString()); + + // prev() + content = "

Hello

Hello Again

And Again

"; + expected = "
Hello Again
"; + $(e).html(content); + assertEquals(1, $("p", e).prev().size()); + assertEquals(expected, $("p", e).prev().get(0).getString()); + + // prev() + content + = "
Hello

Hello Again

And Again

"; + expected = "

Hello Again

"; + $(e).html(content); + assertEquals(2, $("p", e).prev().size()); + assertEquals(1, $("p", e).prev(".selected").size()); + assertEquals(expected, $("p", e).prev(".selected").get(0).getString()); + + // siblings() + content = "

Hello

Hello Again

And Again

"; + next1 = "

Hello

"; + next2 = "

And Again

"; + $(e).html(content); + assertEquals(2, $("div", e).siblings().size()); + assertEquals(next1, $("div", e).siblings().get(0).getString()); + assertEquals(next2, $("div", e).siblings().get(1).getString()); + + // siblings() + content + = "
Hello

Hello Again

And Again

"; + expected = "

Hello Again

"; + $(e).html(content); + assertEquals(1, $("p", e).siblings(".selected").size()); + assertEquals(expected, $("p", e).siblings(".selected").get(0).getString()); + + // children() + content = "

Hello

Hello Again

And Again

"; + expected = "Hello Again"; + $(e).html(content); + assertEquals(expected, $("div", e).children().toString()); + + // children() + content + = "
Hello

Hello Again

And Again

"; + expected = "

Hello Again

"; + $(e).html(content); + assertEquals(expected, $("div", e).children(".selected").toString()); + + // contains() + content = "

This is just a test.

So is this

"; + expected = "

This is just a test.

"; + $(e).html(content); + assertEquals(expected, $("p", e).contains("test").toString()); + } + + public void testSliceMethods() { + String content = "

This is just a test.

So is this

"; + $(e).html(content); + + String expected = "

So is this

"; + assertEquals(1, $("p", e).eq(1).size()); + assertEquals(expected, $("p", e).eq(1).toString()); + + expected = "

This is just a test.

"; + assertEquals(1, $("p", e).lt(1).size()); + assertEquals(expected, $("p", e).lt(1).toString()); + + expected = "

So is this

"; + assertEquals(1, $("p", e).gt(0).size()); + assertEquals(expected, $("p", e).gt(0).toString()); + + assertEquals(2, $("p", e).slice(0, 2).size()); + assertEquals(2, $("p", e).slice(0, -1).size()); + assertEquals(0, $("p", e).slice(3, 2).size()); + } + + public void testWrapMethod() { + String content = "

Test Paragraph.

Content
"; + + String expected = "
Content

Test Paragraph.

"; + $(e).html(content); + + $("p", e).wrap($("div", e).get(0)); + assertEquals(expected, $(e).html()); + + expected + = "

Test Paragraph.

Content
"; + $(e).html(content); + $("*", e).wrap(""); + assertEquals(expected, $(e).html()); + } } diff --git a/samples/src/main/java/gwtquery/samples/client/MySelectors.java b/samples/src/main/java/gwtquery/samples/client/MySelectors.java index ff0424d2..8a934080 100644 --- a/samples/src/main/java/gwtquery/samples/client/MySelectors.java +++ b/samples/src/main/java/gwtquery/samples/client/MySelectors.java @@ -6,127 +6,130 @@ import com.google.gwt.query.client.Selector; import com.google.gwt.query.client.Selectors; /** -*/ + * Sample selectors from SlickSpeed benchmark. + */ public interface MySelectors extends Selectors { - @Selector("#title,h1#title") - NodeList titleAndh1Title(); - +// @Selector("h1[id]:contains(Selectors)") +// NodeList h1IdContainsSelectors(); + + // + @Selector("a[href][lang][class]") + NodeList aHrefLangClass(); + + @Selector("*:checked") + NodeList allChecked(); + @Selector("body") NodeList body(); @Selector("body div") NodeList bodyDiv(); - @Selector("div p") - NodeList divP(); + @Selector("div .example") + NodeList divExample(); @Selector("div > div") NodeList divGtP(); - @Selector("div + p") - NodeList divPlusP(); +// @Selector("*:first") +// NodeList allFirst(); - @Selector("div ~ p") - NodeList divTildeP(); + // + @Selector("div:not(.example)") + NodeList divNotExample(); - @Selector("div[class^=exa][class$=mple]") - NodeList divPrefixExaSuffixMple(); + @Selector("div p") + NodeList divP(); @Selector("div p a") NodeList divPA(); -// @Selector("div, p a") -// NodeList divCommaPA(); - - @Selector(".note") - NodeList note(); - - @Selector("div .example") - NodeList divExample(); - - @Selector("ul .tocline2") - NodeList ulTocline2(); - - @Selector("#title") - NodeList title(); + @Selector("div + p") + NodeList divPlusP(); - @Selector("h1#title") - NodeList h1Title(); + @Selector("div[class^=exa][class$=mple]") + NodeList divPrefixExaSuffixMple(); @Selector("div #title") NodeList divSpaceTitle(); - @Selector("ui.toc li.tocline2") - NodeList ulTocLiTocLine2(); - - @Selector("h1#title + div > p") - NodeList h1TitlePlusDivGtP(); + @Selector("div ~ p") + NodeList divTildeP(); -// @Selector("h1[id]:contains(Selectors)") -// NodeList h1IdContainsSelectors(); -// - @Selector("a[href][lang][class]") - NodeList aHrefLangClass(); - @Selector("div[class]") NodeList divWithClass(); - - @Selector("div[class=example]") - NodeList divWithClassExample(); - - @Selector("div[class^=exa]") - NodeList divWithClassPrefixExa(); - - @Selector("div[class$=mple]") - NodeList divWithClassSuffixMple(); - + @Selector("div[class~=dialog]") NodeList divWithClassContainsDialog(); - + @Selector("div[class*=e]") NodeList divWithClassContainsE(); - + + @Selector("div[class=example]") + NodeList divWithClassExample(); + // @Selector("div[class!=madeup]") // NodeList divWithClassNotContainsMadeup(); // - + @Selector("div[class~=dialog]") NodeList divWithClassListContainsDialog(); - - @Selector("*:checked") - NodeList allChecked(); - -// @Selector("*:first") -// NodeList allFirst(); -// - @Selector("div:not(.example)") - NodeList divNotExample(); - + + @Selector("div[class^=exa]") + NodeList divWithClassPrefixExa(); + + @Selector("div[class$=mple]") + NodeList divWithClassSuffixMple(); + + @Selector("p:first-child") + NodeList firstChild(); + + @Selector("h1#title") + NodeList h1Title(); + + @Selector("h1#title + div > p") + NodeList h1TitlePlusDivGtP(); + + @Selector("p:last-child") + NodeList lastChild(); + +// @Selector("div, p a") +// NodeList divCommaPA(); + + @Selector(".note") + NodeList note(); + + @Selector("p:nth-child(n)") + NodeList nthChild(); + + @Selector("p:nth-child(2n)") + NodeList nThChild2n(); + + @Selector("p:nth-child(2n+1)") + NodeList nThChild2nPlus1(); + // @Selector("p:contains(selectors)") // NodeList pContainsSelectors(); - + @Selector("p:nth-child(even)") NodeList nThChildEven(); - - @Selector("p:nth-child(2n)") - NodeList nThChild2n(); - + @Selector("p:nth-child(odd)") NodeList nThChildOdd(); - - @Selector("p:nth-child(2n+1)") - NodeList nThChild2nPlus1(); - - @Selector("p:nth-child(n)") - NodeList nthChild(); - + @Selector("p:only-child") NodeList onlyChild(); - - @Selector("p:last-child") - NodeList lastChild(); - - @Selector("p:first-child") - NodeList firstChild(); + + @Selector("#title") + NodeList title(); + + @Selector("#title,h1#title") + NodeList titleAndh1Title(); + + @Selector("ul .tocline2") + NodeList ulTocline2(); + + @Selector("ui.toc li.tocline2") + NodeList ulTocLiTocLine2(); } -- 2.39.5