written 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/lib/written/app/assets/javascripts/written/core/content.coffee +10 -10
  3. data/lib/written/app/assets/javascripts/written/core/cursor.coffee +6 -6
  4. data/lib/written/app/assets/javascripts/written/core/document.coffee +39 -6
  5. data/lib/written/app/assets/javascripts/written/parsers/block/code.coffee +34 -30
  6. data/lib/written/app/assets/javascripts/written/parsers/block/heading.coffee +28 -30
  7. data/lib/written/app/assets/javascripts/written/parsers/block/image.coffee +30 -49
  8. data/lib/written/app/assets/javascripts/written/parsers/block/olist.coffee +46 -49
  9. data/lib/written/app/assets/javascripts/written/parsers/block/paragraph.coffee +28 -32
  10. data/lib/written/app/assets/javascripts/written/parsers/block/quote.coffee +30 -32
  11. data/lib/written/app/assets/javascripts/written/parsers/block/ulist.coffee +43 -45
  12. data/lib/written/app/assets/javascripts/written/parsers/inline/code.coffee +28 -30
  13. data/lib/written/app/assets/javascripts/written/parsers/inline/italic.coffee +21 -25
  14. data/lib/written/app/assets/javascripts/written/parsers/inline/link.coffee +21 -25
  15. data/lib/written/app/assets/javascripts/written/parsers/inline/strong.coffee +21 -25
  16. data/lib/written/app/assets/javascripts/written/parsers/parsers.coffee +87 -19
  17. data/lib/written/app/assets/javascripts/written.coffee +0 -1
  18. data/lib/written/version.rb +1 -1
  19. data/test/server/app/assets/javascripts/application.coffee +5 -15
  20. metadata +2 -18
  21. data/lib/written/app/assets/javascripts/written/core/extensions/text.coffee +0 -2
  22. data/lib/written/app/assets/javascripts/written/core/stringify.coffee +0 -15
  23. data/lib/written/app/assets/javascripts/written/parsers/block.coffee +0 -69
  24. data/lib/written/app/assets/javascripts/written/parsers/inline/list.coffee +0 -27
  25. data/lib/written/app/assets/javascripts/written/parsers/inline.coffee +0 -81
  26. data/lib/written/app/assets/javascripts/written/polyfills/CustomElements/CustomElements.js +0 -32
  27. data/lib/written/app/assets/javascripts/written/polyfills/CustomElements/base.js +0 -40
  28. data/lib/written/app/assets/javascripts/written/polyfills/CustomElements/boot.js +0 -124
  29. data/lib/written/app/assets/javascripts/written/polyfills/CustomElements/observe.js +0 -318
  30. data/lib/written/app/assets/javascripts/written/polyfills/CustomElements/register.js +0 -369
  31. data/lib/written/app/assets/javascripts/written/polyfills/CustomElements/traverse.js +0 -86
  32. data/lib/written/app/assets/javascripts/written/polyfills/CustomElements/upgrade.js +0 -130
  33. data/lib/written/app/assets/javascripts/written/polyfills/MutationObserver/MutationObserver.js +0 -575
  34. data/lib/written/app/assets/javascripts/written/polyfills/WeakMap/WeakMap.js +0 -49
  35. data/lib/written/app/assets/javascripts/written/polyfills/base.coffee +0 -10
  36. data/lib/written/app/assets/javascripts/written/polyfills/dom.js +0 -104
@@ -1,318 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
4
- * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
5
- * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
6
- * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
7
- * Code distributed by Google as part of the polymer project is also
8
- * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
9
- */
10
-
11
- /**
12
- * Implements custom element observation and attached/detached callbacks
13
- * @module observe
14
- */
15
-
16
- window.CustomElements.addModule(function(scope){
17
-
18
- // imports
19
- var flags = scope.flags;
20
- var forSubtree = scope.forSubtree;
21
- var forDocumentTree = scope.forDocumentTree;
22
-
23
- /*
24
- Manage nodes attached to document trees
25
- */
26
-
27
- // manage lifecycle on added node and it's subtree; upgrade the node and
28
- // entire subtree if necessary and process attached for the node and entire
29
- // subtree
30
- function addedNode(node, isAttached) {
31
- return added(node, isAttached) || addedSubtree(node, isAttached);
32
- }
33
-
34
- // manage lifecycle on added node; upgrade if necessary and process attached
35
- function added(node, isAttached) {
36
- if (scope.upgrade(node, isAttached)) {
37
- // Return true to indicate
38
- return true;
39
- }
40
- if (isAttached) {
41
- attached(node);
42
- }
43
- }
44
-
45
- // manage lifecycle on added node's subtree only; allows the entire subtree
46
- // to upgrade if necessary and process attached
47
- function addedSubtree(node, isAttached) {
48
- forSubtree(node, function(e) {
49
- if (added(e, isAttached)) {
50
- return true;
51
- }
52
- });
53
- }
54
-
55
- // On platforms without MutationObserver, mutations may not be
56
- // reliable and therefore attached/detached are not reliable. We think this
57
- // occurs sometimes under heavy DOM operation load, but it is not easy to
58
- // reproduce.
59
- // To make these callbacks less likely to fail in this scenario,
60
- // we *optionally* defer all inserts and removes
61
- // to give a chance for elements to be attached into dom.
62
- // This helps ensure attachedCallback fires for elements that are created and
63
- // immediately added to dom.
64
- // This change can significantly alter the performance characteristics
65
- // of attaching elements and therefore we only enable it if the user has
66
- // explicitly provided the `throttle-attached` flag.
67
- var hasThrottledAttached = (window.MutationObserver._isPolyfilled &&
68
- flags['throttle-attached']);
69
- // bc
70
- scope.hasPolyfillMutations = hasThrottledAttached;
71
- // exposed for testing
72
- scope.hasThrottledAttached = hasThrottledAttached;
73
-
74
- var isPendingMutations = false;
75
- var pendingMutations = [];
76
- function deferMutation(fn) {
77
- pendingMutations.push(fn);
78
- if (!isPendingMutations) {
79
- isPendingMutations = true;
80
- setTimeout(takeMutations);
81
- }
82
- }
83
-
84
- function takeMutations() {
85
- isPendingMutations = false;
86
- var $p = pendingMutations;
87
- for (var i=0, l=$p.length, p; (i<l) && (p=$p[i]); i++) {
88
- p();
89
- }
90
- pendingMutations = [];
91
- }
92
-
93
- function attached(element) {
94
- if (hasThrottledAttached) {
95
- deferMutation(function() {
96
- _attached(element);
97
- });
98
- } else {
99
- _attached(element);
100
- }
101
- }
102
-
103
- // NOTE: due to how MO works (see comments below), an element may be attached
104
- // multiple times so we protect against extra processing here.
105
- function _attached(element) {
106
- // track element for insertion if it's upgraded and cares about insertion
107
- // bail if the element is already marked as attached
108
- if (element.__upgraded__ && !element.__attached) {
109
- element.__attached = true;
110
- if (element.attachedCallback) {
111
- element.attachedCallback();
112
- }
113
- }
114
- }
115
-
116
- /*
117
- Manage nodes detached from document trees
118
- */
119
-
120
- // manage lifecycle on detached node and it's subtree; process detached
121
- // for the node and entire subtree
122
- function detachedNode(node) {
123
- detached(node);
124
- forSubtree(node, function(e) {
125
- detached(e);
126
- });
127
- }
128
-
129
- function detached(element) {
130
- if (hasThrottledAttached) {
131
- deferMutation(function() {
132
- _detached(element);
133
- });
134
- } else {
135
- _detached(element);
136
- }
137
- }
138
-
139
- // NOTE: due to how MO works (see comments below), an element may be detached
140
- // multiple times so we protect against extra processing here.
141
- function _detached(element) {
142
- // track element for removal if it's upgraded and cares about removal
143
- // bail if the element is already marked as not attached
144
- if (element.__upgraded__ && element.__attached) {
145
- element.__attached = false;
146
- if (element.detachedCallback) {
147
- element.detachedCallback();
148
- }
149
- }
150
- }
151
-
152
- // recurse up the tree to check if an element is actually in the main document.
153
- function inDocument(element) {
154
- var p = element;
155
- var doc = window.wrap(document);
156
- while (p) {
157
- if (p == doc) {
158
- return true;
159
- }
160
- p = p.parentNode || ((p.nodeType === Node.DOCUMENT_FRAGMENT_NODE) && p.host);
161
- }
162
- }
163
-
164
- // Install an element observer on all shadowRoots owned by node.
165
- function watchShadow(node) {
166
- if (node.shadowRoot && !node.shadowRoot.__watched) {
167
- flags.dom && console.log('watching shadow-root for: ', node.localName);
168
- // watch all unwatched roots...
169
- var root = node.shadowRoot;
170
- while (root) {
171
- observe(root);
172
- root = root.olderShadowRoot;
173
- }
174
- }
175
- }
176
-
177
- /*
178
- NOTE: In order to process all mutations, it's necessary to recurse into
179
- any added nodes. However, it's not possible to determine a priori if a node
180
- will get its own mutation record. This means
181
- *nodes can be seen multiple times*.
182
-
183
- Here's an example:
184
-
185
- (1) In this case, recursion is required to see `child`:
186
-
187
- node.innerHTML = '<div><child></child></div>'
188
-
189
- (2) In this case, child will get its own mutation record:
190
-
191
- node.appendChild(div).appendChild(child);
192
-
193
- We cannot know ahead of time if we need to walk into the node in (1) so we
194
- do and see child; however, if it was added via case (2) then it will have its
195
- own record and therefore be seen 2x.
196
- */
197
- function handler(root, mutations) {
198
- // for logging only
199
- if (flags.dom) {
200
- var mx = mutations[0];
201
- if (mx && mx.type === 'childList' && mx.addedNodes) {
202
- if (mx.addedNodes) {
203
- var d = mx.addedNodes[0];
204
- while (d && d !== document && !d.host) {
205
- d = d.parentNode;
206
- }
207
- var u = d && (d.URL || d._URL || (d.host && d.host.localName)) || '';
208
- u = u.split('/?').shift().split('/').pop();
209
- }
210
- }
211
- console.group('mutations (%d) [%s]', mutations.length, u || '');
212
- }
213
- // handle mutations
214
- // NOTE: do an `inDocument` check dynamically here. It's possible that `root`
215
- // is a document in which case the answer here can never change; however
216
- // `root` may be an element like a shadowRoot that can be added/removed
217
- // from the main document.
218
- var isAttached = inDocument(root);
219
- mutations.forEach(function(mx) {
220
- if (mx.type === 'childList') {
221
- forEach(mx.addedNodes, function(n) {
222
- if (!n.localName) {
223
- return;
224
- }
225
- addedNode(n, isAttached);
226
- });
227
- forEach(mx.removedNodes, function(n) {
228
- if (!n.localName) {
229
- return;
230
- }
231
- detachedNode(n);
232
- });
233
- }
234
- });
235
- flags.dom && console.groupEnd();
236
- };
237
-
238
-
239
- /*
240
- When elements are added to the dom, upgrade and attached/detached may be
241
- asynchronous. `CustomElements.takeRecords` can be called to process any
242
- pending upgrades and attached/detached callbacks synchronously.
243
- */
244
- function takeRecords(node) {
245
- node = window.wrap(node);
246
- // If the optional node is not supplied, assume we mean the whole document.
247
- if (!node) {
248
- node = window.wrap(document);
249
- }
250
- // Find the root of the tree, which will be an Document or ShadowRoot.
251
- while (node.parentNode) {
252
- node = node.parentNode;
253
- }
254
- var observer = node.__observer;
255
- if (observer) {
256
- handler(node, observer.takeRecords());
257
- takeMutations();
258
- }
259
- }
260
-
261
- var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);
262
-
263
-
264
- // observe a node tree; bail if it's already being observed.
265
- function observe(inRoot) {
266
- if (inRoot.__observer) {
267
- return;
268
- }
269
- // For each ShadowRoot, we create a new MutationObserver, so the root can be
270
- // garbage collected once all references to the `inRoot` node are gone.
271
- // Give the handler access to the root so that an 'in document' check can
272
- // be done.
273
- var observer = new MutationObserver(handler.bind(this, inRoot));
274
- observer.observe(inRoot, {childList: true, subtree: true});
275
- inRoot.__observer = observer;
276
- }
277
-
278
- // upgrade an entire document and observe it for elements changes.
279
- function upgradeDocument(doc) {
280
- doc = window.wrap(doc);
281
- flags.dom && console.group('upgradeDocument: ', (doc.baseURI).split('/').pop());
282
- var isMainDocument = (doc === window.wrap(document));
283
- addedNode(doc, isMainDocument);
284
- observe(doc);
285
- flags.dom && console.groupEnd();
286
- }
287
-
288
- /*
289
- This method is intended to be called when the document tree (including imports)
290
- has pending custom elements to upgrade. It can be called multiple times and
291
- should do nothing if no elements are in need of upgrade.
292
- */
293
- function upgradeDocumentTree(doc) {
294
- forDocumentTree(doc, upgradeDocument);
295
- }
296
-
297
-
298
- // Patch `createShadowRoot()` if Shadow DOM is available, otherwise leave
299
- // undefined to aid feature detection of Shadow DOM.
300
- var originalCreateShadowRoot = Element.prototype.createShadowRoot;
301
- if (originalCreateShadowRoot) {
302
- Element.prototype.createShadowRoot = function() {
303
- var root = originalCreateShadowRoot.call(this);
304
- window.CustomElements.watchShadow(this);
305
- return root;
306
- };
307
- }
308
-
309
- // exports
310
- scope.watchShadow = watchShadow;
311
- scope.upgradeDocumentTree = upgradeDocumentTree;
312
- scope.upgradeDocument = upgradeDocument;
313
- scope.upgradeSubtree = addedSubtree;
314
- scope.upgradeAll = addedNode;
315
- scope.attached = attached;
316
- scope.takeRecords = takeRecords;
317
-
318
- });
@@ -1,369 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
4
- * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
5
- * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
6
- * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
7
- * Code distributed by Google as part of the polymer project is also
8
- * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
9
- */
10
-
11
- /**
12
- * Implements `document.registerElement`
13
- * @module register
14
- */
15
-
16
- /**
17
- * Polyfilled extensions to the `document` object.
18
- * @class Document
19
- */
20
-
21
- window.CustomElements.addModule(function(scope) {
22
-
23
- // imports
24
- var isIE = scope.isIE;
25
- var upgradeDocumentTree = scope.upgradeDocumentTree;
26
- var upgradeAll = scope.upgradeAll;
27
- var upgradeWithDefinition = scope.upgradeWithDefinition;
28
- var implementPrototype = scope.implementPrototype;
29
- var useNative = scope.useNative;
30
-
31
- /**
32
- * Registers a custom tag name with the document.
33
- *
34
- * When a registered element is created, a `readyCallback` method is called
35
- * in the scope of the element. The `readyCallback` method can be specified on
36
- * either `options.prototype` or `options.lifecycle` with the latter taking
37
- * precedence.
38
- *
39
- * @method register
40
- * @param {String} name The tag name to register. Must include a dash ('-'),
41
- * for example 'x-component'.
42
- * @param {Object} options
43
- * @param {String} [options.extends]
44
- * (_off spec_) Tag name of an element to extend (or blank for a new
45
- * element). This parameter is not part of the specification, but instead
46
- * is a hint for the polyfill because the extendee is difficult to infer.
47
- * Remember that the input prototype must chain to the extended element's
48
- * prototype (or HTMLElement.prototype) regardless of the value of
49
- * `extends`.
50
- * @param {Object} options.prototype The prototype to use for the new
51
- * element. The prototype must inherit from HTMLElement.
52
- * @param {Object} [options.lifecycle]
53
- * Callbacks that fire at important phases in the life of the custom
54
- * element.
55
- *
56
- * @example
57
- * FancyButton = document.registerElement("fancy-button", {
58
- * extends: 'button',
59
- * prototype: Object.create(HTMLButtonElement.prototype, {
60
- * readyCallback: {
61
- * value: function() {
62
- * console.log("a fancy-button was created",
63
- * }
64
- * }
65
- * })
66
- * });
67
- * @return {Function} Constructor for the newly registered type.
68
- */
69
- function register(name, options) {
70
- //console.warn('document.registerElement("' + name + '", ', options, ')');
71
- // construct a defintion out of options
72
- // TODO(sjmiles): probably should clone options instead of mutating it
73
- var definition = options || {};
74
- if (!name) {
75
- throw new Error('document.registerElement: first argument `name` must not be empty');
76
- }
77
- if (name.indexOf('-') < 0) {
78
- throw new Error('document.registerElement: first argument (\'name\') must contain a dash (\'-\'). Argument provided was \'' + String(name) + '\'.');
79
- }
80
- // prevent registering reserved names
81
- if (isReservedTag(name)) {
82
- throw new Error('Failed to execute \'registerElement\' on \'Document\': Registration failed for type \'' + String(name) + '\'. The type name is invalid.');
83
- }
84
- // elements may only be registered once
85
- if (getRegisteredDefinition(name)) {
86
- throw new Error('DuplicateDefinitionError: a type with name \'' + String(name) + '\' is already registered');
87
- }
88
- // prototype is optional, default to an extension of HTMLElement
89
- if (!definition.prototype) {
90
- definition.prototype = Object.create(HTMLElement.prototype);
91
- }
92
- // record name
93
- definition.__name = name.toLowerCase();
94
- // ensure extended name is also treated case-insensitively
95
- if (definition.extends) {
96
- definition.extends = definition.extends.toLowerCase();
97
- }
98
- // ensure a lifecycle object so we don't have to null test it
99
- definition.lifecycle = definition.lifecycle || {};
100
- // build a list of ancestral custom elements (for native base detection)
101
- // TODO(sjmiles): we used to need to store this, but current code only
102
- // uses it in 'resolveTagName': it should probably be inlined
103
- definition.ancestry = ancestry(definition.extends);
104
- // extensions of native specializations of HTMLElement require localName
105
- // to remain native, and use secondary 'is' specifier for extension type
106
- resolveTagName(definition);
107
- // some platforms require modifications to the user-supplied prototype
108
- // chain
109
- resolvePrototypeChain(definition);
110
- // overrides to implement attributeChanged callback
111
- overrideAttributeApi(definition.prototype);
112
- // 7.1.5: Register the DEFINITION with DOCUMENT
113
- registerDefinition(definition.__name, definition);
114
- // 7.1.7. Run custom element constructor generation algorithm with PROTOTYPE
115
- // 7.1.8. Return the output of the previous step.
116
- definition.ctor = generateConstructor(definition);
117
- definition.ctor.prototype = definition.prototype;
118
- // force our .constructor to be our actual constructor
119
- definition.prototype.constructor = definition.ctor;
120
- // if initial parsing is complete
121
- if (scope.ready) {
122
- // upgrade any pre-existing nodes of this type
123
- upgradeDocumentTree(document);
124
- }
125
- return definition.ctor;
126
- }
127
-
128
- // attribute watching
129
- function overrideAttributeApi(prototype) {
130
- // overrides to implement callbacks
131
- // TODO(sjmiles): should support access via .attributes NamedNodeMap
132
- // TODO(sjmiles): preserves user defined overrides, if any
133
- if (prototype.setAttribute._polyfilled) {
134
- return;
135
- }
136
- var setAttribute = prototype.setAttribute;
137
- prototype.setAttribute = function(name, value) {
138
- changeAttribute.call(this, name, value, setAttribute);
139
- };
140
- var removeAttribute = prototype.removeAttribute;
141
- prototype.removeAttribute = function(name) {
142
- changeAttribute.call(this, name, null, removeAttribute);
143
- };
144
- prototype.setAttribute._polyfilled = true;
145
- }
146
-
147
- // https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/custom/
148
- // index.html#dfn-attribute-changed-callback
149
- function changeAttribute(name, value, operation) {
150
- name = name.toLowerCase();
151
- var oldValue = this.getAttribute(name);
152
- operation.apply(this, arguments);
153
- var newValue = this.getAttribute(name);
154
- if (this.attributeChangedCallback &&
155
- (newValue !== oldValue)) {
156
- this.attributeChangedCallback(name, oldValue, newValue);
157
- }
158
- }
159
-
160
- function isReservedTag(name) {
161
- for (var i = 0; i < reservedTagList.length; i++) {
162
- if (name === reservedTagList[i]) {
163
- return true;
164
- }
165
- }
166
- }
167
-
168
- var reservedTagList = [
169
- 'annotation-xml', 'color-profile', 'font-face', 'font-face-src',
170
- 'font-face-uri', 'font-face-format', 'font-face-name', 'missing-glyph'
171
- ];
172
-
173
- function ancestry(extnds) {
174
- var extendee = getRegisteredDefinition(extnds);
175
- if (extendee) {
176
- return ancestry(extendee.extends).concat([extendee]);
177
- }
178
- return [];
179
- }
180
-
181
- function resolveTagName(definition) {
182
- // if we are explicitly extending something, that thing is our
183
- // baseTag, unless it represents a custom component
184
- var baseTag = definition.extends;
185
- // if our ancestry includes custom components, we only have a
186
- // baseTag if one of them does
187
- for (var i=0, a; (a=definition.ancestry[i]); i++) {
188
- baseTag = a.is && a.tag;
189
- }
190
- // our tag is our baseTag, if it exists, and otherwise just our name
191
- definition.tag = baseTag || definition.__name;
192
- if (baseTag) {
193
- // if there is a base tag, use secondary 'is' specifier
194
- definition.is = definition.__name;
195
- }
196
- }
197
-
198
- function resolvePrototypeChain(definition) {
199
- // if we don't support __proto__ we need to locate the native level
200
- // prototype for precise mixing in
201
- if (!Object.__proto__) {
202
- // default prototype
203
- var nativePrototype = HTMLElement.prototype;
204
- // work out prototype when using type-extension
205
- if (definition.is) {
206
- var inst = document.createElement(definition.tag);
207
- nativePrototype = Object.getPrototypeOf(inst);
208
- }
209
- // ensure __proto__ reference is installed at each point on the prototype
210
- // chain.
211
- // NOTE: On platforms without __proto__, a mixin strategy is used instead
212
- // of prototype swizzling. In this case, this generated __proto__ provides
213
- // limited support for prototype traversal.
214
- var proto = definition.prototype, ancestor;
215
- var foundPrototype = false;
216
- while (proto) {
217
- if (proto == nativePrototype) {
218
- foundPrototype = true;
219
- }
220
- ancestor = Object.getPrototypeOf(proto);
221
- if (ancestor) {
222
- proto.__proto__ = ancestor;
223
- }
224
- proto = ancestor;
225
- }
226
- if (!foundPrototype) {
227
- // Note the spec actually allows this, but it results in broken elements
228
- // and is difficult to polyfill correctly, so we throw
229
- console.warn(definition.tag + ' prototype not found in prototype chain for ' +
230
- definition.is);
231
- }
232
- // cache this in case of mixin
233
- definition.native = nativePrototype;
234
- }
235
- }
236
-
237
- // SECTION 4
238
-
239
- function instantiate(definition) {
240
- // 4.a.1. Create a new object that implements PROTOTYPE
241
- // 4.a.2. Let ELEMENT by this new object
242
- //
243
- // the custom element instantiation algorithm must also ensure that the
244
- // output is a valid DOM element with the proper wrapper in place.
245
- //
246
- return upgradeWithDefinition(domCreateElement(definition.tag), definition);
247
- }
248
-
249
- // element registry (maps tag names to definitions)
250
-
251
- var registry = {};
252
-
253
- function getRegisteredDefinition(name) {
254
- if (name) {
255
- return registry[name.toLowerCase()];
256
- }
257
- }
258
-
259
- function registerDefinition(name, definition) {
260
- registry[name] = definition;
261
- }
262
-
263
- function generateConstructor(definition) {
264
- return function() {
265
- return instantiate(definition);
266
- };
267
- }
268
-
269
- var HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
270
- function createElementNS(namespace, tag, typeExtension) {
271
- // NOTE: we do not support non-HTML elements,
272
- // just call createElementNS for non HTML Elements
273
- if (namespace === HTML_NAMESPACE) {
274
- return createElement(tag, typeExtension);
275
- } else {
276
- return domCreateElementNS(namespace, tag);
277
- }
278
- }
279
-
280
- function createElement(tag, typeExtension) {
281
- // TODO(sjmiles): ignore 'tag' when using 'typeExtension', we could
282
- // error check it, or perhaps there should only ever be one argument
283
- if (tag) {
284
- tag = tag.toLowerCase();
285
- }
286
- if (typeExtension) {
287
- typeExtension = typeExtension.toLowerCase();
288
- }
289
- var definition = getRegisteredDefinition(typeExtension || tag);
290
- if (definition) {
291
- if (tag == definition.tag && typeExtension == definition.is) {
292
- return new definition.ctor();
293
- }
294
- // Handle empty string for type extension.
295
- if (!typeExtension && !definition.is) {
296
- return new definition.ctor();
297
- }
298
- }
299
- var element;
300
- if (typeExtension) {
301
- element = createElement(tag);
302
- element.setAttribute('is', typeExtension);
303
- return element;
304
- }
305
- element = domCreateElement(tag);
306
- // Custom tags should be HTMLElements even if not upgraded.
307
- if (tag.indexOf('-') >= 0) {
308
- implementPrototype(element, HTMLElement);
309
- }
310
- return element;
311
- }
312
-
313
- // capture native createElement before we override it
314
- var domCreateElement = document.createElement.bind(document);
315
- var domCreateElementNS = document.createElementNS.bind(document);
316
-
317
- // Create a custom 'instanceof'. This is necessary when CustomElements
318
- // are implemented via a mixin strategy, as for example on IE10.
319
- var isInstance;
320
- if (!Object.__proto__ && !useNative) {
321
- isInstance = function(obj, ctor) {
322
- // Allows instanceof(<div>, HTMLElement.prototype) to work
323
- if (obj instanceof ctor) {
324
- return true;
325
- }
326
- var p = obj;
327
- while (p) {
328
- // NOTE: this is not technically correct since we're not checking if
329
- // an object is an instance of a constructor; however, this should
330
- // be good enough for the mixin strategy.
331
- if (p === ctor.prototype) {
332
- return true;
333
- }
334
- p = p.__proto__;
335
- }
336
- return false;
337
- };
338
- } else {
339
- isInstance = function(obj, base) {
340
- return obj instanceof base;
341
- };
342
- }
343
-
344
- // wrap a dom object method that works on nodes such that it forces upgrade
345
- function wrapDomMethodToForceUpgrade(obj, methodName) {
346
- var orig = obj[methodName];
347
- obj[methodName] = function() {
348
- var n = orig.apply(this, arguments);
349
- upgradeAll(n);
350
- return n;
351
- };
352
- }
353
-
354
- wrapDomMethodToForceUpgrade(Node.prototype, 'cloneNode');
355
- wrapDomMethodToForceUpgrade(document, 'importNode');
356
-
357
- // exports
358
- document.registerElement = register;
359
- document.createElement = createElement; // override
360
- document.createElementNS = createElementNS; // override
361
- scope.registry = registry;
362
- scope.instanceof = isInstance;
363
- scope.reservedTagList = reservedTagList;
364
- scope.getRegisteredDefinition = getRegisteredDefinition;
365
-
366
- // bc
367
- document.register = document.registerElement;
368
-
369
- });