diff options
author | Manuel Carrasco <manolo@apache.org> | 2013-12-23 01:14:04 -0800 |
---|---|---|
committer | Manuel Carrasco <manolo@apache.org> | 2013-12-23 01:14:04 -0800 |
commit | 25b10eb97f12df4b53ce13b0a56d65deff3b149c (patch) | |
tree | 63e43a9d2452aa7ab3d7350ed9c317d343be1790 | |
parent | c0d4a56ebfe6b51e75b47654e997b46da5700e2e (diff) | |
parent | 4141264c161bcd386286653a35afd371139c610c (diff) | |
download | gwtquery-25b10eb97f12df4b53ce13b0a56d65deff3b149c.tar.gz gwtquery-25b10eb97f12df4b53ce13b0a56d65deff3b149c.zip |
Merge pull request #256 from gwtquery/mcm_ajax_progress
done
4 files changed, 141 insertions, 72 deletions
diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsUtils.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsUtils.java index 693ff708..be06f79b 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsUtils.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsUtils.java @@ -316,6 +316,13 @@ public class JsUtils { return Object.prototype.toString.call(o) == '[object Array]' || typeof o.length == 'number'; }-*/; + + /** + * Check is a javascript object is a FormData + */ + public static native boolean isFormData(JavaScriptObject o) /*-{ + return Object.prototype.toString.call(o) == '[object FormData]'; + }-*/; /** * Return whether the event was prevented 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 3c834330..3170c3cb 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 @@ -5,8 +5,6 @@ import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.ScriptInjector; import com.google.gwt.dom.client.Element; import com.google.gwt.http.client.Request; -import com.google.gwt.http.client.RequestBuilder; -import com.google.gwt.http.client.RequestBuilder.Method; import com.google.gwt.http.client.Response; import com.google.gwt.query.client.Function; import com.google.gwt.query.client.GQuery; @@ -18,7 +16,6 @@ import com.google.gwt.query.client.plugins.Plugin; import com.google.gwt.query.client.plugins.deferred.PromiseFunction; import com.google.gwt.query.client.plugins.deferred.PromiseReqBuilder; import com.google.gwt.query.client.plugins.deferred.PromiseReqBuilderJSONP; -import com.google.gwt.user.client.ui.FormPanel; /** * Ajax class for GQuery. @@ -119,8 +116,8 @@ public class Ajax extends GQuery { onError.setElement(settings.getContext()); } - Method httpMethod = resolveHttpMethod(settings); - String data = resolveData(settings, httpMethod); + String httpMethod = settings.getType() == null ? "POST" : settings.getType().toUpperCase(); + Object data = resolveData(settings, httpMethod); final String url = resolveUrl(settings, httpMethod, data); final String dataType = settings.getDataType(); @@ -131,7 +128,7 @@ public class Ajax extends GQuery { } else if ("loadscript".equalsIgnoreCase(dataType)){ ret = createPromiseScriptInjector(url); } else { - ret = createPromiseRequestBuilder(settings, httpMethod, url, data) + ret = new PromiseReqBuilder(settings, httpMethod, url, data) .then(new Function() { public Object f(Object...args) { Response response = (Response)args[0]; @@ -172,45 +169,6 @@ public class Ajax extends GQuery { return ret; } - private static Promise createPromiseRequestBuilder(Settings settings, Method httpMethod, String url, String data) { - - RequestBuilder requestBuilder = new RequestBuilder(httpMethod, url); - - if (data != null && httpMethod != RequestBuilder.GET) { - String ctype = settings.getContentType(); - if (ctype == null) { - String type = settings.getDataType(); - if (type != null && type.toLowerCase().startsWith("json")) { - ctype = "application/json; charset=utf-8"; - } else { - ctype = FormPanel.ENCODING_URLENCODED; - } - } - requestBuilder.setHeader("Content-Type", ctype); - requestBuilder.setRequestData(data); - } - - requestBuilder.setTimeoutMillis(settings.getTimeout()); - - String user = settings.getUsername(); - if (user != null) { - requestBuilder.setUser(user); - } - - String password = settings.getPassword(); - if (password != null) { - requestBuilder.setPassword(password); - } - - Properties headers = settings.getHeaders(); - if (headers != null) { - for (String headerKey : headers.keys()) { - requestBuilder.setHeader(headerKey, headers.getStr(headerKey)); - } - } - - return new PromiseReqBuilder(requestBuilder); - } private static Promise createPromiseScriptInjector(final String url) { return new PromiseFunction() { @@ -228,48 +186,33 @@ public class Ajax extends GQuery { }; } - private static String resolveUrl(Settings settings, Method httpMethod, String data) { + private static String resolveUrl(Settings settings, String httpMethod, Object data) { String url = settings.getUrl(); assert url != null : "no url found in settings"; - if (httpMethod == RequestBuilder.GET && data != null) { + if ("GET".equals(httpMethod) && data instanceof String) { url += (url.contains("?") ? "&" : "?") + data; } return url; } - private static String resolveData(Settings settings, Method httpMethod) { - String data = settings.getDataString(); - if (data == null && settings.getData() != null) { + private static Object resolveData(Settings settings, String httpMethod) { + Object data = settings.getDataString(); + Properties sdata = settings.getData(); + if (data == null && sdata != null) { String type = settings.getDataType(); if (type != null - && (httpMethod == RequestBuilder.POST || httpMethod == RequestBuilder.PUT) + && (httpMethod.matches("(POST|PUT)")) && type.equalsIgnoreCase("json")) { - data = settings.getData().toJsonString(); + data = sdata.toJsonString(); + } else if (JsUtils.isFormData(sdata)) { + data = sdata; } else { - data = settings.getData().toQueryString(); + data = sdata.toQueryString(); } } return data; } - private static Method resolveHttpMethod(Settings settings) { - String method = settings.getType(); - if ("get".equalsIgnoreCase(method)) { - return RequestBuilder.GET; - } else if ("post".equalsIgnoreCase(method)) { - return RequestBuilder.POST; - } else if ("put".equalsIgnoreCase(method)) { - return RequestBuilder.PUT; - } else if ("delete".equalsIgnoreCase(method)) { - return RequestBuilder.DELETE; - } else if ("head".equalsIgnoreCase(method)) { - return RequestBuilder.HEAD; - } - - GWT.log("GQuery.Ajax: no method type provided, using POST as default method"); - return RequestBuilder.POST; - } - public static Promise ajax(String url, Function onSuccess, Function onError) { return ajax(url, onSuccess, onError, (Settings) null); } @@ -384,6 +327,10 @@ public class Ajax extends GQuery { ); } + public static Promise post(String url, Properties data) { + return post(url, data, null); + } + public static Promise post(String url, Properties data, final Function onSuccess) { Settings s = createSettings(); s.setUrl(url); @@ -398,6 +345,10 @@ public class Ajax extends GQuery { super(gq); } + public Ajax load(String url, Properties data) { + return load(url, data); + } + public Ajax load(String url, Properties data, final Function onSuccess) { Settings s = createSettings(); final String filter = url.contains(" ") ? url.replaceFirst("^[^\\s]+\\s+", "") : ""; diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/deferred/PromiseReqBuilder.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/deferred/PromiseReqBuilder.java index 9486b64d..c19cf704 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/deferred/PromiseReqBuilder.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/deferred/PromiseReqBuilder.java @@ -13,12 +13,23 @@ package com.google.gwt.query.client.plugins.deferred; * or implied. See the License for the specific language governing permissions and limitations under * the License. */ +import com.google.gwt.core.client.JavaScriptException; +import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.http.client.Request; import com.google.gwt.http.client.RequestBuilder; import com.google.gwt.http.client.RequestCallback; import com.google.gwt.http.client.RequestException; +import com.google.gwt.http.client.RequestPermissionException; import com.google.gwt.http.client.Response; +import com.google.gwt.query.client.Function; +import com.google.gwt.query.client.Properties; +import com.google.gwt.query.client.js.JsCache; +import com.google.gwt.query.client.js.JsUtils; +import com.google.gwt.query.client.plugins.ajax.Ajax.Settings; import com.google.gwt.query.client.plugins.deferred.Deferred.DeferredPromiseImpl; +import com.google.gwt.user.client.ui.FormPanel; +import com.google.gwt.xhr.client.ReadyStateChangeHandler; +import com.google.gwt.xhr.client.XMLHttpRequest; /** * Utility class used to create promises for RequestBuilder. @@ -38,6 +49,7 @@ import com.google.gwt.query.client.plugins.deferred.Deferred.DeferredPromiseImpl * </pre> */ public class PromiseReqBuilder extends DeferredPromiseImpl implements RequestCallback { + public PromiseReqBuilder(RequestBuilder builder) { builder.setCallback(this); try { @@ -46,6 +58,91 @@ public class PromiseReqBuilder extends DeferredPromiseImpl implements RequestCal onError(null, e); } } + + /** + * Using this constructor we access to some things in the xmlHttpRequest + * which are not available in GWT, like adding progress handles or sending + * javascript data (like forms in modern html5 file api) + */ + public PromiseReqBuilder(Settings settings, String httpMethod, String url, Object data) { + XMLHttpRequest xmlHttpRequest = XMLHttpRequest.create(); + try { + if (settings.getUsername() != null && settings.getPassword() != null) { + xmlHttpRequest.open(httpMethod, url, settings.getUsername(), settings.getPassword()); + } else if (settings.getUsername() != null) { + xmlHttpRequest.open(httpMethod, url, settings.getUsername()); + } else { + xmlHttpRequest.open(httpMethod, url); + } + } catch (JavaScriptException e) { + RequestPermissionException requestPermissionException = new RequestPermissionException(url); + requestPermissionException.initCause(new RequestException(e.getMessage())); + onError(null, e); + return; + } + + JsUtils.prop(xmlHttpRequest, "onprogress", JsUtils.wrapFunction(new Function() { + public void f() { + JsCache p = arguments(0); + double total = p.getDouble("total"); + double loaded = p.getDouble("loaded"); + double percent = 100 * loaded / total; + dfd.notify(total, loaded, percent, "download"); + } + })); + + JavaScriptObject upload = JsUtils.prop(xmlHttpRequest, "upload"); + JsUtils.prop(upload, "onprogress", JsUtils.wrapFunction(new Function() { + public void f() { + JsCache p = arguments(0); + double total = p.getDouble("total"); + double loaded = p.getDouble("loaded"); + double percent = 100 * loaded / total; + dfd.notify(total, loaded, percent, "upload"); + } + })); + + Properties headers = settings.getHeaders(); + if (headers != null) { + for (String headerKey : headers.keys()) { + xmlHttpRequest.setRequestHeader(headerKey, headers.getStr(headerKey)); + } + } + + if (data != null && !"GET".equalsIgnoreCase(httpMethod)) { + String ctype = settings.getContentType(); + if (data instanceof JavaScriptObject && JsUtils.isFormData((JavaScriptObject)data)) { + ctype = FormPanel.ENCODING_MULTIPART;; + } else if (ctype == null) { + String type = settings.getDataType(); + if (type != null && type.toLowerCase().startsWith("json")) { + ctype = "application/json; charset=utf-8"; + } else { + ctype = FormPanel.ENCODING_URLENCODED; + } + } + xmlHttpRequest.setRequestHeader("Content-Type", ctype); + } + + xmlHttpRequest.setWithCredentials(true); + + final Request request = createRequestVltr(xmlHttpRequest, settings.getTimeout(), this); + + xmlHttpRequest.setOnReadyStateChange(new ReadyStateChangeHandler() { + public void onReadyStateChange(XMLHttpRequest xhr) { + if (xhr.getReadyState() == XMLHttpRequest.DONE) { + xhr.clearOnReadyStateChange(); + fireOnResponseReceivedVltr(request, PromiseReqBuilder.this); + } + } + }); + + try { + JsUtils.runJavascriptFunction(xmlHttpRequest, "send", data); + } catch (JavaScriptException e) { + onError(null, e); + } + } public void onError(Request request, Throwable exception) { dfd.reject(exception, request); @@ -60,4 +157,18 @@ public class PromiseReqBuilder extends DeferredPromiseImpl implements RequestCal dfd.resolve(response, request); } } + + /** + * Using violator pattern to execute private method + */ + private native void fireOnResponseReceivedVltr(Request rq, RequestCallback cb) /*-{ + rq.@com.google.gwt.http.client.Request::fireOnResponseReceived(Lcom/google/gwt/http/client/RequestCallback;)(cb); + }-*/; + + /** + * Using violator pattern to use protected constructor + */ + private native Request createRequestVltr(XMLHttpRequest rq, int ms, RequestCallback cb) /*-{ + return @com.google.gwt.http.client.Request::new(Lcom/google/gwt/xhr/client/XMLHttpRequest;ILcom/google/gwt/http/client/RequestCallback;)(rq, + }-*/; } diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryAjaxTestGwt.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryAjaxTestGwt.java index 4d27f41a..695e1d01 100644 --- a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryAjaxTestGwt.java +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryAjaxTestGwt.java @@ -131,7 +131,7 @@ public class GQueryAjaxTestGwt extends GWTTestCase { c.setItems(Arrays.asList(items)); assertEquals(2000l, c.getItems().get(0).getDate().getTime()); assertEquals(3000l, c.getItems().get(1).getDate().getTime()); - String s = "{'M':0,'a':1,'b':{'a':2,'b':{'a':3}},'u':'url','d':1234,'t':['foo','bar'],'z':false,'y':'y','items':[{'date':2000},{'date':3000}] + String s = "{'M':0,'a':1,'b':{'a':2,'b':{'a':3}},'u':'url','d':1234,'t':['foo','bar'],'z':false,'y':'y','items':[{'date':2000},{'date':3000}]"; assertEquals(s, c.toString().replaceAll("\"", "'")); } |