diff --git a/html-imports.js b/html-imports.js
index 2477ffb..9c97b9c 100644
--- a/html-imports.js
+++ b/html-imports.js
@@ -11,6 +11,7 @@ var scopeName = 'HTMLImports';
var modules = [
'src/scope.js',
'src/path.js',
+ 'src/Loader.js',
'src/HTMLImports.js',
'src/Parser.js',
'src/boot.js'
diff --git a/src/HTMLImports.js b/src/HTMLImports.js
index ff086ca..d093a90 100644
--- a/src/HTMLImports.js
+++ b/src/HTMLImports.js
@@ -13,6 +13,7 @@ if (!useNative) {
// imports
var path = scope.path;
+ var Loader = scope.Loader;
var xhr = scope.xhr;
// importer
@@ -33,7 +34,7 @@ if (!useNative) {
// linked style sheets in an are loaded, and the content gets path fixups
// inline style sheets get path fixups when their containing import modifies paths
- var loader;
+ var importLoader;
var IMPORT_LINK_TYPE = 'import';
var STYLE_LINK_TYPE = 'stylesheet';
@@ -47,30 +48,30 @@ if (!useNative) {
'script[src][type="text/javascript"]'
].join(','),
loader: function(next) {
- if (loader && loader.inflight) {
- var currentComplete = loader.oncomplete;
- loader.oncomplete = function() {
+ if (importLoader && importLoader.inflight) {
+ var currentComplete = importLoader.oncomplete;
+ importLoader.oncomplete = function() {
currentComplete();
next();
}
- return loader;
+ return importLoader;
}
// construct a loader instance
- loader = new Loader(importer.loaded, next);
+ importLoader = new Loader(importer.loaded, next);
// alias the importer cache (for debugging)
- loader.cache = importer.cache;
- return loader;
+ importLoader.cache = importer.cache;
+ return importLoader;
},
load: function(doc, next) {
// get a loader instance from the factory
- loader = importer.loader(next);
+ importLoader = importer.loader(next);
// add nodes from document into loader queue
importer.preload(doc);
},
preload: function(doc) {
var nodes = this.marshalNodes(doc);
// add these nodes to loader's queue
- loader.addNodes(nodes);
+ importLoader.addNodes(nodes);
},
marshalNodes: function(doc) {
// all preloadable nodes in inDocument
@@ -188,178 +189,13 @@ if (!useNative) {
return doc;
}
- var Loader = function(onLoad, onComplete) {
- this.onload = onLoad;
- this.oncomplete = onComplete;
- this.inflight = 0;
- this.pending = {};
- this.cache = {};
- };
-
- Loader.prototype = {
- addNodes: function(nodes) {
- // number of transactions to complete
- this.inflight += nodes.length;
- // commence transactions
- forEach(nodes, this.require, this);
- // anything to do?
- this.checkDone();
- },
- require: function(elt) {
- var url = path.nodeUrl(elt);
- // ensure we have a standard url that can be used
- // reliably for deduping.
- url = path.makeAbsUrl(url);
- // TODO(sjmiles): ad-hoc
- elt.__nodeUrl = url;
- // deduplication
- if (!this.dedupe(url, elt)) {
- // fetch this resource
- this.fetch(url, elt);
- }
- },
- dedupe: function(url, elt) {
- if (this.pending[url]) {
- // add to list of nodes waiting for inUrl
- this.pending[url].push(elt);
- // don't need fetch
- return true;
- }
- if (this.cache[url]) {
- // complete load using cache data
- this.onload(url, elt, loader.cache[url]);
- // finished this transaction
- this.tail();
- // don't need fetch
- return true;
- }
- // first node waiting for inUrl
- this.pending[url] = [elt];
- // need fetch (not a dupe)
- return false;
- },
- fetch: function(url, elt) {
- var receiveXhr = function(err, resource) {
- this.receive(url, elt, err, resource);
- }.bind(this);
- xhr.load(url, receiveXhr);
- // TODO(sorvell): blocked on
- // https://code.google.com/p/chromium/issues/detail?id=257221
- // xhr'ing for a document makes scripts in imports runnable; otherwise
- // they are not; however, it requires that we have doctype=html in
- // the import which is unacceptable. This is only needed on Chrome
- // to avoid the bug above.
- /*
- if (isDocumentLink(elt)) {
- xhr.loadDocument(url, receiveXhr);
- } else {
- xhr.load(url, receiveXhr);
- }
- */
- },
- receive: function(url, elt, err, resource) {
- if (!err) {
- loader.cache[url] = resource;
- }
- loader.pending[url].forEach(function(e) {
- if (!err) {
- this.onload(url, e, resource);
- }
- this.tail();
- }, this);
- loader.pending[url] = null;
- },
- tail: function() {
- --this.inflight;
- this.checkDone();
- },
- checkDone: function() {
- if (!this.inflight) {
- this.oncomplete();
- }
- }
- };
-
- xhr = xhr || {
- async: true,
- ok: function(request) {
- return (request.status >= 200 && request.status < 300)
- || (request.status === 304)
- || (request.status === 0);
- },
- load: function(url, next, nextContext) {
- var request = new XMLHttpRequest();
- if (scope.flags.debug || scope.flags.bust) {
- url += '?' + Math.random();
- }
- request.open('GET', url, xhr.async);
- request.addEventListener('readystatechange', function(e) {
- if (request.readyState === 4) {
- next.call(nextContext, !xhr.ok(request) && request,
- request.response || request.responseText, url);
- }
- });
- request.send();
- return request;
- },
- loadDocument: function(url, next, nextContext) {
- this.load(url, next, nextContext).responseType = 'document';
- }
- };
-
var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);
// exports
- scope.xhr = xhr;
scope.importer = importer;
scope.IMPORT_LINK_TYPE = IMPORT_LINK_TYPE;
} else {
// do nothing if using native imports
- /*
- // TODO(sorvell): this exists as a load extension point.
- importer.preloadSelectors = [
- 'template'
- ].join(',');
-
- function forEachImport(imp, cb) {
- if (cb) {
- cb(imp);
- }
- var n$ = imp.querySelectorAll('link[rel=' + IMPORT_LINK_TYPE + ']');
- for (var i=0, l=n$.length, n; (i= 200 && request.status < 300)
+ || (request.status === 304)
+ || (request.status === 0);
+ },
+ load: function(url, next, nextContext) {
+ var request = new XMLHttpRequest();
+ if (scope.flags.debug || scope.flags.bust) {
+ url += '?' + Math.random();
+ }
+ request.open('GET', url, xhr.async);
+ request.addEventListener('readystatechange', function(e) {
+ if (request.readyState === 4) {
+ next.call(nextContext, !xhr.ok(request) && request,
+ request.response || request.responseText, url);
+ }
+ });
+ request.send();
+ return request;
+ },
+ loadDocument: function(url, next, nextContext) {
+ this.load(url, next, nextContext).responseType = 'document';
+ }
+ };
+
+ var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);
+
+ // exports
+ scope.xhr = xhr;
+ scope.Loader = Loader;
+
+})(window.HTMLImports);
diff --git a/src/boot.js b/src/boot.js
index 7d12744..c2dbd15 100644
--- a/src/boot.js
+++ b/src/boot.js
@@ -35,7 +35,7 @@ function notifyReady() {
}
if (HTMLImports.useNative) {
- notifyReady();
+ //notifyReady();
} else {
function bootstrap() {
// preload document resource trees
@@ -56,6 +56,10 @@ if (HTMLImports.useNative) {
} else {
window.addEventListener('DOMContentLoaded', bootstrap);
}
+
+ HTMLImports.whenImportsReady(function() {
+ notifyReady();
+ });
}
})();