/* * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt * Code distributed by Google as part of the polymer project is also * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt */ (function(scope) { // imports var extend = scope.extend; var api = scope.api; var queue = scope.queue; var whenReady = scope.whenReady; var getRegisteredPrototype = scope.getRegisteredPrototype; var waitingForPrototype = scope.waitingForPrototype; // declarative implementation: var prototype = extend(Object.create(HTMLElement.prototype), { createdCallback: function() { if (this.getAttribute('name')) { this.init(); } }, init: function() { // fetch declared values this.name = this.getAttribute('name'); this.extends = this.getAttribute('extends'); queue.wait(this); // initiate any async resource fetches this.loadResources(); // register when all constraints are met this.registerWhenReady(); }, // TODO(sorvell): we currently queue in the order the prototypes are // registered, but we should queue in the order that polymer-elements // are registered. We are currently blocked from doing this based on // crbug.com/395686. registerWhenReady: function() { if (this.registered || this.waitingForPrototype(this.name) || this.waitingForQueue() || this.waitingForResources()) { return; } queue.go(this); }, _register: function() { //console.log('registering', this.name); // warn if extending from a custom element not registered via Polymer if (isCustomTag(this.extends) && !isRegistered(this.extends)) { console.warn('%s is attempting to extend %s, an unregistered element ' + 'or one that was not registered with Polymer.', this.name, this.extends); } this.register(this.name, this.extends); this.registered = true; }, waitingForPrototype: function(name) { if (!getRegisteredPrototype(name)) { // then wait for a prototype waitingForPrototype(name, this); // emulate script if user is not supplying one this.handleNoScript(name); // prototype not ready yet return true; } }, handleNoScript: function(name) { // if explicitly marked as 'noscript' if (this.hasAttribute('noscript') && !this.noscript) { this.noscript = true; // imperative element registration Polymer(name); } }, waitingForResources: function() { return this._needsResources; }, // NOTE: Elements must be queued in proper order for inheritance/composition // dependency resolution. Previously this was enforced for inheritance, // and by rule for composition. It's now entirely by rule. waitingForQueue: function() { return queue.enqueue(this, this.registerWhenReady, this._register); }, loadResources: function() { this._needsResources = true; this.loadStyles(function() { this._needsResources = false; this.registerWhenReady(); }.bind(this)); } }); // semi-pluggable APIs // TODO(sjmiles): should be fully pluggable (aka decoupled, currently // the various plugins are allowed to depend on each other directly) api.publish(api.declaration, prototype); // utility and bookkeeping function isRegistered(name) { return Boolean(HTMLElement.getPrototypeForTag(name)); } function isCustomTag(name) { return (name && name.indexOf('-') >= 0); } // boot tasks whenReady(function() { document.body.removeAttribute('unresolved'); document.dispatchEvent( new CustomEvent('polymer-ready', {bubbles: true}) ); }); // register polymer-element with document document.registerElement('polymer-element', {prototype: prototype}); })(Polymer);