From: Julien Dramaix
Date: Fri, 8 Apr 2011 18:35:54 +0000 (+0000)
Subject: implement live() and die methods
X-Git-Tag: release-1.3.2~428
X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=f9d6e292acc225f85dd6fc281805cf47395a1694;p=gwtquery.git
implement live() and die methods
---
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 e6958722..c8c95539 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
@@ -352,7 +352,7 @@ public class GQuery implements Lazy {
n = n.getLastChild();
}
// TODO: add fixes for IE TBODY issue
- return $((NodeList) n.getChildNodes().cast()).as(Events).addLiveEvents();
+ return $((NodeList) n.getChildNodes().cast());
}
protected static Object data(Element item, String name, S value) {
@@ -972,7 +972,7 @@ public class GQuery implements Lazy {
GQuery ret = new GQuery(result);
ret.currentContext = currentContext;
ret.currentSelector = currentSelector;
- return ret.as(Events).addLiveEvents();
+ return ret;
}
/**
@@ -987,67 +987,80 @@ public class GQuery implements Lazy {
}
/**
- * Returns a {@link Map} object as key a selector and as value the first ancestor elements matching this selectors, beginning at the
- * first matched element and progressing up through the DOM. This method allows retrieving the list of closest ancestors matching
- * many selectors and by reducing the number of DOM traversing.
+ * Returns a {@link Map} object as key a selector and as value the list of
+ * ancestor elements matching this selectors, beginning at the first matched
+ * element and progressing up through the DOM. This method allows retrieving
+ * the list of ancestors matching many selectors by traversing the DOM only
+ * one time.
*
* @param selector
* @return
*/
- public Map closest(String[] selectors){
+ public Map> closest(String[] selectors) {
return closest(selectors, null);
}
-
+
/**
- * Returns a GQuery object containing the first ancestor elements matching each selectors, beginning at the
- * first matched element and progressing up through the DOM tree until reach the context
node..
- * This method allows retrieving the list of closest ancestors matching many selectors and by reducing the number of DOM traversing.
+ * Returns a {@link Map} object as key a selector and as value the list of
+ * ancestor elements matching this selectors, beginning at the first matched
+ * element and progressing up through the DOM until reach the
+ * context
node.. This method allows retrieving the list of
+ * ancestors matching many selectors by traversing the DOM only one time.
*
* @param selector
* @return
*/
- public Map closest(String[] selectors, Node context){
- Map results = new HashMap();
-
- if (context == null){
+ public Map> closest(String[] selectors, Node context) {
+ Map> results = new HashMap>();
+
+ if (context == null) {
context = currentContext;
}
-
+
Element first = get(0);
-
- if (first != null && selectors != null && selectors.length > 0){
-
+
+ if (first != null && selectors != null && selectors.length > 0) {
+
Map matches = new HashMap();
-
- for (String selector : selectors){
- if (!matches.containsKey(selector)){
- matches.put(selector, selector.matches(POS_REGEX) ? $(selector, context) : null);
+
+ for (String selector : selectors) {
+ if (!matches.containsKey(selector)) {
+ matches.put(selector, selector.matches(POS_REGEX) ? $(selector,
+ context) : null);
}
}
-
+
Element current = first;
-
- while (current != null && current.getOwnerDocument() != null && current != context){
- //for each selector, check if the current element match it.
- for (String selector : matches.keySet()){
- if (results.containsKey(selector)){
- //first ancestors already found for this selector
- continue;
- }
+
+ while (current != null && current.getOwnerDocument() != null
+ && current != context) {
+ // for each selector, check if the current element match it.
+ for (String selector : matches.keySet()) {
+
GQuery pos = matches.get(selector);
- boolean match = pos != null ? pos.index(current) > -1 : $(current).is(selector);
- if (match){
- results.put(selector, current);
+
+ boolean match = pos != null ? pos.index(current) > -1
+ : $(current).is(selector);
+
+ if (match) {
+
+ List elementsMatchingSelector = results.get(selector);
+
+ if (elementsMatchingSelector == null) {
+ elementsMatchingSelector = new ArrayList();
+ results.put(selector, elementsMatchingSelector);
+ }
+
+ elementsMatchingSelector.add(current);
}
}
-
- current = current.getParentElement();
+
+ current = current.getParentElement();
}
-
-
+
}
-
- return results;
+
+ return results;
}
/**
@@ -1406,16 +1419,27 @@ public class GQuery implements Lazy {
public GQuery detach(String filter) {
return remove(filter, false);
}
-
+
/**
- * Remove all event handlers previously attached using live()
- * The selector used with it must match exactly the selector initially
- * used with live().
+ * Remove all event handlers previously attached using
+ * {@link #live(String, Function)}. In order for this method to function
+ * correctly, the selector used with it must match exactly the selector
+ * initially used with {@link #live(String, Function)}
*/
- public GQuery die(int eventbits) {
- return as(Events).die(eventbits);
+ public GQuery die() {
+ return as(Events).die(null);
}
-
+
+ /**
+ * Remove an event handlers previously attached using
+ * {@link #live(String, Function)} In order for this method to function
+ * correctly, the selector used with it must match exactly the selector
+ * initially used with {@link #live(String, Function)}
+ */
+ public GQuery die(String eventName) {
+ return as(Events).die(eventName);
+ }
+
/**
* 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
@@ -1763,7 +1787,7 @@ public class GQuery implements Lazy {
}
e.setInnerHTML(html);
}
- return as(Events).addLiveEvents();
+ return this;
}
/**
@@ -1932,13 +1956,117 @@ public class GQuery implements Lazy {
public int length() {
return size();
}
+
+ /**
+ *
+ * Attach a handler for this event to all elements which match the current
+ * selector, now and in the future.
+ *
+ *
+ * Ex :
+ *
+ *
+ * $(".clickable").live("click", new Function(){
+ * public void f(Element e){
+ * $(e).css(CSS.COLOR.with(RGBColor.RED));
+ * }
+ * });
+ *
+ *
+ * With this code, all elements with class "clickable" present in the DOM or
+ * added to the DOM in the future will be clickable. The text color will be
+ * changed to red when they will be clicked. So if after in the code, you add
+ * another element :
+ *
+ *
+ * $("body").append("Click me and I will be red
");
+ *
+ *
+ * The click on this new element will also trigger the handler.
+ *
+ *
+ * In the same way, if you add "clickable" class on some existing element,
+ * these elements will be clickable also.
+ *
+ *
+ *
important remarks
+ *
+ *
+ */
+ public GQuery live(String eventName, Function func) {
+ return as(Events).live(eventName, null, func);
+ }
+
/**
- * Add events to all elements which match the current selector,
- * now and in the future.
+ *
+ * Attach a handler for this event to all elements which match the current
+ * selector, now and in the future.
+ * The data
parameter allows us to pass data to the handler.
+ *
+ *
+ * Ex :
+ *
+ *
+ * $(".clickable").live("click", new Function(){
+ * public void f(Element e){
+ * $(e).css(CSS.COLOR.with(RGBColor.RED));
+ * }
+ * });
+ *
+ *
+ * With this code, all elements with class "clickable" present in the DOM or
+ * added to the DOM in the future will be clickable. The text color will be
+ * changed to red when they will be clicked. So if after in the code, you add
+ * another element :
+ *
+ *
+ * $("body").append("Click me and I will be red
");
+ *
+ *
+ * The click on this new element will also trigger the handler.
+ *
+ *
+ * In the same way, if you add "clickable" class on some existing element,
+ * these elements will be clickable also.
+ *
+ *
+ *
important remarks
+ *
+ *
*/
- public GQuery live(int eventBits, Function... funcs) {
- return as(Events).live(eventBits, funcs);
+ public GQuery live(String eventName, Object data, Function func) {
+ return as(Events).live(eventName, data, func);
}
/**
diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/LazyGQuery.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/LazyGQuery.java
index 402d782f..2a5b32ce 100644
--- a/gwtquery-core/src/main/java/com/google/gwt/query/client/LazyGQuery.java
+++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/LazyGQuery.java
@@ -57,6 +57,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import com.google.gwt.query.client.LazyBase;
public interface LazyGQuery extends LazyBase{
@@ -399,6 +400,48 @@ public interface LazyGQuery extends LazyBase{
*/
LazyGQuery clone();
+ /**
+ * Get the first ancestor element that matches the selector (for each matched element), beginning at the
+ * current element and progressing up through the DOM tree.
+ *
+ * @param selector
+ * @return
+ */
+ LazyGQuery closest(String selector);
+
+ /**
+ * Returns a {@link Map} object as key a selector and as value the list of
+ * ancestor elements matching this selectors, beginning at the first matched
+ * element and progressing up through the DOM. This method allows retrieving
+ * the list of ancestors matching many selectors by traversing the DOM only
+ * one time.
+ *
+ * @param selector
+ * @return
+ */
+ Map> closest(String[] selectors);
+
+ /**
+ * Returns a {@link Map} object as key a selector and as value the list of
+ * ancestor elements matching this selectors, beginning at the first matched
+ * element and progressing up through the DOM until reach the
+ * context
node.. This method allows retrieving the list of
+ * ancestors matching many selectors by traversing the DOM only one time.
+ *
+ * @param selector
+ * @return
+ */
+ Map> closest(String[] selectors, Node context);
+
+ /**
+ * Get the first ancestor element that matches the selector (for each matched element), beginning at the
+ * current element and progressing up through the DOM tree until reach the context
node.
+ *
+ * If no context is passed in then the context of the gQuery object will be used instead.
+ *
+ */
+ LazyGQuery closest(String selector, Node context);
+
/**
* Filter the set of elements to those that contain the specified text.
*/
@@ -622,11 +665,20 @@ public interface LazyGQuery extends LazyBase{
LazyGQuery 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().
+ * Remove all event handlers previously attached using
+ * {@link #live(String, Function)}. In order for this method to function
+ * correctly, the selector used with it must match exactly the selector
+ * initially used with {@link #live(String, Function)}
+ */
+ LazyGQuery die();
+
+ /**
+ * Remove an event handlers previously attached using
+ * {@link #live(String, Function)} In order for this method to function
+ * correctly, the selector used with it must match exactly the selector
+ * initially used with {@link #live(String, Function)}
*/
- LazyGQuery die(int eventbits);
+ LazyGQuery die(String eventName);
/**
* Run one or more Functions over each element of the GQuery. You have to
@@ -760,6 +812,8 @@ public interface LazyGQuery extends LazyBase{
*/
Element get(int i);
+ Node getContext();
+
/**
* Return the previous set of matched elements prior to the last destructive
* operation (e.g. query)
@@ -946,10 +1000,111 @@ public interface LazyGQuery extends LazyBase{
int length();
/**
- * Add events to all elements which match the current selector,
- * now and in the future.
+ *
+ * Attach a handler for this event to all elements which match the current
+ * selector, now and in the future.
+ *
+ *
+ * Ex :
+ *
+ *
+ * $(".clickable").live("click", new Function(){
+ * public void f(Element e){
+ * $(e).css(CSS.COLOR.with(RGBColor.RED));
+ * }
+ * });
+ *
+ *
+ * With this code, all elements with class "clickable" present in the DOM or
+ * added to the DOM in the future will be clickable. The text color will be
+ * changed to red when they will be clicked. So if after in the code, you add
+ * another element :
+ *
+ *
+ * $("body").append("Click me and I will be red
");
+ *
+ *
+ * The click on this new element will also trigger the handler.
+ *
+ *
+ * In the same way, if you add "clickable" class on some existing element,
+ * these elements will be clickable also.
+ *
+ *
+ *
important remarks
+ *
+ *
+ */
+ LazyGQuery live(String eventName, Function func);
+
+ /**
+ *
+ * Attach a handler for this event to all elements which match the current
+ * selector, now and in the future.
+ * The data
parameter allows us to pass data to the handler.
+ *
+ *
+ * Ex :
+ *
+ *
+ * $(".clickable").live("click", new Function(){
+ * public void f(Element e){
+ * $(e).css(CSS.COLOR.with(RGBColor.RED));
+ * }
+ * });
+ *
+ *
+ * With this code, all elements with class "clickable" present in the DOM or
+ * added to the DOM in the future will be clickable. The text color will be
+ * changed to red when they will be clicked. So if after in the code, you add
+ * another element :
+ *
+ *
+ * $("body").append("Click me and I will be red
");
+ *
+ *
+ * The click on this new element will also trigger the handler.
+ *
+ *
+ * In the same way, if you add "clickable" class on some existing element,
+ * these elements will be clickable also.
+ *
+ *
+ *
important remarks
+ *
+ *
*/
- LazyGQuery live(int eventBits, Function... funcs);
+ LazyGQuery live(String eventName, Object data, Function func);
/**
* Bind a function to the load event of each matched element.
diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/Events.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/Events.java
index d8e5d52b..fc58ce0f 100644
--- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/Events.java
+++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/Events.java
@@ -19,8 +19,6 @@ import com.google.gwt.dom.client.Element;
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;
@@ -30,8 +28,6 @@ import com.google.gwt.user.client.Event;
public class Events extends GQuery {
public static final Class Events = Events.class;
-
- protected static final String LIVE_ID_DATA = "_lid_";
static {
GQuery.registerPlugin(Events.class, new Plugin() {
@@ -44,6 +40,7 @@ public class Events extends GQuery {
public Events(GQuery gq) {
super(gq);
}
+
/**
* Binds a set of handlers to a particular Event for each matched element.
*
@@ -55,7 +52,7 @@ public class Events extends GQuery {
* parameter
*
*/
- public Events bind(int eventbits, Object data, Function...funcs) {
+ public Events bind(int eventbits, Object data, Function... funcs) {
for (Element e : elements()) {
EventsListener.getInstance(e).bind(eventbits, data, funcs);
}
@@ -65,8 +62,8 @@ public class Events extends GQuery {
/**
* Binds a set of handlers to a particular Event for each matched element.
*
- * The namespace is a way to group events of the same type, making easier unbind
- * specific handlers.
+ * The namespace is a way to group events of the same type, making easier
+ * unbind specific handlers.
*
* The event handlers are passed as Functions that you can use to prevent
* default behavior. To stop both default action and event bubbling, the
@@ -74,8 +71,9 @@ public class Events extends GQuery {
*
* You can pass an additional Object data to your Function
*
- */
- public Events bind(int eventbits, String namespace, Object data, Function...funcs) {
+ */
+ public Events bind(int eventbits, String namespace, Object data,
+ Function... funcs) {
for (Element e : elements()) {
EventsListener.getInstance(e).bind(eventbits, namespace, data, funcs);
}
@@ -85,8 +83,8 @@ public class Events extends GQuery {
/**
* Binds a set of handlers to a particular Event for each matched element.
*
- * The name could contain a namespace which is a way to group events of the same type,
- * making easier unbind specific handlers.
+ * The name could contain a namespace which is a way to group events of the
+ * same type, making easier unbind specific handlers.
*
* The event handlers are passed as Functions that you can use to prevent
* default behavior. To stop both default action and event bubbling, the
@@ -94,89 +92,68 @@ public class Events extends GQuery {
*
* You can pass an additional Object data to your Function
*
- */
- public Events bind(String event, Object data, Function...funcs) {
+ */
+ public Events bind(String event, Object data, Function... funcs) {
for (Element e : elements()) {
EventsListener.getInstance(e).bind(event, data, funcs);
}
return this;
}
-
+
/**
- * Remove all event handlers previously attached using live()
- * The selector used with it must match exactly the selector initially
- * used with live().
+ * Remove an event handlers previously attached using live() The selector used
+ * with it must match exactly the selector initially used with live(). if
+ * eventName
is null, all event handlers corresponding of the
+ * GQuery selector will be removed
*/
- 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);
+ public GQuery die(String eventName) {
+ EventsListener.getInstance(
+ Element.is(currentContext) ? (Element) currentContext : body).die(
+ eventName, currentSelector);
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 functions = cache.get(eventBits);
- if (functions == null) {
- functions = JsObjectArray.create().cast();
- cache.put(eventBits, functions);
- }
- functions.add(funcs);
- bind(eventBits, null, funcs);
+ public GQuery live(String eventName, final Object data, Function func) {
+
+ // bind live delegating event to the current context
+ EventsListener.getInstance(
+ Element.is(currentContext) ? (Element) currentContext : body).live(
+ eventName, currentSelector, data, func);
+
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.
- *
+ *
* The event handler is passed as a Function that you can use to prevent
* default behavior. To stop both default action and event bubbling, the
* function event handler has to return false.
- *
+ *
* You can pass an additional Object data to your Function as the second
* parameter
- */
+ */
public Events one(int eventbits, final Object data, final Function f) {
for (Element e : elements()) {
EventsListener.getInstance(e).bind(eventbits, data, f, 1);
}
return this;
}
-
+
/**
- * Execute all handlers and behaviors attached to the matched elements for the given event types.
+ * Execute all handlers and behaviors attached to the matched elements for the
+ * given event types.
*
- * Different event types can be passed joining these using the or bit wise operator.
+ * Different event types can be passed joining these using the or bit wise
+ * operator.
*
- * For keyboard events you can pass a second parameter which represents
- * the key-code of the pushed key.
+ * For keyboard events you can pass a second parameter which represents the
+ * key-code of the pushed key.
*
- * Example: fire(Event.ONCLICK | Event.ONFOCUS)
- * Example: fire(Event.ONKEYDOWN. 'a');
+ * Example: fire(Event.ONCLICK | Event.ONFOCUS) Example: fire(Event.ONKEYDOWN.
+ * 'a');
*/
@SuppressWarnings("deprecation")
public Events trigger(int eventbits, int... keys) {
@@ -185,35 +162,46 @@ public class Events extends GQuery {
if ((eventbits | Event.ONCHANGE) == Event.ONCHANGE)
dispatchEvent(document.createChangeEvent());
if ((eventbits | Event.ONCLICK) == Event.ONCLICK)
- dispatchEvent(document.createClickEvent(0, 0, 0, 0, 0, false, false, false, false));
+ dispatchEvent(document.createClickEvent(0, 0, 0, 0, 0, false, false,
+ false, false));
if ((eventbits | Event.ONDBLCLICK) == Event.ONDBLCLICK)
- dispatchEvent(document.createDblClickEvent(0, 0, 0, 0, 0, false, false, false, false));
+ dispatchEvent(document.createDblClickEvent(0, 0, 0, 0, 0, false, false,
+ false, false));
if ((eventbits | Event.ONFOCUS) == Event.ONFOCUS)
dispatchEvent(document.createFocusEvent());
if ((eventbits | Event.ONKEYDOWN) == Event.ONKEYDOWN)
- dispatchEvent(document.createKeyDownEvent(false, false, false, false, keys[0], 0));
+ dispatchEvent(document.createKeyDownEvent(false, false, false, false,
+ keys[0], 0));
if ((eventbits | Event.ONKEYPRESS) == Event.ONKEYPRESS)
- dispatchEvent(document.createKeyPressEvent(false, false, false, false, keys[0], 0));
+ dispatchEvent(document.createKeyPressEvent(false, false, false, false,
+ keys[0], 0));
if ((eventbits | Event.ONKEYUP) == Event.ONKEYUP)
- dispatchEvent(document.createKeyUpEvent(false, false, false, false, keys[0], 0));
+ dispatchEvent(document.createKeyUpEvent(false, false, false, false,
+ keys[0], 0));
if ((eventbits | Event.ONLOSECAPTURE) == Event.ONLOSECAPTURE)
triggerHtmlEvent("losecapture");
if ((eventbits | Event.ONMOUSEDOWN) == Event.ONMOUSEDOWN)
- dispatchEvent(document.createMouseDownEvent(0, 0, 0, 0, 0, false, false, false, false, NativeEvent.BUTTON_LEFT));
+ dispatchEvent(document.createMouseDownEvent(0, 0, 0, 0, 0, false, false,
+ false, false, NativeEvent.BUTTON_LEFT));
if ((eventbits | Event.ONMOUSEMOVE) == Event.ONMOUSEMOVE)
- dispatchEvent(document.createMouseMoveEvent(0, 0, 0, 0, 0, false, false, false, false, NativeEvent.BUTTON_LEFT));
+ dispatchEvent(document.createMouseMoveEvent(0, 0, 0, 0, 0, false, false,
+ false, false, NativeEvent.BUTTON_LEFT));
if ((eventbits | Event.ONMOUSEOUT) == Event.ONMOUSEOUT)
- dispatchEvent(document.createMouseOutEvent(0, 0, 0, 0, 0, false, false, false, false, NativeEvent.BUTTON_LEFT, null));
+ dispatchEvent(document.createMouseOutEvent(0, 0, 0, 0, 0, false, false,
+ false, false, NativeEvent.BUTTON_LEFT, null));
if ((eventbits | Event.ONMOUSEOVER) == Event.ONMOUSEOVER)
- dispatchEvent(document.createMouseOverEvent(0, 0, 0, 0, 0, false, false, false, false, NativeEvent.BUTTON_LEFT, null));
+ dispatchEvent(document.createMouseOverEvent(0, 0, 0, 0, 0, false, false,
+ false, false, NativeEvent.BUTTON_LEFT, null));
if ((eventbits | Event.ONMOUSEUP) == Event.ONMOUSEUP)
- dispatchEvent(document.createMouseUpEvent(0, 0, 0, 0, 0, false, false, false, false, NativeEvent.BUTTON_LEFT));
+ dispatchEvent(document.createMouseUpEvent(0, 0, 0, 0, 0, false, false,
+ false, false, NativeEvent.BUTTON_LEFT));
if ((eventbits | Event.ONSCROLL) == Event.ONSCROLL)
dispatchEvent(document.createScrollEvent());
if ((eventbits | Event.ONERROR) == Event.ONERROR)
dispatchEvent(document.createErrorEvent());
if ((eventbits | Event.ONMOUSEWHEEL) == Event.ONMOUSEWHEEL)
- dispatchEvent(document.createMouseEvent("mousewheel", true, true, 0, 0, 0, 0, 0, false, false, false, false, NativeEvent.BUTTON_LEFT, null));
+ dispatchEvent(document.createMouseEvent("mousewheel", true, true, 0, 0,
+ 0, 0, 0, false, false, false, false, NativeEvent.BUTTON_LEFT, null));
if (eventbits == EventsListener.ONSUBMIT)
triggerHtmlEvent("submit");
return this;
@@ -222,14 +210,13 @@ public class Events extends GQuery {
/**
* Trigger a html event in all matched elements.
*
- * @param htmlEvent
- * An string representing the html event desired
+ * @param htmlEvent An string representing the html event desired
*/
public Events triggerHtmlEvent(String htmlEvent) {
dispatchEvent(document.createHtmlEvent(htmlEvent, true, true));
return this;
}
-
+
/**
* Removes all handlers, that matches the events bits passed, from each
* element.
@@ -242,7 +229,7 @@ public class Events extends GQuery {
}
return this;
}
-
+
/**
* Removes all handlers, that matches the events bits and the namespace
* passed, from each element.
@@ -255,10 +242,10 @@ public class Events extends GQuery {
}
return this;
}
-
+
/**
- * Removes all handlers, that matches event name passed. This name
- * could contain a namespace.
+ * Removes all handlers, that matches event name passed. This name could
+ * contain a namespace.
*
* Example: unbind("click.my.namespace")
*/
@@ -268,29 +255,11 @@ public class Events extends GQuery {
}
return this;
}
-
+
private void dispatchEvent(NativeEvent evt) {
for (Element e : 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 functions = cache.get(eventBits);
- for (int j = 0; j extends LazyBase{
* parameter
*
*/
- LazyEvents bind(int eventbits, Object data, Function...funcs);
+ LazyEvents bind(int eventbits, Object data, Function... funcs);
/**
* Binds a set of handlers to a particular Event for each matched element.
*
- * The namespace is a way to group events of the same type, making easier unbind
- * specific handlers.
+ * The namespace is a way to group events of the same type, making easier
+ * unbind specific handlers.
*
* The event handlers are passed as Functions that you can use to prevent
* default behavior. To stop both default action and event bubbling, the
@@ -51,14 +49,14 @@ public interface LazyEvents extends LazyBase{
*
* You can pass an additional Object data to your Function
*
- */
- LazyEvents bind(int eventbits, String namespace, Object data, Function...funcs);
+ */
+ LazyEvents bind(int eventbits, String namespace, Object data, Function... funcs);
/**
* Binds a set of handlers to a particular Event for each matched element.
*
- * The name could contain a namespace which is a way to group events of the same type,
- * making easier unbind specific handlers.
+ * The name could contain a namespace which is a way to group events of the
+ * same type, making easier unbind specific handlers.
*
* The event handlers are passed as Functions that you can use to prevent
* default behavior. To stop both default action and event bubbling, the
@@ -66,53 +64,51 @@ public interface LazyEvents extends LazyBase{
*
* You can pass an additional Object data to your Function
*
- */
- LazyEvents 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);
+ LazyEvents bind(String event, Object data, Function... funcs);
/**
- * Add events to all elements which match the current selector,
- * now and in the future.
+ * Remove an event handlers previously attached using live() The selector used
+ * with it must match exactly the selector initially used with live(). if
+ * eventName
is null, all event handlers corresponding of the
+ * GQuery selector will be removed
*/
- GQuery live(int eventBits, Function... funcs);
+ GQuery die(String eventName);
+
+ GQuery live(String eventName, Object data, Function func);
/**
* Binds a handler to a particular Event (like Event.ONCLICK) for each matched
* element. The handler is executed only once for each element.
- *
+ *
* The event handler is passed as a Function that you can use to prevent
* default behavior. To stop both default action and event bubbling, the
* function event handler has to return false.
- *
+ *
* You can pass an additional Object data to your Function as the second
* parameter
- */
+ */
LazyEvents one(int eventbits, Object data, Function f);
/**
- * Execute all handlers and behaviors attached to the matched elements for the given event types.
+ * Execute all handlers and behaviors attached to the matched elements for the
+ * given event types.
*
- * Different event types can be passed joining these using the or bit wise operator.
+ * Different event types can be passed joining these using the or bit wise
+ * operator.
*
- * For keyboard events you can pass a second parameter which represents
- * the key-code of the pushed key.
+ * For keyboard events you can pass a second parameter which represents the
+ * key-code of the pushed key.
*
- * Example: fire(Event.ONCLICK | Event.ONFOCUS)
- * Example: fire(Event.ONKEYDOWN. 'a');
+ * Example: fire(Event.ONCLICK | Event.ONFOCUS) Example: fire(Event.ONKEYDOWN.
+ * 'a');
*/
LazyEvents trigger(int eventbits, int... keys);
/**
* Trigger a html event in all matched elements.
*
- * @param htmlEvent
- * An string representing the html event desired
+ * @param htmlEvent An string representing the html event desired
*/
LazyEvents triggerHtmlEvent(String htmlEvent);
@@ -133,8 +129,8 @@ public interface LazyEvents extends LazyBase{
LazyEvents unbind(int eventbits, String name);
/**
- * Removes all handlers, that matches event name passed. This name
- * could contain a namespace.
+ * Removes all handlers, that matches event name passed. This name could
+ * contain a namespace.
*
* Example: unbind("click.my.namespace")
*/
diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/MousePlugin.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/MousePlugin.java
index 5dee20d5..ccac4b19 100755
--- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/MousePlugin.java
+++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/MousePlugin.java
@@ -62,14 +62,14 @@ public abstract class MousePlugin extends UiPlugin {
(Object) null, new Function() {
@Override
public boolean f(com.google.gwt.user.client.Event event) {
- return mouseDown(e, Event.create(event));
+ return mouseDown(e, (Event)Event.create(event));
}
}).bind(Event.ONCLICK, getPluginName(), (Object) null,
new Function() {
@Override
public boolean f(com.google.gwt.user.client.Event event) {
- preventClickEvent |= !mouseClick(e, Event.create(event));
+ preventClickEvent |= !mouseClick(e, (Event)Event.create(event));
if (preventClickEvent) {
@@ -212,14 +212,14 @@ public abstract class MousePlugin extends UiPlugin {
(Object) null, new Function() {
@Override
public boolean f(com.google.gwt.user.client.Event e) {
- mouseMove(element, Event.create(e));
+ mouseMove(element, (Event) Event.create(e));
return false;
}
}).bind(Event.ONMOUSEUP, getPluginName(), (Object) null,
new Function() {
@Override
public boolean f(com.google.gwt.user.client.Event e) {
- mouseUp(element, Event.create(e));
+ mouseUp(element, (Event) Event.create(e));
return false;
}
});
diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/UiPlugin.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/UiPlugin.java
index 78dc3b10..92c75395 100755
--- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/UiPlugin.java
+++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/UiPlugin.java
@@ -64,72 +64,14 @@ public class UiPlugin extends GQuery {
}
/**
- * This object allows you to have a full copy of the original Event and
- * implements some useful method of the jQuery event model. This is also
- * useful in Internet Explorer because it use the same javascript object to
- * fire MouseDownEvent, MouseMoveEvent or MouseStopEvent on the same element.
- * So, we cannot keep a copy of the MouseDownEvent during a dragginf for
- * example. Now we can !
*
- * TOBEFIXED : the method preventDefault() must be called directly on the
- * original event
*
- *
+ * @deprecated use {@link com.google.gwt.query.client.plugins.events.Event} instead
*/
- public static class Event extends com.google.gwt.user.client.Event {
-
- /**
- * Create a new {@link Event} by copying the originalEvent
.
- */
- public static Event create(com.google.gwt.user.client.Event originalEvent) {
- Event gQueryEvent = createObject().cast();
- copy(originalEvent, gQueryEvent);
- return gQueryEvent;
- }
-
- private static native void copy(
- com.google.gwt.user.client.Event originalEvent, Event gQueryEvent) /*-{
- for ( var field in originalEvent ) {
- gQueryEvent[field] = originalEvent[field];
- }
- gQueryEvent.originalEvent = originalEvent;
- }-*/;
-
- protected Event() {
- }
-
- /**
- * Return the original event (the one created by the browser)
- */
- public final native com.google.gwt.user.client.Event getOriginalEvent()/*-{
- return this.originalEvent;
- }-*/;
-
- /**
- * Tell whether ctrl or cmd key is pressed
- *
- */
- public final boolean isMetaKeyPressed() {
- return getMetaKey() || getCtrlKey();
- }
-
- /**
- * The mouse position relative to the left edge of the document
- *
- */
- public final int pageX() {
- return getClientX() + document.getScrollLeft();
- }
-
- /**
- * The mouse position relative to the top edge of the document.
- *
- */
- public final int pageY() {
- return getClientY() + document.getScrollTop();
- }
+ public static class Event extends com.google.gwt.query.client.plugins.events.Event {
}
+
private static class GQueryUiImpl {
diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/Event.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/Event.java
new file mode 100644
index 00000000..0b5ae1bd
--- /dev/null
+++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/Event.java
@@ -0,0 +1,88 @@
+package com.google.gwt.query.client.plugins.events;
+
+import com.google.gwt.dom.client.Element;
+import com.google.gwt.query.client.GQuery;
+
+/**
+ * This object allows you to have a full copy of the original Event and
+ * implements some useful method of the jQuery event model.
+ *
+ * This is also useful in Internet Explorer because it use the same javascript
+ * object to fire MouseDownEvent, MouseMoveEvent or MouseStopEvent on the same
+ * element. So, we cannot keep a copy of the MouseDownEvent during a dragging
+ * for example.
+ *
+ *
+ *
+ * TOBEFIXED : the method preventDefault() must be called directly on the
+ * original event
+ *
+ *
+ */
+public class Event extends com.google.gwt.user.client.Event {
+
+
+ /**
+ * Create a new {@link Event} by copying the originalEvent
.
+ */
+ public static Event create(com.google.gwt.user.client.Event originalEvent) {
+ Event gQueryEvent = createObject().cast();
+ copy(originalEvent, gQueryEvent);
+ return gQueryEvent;
+ }
+
+ private static native void copy(
+ com.google.gwt.user.client.Event originalEvent, Event gQueryEvent) /*-{
+ for ( var field in originalEvent) {
+ gQueryEvent[field] = originalEvent[field];
+ }
+ gQueryEvent.originalEvent = originalEvent;
+ }-*/;
+
+ protected Event() {
+ }
+
+ /**
+ * Return the original event (the one created by the browser)
+ */
+ public final native com.google.gwt.user.client.Event getOriginalEvent()/*-{
+ return this.originalEvent;
+ }-*/;
+
+ public final native void setCurrentElementTarget(Element e)/*-{
+
+ this.currentTarget = e;
+
+ //ie don't have a currentEventTarget field on event
+ try{
+ @com.google.gwt.dom.client.DOMImplTrident::currentEventTarget = e;
+ }catch(e){}
+ }-*/;
+
+ /**
+ * Tell whether ctrl or cmd key is pressed
+ *
+ */
+ public final boolean isMetaKeyPressed() {
+ return getMetaKey() || getCtrlKey();
+ }
+
+ /**
+ * The mouse position relative to the left edge of the document
+ *
+ */
+ public final int pageX() {
+ return getClientX() + GQuery.document.getScrollLeft();
+ }
+
+ /**
+ * The mouse position relative to the top edge of the document.
+ *
+ */
+ public final int pageY() {
+ return getClientY() + GQuery.document.getScrollTop();
+ }
+
+
+
+}
diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/EventsListener.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/EventsListener.java
index dbb7e70a..e77540ff 100644
--- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/EventsListener.java
+++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/EventsListener.java
@@ -15,14 +15,21 @@
*/
package com.google.gwt.query.client.plugins.events;
+import static com.google.gwt.query.client.GQuery.$;
+
import com.google.gwt.core.client.Duration;
import com.google.gwt.dom.client.Element;
+import com.google.gwt.dom.client.EventTarget;
import com.google.gwt.query.client.Function;
import com.google.gwt.query.client.js.JsObjectArray;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.EventListener;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
/**
* This class implements an event queue instance for one Element. The queue
* instance is configured as the default event listener in GWT.
@@ -48,7 +55,7 @@ public class EventsListener implements EventListener {
type = t;
function = f;
data = d;
- if (n!=null) {
+ if (n != null) {
nameSpace = n;
}
}
@@ -69,17 +76,148 @@ public class EventsListener implements EventListener {
public boolean hasEventType(int etype) {
return (type & etype) == type;
}
+
+ @Override
+ public String toString() {
+ return "bind function for event type " + type;
+ }
+ }
+
+ /**
+ * {@link BindFunction} used for live() method.
+ *
+ */
+ private static class LiveBindFunction extends BindFunction {
+
+ // TODO can be a list of BindFunction
+ Map bindFunctionBySelector;
+
+ LiveBindFunction(int type, String namespace) {
+
+ super(type, namespace, null, null, -1);
+ bindFunctionBySelector = new HashMap();
+ }
+
+ /**
+ * Add a {@link BindFunction} for a specific css selector
+ */
+ public void addBindFunctionForSelector(String cssSelector, BindFunction f) {
+ bindFunctionBySelector.put(cssSelector, f);
+ }
+
+ @Override
+ public boolean fire(Event event) {
+
+ if (isEmpty()) {
+ return true;
+ }
+
+ String[] selectors = bindFunctionBySelector.keySet().toArray(
+ new String[0]);
+
+ // first element where the event was fired
+ Element eventTarget = getEventTarget(event);
+ // last element where the event was dispatched on
+ Element liveContextElement = getCurrentEventTarget(event);
+
+ if (eventTarget == null || liveContextElement == null) {
+ return true;
+ }
+
+ Map> realCurrentTargetBySelector = $(eventTarget).closest(
+ selectors, liveContextElement);
+
+ // nothing match the selectors
+ if (realCurrentTargetBySelector.isEmpty()) {
+ return true;
+ }
+
+ boolean result = true;
+
+ com.google.gwt.query.client.plugins.events.Event gqEvent = com.google.gwt.query.client.plugins.events.Event.create(event);
+
+ for (String cssSelector : realCurrentTargetBySelector.keySet()) {
+ BindFunction f = bindFunctionBySelector.get(cssSelector);
+ for (Element element : realCurrentTargetBySelector.get(cssSelector)) {
+ gqEvent.setCurrentElementTarget(element);
+ boolean subResult = f.fire(gqEvent);
+ result &= subResult;
+ if (!subResult) {
+ // Event should not continue to be bubbled, break the second for
+ break;
+ }
+ }
+ }
+
+ // trick to reset the right currentTarget on the original event on ie
+ gqEvent.setCurrentElementTarget(liveContextElement);
+
+ return result;
+
+ }
+
+ /**
+ * Remove the BindFunction associated to this cssSelector
+ */
+ public BindFunction removeBindFunctionForSelector(String cssSelector) {
+ return bindFunctionBySelector.remove(cssSelector);
+ }
+
+ /**
+ * Tell if no {@link BindFunction} are linked to this object
+ *
+ * @return
+ */
+ public boolean isEmpty() {
+ return bindFunctionBySelector.isEmpty();
+ }
+
+ @Override
+ public String toString() {
+ return "live bind function for selector "
+ + bindFunctionBySelector.keySet();
+ }
+
+ /**
+ * Return the element whose the listener fired last. It represent the
+ * context element where the {@link LiveBindFunction} was binded
+ *
+ */
+ private Element getCurrentEventTarget(Event e) {
+ EventTarget currentEventTarget = e.getCurrentEventTarget();
+
+ if (!Element.is(currentEventTarget)) {
+ return null;
+ }
+
+ return Element.as(currentEventTarget);
+ }
+
+ /**
+ * Return the element that was the actual target of the element
+ */
+ private Element getEventTarget(Event e) {
+ EventTarget eventTarget = e.getEventTarget();
+
+ if (!Element.is(eventTarget)) {
+ return null;
+ }
+
+ return Element.as(eventTarget);
+ }
+
}
+
// Gwt Events class has not this event defined
public static int ONSUBMIT = 0x08000;
public static void clean(Element e) {
EventsListener ret = getGQueryEventListener(e);
- if (ret != null){
+ if (ret != null) {
ret.clean();
- }
+ }
}
-
+
public static EventsListener getInstance(Element e) {
EventsListener ret = getGQueryEventListener(e);
return ret != null ? ret : new EventsListener(e);
@@ -87,9 +225,9 @@ public class EventsListener implements EventListener {
public static void rebind(Element e) {
EventsListener ret = getGQueryEventListener(e);
- if (ret != null && ret.eventBits != 0){
+ if (ret != null && ret.eventBits != 0) {
ret.sink();
- }
+ }
}
private static native void cleanGQListeners(Element elem) /*-{
@@ -100,39 +238,41 @@ public class EventsListener implements EventListener {
elem.__gqueryevent = null
}-*/;
-
+
private static native EventsListener getGQueryEventListener(Element elem) /*-{
- return elem.__gqueryevent;
+ return elem.__gqueryevent;
}-*/;
-
+
private static native EventListener getGwtEventListener(Element elem) /*-{
- return elem.__gwtlistener;
+ return elem.__gwtlistener;
}-*/;
private static native void setGQueryEventListener(Element elem,
EventsListener gqevent) /*-{
- if (elem.__gqueryevent) {
- elem.__listener = elem.__gqueryevent;
- } else {
- elem.__gwtlistener = elem.__listener;
- elem.__gqueryevent = gqevent;
- }
+ if (elem.__gqueryevent) {
+ elem.__listener = elem.__gqueryevent;
+ } else {
+ elem.__gwtlistener = elem.__listener;
+ elem.__gqueryevent = gqevent;
+ }
}-*/;
// Gwt does't handle submit events in DOM.sinkEvents
private static native void sinkSubmitEvent(Element elem) /*-{
- if (elem.__gquerysubmit) return;
- elem.__gquerysubmit = true;
-
- var handle = function(event) {
- elem.__gqueryevent.@com.google.gwt.query.client.plugins.events.EventsListener::dispatchEvent(Lcom/google/gwt/user/client/Event;)(event);
- };
-
- if (elem.addEventListener)
- elem.addEventListener("submit", handle, true);
- else
- elem.attachEvent("onsubmit", handle);
+ if (elem.__gquerysubmit)
+ return;
+ elem.__gquerysubmit = true;
+
+ var handle = function(event) {
+ elem.__gqueryevent.@com.google.gwt.query.client.plugins.events.EventsListener::dispatchEvent(Lcom/google/gwt/user/client/Event;)(event);
+ };
+
+ if (elem.addEventListener)
+ elem.addEventListener("submit", handle, true);
+ else
+ elem.attachEvent("onsubmit", handle);
}-*/;
+
int eventBits = 0;
double lastEvnt = 0;
@@ -140,14 +280,14 @@ public class EventsListener implements EventListener {
private Element element;
- private JsObjectArray elementEvents = JsObjectArray
- .createArray().cast();
-
+ private JsObjectArray elementEvents = JsObjectArray.createArray().cast();
+ private Map liveBindFunctionByEventType = new HashMap();
+
private EventsListener(Element element) {
this.element = element;
}
-
- public void bind(int eventbits, final Object data, Function...funcs) {
+
+ public void bind(int eventbits, final Object data, Function... funcs) {
bind(eventbits, null, data, funcs);
}
@@ -155,25 +295,27 @@ public class EventsListener implements EventListener {
int times) {
bind(eventbits, null, data, function, times);
}
-
- public void bind(int eventbits, String name, final Object data, Function...funcs) {
- for (Function function: funcs) {
+
+ public void bind(int eventbits, String name, final Object data,
+ Function... funcs) {
+ for (Function function : funcs) {
bind(eventbits, name, data, function, -1);
}
}
-
- public void bind(int eventbits, String namespace, final Object data, final Function function,
- int times) {
+
+ public void bind(int eventbits, String namespace, final Object data,
+ final Function function, int times) {
if (function == null) {
unbind(eventbits, namespace);
return;
}
eventBits |= eventbits;
sink();
- elementEvents.add(new BindFunction(eventbits, namespace, function, data, times));
+ elementEvents.add(new BindFunction(eventbits, namespace, function, data,
+ times));
}
-
- public void bind(String event, final Object data, Function...funcs) {
+
+ public void bind(String event, final Object data, Function... funcs) {
String nameSpace = event.replaceFirst("^[^\\.]+\\.*(.*)$", "$1");
String eventName = event.replaceFirst("^([^\\.]+).*$", "$1");
int b = 0;
@@ -182,12 +324,25 @@ public class EventsListener implements EventListener {
} else {
b = Event.getTypeInt(eventName);
}
- for (Function function: funcs) {
+ for (Function function : funcs) {
bind(b, nameSpace, data, function, -1);
}
}
-
+
+ public void die(String eventName, String cssSelector) {
+ if (eventName == null) {
+ for (LiveBindFunction liveBindFunction : liveBindFunctionByEventType.values()) {
+ liveBindFunction.removeBindFunctionForSelector(cssSelector);
+ }
+ } else {
+ LiveBindFunction liveBindFunction = liveBindFunctionByEventType.get(eventName);
+ liveBindFunction.removeBindFunctionForSelector(cssSelector);
+ }
+
+ }
+
public void dispatchEvent(Event event) {
+
int etype = "submit".equalsIgnoreCase(event.getType()) ? ONSUBMIT
: DOM.eventGetType(event);
for (int i = 0; i < elementEvents.length(); i++) {
@@ -200,16 +355,38 @@ public class EventsListener implements EventListener {
}
}
}
-
+
/**
- * Return the original gwt EventListener associated with
- * this element, before gquery replaced it to introduce its
- * own event handler.
+ * Return the original gwt EventListener associated with this element, before
+ * gquery replaced it to introduce its own event handler.
*/
public EventListener getOriginalEventListener() {
return getGwtEventListener(element);
}
-
+
+ public void live(String eventName, String cssSelector, Object data, Function f) {
+ int eventType = 0;
+ if ("submit".equals(eventName)) {
+ eventType = ONSUBMIT;
+ } else {
+ eventType = Event.getTypeInt(eventName);
+ }
+
+ // is a LiveBindFunction already attached for this kind of event
+ LiveBindFunction liveBindFunction = liveBindFunctionByEventType.get(eventName);
+ if (liveBindFunction == null) {
+ liveBindFunction = new LiveBindFunction(eventType, "live");
+ eventBits |= eventType;
+ sink();
+ elementEvents.add(liveBindFunction);
+ liveBindFunctionByEventType.put(eventName, liveBindFunction);
+ }
+
+ liveBindFunction.addBindFunctionForSelector(cssSelector, new BindFunction(
+ eventType, "live", f, data));
+
+ }
+
public void onBrowserEvent(Event event) {
// Workaround for Issue_20
if (lastType == event.getTypeInt()
@@ -224,20 +401,20 @@ public class EventsListener implements EventListener {
if (getOriginalEventListener() != null) {
getOriginalEventListener().onBrowserEvent(event);
}
-
+
dispatchEvent(event);
}
-
+
public void unbind(int eventbits) {
unbind(eventbits, null);
}
-
+
public void unbind(int eventbits, String namespace) {
- JsObjectArray newList = JsObjectArray
- .createArray().cast();
+ JsObjectArray newList = JsObjectArray.createArray().cast();
for (int i = 0; i < elementEvents.length(); i++) {
BindFunction listener = elementEvents.get(i);
- boolean matchNS = namespace == null || namespace.isEmpty() || listener.nameSpace.equals(namespace);
+ boolean matchNS = namespace == null || namespace.isEmpty()
+ || listener.nameSpace.equals(namespace);
boolean matchEV = eventbits <= 0 || listener.hasEventType(eventbits);
if (matchNS && matchEV) {
continue;
@@ -246,7 +423,7 @@ public class EventsListener implements EventListener {
}
elementEvents = newList;
}
-
+
public void unbind(String event) {
String nameSpace = event.replaceFirst("^[^\\.]+\\.*(.*)$", "$1");
String eventName = event.replaceFirst("^([^\\.]+).*$", "$1");
@@ -258,24 +435,26 @@ public class EventsListener implements EventListener {
}
unbind(b, nameSpace);
}
-
- private void clean(){
+
+ private void clean() {
cleanGQListeners(element);
- elementEvents = JsObjectArray.createArray().cast();
+ elementEvents = JsObjectArray.createArray().cast();
+ liveBindFunctionByEventType = new HashMap();
}
-
+
private void sink() {
setGQueryEventListener(element, this);
- DOM.setEventListener((com.google.gwt.user.client.Element)element, this);
+ DOM.setEventListener((com.google.gwt.user.client.Element) element, this);
if (eventBits == ONSUBMIT) {
sinkSubmitEvent(element);
} else {
- if ((eventBits | Event.FOCUSEVENTS) == Event.FOCUSEVENTS && element.getAttribute("tabIndex").length() == 0) {
+ if ((eventBits | Event.FOCUSEVENTS) == Event.FOCUSEVENTS
+ && element.getAttribute("tabIndex").length() == 0) {
element.setAttribute("tabIndex", "0");
}
DOM.sinkEvents((com.google.gwt.user.client.Element) element, eventBits
| DOM.getEventsSunk((com.google.gwt.user.client.Element) element));
-
+
}
}
}
diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryCoreTest.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryCoreTest.java
index 5d1d7ddf..ed8d3b80 100644
--- a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryCoreTest.java
+++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryCoreTest.java
@@ -1201,18 +1201,28 @@ public class GQueryCoreTest extends GWTTestCase {
public void testClosestMethodWithArrayOfString(){
- String html = "";
+ String html = "";
$(e).html(html);
- Map close = $("input", e).closest(new String[]{"p","div", ".test", "#unknown"});
+ Map> close = $("input", e).closest(new String[]{"p","div", ".test", "#unknown"});
assertEquals(3, close.size());
+
assertNotNull(close.get("p"));
- assertEquals("firstP", close.get("p").getId());
+ assertEquals(1,close.get("p").size());
+ assertEquals("mainP", close.get("p").get(0).getId());
+
assertNotNull(close.get("div"));
- assertEquals("firstDiv", close.get("div").getId());
+ assertEquals(3,close.get("div").size());
+ assertEquals("subSubDiv", close.get("div").get(0).getId());
+ assertEquals("subDiv", close.get("div").get(1).getId());
+ assertEquals("mainDiv", close.get("div").get(2).getId());
+
assertNotNull(close.get(".test"));
- assertEquals("mainDiv", close.get(".test").getId());
+ assertEquals(2,close.get(".test").size());
+ assertEquals("testSpan", close.get(".test").get(0).getId());
+ assertEquals("subDiv", close.get(".test").get(1).getId());
+
assertNull(close.get("#unknown"));
}
diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEventsTest.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEventsTest.java
index eb4a9e80..99515ec3 100644
--- a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEventsTest.java
+++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEventsTest.java
@@ -58,10 +58,90 @@ public class GQueryEventsTest extends GWTTestCase {
e = testPanel.getElement();
e.setId("evnt-tst");
} else {
+ EventsListener.clean(e);
e.setInnerHTML("");
}
}
+
+
+ public void testDie() {
+ $(e).html("content
");
+ $(".clickMe", e).live("click", new Function(){
+ public void f(Element e) {
+ $(e).css(CSS.COLOR.with(RGBColor.RED));
+ }
+ });
+
+ $(".clickMe", e).live("dblclick", new Function(){
+ public void f(Element e) {
+ $(e).css(CSS.COLOR.with(RGBColor.BLUE));
+ }
+ });
+
+ $("#div1",e).addClass("clickMe");
+
+ $("#div1",e).click();
+ assertEquals(RGBColor.RED.getCssName(), $("#div1", e).css(CSS.COLOR));
+
+ $("#div1",e).dblclick();
+ assertEquals(RGBColor.BLUE.getCssName(), $("#div1", e).css(CSS.COLOR));
+
+ //reset
+ $("#div1",e).css(CSS.COLOR.with(RGBColor.BLACK));
+
+ $(".clickMe", e).die("click");
+ $("#div1",e).click();
+ assertEquals(RGBColor.BLACK.getCssName(), $("#div1", e).css(CSS.COLOR));
+
+ $("#div1",e).dblclick();
+ assertEquals(RGBColor.BLUE.getCssName(), $("#div1", e).css(CSS.COLOR));
+
+ //reset
+ $("#div1",e).css(CSS.COLOR.with(RGBColor.BLACK));
+
+ $(".clickMe", e).die("dblclick");
+
+ $("#div1",e).dblclick();
+ assertEquals(RGBColor.BLACK.getCssName(), $("#div1", e).css(CSS.COLOR));
+
+ }
+
+ public void testDie2() {
+ $(e).html("content
");
+ $(".clickMe", e).live("click", new Function(){
+ public void f(Element e) {
+ $(e).css(CSS.COLOR.with(RGBColor.RED));
+ }
+ });
+
+ $(".clickMe", e).live("dblclick", new Function(){
+ public void f(Element e) {
+ $(e).css(CSS.COLOR.with(RGBColor.BLUE));
+ }
+ });
+
+ $("#div1",e).addClass("clickMe");
+
+ $("#div1",e).click();
+ assertEquals(RGBColor.RED.getCssName(), $("#div1", e).css(CSS.COLOR));
+
+ $("#div1",e).dblclick();
+ assertEquals(RGBColor.BLUE.getCssName(), $("#div1", e).css(CSS.COLOR));
+
+ //reset
+ $("#div1",e).css(CSS.COLOR.with(RGBColor.BLACK));
+
+ $(".clickMe", e).die();
+
+ $("#div1",e).click();
+ assertEquals(RGBColor.BLACK.getCssName(), $("#div1", e).css(CSS.COLOR));
+
+ $("#div1",e).dblclick();
+ assertEquals(RGBColor.BLACK.getCssName(), $("#div1", e).css(CSS.COLOR));
+
+ }
+
/**
* TODO: DblClick doesn't work with HtmlUnit, investigate and report.
*/
@@ -77,7 +157,7 @@ public class GQueryEventsTest extends GWTTestCase {
$("p", e).dblclick();
assertEquals("yellow", $("p", e).css("color"));
}
-
+
public void testEventsPlugin() {
$(e).html("Content
");
@@ -184,30 +264,6 @@ public class GQueryEventsTest extends GWTTestCase {
$("input", e).keyup('c');
assertEquals("abc", $("input", e).val());
}
-
- public void testLive() {
- $(e).html("Content 1
");
- $(".clickMe").live(Event.ONCLICK, new Function(){
- public void f(Element e) {
- $(e).css("color", "red");
- }
- });
- $(e).append("Content 2
");
- 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("Content 3");
-
- $(".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));
@@ -222,6 +278,92 @@ public class GQueryEventsTest extends GWTTestCase {
assertEquals("black", $(e).css("color"));
}
+ public void testLive() {
+ $(e).html("");
+ $(".clickMe", e).live("click", new Function(){
+ public void f(Element el) {
+ $(el).css("color", "red");
+ }
+ });
+
+ $(e).append("");
+
+ $(".clickMe", e).click();
+ assertEquals("red", $("#div1", e).css("color"));
+ assertEquals("red", $("#div3", e).css("color"));
+
+ //reset
+ $("*", e).css(CSS.COLOR.with(RGBColor.BLACK));
+ assertEquals("black", $("div", e).css("color"));
+ assertEquals("black", $("span", e).css("color"));
+
+ $("#span1", e).click();
+ assertEquals("red", $("#div1", e).css("color"));
+ assertEquals("black", $("#div3", e).css("color"));
+
+ //reset
+ $("*", e).css(CSS.COLOR.with(RGBColor.BLACK));
+
+ $("#span2", e).click();
+ assertEquals("black", $("#div1", e).css("color"));
+ assertEquals("red", $("#div3", e).css("color"));
+
+ //reset
+ $("*", e).css(CSS.COLOR.with(RGBColor.BLACK));
+
+ $("#div2, #div4", e).addClass("clickMe");
+
+ $("#span1", e).click();
+ assertEquals("red", $("#div1", e).css("color"));
+ assertEquals("red", $("#div2", e).css("color"));
+ assertEquals("black", $("#div3", e).css("color"));
+ assertEquals("black", $("#div4", e).css("color"));
+
+ //reset
+ $("*", e).css(CSS.COLOR.with(RGBColor.BLACK));
+
+ $("#span2", e).click();
+ assertEquals("black", $("#div1", e).css("color"));
+ assertEquals("black", $("#div2", e).css("color"));
+ assertEquals("red", $("#div3", e).css("color"));
+ assertEquals("red", $("#div4", e).css("color"));
+
+ }
+
+ public void testLive2() {
+
+ $(e).html("");
+
+ $(".clickable", e).live("click", new Function(){
+ public void f(Element e) {
+ $(e).css(CSS.COLOR.with(RGBColor.RED));
+ }
+ });
+
+ $(".clickable2", e).live("click", new Function(){
+ public void f(Element e) {
+ $(e).css(CSS.COLOR.with(RGBColor.BLUE));
+ }
+ });
+
+ $(".hover", e).live("mouseover", new Function(){
+ public void f(Element e) {
+ $(e).css(CSS.BACKGROUND_COLOR.with(RGBColor.YELLOW));
+ }
+ });
+
+ $("#div1", e).addClass("clickable");
+ $("#div2", e).addClass("clickable2", "hover");
+
+ $("#span1", e).click();
+
+ assertEquals("red", $("#div1", e).css(CSS.COLOR));
+ assertEquals("blue", $("#div2", e).css(CSS.COLOR));
+ assertNotSame("yellow", $("#div2", e).css(CSS.BACKGROUND_COLOR));
+
+
+ }
+
public void testNamedBinding() {
$(e).html("Content
");
@@ -269,6 +411,18 @@ public class GQueryEventsTest extends GWTTestCase {
assertEquals(12.0d, $("p", e).cur("fontSize", true));
}
+ public void testRebind() {
+ final GQuery b = $("content
");
+ b.click(new Function() {
+ public void f(Element e){
+ b.css(CSS.COLOR.with(RGBColor.RED));
+ }
+ });
+ $(e).append(b);
+ b.click();
+ assertEquals("red", $(b).css("color"));
+ }
+
public void testSubmitEvent() {
// Add a form and an iframe to the dom. The form target is the iframe
$(e).html("