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

Commit

Permalink
Merge branch 'master' into dynamic
Browse files Browse the repository at this point in the history
  • Loading branch information
sorvell committed Jan 23, 2014
2 parents 2cda7f4 + a2accf9 commit d16a0d8
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 72 deletions.
36 changes: 26 additions & 10 deletions src/HTMLImports.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,10 @@ if (!useNative) {
// cache document
importer.documents[url] = doc;
}
elt.import = doc;
}
// don't store import record until we're actually loaded
// store document resource
elt.import = elt.content = resource = doc;
}
parser.parseNext();
},
Expand Down Expand Up @@ -153,8 +156,11 @@ if (!useNative) {
doc._URL = url;
// establish a relative path via <base>
var base = doc.createElement('base');
//base.setAttribute('href', document.baseURI || document.URL);
base.setAttribute('href', url);
// add baseURI support to browsers (IE) that lack it.
if (!doc.baseURI) {
doc.baseURI = url;
}
doc.head.appendChild(base);
// install HTML last as it may trigger CustomElement upgrades
// TODO(sjmiles): problem wrt to template boostrapping below,
Expand All @@ -179,13 +185,16 @@ if (!useNative) {
// do nothing if using native imports
}

var wrappedDoc = window.ShadowDOMPolyfill ? wrap(document) : document;


// NOTE: We cannot polyfill document.currentScript because it's not possible
// both to override and maintain the ability to capture the native value;
// therefore we choose to expose _currentScript both when native imports
// and the polyfill are in use.
Object.defineProperty(document, '_currentScript', {
Object.defineProperty(wrappedDoc, '_currentScript', {
get: function() {
return HTMLImports.currentScript || document.currentScript;
return HTMLImports.currentScript || wrappedDoc.currentScript;
},
writeable: true,
configurable: true
Expand All @@ -195,15 +204,22 @@ Object.defineProperty(document, '_currentScript', {
// which may not be desireable; calls should resolve in the correct order,
// however.
function whenImportsReady(callback, doc) {
doc = doc || document;
doc = doc || wrappedDoc;
// if document is loading, wait and try again
if (doc.readyState === 'loading') {
doc.addEventListener('DOMContentLoaded', function() {
whenImportsReady(callback, doc);
})
var requiredState = HTMLImports.isIE ? 'complete' : 'interactive';
var isReady = (doc.readyState === 'complete' ||
doc.readyState === requiredState);
if (!isReady) {
var checkReady = function(e) {
if (doc.readyState === 'complete' || doc.readyState === requiredState) {
doc.removeEventListener('readystatechange', checkReady)
whenImportsReady(callback, doc);
}
}
doc.addEventListener('readystatechange', checkReady)
return;
}
var imports = doc.querySelectorAll('link[rel=import');
var imports = doc.querySelectorAll('link[rel=import]');
var loaded = 0, l = imports.length;
function checkDone(d) {
if (loaded == l) {
Expand Down
91 changes: 34 additions & 57 deletions src/Parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,17 @@ var importParser = {
} else {
elt.dispatchEvent(new CustomEvent('error', {bubbles: false}));
}
// TODO(sorvell): workaround for Safari addEventListener not working
// for elements not in the main document.
if (linkElt.__pending) {
var fn;
while (linkElt.__pending.length) {
fn = linkElt.__pending.shift();
if (fn) {
fn({target: linkElt});
}
}
}
this.markParsingComplete(elt);
},
parseLink: function(linkElt) {
Expand Down Expand Up @@ -153,69 +164,33 @@ var importParser = {
// NOTE: styles are the only elements that require direct path fixup.
function cloneStyle(style) {
var clone = style.ownerDocument.createElement('style');
clone.textContent = relativeCssForStyle(style);
clone.textContent = style.textContent;
path.resolveUrlsInStyle(clone);
return clone;
}

function relativeCssForStyle(style) {
var doc = style.ownerDocument;
var resolver = doc.createElement('a');
var cssText = replaceUrlsInCssText(style.textContent, resolver,
CSS_URL_REGEXP);
return replaceUrlsInCssText(cssText, resolver, CSS_IMPORT_REGEXP);
}

var CSS_URL_REGEXP = /(url\()([^)]*)(\))/g;
var CSS_IMPORT_REGEXP = /(@import[\s]*)([^;]*)(;)/g;
function replaceUrlsInCssText(cssText, resolver, regexp) {
return cssText.replace(regexp, function(m, pre, url, post) {
var urlPath = url.replace(/["']/g, '');
resolver.href = urlPath;
urlPath = resolver.href;
return pre + '\'' + urlPath + '\'' + post;
});
}

function LoadTracker(doc, callback) {
this.doc = doc;
this.doc.__loadTracker = this;
this.callback = callback;
}

LoadTracker.prototype = {
pending: 0,
isOpen: false,
open: function() {
this.isOpen = true;
this.checkDone();
},
add: function() {
this.pending++;
},
require: function(elt) {
this.add();
//console.log('require', elt, this.pending);
var names = ['load', 'error'], self = this;
for (var i=0, l=names.length, n; (i<l) && (n=names[i]); i++) {
elt.addEventListener(n, function(e) {
self.receive(e);
});
}
},
receive: function(e) {
this.pending--;
//console.log('receive', e.target, this.pending);
this.checkDone();
},
checkDone: function() {
if (!this.isOpen) {
return;
}
if (this.pending <= 0 && this.callback) {
//console.log('done!', this.doc, this.doc.baseURI);
this.isOpen = false;
this.callback();
}
var path = {
resolveUrlsInStyle: function(style) {
var doc = style.ownerDocument;
var resolver = doc.createElement('a');
style.textContent = this.resolveUrlsInCssText(style.textContent, resolver);
return style;
},
resolveUrlsInCssText: function(cssText, urlObj) {
var r = this.replaceUrls(cssText, urlObj, CSS_URL_REGEXP);
r = this.replaceUrls(r, urlObj, CSS_IMPORT_REGEXP);
return r;
},
replaceUrls: function(text, urlObj, regexp) {
return text.replace(regexp, function(m, pre, url, post) {
var urlPath = url.replace(/["']/g, '');
urlObj.href = urlPath;
urlPath = urlObj.href;
return pre + '\'' + urlPath + '\'' + post;
});
}
}

Expand All @@ -242,5 +217,7 @@ function inMainDocument(elt) {

// exports
scope.parser = importParser;
scope.path = path;
scope.isIE = isIe;

})(HTMLImports);
1 change: 0 additions & 1 deletion src/boot.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ var doc = window.ShadowDOMPolyfill ?
HTMLImports.whenImportsReady(function() {
HTMLImports.ready = true;
HTMLImports.readyTime = new Date().getTime();
//console.log('HTMLImportsLoaded');
doc.dispatchEvent(
new CustomEvent('HTMLImportsLoaded', {bubbles: true})
);
Expand Down
16 changes: 12 additions & 4 deletions test/html/load.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,33 @@
chai.assert.ok(s, 'load event target can be used to find element in import');
}
}

function importError(event) {
window.loadEvents++;
}

window.importLoaded = importLoaded;
window.importError = importError;
})();
</script>
<script src="../../../tools/test/htmltest.js"></script>
<script src="../../../tools/test/chai/chai.js"></script>
<script src="../../html-imports.js"></script>
<link rel="import" href="imports/load-1.html" onload="importLoaded(event)">
<link rel="import" href="imports/load-2.html" onload="importLoaded(event)">
<link rel="import" href="imports/404.html" onerror="importLoaded(event)">
<!-- TODO(sorvell): note, native imports currently fires onload for 404
documents. This doesn't really make sense, check spec.
See: https://code.google.com/p/chromium/issues/detail?id=336609
-->
<link rel="import" href="imports/404.html" onload="importError(event)" onerror="importError(event)">
</head>
<body>
<div id="test1" class="red">Test</div>
<div id="test2" class="blue">Test</div>
<div id="test3" class="image"></div>
<script>
document.addEventListener('HTMLImportsLoaded', function() {
// TODO(sorvell): onerror doesn't work in native, filing bug...
var num = HTMLImports.useNative ? 2 : 3;
chai.assert.equal(loadEvents, num, 'expected # of load events');
chai.assert.equal(loadEvents, 3, 'expected # of load events');
var test1 = getComputedStyle(document.querySelector('#test1')).backgroundColor;
chai.assert.equal(test1, 'rgb(255, 0, 0)');
var test2 = getComputedStyle(document.querySelector('#test2')).backgroundColor;
Expand Down

0 comments on commit d16a0d8

Please sign in to comment.