*/\r
public static final Element window = window();\r
\r
- private static JsCache dataCache = null;\r
+ protected static JsCache dataCache = null;\r
\r
private static SelectorEngine engine;\r
\r
FUNC_BEFORE = 3;\r
\r
private static final String OLD_DATA_PREFIX = "old-";\r
-\r
+ \r
private static JsMap<Class<? extends GQuery>, Plugin<? extends GQuery>> plugins;\r
\r
private static DocumentStyleImpl styleImpl = GWT.create(DocumentStyleImpl.class);\r
: ctx.getOwnerDocument();\r
return $(cleanHtmlString(selectorOrHtml, doc));\r
}\r
- return new GQuery(select(selectorOrHtml, ctx));\r
+ return new GQuery(select(selectorOrHtml, ctx)).setSelector(selectorOrHtml);\r
}\r
\r
/**\r
try {\r
if (plugins != null) {\r
T gquery = (T) plugins.get(plugin).init(\r
- new GQuery(select(selector, context)));\r
+ new GQuery(select(selector, context))).setSelector(selector);\r
return gquery;\r
}\r
throw new RuntimeException("No plugin for class " + plugin);\r
n = n.getLastChild();\r
}\r
// TODO: add fixes for IE TBODY issue\r
- return $((NodeList<Element>) n.getChildNodes().cast());\r
+ return $((NodeList<Element>) n.getChildNodes().cast()).as(Events).addLiveEvents();\r
}\r
\r
protected static <S> Object data(Element item, String name, S value) {\r
return $wnd;\r
}-*/;\r
\r
- private String currentSelector;\r
+ protected String currentSelector;\r
\r
private NodeList<Element> elements = JavaScriptObject.createArray().cast();\r
\r
} else if (plugins != null) {\r
Plugin<?> p = plugins.get(plugin);\r
if (p != null) {\r
- return (T) p.init(this);\r
+ return (T) p.init(this).setSelector(currentSelector);\r
}\r
}\r
throw new RuntimeException("No plugin registered for class "\r
public GQuery attr(Properties properties) {\r
for (Element e : elements()) {\r
for (String name : properties.keys()) {\r
- e.setAttribute(name, properties.get(name));\r
+ e.setAttribute(name, properties.getStr(name));\r
}\r
}\r
return this;\r
for (Element e : elements()) {\r
result.addNode(e.cloneNode(true));\r
}\r
- return new GQuery(result);\r
+ return new GQuery(result).as(Events).addLiveEvents();\r
}\r
\r
/**\r
*/\r
public GQuery css(Properties properties) {\r
for (String property : properties.keys()) {\r
- css(property, properties.get(property));\r
+ css(property, properties.getStr(property));\r
}\r
return this;\r
}\r
return remove(filter, false);\r
}\r
\r
+ /**\r
+ * Remove all event handlers previously attached using live()\r
+ * The selector used with it must match exactly the selector initially\r
+ * used with live().\r
+ */\r
+ public GQuery die(int eventbits) {\r
+ return as(Events).die(eventbits);\r
+ }\r
+ \r
/**\r
* Run one or more Functions over each element of the GQuery. You have to\r
* override one of these funcions: public void f(Element e) public String\r
}\r
e.setInnerHTML(html);\r
}\r
- return this;\r
+ return as(Events).addLiveEvents();\r
}\r
\r
/**\r
public int length() {\r
return size();\r
}\r
+ \r
+ /**\r
+ * Add events to all elements which match the current selector,\r
+ * now and in the future.\r
+ */\r
+ public GQuery live(int eventBits, Function... funcs) {\r
+ return as(Events).live(eventBits, funcs);\r
+ }\r
\r
/**\r
* Bind a function to the load event of each matched element.\r
*/\r
@SuppressWarnings("unchecked")\r
public <W> List<W> map(Function f) {\r
+ @SuppressWarnings("rawtypes")\r
ArrayList ret = new ArrayList();\r
for (int i = 0; i < elements().length; i++) {\r
Object o = f.f(elements()[i], i);\r
this.previousObject = previousObject;\r
}\r
\r
- public void setSelector(String selector) {\r
+ public GQuery setSelector(String selector) {\r
this.currentSelector = selector;\r
+ return this;\r
}\r
\r
/**\r
dataCache.delete(id);\r
}\r
}\r
+\r
}\r
*/
LazyGQuery<T> detach(String filter);
+ /**
+ * Remove all event handlers previously attached using live()
+ * The selector used with it must match exactly the selector initially
+ * used with live().
+ */
+ LazyGQuery<T> die(int eventbits);
+
/**
* Run one or more Functions over each element of the GQuery. You have to
* override one of these funcions: public void f(Element e) public String
*/
int length();
+ /**
+ * Add events to all elements which match the current selector,
+ * now and in the future.
+ */
+ LazyGQuery<T> live(int eventBits, Function... funcs);
+
/**
* Bind a function to the load event of each matched element.
*/
void setPreviousObject(GQuery previousObject);
- void setSelector(String selector);
+ LazyGQuery<T> setSelector(String selector);
/**
* Make all matched elements visible
return (Properties) createImpl("({})");\r
}\r
}\r
+ \r
+ public static Properties create() {\r
+ return (Properties) createImpl("({})");\r
+ }\r
\r
public static final native JavaScriptObject createImpl(String properties) /*-{\r
return eval(properties);\r
return this[name] != undefined; \r
}-*/;\r
\r
- public final native String get(String name) /*-{\r
+ public final native <T> T get(String name) /*-{\r
return this[name];\r
}-*/;\r
\r
+ public final native String getStr(String name) /*-{\r
+ return String(this[name]);\r
+ }-*/;\r
+\r
public final native float getFloat(String name) /*-{\r
return this[name];\r
}-*/;\r
return keys;\r
}-*/;\r
\r
- public final native void set(String key, String val) /*-{\r
+ public final native void set(String key, Object val) /*-{\r
this[key]=val;\r
}-*/;\r
\r
public final String tostring() {\r
String ret = "";\r
for (String k : keys()){\r
- ret += k + ": '" + get(k) + "', ";\r
+ ret += k + ": '" + getStr(k) + "', ";\r
}\r
return "({" + ret.replaceAll("[, ]+$","") + "})";\r
}\r
package com.google.gwt.query.client.js;
import com.google.gwt.core.client.JavaScriptObject;
+import com.google.gwt.core.client.JsArrayString;
/**
* A Lightweight JSO class to store data.
protected JsCache() {
}
+
+ public static JsCache create() {
+ return createObject().cast();
+ }
public final native void concat(Object ary) /*-{
if (ary) this.concat(ary);
delete this[name];
}-*/;
+ public final native boolean exists(String name) /*-{
+ return !!this[name];
+ }-*/;
+
public final native boolean exists(int id) /*-{
return !!this[id];
}-*/;
- public final native Object get(int id) /*-{
+ public final native <T> T get(int id) /*-{
return this[id] || null;
}-*/;
- public final native Object get(String id) /*-{
+ public final native <T> T get(String id) /*-{
return this[id] || null;
}-*/;
public final native int length() /*-{
return this.length;
}-*/;
+
+ public final int[] indexes() {
+ JsArrayString a = keysImpl();
+ int[] ret = new int[a.length()];
+ for (int i = 0; i < a.length(); i++) {
+ try {
+ ret[i] = Integer.valueOf(a.get(i));
+ } catch (Exception e) {
+ ret[i] = i;
+ }
+ }
+ return ret;
+ }
+
+ public final String[] keys() {
+ JsArrayString a = keysImpl();
+ String[] ret = new String[a.length()];
+ for (int i = 0; i < a.length(); i++) {
+ ret[i] = a.get(i);
+ }
+ return ret;
+ }
+
+ public final Object[] elements() {
+ String[] keys = keys();
+ Object[] ret = new Object[keys.length];
+ int i=0;
+ for (String s: keys) {
+ ret[i++] = get(s);
+ }
+ return ret;
+ }
+
+ public final native Object[] elemImpl() /*-{
+ var key, ret=[];
+ for(key in this) ret.push(this[key]);
+ return ret;
+ }-*/;
+
+
+ public final native JsArrayString keysImpl() /*-{
+ var key, keys=[];
+ for(key in this) keys.push("" + key);
+ return keys;
+ }-*/;
}
package com.google.gwt.query.client.js;
import com.google.gwt.core.client.JavaScriptObject;
+import com.google.gwt.core.client.JsArrayString;
/**
public void put(S key, T val) {
c().put(key.hashCode(), val);
}
+
+ public final String[] keys() {
+ return c().keys();
+ }
}
*/
package com.google.gwt.query.client.js;
+import java.util.ArrayList;
+import java.util.Arrays;
+
import com.google.gwt.core.client.JavaScriptObject;
/**
return cast();
}
- public void add(T val) {
- c().put(length(), val);
+ public void add(T...vals) {
+ for (T t: vals) {
+ c().put(length(), t);
+ }
}
public void add(int i, T val) {
public void pushAll(JavaScriptObject prevElem) {
c().pushAll(prevElem);
}
+
}
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.query.client.Function;
import com.google.gwt.query.client.GQuery;
+import com.google.gwt.query.client.js.JsCache;
+import com.google.gwt.query.client.js.JsObjectArray;
import com.google.gwt.query.client.plugins.events.EventsListener;
import com.google.gwt.user.client.Event;
public class Events extends GQuery {
public static final Class<Events> Events = Events.class;
+
+ protected static final String LIVE_ID_DATA = "_lid_";
static {
GQuery.registerPlugin(Events.class, new Plugin<Events>() {
return this;
}
+ /**
+ * Remove all event handlers previously attached using live()
+ * The selector used with it must match exactly the selector initially
+ * used with live().
+ */
+ public GQuery die(int eventbits) {
+ JsCache d = dataCache.get(LIVE_ID_DATA);
+ if (d != null) {
+ JsCache cache = d.get(currentSelector);
+ if (cache != null) {
+ cache.delete(eventbits);
+ }
+ }
+ unbind(eventbits);
+ return this;
+ }
+
+ /**
+ * Add events to all elements which match the current selector,
+ * now and in the future.
+ */
+ public GQuery live(int eventBits, Function... funcs) {
+ if (currentSelector == null || currentSelector.isEmpty()) {
+ return this;
+ }
+ JsCache d = dataCache.get(LIVE_ID_DATA);
+ if (d == null) {
+ d = JsCache.create();
+ dataCache.put(LIVE_ID_DATA, d);
+ }
+
+ JsCache cache = d.get(currentSelector);
+ if (cache == null) {
+ cache = JsCache.create();
+ d.put(currentSelector, cache);
+ }
+
+ JsObjectArray<Function> functions = cache.get(eventBits);
+ if (functions == null) {
+ functions = JsObjectArray.create().cast();
+ cache.put(eventBits, functions);
+ }
+ functions.add(funcs);
+ bind(eventBits, null, funcs);
+ return this;
+ }
+
/**
* Binds a handler to a particular Event (like Event.ONCLICK) for each matched
* element. The handler is executed only once for each element.
triggerHtmlEvent("submit");
return this;
}
-
/**
* Trigger a html event in all matched elements.
e.dispatchEvent(evt);
}
}
+
+ public GQuery addLiveEvents() {
+ if (dataCache.exists(LIVE_ID_DATA)) {
+ JsCache d = dataCache.get(LIVE_ID_DATA);
+ for (String selector : d.keys()) {
+ GQuery g = find(selector).add(filter(selector));
+ if (g.size() > 0) {
+ JsCache cache = d.get(selector);
+ for (int eventBits : cache.indexes()) {
+ JsObjectArray<Function> functions = cache.get(eventBits);
+ for (int j = 0; j<functions.length(); j++) {
+ g.bind(eventBits, null, functions.get(j));
+ }
+ }
+ }
+ }
+ }
+ return this;
+ }
}
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.query.client.Function;
import com.google.gwt.query.client.GQuery;
+import com.google.gwt.query.client.js.JsCache;
+import com.google.gwt.query.client.js.JsObjectArray;
import com.google.gwt.query.client.plugins.events.EventsListener;
import com.google.gwt.user.client.Event;
import com.google.gwt.query.client.LazyBase;
*/
LazyEvents<T> bind(String event, Object data, Function...funcs);
+ /**
+ * Remove all event handlers previously attached using live()
+ * The selector used with it must match exactly the selector initially
+ * used with live().
+ */
+ GQuery die(int eventbits);
+
+ /**
+ * Add events to all elements which match the current selector,
+ * now and in the future.
+ */
+ GQuery live(int eventBits, Function... funcs);
+
/**
* Binds a handler to a particular Event (like Event.ONCLICK) for each matched
* element. The handler is executed only once for each element.
Effect fx;\r
//g.show();\r
for (String key : prps.keys()) {\r
- String val = prps.get(key);\r
+ String val = prps.getStr(key);\r
if ((fx = computeFxProp(e, key, val, hidden)) != null) {\r
effects.add(fx);\r
resize = resize || "height".equals(key) || "width".equals(key);\r
public void testProperties() {
Properties p = $$("border:'1px solid black'");
assertEquals(1, p.keys().length);
- assertNotNull(p.get("border"));
+ assertNotNull(p.getStr("border"));
p = $$("({border:'1px solid black'})");
assertEquals(1, p.keys().length);
- assertNotNull(p.get("border"));
+ assertNotNull(p.getStr("border"));
}
public void testRelativeMethods() {
assertEquals(expectedHtml, $(e).html());
}
-
+
}
assertEquals("abc", $("input", e).val());
}
+ public void testLive() {
+ $(e).html("<div class='clickMe'>Content 1</div>");
+ $(".clickMe").live(Event.ONCLICK, new Function(){
+ public void f(Element e) {
+ $(e).css("color", "red");
+ }
+ });
+ $(e).append("<p class='clickMe'>Content 2</p>");
+ assertEquals("", $("#d1").css("color"));
+
+ $(".clickMe", e).click();
+ assertEquals("red", $("div", e).css("color"));
+ assertEquals("red", $("p", e).css("color"));
+
+ $(".clickMe", e).css("color", "yellow");
+ $(".clickMe").die(Event.ONCLICK);
+ $(e).append("<span class='clickMe'>Content 3</span>");
+
+ $(".clickMe", e).click();
+ assertEquals("yellow", $("div", e).css("color"));
+ assertEquals("yellow", $("p", e).css("color"));
+ assertEquals("", $("span", e).css("color"));
+ }
+
public void testLazyMethods() {
$(e).css(CSS.COLOR.with(RGBColor.WHITE));
assertEquals("white", $(e).css("color"));
$("#test").focus(new Function(){});
assertEquals($("#test").attr("tabIndex"), "2");
-
}
+
}