-
Notifications
You must be signed in to change notification settings - Fork 2k
/
polymer-element.js
138 lines (113 loc) · 4.17 KB
/
polymer-element.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/*
* 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: <polymer-element>
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);