From 8d14bba23b22cc88312dcefd6e2a8e9cabfb37b2 Mon Sep 17 00:00:00 2001 From: Manolo Carrasco Date: Tue, 16 Dec 2014 07:51:31 +0100 Subject: Make special events api more easy for plugins --- .../gwt/query/client/plugins/events/EventsListener.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'gwtquery-core') 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 5f3cf531..aef9d876 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 @@ -74,19 +74,20 @@ public class EventsListener implements EventListener { return originalType; } - public Function createDelegateHandler(Function originalHandler) { - return new SpecialMouseEventHandler(originalHandler); + public HandlerWrapperFunction createDelegateHandler(Function originalHandler) { + return new HandlerWrapperFunction(originalHandler); } } - private interface HandlerWrapper { + public interface HandlerWrapper { Function getOriginalHandler(); } - private static class SpecialMouseEventHandler extends Function implements HandlerWrapper { + + public static class HandlerWrapperFunction extends Function implements HandlerWrapper { private Function delegateHandler; - public SpecialMouseEventHandler(Function originalHandler) { + public HandlerWrapperFunction(Function originalHandler) { this.delegateHandler = originalHandler; } @@ -401,7 +402,7 @@ public class EventsListener implements EventListener { /** * We have to set the gQuery event listener to the element again when - * the element is a widget, because when GWT detaches a widget it removes the + * the element is a widget, because when GWT detaches a widget it removes the * event listener. */ public static void rebind(Element e) { @@ -732,7 +733,7 @@ public class EventsListener implements EventListener { public void unbind(int eventbits, String namespace, String eventName, String originalEventType, Function f) { - + JsObjectArray newList = JsObjectArray.createArray().cast(); for (int i = 0; i < elementEvents.length(); i++) { BindFunction listener = elementEvents.get(i); -- cgit v1.2.3 From 7a54cd8a80b59cfbe6f69bc782e14a23fa83625a Mon Sep 17 00:00:00 2001 From: Manolo Carrasco Date: Sun, 21 Dec 2014 08:30:53 +0100 Subject: Implement API based on jQuery for special events - SpecialEvents have an API with three methods: setup tearDown add remove - Migrated mouse special events to use this API --- devtest/pom.xml | 33 --- .../com/google/gwt/query/DevTestRunner.gwt.xml | 1 + .../java/com/google/gwt/query/client/GQuery.java | 4 +- .../google/gwt/query/client/plugins/Events.java | 13 +- .../client/plugins/events/EventsListener.java | 239 +++++++++++++-------- .../gwt/query/client/plugins/events/GqEvent.java | 8 - .../gwt/query/client/GQueryEventsTestGwt.java | 8 +- 7 files changed, 160 insertions(+), 146 deletions(-) (limited to 'gwtquery-core') diff --git a/devtest/pom.xml b/devtest/pom.xml index 2ba90061..36100cde 100644 --- a/devtest/pom.xml +++ b/devtest/pom.xml @@ -33,29 +33,12 @@ - - - ${basedir}/src/main/java - - - ${basedir}/src/main/resources - - - - - ${basedir}/src/test/java - - - ${basedir}/src/test/resources - - org.codehaus.mojo gwt-maven-plugin ${gwtmaven} - ${gwtversion} com.google.gwt.query.DevTestRunner @@ -73,22 +56,6 @@ - - org.apache.maven.plugins - maven-eclipse-plugin - - true - false - - - com.google.gwt.eclipse.core.gwtProjectValidator - - - - com.google.gwt.eclipse.core.gwtNature - - - ${project.build.directory}/${project.build.finalName}/WEB-INF/classes diff --git a/devtest/src/main/java/com/google/gwt/query/DevTestRunner.gwt.xml b/devtest/src/main/java/com/google/gwt/query/DevTestRunner.gwt.xml index b3ce809f..373d2f15 100644 --- a/devtest/src/main/java/com/google/gwt/query/DevTestRunner.gwt.xml +++ b/devtest/src/main/java/com/google/gwt/query/DevTestRunner.gwt.xml @@ -2,5 +2,6 @@ + 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 098cb2da..3702f010 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 @@ -2503,7 +2503,7 @@ public class GQuery implements Lazy { * Since GQuery 1.4.0, this method binds handlers for both mouseenter and mouseleave events. */ public GQuery hover(Function fover, Function fout) { - return bind("mouseenter", null, fover).bind("mouseleave", null, fout); + return bind("mouseenter", fover).bind("mouseleave", fout); } /** @@ -2856,7 +2856,7 @@ public class GQuery implements Lazy { */ @Deprecated public GQuery load(Function f) { - return bind(Event.ONLOAD, null, f); + return bind(Event.ONLOAD, f); } /** 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 101ae0b9..a16230f0 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 @@ -288,18 +288,7 @@ public class Events extends GQuery { * @functions a set of function to run if the event is not canceled. */ public Events triggerHtmlEvent(String htmlEvent, Object[] datas, final Function... functions) { - SpecialEvent specialEvent = EventsListener.special.get(htmlEvent); - boolean isSpecialEvent = specialEvent != null; - - String originalEventName = htmlEvent; - String delegateEventName = isSpecialEvent ? specialEvent.getDelegateType() : htmlEvent; - - NativeEvent e = document.createHtmlEvent(delegateEventName, true, true); - - if (isSpecialEvent) { - GqEvent.setOriginalEventType(e, originalEventName); - } - + NativeEvent e = document.createHtmlEvent(htmlEvent, true, true); if ("submit".equals(htmlEvent)){ Function submitFunction = new Function() { public void f(Element e) { 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 aef9d876..94182385 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 @@ -13,6 +13,8 @@ */ 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; @@ -29,10 +31,9 @@ import com.google.gwt.user.client.Event; import com.google.gwt.user.client.EventListener; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; -import static com.google.gwt.query.client.GQuery.$; - /** * This class implements an event queue instance for one Element. The queue instance is configured * as the default event listener in GWT. @@ -46,78 +47,112 @@ import static com.google.gwt.query.client.GQuery.$; public class EventsListener implements EventListener { public interface SpecialEvent { - String getDelegateType(); + boolean tearDown(EventsListener l); - String getOriginalType(); + boolean setup(EventsListener l); - Function createDelegateHandler(Function originalHandler); + boolean remove(EventsListener l, String nameSpace, Function f); + + boolean add(EventsListener l, String nameSpace, Object data, Function f); + + String getDelegateType(); + + boolean hasHandlers(EventsListener l); } /** * Used for simulating mouseenter and mouseleave events */ public static class MouseSpecialEvent implements SpecialEvent { - private String originalType; private String delegateType; - + + HashMap handlers = new HashMap(); + + private class MouseSpecialFunction extends Function { + final EventsListener listener; + public MouseSpecialFunction(EventsListener l) { + listener = l; + } + + public boolean f(Event e, Object... arg) { + EventTarget eventTarget = e.getCurrentEventTarget(); + Element target = eventTarget != null ? eventTarget. cast() : null; + + EventTarget relatedEventTarget = e.getRelatedEventTarget(); + Element related = relatedEventTarget != null ? relatedEventTarget. cast() : null; + + if (related == null || (related != target && !GQuery.contains(target, related))) { + for (int i = 0, l = listener.elementEvents.length(); i < l ; i ++) { + BindFunction function = listener.elementEvents.get(i); + if (function.isTypeOf(originalType) && !function.fire(e, arg)) { + return false; + } + } + } + return true; + }; + } + public MouseSpecialEvent(String originalType, String delegateType) { this.originalType = originalType; this.delegateType = delegateType; } - public String getDelegateType() { - return delegateType; + @Override + public boolean add(EventsListener l, String nameSpace, Object data, Function f) { + l.bind(BITLESS, nameSpace, originalType, null, null, f, -1); + return false; } - public String getOriginalType() { - return originalType; + @Override + public boolean remove(EventsListener l, String nameSpace, Function f) { + l.elementEvents = unbindFunctions(l.elementEvents, BITLESS, nameSpace, delegateType, null, f); + return false; } - - public HandlerWrapperFunction createDelegateHandler(Function originalHandler) { - return new HandlerWrapperFunction(originalHandler); + + @Override + public boolean setup(EventsListener l) { + MouseSpecialFunction handler = new MouseSpecialFunction(l); + handlers.put(l, handler); + int b = Event.getTypeInt(delegateType); + l.bind(b, null, delegateType, originalType, null, handler, -1); + return false; } - } - - public interface HandlerWrapper { - Function getOriginalHandler(); - } - - public static class HandlerWrapperFunction extends Function implements HandlerWrapper { - - private Function delegateHandler; - - public HandlerWrapperFunction(Function originalHandler) { - this.delegateHandler = originalHandler; + + @Override + public boolean tearDown(EventsListener l) { + MouseSpecialFunction handler = handlers.remove(l); + if (handler != null) { + int b = Event.getTypeInt(delegateType); + l.unbind(b, null, delegateType, originalType, handler); + } + return false; } @Override - public boolean f(Event e, Object... data) { - EventTarget eventTarget = e.getCurrentEventTarget(); - Element target = eventTarget != null ? eventTarget. cast() : null; - - EventTarget relatedEventTarget = e.getRelatedEventTarget(); - Element related = relatedEventTarget != null ? relatedEventTarget. cast() : null; + public String getDelegateType() { + return delegateType; + } - // For mousenter/leave call the handler if related is outside the target. - if (related == null || (related != target && !GQuery.contains(target, related))) { - return delegateHandler != null ? delegateHandler.f(e, data) : false; + @Override + public boolean hasHandlers(EventsListener l) { + for (int i = 0, j = l.elementEvents.length(); i < j; i++) { + BindFunction function = l.elementEvents.get(i); + if (function.isTypeOf(delegateType)) { + return true; + } } - return false; } - - public Function getOriginalHandler() { - return delegateHandler; - } } + private static class BindFunction { Object data; Function function; String nameSpace; - // for special event like mouseleave, mouseenter String originalEventType; int times; int type; @@ -130,7 +165,7 @@ public class EventsListener implements EventListener { this.type = type; this.function = function; this.data = data; - this.originalEventType = originalEventType; +// this.originalEventType = originalEventType; this.nameSpace = nameSpace != null ? nameSpace : ""; } @@ -149,7 +184,10 @@ public class EventsListener implements EventListener { } else { arguments = eventData; } - return function.fe(event, arguments); + // FIXME(manolo): figure out when this is null, and fix or comment it. + if (function != null) { + return function.fe(event, arguments); + } } return true; } @@ -157,6 +195,7 @@ public class EventsListener implements EventListener { public boolean hasEventType(int etype) { return type != BITLESS && etype != BITLESS && (type & etype) != 0; } + public boolean isTypeOf(String eName) { return eventName != null && eventName.equalsIgnoreCase(eName); @@ -185,10 +224,7 @@ public class EventsListener implements EventListener { public boolean isEquals(Function f) { assert f != null : "function f cannot be null"; - Function functionToCompare = - function instanceof HandlerWrapper ? ((HandlerWrapper) function).getOriginalHandler() - : function; - return f.equals(functionToCompare); + return f.equals(function); } public Object getOriginalEventType() { @@ -380,10 +416,10 @@ public class EventsListener implements EventListener { public static String MOUSEENTER = "mouseenter"; public static String MOUSELEAVE = "mouseleave"; - public static JsMap special; + public static HashMap special; static { - special = JsMap.create(); + special = new HashMap(); special.put(MOUSEENTER, new MouseSpecialEvent(MOUSEENTER, "mouseover")); special.put(MOUSELEAVE, new MouseSpecialEvent(MOUSELEAVE, "mouseout")); } @@ -505,26 +541,31 @@ public class EventsListener implements EventListener { //handle special event like mouseenter or mouseleave SpecialEvent hook = special.get(eventName); - eventName = hook != null ? hook.getDelegateType() : eventName; - String originalEventName = hook != null ? hook.getOriginalType() : null; - - int b = Event.getTypeInt(eventName); + if (hook != null && !hook.hasHandlers(this)) { + hook.setup(this); + } for (Function function : funcs) { - Function handler = hook != null ? hook.createDelegateHandler(function) : function; - bind(b, nameSpace, eventName, originalEventName, data, handler, -1); + if (hook == null) { + int b = Event.getTypeInt(eventName); + if (function != null) { + bind(b, nameSpace, eventName, null, data, function, -1); + } else { + unbind(b, nameSpace, eventName, null, null); + } + } else { + if (function != null) { + hook.add(this, nameSpace, data, function); + } else { + hook.remove(this, nameSpace, function); + } + } } } } - private void bind(int eventbits, String namespace, String eventName, String originalEventType, + public void bind(int eventbits, String namespace, String eventName, String originalEventType, Object data, Function function, int times) { - if (function == null) { - unbind(eventbits, namespace, eventName, originalEventType, null); - return; - } - sink(eventbits, eventName); - elementEvents.add(new BindFunction(eventbits, eventName, namespace, originalEventType, function, data, times)); } @@ -547,15 +588,17 @@ public class EventsListener implements EventListener { //handle special event like mouseenter or mouseleave SpecialEvent hook = special.get(eventName); - eventName = hook != null ? hook.getDelegateType() : eventName; - String originalEventName = hook != null ? hook.getOriginalType() : null; - + if (hook != null) { + hook.remove(this, nameSpace, null); + if (!hook.hasHandlers(this)) { + hook.tearDown(this); + } + // TODO: MCM handle correctly this + return; + } int b = Event.getTypeInt(eventName); - - die(b, nameSpace, eventName, originalEventName, cssSelector); + die(b, nameSpace, eventName, null, cssSelector); } - - } public void die(int eventbits, String nameSpace, String eventName, String originalEventName, @@ -607,13 +650,10 @@ public class EventsListener implements EventListener { public void dispatchEvent(Event event) { String ename = event.getType(); int etype = Event.getTypeInt(ename); - String originalEventType = GqEvent.getOriginalEventType(event); Object[] handlerData = $(element).data(EVENT_DATA); - for (int i = 0, l = elementEvents.length(); i < l; i++) { BindFunction listener = elementEvents.get(i); - if (listener != null && (listener.hasEventType(etype) || listener.isTypeOf(ename)) - && (originalEventType == null || originalEventType.equals(listener.getOriginalEventType()))) { + if (listener != null && (listener.hasEventType(etype) || listener.isTypeOf(ename))) { if (!listener.fire(event, handlerData)) { event.stopPropagation(); event.preventDefault(); @@ -649,13 +689,16 @@ public class EventsListener implements EventListener { //handle special event like mouseenter or mouseleave SpecialEvent hook = special.get(eventName); - eventName = hook != null ? hook.getDelegateType() : eventName; - String originalEventName = hook != null ? hook.getOriginalType() : null; + if (hook != null) { +// eventName = hook != null ? hook.getDelegateType() : eventName; +// String originalEventName = hook != null ? hook.getOriginalType() : null; + // FIXME: MCM handle live + return; + } int b = Event.getTypeInt(eventName); for (Function function : funcs) { - Function handler = hook != null ? hook.createDelegateHandler(function) : function; - live(b, nameSpace, eventName, originalEventName, cssSelector, data, handler); + live(b, nameSpace, eventName, null, cssSelector, data, function); } } } @@ -730,13 +773,17 @@ public class EventsListener implements EventListener { public void unbind(int eventbits) { unbind(eventbits, null, null, null, null); } - + public void unbind(int eventbits, String namespace, String eventName, String originalEventType, Function f) { + elementEvents = unbindFunctions(elementEvents, eventbits, namespace, eventName, originalEventType, f); + } + public static JsObjectArray unbindFunctions(JsObjectArray list, + int eventbits, String namespace, String eventName, String originalEventType, Function f) { JsObjectArray newList = JsObjectArray.createArray().cast(); - for (int i = 0; i < elementEvents.length(); i++) { - BindFunction listener = elementEvents.get(i); + for (int i = 0; i < list.length(); i++) { + BindFunction listener = list.get(i); boolean matchNS = isNullOrEmpty(namespace) || listener.nameSpace.equals(namespace); boolean matchEV = eventbits <= 0 || listener.hasEventType(eventbits); @@ -748,7 +795,6 @@ public class EventsListener implements EventListener { if (matchNS && matchEV && matchEVN && matchFC && matchOEVT) { int currentEventbits = listener.unsink(eventbits); - if (currentEventbits == 0) { // the BindFunction doesn't listen anymore on any events continue; @@ -757,11 +803,10 @@ public class EventsListener implements EventListener { newList.add(listener); } - elementEvents = newList; - + return newList; } - private boolean isNullOrEmpty(String s) { + private static boolean isNullOrEmpty(String s) { return s == null || s.isEmpty(); } @@ -783,13 +828,27 @@ public class EventsListener implements EventListener { } //handle special event - SpecialEvent hook = special.get(eventName); - eventName = hook != null ? hook.getDelegateType() : eventName; - String originalEventName = hook != null ? hook.getOriginalType() : null; - + // TODO(manolo): maybe we can remove this + if (!isNullOrEmpty(nameSpace) && isNullOrEmpty(eventName)) { + for (SpecialEvent hook : special.values()) { + hook.remove(this, nameSpace, f); + if (!hook.hasHandlers(this)) { + hook.tearDown(this); + } + } + } else { + SpecialEvent hook = special.get(eventName); + if (hook != null) { + hook.remove(this, nameSpace, f); + if (!hook.hasHandlers(this)) { + hook.tearDown(this); + } + return; + } + } + int b = Event.getTypeInt(eventName); - - unbind(b, nameSpace, eventName, originalEventName, f); + unbind(b, nameSpace, eventName, null, f); } } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/GqEvent.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/GqEvent.java index 1a92374f..d6475c1f 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/GqEvent.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/GqEvent.java @@ -23,14 +23,6 @@ import com.google.gwt.user.client.Event; */ public class GqEvent extends Event { - public static native void setOriginalEventType(NativeEvent evt, String originalEventName)/*-{ - evt["__gwtquery_originalEventName"] = originalEventName; - }-*/; - - public static native String getOriginalEventType(Event evt)/*-{ - return evt["__gwtquery_originalEventName"] || null; - }-*/; - // Gwt Events class has not this event defined, // so we have to select one power of 2 which is unused in Event class public static int ONSUBMIT = 0x10000000; diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEventsTestGwt.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEventsTestGwt.java index 98700235..33e185e3 100644 --- a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEventsTestGwt.java +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEventsTestGwt.java @@ -43,6 +43,7 @@ import com.google.gwt.query.client.plugins.Events; import com.google.gwt.query.client.plugins.events.EventsListener; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.Timer; +import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.RootPanel; @@ -383,7 +384,7 @@ public class GQueryEventsTestGwt extends GWTTestCase { $("p", e).click(); assertEquals("white", $("p", e).css("color", false)); - // hover (mouseover, mouseout) + // hover (mouseenter, mouseleave) $("p", e).hover(new Function() { public void f(Element elem) { $(elem).css(CSS.BACKGROUND_COLOR.with(RGBColor.YELLOW)); @@ -397,6 +398,11 @@ public class GQueryEventsTestGwt extends GWTTestCase { assertEquals("yellow", $("p", e).css("background-color", false)); $("p", e).trigger(Event.ONMOUSEOUT); assertEquals("white", $("p", e).css("background-color", false)); + + $("p", e).css(CSS.COLOR.with(RGBColor.WHITE)); + $("p", e).hover(null, null); + $("p", e).trigger(Event.ONMOUSEOVER); + assertEquals("white", $("p", e).css("background-color", false)); // key events $(e).html(""); -- cgit v1.2.3 From 5d055dc9125c18a83543b87cd2baf11db8837a0f Mon Sep 17 00:00:00 2001 From: Manolo Carrasco Date: Sun, 21 Dec 2014 09:18:17 +0100 Subject: Original event names are not needed any more :-) --- .../google/gwt/query/client/plugins/Events.java | 6 +- .../client/plugins/events/EventsListener.java | 166 ++++++++++----------- 2 files changed, 78 insertions(+), 94 deletions(-) (limited to 'gwtquery-core') 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 a16230f0..88c87413 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 @@ -110,7 +110,7 @@ public class Events extends GQuery { public GQuery die(int eventbits, String nameSpace) { EventsListener.getInstance(Element.is(currentContext) ? (Element) currentContext : body).die( - eventbits, nameSpace, null, null, currentSelector); + eventbits, nameSpace, null, currentSelector); return this; } @@ -137,7 +137,7 @@ public class Events extends GQuery { public GQuery live(int eventbits, String nameSpace, final Object data, Function... funcs) { EventsListener.getInstance(Element.is(currentContext) ? (Element) currentContext : body).live( - eventbits, nameSpace, null, null, currentSelector, data, funcs); + eventbits, nameSpace, null, currentSelector, data, funcs); return this; } @@ -337,7 +337,7 @@ public class Events extends GQuery { public Events unbind(int eventbits, String name, Function f) { for (Element e : elements()) { if (isEventCapable(e)) { - EventsListener.getInstance(e).unbind(eventbits, name, null, null, f); + EventsListener.getInstance(e).unbind(eventbits, name, null, f); } } return this; 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 94182385..903bfbfe 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 @@ -47,16 +47,30 @@ import java.util.List; public class EventsListener implements EventListener { public interface SpecialEvent { + /** + * The last unbind call triggers the tearDown method. + */ boolean tearDown(EventsListener l); + /** + * When the first event handler is bound for an EventsListener + * gQuery executes the setup function. + */ boolean setup(EventsListener l); + /** + * For each unbind call the remove function is called. + */ boolean remove(EventsListener l, String nameSpace, Function f); + /** + * For each bind call the add function is called. + */ boolean add(EventsListener l, String nameSpace, Object data, Function f); - String getDelegateType(); - + /** + * Return true if there are handlers bound to this special event. + */ boolean hasHandlers(EventsListener l); } @@ -64,17 +78,17 @@ public class EventsListener implements EventListener { * Used for simulating mouseenter and mouseleave events */ public static class MouseSpecialEvent implements SpecialEvent { - private String originalType; + private String type; private String delegateType; - - HashMap handlers = new HashMap(); - + + HashMap registeredHandlers = new HashMap(); + private class MouseSpecialFunction extends Function { final EventsListener listener; public MouseSpecialFunction(EventsListener l) { listener = l; } - + public boolean f(Event e, Object... arg) { EventTarget eventTarget = e.getCurrentEventTarget(); Element target = eventTarget != null ? eventTarget. cast() : null; @@ -85,7 +99,7 @@ public class EventsListener implements EventListener { if (related == null || (related != target && !GQuery.contains(target, related))) { for (int i = 0, l = listener.elementEvents.length(); i < l ; i ++) { BindFunction function = listener.elementEvents.get(i); - if (function.isTypeOf(originalType) && !function.fire(e, arg)) { + if (function.isTypeOf(type) && !function.fire(e, arg)) { return false; } } @@ -93,48 +107,41 @@ public class EventsListener implements EventListener { return true; }; } - - public MouseSpecialEvent(String originalType, String delegateType) { - this.originalType = originalType; + + public MouseSpecialEvent(String type, String delegateType) { + this.type = type; this.delegateType = delegateType; } @Override public boolean add(EventsListener l, String nameSpace, Object data, Function f) { - l.bind(BITLESS, nameSpace, originalType, null, null, f, -1); + l.bind(BITLESS, nameSpace, type, null, f, -1); return false; } @Override public boolean remove(EventsListener l, String nameSpace, Function f) { - l.elementEvents = unbindFunctions(l.elementEvents, BITLESS, nameSpace, delegateType, null, f); + l.elementEvents = unbindFunctions(l.elementEvents, BITLESS, nameSpace, null, f); return false; } - + @Override public boolean setup(EventsListener l) { MouseSpecialFunction handler = new MouseSpecialFunction(l); - handlers.put(l, handler); - int b = Event.getTypeInt(delegateType); - l.bind(b, null, delegateType, originalType, null, handler, -1); + registeredHandlers.put(l, handler); + l.bind(Event.getTypeInt(delegateType), null, delegateType, null, handler, -1); return false; } - + @Override public boolean tearDown(EventsListener l) { - MouseSpecialFunction handler = handlers.remove(l); + MouseSpecialFunction handler = registeredHandlers.remove(l); if (handler != null) { - int b = Event.getTypeInt(delegateType); - l.unbind(b, null, delegateType, originalType, handler); + l.unbind(Event.getTypeInt(delegateType), null, delegateType, handler); } return false; } - @Override - public String getDelegateType() { - return delegateType; - } - @Override public boolean hasHandlers(EventsListener l) { for (int i = 0, j = l.elementEvents.length(); i < j; i++) { @@ -146,26 +153,23 @@ public class EventsListener implements EventListener { return false; } } - - private static class BindFunction { + private static class BindFunction { Object data; Function function; String nameSpace; - String originalEventType; int times; int type; String eventName; - BindFunction(int type, String eventName, String nameSpace, String originalEventType, - Function function, Object data, int times) { + BindFunction(int type, String eventName, String nameSpace, Function function, Object data, + int times) { this.times = times; this.eventName = eventName; this.type = type; this.function = function; this.data = data; -// this.originalEventType = originalEventType; this.nameSpace = nameSpace != null ? nameSpace : ""; } @@ -195,7 +199,7 @@ public class EventsListener implements EventListener { public boolean hasEventType(int etype) { return type != BITLESS && etype != BITLESS && (type & etype) != 0; } - + public boolean isTypeOf(String eName) { return eventName != null && eventName.equalsIgnoreCase(eName); @@ -226,10 +230,6 @@ public class EventsListener implements EventListener { assert f != null : "function f cannot be null"; return f.equals(function); } - - public Object getOriginalEventType() { - return originalEventType; - } } /** @@ -241,12 +241,12 @@ public class EventsListener implements EventListener { JsNamedArray> bindFunctionBySelector; LiveBindFunction(String eventName, String namespace, Object data) { - super(BITLESS, eventName, namespace, null, null, data, -1); + super(BITLESS, eventName, namespace, null, data, -1); clean(); } LiveBindFunction(int type, String namespace, Object data) { - super(type, null, namespace, null, null, data, -1); + super(type, null, namespace, null, data, -1); clean(); } @@ -336,8 +336,8 @@ public class EventsListener implements EventListener { /** * Remove the BindFunction associated to this cssSelector */ - public void removeBindFunctionForSelector(String cssSelector, String nameSpace, String originalEventName) { - if (nameSpace == null && originalEventName == null) { + public void removeBindFunctionForSelector(String cssSelector, String nameSpace) { + if (nameSpace == null) { bindFunctionBySelector.delete(cssSelector); } else { JsObjectArray functions = bindFunctionBySelector.get(cssSelector); @@ -349,10 +349,7 @@ public class EventsListener implements EventListener { for (int i = 0; i < functions.length(); i++) { BindFunction f = functions.get(i); - boolean matchNamespace = nameSpace == null || nameSpace.equals(f.nameSpace); - boolean matchOriginalEventName = originalEventName == null || originalEventName.equals(f.originalEventType); - - if (!matchNamespace || !matchOriginalEventName) { + if (nameSpace != null && !nameSpace.equals(f.nameSpace)) { newFunctions.add(f); } } @@ -517,9 +514,8 @@ public class EventsListener implements EventListener { } } - public void bind(int eventbits, String namespace, String originalEventType, Object data, - Function function, int times) { - bind(eventbits, namespace, null, originalEventType, data, function, times); + public void bind(int eventbits, String namespace, Object data, Function function, int times) { + bind(eventbits, namespace, null, data, function, times); } public void bind(String events, final Object data, Function... funcs) { @@ -548,9 +544,9 @@ public class EventsListener implements EventListener { if (hook == null) { int b = Event.getTypeInt(eventName); if (function != null) { - bind(b, nameSpace, eventName, null, data, function, -1); + bind(b, nameSpace, eventName, data, function, -1); } else { - unbind(b, nameSpace, eventName, null, null); + unbind(b, nameSpace, eventName, null); } } else { if (function != null) { @@ -563,11 +559,9 @@ public class EventsListener implements EventListener { } } - public void bind(int eventbits, String namespace, String eventName, String originalEventType, - Object data, Function function, int times) { + public void bind(int eventbits, String namespace, String eventName, Object data, Function function, int times) { sink(eventbits, eventName); - elementEvents.add(new BindFunction(eventbits, eventName, namespace, originalEventType, - function, data, times)); + elementEvents.add(new BindFunction(eventbits, eventName, namespace, function, data, times)); } public void die(String eventNames, String cssSelector) { @@ -597,23 +591,21 @@ public class EventsListener implements EventListener { return; } int b = Event.getTypeInt(eventName); - die(b, nameSpace, eventName, null, cssSelector); + die(b, nameSpace, eventName, cssSelector); } } - public void die(int eventbits, String nameSpace, String eventName, String originalEventName, - String cssSelector) { + public void die(int eventbits, String nameSpace, String eventName, String cssSelector) { if (eventbits <= 0) { if (eventName != null && eventName.length() > 0) { LiveBindFunction liveBindFunction = liveBindFunctionByEventName.get(eventName); - maybeRemoveLiveBindFunction(liveBindFunction, cssSelector, BITLESS, eventName, nameSpace, - originalEventName); + maybeRemoveLiveBindFunction(liveBindFunction, cssSelector, BITLESS, eventName, nameSpace); } else { // if eventbits == -1 and eventName is null, remove all event handlers for this selector for (String k : liveBindFunctionByEventType.keys()) { int bits = Integer.parseInt(k); LiveBindFunction liveBindFunction = liveBindFunctionByEventType.get(bits); - maybeRemoveLiveBindFunction(liveBindFunction, cssSelector, bits, null, nameSpace, null); + maybeRemoveLiveBindFunction(liveBindFunction, cssSelector, bits, null, nameSpace); } for (String k : liveBindFunctionByEventName.keys()) { @@ -621,22 +613,20 @@ public class EventsListener implements EventListener { LiveBindFunction liveBindFunction = liveBindFunctionByEventName.get(realKey); if (liveBindFunction != null) { String eName = liveBindFunction.eventName; - maybeRemoveLiveBindFunction(liveBindFunction, cssSelector, BITLESS, eName, - nameSpace, originalEventName); + maybeRemoveLiveBindFunction(liveBindFunction, cssSelector, BITLESS, eName, nameSpace); } } } } else { LiveBindFunction liveBindFunction = liveBindFunctionByEventType.get(eventbits); - maybeRemoveLiveBindFunction(liveBindFunction, cssSelector, eventbits, null, nameSpace, - originalEventName); + maybeRemoveLiveBindFunction(liveBindFunction, cssSelector, eventbits, null, nameSpace); } } private void maybeRemoveLiveBindFunction(LiveBindFunction liveBindFunction, String cssSelector, - int eventbits, String eventName, String nameSpace, String originalEventName) { + int eventbits, String eventName, String nameSpace) { if (liveBindFunction != null) { - liveBindFunction.removeBindFunctionForSelector(cssSelector, nameSpace, originalEventName); + liveBindFunction.removeBindFunctionForSelector(cssSelector, nameSpace); if (liveBindFunction.isEmpty()){ if (eventbits != BITLESS) { liveBindFunctionByEventType.remove(eventbits); @@ -690,30 +680,28 @@ public class EventsListener implements EventListener { //handle special event like mouseenter or mouseleave SpecialEvent hook = special.get(eventName); if (hook != null) { -// eventName = hook != null ? hook.getDelegateType() : eventName; -// String originalEventName = hook != null ? hook.getOriginalType() : null; // FIXME: MCM handle live return; } int b = Event.getTypeInt(eventName); for (Function function : funcs) { - live(b, nameSpace, eventName, null, cssSelector, data, function); + live(b, nameSpace, eventName, cssSelector, data, function); } } } - public void live(int eventbits, String nameSpace, String eventName, String originalEventName, - String cssSelector, Object data, Function... funcs) { + public void live(int eventbits, String nameSpace, String eventName, String cssSelector, + Object data, Function... funcs) { if (eventbits != BITLESS) { - liveBitEvent(eventbits, nameSpace, originalEventName, cssSelector, data, funcs); + liveBitEvent(eventbits, nameSpace, cssSelector, data, funcs); } else { - liveBitlessEvent(eventName, nameSpace, originalEventName, cssSelector, data, funcs); + liveBitlessEvent(eventName, nameSpace, cssSelector, data, funcs); } } - private void liveBitlessEvent(String eventName, String nameSpace, String originalEventName, - String cssSelector, Object data, Function... funcs) { + private void liveBitlessEvent(String eventName, String nameSpace, String cssSelector, + Object data, Function... funcs) { LiveBindFunction liveBindFunction = liveBindFunctionByEventName.get(eventName); if (liveBindFunction == null) { @@ -725,12 +713,12 @@ public class EventsListener implements EventListener { for (Function f : funcs) { liveBindFunction.addBindFunctionForSelector(cssSelector, new BindFunction(BITLESS, eventName, - nameSpace, originalEventName, f, data, -1)); + nameSpace, f, data, -1)); } } - private void liveBitEvent(int eventbits, String nameSpace, String originalEventName, - String cssSelector, Object data, Function... funcs) { + private void liveBitEvent(int eventbits, String nameSpace, String cssSelector, Object data, + Function... funcs) { for (int i = 0; i < 28; i++) { int event = (int) Math.pow(2, i); if ((eventbits & event) == event) { @@ -746,7 +734,7 @@ public class EventsListener implements EventListener { for (Function f : funcs) { liveBindFunction.addBindFunctionForSelector(cssSelector, new BindFunction(event, - null, nameSpace, originalEventName, f, data, -1)); + null, nameSpace, f, data, -1)); } } } @@ -771,16 +759,15 @@ public class EventsListener implements EventListener { } public void unbind(int eventbits) { - unbind(eventbits, null, null, null, null); + unbind(eventbits, null, null, null); } - - public void unbind(int eventbits, String namespace, String eventName, String originalEventType, - Function f) { - elementEvents = unbindFunctions(elementEvents, eventbits, namespace, eventName, originalEventType, f); + + public void unbind(int eventbits, String namespace, String eventName, Function f) { + elementEvents = unbindFunctions(elementEvents, eventbits, namespace, eventName, f); } public static JsObjectArray unbindFunctions(JsObjectArray list, - int eventbits, String namespace, String eventName, String originalEventType, Function f) { + int eventbits, String namespace, String eventName, Function f) { JsObjectArray newList = JsObjectArray.createArray().cast(); for (int i = 0; i < list.length(); i++) { BindFunction listener = list.get(i); @@ -788,12 +775,9 @@ public class EventsListener implements EventListener { boolean matchNS = isNullOrEmpty(namespace) || listener.nameSpace.equals(namespace); boolean matchEV = eventbits <= 0 || listener.hasEventType(eventbits); boolean matchEVN = matchEV || listener.isTypeOf(eventName); - boolean matchOEVT = (isNullOrEmpty(eventName) && !isNullOrEmpty(namespace) && matchNS) - || (originalEventType == null && listener.getOriginalEventType() == null) - || (originalEventType != null && originalEventType.equals(listener.getOriginalEventType())); boolean matchFC = f == null || listener.isEquals(f); - if (matchNS && matchEV && matchEVN && matchFC && matchOEVT) { + if (matchNS && matchEV && matchEVN && matchFC) { int currentEventbits = listener.unsink(eventbits); if (currentEventbits == 0) { // the BindFunction doesn't listen anymore on any events @@ -846,9 +830,9 @@ public class EventsListener implements EventListener { return; } } - + int b = Event.getTypeInt(eventName); - unbind(b, nameSpace, eventName, null, f); + unbind(b, nameSpace, eventName, f); } } -- cgit v1.2.3 From bc07b4d9a8393b3a75fbdc0162e3f5c90de8d53d Mon Sep 17 00:00:00 2001 From: Manolo Carrasco Date: Sun, 21 Dec 2014 09:54:19 +0100 Subject: Unify code related with eventNames split --- .../client/plugins/events/EventsListener.java | 170 +++++++-------------- 1 file changed, 56 insertions(+), 114 deletions(-) (limited to 'gwtquery-core') 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 903bfbfe..e0b9027d 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 @@ -61,12 +61,12 @@ public class EventsListener implements EventListener { /** * For each unbind call the remove function is called. */ - boolean remove(EventsListener l, String nameSpace, Function f); + void remove(EventsListener l, String nameSpace, Function f); /** * For each bind call the add function is called. */ - boolean add(EventsListener l, String nameSpace, Object data, Function f); + void add(EventsListener l, String nameSpace, Object data, Function f); /** * Return true if there are handlers bound to this special event. @@ -114,15 +114,13 @@ public class EventsListener implements EventListener { } @Override - public boolean add(EventsListener l, String nameSpace, Object data, Function f) { - l.bind(BITLESS, nameSpace, type, null, f, -1); - return false; + public void add(EventsListener l, String nameSpace, Object data, Function f) { + // Nothing to do, let gQuery use default elementEvents mechanism } @Override - public boolean remove(EventsListener l, String nameSpace, Function f) { - l.elementEvents = unbindFunctions(l.elementEvents, BITLESS, nameSpace, null, f); - return false; + public void remove(EventsListener l, String nameSpace, Function f) { + // Nothing to do, let gQuery use default elementEvents mechanism } @Override @@ -154,6 +152,29 @@ public class EventsListener implements EventListener { } } + /** + * Utility class to split a list of events with or without namespaces + */ + private static class EvPart { + String nameSpace; + String eventName; + public EvPart(String n, String e) { + nameSpace = n; + eventName = e; + } + + static List split(String events) { + List ret = new ArrayList(); + String[] parts = events.split("[\\s,]+"); + for (String event : parts) { + String[] tmp = event.split("\\.", 2); + String eventName = tmp[0]; + String nameSpace = tmp.length > 1 ? tmp[1] : null; + ret.add(new EvPart(nameSpace, eventName)); + } + return ret; + } + } private static class BindFunction { Object data; @@ -519,41 +540,20 @@ public class EventsListener implements EventListener { } public void bind(String events, final Object data, Function... funcs) { - String[] parts = events.split("[\\s,]+"); - - for (String event : parts) { - - String nameSpace = null; - String eventName = event; - - //seperate possible namespace - //jDramaix: I removed old regex ^([^.]*)\.?(.*$) because it didn't work on IE8... - String[] subparts = event.split("\\.", 2); - - if (subparts.length == 2){ - nameSpace = subparts[1]; - eventName = subparts[0]; - } + if (funcs.length == 0 || funcs[0] == null) { + unbind(events, null); + } - //handle special event like mouseenter or mouseleave - SpecialEvent hook = special.get(eventName); + for (EvPart ev : EvPart.split(events)) { + SpecialEvent hook = special.get(ev.eventName); if (hook != null && !hook.hasHandlers(this)) { hook.setup(this); } for (Function function : funcs) { - if (hook == null) { - int b = Event.getTypeInt(eventName); - if (function != null) { - bind(b, nameSpace, eventName, data, function, -1); - } else { - unbind(b, nameSpace, eventName, null); - } - } else { - if (function != null) { - hook.add(this, nameSpace, data, function); - } else { - hook.remove(this, nameSpace, function); - } + int b = Event.getTypeInt(ev.eventName); + bind(b, ev.nameSpace, ev.eventName, data, function, -1); + if (hook != null) { + hook.add(this, ev.nameSpace, data, function); } } } @@ -564,34 +564,19 @@ public class EventsListener implements EventListener { elementEvents.add(new BindFunction(eventbits, eventName, namespace, function, data, times)); } - public void die(String eventNames, String cssSelector) { - String[] parts = eventNames.split("[\\s,]+"); - - for (String event : parts) { - String nameSpace = null; - String eventName = event; - - //seperate possible namespace - //jDramaix: I removed old regex ^([^.]*)\.?(.*$) because it didn't work on IE8... - String[] subparts = event.split("\\.", 2); - - if (subparts.length == 2) { - nameSpace = subparts[1]; - eventName = subparts[0]; - } - - //handle special event like mouseenter or mouseleave - SpecialEvent hook = special.get(eventName); + public void die(String events, String cssSelector) { + for (EvPart ev : EvPart.split(events)) { + SpecialEvent hook = special.get(ev.eventName); if (hook != null) { - hook.remove(this, nameSpace, null); + hook.remove(this, ev.nameSpace, null); if (!hook.hasHandlers(this)) { hook.tearDown(this); } // TODO: MCM handle correctly this return; } - int b = Event.getTypeInt(eventName); - die(b, nameSpace, eventName, cssSelector); + int b = Event.getTypeInt(ev.eventName); + die(b, ev.nameSpace, ev.eventName, cssSelector); } } @@ -661,32 +646,16 @@ public class EventsListener implements EventListener { } public void live(String events, String cssSelector, Object data, Function... funcs) { - - String[] parts = events.split("[\\s,]+"); - - for (String event : parts) { - - String nameSpace = null; - String eventName = event; - - - String[] subparts = event.split("\\.", 2); - - if (subparts.length == 2) { - nameSpace = subparts[1]; - eventName = subparts[0]; - } - - //handle special event like mouseenter or mouseleave - SpecialEvent hook = special.get(eventName); + for (EvPart ev : EvPart.split(events)) { + SpecialEvent hook = special.get(ev.eventName); if (hook != null) { // FIXME: MCM handle live return; } - int b = Event.getTypeInt(eventName); + int b = Event.getTypeInt(ev.eventName); for (Function function : funcs) { - live(b, nameSpace, eventName, cssSelector, data, function); + live(b, ev.nameSpace, ev.eventName, cssSelector, data, function); } } } @@ -795,44 +764,17 @@ public class EventsListener implements EventListener { } public void unbind(String events, Function f) { - - String[] parts = events.split("[\\s,]+"); - - for (String event : parts) { - String nameSpace = null; - String eventName = event; - - //seperate possible namespace - //jDramaix: I removed old regex ^([^.]*)\.?(.*$) because it didn't work on IE8... - String[] subparts = event.split("\\.", 2); - - if (subparts.length == 2){ - nameSpace = subparts[1]; - eventName = subparts[0]; - } - + for (EvPart ev : EvPart.split(events)) { + int b = Event.getTypeInt(ev.eventName); + unbind(b, ev.nameSpace, ev.eventName, f); //handle special event - // TODO(manolo): maybe we can remove this - if (!isNullOrEmpty(nameSpace) && isNullOrEmpty(eventName)) { - for (SpecialEvent hook : special.values()) { - hook.remove(this, nameSpace, f); - if (!hook.hasHandlers(this)) { - hook.tearDown(this); - } - } - } else { - SpecialEvent hook = special.get(eventName); - if (hook != null) { - hook.remove(this, nameSpace, f); - if (!hook.hasHandlers(this)) { - hook.tearDown(this); - } - return; + SpecialEvent hook = special.get(ev.eventName); + if (hook != null) { + hook.remove(this, ev.nameSpace, f); + if (!hook.hasHandlers(this)) { + hook.tearDown(this); } } - - int b = Event.getTypeInt(eventName); - unbind(b, nameSpace, eventName, f); } } -- cgit v1.2.3 From 3019c9d1418d51d78f6852df8fc4dafd78b6b57f Mon Sep 17 00:00:00 2001 From: Manolo Carrasco Date: Sun, 21 Dec 2014 10:36:43 +0100 Subject: Handle live and die special events --- .../client/plugins/events/EventsListener.java | 14 +++--- .../gwt/query/client/plugins/events/GqEvent.java | 1 - .../gwt/query/client/GQueryEventsTestGwt.java | 56 ++++++++++++++++++---- 3 files changed, 55 insertions(+), 16 deletions(-) (limited to 'gwtquery-core') 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 e0b9027d..a9dae295 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 @@ -566,17 +566,15 @@ public class EventsListener implements EventListener { public void die(String events, String cssSelector) { for (EvPart ev : EvPart.split(events)) { + die(Event.getTypeInt(ev.eventName), ev.nameSpace, ev.eventName, cssSelector); + SpecialEvent hook = special.get(ev.eventName); if (hook != null) { hook.remove(this, ev.nameSpace, null); if (!hook.hasHandlers(this)) { hook.tearDown(this); } - // TODO: MCM handle correctly this - return; } - int b = Event.getTypeInt(ev.eventName); - die(b, ev.nameSpace, ev.eventName, cssSelector); } } @@ -648,14 +646,16 @@ public class EventsListener implements EventListener { public void live(String events, String cssSelector, Object data, Function... funcs) { for (EvPart ev : EvPart.split(events)) { SpecialEvent hook = special.get(ev.eventName); - if (hook != null) { - // FIXME: MCM handle live - return; + if (hook != null && !hook.hasHandlers(this)) { + hook.setup(this); } int b = Event.getTypeInt(ev.eventName); for (Function function : funcs) { live(b, ev.nameSpace, ev.eventName, cssSelector, data, function); + if (hook != null) { + hook.add(this, ev.nameSpace, data, function); + } } } } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/GqEvent.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/GqEvent.java index d6475c1f..e98a5f4c 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/GqEvent.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/GqEvent.java @@ -1,7 +1,6 @@ package com.google.gwt.query.client.plugins.events; import com.google.gwt.dom.client.Element; -import com.google.gwt.dom.client.NativeEvent; import com.google.gwt.query.client.GQuery; import com.google.gwt.user.client.Event; diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEventsTestGwt.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEventsTestGwt.java index 33e185e3..6ec17595 100644 --- a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEventsTestGwt.java +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEventsTestGwt.java @@ -398,7 +398,7 @@ public class GQueryEventsTestGwt extends GWTTestCase { assertEquals("yellow", $("p", e).css("background-color", false)); $("p", e).trigger(Event.ONMOUSEOUT); assertEquals("white", $("p", e).css("background-color", false)); - + $("p", e).css(CSS.COLOR.with(RGBColor.WHITE)); $("p", e).hover(null, null); $("p", e).trigger(Event.ONMOUSEOVER); @@ -572,6 +572,46 @@ public class GQueryEventsTestGwt extends GWTTestCase { } + public void testLiveWithSpecial() { + $(e).html("
Content 1 blop
"); + + $(".clickable", e).live("mouseenter", new Function() { + public void f(Element e) { + $(e).css(CSS.COLOR.with(RGBColor.RED)); + } + }); + + $("#div1", e).addClass("clickable"); + $("#span1", e).mouseenter(); + assertEquals("red", $("#div1", e).css(CSS.COLOR, false)); + + $(".clickable", e).die("mouseenter"); + $("*", e).css(CSS.COLOR.with(RGBColor.BLACK)); + + $("#span1", e).mouseenter(); + assertEquals("black", $("#div1", e).css(CSS.COLOR, false)); + } + + public void testOnOffWithSpecial() { + $(e).html("
Content 1 blop
"); + + $(e).on("mouseenter", ".clickable", new Function() { + public void f(Element e) { + $(e).css(CSS.COLOR.with(RGBColor.RED)); + } + }); + + $("#div1", e).addClass("clickable"); + $("#span1", e).mouseenter(); + assertEquals("red", $("#div1", e).css(CSS.COLOR, false)); + + $(e).off("mouseenter", ".clickable"); + $("*", e).css(CSS.COLOR.with(RGBColor.BLACK)); + + $("#span1", e).mouseenter(); + assertEquals("black", $("#div1", e).css(CSS.COLOR, false)); + } + public void testLiveWithMultipleEvent() { $(e).html("
Content 1 blop
"); @@ -1204,10 +1244,10 @@ public class GQueryEventsTestGwt extends GWTTestCase { $(".mainDiv", e).click(); assertEquals("red", $(".mainDiv", e).css("color", false)); - + // reset $(".mainDiv", e).css("color", "black"); - + $(".mainDiv", e).off("click"); $(".mainDiv", e).click(); @@ -1225,7 +1265,7 @@ public class GQueryEventsTestGwt extends GWTTestCase { $(".mainDiv", e).click(); assertEquals("red", $(".mainDiv", e).css("color", false)); - + // reset $(".mainDiv", e).css("color", "black"); @@ -1279,7 +1319,7 @@ public class GQueryEventsTestGwt extends GWTTestCase { assertEquals("white", $(".mainDiv", e).css("background-color", false)); } - + public void testOnOffWithSelector() { $(e).html("
Content " + "0blop
" + @@ -1291,7 +1331,7 @@ public class GQueryEventsTestGwt extends GWTTestCase { $(e).css("color", "red"); } }); - + for (Element mainDiv : $(".mainDiv", e).elements()) { for (int i = 0; i < 3; i++) { @@ -1442,10 +1482,10 @@ public class GQueryEventsTestGwt extends GWTTestCase { $(b).trigger("custom"); assertEquals("200px", $("button").css("width", false)); } - + public void testIssue152() { $(e).html("
"); - final GQuery div = $(".mdiv", e); + final GQuery div = $(".mdiv", e); final int[] count = { 0 }; div.one(Event.ONCLICK, null, new Function() { public void f() { -- cgit v1.2.3 From a8511be680e954b370123bd4710dad29e220348d Mon Sep 17 00:00:00 2001 From: Manolo Carrasco Date: Sun, 21 Dec 2014 10:45:35 +0100 Subject: make hasHandlers public so as it can be used in plugins --- .../client/plugins/events/EventsListener.java | 35 +++++++++++----------- 1 file changed, 18 insertions(+), 17 deletions(-) (limited to 'gwtquery-core') 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 a9dae295..a7a65b43 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 @@ -142,13 +142,7 @@ public class EventsListener implements EventListener { @Override public boolean hasHandlers(EventsListener l) { - for (int i = 0, j = l.elementEvents.length(); i < j; i++) { - BindFunction function = l.elementEvents.get(i); - if (function.isTypeOf(delegateType)) { - return true; - } - } - return false; + return l.hasHandlers(BITLESS, type); } } @@ -732,15 +726,9 @@ public class EventsListener implements EventListener { } public void unbind(int eventbits, String namespace, String eventName, Function f) { - elementEvents = unbindFunctions(elementEvents, eventbits, namespace, eventName, f); - } - - public static JsObjectArray unbindFunctions(JsObjectArray list, - int eventbits, String namespace, String eventName, Function f) { JsObjectArray newList = JsObjectArray.createArray().cast(); - for (int i = 0; i < list.length(); i++) { - BindFunction listener = list.get(i); - + for (int i = 0; i < elementEvents.length(); i++) { + BindFunction listener = elementEvents.get(i); boolean matchNS = isNullOrEmpty(namespace) || listener.nameSpace.equals(namespace); boolean matchEV = eventbits <= 0 || listener.hasEventType(eventbits); boolean matchEVN = matchEV || listener.isTypeOf(eventName); @@ -753,10 +741,23 @@ public class EventsListener implements EventListener { continue; } } - newList.add(listener); } - return newList; + elementEvents = newList; + } + + /** + * Return true if the element is listening for the + * given eventBit or eventName. + */ + public boolean hasHandlers(int eventBits, String eventName) { + for (int i = 0, j = elementEvents.length(); i < j; i++) { + BindFunction function = elementEvents.get(i); + if (function.hasEventType(eventBits) || function.isTypeOf(eventName)) { + return true; + } + } + return false; } private static boolean isNullOrEmpty(String s) { -- cgit v1.2.3 From 38513d2716258a80605938ea165d4664bf03966b Mon Sep 17 00:00:00 2001 From: Manolo Carrasco Date: Sun, 21 Dec 2014 12:20:01 +0100 Subject: re-factor SpecialEffects in order to make easier new specials. - Implementing specials focusin focusout. Fixes #11 --- .../client/plugins/events/EventsListener.java | 105 ++++++++++++--------- .../gwt/query/client/GQueryEventsTestGwt.java | 23 ++++- 2 files changed, 84 insertions(+), 44 deletions(-) (limited to 'gwtquery-core') 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 a7a65b43..923d6b57 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 @@ -74,41 +74,12 @@ public class EventsListener implements EventListener { boolean hasHandlers(EventsListener l); } - /** - * Used for simulating mouseenter and mouseleave events - */ - public static class MouseSpecialEvent implements SpecialEvent { - private String type; - private String delegateType; - - HashMap registeredHandlers = new HashMap(); - - private class MouseSpecialFunction extends Function { - final EventsListener listener; - public MouseSpecialFunction(EventsListener l) { - listener = l; - } - - public boolean f(Event e, Object... arg) { - EventTarget eventTarget = e.getCurrentEventTarget(); - Element target = eventTarget != null ? eventTarget. cast() : null; - - EventTarget relatedEventTarget = e.getRelatedEventTarget(); - Element related = relatedEventTarget != null ? relatedEventTarget. cast() : null; + public static abstract class AbstractSpecialEvent implements SpecialEvent { + protected String type; + protected String delegateType; + protected Function handler = null; - if (related == null || (related != target && !GQuery.contains(target, related))) { - for (int i = 0, l = listener.elementEvents.length(); i < l ; i ++) { - BindFunction function = listener.elementEvents.get(i); - if (function.isTypeOf(type) && !function.fire(e, arg)) { - return false; - } - } - } - return true; - }; - } - - public MouseSpecialEvent(String type, String delegateType) { + public AbstractSpecialEvent(String type, String delegateType) { this.type = type; this.delegateType = delegateType; } @@ -125,18 +96,13 @@ public class EventsListener implements EventListener { @Override public boolean setup(EventsListener l) { - MouseSpecialFunction handler = new MouseSpecialFunction(l); - registeredHandlers.put(l, handler); l.bind(Event.getTypeInt(delegateType), null, delegateType, null, handler, -1); return false; } @Override public boolean tearDown(EventsListener l) { - MouseSpecialFunction handler = registeredHandlers.remove(l); - if (handler != null) { - l.unbind(Event.getTypeInt(delegateType), null, delegateType, handler); - } + l.unbind(Event.getTypeInt(delegateType), null, delegateType, handler); return false; } @@ -146,6 +112,45 @@ public class EventsListener implements EventListener { } } + /** + * Used for simulating mouseenter and mouseleave events + */ + public static class MouseSpecialEvent extends AbstractSpecialEvent { + public MouseSpecialEvent(final String type, String delegateType) { + super(type, delegateType); + handler = new Function() { + public boolean f(Event e, Object... arg) { + EventTarget eventTarget = e.getCurrentEventTarget(); + Element target = eventTarget != null ? eventTarget. cast() : null; + + EventTarget relatedEventTarget = e.getRelatedEventTarget(); + Element related = relatedEventTarget != null ? relatedEventTarget. cast() : null; + + if (related == null || (related != target && !GQuery.contains(target, related))) { + getInstance(target).dispatchEvent(e, type); + } + return true; + }; + }; + } + } + + /** + * Used for simulating mouseenter and mouseleave events + */ + public static class FocusSpecialEvent extends AbstractSpecialEvent { + public FocusSpecialEvent(final String type, String delegateType) { + super(type, delegateType); + handler = new Function() { + public boolean f(Event e, Object... arg) { + setEvent(e); + getInstance(getElement()).dispatchEvent(e, type); + return true; + }; + }; + } + } + /** * Utility class to split a list of events with or without namespaces */ @@ -427,6 +432,8 @@ public class EventsListener implements EventListener { public static String MOUSEENTER = "mouseenter"; public static String MOUSELEAVE = "mouseleave"; + public static String FOCUSIN = "focusin"; + public static String FOCUSOUT = "focusout"; public static HashMap special; @@ -434,6 +441,8 @@ public class EventsListener implements EventListener { special = new HashMap(); special.put(MOUSEENTER, new MouseSpecialEvent(MOUSEENTER, "mouseover")); special.put(MOUSELEAVE, new MouseSpecialEvent(MOUSELEAVE, "mouseout")); + special.put(FOCUSIN, new MouseSpecialEvent(FOCUSIN, "focus")); + special.put(FOCUSOUT, new MouseSpecialEvent(FOCUSOUT, "blur")); } public static void clean(Element e) { @@ -614,13 +623,23 @@ public class EventsListener implements EventListener { } } + /** + * Dispatch an event in this element. + */ public void dispatchEvent(Event event) { - String ename = event.getType(); - int etype = Event.getTypeInt(ename); + dispatchEvent(event, event.getType()); + } + + /** + * Dispatch an event in this element but changing the type, + * it's useful for special events. + */ + public void dispatchEvent(Event event, String eventName) { + int etype = Event.getTypeInt(eventName); Object[] handlerData = $(element).data(EVENT_DATA); for (int i = 0, l = elementEvents.length(); i < l; i++) { BindFunction listener = elementEvents.get(i); - if (listener != null && (listener.hasEventType(etype) || listener.isTypeOf(ename))) { + if (listener != null && (listener.hasEventType(etype) || listener.isTypeOf(eventName))) { if (!listener.fire(event, handlerData)) { event.stopPropagation(); event.preventDefault(); diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEventsTestGwt.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEventsTestGwt.java index 6ec17595..08777f32 100644 --- a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEventsTestGwt.java +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEventsTestGwt.java @@ -43,7 +43,6 @@ import com.google.gwt.query.client.plugins.Events; import com.google.gwt.query.client.plugins.events.EventsListener; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.Timer; -import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.RootPanel; @@ -456,6 +455,28 @@ public class GQueryEventsTestGwt extends GWTTestCase { assertEquals("", $("p", e).css("border", false)); } + @DoNotRunWith({Platform.HtmlUnitLayout}) + public void testSpecialFocusInOut() { + $(e).html("

Content

"); + $("p", e).on(EventsListener.FOCUSIN, new Function() { + public void f(Element elem) { + GQuery.console.log("focus"); + $(elem).css("background-color", "red"); + } + }); + $("p", e).focus(); + assertEquals("red", $("p", e).css("background-color", false)); + + // blur + $("p", e).on(EventsListener.FOCUSOUT, new Function() { + public void f(Element elem) { + $(elem).css("background-color", "white"); + } + }); + $("p", e).blur(); + assertEquals("white", $("p", e).css("background-color", false)); + } + public void testLazyMethods() { $(e).css(CSS.COLOR.with(RGBColor.WHITE)); assertEquals("white", $(e).css("color", false)); -- cgit v1.2.3 From 4b23f93310daea8dbca6aa45e2a0c44816527ec3 Mon Sep 17 00:00:00 2001 From: Manolo Carrasco Date: Sun, 21 Dec 2014 13:15:05 +0100 Subject: Extracted SpecialEvent interface to its own class Handle return values of setup and tearDown Changed SpecialEvent API so as we use the Element instead of the EventListener --- .../google/gwt/query/client/plugins/Events.java | 2 - .../gwt/query/client/plugins/LazyEvents.java | 1 - .../client/plugins/events/EventsListener.java | 131 ++++++--------------- .../query/client/plugins/events/SpecialEvent.java | 106 +++++++++++++++++ 4 files changed, 142 insertions(+), 98 deletions(-) create mode 100644 gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/SpecialEvent.java (limited to 'gwtquery-core') 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 88c87413..7f2127d1 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 @@ -21,8 +21,6 @@ import com.google.gwt.query.client.Function; import com.google.gwt.query.client.GQuery; import com.google.gwt.query.client.js.JsUtils; import com.google.gwt.query.client.plugins.events.EventsListener; -import com.google.gwt.query.client.plugins.events.EventsListener.SpecialEvent; -import com.google.gwt.query.client.plugins.events.GqEvent; import com.google.gwt.user.client.Event; /** diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/LazyEvents.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/LazyEvents.java index 081e1702..98eaf97e 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/LazyEvents.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/LazyEvents.java @@ -20,7 +20,6 @@ import com.google.gwt.query.client.Function; import com.google.gwt.query.client.GQuery; import com.google.gwt.query.client.js.JsUtils; import com.google.gwt.query.client.plugins.events.EventsListener; -import com.google.gwt.query.client.plugins.events.EventsListener.SpecialEvent; import com.google.gwt.query.client.plugins.events.GqEvent; import com.google.gwt.user.client.Event; import com.google.gwt.query.client.GQuery.*; 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 923d6b57..d2e4550c 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 @@ -26,6 +26,7 @@ import com.google.gwt.query.client.js.JsMap; import com.google.gwt.query.client.js.JsNamedArray; import com.google.gwt.query.client.js.JsObjectArray; import com.google.gwt.query.client.js.JsUtils; +import com.google.gwt.query.client.plugins.events.SpecialEvent.AbstractSpecialEvent; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.EventListener; @@ -46,76 +47,10 @@ import java.util.List; */ public class EventsListener implements EventListener { - public interface SpecialEvent { - /** - * The last unbind call triggers the tearDown method. - */ - boolean tearDown(EventsListener l); - - /** - * When the first event handler is bound for an EventsListener - * gQuery executes the setup function. - */ - boolean setup(EventsListener l); - - /** - * For each unbind call the remove function is called. - */ - void remove(EventsListener l, String nameSpace, Function f); - - /** - * For each bind call the add function is called. - */ - void add(EventsListener l, String nameSpace, Object data, Function f); - - /** - * Return true if there are handlers bound to this special event. - */ - boolean hasHandlers(EventsListener l); - } - - public static abstract class AbstractSpecialEvent implements SpecialEvent { - protected String type; - protected String delegateType; - protected Function handler = null; - - public AbstractSpecialEvent(String type, String delegateType) { - this.type = type; - this.delegateType = delegateType; - } - - @Override - public void add(EventsListener l, String nameSpace, Object data, Function f) { - // Nothing to do, let gQuery use default elementEvents mechanism - } - - @Override - public void remove(EventsListener l, String nameSpace, Function f) { - // Nothing to do, let gQuery use default elementEvents mechanism - } - - @Override - public boolean setup(EventsListener l) { - l.bind(Event.getTypeInt(delegateType), null, delegateType, null, handler, -1); - return false; - } - - @Override - public boolean tearDown(EventsListener l) { - l.unbind(Event.getTypeInt(delegateType), null, delegateType, handler); - return false; - } - - @Override - public boolean hasHandlers(EventsListener l) { - return l.hasHandlers(BITLESS, type); - } - } - /** * Used for simulating mouseenter and mouseleave events */ - public static class MouseSpecialEvent extends AbstractSpecialEvent { + private static class MouseSpecialEvent extends AbstractSpecialEvent { public MouseSpecialEvent(final String type, String delegateType) { super(type, delegateType); handler = new Function() { @@ -138,7 +73,7 @@ public class EventsListener implements EventListener { /** * Used for simulating mouseenter and mouseleave events */ - public static class FocusSpecialEvent extends AbstractSpecialEvent { + private static class FocusSpecialEvent extends AbstractSpecialEvent { public FocusSpecialEvent(final String type, String delegateType) { super(type, delegateType); handler = new Function() { @@ -175,6 +110,9 @@ public class EventsListener implements EventListener { } } + /** + * The function used per each element event. + */ private static class BindFunction { Object data; Function function; @@ -438,11 +376,12 @@ public class EventsListener implements EventListener { public static HashMap special; static { + // Register some special events which already exist in jQuery special = new HashMap(); special.put(MOUSEENTER, new MouseSpecialEvent(MOUSEENTER, "mouseover")); special.put(MOUSELEAVE, new MouseSpecialEvent(MOUSELEAVE, "mouseout")); - special.put(FOCUSIN, new MouseSpecialEvent(FOCUSIN, "focus")); - special.put(FOCUSOUT, new MouseSpecialEvent(FOCUSOUT, "blur")); + special.put(FOCUSIN, new FocusSpecialEvent(FOCUSIN, "focus")); + special.put(FOCUSOUT, new FocusSpecialEvent(FOCUSOUT, "blur")); } public static void clean(Element e) { @@ -549,14 +488,14 @@ public class EventsListener implements EventListener { for (EvPart ev : EvPart.split(events)) { SpecialEvent hook = special.get(ev.eventName); - if (hook != null && !hook.hasHandlers(this)) { - hook.setup(this); - } + boolean bind = hook == null || hook.setup(element) == false; for (Function function : funcs) { int b = Event.getTypeInt(ev.eventName); - bind(b, ev.nameSpace, ev.eventName, data, function, -1); + if (bind) { + bind(b, ev.nameSpace, ev.eventName, data, function, -1); + } if (hook != null) { - hook.add(this, ev.nameSpace, data, function); + hook.add(element, ev.eventName, ev.nameSpace, data, function); } } } @@ -569,14 +508,13 @@ public class EventsListener implements EventListener { public void die(String events, String cssSelector) { for (EvPart ev : EvPart.split(events)) { - die(Event.getTypeInt(ev.eventName), ev.nameSpace, ev.eventName, cssSelector); - SpecialEvent hook = special.get(ev.eventName); + boolean unbind = hook == null || hook.tearDown(element) == false; + if (unbind) { + die(Event.getTypeInt(ev.eventName), ev.nameSpace, ev.eventName, cssSelector); + } if (hook != null) { - hook.remove(this, ev.nameSpace, null); - if (!hook.hasHandlers(this)) { - hook.tearDown(this); - } + hook.remove(element, ev.eventName, ev.nameSpace, null); } } } @@ -659,15 +597,14 @@ public class EventsListener implements EventListener { public void live(String events, String cssSelector, Object data, Function... funcs) { for (EvPart ev : EvPart.split(events)) { SpecialEvent hook = special.get(ev.eventName); - if (hook != null && !hook.hasHandlers(this)) { - hook.setup(this); - } - - int b = Event.getTypeInt(ev.eventName); + boolean bind = hook == null || hook.setup(element) == false; for (Function function : funcs) { - live(b, ev.nameSpace, ev.eventName, cssSelector, data, function); + int b = Event.getTypeInt(ev.eventName); + if (bind) { + live(b, ev.nameSpace, ev.eventName, cssSelector, data, function); + } if (hook != null) { - hook.add(this, ev.nameSpace, data, function); + hook.add(element, ev.eventName, ev.nameSpace, data, function); } } } @@ -785,15 +722,13 @@ public class EventsListener implements EventListener { public void unbind(String events, Function f) { for (EvPart ev : EvPart.split(events)) { - int b = Event.getTypeInt(ev.eventName); - unbind(b, ev.nameSpace, ev.eventName, f); - //handle special event SpecialEvent hook = special.get(ev.eventName); + boolean unbind = hook == null || hook.tearDown(element) == false; + if (unbind) { + unbind(Event.getTypeInt(ev.eventName), ev.nameSpace, ev.eventName, f); + } if (hook != null) { - hook.remove(this, ev.nameSpace, f); - if (!hook.hasHandlers(this)) { - hook.tearDown(this); - } + hook.remove(element, ev.eventName, ev.nameSpace, f); } } } @@ -831,4 +766,10 @@ public class EventsListener implements EventListener { function.clean(); } } + + public void list() { + for (int i = 0, l = elementEvents.length(); i < l; i++) { + GQuery.console.log(elementEvents.get(i).toString()); + } + } } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/SpecialEvent.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/SpecialEvent.java new file mode 100644 index 00000000..cda229c0 --- /dev/null +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/SpecialEvent.java @@ -0,0 +1,106 @@ +/* + * Copyright 2014, The gwtquery team. + * + * 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.plugins.events; + +import com.google.gwt.dom.client.Element; +import com.google.gwt.query.client.Function; +import com.google.gwt.user.client.Event; + +/** + * Interface used to register special events. + * + * Use EventsListeners.special.add( + */ +public interface SpecialEvent { + + /** + * Abstract implementation of SpecialEvents + */ + public static abstract class AbstractSpecialEvent implements SpecialEvent { + protected final String delegateType; + protected final String type; + protected Function handler = null; + + public AbstractSpecialEvent(String type, String delegateType) { + this.type = type; + this.delegateType = delegateType; + } + + protected EventsListener listener(Element e) { + return EventsListener.getInstance(e); + } + + @Override + public void add(Element e, String eventType, String nameSpace, Object data, Function f) { + // Nothing to do, let gQuery use default eentEvents mechanism + } + + @Override + public boolean hasHandlers(Element e) { + return listener(e).hasHandlers(Event.getTypeInt(type), type); + } + + @Override + public void remove(Element e, String eventType, String nameSpace, Function f) { + // Nothing to do, let gQuery use default eentEvents mechanism + } + + @Override + public boolean setup(Element e) { + if (!hasHandlers(e)) { + listener(e).bind(Event.getTypeInt(delegateType), null, delegateType, null, handler, -1); + } + return false; + } + + @Override + public boolean tearDown(Element e) { + if (!hasHandlers(e)) { + listener(e).unbind(Event.getTypeInt(delegateType), null, delegateType, handler); + } + return false; + } + } + + /** + * For each bind call the add function is called. + */ + void add(Element e, String eventType, String nameSpace, Object data, Function f); + + /** + * Return true if there are handlers bound to this special event. + */ + boolean hasHandlers(Element e); + + /** + * For each unbind call the remove function is called. + */ + void remove(Element e, String eventType, String nameSpace, Function f); + + /** + * When the first event handler is bound for an EventsListener gQuery executes the setup function. + * + * If the method returns false means that gQuery has to run the default bind for the event before + * calling add. + */ + boolean setup(Element e); + + /** + * The last unbind call triggers the tearDown method. + * + * If the method returns false means that gQuery has to run the default unbind for the event + * before calling remove. + */ + boolean tearDown(Element e); +} \ No newline at end of file -- cgit v1.2.3 From e4ea1388ed6ac6ee6d1ab594202da418110cdbc8 Mon Sep 17 00:00:00 2001 From: Manolo Carrasco Date: Wed, 24 Dec 2014 17:00:03 +0100 Subject: trigger methods should work with namespaces --- .../google/gwt/query/client/plugins/Events.java | 52 +++++++++++++++------- .../client/plugins/events/EventsListener.java | 13 +++--- .../gwt/query/client/plugins/events/GqEvent.java | 3 ++ .../gwt/query/client/GQueryEventsTestGwt.java | 12 +++++ 4 files changed, 58 insertions(+), 22 deletions(-) (limited to 'gwtquery-core') 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 7f2127d1..d7f7e7df 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 @@ -21,6 +21,7 @@ import com.google.gwt.query.client.Function; import com.google.gwt.query.client.GQuery; import com.google.gwt.query.client.js.JsUtils; import com.google.gwt.query.client.plugins.events.EventsListener; +import com.google.gwt.query.client.plugins.events.EventsListener.EvPart; import com.google.gwt.user.client.Event; /** @@ -264,8 +265,20 @@ public class Events extends GQuery { * @param nativeEvent the browser native event. * @functions a set of function to run if the event is not canceled. */ - public Events trigger(NativeEvent nativeEvent, Function... functions) { - dispatchEvent(nativeEvent, null, functions); + public Events trigger(NativeEvent nativeEvent, Function... fcns) { + dispatchEvent(nativeEvent, null, fcns); + return this; + } + + /** + * Trigger a native event in all matched elements. + * + * @param nativeEvent the browser native event. + * @param datas a set of object passed as data when executed the handlers + * @param functions a set of function to run if the event is not canceled. + */ + public Events trigger(NativeEvent nativeEvent, Object[] datas, Function... functions) { + dispatchEvent(nativeEvent, datas, functions); return this; } @@ -273,7 +286,7 @@ public class Events extends GQuery { * Trigger a html event in all matched elements. * * @param htmlEvent A string representing the desired html event. - * @functions a set of function to run if the event is not canceled. + * @param functions a set of function to run. */ public Events triggerHtmlEvent(String htmlEvent, Function... functions) { return triggerHtmlEvent(htmlEvent, null, functions); @@ -283,24 +296,29 @@ public class Events extends GQuery { * Trigger a html event in all matched elements. * * @param htmlEvent An string representing the desired html event. - * @functions a set of function to run if the event is not canceled. + * @param datas a set of object passed as data when executed the handlers + * @param functions a set of function to run. */ public Events triggerHtmlEvent(String htmlEvent, Object[] datas, final Function... functions) { - NativeEvent e = document.createHtmlEvent(htmlEvent, true, true); - if ("submit".equals(htmlEvent)){ - Function submitFunction = new Function() { - public void f(Element e) { - // first submit the form then call the others functions - if (FormElement.is(e)) { - e.cast().submit(); + for (EvPart part : EvPart.split(htmlEvent)) { + NativeEvent e = document.createHtmlEvent(part.eventName, true, true); + JsUtils.prop(e, "namespace", part.nameSpace); + if ("submit".equals(part.eventName)){ + Function submitFunction = new Function() { + public void f(Element e) { + // first submit the form then call the others functions + if (FormElement.is(e)) { + e.cast().submit(); + } + callHandlers(e, getEvent(), functions); } - callHandlers(e, getEvent(), functions); - } - }; - dispatchEvent(e, datas, submitFunction); - } else { - dispatchEvent(e, datas, functions); + }; + dispatchEvent(e, datas, submitFunction); + } else { + dispatchEvent(e, datas, functions); + } } + return this; } 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 d8b80e55..a6e5912e 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 @@ -73,15 +73,15 @@ public class EventsListener implements EventListener { /** * Utility class to split a list of events with or without namespaces */ - private static class EvPart { - String nameSpace; - String eventName; + public static class EvPart { + public final String nameSpace; + public final String eventName; public EvPart(String n, String e) { nameSpace = n; eventName = e; } - static List split(String events) { + public static List split(String events) { List ret = new ArrayList(); String[] parts = events.split("[\\s,]+"); for (String event : parts) { @@ -561,7 +561,10 @@ public class EventsListener implements EventListener { Object[] handlerData = $(element).data(EVENT_DATA); for (int i = 0, l = elementEvents.length(); i < l; i++) { BindFunction listener = elementEvents.get(i); - if (listener != null && (listener.hasEventType(etype) || listener.isTypeOf(eventName))) { + String namespace = JsUtils.prop(event, "namespace"); + boolean matchEV = listener != null && (listener.hasEventType(etype) || listener.isTypeOf(eventName)); + boolean matchNS = matchEV && (isNullOrEmpty(namespace) || listener.nameSpace.equals(namespace)); + if (matchEV && matchNS) { if (!listener.fire(event, handlerData)) { event.stopPropagation(); event.preventDefault(); diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/GqEvent.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/GqEvent.java index e98a5f4c..cd78bde1 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/GqEvent.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/GqEvent.java @@ -96,4 +96,7 @@ public class GqEvent extends Event { } } + public static final GqEvent as(Event e) { + return e.cast(); + } } diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEventsTestGwt.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEventsTestGwt.java index 08777f32..0ad8ae40 100644 --- a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEventsTestGwt.java +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEventsTestGwt.java @@ -1904,4 +1904,16 @@ public class GQueryEventsTestGwt extends GWTTestCase { assertEquals(2, mouseEnterFunction.invokationCounter); } + public void testBindAndTriggerWithNameSpace() { + $(e).html("
blop
"); + CounterFunction counter = new CounterFunction(); + $("#mainDiv", e).on("click.mynamespace;foo", counter); + $("#mainDiv").trigger("click"); + assertEquals(1, counter.invokationCounter); + $("#mainDiv").trigger("click.mynamespace;bar"); + assertEquals(1, counter.invokationCounter); + $("#mainDiv").trigger("click.mynamespace;foo"); + assertEquals(2, counter.invokationCounter); + } + } -- cgit v1.2.3 From 37cff9a5acb515c13b299b842971bb1d128a4359 Mon Sep 17 00:00:00 2001 From: Manolo Carrasco Date: Tue, 30 Dec 2014 13:52:32 +0100 Subject: Change EvPart name, remove focusin/focusout aliases. --- .../google/gwt/query/client/plugins/Events.java | 4 ++-- .../client/plugins/events/EventsListener.java | 25 ++++++++++------------ .../query/client/plugins/events/SpecialEvent.java | 2 +- .../gwt/query/client/GQueryEventsTestGwt.java | 22 ------------------- 4 files changed, 14 insertions(+), 39 deletions(-) (limited to 'gwtquery-core') 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 d7f7e7df..55190938 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 @@ -21,7 +21,7 @@ import com.google.gwt.query.client.Function; import com.google.gwt.query.client.GQuery; import com.google.gwt.query.client.js.JsUtils; import com.google.gwt.query.client.plugins.events.EventsListener; -import com.google.gwt.query.client.plugins.events.EventsListener.EvPart; +import com.google.gwt.query.client.plugins.events.EventsListener.EventName; import com.google.gwt.user.client.Event; /** @@ -300,7 +300,7 @@ public class Events extends GQuery { * @param functions a set of function to run. */ public Events triggerHtmlEvent(String htmlEvent, Object[] datas, final Function... functions) { - for (EvPart part : EvPart.split(htmlEvent)) { + for (EventName part : EventName.split(htmlEvent)) { NativeEvent e = document.createHtmlEvent(part.eventName, true, true); JsUtils.prop(e, "namespace", part.nameSpace); if ("submit".equals(part.eventName)){ 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 a6e5912e..f6f2113a 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 @@ -34,6 +34,7 @@ import com.google.gwt.user.client.EventListener; import java.util.ArrayList; 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 @@ -73,22 +74,22 @@ public class EventsListener implements EventListener { /** * Utility class to split a list of events with or without namespaces */ - public static class EvPart { + public static class EventName { public final String nameSpace; public final String eventName; - public EvPart(String n, String e) { + public EventName(String n, String e) { nameSpace = n; eventName = e; } - public static List split(String events) { - List ret = new ArrayList(); + public static List split(String events) { + List ret = new ArrayList(); String[] parts = events.split("[\\s,]+"); for (String event : parts) { String[] tmp = event.split("\\.", 2); String eventName = tmp[0]; String nameSpace = tmp.length > 1 ? tmp[1] : null; - ret.add(new EvPart(nameSpace, eventName)); + ret.add(new EventName(nameSpace, eventName)); } return ret; } @@ -354,18 +355,14 @@ public class EventsListener implements EventListener { public static String MOUSEENTER = "mouseenter"; public static String MOUSELEAVE = "mouseleave"; - public static String FOCUSIN = "focusin"; - public static String FOCUSOUT = "focusout"; - public static HashMap special; + public static Map special; static { // Register some special events which already exist in jQuery special = new HashMap(); special.put(MOUSEENTER, new MouseSpecialEvent(MOUSEENTER, "mouseover")); special.put(MOUSELEAVE, new MouseSpecialEvent(MOUSELEAVE, "mouseout")); - special.put(FOCUSIN, new DefaultSpecialEvent(FOCUSIN, "focus")); - special.put(FOCUSOUT, new DefaultSpecialEvent(FOCUSOUT, "blur")); } public static void clean(Element e) { @@ -470,7 +467,7 @@ public class EventsListener implements EventListener { unbind(events, null); } - for (EvPart ev : EvPart.split(events)) { + for (EventName ev : EventName.split(events)) { SpecialEvent hook = special.get(ev.eventName); boolean bind = hook == null || hook.setup(element) == false; for (Function function : funcs) { @@ -491,7 +488,7 @@ public class EventsListener implements EventListener { } public void die(String events, String cssSelector) { - for (EvPart ev : EvPart.split(events)) { + for (EventName ev : EventName.split(events)) { SpecialEvent hook = special.get(ev.eventName); boolean unbind = hook == null || hook.tearDown(element) == false; if (unbind) { @@ -582,7 +579,7 @@ public class EventsListener implements EventListener { } public void live(String events, String cssSelector, Object data, Function... funcs) { - for (EvPart ev : EvPart.split(events)) { + for (EventName ev : EventName.split(events)) { SpecialEvent hook = special.get(ev.eventName); boolean bind = hook == null || hook.setup(element) == false; for (Function function : funcs) { @@ -708,7 +705,7 @@ public class EventsListener implements EventListener { } public void unbind(String events, Function f) { - for (EvPart ev : EvPart.split(events)) { + for (EventName ev : EventName.split(events)) { SpecialEvent hook = special.get(ev.eventName); boolean unbind = hook == null || hook.tearDown(element) == false; if (unbind) { diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/SpecialEvent.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/SpecialEvent.java index cc4020b9..8083b098 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/SpecialEvent.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/SpecialEvent.java @@ -112,4 +112,4 @@ public interface SpecialEvent { * before calling remove. */ boolean tearDown(Element e); -} \ No newline at end of file +} diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEventsTestGwt.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEventsTestGwt.java index 0ad8ae40..315999a1 100644 --- a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEventsTestGwt.java +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEventsTestGwt.java @@ -455,28 +455,6 @@ public class GQueryEventsTestGwt extends GWTTestCase { assertEquals("", $("p", e).css("border", false)); } - @DoNotRunWith({Platform.HtmlUnitLayout}) - public void testSpecialFocusInOut() { - $(e).html("

Content

"); - $("p", e).on(EventsListener.FOCUSIN, new Function() { - public void f(Element elem) { - GQuery.console.log("focus"); - $(elem).css("background-color", "red"); - } - }); - $("p", e).focus(); - assertEquals("red", $("p", e).css("background-color", false)); - - // blur - $("p", e).on(EventsListener.FOCUSOUT, new Function() { - public void f(Element elem) { - $(elem).css("background-color", "white"); - } - }); - $("p", e).blur(); - assertEquals("white", $("p", e).css("background-color", false)); - } - public void testLazyMethods() { $(e).css(CSS.COLOR.with(RGBColor.WHITE)); assertEquals("white", $(e).css("color", false)); -- cgit v1.2.3 From 573379b366385dcb78a6209e6bb2028fef92967f Mon Sep 17 00:00:00 2001 From: Manolo Carrasco Date: Fri, 2 Jan 2015 15:05:11 +0100 Subject: Make TC windows happy --- .../java/com/google/gwt/query/client/GQueryEffectsTestGwt.java | 4 ++++ .../google/gwt/query/client/dbinding/DataBindingTestJre.java | 10 ++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) (limited to 'gwtquery-core') diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEffectsTestGwt.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEffectsTestGwt.java index 287742fa..f08c9f80 100644 --- a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEffectsTestGwt.java +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEffectsTestGwt.java @@ -66,6 +66,8 @@ public class GQueryEffectsTestGwt extends GWTTestCase { } } + // Fails in TC windows, pass in Jenkins Linux + @DoNotRunWith(Platform.HtmlUnitLayout) public void testClipAnimation() { $(e).html("

Content 1

"); @@ -354,6 +356,8 @@ public class GQueryEffectsTestGwt extends GWTTestCase { assertTrue(msg, c); } + // Fails in TC windows, pass in Jenkins Linux + @DoNotRunWith(Platform.HtmlUnitLayout) public void testAttrEffect() { $(e).html("
AB
"); diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/dbinding/DataBindingTestJre.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/dbinding/DataBindingTestJre.java index 5ea76a18..50123b80 100644 --- a/gwtquery-core/src/test/java/com/google/gwt/query/client/dbinding/DataBindingTestJre.java +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/dbinding/DataBindingTestJre.java @@ -16,6 +16,8 @@ package com.google.gwt.query.client.dbinding; import com.google.gwt.core.shared.GWT; +import com.google.gwt.junit.DoNotRunWith; +import com.google.gwt.junit.Platform; import com.google.gwt.junit.client.GWTTestCase; import com.google.gwt.query.client.Function; import com.google.gwt.query.client.GQ; @@ -177,8 +179,7 @@ public class DataBindingTestJre extends GWTTestCase { + " }" + "}"; - public void - test_parse_json() { + public void test_parse_json() { GUser entity = GQ.create(GUser.class); entity.parse(JSON_USER_EXAMPLE, true); @@ -191,8 +192,9 @@ public class DataBindingTestJre extends GWTTestCase { assertNotNull(entity.address().get("phone")); } - public void - test_parse_strict_json() { + // Nested strict not implemented in JS + @DoNotRunWith(Platform.Prod) + public void test_parse_strict_json() { GUser entity = GQ.create(GUser.class); entity.parse(JSON_USER_EXAMPLE, true); entity.strip(); -- cgit v1.2.3