From: Manolo Carrasco Date: Wed, 8 Feb 2012 11:55:08 +0000 (+0000) Subject: Implementation of Ajax JSONP using script tags X-Git-Tag: release-1.3.2~123 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=1b2bc50acd572a992e5178a205501c2a5b96d0b2;p=gwtquery.git Implementation of Ajax JSONP using script tags --- 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 75a023ce..08f6415d 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 @@ -40,7 +40,7 @@ public abstract class Function { public void setEvent(Event e) { event = e; - element = e.getCurrentEventTarget().cast(); + element = e != null ? e.getCurrentEventTarget().cast() : null; } public Event getEvent() { @@ -59,6 +59,38 @@ public abstract class Function { this.data = data; } + public Object getDataObject() { + return getDataObject(0); + } + + public Object getDataObject(int idx) { + return data.length > idx ? data[idx] : null; + } + + public Properties getDataProperties() { + return getDataProperties(0); + } + + public Properties getDataProperties(int idx) { + Object o = getDataObject(idx); + if (o != null && o instanceof JavaScriptObject) { + return (Properties)o; + } + return null; + } + + public void setData(boolean b) { + setData(Boolean.valueOf(b)); + } + + public void setData(double b) { + setData(Double.valueOf(b)); + } + + public void setDataObject(Object data) { + setData(data); + } + public int getIndex() { return index; } @@ -183,7 +215,7 @@ public abstract class Function { */ public boolean f(Event e) { setEvent(e); - f(e.getCurrentEventTarget().cast()); + f(element); return true; } @@ -208,7 +240,7 @@ public abstract class Function { private boolean loop = false; public void f(com.google.gwt.user.client.Element e) { setElement(e); - Widget w = GQuery.getAssociatedWidget(e); + Widget w = e != null ? GQuery.getAssociatedWidget(e) : null; if (w != null){ loop = true; f(w); 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 2bc9aa45..bf64308d 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 @@ -77,6 +77,8 @@ public class JsCache extends JavaScriptObject { } public final native double getDouble(T id) /*-{ + // HtmlUnit prints an 'Unknown property name in get valueOf' + // error here, but it is ok. var r = this[id] ? Number(this[id]) : 0; return r ? r : 0; }-*/; 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 d2881c28..d30020c5 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 @@ -11,6 +11,7 @@ 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.Properties; +import com.google.gwt.query.client.builders.JsonBuilder; import com.google.gwt.query.client.js.JsUtils; import com.google.gwt.query.client.plugins.Plugin; @@ -33,159 +34,33 @@ public class Ajax extends GQuery { /** * Ajax Settings object */ - public static class Settings { - - private static final String CONTENT_TYPE_KEY = "contentType"; - private static final String CONTEXT_KEY = "context"; - private static final String DATA_KEY = "data"; - private static final String DATA_STRING_KEY = "dataString"; - private static final String DATA_TYPE_KEY = "dataType"; - private static final String HEADERS_KEY = "headers"; - private static final String PASSWORD_KEY = "password"; - private static final String TIMEOUT_KEY = "timeout"; - private static final String TYPE_KEY = "type"; - private static final String URL_KEY = "url"; - private static final String USERNAME_KEY = "username"; - - public Properties settings; - public Function onSuccess; - public Function onError; - - public Settings() { - settings = Properties.create(); - initDefaults(); - } - - /** - * Init some settings with default value - */ - private void initDefaults() { - setDataType("text"); - setType("POST"); - setContentType("application/x-www-form-urlencoded"); - } - - public String getContentType() { - return settings.getStr(CONTENT_TYPE_KEY); - } - - public Element getContext() { - return settings.get(CONTEXT_KEY); - } - - public Properties getData() { - return settings.get(DATA_KEY); - } - - public String getDataString() { - return settings.get(DATA_STRING_KEY); - } - - public String getDataType() { - return settings.get(DATA_TYPE_KEY); - } - - public Function getError() { - return onError; - } - - public Properties getHeaders() { - return settings.get(HEADERS_KEY); - } - - public String getPassword() { - return settings.get(PASSWORD_KEY); - } - - public Function getSuccess() { - return onSuccess; - } - - public int getTimeout() { - Integer timeout = settings.get(TIMEOUT_KEY); - return timeout != null ? timeout.intValue() : 0; - } - - public String getType() { - return settings.get(TYPE_KEY); - } - - public String getUrl() { - return settings.get(URL_KEY); - } - - public String getUsername() { - return settings.get(USERNAME_KEY); - } - - public Settings setContentType(String t) { - settings.set(CONTENT_TYPE_KEY, t); - return this; - } - - public Settings setContext(Element e) { - settings.set(CONTEXT_KEY, e); - return this; - } - - public Settings setData(Properties p) { - settings.set(DATA_KEY, p); - return this; - } - - public Settings setDataString(String d) { - settings.set(DATA_STRING_KEY, d); - return this; - } - - public Settings setDataType(String t) { - settings.set(DATA_TYPE_KEY, t); - return this; - } - - public Settings setError(Function f) { - onError = f; - return this; - } - - public Settings setHeaders(Properties p) { - settings.set(HEADERS_KEY, p); - return this; - } - - public Settings setPassword(String p) { - settings.set(PASSWORD_KEY, p); - return this; - } - - public Settings setSuccess(Function f) { - onSuccess = f; - return this; - } - - public Settings setTimeout(int t) { - settings.set(TIMEOUT_KEY, t); - return this; - } - - public Settings setType(String t) { - settings.set(TYPE_KEY, t); - return this; - } - - public Settings setUrl(String u) { - settings.set(URL_KEY, u); - return this; - } - - public Settings setUsername(String u) { - settings.set(USERNAME_KEY, u); - return this; - } - - public void load(Properties p) { - settings = p; - } + public interface Settings extends JsonBuilder { + String getContentType(); + Element getContext(); + Properties getData(); + String getDataString(); + String getDataType(); + Function getError(); + Properties getHeaders(); + String getPassword(); + Function getSuccess(); + int getTimeout(); + String getType(); + String getUrl(); + String getUsername(); + Settings setContentType(String t); + Settings setContext(Element e); + Settings setData(Properties p); + Settings setDataString(String d); + Settings setDataType(String t); + Settings setError(Function f); + Settings setHeaders(Properties p); + Settings setPassword(String p); + Settings setSuccess(Function f); + Settings setTimeout(int t); + Settings setType(String t); + Settings setUrl(String u); + Settings setUsername(String u); } public static final Class Ajax = registerPlugin(Ajax.class, new Plugin() { @@ -229,10 +104,6 @@ public class Ajax extends GQuery { */ public static void ajax(Settings settings) { - final RequestBuilder requestBuilder = createRequestBuilder(settings); - - final String dataType = settings.getDataType(); - final Function onSuccess = settings.getSuccess(); if (onSuccess != null) { @@ -244,6 +115,19 @@ public class Ajax extends GQuery { if (onError != null) { onError.setElement(settings.getContext()); } + + + final String dataType = settings.getDataType(); + if ("jsonp".equalsIgnoreCase(dataType)) { + Method httpMethod = resolveHttpMethod(settings); + String data = resolveData(settings); + String url = resolveUrl(settings, httpMethod, data); + int timeout = settings.getTimeout(); + getJSONP(url, onSuccess, onError, timeout); + return; + } + + final RequestBuilder requestBuilder = createRequestBuilder(settings); requestBuilder.setCallback(new RequestCallback() { @@ -323,7 +207,6 @@ public class Ajax extends GQuery { } private static String resolveUrl(Settings settings, Method httpMethod, String data) { - String url = settings.getUrl(); assert url != null : "no url found in settings"; @@ -331,7 +214,6 @@ public class Ajax extends GQuery { if (data != null && httpMethod == RequestBuilder.GET) { url += (url.contains("?") ? "&" : "?") + data; } - return url; } @@ -341,18 +223,15 @@ public class Ajax extends GQuery { if (data == null && settings.getData() != null) { data = settings.getData().toQueryString(); } - return data; } private static Method resolveHttpMethod(Settings settings) { - String method = settings.getType(); if ("get".equalsIgnoreCase(method)) { return RequestBuilder.GET; } - return RequestBuilder.POST; } @@ -380,7 +259,7 @@ public class Ajax extends GQuery { } public static Settings createSettings() { - return new Settings(); + return createSettings($$("")); } public static Settings createSettings(String prop) { @@ -412,6 +291,30 @@ public class Ajax extends GQuery { s.setSuccess(onSuccess); ajax(s); } + + public static void getJSONP(String url, Properties data, Function onSuccess) { + Settings s = createSettings(); + s.setUrl(url); + s.setDataType("jsonp"); + s.setType("get"); + s.setData(data); + s.setSuccess(onSuccess); + ajax(s); + } + + public static void getJSONP(String url, Function success, Function error, int timeout) { + System.err.println("EEE"); + + if (!url.contains("=?")) { + url += (url.contains("?") ? "&" : "?") + "callback=?"; + } + url += "&_=" + System.currentTimeMillis(); + Element e = $("head").get(0); + if (e == null) { + e = document.getDocumentElement(); + } + getJsonpImpl(e, url, null, success, error == null ? success : error, timeout); + } public static void post(String url, Properties data, final Function onSuccess) { Settings s = createSettings(); @@ -447,4 +350,42 @@ public class Ajax extends GQuery { ajax(s); return this; } + + private static int callBackCounter = 0; + + public static native void getJsonpImpl(Element elem, String url, String charset, Function success, Function error, 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::setDataObject(Ljava/lang/Object;)(data); + success.@com.google.gwt.query.client.Function::f()(); + } + } + function err() { + if (!done) { + done = true; + $wnd[fName] = null; + if (error) error.@com.google.gwt.query.client.Function::f()(); + else success.@com.google.gwt.query.client.Function::f()(); + } + } + if (timeout) { + setTimeout(err, timeout); + } + + url = url.replace(/=\?/g,'=' + fName); + var script = document.createElement("script" ); + script.async = "async"; + if (charset) script.charset = charset; + script.src = url; + script.onload = script.onreadystatechange = function(evt) { + script.onload = script.onreadystatechange = null; + elem.removeChild(script); + err(); + }; + elem.insertBefore(script, elem.firstChild); + }-*/; } 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 5d3e8d68..98a85094 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 @@ -24,10 +24,14 @@ import java.util.List; import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.Element; +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.builders.JsonBuilder; import com.google.gwt.query.client.builders.Name; import com.google.gwt.query.client.builders.XmlBuilder; +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.ui.HTML; import com.google.gwt.user.client.ui.RootPanel; @@ -81,7 +85,7 @@ public class GQueryAjaxTestGwt extends GWTTestCase { } public void testJsonBuilder() { - String json = "[{a:1, b:{a:2,b:{a:3}},u:url, d:'2','t':['hola','adios'], 'z': true}]"; + String json = "{a:1, b:{a:2,b:{a:3}},u:url, d:'2','t':['hola','adios'], 'z': true}"; JsonExample c = GWT.create(JsonExample.class); assertEquals(0, c.getA()); c.parse(json, true); @@ -140,4 +144,52 @@ public class GQueryAjaxTestGwt extends GWTTestCase { assertEquals("X", x.getA()); assertEquals(1234, x.getNumber()); } + + public void testJsonValidService() { + delayTestFinish(5000); + String testJsonpUrl = "http://services.digg.com/stories/top?appkey=http://mashup.com&type=javascript&callback=?"; + Ajax.getJSONP(testJsonpUrl, new Function(){ + public void f() { + Properties p = getDataProperties(); + assertTrue(0 < p.getInt("count")); + finishTest(); + } + }, null, 0); + } + + @DoNotRunWith({Platform.HtmlUnitLayout}) + public void testJsonNonCallbackResponse() { + delayTestFinish(5000); + String testJsonpUrl = "http://www.google.com"; + Ajax.getJSONP(testJsonpUrl, null, new Function(){ + public void f() { + Properties p = getDataProperties(); + assertNull(p); + finishTest(); + } + }, 500); + } + + public void testJsonTimeout() { + delayTestFinish(5000); + String nonJsonpUrl = "http://www.google.com/nopage"; + + Settings s = Ajax.createSettings(); + s.setTimeout(400); + 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); + } + }