com.sksamuel.jqm4gwt.SequentialScriptInjector Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jqm4gwt-remote Show documentation
Show all versions of jqm4gwt-remote Show documentation
jqm4gwt using remote dependencies
The newest version!
package com.sksamuel.jqm4gwt;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import com.google.gwt.core.client.Callback;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.HeadElement;
import com.google.gwt.dom.client.ScriptElement;
/**
* Dynamically injects JS scripts into DOM, strictly one after one (sequentially).
*/
public class SequentialScriptInjector {
private HeadElement head;
private String urlPrefix;
private Callback, Throwable> injectCallback;
private List injectList;
public String getUrlPrefix() {
return urlPrefix;
}
public void setUrlPrefix(String urlPrefix) {
this.urlPrefix = urlPrefix;
}
private void injectDone() {
if (injectCallback == null) return;
List lst = injectList != null ? new ArrayList(injectList.size()) : null;
if (lst != null) {
for (InjectTask t : injectList) lst.add(t.url);
}
injectCallback.onSuccess(lst);
}
private void success(InjectTask task) {
int i = injectList.indexOf(task);
if (i == -1) throw new RuntimeException("Invalid Task: " + task.url);
if (i == injectList.size() - 1) {
injectDone();
return;
}
injectList.get(i + 1).exec();
}
private void failure(InjectTask task, Throwable throwable) {
if (injectCallback != null) injectCallback.onFailure(throwable);
else throw new RuntimeException(task.url, throwable);
}
private static class InjectTask {
final HeadElement head;
final String url;
final SequentialScriptInjector manager;
public InjectTask(HeadElement head, String url, SequentialScriptInjector manager) {
this.head = head;
this.url = url;
this.manager = manager;
}
public void exec() {
// ScriptInjector.fromUrl(url) CANNOT be used here, because it injects scripts into $wnd namespace
ScriptElement script = Document.get().createScriptElement();
script.setSrc(url);
head.appendChild(script);
SequentialScriptInjector.attachListeners(script, new Callback() {
@Override
public void onFailure(Exception reason) {
manager.failure(InjectTask.this, reason);
}
@Override
public void onSuccess(Void result) {
manager.success(InjectTask.this);
}
}, false/*removeTag*/);
}
}
public void inject(Callback, Throwable> done, String... urls) {
injectList = null;
injectCallback = done;
if (urls == null || urls.length == 0) {
injectDone();
return;
}
boolean urlPrefixDefined = urlPrefix != null && !urlPrefix.isEmpty();
List lst = null;
for (String url : urls) {
if (url == null || url.isEmpty()) continue;
if (lst == null) lst = new ArrayList();
InjectTask t = new InjectTask(checkHead(), urlPrefixDefined ? urlPrefix + url : url, this);
lst.add(t);
}
if (lst == null) {
injectDone();
return;
}
injectList = lst;
injectList.get(0).exec();
}
private static HeadElement getHead() {
Element elt = Document.get().getElementsByTagName("head").getItem(0);
if (elt == null) {
throw new RuntimeException("The host HTML page does not have a element"
+ " which is required by StyleInjector");
}
return HeadElement.as(elt);
}
private HeadElement checkHead() {
if (head != null) return head;
head = getHead();
return head;
}
/** Exact copy from ScriptInjector */
private static native void attachListeners(JavaScriptObject scriptElement,
Callback callback, boolean removeTag) /*-{
function clearCallbacks() {
scriptElement.onerror = scriptElement.onreadystatechange = scriptElement.onload = function() {
};
if (removeTag) {
@com.google.gwt.core.client.ScriptInjector::nativeRemove(Lcom/google/gwt/core/client/JavaScriptObject;)(scriptElement);
}
}
scriptElement.onload = $entry(function() {
clearCallbacks();
if (callback) {
[email protected]::onSuccess(Ljava/lang/Object;)(null);
}
});
// or possibly more portable script_tag.addEventListener('error', function(){...}, true);
scriptElement.onerror = $entry(function() {
clearCallbacks();
if (callback) {
var ex = @com.google.gwt.core.client.CodeDownloadException::new(Ljava/lang/String;)("onerror() called.");
[email protected]::onFailure(Ljava/lang/Object;)(ex);
}
});
scriptElement.onreadystatechange = $entry(function() {
if (scriptElement.readyState == 'complete' || scriptElement.readyState == 'loaded') {
scriptElement.onload();
}
});
}-*/;
}