aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorManuel Carrasco <manolo@apache.org>2013-12-23 01:14:04 -0800
committerManuel Carrasco <manolo@apache.org>2013-12-23 01:14:04 -0800
commit25b10eb97f12df4b53ce13b0a56d65deff3b149c (patch)
tree63e43a9d2452aa7ab3d7350ed9c317d343be1790
parentc0d4a56ebfe6b51e75b47654e997b46da5700e2e (diff)
parent4141264c161bcd386286653a35afd371139c610c (diff)
downloadgwtquery-25b10eb97f12df4b53ce13b0a56d65deff3b149c.tar.gz
gwtquery-25b10eb97f12df4b53ce13b0a56d65deff3b149c.zip
Merge pull request #256 from gwtquery/mcm_ajax_progress
done
-rw-r--r--gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsUtils.java7
-rw-r--r--gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/ajax/Ajax.java93
-rw-r--r--gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/deferred/PromiseReqBuilder.java111
-rw-r--r--gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryAjaxTestGwt.java2
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("\"", "'"));
}