Skip to content
This repository has been archived by the owner on Mar 13, 2018. It is now read-only.

Commit

Permalink
Merge pull request #79 from Polymer/dynamic
Browse files Browse the repository at this point in the history
Fixes #78
  • Loading branch information
Steve Orvell committed Sep 29, 2014
2 parents af95b49 + 40d6b02 commit 8d4f5ec
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 60 deletions.
24 changes: 16 additions & 8 deletions src/HTMLImports.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,15 @@
*/
(function(scope) {

// imports
var useNative = scope.useNative;
var flags = scope.flags;
var IMPORT_LINK_TYPE = 'import';

// TODO(sorvell): SD polyfill intrusion
var mainDoc = window.ShadowDOMPolyfill ?
ShadowDOMPolyfill.wrapIfNeeded(document) : document;
var IMPORT_LINK_TYPE = scope.IMPORT_LINK_TYPE;

if (!useNative) {

// imports
var rootDocument = scope.rootDocument;
var xhr = scope.xhr;
var Loader = scope.Loader;
var parser = scope.parser;
Expand All @@ -30,32 +28,40 @@ if (!useNative) {
// - loads any linked import documents (with deduping)

var importer = {

documents: {},

// nodes to load in the mian document
documentPreloadSelectors: 'link[rel=' + IMPORT_LINK_TYPE + ']',

// nodes to load in imports
importsPreloadSelectors: [
'link[rel=' + IMPORT_LINK_TYPE + ']'
].join(','),

loadNode: function(node) {
importLoader.addNode(node);
},

// load all loadable elements within the parent element
loadSubtree: function(parent) {
var nodes = this.marshalNodes(parent);
// add these nodes to loader's queue
importLoader.addNodes(nodes);
},

marshalNodes: function(parent) {
// all preloadable nodes in inDocument
return parent.querySelectorAll(this.loadSelectorsForNode(parent));
},

// find the proper set of load selectors for a given node
loadSelectorsForNode: function(node) {
var doc = node.ownerDocument || node;
return doc === mainDoc ? this.documentPreloadSelectors :
return doc === rootDocument ? this.documentPreloadSelectors :
this.importsPreloadSelectors;
},

loaded: function(url, elt, resource, err, redirectedUrl) {
flags.load && console.log('loaded', url, elt);
// store generic resource
Expand Down Expand Up @@ -84,14 +90,17 @@ if (!useNative) {
}
parser.parseNext();
},

bootDocument: function(doc) {
this.loadSubtree(doc);
this.observe(doc);
parser.parseNext();
},

loadedAll: function() {
parser.parseNext();
}

};

// loader singleton
Expand Down Expand Up @@ -159,7 +168,7 @@ if (!useNative) {
};

Object.defineProperty(document, 'baseURI', baseURIDescriptor);
Object.defineProperty(mainDoc, 'baseURI', baseURIDescriptor);
Object.defineProperty(rootDocument, 'baseURI', baseURIDescriptor);
}

// IE shim for CustomEvent
Expand All @@ -184,5 +193,4 @@ scope.importer = importer;
scope.IMPORT_LINK_TYPE = IMPORT_LINK_TYPE;
scope.importLoader = importLoader;


})(window.HTMLImports);
13 changes: 13 additions & 0 deletions src/Loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
};

Loader.prototype = {

addNodes: function(nodes) {
// number of transactions to complete
this.inflight += nodes.length;
Expand All @@ -36,6 +37,7 @@
// anything to do?
this.checkDone();
},

addNode: function(node) {
// number of transactions to complete
this.inflight++;
Expand All @@ -44,6 +46,7 @@
// anything to do?
this.checkDone();
},

require: function(elt) {
var url = elt.src || elt.href;
// ensure we have a standard url that can be used
Expand All @@ -56,6 +59,7 @@
this.fetch(url, elt);
}
},

dedupe: function(url, elt) {
if (this.pending[url]) {
// add to list of nodes waiting for inUrl
Expand All @@ -76,6 +80,7 @@
// need fetch (not a dupe)
return false;
},

fetch: function(url, elt) {
flags.load && console.log('fetch', url, elt);
if (url.match(/^data:/)) {
Expand Down Expand Up @@ -111,6 +116,7 @@
*/
}
},

receive: function(url, elt, err, resource, redirectedUrl) {
this.cache[url] = resource;
var $p = this.pending[url];
Expand All @@ -122,24 +128,29 @@
}
this.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) {
Expand All @@ -164,9 +175,11 @@
request.send();
return request;
},

loadDocument: function(url, next, nextContext) {
this.load(url, next, nextContext).responseType = 'document';
}

};

// exports
Expand Down
37 changes: 24 additions & 13 deletions src/Observer.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@
*/
(function(scope){

// imports
var IMPORT_LINK_TYPE = scope.IMPORT_LINK_TYPE;
var importSelector = 'link[rel=' + IMPORT_LINK_TYPE + ']';
var importer = scope.importer;
var parser = scope.parser;

var importSelector = 'link[rel=' + IMPORT_LINK_TYPE + ']';


// we track mutations for addedNodes, looking for imports
function handler(mutations) {
for (var i=0, l=mutations.length, m; (i<l) && (m=mutations[i]); i++) {
Expand All @@ -23,32 +26,40 @@ function handler(mutations) {
}

// find loadable elements and add them to the importer
// IFF the owning document has already parsed, then parsable elements
// need to be marked for dynamic parsing.
function addedNodes(nodes) {
var owner;
for (var i=0, l=nodes.length, n; (i<l) && (n=nodes[i]); i++) {
owner = owner || n.ownerDocument;
if (shouldLoadNode(n)) {
var owner, parsed;
for (var i=0, l=nodes.length, n, loading; (i<l) && (n=nodes[i]); i++) {
if (!owner) {
owner = n.ownerDocument;
parsed = parser.isParsed(owner);
}
// note: the act of loading kicks the parser, so we use parseDynamic's
// 2nd argument to control if this added node needs to kick the parser.
loading = shouldLoadNode(n);
if (loading) {
importer.loadNode(n);
}
if (shouldParseNode(n) && parsed) {
parser.parseDynamic(n, loading);
}
if (n.children && n.children.length) {
addedNodes(n.children);
}
}
// TODO(sorvell): This is not the right approach here. We shouldn't need to
// invalidate parsing when an element is added. Disabling this code
// until a better approach is found.
/*
if (owner) {
parser.invalidateParse(owner);
}
*/
}

function shouldLoadNode(node) {
return (node.nodeType === 1) && matches.call(node,
importer.loadSelectorsForNode(node));
}

function shouldParseNode(node) {
return (node.nodeType === 1) && matches.call(node,
parser.parseSelectorsForNode(node));
}

// x-plat matches
var matches = HTMLElement.prototype.matches ||
HTMLElement.prototype.matchesSelector ||
Expand Down
Loading

0 comments on commit 8d4f5ec

Please sign in to comment.