aboutsummaryrefslogtreecommitdiffstats
path: root/client
diff options
context:
space:
mode:
authorArtur <artur@vaadin.com>2017-01-25 11:27:49 +0200
committerGitHub <noreply@github.com>2017-01-25 11:27:49 +0200
commitbe694984fb35262b32c89be075e6d4a059931b62 (patch)
treed66a85f91404b5bb7f82d845a25b96ec9cebf350 /client
parente397ea01e5ddb0c977561c008b84c6ed7c0ef706 (diff)
downloadvaadin-framework-be694984fb35262b32c89be075e6d4a059931b62.tar.gz
vaadin-framework-be694984fb35262b32c89be075e6d4a059931b62.zip
Support loading of HTML imports using @HtmlImport (#8301)
Note that not all browsers yet support HTML imports. If a polyfill is needed to load HTML imports, it must be loaded before HTML Imports can be loaded. There is no automatic loading of any polyfills.
Diffstat (limited to 'client')
-rw-r--r--client/src/main/java/com/vaadin/client/DependencyLoader.java113
-rw-r--r--client/src/main/java/com/vaadin/client/ResourceLoader.java52
2 files changed, 96 insertions, 69 deletions
diff --git a/client/src/main/java/com/vaadin/client/DependencyLoader.java b/client/src/main/java/com/vaadin/client/DependencyLoader.java
index d217c824b2..4a8e054a54 100644
--- a/client/src/main/java/com/vaadin/client/DependencyLoader.java
+++ b/client/src/main/java/com/vaadin/client/DependencyLoader.java
@@ -17,7 +17,7 @@ package com.vaadin.client;
import java.util.logging.Logger;
-import com.google.gwt.core.client.JsArrayString;
+import com.google.gwt.core.client.JsArray;
import com.google.gwt.user.client.Command;
import com.vaadin.client.ResourceLoader.ResourceLoadEvent;
import com.vaadin.client.ResourceLoader.ResourceLoadListener;
@@ -34,10 +34,31 @@ import com.vaadin.client.ResourceLoader.ResourceLoadListener;
*/
public class DependencyLoader {
- private static final String STYLE_DEPENDENCIES = "styleDependencies";
- private static final String SCRIPT_DEPENDENCIES = "scriptDependencies";
+ private static final String DEPENDENCIES = "dependencies";
private ApplicationConnection connection = null;
+ private ResourceLoader loader = ResourceLoader.get();
+
+ private ResourceLoadListener dependencyLoadingTracker = new ResourceLoadListener() {
+
+ @Override
+ public void onLoad(ResourceLoadEvent event) {
+ ApplicationConfiguration.endDependencyLoading();
+ }
+
+ @Override
+ public void onError(ResourceLoadEvent event) {
+ String error = event.getResourceUrl() + " could not be loaded.";
+ if (event.getResourceUrl().endsWith("css")) {
+ error += " or the load detection failed because the stylesheet is empty.";
+ }
+ getLogger().severe(error);
+ // The show must go on
+ onLoad(event);
+ }
+
+ };
+
/**
* Sets the ApplicationConnection this instance is connected to.
*
@@ -61,83 +82,43 @@ public class DependencyLoader {
/**
* Loads the any dependencies present in the given json snippet.
*
- * Scans the key "{@literal scriptDependencies}" for JavaScripts and the key
- * "{@literal styleDependencies}" for style sheets.
+ * Handles all dependencies found with the key "{@literal dependencies}".
*
- * Ensures that the given JavaScript dependencies are loaded in the given
- * order. Does not ensure anything about stylesheet order.
+ * Ensures that
+ * <ul>
+ * <li>JavaScript dependencies are loaded in the given order.
+ * <li>HTML imports are loaded after all JavaScripts are loaded and
+ * executed.
+ * <li>Style sheets are loaded and evaluated in some undefined order
+ * </ul>
*
* @param json
* the JSON containing the dependencies to load
*/
public void loadDependencies(ValueMap json) {
- if (json.containsKey(SCRIPT_DEPENDENCIES)) {
- loadScriptDependencies(json.getJSStringArray(SCRIPT_DEPENDENCIES));
- }
- if (json.containsKey(STYLE_DEPENDENCIES)) {
- loadStyleDependencies(json.getJSStringArray(STYLE_DEPENDENCIES));
- }
-
- }
-
- private void loadStyleDependencies(JsArrayString dependencies) {
- // Assuming no reason to interpret in a defined order
- ResourceLoadListener resourceLoadListener = new ResourceLoadListener() {
- @Override
- public void onLoad(ResourceLoadEvent event) {
- ApplicationConfiguration.endDependencyLoading();
- }
-
- @Override
- public void onError(ResourceLoadEvent event) {
- getLogger().severe(event.getResourceUrl()
- + " could not be loaded, or the load detection failed because the stylesheet is empty.");
- // The show must go on
- onLoad(event);
- }
- };
- ResourceLoader loader = ResourceLoader.get();
- for (int i = 0; i < dependencies.length(); i++) {
- String url = translateVaadinUri(dependencies.get(i));
- ApplicationConfiguration.startDependencyLoading();
- loader.loadStylesheet(url, resourceLoadListener);
- }
- }
-
- private void loadScriptDependencies(final JsArrayString dependencies) {
- if (dependencies.length() == 0) {
+ if (!json.containsKey(DEPENDENCIES)) {
return;
}
+ JsArray<ValueMap> deps = json.getJSValueMapArray(DEPENDENCIES);
- // Listener that loads the next when one is completed
- ResourceLoadListener resourceLoadListener = new ResourceLoadListener() {
- @Override
- public void onLoad(ResourceLoadEvent event) {
- // Call start for next before calling end for current
+ for (int i = 0; i < deps.length(); i++) {
+ ValueMap dep = deps.get(i);
+ String type = dep.getAsString("type");
+ String url = connection.translateVaadinUri(dep.getAsString("url"));
+ ApplicationConfiguration.startDependencyLoading();
+ if (type.equals("STYLESHEET")) {
+ loader.loadStylesheet(url, dependencyLoadingTracker);
+ } else if (type.equals("JAVASCRIPT")) {
+ loader.loadScript(url, dependencyLoadingTracker);
+ } else if (type.equals("HTMLIMPORT")) {
+ loader.loadHtmlImport(url, dependencyLoadingTracker);
+ } else {
ApplicationConfiguration.endDependencyLoading();
+ throw new IllegalArgumentException("Unknown type: " + type);
}
-
- @Override
- public void onError(ResourceLoadEvent event) {
- getLogger().severe(
- event.getResourceUrl() + " could not be loaded.");
- // The show must go on
- onLoad(event);
- }
- };
-
- ResourceLoader loader = ResourceLoader.get();
- for (int i = 0; i < dependencies.length(); i++) {
- ApplicationConfiguration.startDependencyLoading();
- String preloadUrl = translateVaadinUri(dependencies.get(i));
- loader.loadScript(preloadUrl, resourceLoadListener);
}
}
- private String translateVaadinUri(String url) {
- return connection.translateVaadinUri(url);
- }
-
private static Logger getLogger() {
return Logger.getLogger(DependencyLoader.class.getName());
}
diff --git a/client/src/main/java/com/vaadin/client/ResourceLoader.java b/client/src/main/java/com/vaadin/client/ResourceLoader.java
index a20daced44..f58453ced5 100644
--- a/client/src/main/java/com/vaadin/client/ResourceLoader.java
+++ b/client/src/main/java/com/vaadin/client/ResourceLoader.java
@@ -135,7 +135,7 @@ public class ResourceLoader {
Document document = Document.get();
head = document.getElementsByTagName("head").getItem(0);
- // detect already loaded scripts and stylesheets
+ // detect already loaded scripts, html imports and stylesheets
NodeList<Element> scripts = document.getElementsByTagName("script");
for (int i = 0; i < scripts.getLength(); i++) {
ScriptElement element = ScriptElement.as(scripts.getItem(i));
@@ -154,6 +154,10 @@ public class ResourceLoader {
&& href.length() != 0) {
loadedResources.add(href);
}
+ if ("import".equalsIgnoreCase(rel) && href != null
+ && href.length() != 0) {
+ loadedResources.add(href);
+ }
}
}
@@ -215,6 +219,48 @@ public class ResourceLoader {
}
/**
+ * Loads an HTML import and notify a listener when the HTML import is
+ * loaded. Calling this method when the HTML import is currently loading or
+ * already loaded doesn't cause the HTML import to be loaded again, but the
+ * listener will still be notified when appropriate.
+ *
+ * @param htmlUrl
+ * url of HTML import to load
+ * @param resourceLoadListener
+ * listener to notify when the HTML import is loaded
+ */
+ public void loadHtmlImport(final String htmlUrl,
+ final ResourceLoadListener resourceLoadListener) {
+ final String url = WidgetUtil.getAbsoluteUrl(htmlUrl);
+ ResourceLoadEvent event = new ResourceLoadEvent(this, url);
+ if (loadedResources.contains(url)) {
+ if (resourceLoadListener != null) {
+ resourceLoadListener.onLoad(event);
+ }
+ return;
+ }
+
+ if (addListener(url, resourceLoadListener, loadListeners)) {
+ LinkElement linkTag = Document.get().createLinkElement();
+ linkTag.setAttribute("rel", "import");
+ linkTag.setAttribute("href", url);
+
+ addOnloadHandler(linkTag, new ResourceLoadListener() {
+ @Override
+ public void onLoad(ResourceLoadEvent event) {
+ fireLoad(event);
+ }
+
+ @Override
+ public void onError(ResourceLoadEvent event) {
+ fireError(event);
+ }
+ }, event);
+ head.appendChild(linkTag);
+ }
+ }
+
+ /**
* Adds an onload listener to the given element, which should be a link or a
* script tag. The listener is called whenever loading is complete or an
* error occurred.
@@ -355,12 +401,12 @@ public class ResourceLoader {
if (rules === undefined) {
rules = sheet.rules;
}
-
+
if (rules === null) {
// Style sheet loaded, but can't access length because of XSS -> assume there's something there
return 1;
}
-
+
// Return length so we can distinguish 0 (probably 404 error) from normal case.
return rules.length;
} catch (err) {