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

Commit

Permalink
wip: four prevention strategy; polymer-element can wait to register u…
Browse files Browse the repository at this point in the history
…ntil resources are loaded.
  • Loading branch information
sorvell committed Jan 16, 2014
1 parent fabbb48 commit 2e875a0
Show file tree
Hide file tree
Showing 4 changed files with 190 additions and 35 deletions.
133 changes: 118 additions & 15 deletions src/declaration/polymer-element.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,27 @@
this.name = this.getAttribute('name');
// fetch our extendee name
this.extends = this.getAttribute('extends');
// install element definition, if ready
this.loadResources();
this.registerWhenReady();
},
registerWhenReady: function() {
// if we have no prototype, wait
if (this.waitingForPrototype(this.name)) {
return;
}
// TODO(sorvell): this establishes an element's place in line
// so it's critical that this be done in proper order.
// NOTE: polymer previously explicitly waited for extendee's to be
// ready before extendors. This has been removed and is the user's
// responsibility.
if (waitingForQueue(this)) {
return;
}
if (this.waitingForResources()) {
return;
}
this._register();
/*
var extendee = this.extends;
if (this.waitingForExtendee(extendee)) {
//console.warn(this.name + ': waitingForExtendee:' + extendee);
Expand All @@ -55,13 +68,15 @@
} else {
this._register(extendee);
}
*/
},
_register: function(extendee) {
_register: function() {
//console.group('registering', this.name);
this.register(this.name, extendee);
this.register(this.name, this.extends);
//console.groupEnd();
// subclasses may now register themselves
notifySuper(this.name);
//notifySuper(this.name);
notifyQueue(this);
},
waitingForPrototype: function(name) {
if (!getRegisteredPrototype(name)) {
Expand All @@ -86,6 +101,16 @@
return true;
}
},
waitingForResources: function() {
return this._needsResources;
},
loadResources: function() {
this._needsResources = this.preloadStyles(function() {
this._needsResources = false;
this.registerWhenReady();
}.bind(this));
}
/*,
waitingForExtendee: function(extendee) {
// if extending a custom element...
if (extendee && extendee.indexOf('-') >= 0) {
Expand All @@ -95,7 +120,7 @@
return true;
}
}
}
}*/
});

// semi-pluggable APIs
Expand All @@ -106,7 +131,15 @@
});

// utility and bookkeeping

/*
function whenImportsLoaded(doThis) {
if (window.HTMLImports && !HTMLImports.ready) {
addEventListener('HTMLImportsLoaded', doThis);
} else {
doThis();
}
}*/

// maps tag names to prototypes
var prototypesByName = {};

Expand All @@ -124,6 +157,7 @@
}
}

/*
// elements waiting for super, by name
var waitSuper = {};
Expand All @@ -137,21 +171,90 @@
delete waitSuper[name];
}
}
*/
var importQueue = [];
var mainQueue = [];

// track document.register'ed tag names
function queueForElement(element) {
return document.contains(element) ? mainQueue : importQueue;
}

var registered = {};
function pushQueue(element) {
queueForElement(element).push(element);
}

function isRegistered(name) {
return registered[name];
function shiftQueue(element) {
var i = queueIndex(element);
if (i !== 0) {
console.warn('queue order wrong', i);
return;
}
queueForElement(element).shift();
}

function whenImportsLoaded(doThis) {
if (window.HTMLImports && !HTMLImports.ready) {
addEventListener('HTMLImportsLoaded', doThis);
} else {
doThis();
function queueIndex(element) {
var i = queueForElement(element).indexOf(element);
if (i >= 0 && document.contains(element)) {
i += HTMLImports.useNative ? importQueue.length : 1e9;
}
return i;
}

function nextInQueue() {
return importQueue.length ? importQueue[0] : mainQueue[0];
}

function pokeQueue() {
// next
var element = nextInQueue();
if (element) {
element.registerWhenReady();
}
}

function isQueueEmpty() {
return !importQueue.length && !mainQueue.length;
}

function waitingForQueue(element) {
if (queueIndex(element) === -1) {
pushQueue(element);
}
var ready = (queueIndex(element) === 0);
return !ready;
}

function notifyQueue(element) {
shiftQueue(element);
pokeQueue();
notifyElements();
}


var canNotifyElements;
HTMLImports.whenImportsReady(function() {
pokeQueue();
canNotifyElements = true;
});

// TODO(sorvell): highly experimental replacement for WCR:
var registerCallback;
function notifyElements() {
if (isQueueEmpty() && canNotifyElements) {
requestAnimationFrame(function() {
document.dispatchEvent(
new CustomEvent('PolymerElementsReady', {bubbles: true})
//new CustomEvent('WebComponentsReady', {bubbles: true})
);
});
}
}

// track document.register'ed tag names
var registered = {};

function isRegistered(name) {
return registered[name];
}

// exports
Expand Down
72 changes: 62 additions & 10 deletions src/declaration/styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,54 @@
// magic words

var STYLE_SELECTOR = 'style';
var SHEET_SELECTOR = '[rel=stylesheet]';
var SHEET_SELECTOR = 'link[rel=stylesheet]';
var STYLE_GLOBAL_SCOPE = 'global';
var SCOPE_ATTR = 'polymer-scope';
var STYLE_LOADABLE_MATCH = '@import';

var styles = {
// returns true if resources are loading
preloadStyles: function(callback) {
var styles = [];
var t$ = this.querySelectorAll('template');
for (var i=0, l=t$.length, t; (i<l) && (t=t$[i]); i++) {
this.convertSheetsToStyles(t.content);
styles = styles.concat(this.findLoadableStyles(t.content));
}
if (styles.length) {
if (window.ShadowDOMPolyfill) {
Platform.ShadowCSS.loadStyles(styles, callback);
} else {
var css = [];
for (var i=0, l=styles.length, s; (i<l) && (s=styles[i]); i++) {
css.push(s.textContent);
}
preloadCssText(css.join('\n'), callback);
}
return true;
}
},
convertSheetsToStyles: function(root) {
var s$ = root.querySelectorAll(SHEET_SELECTOR);
for (var i=0, l=s$.length, s, c; (i<l) && (s=s$[i]); i++) {
c = createStyleElement(importRuleForSheet(s));
var scope = s.getAttribute(SCOPE_ATTR);
if (scope) {
c.setAttribute(SCOPE_ATTR, scope);
}
s.parentNode.replaceChild(c, s);
}
},
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;
},
/**
* Install external stylesheets loaded in <polymer-element> elements into the
* element's template.
Expand All @@ -34,7 +77,7 @@
// the stylesheet from dom.
installSheets: function() {
this.cacheSheets();
//this.cacheStyles();
this.cacheStyles();
this.installLocalSheets();
//this.installGlobalStyles();
},
Expand Down Expand Up @@ -74,17 +117,16 @@
if (content) {
var cssText = '';
sheets.forEach(function(sheet) {
//cssText += cssTextFromSheet(sheet) + '\n';
cssText += importRuleForSheet(sheet) + '\n';
cssText += cssTextFromSheet(sheet) + '\n';
});
if (cssText) {
content.insertBefore(createStyleElement(cssText, this.ownerDocument), content.firstChild);
var style = createStyleElement(cssText, this.ownerDocument);
content.insertBefore(style, content.firstChild);
}
}
},
findNodes: function(selector, matcher) {
//var nodes = this.querySelectorAll(selector).array();
var nodes = [];
var nodes = this.querySelectorAll(selector).array();
var content = this.templateContent();
if (content) {
var templateNodes = content.querySelectorAll(selector).array();
Expand Down Expand Up @@ -119,15 +161,12 @@
var sheets = this.sheets.filter(matcher);
sheets.forEach(function(sheet) {
cssText += cssTextFromSheet(sheet) + '\n\n';
cssText += importRuleForSheet(sheet) + '\n';
});
// handle cached style elements
/*
var styles = this.styles.filter(matcher);
styles.forEach(function(style) {
cssText += style.textContent + '\n\n';
});
*/
return cssText;
},
styleForScope: function(scopeDescriptor) {
Expand All @@ -144,6 +183,19 @@
}
};

var preloader = document.createElement('preloader');
preloader.style.display = 'none';
var preloaderRoot = preloader.createShadowRoot();
document.head.appendChild(preloader);

function preloadCssText(cssText, callback) {
var style = createStyleElement(cssText);
if (callback) {
style.addEventListener('load', callback);
}
preloaderRoot.appendChild(style);
}

function importRuleForSheet(sheet) {
return '@import \'' + sheet.href + '\';';
}
Expand Down
18 changes: 9 additions & 9 deletions test/html/element-registration.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,15 @@
</template>
</polymer-element>

<!-- script following declaration -->
<script>
Polymer('x-foo', {
ready: function() {
this.squid = 'ink';
}
});
</script>

<!-- script embedded in declaration -->
<!-- super script follows declaration -->
<polymer-element name="x-bar" extends="x-foo" noscript>
Expand All @@ -58,15 +67,6 @@
</template>
</polymer-element>

<!-- script following declaration -->
<script>
Polymer('x-foo', {
ready: function() {
this.squid = 'ink';
}
});
</script>

<!-- script embedded in declaration -->
<!-- super follows declaration -->
<!-- script extends no script -->
Expand Down
2 changes: 1 addition & 1 deletion test/html/styling/sheet-order.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<body>
<x-sheets></x-sheets>
<script>
document.addEventListener('WebComponentsReady', function() {
document.addEventListener('PolymerElementsReady', function() {
var xSheets = document.querySelector('x-sheets');

function test(node, color) {
Expand Down

0 comments on commit 2e875a0

Please sign in to comment.