From 42f082a144b416fb3345f89ac968b7dcbe3d8d08 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Manuel=20Carrasco=20Mo=C3=B1ino?= Date: Sun, 3 Mar 2013 22:00:29 +0100 Subject: [PATCH] First implementation of Deferred and Promises. Ajax tests work. then implementation is not ok. Needs tests --- devtest/pom.xml | 29 ++++ .../google/gwt/query/DevTestRunner.gwt.xml | 1 + .../gwt/query/client/DevTestRunner.java | 89 +++++++++- .../com/google/gwt/query/client/Function.java | 66 ++++--- .../com/google/gwt/query/client/GQuery.java | 32 ++-- .../com/google/gwt/query/client/Promise.java | 41 +++++ .../google/gwt/query/client/js/JsCache.java | 2 +- .../gwt/query/client/plugins/Deferred.java | 146 ++++++++++++++++ .../gwt/query/client/plugins/ajax/Ajax.java | 161 +++++++++++++++--- .../client/plugins/callbacks/Callbacks.java | 28 ++- .../query/client/GQueryDeferredTestGwt.java | 12 +- .../gwt/query/client/GQueryEventsTestGwt.java | 2 +- 12 files changed, 542 insertions(+), 67 deletions(-) create mode 100644 gwtquery-core/src/main/java/com/google/gwt/query/client/Promise.java create mode 100644 gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/Deferred.java diff --git a/devtest/pom.xml b/devtest/pom.xml index 3f73740f..42e25b56 100644 --- a/devtest/pom.xml +++ b/devtest/pom.xml @@ -31,6 +31,11 @@ ${gwtversion} provided + + com.google.gwt + gwt-codeserver + ${gwtversion} + @@ -89,6 +94,30 @@ + + org.codehaus.mojo + exec-maven-plugin + 1.2.1 + + + + java + + + + + com.google.gwt.dev.codeserver.CodeServer + + -src + src/main/java + -bindAddress + 0.0.0.0 + com.google.gwt.query.DevTestRunner + + compile + + + ${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 401fde05..b3ce809f 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 @@ -1,5 +1,6 @@ + diff --git a/devtest/src/main/java/com/google/gwt/query/client/DevTestRunner.java b/devtest/src/main/java/com/google/gwt/query/client/DevTestRunner.java index 53ef8e18..18de0c87 100644 --- a/devtest/src/main/java/com/google/gwt/query/client/DevTestRunner.java +++ b/devtest/src/main/java/com/google/gwt/query/client/DevTestRunner.java @@ -22,6 +22,9 @@ import com.google.gwt.core.client.EntryPoint; import com.google.gwt.core.client.Scheduler; import com.google.gwt.core.client.Scheduler.RepeatingCommand; import com.google.gwt.query.client.js.JsUtils; +import com.google.gwt.query.client.plugins.ajax.Ajax; +import com.google.gwt.query.client.plugins.ajax.Ajax.Settings; +import com.google.gwt.user.client.Window; /** * This module is thought to emulate a test environment similar to @@ -45,8 +48,92 @@ public class DevTestRunner extends MyTestCase implements EntryPoint { $(e).html("").after("
ERROR: " + ex.getMessage() + "
"); } } - + public void testSomething() { + System.out.println("com"); + + delayTestFinish(5000); + String nonJsonpUrl = "http://127.0.0.1/nopage"; + + Settings s = Ajax.createSettings(); + s.setTimeout(1000); + s.setSuccess(new Function(){ + public void f() { + fail(); + } + }); + s.setError(new Function(){ + public void f() { + finishTest(); + } + }); + s.setDataType("jsonp"); + s.setUrl(nonJsonpUrl); + + Ajax.ajax(s); + +// GQuery.ajax(Ajax.createSettings() +// .setUrl("test.html") +// .setDataType("txt") // txt, json, jsonp, xml +// .setType("get") // post, get +// .setData(GQuery.$$("param1: 1, param2: 2")) // parameters for the query-string +// .setTimeout(3000) +// .setSuccess(new Function(){ // callback to be run if the request success +// public void f() { +// // The response when dataType=xml, is a dom tree which we can traverse using gquery +// Window.alert("ok"); +// } +// }) +//// .setError(new Function(){ // callback to be run if the request fails +//// public void f() { +//// Window.alert("There was an error" + getDataObject()); +//// } +//// }) +// ).done(new Function(){ +// public void f() { +// System.out.println("Aqui"); +// } +// }, new Function(){ +// public void f() { +// System.out.println("Aqui2"); +// } +// } +// ); +// + + +// Settings set = Ajax.createSettings(); +// +// $(window).delay(1000, new Function(){ +// public void f() { +// System.out.println("Run 1"); +// } +// }); +// $(window).delay(3000, new Function(){ +// public void f() { +// System.out.println("Run 3"); +// } +// }); + } + + + private native void setWindowVars() /*-{ + $wnd._boolean = true; + $wnd._number = 0.56; + $wnd._string = "string"; + $wnd._element = $doc.body; + $wnd._object = $wnd.console; + }-*/; + + public void testSomething2() { + setWindowVars(); + System.out.println($(window).prop("_boolean")); + System.out.println($(window).propString("_string")); + System.out.println($(window).propDouble("_number")); + System.out.println($(window).propObject("_boolean")); + System.out.println($(window).propJSO("_element")); + Object o = window.getPropertyObject("_element"); + System.out.println(o); // Copy and paste any test from the gquery suite } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/Function.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/Function.java index 361eea1f..5bb4f5f6 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/Function.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/Function.java @@ -29,7 +29,7 @@ public abstract class Function { private com.google.gwt.dom.client.Element element = null; private Event event = null; private int index = -1; - private Object[] data = new Object[0]; + protected Object[] arguments = new Object[0]; public T getElement() { return element.cast(); @@ -51,21 +51,48 @@ public abstract class Function { public void setIndex(int i) { index = i; } - + + @Deprecated public Object[] getData() { - return data; + return getArguments(); } - public void setData(Object...data) { - this.data = data; + public Object[] getArguments() { + return arguments; + } + + @Deprecated + public void setData(Object...arguments) { + setArguments(arguments); + } + + /** + * Set the list of arguments to be passed to the function + */ + public void setArguments(Object...arguments) { + this.arguments = arguments; } + /** + * Return the first element of the arguments list + */ public Object getDataObject() { - return getDataObject(0); + return getArgument(0); } + /** + * @deprecated use getArgument instead + */ + @Deprecated public Object getDataObject(int idx) { - return data != null && data.length > idx ? data[idx] : null; + return getArgument(0); + } + + /** + * return the argument in position idx; + */ + public Object getArgument(int idx) { + return arguments != null && arguments.length > idx ? arguments[idx] : null; } public Properties getDataProperties() { @@ -73,7 +100,7 @@ public abstract class Function { } public Properties getDataProperties(int idx) { - Object o = getDataObject(idx); + Object o = getArgument(idx); if (o != null && o instanceof JavaScriptObject) { return (Properties)o; } @@ -89,7 +116,7 @@ public abstract class Function { } public void setDataObject(Object data) { - setData(data); + setArguments(data); } public int getIndex() { @@ -177,8 +204,10 @@ public abstract class Function { /** * Override this method for bound callbacks */ - public void f(Object... data) { - fe(data); + public Object f(Object... data) { + setArguments(data); + f(); + return true; } /** @@ -193,7 +222,7 @@ public abstract class Function { */ public void f(int i, Object... data) { setIndex(i); - setData(data); + setArguments(data); if (data.length == 1 && data[0] instanceof JavaScriptObject) { if (JsUtils.isElement((JavaScriptObject)data[0])) { setElement((com.google.gwt.dom.client.Element)data[0]); @@ -212,7 +241,7 @@ public abstract class Function { * per-handler user data. */ public boolean f(Event e, Object data) { - setData(data); + setArguments(data); setEvent(e); return f(e); } @@ -282,7 +311,7 @@ public abstract class Function { * They are intentionally final to avoid override them */ public final void fe() { - fe(data); + fe(arguments); } /** @@ -299,17 +328,16 @@ public abstract class Function { * catch the exception and send it to the GWT UncaughtExceptionHandler * They are intentionally final to avoid override them */ - public final void fe(Object... data) { - setData(data); + public final Object fe(Object... data) { if (GWT.getUncaughtExceptionHandler() != null) { try { - f(); + return f(data); } catch (Exception e) { GWT.getUncaughtExceptionHandler().onUncaughtException(e); } - return; + return true; } - f(); + return f(data); } /** 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 47370ef4..1a2afc78 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 @@ -25,9 +25,18 @@ import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.core.client.JsArray; import com.google.gwt.core.client.JsArrayMixed; import com.google.gwt.core.client.JsArrayString; -import com.google.gwt.dom.client.*; +import com.google.gwt.dom.client.BodyElement; +import com.google.gwt.dom.client.ButtonElement; +import com.google.gwt.dom.client.Document; +import com.google.gwt.dom.client.Element; +import com.google.gwt.dom.client.InputElement; +import com.google.gwt.dom.client.Node; +import com.google.gwt.dom.client.NodeList; +import com.google.gwt.dom.client.OptionElement; +import com.google.gwt.dom.client.SelectElement; import com.google.gwt.dom.client.Style.Display; import com.google.gwt.dom.client.Style.HasCssName; +import com.google.gwt.dom.client.TextAreaElement; import com.google.gwt.query.client.css.CSS; import com.google.gwt.query.client.css.HasCssValue; import com.google.gwt.query.client.css.TakesCssValue; @@ -232,7 +241,8 @@ public class GQuery implements Lazy { return JsUtils.isWindow(jso) ? $(jso. cast()) : JsUtils.isElement(jso) ? $(jso. cast()) : JsUtils.isEvent(jso) ? $(jso. cast()) : - JsUtils.isNodeList(jso) ? $(jso.> cast()) : $(); + JsUtils.isNodeList(jso) ? $(jso.> cast()) : + $(jso. cast()); } /** @@ -402,22 +412,22 @@ public class GQuery implements Lazy { /** * Perform an ajax request to the server. */ - public static void ajax(Properties p) { - Ajax.ajax(p); + public static Promise ajax(Properties p) { + return Ajax.ajax(p); } /** * Perform an ajax request to the server. */ - public static void ajax(Settings settings) { - Ajax.ajax(settings); + public static Promise ajax(Settings settings) { + return Ajax.ajax(settings); } /** * Perform an ajax request to the server. */ - public static void ajax(String url, Settings settings) { - Ajax.ajax(url, settings); + public static Promise ajax(String url, Settings settings) { + return Ajax.ajax(url, settings); } @SuppressWarnings("unchecked") @@ -3454,11 +3464,9 @@ public class GQuery implements Lazy { * */ public boolean prop(String key) { - assert key != null : "Key is null"; - - return !isEmpty() && get(0).getPropertyBoolean(key); + return !isEmpty() && elements[0].getPropertyBoolean(key); } - + /** * Sets a boolean property to a value on all matched elements. * diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/Promise.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/Promise.java new file mode 100644 index 00000000..c31e0c99 --- /dev/null +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/Promise.java @@ -0,0 +1,41 @@ +/* + * Copyright 2013, 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; + +import com.google.gwt.query.client.Function; + +/** + * Definition of jquery Promise interface used in gquery. + */ +public interface Promise { + + public static final String PENDING = "pending"; + public static final String REJECTED = "rejected"; + public static final String RESOLVED = "resolved"; + + Promise always(Function... o); + + Promise done(Function... o); + + Promise fail(Function... o); + + Promise pipe(Function... f); + + Promise progress(Function... o); + + String state(); + + Promise then(Function... f); + +} \ No newline at end of file diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsCache.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsCache.java index f8dca659..259ed204 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsCache.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsCache.java @@ -94,7 +94,7 @@ public class JsCache extends JavaScriptObject { public final native JsArrayMixed getArray(T id) /*-{ var r = this[id]; - if (r && @com.google.gwt.query.client.js.JsUtils::isArray(*)(r)) { + if (r && Object.prototype.toString.call(r) == '[object Array]') { return r; } return null; diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/Deferred.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/Deferred.java new file mode 100644 index 00000000..6b89b884 --- /dev/null +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/Deferred.java @@ -0,0 +1,146 @@ +/* + * Copyright 2013, 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; + +import com.google.gwt.query.client.Function; +import com.google.gwt.query.client.GQuery; +import com.google.gwt.query.client.Promise; +import com.google.gwt.query.client.plugins.callbacks.Callbacks; + +/** + * Implementation of jQuery.Deffered for gwtquery. + */ +public class Deferred extends GQuery { + + private class DeferredPromise extends GQuery implements Promise { + private Deferred dfd; + + protected DeferredPromise(GQuery gq) { + super(gq); + if (gq instanceof Deferred) { + dfd = (Deferred) gq; + } else if (gq instanceof DeferredPromise) { + dfd = ((DeferredPromise)gq).dfd;; + } else { + dfd = gq.as(Deferred); + } + } + + public Promise always(Function... o) { + return done(o).fail(o); + } + + public Promise done(Function... o) { + dfd.resolve.add(o); + return this; + } + + public Promise fail(Function... o) { + dfd.reject.add(o); + return this; + } + + public Promise pipe(Function... f) { + return then(f); + } + + public Promise progress(Function... o) { + dfd.notify.add(o); + return this; + } + + public String state() { + return dfd.state; + } + + public Promise then(Function... f) { + switch (f.length) { + case 3: progress(f[0]); + case 2: fail(f[0]); + case 1: done(f[0]); + } + return this; + } + } + public static final Class Deferred = GQuery.registerPlugin( + Deferred.class, new Plugin() { + public Deferred init(GQuery gq) { + return new Deferred(gq); + } + }); + public static Promise when(Deferred d) { + return d.promise(); + } + private Callbacks notify = new Callbacks("memory"); + + private Promise promise = null; + + private Callbacks reject = new Callbacks("once memory"); + + private Callbacks resolve = new Callbacks("once memory"); + + private String state = Promise.PENDING; + + protected Deferred(GQuery gq) { + super(gq); + resolve.add(new Function() { + public void f() { + state = Promise.RESOLVED; + resolve.disable(); + notify.lock(); + } + }); + + reject.add(new Function() { + public void f() { + state = Promise.REJECTED; + reject.disable(); + notify.lock(); + } + }); + } + // private, used from jsni + @SuppressWarnings("unused") + private void err(Object o) { + reject(o); + } + public Deferred notify(Object... o) { + notify.fire(o); + return this; + } + + // private, used from jsni + @SuppressWarnings("unused") + private void ok(Object o) { + resolve(o); + } + + public Promise promise() { + if (promise == null) { + promise = new DeferredPromise(this); + } + return promise; + } + + + public Deferred reject(Object... o) { + reject.fire(o); + return this; + } + + public Deferred resolve(Object... o) { + resolve.fire(o); + return this; + } +} diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/ajax/Ajax.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/ajax/Ajax.java index 96a3d35b..0c60de9c 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/ajax/Ajax.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/ajax/Ajax.java @@ -1,6 +1,7 @@ package com.google.gwt.query.client.plugins.ajax; import com.google.gwt.core.client.GWT; +import com.google.gwt.core.client.JavaScriptException; import com.google.gwt.dom.client.Element; import com.google.gwt.http.client.Request; import com.google.gwt.http.client.RequestBuilder; @@ -10,11 +11,15 @@ import com.google.gwt.http.client.RequestException; import com.google.gwt.http.client.Response; import com.google.gwt.query.client.Function; import com.google.gwt.query.client.GQuery; +import com.google.gwt.query.client.Promise; import com.google.gwt.query.client.Properties; import com.google.gwt.query.client.builders.JsonBuilder; import com.google.gwt.query.client.js.JsUtils; +import com.google.gwt.query.client.plugins.Deferred; import com.google.gwt.query.client.plugins.Plugin; import com.google.gwt.user.client.ui.FormPanel; +import com.google.gwt.xhr.client.ReadyStateChangeHandler; +import com.google.gwt.xhr.client.XMLHttpRequest; /** * Ajax class for GQuery. @@ -70,10 +75,10 @@ public class Ajax extends GQuery { } }); - public static void ajax(Properties p) { + public static Promise ajax(Properties p) { Settings s = createSettings(); s.load(p); - ajax(s); + return ajax(s); } /** @@ -103,7 +108,7 @@ public class Ajax extends GQuery { * @param onError the function to execute on error * @param settings a Properties object with the configuration of the Ajax request. */ - public static void ajax(Settings settings) { + public static void ajaxOld(Settings settings) { final Function onSuccess = settings.getSuccess(); if (onSuccess != null) { @@ -133,6 +138,8 @@ public class Ajax extends GQuery { onError.f(null, exception.getMessage(), request, null, exception); } } + + public void onResponseReceived(Request request, Response response) { int statusCode = response.getStatusCode(); @@ -172,6 +179,120 @@ public class Ajax extends GQuery { } } } + + + public static Promise ajax(Settings settings) { + + final Deferred dfd = $().as(Deferred.Deferred); + + final Function onSuccess = settings.getSuccess(); + if (onSuccess != null) { + onSuccess.setElement(settings.getContext()); + dfd.promise().done(onSuccess); + } + + final Function onError = settings.getError(); + if (onError != null) { + onError.setElement(settings.getContext()); + dfd.promise().fail(onError); + } + + Method httpMethod = resolveHttpMethod(settings); + String data = resolveData(settings, httpMethod); + final String url = resolveUrl(settings, httpMethod, data); + final String dataType = settings.getDataType(); + + if ("jsonp".equalsIgnoreCase(dataType)) { + int timeout = settings.getTimeout(); + return getJSONP(url, onSuccess, onError, timeout); + } + + RequestCallback mdb = new RequestCallback() { + public void onError(Request request, Throwable exception) { + if (onError != null) { + onError.f(null, exception.getMessage(), request, null, exception); + } + } + + public void onResponseReceived(Request request, Response response) { + int statusCode = response.getStatusCode(); + if (statusCode <= 0 || statusCode >= 400) { + if (statusCode == 0) { + // Just warn the developer about the status code + GWT.log("GQuery.ajax error, the response.statusCode is 0, this usually happens when you try to access an external server without CORS enabled. url=" + url); + } + dfd.reject(response.getText(), "error", request, response); + } else if (onSuccess != null) { + Object retData = null; + try { + if ("xml".equalsIgnoreCase(dataType)) { + retData = JsUtils.parseXML(response.getText()); + } else if ("json".equalsIgnoreCase(dataType)) { + retData = JsUtils.parseJSON(response.getText()); + } else { + retData = response.getText(); + } + } catch (Exception e) { + if (GWT.getUncaughtExceptionHandler() != null) { + GWT.getUncaughtExceptionHandler().onUncaughtException(e); + } + } + dfd.resolve(retData, "success", request, response); + } + } + }; + + XMLHttpRequest xmlHttpRequest = createXHR(settings, httpMethod.toString(), url, dataType, mdb); + + try { + xmlHttpRequest.send(data); + } catch (JavaScriptException e) { + dfd.reject(e.getMessage(), "error", null, null, e); + } + + return dfd.promise(); + } + + + private static native Request createRequest(XMLHttpRequest r, int t, RequestCallback c) /*-{ + return @com.google.gwt.http.client.Request::new(Lcom/google/gwt/xhr/client/XMLHttpRequest;ILcom/google/gwt/http/client/RequestCallback;)(r, t, c); + }-*/; + + private static native void fireOnResponseReceived(Request q, RequestCallback c) /*-{ + q.@com.google.gwt.http.client.Request::fireOnResponseReceived(*)(c); + }-*/; + + + private static XMLHttpRequest createXHR (Settings settings, String httpMethod, String url, String data, final RequestCallback cb) { + XMLHttpRequest xmlHttpRequest = XMLHttpRequest.create(); + + if (settings.getUsername() != null && settings.getPassword() != null) { + xmlHttpRequest.open(httpMethod.toString(), url, settings.getUsername(), settings.getPassword()); + } else if (settings.getUsername() != null) { + xmlHttpRequest.open(httpMethod, url, settings.getUsername()); + } else { + xmlHttpRequest.open(httpMethod, url); + } + + Properties headers = settings.getHeaders(); + if (headers != null) { + for (String headerKey : headers.keys()) { + xmlHttpRequest.setRequestHeader(headerKey, headers.getStr(headerKey)); + } + } + + final Request request = createRequest(xmlHttpRequest, settings.getTimeout(), cb); + xmlHttpRequest.setOnReadyStateChange(new ReadyStateChangeHandler() { + public void onReadyStateChange(XMLHttpRequest xhr) { + if (xhr.getReadyState() == XMLHttpRequest.DONE) { + xhr.clearOnReadyStateChange(); + fireOnResponseReceived(request, cb); + } + } + }); + + return xmlHttpRequest; + } private static RequestBuilder createRequestBuilder(Settings settings, Method httpMethod, String url, String data) { @@ -255,27 +376,27 @@ public class Ajax extends GQuery { return RequestBuilder.POST; } - public static void ajax(String url, Function onSuccess, Function onError) { - ajax(url, onSuccess, onError, (Settings) null); + public static Promise ajax(String url, Function onSuccess, Function onError) { + return ajax(url, onSuccess, onError, (Settings) null); } - public static void ajax(String url, Function onSuccess, Function onError, Settings s) { + public static Promise ajax(String url, Function onSuccess, Function onError, Settings s) { if (s == null) { s = createSettings(); } s.setUrl(url).setSuccess(onSuccess).setError(onError); - ajax(s); + return ajax(s); } - public static void ajax(String url, Properties p) { + public static Promise ajax(String url, Properties p) { Settings s = createSettings(); s.load(p); s.setUrl(url); - ajax(s); + return ajax(s); } - public static void ajax(String url, Settings settings) { - ajax(settings.setUrl(url)); + public static Promise ajax(String url, Settings settings) { + return ajax(settings.setUrl(url)); } public static Settings createSettings() { @@ -322,7 +443,7 @@ public class Ajax extends GQuery { ajax(s); } - public static void getJSONP(String url, Function success, Function error, int timeout) { + public static Promise getJSONP(String url, Function success, Function error, int timeout) { if (!url.contains("=?") && !url.contains("callback=")) { url += (url.contains("?") ? "&" : "?") + "callback=?"; } @@ -331,7 +452,10 @@ public class Ajax extends GQuery { if (e == null) { e = document.getDocumentElement(); } - getJsonpImpl(e, url, null, success, error == null ? success : error, timeout); + Deferred dfd = $().as(Deferred.Deferred); + dfd.promise().done(success).fail(error == null ? success : error); + getJsonpImpl(e, url, null, dfd, timeout); + return dfd.promise(); } public static void post(String url, Properties data, final Function onSuccess) { @@ -362,7 +486,7 @@ public class Ajax extends GQuery { // Note: using '\s\S' instead of '.' because gwt String emulation does // not support java embedded flag expressions (?s) and javascript does // not have multidot flag. - String s = getData()[0].toString().replaceAll("]+>\\s*", "") + String s = getArguments()[0].toString().replaceAll("]+>\\s*", "") .replaceAll("\\s*", "") .replaceAll("\\s*", "") .replaceAll("\\s*", "") @@ -388,22 +512,21 @@ public class Ajax extends GQuery { private static int callBackCounter = 0; - public static native void getJsonpImpl(Element elem, String url, String charset, Function success, Function error, int timeout) /*-{ + public static native void getJsonpImpl(Element elem, String url, String charset, Deferred dfd, int timeout) /*-{ var fName = "__GQ_cb_" + @com.google.gwt.query.client.plugins.ajax.Ajax::callBackCounter ++; var done = false; $wnd[fName] = function(data) { if (!done) { done = true; $wnd[fName] = null; - success.@com.google.gwt.query.client.Function::fe(Ljava/lang/Object;)(data); + dfd.@com.google.gwt.query.client.plugins.Deferred::ok(*)(data) } } function err() { if (!done) { done = true; $wnd[fName] = null; - var func = error ? error : success; - func.@com.google.gwt.query.client.Function::fe(Ljava/lang/Object;)(); + dfd.@com.google.gwt.query.client.plugins.Deferred::err(*)(null) } } if (timeout) { @@ -411,7 +534,7 @@ public class Ajax extends GQuery { } url = url.replace(/=\?/g,'=' + fName); - var script = document.createElement("script" ); + var script = document.createElement("script"); script.async = "async"; if (charset) script.charset = charset; script.src = url; diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/callbacks/Callbacks.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/callbacks/Callbacks.java index 0a34b5d5..7ffd510a 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/callbacks/Callbacks.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/callbacks/Callbacks.java @@ -56,7 +56,7 @@ public class Callbacks { return GWT.create(CallbackOptions.class); } - private JsObjectArray callbacks = JsObjectArray.create(); + private JsObjectArray stack = JsObjectArray.create(); private boolean done = false; @@ -119,10 +119,21 @@ public class Callbacks { * Disable a callback list from doing anything more. */ public Callbacks disable() { - callbacks = memory = null; + stack = memory = null; done = true; return this; } + + /** + * lock + */ + public Callbacks lock() { + if (!opts.getMemory()) { + disable(); + } + stack = null; + return this; + } /** * Call all of the callbacks with the given arguments. @@ -130,7 +141,7 @@ public class Callbacks { public Callbacks fire(Object... o) { if (!done) { done = opts.getOnce(); - for (Object c : callbacks.elements()) { + for (Object c : stack.elements()) { if (!run(c, o) && opts.getStopOnFalse()) { break; } @@ -146,15 +157,15 @@ public class Callbacks { * Remove a callback or a collection of callbacks from a callback list. */ public Callbacks remove(Object... o) { - callbacks.remove(o); + stack.remove(o); return this; } private void addAll(Object...o) { - if (callbacks != null) { + if (stack != null) { for (Object c : o) { - if (!opts.getUnique() || !callbacks.contains(c)) { - callbacks.add(c); + if (!opts.getUnique() || !stack.contains(c)) { + stack.add(c); } // In jQuery add always is run when memory is true even when unique is set if (opts.getMemory() && memory != null) { @@ -169,7 +180,8 @@ public class Callbacks { if (c instanceof Callback) { return ((Callback)c).f(o); } else if (c instanceof Function) { - ((Function)c).f(o); + Object r = ((Function)c).f(o); + return (r instanceof Boolean) ? (Boolean)r : true; } else if (c instanceof com.google.gwt.core.client.Callback) { ((com.google.gwt.core.client.Callback)c).onSuccess(o); } diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryDeferredTestGwt.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryDeferredTestGwt.java index 9bcc4884..c7ceb128 100644 --- a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryDeferredTestGwt.java +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryDeferredTestGwt.java @@ -33,12 +33,13 @@ public class GQueryDeferredTestGwt extends GWTTestCase { public void testCallbacks() { Function fn1 = new Function() { - public void f() { + public Object f(Object...arguments) { String s = " f1:"; - for (Object o: getData()){ + for (Object o: arguments){ s += " " + o; } result += s; + return false; } }; @@ -55,8 +56,7 @@ public class GQueryDeferredTestGwt extends GWTTestCase { com.google.gwt.core.client.Callback fn3 = new com.google.gwt.core.client.Callback() { public void onFailure(Object reason) { - String s = " f3_fail: " + reason; - System.out.println(s); + result += " f3_fail: " + reason; } public void onSuccess(Object objects) { String s = " f3_success:"; @@ -112,10 +112,10 @@ public class GQueryDeferredTestGwt extends GWTTestCase { result = ""; callbacks = new Callbacks("stopOnFalse"); - callbacks.add( fn2 ); callbacks.add( fn1 ); + callbacks.add( fn2 ); callbacks.fire( "bar" ); - assertEquals(" f2: bar", result); + assertEquals(" f1: bar", result); result = ""; callbacks.disable(); 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 c833c130..6951f751 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 @@ -953,7 +953,7 @@ public class GQueryEventsTestGwt extends GWTTestCase { public void f(Element elem) { $(elem).css(CSS.FONT_SIZE.with(Length.px(24))); - assertEquals("red", getData()[0]); + assertEquals("red", getArguments()[0]); } }); $("p", e, Events.Events).trigger(Event.ONCLICK); -- 2.39.5