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

Commit

Permalink
add loader to Platform; allows loading of stylesheets; will be refine…
Browse files Browse the repository at this point in the history
…d to share code with the HTMLImports polyfill.
  • Loading branch information
sorvell committed Jan 18, 2014
1 parent f0ba61d commit 0d211f4
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 2 deletions.
3 changes: 2 additions & 1 deletion platform.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ function processFlags(flags) {
'../HTMLImports/html-imports.js',
'../CustomElements/custom-elements.js',
'src/patches-custom-elements.js',
'src/microtask.js'
'src/microtask.js',
'src/loader.js'
];

// select ShadowDOM impl
Expand Down
2 changes: 1 addition & 1 deletion src/ShadowCSS.js
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,7 @@ if (window.ShadowDOMPolyfill) {
head.insertBefore(getSheet(), head.childNodes[0]);

document.addEventListener('DOMContentLoaded', function() {
if (window.HTMLImports) {
if (window.HTMLImports && !HTMLImports.useNative) {
HTMLImports.importer.preloadSelectors +=
', link[rel=stylesheet]:not([nopolyfill])';
HTMLImports.parser.parseGeneric = function(elt) {
Expand Down
107 changes: 107 additions & 0 deletions src/loader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* Copyright 2014 The Polymer Authors. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
(function(scope) {

var STYLE_SELECTOR = 'style';
var STYLE_LOADABLE_MATCH = '@import';

var loader = {
loadStyles: function(root, callback) {
var styles = this.findLoadableStyles(root);
if (styles.length) {
if (window.ShadowDOMPolyfill) {
this.polyfillLoadStyles(styles, callback);
} else {
this.platformLoadStyles(styles, callback);
}
return true;
}
},
findLoadableStyles: function(root) {
var loadables = [];
var s$ = root.querySelectorAll(STYLE_SELECTOR);
for (var i=0, l=s$.length, s; (i<l) && (s=s$[i]); i++) {
if (s.textContent.match(STYLE_LOADABLE_MATCH)) {
loadables.push(s);
}
}
return loadables;
},
platformLoadStyles: function(styles, callback) {
var css = [];
for (var i=0, l=styles.length, s; (i<l) && (s=styles[i]); i++) {
css.push(s.textContent);
}
loadCssText(css.join('\n'), callback);
},
polyfillLoadStyles: function(styles, callback) {
var loaded=0, l = styles.length;
// called in the context of the style
function loadedStyle(style) {
//console.log(style.textContent);
loaded++;
if (loaded === l && callback) {
callback();
}
}
for (var i=0, s; (i<l) && (s=styles[i]); i++) {
polyfillLoadStyle(s, loadedStyle);
}
}
};

// use the platform to preload styles
var preloadElement = document.createElement('preloader');
preloadElement.style.display = 'none';
var preloadRoot = preloadElement.createShadowRoot();
document.head.appendChild(preloadElement);

function loadCssText(cssText, callback) {
var style = createStyleElement(cssText);
if (callback) {
style.addEventListener('load', callback);
style.addEventListener('error', callback);
}
preloadRoot.appendChild(style);
}

function createStyleElement(cssText, scope) {
scope = scope || document;
scope = scope.createElement ? scope : scope.ownerDocument;
var style = scope.createElement('style');
style.textContent = cssText;
return style;
}

// TODO(sorvell): use a common loader shared with HTMLImports polyfill
// currently, this just loads the first @import per style element
// and does not recurse into loaded elements; we'll address this with a
// generalized loader that's built out of the one in the HTMLImports polyfill.
// polyfill the loading of a style element's @import via xhr
function polyfillLoadStyle(style, callback) {
HTMLImports.xhr.load(atImportUrlFromStyle(style), function (err, resource,
url) {
replaceAtImportWithCssText(this, url, resource);
callback && callback(this);
}, style);
}

var atImportRe = /@import\s[(]?['"]?([^\s'";)]*)/;

// get the first @import rule from a style
function atImportUrlFromStyle(style) {
var matches = style.textContent.match(atImportRe);
return matches && matches[1];
}

function replaceAtImportWithCssText(style, url, cssText) {
var re = new RegExp('@import[^;]*' + url + '[^;]*;', 'i');
style.textContent = style.textContent.replace(re, cssText);
}

scope.loader = loader;

})(window.Platform);

0 comments on commit 0d211f4

Please sign in to comment.