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
12 window.WebComponents = window.WebComponents || {
15 var file = "webcomponents.js";
16 var script = document.querySelector('script[src*="' + file + '"]');
19 location.search.slice(1).split("&").forEach(function(option) {
20 var parts = option.split("=");
22 if (parts[0] && (match = parts[0].match(/wc-(.+)/))) {
23 flags[match[1]] = parts[1] || true;
27 for (var i = 0, a; a = script.attributes[i]; i++) {
28 if (a.name !== "src") {
29 flags[a.name] = a.value || true;
33 if (flags.log && flags.log.split) {
34 var parts = flags.log.split(",");
36 parts.forEach(function(f) {
43 flags.shadow = flags.shadow || flags.shadowdom || flags.polyfill;
44 if (flags.shadow === "native") {
47 flags.shadow = flags.shadow || !HTMLElement.prototype.createShadowRoot;
50 window.CustomElements = window.CustomElements || {
53 window.CustomElements.flags.register = flags.register;
55 WebComponents.flags = flags;
58 if (WebComponents.flags.shadow) {
59 if (typeof WeakMap === "undefined") {
61 var defineProperty = Object.defineProperty;
62 var counter = Date.now() % 1e9;
63 var WeakMap = function() {
64 this.name = "__st" + (Math.random() * 1e9 >>> 0) + (counter++ + "__");
67 set: function(key, value) {
68 var entry = key[this.name];
69 if (entry && entry[0] === key) entry[1] = value; else defineProperty(key, this.name, {
70 value: [ key, value ],
77 return (entry = key[this.name]) && entry[0] === key ? entry[1] : undefined;
79 "delete": function(key) {
80 var entry = key[this.name];
81 if (!entry || entry[0] !== key) return false;
82 entry[0] = entry[1] = undefined;
86 var entry = key[this.name];
87 if (!entry) return false;
88 return entry[0] === key;
91 window.WeakMap = WeakMap;
94 window.ShadowDOMPolyfill = {};
97 var constructorTable = new WeakMap();
98 var nativePrototypeTable = new WeakMap();
99 var wrappers = Object.create(null);
100 function detectEval() {
101 if (typeof chrome !== "undefined" && chrome.app && chrome.app.runtime) {
104 if (navigator.getDeviceStorage) {
108 var f = new Function("return true;");
114 var hasEval = detectEval();
116 if (!b) throw new Error("Assertion failed");
118 var defineProperty = Object.defineProperty;
119 var getOwnPropertyNames = Object.getOwnPropertyNames;
120 var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
121 function mixin(to, from) {
122 var names = getOwnPropertyNames(from);
123 for (var i = 0; i < names.length; i++) {
125 defineProperty(to, name, getOwnPropertyDescriptor(from, name));
129 function mixinStatics(to, from) {
130 var names = getOwnPropertyNames(from);
131 for (var i = 0; i < names.length; i++) {
142 defineProperty(to, name, getOwnPropertyDescriptor(from, name));
146 function oneOf(object, propertyNames) {
147 for (var i = 0; i < propertyNames.length; i++) {
148 if (propertyNames[i] in object) return propertyNames[i];
151 var nonEnumerableDataDescriptor = {
157 function defineNonEnumerableDataProperty(object, name, value) {
158 nonEnumerableDataDescriptor.value = value;
159 defineProperty(object, name, nonEnumerableDataDescriptor);
161 getOwnPropertyNames(window);
162 function getWrapperConstructor(node, opt_instance) {
163 var nativePrototype = node.__proto__ || Object.getPrototypeOf(node);
166 getOwnPropertyNames(nativePrototype);
168 nativePrototype = nativePrototype.__proto__;
171 var wrapperConstructor = constructorTable.get(nativePrototype);
172 if (wrapperConstructor) return wrapperConstructor;
173 var parentWrapperConstructor = getWrapperConstructor(nativePrototype);
174 var GeneratedWrapper = createWrapperConstructor(parentWrapperConstructor);
175 registerInternal(nativePrototype, GeneratedWrapper, opt_instance);
176 return GeneratedWrapper;
178 function addForwardingProperties(nativePrototype, wrapperPrototype) {
179 installProperty(nativePrototype, wrapperPrototype, true);
181 function registerInstanceProperties(wrapperPrototype, instanceObject) {
182 installProperty(instanceObject, wrapperPrototype, false);
184 var isFirefox = /Firefox/.test(navigator.userAgent);
185 var dummyDescriptor = {
191 function isEventHandlerName(name) {
192 return /^on[a-z]+$/.test(name);
194 function isIdentifierName(name) {
195 return /^[a-zA-Z_$][a-zA-Z_$0-9]*$/.test(name);
197 function getGetter(name) {
198 return hasEval && isIdentifierName(name) ? new Function("return this.__impl4cf1e782hg__." + name) : function() {
199 return this.__impl4cf1e782hg__[name];
202 function getSetter(name) {
203 return hasEval && isIdentifierName(name) ? new Function("v", "this.__impl4cf1e782hg__." + name + " = v") : function(v) {
204 this.__impl4cf1e782hg__[name] = v;
207 function getMethod(name) {
208 return hasEval && isIdentifierName(name) ? new Function("return this.__impl4cf1e782hg__." + name + ".apply(this.__impl4cf1e782hg__, arguments)") : function() {
209 return this.__impl4cf1e782hg__[name].apply(this.__impl4cf1e782hg__, arguments);
212 function getDescriptor(source, name) {
214 return Object.getOwnPropertyDescriptor(source, name);
216 return dummyDescriptor;
219 var isBrokenSafari = function() {
220 var descr = Object.getOwnPropertyDescriptor(Node.prototype, "nodeType");
221 return descr && !descr.get && !descr.set;
223 function installProperty(source, target, allowMethod, opt_blacklist) {
224 var names = getOwnPropertyNames(source);
225 for (var i = 0; i < names.length; i++) {
227 if (name === "polymerBlackList_") continue;
228 if (name in target) continue;
229 if (source.polymerBlackList_ && source.polymerBlackList_[name]) continue;
231 source.__lookupGetter__(name);
233 var descriptor = getDescriptor(source, name);
235 if (typeof descriptor.value === "function") {
237 target[name] = getMethod(name);
241 var isEvent = isEventHandlerName(name);
242 if (isEvent) getter = scope.getEventHandlerGetter(name); else getter = getGetter(name);
243 if (descriptor.writable || descriptor.set || isBrokenSafari) {
244 if (isEvent) setter = scope.getEventHandlerSetter(name); else setter = getSetter(name);
246 var configurable = isBrokenSafari || descriptor.configurable;
247 defineProperty(target, name, {
250 configurable: configurable,
251 enumerable: descriptor.enumerable
255 function register(nativeConstructor, wrapperConstructor, opt_instance) {
256 if (nativeConstructor == null) {
259 var nativePrototype = nativeConstructor.prototype;
260 registerInternal(nativePrototype, wrapperConstructor, opt_instance);
261 mixinStatics(wrapperConstructor, nativeConstructor);
263 function registerInternal(nativePrototype, wrapperConstructor, opt_instance) {
264 var wrapperPrototype = wrapperConstructor.prototype;
265 assert(constructorTable.get(nativePrototype) === undefined);
266 constructorTable.set(nativePrototype, wrapperConstructor);
267 nativePrototypeTable.set(wrapperPrototype, nativePrototype);
268 addForwardingProperties(nativePrototype, wrapperPrototype);
269 if (opt_instance) registerInstanceProperties(wrapperPrototype, opt_instance);
270 defineNonEnumerableDataProperty(wrapperPrototype, "constructor", wrapperConstructor);
271 wrapperConstructor.prototype = wrapperPrototype;
273 function isWrapperFor(wrapperConstructor, nativeConstructor) {
274 return constructorTable.get(nativeConstructor.prototype) === wrapperConstructor;
276 function registerObject(object) {
277 var nativePrototype = Object.getPrototypeOf(object);
278 var superWrapperConstructor = getWrapperConstructor(nativePrototype);
279 var GeneratedWrapper = createWrapperConstructor(superWrapperConstructor);
280 registerInternal(nativePrototype, GeneratedWrapper, object);
281 return GeneratedWrapper;
283 function createWrapperConstructor(superWrapperConstructor) {
284 function GeneratedWrapper(node) {
285 superWrapperConstructor.call(this, node);
287 var p = Object.create(superWrapperConstructor.prototype);
288 p.constructor = GeneratedWrapper;
289 GeneratedWrapper.prototype = p;
290 return GeneratedWrapper;
292 function isWrapper(object) {
293 return object && object.__impl4cf1e782hg__;
295 function isNative(object) {
296 return !isWrapper(object);
298 function wrap(impl) {
299 if (impl === null) return null;
300 assert(isNative(impl));
301 var wrapper = impl.__wrapper8e3dd93a60__;
302 if (wrapper != null) {
305 return impl.__wrapper8e3dd93a60__ = new (getWrapperConstructor(impl, impl))(impl);
307 function unwrap(wrapper) {
308 if (wrapper === null) return null;
309 assert(isWrapper(wrapper));
310 return wrapper.__impl4cf1e782hg__;
312 function unsafeUnwrap(wrapper) {
313 return wrapper.__impl4cf1e782hg__;
315 function setWrapper(impl, wrapper) {
316 wrapper.__impl4cf1e782hg__ = impl;
317 impl.__wrapper8e3dd93a60__ = wrapper;
319 function unwrapIfNeeded(object) {
320 return object && isWrapper(object) ? unwrap(object) : object;
322 function wrapIfNeeded(object) {
323 return object && !isWrapper(object) ? wrap(object) : object;
325 function rewrap(node, wrapper) {
326 if (wrapper === null) return;
327 assert(isNative(node));
328 assert(wrapper === undefined || isWrapper(wrapper));
329 node.__wrapper8e3dd93a60__ = wrapper;
331 var getterDescriptor = {
336 function defineGetter(constructor, name, getter) {
337 getterDescriptor.get = getter;
338 defineProperty(constructor.prototype, name, getterDescriptor);
340 function defineWrapGetter(constructor, name) {
341 defineGetter(constructor, name, function() {
342 return wrap(this.__impl4cf1e782hg__[name]);
345 function forwardMethodsToWrapper(constructors, names) {
346 constructors.forEach(function(constructor) {
347 names.forEach(function(name) {
348 constructor.prototype[name] = function() {
349 var w = wrapIfNeeded(this);
350 return w[name].apply(w, arguments);
355 scope.addForwardingProperties = addForwardingProperties;
356 scope.assert = assert;
357 scope.constructorTable = constructorTable;
358 scope.defineGetter = defineGetter;
359 scope.defineWrapGetter = defineWrapGetter;
360 scope.forwardMethodsToWrapper = forwardMethodsToWrapper;
361 scope.isIdentifierName = isIdentifierName;
362 scope.isWrapper = isWrapper;
363 scope.isWrapperFor = isWrapperFor;
365 scope.nativePrototypeTable = nativePrototypeTable;
367 scope.registerObject = registerObject;
368 scope.registerWrapper = register;
369 scope.rewrap = rewrap;
370 scope.setWrapper = setWrapper;
371 scope.unsafeUnwrap = unsafeUnwrap;
372 scope.unwrap = unwrap;
373 scope.unwrapIfNeeded = unwrapIfNeeded;
375 scope.wrapIfNeeded = wrapIfNeeded;
376 scope.wrappers = wrappers;
377 })(window.ShadowDOMPolyfill);
380 function newSplice(index, removed, addedCount) {
384 addedCount: addedCount
391 function ArraySplice() {}
392 ArraySplice.prototype = {
393 calcEditDistances: function(current, currentStart, currentEnd, old, oldStart, oldEnd) {
394 var rowCount = oldEnd - oldStart + 1;
395 var columnCount = currentEnd - currentStart + 1;
396 var distances = new Array(rowCount);
397 for (var i = 0; i < rowCount; i++) {
398 distances[i] = new Array(columnCount);
401 for (var j = 0; j < columnCount; j++) distances[0][j] = j;
402 for (var i = 1; i < rowCount; i++) {
403 for (var j = 1; j < columnCount; j++) {
404 if (this.equals(current[currentStart + j - 1], old[oldStart + i - 1])) distances[i][j] = distances[i - 1][j - 1]; else {
405 var north = distances[i - 1][j] + 1;
406 var west = distances[i][j - 1] + 1;
407 distances[i][j] = north < west ? north : west;
413 spliceOperationsFromEditDistances: function(distances) {
414 var i = distances.length - 1;
415 var j = distances[0].length - 1;
416 var current = distances[i][j];
418 while (i > 0 || j > 0) {
420 edits.push(EDIT_ADD);
425 edits.push(EDIT_DELETE);
429 var northWest = distances[i - 1][j - 1];
430 var west = distances[i - 1][j];
431 var north = distances[i][j - 1];
433 if (west < north) min = west < northWest ? west : northWest; else min = north < northWest ? north : northWest;
434 if (min == northWest) {
435 if (northWest == current) {
436 edits.push(EDIT_LEAVE);
438 edits.push(EDIT_UPDATE);
443 } else if (min == west) {
444 edits.push(EDIT_DELETE);
448 edits.push(EDIT_ADD);
456 calcSplices: function(current, currentStart, currentEnd, old, oldStart, oldEnd) {
459 var minLength = Math.min(currentEnd - currentStart, oldEnd - oldStart);
460 if (currentStart == 0 && oldStart == 0) prefixCount = this.sharedPrefix(current, old, minLength);
461 if (currentEnd == current.length && oldEnd == old.length) suffixCount = this.sharedSuffix(current, old, minLength - prefixCount);
462 currentStart += prefixCount;
463 oldStart += prefixCount;
464 currentEnd -= suffixCount;
465 oldEnd -= suffixCount;
466 if (currentEnd - currentStart == 0 && oldEnd - oldStart == 0) return [];
467 if (currentStart == currentEnd) {
468 var splice = newSplice(currentStart, [], 0);
469 while (oldStart < oldEnd) splice.removed.push(old[oldStart++]);
471 } else if (oldStart == oldEnd) return [ newSplice(currentStart, [], currentEnd - currentStart) ];
472 var ops = this.spliceOperationsFromEditDistances(this.calcEditDistances(current, currentStart, currentEnd, old, oldStart, oldEnd));
473 var splice = undefined;
475 var index = currentStart;
476 var oldIndex = oldStart;
477 for (var i = 0; i < ops.length; i++) {
481 splices.push(splice);
489 if (!splice) splice = newSplice(index, [], 0);
492 splice.removed.push(old[oldIndex]);
497 if (!splice) splice = newSplice(index, [], 0);
503 if (!splice) splice = newSplice(index, [], 0);
504 splice.removed.push(old[oldIndex]);
510 splices.push(splice);
514 sharedPrefix: function(current, old, searchLength) {
515 for (var i = 0; i < searchLength; i++) if (!this.equals(current[i], old[i])) return i;
518 sharedSuffix: function(current, old, searchLength) {
519 var index1 = current.length;
520 var index2 = old.length;
522 while (count < searchLength && this.equals(current[--index1], old[--index2])) count++;
525 calculateSplices: function(current, previous) {
526 return this.calcSplices(current, 0, current.length, previous, 0, previous.length);
528 equals: function(currentValue, previousValue) {
529 return currentValue === previousValue;
532 scope.ArraySplice = ArraySplice;
533 })(window.ShadowDOMPolyfill);
536 var OriginalMutationObserver = window.MutationObserver;
542 var copies = callbacks.slice(0);
544 for (var i = 0; i < copies.length; i++) {
548 if (OriginalMutationObserver) {
550 var observer = new OriginalMutationObserver(handle);
551 var textNode = document.createTextNode(counter);
552 observer.observe(textNode, {
555 timerFunc = function() {
556 counter = (counter + 1) % 2;
557 textNode.data = counter;
560 timerFunc = window.setTimeout;
562 function setEndOfMicrotask(func) {
563 callbacks.push(func);
566 timerFunc(handle, 0);
568 context.setEndOfMicrotask = setEndOfMicrotask;
569 })(window.ShadowDOMPolyfill);
572 var setEndOfMicrotask = scope.setEndOfMicrotask;
573 var wrapIfNeeded = scope.wrapIfNeeded;
574 var wrappers = scope.wrappers;
575 var registrationsTable = new WeakMap();
576 var globalMutationObservers = [];
577 var isScheduled = false;
578 function scheduleCallback(observer) {
579 if (observer.scheduled_) return;
580 observer.scheduled_ = true;
581 globalMutationObservers.push(observer);
582 if (isScheduled) return;
583 setEndOfMicrotask(notifyObservers);
586 function notifyObservers() {
588 while (globalMutationObservers.length) {
589 var notifyList = globalMutationObservers;
590 globalMutationObservers = [];
591 notifyList.sort(function(x, y) {
592 return x.uid_ - y.uid_;
594 for (var i = 0; i < notifyList.length; i++) {
595 var mo = notifyList[i];
596 mo.scheduled_ = false;
597 var queue = mo.takeRecords();
598 removeTransientObserversFor(mo);
600 mo.callback_(queue, mo);
605 function MutationRecord(type, target) {
607 this.target = target;
608 this.addedNodes = new wrappers.NodeList();
609 this.removedNodes = new wrappers.NodeList();
610 this.previousSibling = null;
611 this.nextSibling = null;
612 this.attributeName = null;
613 this.attributeNamespace = null;
614 this.oldValue = null;
616 function registerTransientObservers(ancestor, node) {
617 for (;ancestor; ancestor = ancestor.parentNode) {
618 var registrations = registrationsTable.get(ancestor);
619 if (!registrations) continue;
620 for (var i = 0; i < registrations.length; i++) {
621 var registration = registrations[i];
622 if (registration.options.subtree) registration.addTransientObserver(node);
626 function removeTransientObserversFor(observer) {
627 for (var i = 0; i < observer.nodes_.length; i++) {
628 var node = observer.nodes_[i];
629 var registrations = registrationsTable.get(node);
630 if (!registrations) return;
631 for (var j = 0; j < registrations.length; j++) {
632 var registration = registrations[j];
633 if (registration.observer === observer) registration.removeTransientObservers();
637 function enqueueMutation(target, type, data) {
638 var interestedObservers = Object.create(null);
639 var associatedStrings = Object.create(null);
640 for (var node = target; node; node = node.parentNode) {
641 var registrations = registrationsTable.get(node);
642 if (!registrations) continue;
643 for (var j = 0; j < registrations.length; j++) {
644 var registration = registrations[j];
645 var options = registration.options;
646 if (node !== target && !options.subtree) continue;
647 if (type === "attributes" && !options.attributes) continue;
648 if (type === "attributes" && options.attributeFilter && (data.namespace !== null || options.attributeFilter.indexOf(data.name) === -1)) {
651 if (type === "characterData" && !options.characterData) continue;
652 if (type === "childList" && !options.childList) continue;
653 var observer = registration.observer;
654 interestedObservers[observer.uid_] = observer;
655 if (type === "attributes" && options.attributeOldValue || type === "characterData" && options.characterDataOldValue) {
656 associatedStrings[observer.uid_] = data.oldValue;
660 for (var uid in interestedObservers) {
661 var observer = interestedObservers[uid];
662 var record = new MutationRecord(type, target);
663 if ("name" in data && "namespace" in data) {
664 record.attributeName = data.name;
665 record.attributeNamespace = data.namespace;
667 if (data.addedNodes) record.addedNodes = data.addedNodes;
668 if (data.removedNodes) record.removedNodes = data.removedNodes;
669 if (data.previousSibling) record.previousSibling = data.previousSibling;
670 if (data.nextSibling) record.nextSibling = data.nextSibling;
671 if (associatedStrings[uid] !== undefined) record.oldValue = associatedStrings[uid];
672 scheduleCallback(observer);
673 observer.records_.push(record);
676 var slice = Array.prototype.slice;
677 function MutationObserverOptions(options) {
678 this.childList = !!options.childList;
679 this.subtree = !!options.subtree;
680 if (!("attributes" in options) && ("attributeOldValue" in options || "attributeFilter" in options)) {
681 this.attributes = true;
683 this.attributes = !!options.attributes;
685 if ("characterDataOldValue" in options && !("characterData" in options)) this.characterData = true; else this.characterData = !!options.characterData;
686 if (!this.attributes && (options.attributeOldValue || "attributeFilter" in options) || !this.characterData && options.characterDataOldValue) {
687 throw new TypeError();
689 this.characterData = !!options.characterData;
690 this.attributeOldValue = !!options.attributeOldValue;
691 this.characterDataOldValue = !!options.characterDataOldValue;
692 if ("attributeFilter" in options) {
693 if (options.attributeFilter == null || typeof options.attributeFilter !== "object") {
694 throw new TypeError();
696 this.attributeFilter = slice.call(options.attributeFilter);
698 this.attributeFilter = null;
702 function MutationObserver(callback) {
703 this.callback_ = callback;
706 this.uid_ = ++uidCounter;
707 this.scheduled_ = false;
709 MutationObserver.prototype = {
710 constructor: MutationObserver,
711 observe: function(target, options) {
712 target = wrapIfNeeded(target);
713 var newOptions = new MutationObserverOptions(options);
715 var registrations = registrationsTable.get(target);
716 if (!registrations) registrationsTable.set(target, registrations = []);
717 for (var i = 0; i < registrations.length; i++) {
718 if (registrations[i].observer === this) {
719 registration = registrations[i];
720 registration.removeTransientObservers();
721 registration.options = newOptions;
725 registration = new Registration(this, target, newOptions);
726 registrations.push(registration);
727 this.nodes_.push(target);
730 disconnect: function() {
731 this.nodes_.forEach(function(node) {
732 var registrations = registrationsTable.get(node);
733 for (var i = 0; i < registrations.length; i++) {
734 var registration = registrations[i];
735 if (registration.observer === this) {
736 registrations.splice(i, 1);
743 takeRecords: function() {
744 var copyOfRecords = this.records_;
746 return copyOfRecords;
749 function Registration(observer, target, options) {
750 this.observer = observer;
751 this.target = target;
752 this.options = options;
753 this.transientObservedNodes = [];
755 Registration.prototype = {
756 addTransientObserver: function(node) {
757 if (node === this.target) return;
758 scheduleCallback(this.observer);
759 this.transientObservedNodes.push(node);
760 var registrations = registrationsTable.get(node);
761 if (!registrations) registrationsTable.set(node, registrations = []);
762 registrations.push(this);
764 removeTransientObservers: function() {
765 var transientObservedNodes = this.transientObservedNodes;
766 this.transientObservedNodes = [];
767 for (var i = 0; i < transientObservedNodes.length; i++) {
768 var node = transientObservedNodes[i];
769 var registrations = registrationsTable.get(node);
770 for (var j = 0; j < registrations.length; j++) {
771 if (registrations[j] === this) {
772 registrations.splice(j, 1);
779 scope.enqueueMutation = enqueueMutation;
780 scope.registerTransientObservers = registerTransientObservers;
781 scope.wrappers.MutationObserver = MutationObserver;
782 scope.wrappers.MutationRecord = MutationRecord;
783 })(window.ShadowDOMPolyfill);
786 function TreeScope(root, parent) {
788 this.parent = parent;
790 TreeScope.prototype = {
792 if (this.root instanceof scope.wrappers.ShadowRoot) {
793 return scope.getRendererForHost(this.root.host);
797 contains: function(treeScope) {
798 for (;treeScope; treeScope = treeScope.parent) {
799 if (treeScope === this) return true;
804 function setTreeScope(node, treeScope) {
805 if (node.treeScope_ !== treeScope) {
806 node.treeScope_ = treeScope;
807 for (var sr = node.shadowRoot; sr; sr = sr.olderShadowRoot) {
808 sr.treeScope_.parent = treeScope;
810 for (var child = node.firstChild; child; child = child.nextSibling) {
811 setTreeScope(child, treeScope);
815 function getTreeScope(node) {
816 if (node instanceof scope.wrappers.Window) {
819 if (node.treeScope_) return node.treeScope_;
820 var parent = node.parentNode;
822 if (parent) treeScope = getTreeScope(parent); else treeScope = new TreeScope(node, null);
823 return node.treeScope_ = treeScope;
825 scope.TreeScope = TreeScope;
826 scope.getTreeScope = getTreeScope;
827 scope.setTreeScope = setTreeScope;
828 })(window.ShadowDOMPolyfill);
831 var forwardMethodsToWrapper = scope.forwardMethodsToWrapper;
832 var getTreeScope = scope.getTreeScope;
833 var mixin = scope.mixin;
834 var registerWrapper = scope.registerWrapper;
835 var setWrapper = scope.setWrapper;
836 var unsafeUnwrap = scope.unsafeUnwrap;
837 var unwrap = scope.unwrap;
838 var wrap = scope.wrap;
839 var wrappers = scope.wrappers;
840 var wrappedFuns = new WeakMap();
841 var listenersTable = new WeakMap();
842 var handledEventsTable = new WeakMap();
843 var currentlyDispatchingEvents = new WeakMap();
844 var targetTable = new WeakMap();
845 var currentTargetTable = new WeakMap();
846 var relatedTargetTable = new WeakMap();
847 var eventPhaseTable = new WeakMap();
848 var stopPropagationTable = new WeakMap();
849 var stopImmediatePropagationTable = new WeakMap();
850 var eventHandlersTable = new WeakMap();
851 var eventPathTable = new WeakMap();
852 function isShadowRoot(node) {
853 return node instanceof wrappers.ShadowRoot;
855 function rootOfNode(node) {
856 return getTreeScope(node).root;
858 function getEventPath(node, event) {
863 var destinationInsertionPoints = getDestinationInsertionPoints(current);
864 if (destinationInsertionPoints && destinationInsertionPoints.length > 0) {
865 for (var i = 0; i < destinationInsertionPoints.length; i++) {
866 var insertionPoint = destinationInsertionPoints[i];
867 if (isShadowInsertionPoint(insertionPoint)) {
868 var shadowRoot = rootOfNode(insertionPoint);
869 var olderShadowRoot = shadowRoot.olderShadowRoot;
870 if (olderShadowRoot) path.push(olderShadowRoot);
872 path.push(insertionPoint);
874 current = destinationInsertionPoints[destinationInsertionPoints.length - 1];
876 if (isShadowRoot(current)) {
877 if (inSameTree(node, current) && eventMustBeStopped(event)) {
880 current = current.host;
883 current = current.parentNode;
884 if (current) path.push(current);
890 function eventMustBeStopped(event) {
891 if (!event) return false;
892 switch (event.type) {
906 function isShadowInsertionPoint(node) {
907 return node instanceof HTMLShadowElement;
909 function getDestinationInsertionPoints(node) {
910 return scope.getDestinationInsertionPoints(node);
912 function eventRetargetting(path, currentTarget) {
913 if (path.length === 0) return currentTarget;
914 if (currentTarget instanceof wrappers.Window) currentTarget = currentTarget.document;
915 var currentTargetTree = getTreeScope(currentTarget);
916 var originalTarget = path[0];
917 var originalTargetTree = getTreeScope(originalTarget);
918 var relativeTargetTree = lowestCommonInclusiveAncestor(currentTargetTree, originalTargetTree);
919 for (var i = 0; i < path.length; i++) {
921 if (getTreeScope(node) === relativeTargetTree) return node;
923 return path[path.length - 1];
925 function getTreeScopeAncestors(treeScope) {
927 for (;treeScope; treeScope = treeScope.parent) {
928 ancestors.push(treeScope);
932 function lowestCommonInclusiveAncestor(tsA, tsB) {
933 var ancestorsA = getTreeScopeAncestors(tsA);
934 var ancestorsB = getTreeScopeAncestors(tsB);
936 while (ancestorsA.length > 0 && ancestorsB.length > 0) {
937 var a = ancestorsA.pop();
938 var b = ancestorsB.pop();
939 if (a === b) result = a; else break;
943 function getTreeScopeRoot(ts) {
944 if (!ts.parent) return ts;
945 return getTreeScopeRoot(ts.parent);
947 function relatedTargetResolution(event, currentTarget, relatedTarget) {
948 if (currentTarget instanceof wrappers.Window) currentTarget = currentTarget.document;
949 var currentTargetTree = getTreeScope(currentTarget);
950 var relatedTargetTree = getTreeScope(relatedTarget);
951 var relatedTargetEventPath = getEventPath(relatedTarget, event);
952 var lowestCommonAncestorTree;
953 var lowestCommonAncestorTree = lowestCommonInclusiveAncestor(currentTargetTree, relatedTargetTree);
954 if (!lowestCommonAncestorTree) lowestCommonAncestorTree = relatedTargetTree.root;
955 for (var commonAncestorTree = lowestCommonAncestorTree; commonAncestorTree; commonAncestorTree = commonAncestorTree.parent) {
956 var adjustedRelatedTarget;
957 for (var i = 0; i < relatedTargetEventPath.length; i++) {
958 var node = relatedTargetEventPath[i];
959 if (getTreeScope(node) === commonAncestorTree) return node;
964 function inSameTree(a, b) {
965 return getTreeScope(a) === getTreeScope(b);
968 var CAPTURING_PHASE = 1;
970 var BUBBLING_PHASE = 3;
972 function dispatchOriginalEvent(originalEvent) {
973 if (handledEventsTable.get(originalEvent)) return;
974 handledEventsTable.set(originalEvent, true);
975 dispatchEvent(wrap(originalEvent), wrap(originalEvent.target));
977 var err = pendingError;
982 function isLoadLikeEvent(event) {
983 switch (event.type) {
991 function dispatchEvent(event, originalWrapperTarget) {
992 if (currentlyDispatchingEvents.get(event)) throw new Error("InvalidStateError");
993 currentlyDispatchingEvents.set(event, true);
994 scope.renderAllPending();
998 if (isLoadLikeEvent(event) && !event.bubbles) {
999 var doc = originalWrapperTarget;
1000 if (doc instanceof wrappers.Document && (win = doc.defaultView)) {
1001 overrideTarget = doc;
1006 if (originalWrapperTarget instanceof wrappers.Window) {
1007 win = originalWrapperTarget;
1010 eventPath = getEventPath(originalWrapperTarget, event);
1011 if (!isLoadLikeEvent(event)) {
1012 var doc = eventPath[eventPath.length - 1];
1013 if (doc instanceof wrappers.Document) win = doc.defaultView;
1017 eventPathTable.set(event, eventPath);
1018 if (dispatchCapturing(event, eventPath, win, overrideTarget)) {
1019 if (dispatchAtTarget(event, eventPath, win, overrideTarget)) {
1020 dispatchBubbling(event, eventPath, win, overrideTarget);
1023 eventPhaseTable.set(event, NONE);
1024 currentTargetTable.delete(event, null);
1025 currentlyDispatchingEvents.delete(event);
1026 return event.defaultPrevented;
1028 function dispatchCapturing(event, eventPath, win, overrideTarget) {
1029 var phase = CAPTURING_PHASE;
1031 if (!invoke(win, event, phase, eventPath, overrideTarget)) return false;
1033 for (var i = eventPath.length - 1; i > 0; i--) {
1034 if (!invoke(eventPath[i], event, phase, eventPath, overrideTarget)) return false;
1038 function dispatchAtTarget(event, eventPath, win, overrideTarget) {
1039 var phase = AT_TARGET;
1040 var currentTarget = eventPath[0] || win;
1041 return invoke(currentTarget, event, phase, eventPath, overrideTarget);
1043 function dispatchBubbling(event, eventPath, win, overrideTarget) {
1044 var phase = BUBBLING_PHASE;
1045 for (var i = 1; i < eventPath.length; i++) {
1046 if (!invoke(eventPath[i], event, phase, eventPath, overrideTarget)) return;
1048 if (win && eventPath.length > 0) {
1049 invoke(win, event, phase, eventPath, overrideTarget);
1052 function invoke(currentTarget, event, phase, eventPath, overrideTarget) {
1053 var listeners = listenersTable.get(currentTarget);
1054 if (!listeners) return true;
1055 var target = overrideTarget || eventRetargetting(eventPath, currentTarget);
1056 if (target === currentTarget) {
1057 if (phase === CAPTURING_PHASE) return true;
1058 if (phase === BUBBLING_PHASE) phase = AT_TARGET;
1059 } else if (phase === BUBBLING_PHASE && !event.bubbles) {
1062 if ("relatedTarget" in event) {
1063 var originalEvent = unwrap(event);
1064 var unwrappedRelatedTarget = originalEvent.relatedTarget;
1065 if (unwrappedRelatedTarget) {
1066 if (unwrappedRelatedTarget instanceof Object && unwrappedRelatedTarget.addEventListener) {
1067 var relatedTarget = wrap(unwrappedRelatedTarget);
1068 var adjusted = relatedTargetResolution(event, currentTarget, relatedTarget);
1069 if (adjusted === target) return true;
1073 relatedTargetTable.set(event, adjusted);
1076 eventPhaseTable.set(event, phase);
1077 var type = event.type;
1078 var anyRemoved = false;
1079 targetTable.set(event, target);
1080 currentTargetTable.set(event, currentTarget);
1082 for (var i = 0, len = listeners.length; i < len; i++) {
1083 var listener = listeners[i];
1084 if (listener.removed) {
1088 if (listener.type !== type || !listener.capture && phase === CAPTURING_PHASE || listener.capture && phase === BUBBLING_PHASE) {
1092 if (typeof listener.handler === "function") listener.handler.call(currentTarget, event); else listener.handler.handleEvent(event);
1093 if (stopImmediatePropagationTable.get(event)) return false;
1095 if (!pendingError) pendingError = ex;
1099 if (anyRemoved && listeners.depth === 0) {
1100 var copy = listeners.slice();
1101 listeners.length = 0;
1102 for (var i = 0; i < copy.length; i++) {
1103 if (!copy[i].removed) listeners.push(copy[i]);
1106 return !stopPropagationTable.get(event);
1108 function Listener(type, handler, capture) {
1110 this.handler = handler;
1111 this.capture = Boolean(capture);
1113 Listener.prototype = {
1114 equals: function(that) {
1115 return this.handler === that.handler && this.type === that.type && this.capture === that.capture;
1118 return this.handler === null;
1120 remove: function() {
1121 this.handler = null;
1124 var OriginalEvent = window.Event;
1125 OriginalEvent.prototype.polymerBlackList_ = {
1129 function Event(type, options) {
1130 if (type instanceof OriginalEvent) {
1132 if (!OriginalBeforeUnloadEvent && impl.type === "beforeunload" && !(this instanceof BeforeUnloadEvent)) {
1133 return new BeforeUnloadEvent(impl);
1135 setWrapper(impl, this);
1137 return wrap(constructEvent(OriginalEvent, "Event", type, options));
1142 return targetTable.get(this);
1144 get currentTarget() {
1145 return currentTargetTable.get(this);
1148 return eventPhaseTable.get(this);
1151 var eventPath = eventPathTable.get(this);
1152 if (!eventPath) return [];
1153 return eventPath.slice();
1155 stopPropagation: function() {
1156 stopPropagationTable.set(this, true);
1158 stopImmediatePropagation: function() {
1159 stopPropagationTable.set(this, true);
1160 stopImmediatePropagationTable.set(this, true);
1163 var supportsDefaultPrevented = function() {
1164 var e = document.createEvent("Event");
1165 e.initEvent("test", true, true);
1167 return e.defaultPrevented;
1169 if (!supportsDefaultPrevented) {
1170 Event.prototype.preventDefault = function() {
1171 if (!this.cancelable) return;
1172 unsafeUnwrap(this).preventDefault();
1173 Object.defineProperty(this, "defaultPrevented", {
1181 registerWrapper(OriginalEvent, Event, document.createEvent("Event"));
1182 function unwrapOptions(options) {
1183 if (!options || !options.relatedTarget) return options;
1184 return Object.create(options, {
1186 value: unwrap(options.relatedTarget)
1190 function registerGenericEvent(name, SuperEvent, prototype) {
1191 var OriginalEvent = window[name];
1192 var GenericEvent = function(type, options) {
1193 if (type instanceof OriginalEvent) setWrapper(type, this); else return wrap(constructEvent(OriginalEvent, name, type, options));
1195 GenericEvent.prototype = Object.create(SuperEvent.prototype);
1196 if (prototype) mixin(GenericEvent.prototype, prototype);
1197 if (OriginalEvent) {
1199 registerWrapper(OriginalEvent, GenericEvent, new OriginalEvent("temp"));
1201 registerWrapper(OriginalEvent, GenericEvent, document.createEvent(name));
1204 return GenericEvent;
1206 var UIEvent = registerGenericEvent("UIEvent", Event);
1207 var CustomEvent = registerGenericEvent("CustomEvent", Event);
1208 var relatedTargetProto = {
1209 get relatedTarget() {
1210 var relatedTarget = relatedTargetTable.get(this);
1211 if (relatedTarget !== undefined) return relatedTarget;
1212 return wrap(unwrap(this).relatedTarget);
1215 function getInitFunction(name, relatedTargetIndex) {
1217 arguments[relatedTargetIndex] = unwrap(arguments[relatedTargetIndex]);
1218 var impl = unwrap(this);
1219 impl[name].apply(impl, arguments);
1222 var mouseEventProto = mixin({
1223 initMouseEvent: getInitFunction("initMouseEvent", 14)
1224 }, relatedTargetProto);
1225 var focusEventProto = mixin({
1226 initFocusEvent: getInitFunction("initFocusEvent", 5)
1227 }, relatedTargetProto);
1228 var MouseEvent = registerGenericEvent("MouseEvent", UIEvent, mouseEventProto);
1229 var FocusEvent = registerGenericEvent("FocusEvent", UIEvent, focusEventProto);
1230 var defaultInitDicts = Object.create(null);
1231 var supportsEventConstructors = function() {
1233 new window.FocusEvent("focus");
1239 function constructEvent(OriginalEvent, name, type, options) {
1240 if (supportsEventConstructors) return new OriginalEvent(type, unwrapOptions(options));
1241 var event = unwrap(document.createEvent(name));
1242 var defaultDict = defaultInitDicts[name];
1243 var args = [ type ];
1244 Object.keys(defaultDict).forEach(function(key) {
1245 var v = options != null && key in options ? options[key] : defaultDict[key];
1246 if (key === "relatedTarget") v = unwrap(v);
1249 event["init" + name].apply(event, args);
1252 if (!supportsEventConstructors) {
1253 var configureEventConstructor = function(name, initDict, superName) {
1255 var superDict = defaultInitDicts[superName];
1256 initDict = mixin(mixin({}, superDict), initDict);
1258 defaultInitDicts[name] = initDict;
1260 configureEventConstructor("Event", {
1264 configureEventConstructor("CustomEvent", {
1267 configureEventConstructor("UIEvent", {
1271 configureEventConstructor("MouseEvent", {
1283 configureEventConstructor("FocusEvent", {
1287 var OriginalBeforeUnloadEvent = window.BeforeUnloadEvent;
1288 function BeforeUnloadEvent(impl) {
1289 Event.call(this, impl);
1291 BeforeUnloadEvent.prototype = Object.create(Event.prototype);
1292 mixin(BeforeUnloadEvent.prototype, {
1294 return unsafeUnwrap(this).returnValue;
1296 set returnValue(v) {
1297 unsafeUnwrap(this).returnValue = v;
1300 if (OriginalBeforeUnloadEvent) registerWrapper(OriginalBeforeUnloadEvent, BeforeUnloadEvent);
1301 function isValidListener(fun) {
1302 if (typeof fun === "function") return true;
1303 return fun && fun.handleEvent;
1305 function isMutationEvent(type) {
1307 case "DOMAttrModified":
1308 case "DOMAttributeNameChanged":
1309 case "DOMCharacterDataModified":
1310 case "DOMElementNameChanged":
1311 case "DOMNodeInserted":
1312 case "DOMNodeInsertedIntoDocument":
1313 case "DOMNodeRemoved":
1314 case "DOMNodeRemovedFromDocument":
1315 case "DOMSubtreeModified":
1320 var OriginalEventTarget = window.EventTarget;
1321 function EventTarget(impl) {
1322 setWrapper(impl, this);
1324 var methodNames = [ "addEventListener", "removeEventListener", "dispatchEvent" ];
1325 [ Node, Window ].forEach(function(constructor) {
1326 var p = constructor.prototype;
1327 methodNames.forEach(function(name) {
1328 Object.defineProperty(p, name + "_", {
1333 function getTargetToListenAt(wrapper) {
1334 if (wrapper instanceof wrappers.ShadowRoot) wrapper = wrapper.host;
1335 return unwrap(wrapper);
1337 EventTarget.prototype = {
1338 addEventListener: function(type, fun, capture) {
1339 if (!isValidListener(fun) || isMutationEvent(type)) return;
1340 var listener = new Listener(type, fun, capture);
1341 var listeners = listenersTable.get(this);
1344 listeners.depth = 0;
1345 listenersTable.set(this, listeners);
1347 for (var i = 0; i < listeners.length; i++) {
1348 if (listener.equals(listeners[i])) return;
1351 listeners.push(listener);
1352 var target = getTargetToListenAt(this);
1353 target.addEventListener_(type, dispatchOriginalEvent, true);
1355 removeEventListener: function(type, fun, capture) {
1356 capture = Boolean(capture);
1357 var listeners = listenersTable.get(this);
1358 if (!listeners) return;
1359 var count = 0, found = false;
1360 for (var i = 0; i < listeners.length; i++) {
1361 if (listeners[i].type === type && listeners[i].capture === capture) {
1363 if (listeners[i].handler === fun) {
1365 listeners[i].remove();
1369 if (found && count === 1) {
1370 var target = getTargetToListenAt(this);
1371 target.removeEventListener_(type, dispatchOriginalEvent, true);
1374 dispatchEvent: function(event) {
1375 var nativeEvent = unwrap(event);
1376 var eventType = nativeEvent.type;
1377 handledEventsTable.set(nativeEvent, false);
1378 scope.renderAllPending();
1380 if (!hasListenerInAncestors(this, eventType)) {
1381 tempListener = function() {};
1382 this.addEventListener(eventType, tempListener, true);
1385 return unwrap(this).dispatchEvent_(nativeEvent);
1387 if (tempListener) this.removeEventListener(eventType, tempListener, true);
1391 function hasListener(node, type) {
1392 var listeners = listenersTable.get(node);
1394 for (var i = 0; i < listeners.length; i++) {
1395 if (!listeners[i].removed && listeners[i].type === type) return true;
1400 function hasListenerInAncestors(target, type) {
1401 for (var node = unwrap(target); node; node = node.parentNode) {
1402 if (hasListener(wrap(node), type)) return true;
1406 if (OriginalEventTarget) registerWrapper(OriginalEventTarget, EventTarget);
1407 function wrapEventTargetMethods(constructors) {
1408 forwardMethodsToWrapper(constructors, methodNames);
1410 var originalElementFromPoint = document.elementFromPoint;
1411 function elementFromPoint(self, document, x, y) {
1412 scope.renderAllPending();
1413 var element = wrap(originalElementFromPoint.call(unsafeUnwrap(document), x, y));
1414 if (!element) return null;
1415 var path = getEventPath(element, null);
1416 var idx = path.lastIndexOf(self);
1417 if (idx == -1) return null; else path = path.slice(0, idx);
1418 return eventRetargetting(path, self);
1420 function getEventHandlerGetter(name) {
1422 var inlineEventHandlers = eventHandlersTable.get(this);
1423 return inlineEventHandlers && inlineEventHandlers[name] && inlineEventHandlers[name].value || null;
1426 function getEventHandlerSetter(name) {
1427 var eventType = name.slice(2);
1428 return function(value) {
1429 var inlineEventHandlers = eventHandlersTable.get(this);
1430 if (!inlineEventHandlers) {
1431 inlineEventHandlers = Object.create(null);
1432 eventHandlersTable.set(this, inlineEventHandlers);
1434 var old = inlineEventHandlers[name];
1435 if (old) this.removeEventListener(eventType, old.wrapped, false);
1436 if (typeof value === "function") {
1437 var wrapped = function(e) {
1438 var rv = value.call(this, e);
1439 if (rv === false) e.preventDefault(); else if (name === "onbeforeunload" && typeof rv === "string") e.returnValue = rv;
1441 this.addEventListener(eventType, wrapped, false);
1442 inlineEventHandlers[name] = {
1449 scope.elementFromPoint = elementFromPoint;
1450 scope.getEventHandlerGetter = getEventHandlerGetter;
1451 scope.getEventHandlerSetter = getEventHandlerSetter;
1452 scope.wrapEventTargetMethods = wrapEventTargetMethods;
1453 scope.wrappers.BeforeUnloadEvent = BeforeUnloadEvent;
1454 scope.wrappers.CustomEvent = CustomEvent;
1455 scope.wrappers.Event = Event;
1456 scope.wrappers.EventTarget = EventTarget;
1457 scope.wrappers.FocusEvent = FocusEvent;
1458 scope.wrappers.MouseEvent = MouseEvent;
1459 scope.wrappers.UIEvent = UIEvent;
1460 })(window.ShadowDOMPolyfill);
1463 var UIEvent = scope.wrappers.UIEvent;
1464 var mixin = scope.mixin;
1465 var registerWrapper = scope.registerWrapper;
1466 var setWrapper = scope.setWrapper;
1467 var unsafeUnwrap = scope.unsafeUnwrap;
1468 var wrap = scope.wrap;
1469 var OriginalTouchEvent = window.TouchEvent;
1470 if (!OriginalTouchEvent) return;
1473 nativeEvent = document.createEvent("TouchEvent");
1477 var nonEnumDescriptor = {
1480 function nonEnum(obj, prop) {
1481 Object.defineProperty(obj, prop, nonEnumDescriptor);
1483 function Touch(impl) {
1484 setWrapper(impl, this);
1488 return wrap(unsafeUnwrap(this).target);
1496 [ "clientX", "clientY", "screenX", "screenY", "pageX", "pageY", "identifier", "webkitRadiusX", "webkitRadiusY", "webkitRotationAngle", "webkitForce" ].forEach(function(name) {
1497 descr.get = function() {
1498 return unsafeUnwrap(this)[name];
1500 Object.defineProperty(Touch.prototype, name, descr);
1502 function TouchList() {
1504 nonEnum(this, "length");
1506 TouchList.prototype = {
1507 item: function(index) {
1511 function wrapTouchList(nativeTouchList) {
1512 var list = new TouchList();
1513 for (var i = 0; i < nativeTouchList.length; i++) {
1514 list[i] = new Touch(nativeTouchList[i]);
1519 function TouchEvent(impl) {
1520 UIEvent.call(this, impl);
1522 TouchEvent.prototype = Object.create(UIEvent.prototype);
1523 mixin(TouchEvent.prototype, {
1525 return wrapTouchList(unsafeUnwrap(this).touches);
1527 get targetTouches() {
1528 return wrapTouchList(unsafeUnwrap(this).targetTouches);
1530 get changedTouches() {
1531 return wrapTouchList(unsafeUnwrap(this).changedTouches);
1533 initTouchEvent: function() {
1534 throw new Error("Not implemented");
1537 registerWrapper(OriginalTouchEvent, TouchEvent, nativeEvent);
1538 scope.wrappers.Touch = Touch;
1539 scope.wrappers.TouchEvent = TouchEvent;
1540 scope.wrappers.TouchList = TouchList;
1541 })(window.ShadowDOMPolyfill);
1544 var unsafeUnwrap = scope.unsafeUnwrap;
1545 var wrap = scope.wrap;
1546 var nonEnumDescriptor = {
1549 function nonEnum(obj, prop) {
1550 Object.defineProperty(obj, prop, nonEnumDescriptor);
1552 function NodeList() {
1554 nonEnum(this, "length");
1556 NodeList.prototype = {
1557 item: function(index) {
1561 nonEnum(NodeList.prototype, "item");
1562 function wrapNodeList(list) {
1563 if (list == null) return list;
1564 var wrapperList = new NodeList();
1565 for (var i = 0, length = list.length; i < length; i++) {
1566 wrapperList[i] = wrap(list[i]);
1568 wrapperList.length = length;
1571 function addWrapNodeListMethod(wrapperConstructor, name) {
1572 wrapperConstructor.prototype[name] = function() {
1573 return wrapNodeList(unsafeUnwrap(this)[name].apply(unsafeUnwrap(this), arguments));
1576 scope.wrappers.NodeList = NodeList;
1577 scope.addWrapNodeListMethod = addWrapNodeListMethod;
1578 scope.wrapNodeList = wrapNodeList;
1579 })(window.ShadowDOMPolyfill);
1582 scope.wrapHTMLCollection = scope.wrapNodeList;
1583 scope.wrappers.HTMLCollection = scope.wrappers.NodeList;
1584 })(window.ShadowDOMPolyfill);
1587 var EventTarget = scope.wrappers.EventTarget;
1588 var NodeList = scope.wrappers.NodeList;
1589 var TreeScope = scope.TreeScope;
1590 var assert = scope.assert;
1591 var defineWrapGetter = scope.defineWrapGetter;
1592 var enqueueMutation = scope.enqueueMutation;
1593 var getTreeScope = scope.getTreeScope;
1594 var isWrapper = scope.isWrapper;
1595 var mixin = scope.mixin;
1596 var registerTransientObservers = scope.registerTransientObservers;
1597 var registerWrapper = scope.registerWrapper;
1598 var setTreeScope = scope.setTreeScope;
1599 var unsafeUnwrap = scope.unsafeUnwrap;
1600 var unwrap = scope.unwrap;
1601 var unwrapIfNeeded = scope.unwrapIfNeeded;
1602 var wrap = scope.wrap;
1603 var wrapIfNeeded = scope.wrapIfNeeded;
1604 var wrappers = scope.wrappers;
1605 function assertIsNodeWrapper(node) {
1606 assert(node instanceof Node);
1608 function createOneElementNodeList(node) {
1609 var nodes = new NodeList();
1614 var surpressMutations = false;
1615 function enqueueRemovalForInsertedNodes(node, parent, nodes) {
1616 enqueueMutation(parent, "childList", {
1617 removedNodes: nodes,
1618 previousSibling: node.previousSibling,
1619 nextSibling: node.nextSibling
1622 function enqueueRemovalForInsertedDocumentFragment(df, nodes) {
1623 enqueueMutation(df, "childList", {
1627 function collectNodes(node, parentNode, previousNode, nextNode) {
1628 if (node instanceof DocumentFragment) {
1629 var nodes = collectNodesForDocumentFragment(node);
1630 surpressMutations = true;
1631 for (var i = nodes.length - 1; i >= 0; i--) {
1632 node.removeChild(nodes[i]);
1633 nodes[i].parentNode_ = parentNode;
1635 surpressMutations = false;
1636 for (var i = 0; i < nodes.length; i++) {
1637 nodes[i].previousSibling_ = nodes[i - 1] || previousNode;
1638 nodes[i].nextSibling_ = nodes[i + 1] || nextNode;
1640 if (previousNode) previousNode.nextSibling_ = nodes[0];
1641 if (nextNode) nextNode.previousSibling_ = nodes[nodes.length - 1];
1644 var nodes = createOneElementNodeList(node);
1645 var oldParent = node.parentNode;
1647 oldParent.removeChild(node);
1649 node.parentNode_ = parentNode;
1650 node.previousSibling_ = previousNode;
1651 node.nextSibling_ = nextNode;
1652 if (previousNode) previousNode.nextSibling_ = node;
1653 if (nextNode) nextNode.previousSibling_ = node;
1656 function collectNodesNative(node) {
1657 if (node instanceof DocumentFragment) return collectNodesForDocumentFragment(node);
1658 var nodes = createOneElementNodeList(node);
1659 var oldParent = node.parentNode;
1660 if (oldParent) enqueueRemovalForInsertedNodes(node, oldParent, nodes);
1663 function collectNodesForDocumentFragment(node) {
1664 var nodes = new NodeList();
1666 for (var child = node.firstChild; child; child = child.nextSibling) {
1670 enqueueRemovalForInsertedDocumentFragment(node, nodes);
1673 function snapshotNodeList(nodeList) {
1676 function nodeWasAdded(node, treeScope) {
1677 setTreeScope(node, treeScope);
1678 node.nodeIsInserted_();
1680 function nodesWereAdded(nodes, parent) {
1681 var treeScope = getTreeScope(parent);
1682 for (var i = 0; i < nodes.length; i++) {
1683 nodeWasAdded(nodes[i], treeScope);
1686 function nodeWasRemoved(node) {
1687 setTreeScope(node, new TreeScope(node, null));
1689 function nodesWereRemoved(nodes) {
1690 for (var i = 0; i < nodes.length; i++) {
1691 nodeWasRemoved(nodes[i]);
1694 function ensureSameOwnerDocument(parent, child) {
1695 var ownerDoc = parent.nodeType === Node.DOCUMENT_NODE ? parent : parent.ownerDocument;
1696 if (ownerDoc !== child.ownerDocument) ownerDoc.adoptNode(child);
1698 function adoptNodesIfNeeded(owner, nodes) {
1699 if (!nodes.length) return;
1700 var ownerDoc = owner.ownerDocument;
1701 if (ownerDoc === nodes[0].ownerDocument) return;
1702 for (var i = 0; i < nodes.length; i++) {
1703 scope.adoptNodeNoRemove(nodes[i], ownerDoc);
1706 function unwrapNodesForInsertion(owner, nodes) {
1707 adoptNodesIfNeeded(owner, nodes);
1708 var length = nodes.length;
1709 if (length === 1) return unwrap(nodes[0]);
1710 var df = unwrap(owner.ownerDocument.createDocumentFragment());
1711 for (var i = 0; i < length; i++) {
1712 df.appendChild(unwrap(nodes[i]));
1716 function clearChildNodes(wrapper) {
1717 if (wrapper.firstChild_ !== undefined) {
1718 var child = wrapper.firstChild_;
1721 child = child.nextSibling_;
1722 tmp.parentNode_ = tmp.previousSibling_ = tmp.nextSibling_ = undefined;
1725 wrapper.firstChild_ = wrapper.lastChild_ = undefined;
1727 function removeAllChildNodes(wrapper) {
1728 if (wrapper.invalidateShadowRenderer()) {
1729 var childWrapper = wrapper.firstChild;
1730 while (childWrapper) {
1731 assert(childWrapper.parentNode === wrapper);
1732 var nextSibling = childWrapper.nextSibling;
1733 var childNode = unwrap(childWrapper);
1734 var parentNode = childNode.parentNode;
1735 if (parentNode) originalRemoveChild.call(parentNode, childNode);
1736 childWrapper.previousSibling_ = childWrapper.nextSibling_ = childWrapper.parentNode_ = null;
1737 childWrapper = nextSibling;
1739 wrapper.firstChild_ = wrapper.lastChild_ = null;
1741 var node = unwrap(wrapper);
1742 var child = node.firstChild;
1745 nextSibling = child.nextSibling;
1746 originalRemoveChild.call(node, child);
1747 child = nextSibling;
1751 function invalidateParent(node) {
1752 var p = node.parentNode;
1753 return p && p.invalidateShadowRenderer();
1755 function cleanupNodes(nodes) {
1756 for (var i = 0, n; i < nodes.length; i++) {
1758 n.parentNode.removeChild(n);
1761 var originalImportNode = document.importNode;
1762 var originalCloneNode = window.Node.prototype.cloneNode;
1763 function cloneNode(node, deep, opt_doc) {
1765 if (opt_doc) clone = wrap(originalImportNode.call(opt_doc, unsafeUnwrap(node), false)); else clone = wrap(originalCloneNode.call(unsafeUnwrap(node), false));
1767 for (var child = node.firstChild; child; child = child.nextSibling) {
1768 clone.appendChild(cloneNode(child, true, opt_doc));
1770 if (node instanceof wrappers.HTMLTemplateElement) {
1771 var cloneContent = clone.content;
1772 for (var child = node.content.firstChild; child; child = child.nextSibling) {
1773 cloneContent.appendChild(cloneNode(child, true, opt_doc));
1779 function contains(self, child) {
1780 if (!child || getTreeScope(self) !== getTreeScope(child)) return false;
1781 for (var node = child; node; node = node.parentNode) {
1782 if (node === self) return true;
1786 var OriginalNode = window.Node;
1787 function Node(original) {
1788 assert(original instanceof OriginalNode);
1789 EventTarget.call(this, original);
1790 this.parentNode_ = undefined;
1791 this.firstChild_ = undefined;
1792 this.lastChild_ = undefined;
1793 this.nextSibling_ = undefined;
1794 this.previousSibling_ = undefined;
1795 this.treeScope_ = undefined;
1797 var OriginalDocumentFragment = window.DocumentFragment;
1798 var originalAppendChild = OriginalNode.prototype.appendChild;
1799 var originalCompareDocumentPosition = OriginalNode.prototype.compareDocumentPosition;
1800 var originalIsEqualNode = OriginalNode.prototype.isEqualNode;
1801 var originalInsertBefore = OriginalNode.prototype.insertBefore;
1802 var originalRemoveChild = OriginalNode.prototype.removeChild;
1803 var originalReplaceChild = OriginalNode.prototype.replaceChild;
1804 var isIEOrEdge = /Trident|Edge/.test(navigator.userAgent);
1805 var removeChildOriginalHelper = isIEOrEdge ? function(parent, child) {
1807 originalRemoveChild.call(parent, child);
1809 if (!(parent instanceof OriginalDocumentFragment)) throw ex;
1811 } : function(parent, child) {
1812 originalRemoveChild.call(parent, child);
1814 Node.prototype = Object.create(EventTarget.prototype);
1815 mixin(Node.prototype, {
1816 appendChild: function(childWrapper) {
1817 return this.insertBefore(childWrapper, null);
1819 insertBefore: function(childWrapper, refWrapper) {
1820 assertIsNodeWrapper(childWrapper);
1823 if (isWrapper(refWrapper)) {
1824 refNode = unwrap(refWrapper);
1826 refNode = refWrapper;
1827 refWrapper = wrap(refNode);
1833 refWrapper && assert(refWrapper.parentNode === this);
1835 var previousNode = refWrapper ? refWrapper.previousSibling : this.lastChild;
1836 var useNative = !this.invalidateShadowRenderer() && !invalidateParent(childWrapper);
1837 if (useNative) nodes = collectNodesNative(childWrapper); else nodes = collectNodes(childWrapper, this, previousNode, refWrapper);
1839 ensureSameOwnerDocument(this, childWrapper);
1840 clearChildNodes(this);
1841 originalInsertBefore.call(unsafeUnwrap(this), unwrap(childWrapper), refNode);
1843 if (!previousNode) this.firstChild_ = nodes[0];
1845 this.lastChild_ = nodes[nodes.length - 1];
1846 if (this.firstChild_ === undefined) this.firstChild_ = this.firstChild;
1848 var parentNode = refNode ? refNode.parentNode : unsafeUnwrap(this);
1850 originalInsertBefore.call(parentNode, unwrapNodesForInsertion(this, nodes), refNode);
1852 adoptNodesIfNeeded(this, nodes);
1855 enqueueMutation(this, "childList", {
1857 nextSibling: refWrapper,
1858 previousSibling: previousNode
1860 nodesWereAdded(nodes, this);
1861 return childWrapper;
1863 removeChild: function(childWrapper) {
1864 assertIsNodeWrapper(childWrapper);
1865 if (childWrapper.parentNode !== this) {
1867 var childNodes = this.childNodes;
1868 for (var ieChild = this.firstChild; ieChild; ieChild = ieChild.nextSibling) {
1869 if (ieChild === childWrapper) {
1875 throw new Error("NotFoundError");
1878 var childNode = unwrap(childWrapper);
1879 var childWrapperNextSibling = childWrapper.nextSibling;
1880 var childWrapperPreviousSibling = childWrapper.previousSibling;
1881 if (this.invalidateShadowRenderer()) {
1882 var thisFirstChild = this.firstChild;
1883 var thisLastChild = this.lastChild;
1884 var parentNode = childNode.parentNode;
1885 if (parentNode) removeChildOriginalHelper(parentNode, childNode);
1886 if (thisFirstChild === childWrapper) this.firstChild_ = childWrapperNextSibling;
1887 if (thisLastChild === childWrapper) this.lastChild_ = childWrapperPreviousSibling;
1888 if (childWrapperPreviousSibling) childWrapperPreviousSibling.nextSibling_ = childWrapperNextSibling;
1889 if (childWrapperNextSibling) {
1890 childWrapperNextSibling.previousSibling_ = childWrapperPreviousSibling;
1892 childWrapper.previousSibling_ = childWrapper.nextSibling_ = childWrapper.parentNode_ = undefined;
1894 clearChildNodes(this);
1895 removeChildOriginalHelper(unsafeUnwrap(this), childNode);
1897 if (!surpressMutations) {
1898 enqueueMutation(this, "childList", {
1899 removedNodes: createOneElementNodeList(childWrapper),
1900 nextSibling: childWrapperNextSibling,
1901 previousSibling: childWrapperPreviousSibling
1904 registerTransientObservers(this, childWrapper);
1905 return childWrapper;
1907 replaceChild: function(newChildWrapper, oldChildWrapper) {
1908 assertIsNodeWrapper(newChildWrapper);
1910 if (isWrapper(oldChildWrapper)) {
1911 oldChildNode = unwrap(oldChildWrapper);
1913 oldChildNode = oldChildWrapper;
1914 oldChildWrapper = wrap(oldChildNode);
1916 if (oldChildWrapper.parentNode !== this) {
1917 throw new Error("NotFoundError");
1919 var nextNode = oldChildWrapper.nextSibling;
1920 var previousNode = oldChildWrapper.previousSibling;
1922 var useNative = !this.invalidateShadowRenderer() && !invalidateParent(newChildWrapper);
1924 nodes = collectNodesNative(newChildWrapper);
1926 if (nextNode === newChildWrapper) nextNode = newChildWrapper.nextSibling;
1927 nodes = collectNodes(newChildWrapper, this, previousNode, nextNode);
1930 if (this.firstChild === oldChildWrapper) this.firstChild_ = nodes[0];
1931 if (this.lastChild === oldChildWrapper) this.lastChild_ = nodes[nodes.length - 1];
1932 oldChildWrapper.previousSibling_ = oldChildWrapper.nextSibling_ = oldChildWrapper.parentNode_ = undefined;
1933 if (oldChildNode.parentNode) {
1934 originalReplaceChild.call(oldChildNode.parentNode, unwrapNodesForInsertion(this, nodes), oldChildNode);
1937 ensureSameOwnerDocument(this, newChildWrapper);
1938 clearChildNodes(this);
1939 originalReplaceChild.call(unsafeUnwrap(this), unwrap(newChildWrapper), oldChildNode);
1941 enqueueMutation(this, "childList", {
1943 removedNodes: createOneElementNodeList(oldChildWrapper),
1944 nextSibling: nextNode,
1945 previousSibling: previousNode
1947 nodeWasRemoved(oldChildWrapper);
1948 nodesWereAdded(nodes, this);
1949 return oldChildWrapper;
1951 nodeIsInserted_: function() {
1952 for (var child = this.firstChild; child; child = child.nextSibling) {
1953 child.nodeIsInserted_();
1956 hasChildNodes: function() {
1957 return this.firstChild !== null;
1960 return this.parentNode_ !== undefined ? this.parentNode_ : wrap(unsafeUnwrap(this).parentNode);
1963 return this.firstChild_ !== undefined ? this.firstChild_ : wrap(unsafeUnwrap(this).firstChild);
1966 return this.lastChild_ !== undefined ? this.lastChild_ : wrap(unsafeUnwrap(this).lastChild);
1969 return this.nextSibling_ !== undefined ? this.nextSibling_ : wrap(unsafeUnwrap(this).nextSibling);
1971 get previousSibling() {
1972 return this.previousSibling_ !== undefined ? this.previousSibling_ : wrap(unsafeUnwrap(this).previousSibling);
1974 get parentElement() {
1975 var p = this.parentNode;
1976 while (p && p.nodeType !== Node.ELEMENT_NODE) {
1983 for (var child = this.firstChild; child; child = child.nextSibling) {
1984 if (child.nodeType != Node.COMMENT_NODE) {
1985 s += child.textContent;
1990 set textContent(textContent) {
1991 if (textContent == null) textContent = "";
1992 var removedNodes = snapshotNodeList(this.childNodes);
1993 if (this.invalidateShadowRenderer()) {
1994 removeAllChildNodes(this);
1995 if (textContent !== "") {
1996 var textNode = unsafeUnwrap(this).ownerDocument.createTextNode(textContent);
1997 this.appendChild(textNode);
2000 clearChildNodes(this);
2001 unsafeUnwrap(this).textContent = textContent;
2003 var addedNodes = snapshotNodeList(this.childNodes);
2004 enqueueMutation(this, "childList", {
2005 addedNodes: addedNodes,
2006 removedNodes: removedNodes
2008 nodesWereRemoved(removedNodes);
2009 nodesWereAdded(addedNodes, this);
2012 var wrapperList = new NodeList();
2014 for (var child = this.firstChild; child; child = child.nextSibling) {
2015 wrapperList[i++] = child;
2017 wrapperList.length = i;
2020 cloneNode: function(deep) {
2021 return cloneNode(this, deep);
2023 contains: function(child) {
2024 return contains(this, wrapIfNeeded(child));
2026 compareDocumentPosition: function(otherNode) {
2027 return originalCompareDocumentPosition.call(unsafeUnwrap(this), unwrapIfNeeded(otherNode));
2029 isEqualNode: function(otherNode) {
2030 return originalIsEqualNode.call(unsafeUnwrap(this), unwrapIfNeeded(otherNode));
2032 normalize: function() {
2033 var nodes = snapshotNodeList(this.childNodes);
2037 for (var i = 0, n; i < nodes.length; i++) {
2039 if (n.nodeType === Node.TEXT_NODE) {
2040 if (!modNode && !n.data.length) this.removeChild(n); else if (!modNode) modNode = n; else {
2045 if (modNode && remNodes.length) {
2047 cleanupNodes(remNodes);
2052 if (n.childNodes.length) n.normalize();
2055 if (modNode && remNodes.length) {
2057 cleanupNodes(remNodes);
2061 defineWrapGetter(Node, "ownerDocument");
2062 registerWrapper(OriginalNode, Node, document.createDocumentFragment());
2063 delete Node.prototype.querySelector;
2064 delete Node.prototype.querySelectorAll;
2065 Node.prototype = mixin(Object.create(EventTarget.prototype), Node.prototype);
2066 scope.cloneNode = cloneNode;
2067 scope.nodeWasAdded = nodeWasAdded;
2068 scope.nodeWasRemoved = nodeWasRemoved;
2069 scope.nodesWereAdded = nodesWereAdded;
2070 scope.nodesWereRemoved = nodesWereRemoved;
2071 scope.originalInsertBefore = originalInsertBefore;
2072 scope.originalRemoveChild = originalRemoveChild;
2073 scope.snapshotNodeList = snapshotNodeList;
2074 scope.wrappers.Node = Node;
2075 })(window.ShadowDOMPolyfill);
2078 var HTMLCollection = scope.wrappers.HTMLCollection;
2079 var NodeList = scope.wrappers.NodeList;
2080 var getTreeScope = scope.getTreeScope;
2081 var unsafeUnwrap = scope.unsafeUnwrap;
2082 var wrap = scope.wrap;
2083 var originalDocumentQuerySelector = document.querySelector;
2084 var originalElementQuerySelector = document.documentElement.querySelector;
2085 var originalDocumentQuerySelectorAll = document.querySelectorAll;
2086 var originalElementQuerySelectorAll = document.documentElement.querySelectorAll;
2087 var originalDocumentGetElementsByTagName = document.getElementsByTagName;
2088 var originalElementGetElementsByTagName = document.documentElement.getElementsByTagName;
2089 var originalDocumentGetElementsByTagNameNS = document.getElementsByTagNameNS;
2090 var originalElementGetElementsByTagNameNS = document.documentElement.getElementsByTagNameNS;
2091 var OriginalElement = window.Element;
2092 var OriginalDocument = window.HTMLDocument || window.Document;
2093 function filterNodeList(list, index, result, deep) {
2094 var wrappedItem = null;
2096 for (var i = 0, length = list.length; i < length; i++) {
2097 wrappedItem = wrap(list[i]);
2098 if (!deep && (root = getTreeScope(wrappedItem).root)) {
2099 if (root instanceof scope.wrappers.ShadowRoot) {
2103 result[index++] = wrappedItem;
2107 function shimSelector(selector) {
2108 return String(selector).replace(/\/deep\/|::shadow|>>>/g, " ");
2110 function shimMatchesSelector(selector) {
2111 return String(selector).replace(/:host\(([^\s]+)\)/g, "$1").replace(/([^\s]):host/g, "$1").replace(":host", "*").replace(/\^|\/shadow\/|\/shadow-deep\/|::shadow|\/deep\/|::content|>>>/g, " ");
2113 function findOne(node, selector) {
2114 var m, el = node.firstElementChild;
2116 if (el.matches(selector)) return el;
2117 m = findOne(el, selector);
2119 el = el.nextElementSibling;
2123 function matchesSelector(el, selector) {
2124 return el.matches(selector);
2126 var XHTML_NS = "http://www.w3.org/1999/xhtml";
2127 function matchesTagName(el, localName, localNameLowerCase) {
2128 var ln = el.localName;
2129 return ln === localName || ln === localNameLowerCase && el.namespaceURI === XHTML_NS;
2131 function matchesEveryThing() {
2134 function matchesLocalNameOnly(el, ns, localName) {
2135 return el.localName === localName;
2137 function matchesNameSpace(el, ns) {
2138 return el.namespaceURI === ns;
2140 function matchesLocalNameNS(el, ns, localName) {
2141 return el.namespaceURI === ns && el.localName === localName;
2143 function findElements(node, index, result, p, arg0, arg1) {
2144 var el = node.firstElementChild;
2146 if (p(el, arg0, arg1)) result[index++] = el;
2147 index = findElements(el, index, result, p, arg0, arg1);
2148 el = el.nextElementSibling;
2152 function querySelectorAllFiltered(p, index, result, selector, deep) {
2153 var target = unsafeUnwrap(this);
2155 var root = getTreeScope(this).root;
2156 if (root instanceof scope.wrappers.ShadowRoot) {
2157 return findElements(this, index, result, p, selector, null);
2158 } else if (target instanceof OriginalElement) {
2159 list = originalElementQuerySelectorAll.call(target, selector);
2160 } else if (target instanceof OriginalDocument) {
2161 list = originalDocumentQuerySelectorAll.call(target, selector);
2163 return findElements(this, index, result, p, selector, null);
2165 return filterNodeList(list, index, result, deep);
2167 var SelectorsInterface = {
2168 querySelector: function(selector) {
2169 var shimmed = shimSelector(selector);
2170 var deep = shimmed !== selector;
2172 var target = unsafeUnwrap(this);
2174 var root = getTreeScope(this).root;
2175 if (root instanceof scope.wrappers.ShadowRoot) {
2176 return findOne(this, selector);
2177 } else if (target instanceof OriginalElement) {
2178 wrappedItem = wrap(originalElementQuerySelector.call(target, selector));
2179 } else if (target instanceof OriginalDocument) {
2180 wrappedItem = wrap(originalDocumentQuerySelector.call(target, selector));
2182 return findOne(this, selector);
2186 } else if (!deep && (root = getTreeScope(wrappedItem).root)) {
2187 if (root instanceof scope.wrappers.ShadowRoot) {
2188 return findOne(this, selector);
2193 querySelectorAll: function(selector) {
2194 var shimmed = shimSelector(selector);
2195 var deep = shimmed !== selector;
2197 var result = new NodeList();
2198 result.length = querySelectorAllFiltered.call(this, matchesSelector, 0, result, selector, deep);
2202 var MatchesInterface = {
2203 matches: function(selector) {
2204 selector = shimMatchesSelector(selector);
2205 return scope.originalMatches.call(unsafeUnwrap(this), selector);
2208 function getElementsByTagNameFiltered(p, index, result, localName, lowercase) {
2209 var target = unsafeUnwrap(this);
2211 var root = getTreeScope(this).root;
2212 if (root instanceof scope.wrappers.ShadowRoot) {
2213 return findElements(this, index, result, p, localName, lowercase);
2214 } else if (target instanceof OriginalElement) {
2215 list = originalElementGetElementsByTagName.call(target, localName, lowercase);
2216 } else if (target instanceof OriginalDocument) {
2217 list = originalDocumentGetElementsByTagName.call(target, localName, lowercase);
2219 return findElements(this, index, result, p, localName, lowercase);
2221 return filterNodeList(list, index, result, false);
2223 function getElementsByTagNameNSFiltered(p, index, result, ns, localName) {
2224 var target = unsafeUnwrap(this);
2226 var root = getTreeScope(this).root;
2227 if (root instanceof scope.wrappers.ShadowRoot) {
2228 return findElements(this, index, result, p, ns, localName);
2229 } else if (target instanceof OriginalElement) {
2230 list = originalElementGetElementsByTagNameNS.call(target, ns, localName);
2231 } else if (target instanceof OriginalDocument) {
2232 list = originalDocumentGetElementsByTagNameNS.call(target, ns, localName);
2234 return findElements(this, index, result, p, ns, localName);
2236 return filterNodeList(list, index, result, false);
2238 var GetElementsByInterface = {
2239 getElementsByTagName: function(localName) {
2240 var result = new HTMLCollection();
2241 var match = localName === "*" ? matchesEveryThing : matchesTagName;
2242 result.length = getElementsByTagNameFiltered.call(this, match, 0, result, localName, localName.toLowerCase());
2245 getElementsByClassName: function(className) {
2246 return this.querySelectorAll("." + className);
2248 getElementsByTagNameNS: function(ns, localName) {
2249 var result = new HTMLCollection();
2252 match = localName === "*" ? matchesEveryThing : matchesLocalNameOnly;
2254 match = localName === "*" ? matchesNameSpace : matchesLocalNameNS;
2256 result.length = getElementsByTagNameNSFiltered.call(this, match, 0, result, ns || null, localName);
2260 scope.GetElementsByInterface = GetElementsByInterface;
2261 scope.SelectorsInterface = SelectorsInterface;
2262 scope.MatchesInterface = MatchesInterface;
2263 })(window.ShadowDOMPolyfill);
2266 var NodeList = scope.wrappers.NodeList;
2267 function forwardElement(node) {
2268 while (node && node.nodeType !== Node.ELEMENT_NODE) {
2269 node = node.nextSibling;
2273 function backwardsElement(node) {
2274 while (node && node.nodeType !== Node.ELEMENT_NODE) {
2275 node = node.previousSibling;
2279 var ParentNodeInterface = {
2280 get firstElementChild() {
2281 return forwardElement(this.firstChild);
2283 get lastElementChild() {
2284 return backwardsElement(this.lastChild);
2286 get childElementCount() {
2288 for (var child = this.firstElementChild; child; child = child.nextElementSibling) {
2294 var wrapperList = new NodeList();
2296 for (var child = this.firstElementChild; child; child = child.nextElementSibling) {
2297 wrapperList[i++] = child;
2299 wrapperList.length = i;
2302 remove: function() {
2303 var p = this.parentNode;
2304 if (p) p.removeChild(this);
2307 var ChildNodeInterface = {
2308 get nextElementSibling() {
2309 return forwardElement(this.nextSibling);
2311 get previousElementSibling() {
2312 return backwardsElement(this.previousSibling);
2315 var NonElementParentNodeInterface = {
2316 getElementById: function(id) {
2317 if (/[ \t\n\r\f]/.test(id)) return null;
2318 return this.querySelector('[id="' + id + '"]');
2321 scope.ChildNodeInterface = ChildNodeInterface;
2322 scope.NonElementParentNodeInterface = NonElementParentNodeInterface;
2323 scope.ParentNodeInterface = ParentNodeInterface;
2324 })(window.ShadowDOMPolyfill);
2327 var ChildNodeInterface = scope.ChildNodeInterface;
2328 var Node = scope.wrappers.Node;
2329 var enqueueMutation = scope.enqueueMutation;
2330 var mixin = scope.mixin;
2331 var registerWrapper = scope.registerWrapper;
2332 var unsafeUnwrap = scope.unsafeUnwrap;
2333 var OriginalCharacterData = window.CharacterData;
2334 function CharacterData(node) {
2335 Node.call(this, node);
2337 CharacterData.prototype = Object.create(Node.prototype);
2338 mixin(CharacterData.prototype, {
2342 set nodeValue(data) {
2348 set textContent(value) {
2352 return unsafeUnwrap(this).data;
2355 var oldValue = unsafeUnwrap(this).data;
2356 enqueueMutation(this, "characterData", {
2359 unsafeUnwrap(this).data = value;
2362 mixin(CharacterData.prototype, ChildNodeInterface);
2363 registerWrapper(OriginalCharacterData, CharacterData, document.createTextNode(""));
2364 scope.wrappers.CharacterData = CharacterData;
2365 })(window.ShadowDOMPolyfill);
2368 var CharacterData = scope.wrappers.CharacterData;
2369 var enqueueMutation = scope.enqueueMutation;
2370 var mixin = scope.mixin;
2371 var registerWrapper = scope.registerWrapper;
2372 function toUInt32(x) {
2375 var OriginalText = window.Text;
2376 function Text(node) {
2377 CharacterData.call(this, node);
2379 Text.prototype = Object.create(CharacterData.prototype);
2380 mixin(Text.prototype, {
2381 splitText: function(offset) {
2382 offset = toUInt32(offset);
2384 if (offset > s.length) throw new Error("IndexSizeError");
2385 var head = s.slice(0, offset);
2386 var tail = s.slice(offset);
2388 var newTextNode = this.ownerDocument.createTextNode(tail);
2389 if (this.parentNode) this.parentNode.insertBefore(newTextNode, this.nextSibling);
2393 registerWrapper(OriginalText, Text, document.createTextNode(""));
2394 scope.wrappers.Text = Text;
2395 })(window.ShadowDOMPolyfill);
2398 if (!window.DOMTokenList) {
2399 console.warn("Missing DOMTokenList prototype, please include a " + "compatible classList polyfill such as http://goo.gl/uTcepH.");
2402 var unsafeUnwrap = scope.unsafeUnwrap;
2403 var enqueueMutation = scope.enqueueMutation;
2404 function getClass(el) {
2405 return unsafeUnwrap(el).getAttribute("class");
2407 function enqueueClassAttributeChange(el, oldValue) {
2408 enqueueMutation(el, "attributes", {
2414 function invalidateClass(el) {
2415 scope.invalidateRendererBasedOnAttribute(el, "class");
2417 function changeClass(tokenList, method, args) {
2418 var ownerElement = tokenList.ownerElement_;
2419 if (ownerElement == null) {
2420 return method.apply(tokenList, args);
2422 var oldValue = getClass(ownerElement);
2423 var retv = method.apply(tokenList, args);
2424 if (getClass(ownerElement) !== oldValue) {
2425 enqueueClassAttributeChange(ownerElement, oldValue);
2426 invalidateClass(ownerElement);
2430 var oldAdd = DOMTokenList.prototype.add;
2431 DOMTokenList.prototype.add = function() {
2432 changeClass(this, oldAdd, arguments);
2434 var oldRemove = DOMTokenList.prototype.remove;
2435 DOMTokenList.prototype.remove = function() {
2436 changeClass(this, oldRemove, arguments);
2438 var oldToggle = DOMTokenList.prototype.toggle;
2439 DOMTokenList.prototype.toggle = function() {
2440 return changeClass(this, oldToggle, arguments);
2442 })(window.ShadowDOMPolyfill);
2445 var ChildNodeInterface = scope.ChildNodeInterface;
2446 var GetElementsByInterface = scope.GetElementsByInterface;
2447 var Node = scope.wrappers.Node;
2448 var ParentNodeInterface = scope.ParentNodeInterface;
2449 var SelectorsInterface = scope.SelectorsInterface;
2450 var MatchesInterface = scope.MatchesInterface;
2451 var addWrapNodeListMethod = scope.addWrapNodeListMethod;
2452 var enqueueMutation = scope.enqueueMutation;
2453 var mixin = scope.mixin;
2454 var oneOf = scope.oneOf;
2455 var registerWrapper = scope.registerWrapper;
2456 var unsafeUnwrap = scope.unsafeUnwrap;
2457 var wrappers = scope.wrappers;
2458 var OriginalElement = window.Element;
2459 var matchesNames = [ "matches", "mozMatchesSelector", "msMatchesSelector", "webkitMatchesSelector" ].filter(function(name) {
2460 return OriginalElement.prototype[name];
2462 var matchesName = matchesNames[0];
2463 var originalMatches = OriginalElement.prototype[matchesName];
2464 function invalidateRendererBasedOnAttribute(element, name) {
2465 var p = element.parentNode;
2466 if (!p || !p.shadowRoot) return;
2467 var renderer = scope.getRendererForHost(p);
2468 if (renderer.dependsOnAttribute(name)) renderer.invalidate();
2470 function enqueAttributeChange(element, name, oldValue) {
2471 enqueueMutation(element, "attributes", {
2477 var classListTable = new WeakMap();
2478 function Element(node) {
2479 Node.call(this, node);
2481 Element.prototype = Object.create(Node.prototype);
2482 mixin(Element.prototype, {
2483 createShadowRoot: function() {
2484 var newShadowRoot = new wrappers.ShadowRoot(this);
2485 unsafeUnwrap(this).polymerShadowRoot_ = newShadowRoot;
2486 var renderer = scope.getRendererForHost(this);
2487 renderer.invalidate();
2488 return newShadowRoot;
2491 return unsafeUnwrap(this).polymerShadowRoot_ || null;
2493 setAttribute: function(name, value) {
2494 var oldValue = unsafeUnwrap(this).getAttribute(name);
2495 unsafeUnwrap(this).setAttribute(name, value);
2496 enqueAttributeChange(this, name, oldValue);
2497 invalidateRendererBasedOnAttribute(this, name);
2499 removeAttribute: function(name) {
2500 var oldValue = unsafeUnwrap(this).getAttribute(name);
2501 unsafeUnwrap(this).removeAttribute(name);
2502 enqueAttributeChange(this, name, oldValue);
2503 invalidateRendererBasedOnAttribute(this, name);
2506 var list = classListTable.get(this);
2508 list = unsafeUnwrap(this).classList;
2510 list.ownerElement_ = this;
2511 classListTable.set(this, list);
2516 return unsafeUnwrap(this).className;
2519 this.setAttribute("class", v);
2522 return unsafeUnwrap(this).id;
2525 this.setAttribute("id", v);
2528 matchesNames.forEach(function(name) {
2529 if (name !== "matches") {
2530 Element.prototype[name] = function(selector) {
2531 return this.matches(selector);
2535 if (OriginalElement.prototype.webkitCreateShadowRoot) {
2536 Element.prototype.webkitCreateShadowRoot = Element.prototype.createShadowRoot;
2538 mixin(Element.prototype, ChildNodeInterface);
2539 mixin(Element.prototype, GetElementsByInterface);
2540 mixin(Element.prototype, ParentNodeInterface);
2541 mixin(Element.prototype, SelectorsInterface);
2542 mixin(Element.prototype, MatchesInterface);
2543 registerWrapper(OriginalElement, Element, document.createElementNS(null, "x"));
2544 scope.invalidateRendererBasedOnAttribute = invalidateRendererBasedOnAttribute;
2545 scope.matchesNames = matchesNames;
2546 scope.originalMatches = originalMatches;
2547 scope.wrappers.Element = Element;
2548 })(window.ShadowDOMPolyfill);
2551 var Element = scope.wrappers.Element;
2552 var defineGetter = scope.defineGetter;
2553 var enqueueMutation = scope.enqueueMutation;
2554 var mixin = scope.mixin;
2555 var nodesWereAdded = scope.nodesWereAdded;
2556 var nodesWereRemoved = scope.nodesWereRemoved;
2557 var registerWrapper = scope.registerWrapper;
2558 var snapshotNodeList = scope.snapshotNodeList;
2559 var unsafeUnwrap = scope.unsafeUnwrap;
2560 var unwrap = scope.unwrap;
2561 var wrap = scope.wrap;
2562 var wrappers = scope.wrappers;
2563 var escapeAttrRegExp = /[&\u00A0"]/g;
2564 var escapeDataRegExp = /[&\u00A0<>]/g;
2565 function escapeReplace(c) {
2583 function escapeAttr(s) {
2584 return s.replace(escapeAttrRegExp, escapeReplace);
2586 function escapeData(s) {
2587 return s.replace(escapeDataRegExp, escapeReplace);
2589 function makeSet(arr) {
2591 for (var i = 0; i < arr.length; i++) {
2596 var voidElements = makeSet([ "area", "base", "br", "col", "command", "embed", "hr", "img", "input", "keygen", "link", "meta", "param", "source", "track", "wbr" ]);
2597 var plaintextParents = makeSet([ "style", "script", "xmp", "iframe", "noembed", "noframes", "plaintext", "noscript" ]);
2598 var XHTML_NS = "http://www.w3.org/1999/xhtml";
2599 function needsSelfClosingSlash(node) {
2600 if (node.namespaceURI !== XHTML_NS) return true;
2601 var doctype = node.ownerDocument.doctype;
2602 return doctype && doctype.publicId && doctype.systemId;
2604 function getOuterHTML(node, parentNode) {
2605 switch (node.nodeType) {
2606 case Node.ELEMENT_NODE:
2607 var tagName = node.tagName.toLowerCase();
2608 var s = "<" + tagName;
2609 var attrs = node.attributes;
2610 for (var i = 0, attr; attr = attrs[i]; i++) {
2611 s += " " + attr.name + '="' + escapeAttr(attr.value) + '"';
2613 if (voidElements[tagName]) {
2614 if (needsSelfClosingSlash(node)) s += "/";
2617 return s + ">" + getInnerHTML(node) + "</" + tagName + ">";
2619 case Node.TEXT_NODE:
2620 var data = node.data;
2621 if (parentNode && plaintextParents[parentNode.localName]) return data;
2622 return escapeData(data);
2624 case Node.COMMENT_NODE:
2625 return "<!--" + node.data + "-->";
2628 console.error(node);
2629 throw new Error("not implemented");
2632 function getInnerHTML(node) {
2633 if (node instanceof wrappers.HTMLTemplateElement) node = node.content;
2635 for (var child = node.firstChild; child; child = child.nextSibling) {
2636 s += getOuterHTML(child, node);
2640 function setInnerHTML(node, value, opt_tagName) {
2641 var tagName = opt_tagName || "div";
2642 node.textContent = "";
2643 var tempElement = unwrap(node.ownerDocument.createElement(tagName));
2644 tempElement.innerHTML = value;
2646 while (firstChild = tempElement.firstChild) {
2647 node.appendChild(wrap(firstChild));
2650 var oldIe = /MSIE/.test(navigator.userAgent);
2651 var OriginalHTMLElement = window.HTMLElement;
2652 var OriginalHTMLTemplateElement = window.HTMLTemplateElement;
2653 function HTMLElement(node) {
2654 Element.call(this, node);
2656 HTMLElement.prototype = Object.create(Element.prototype);
2657 mixin(HTMLElement.prototype, {
2659 return getInnerHTML(this);
2661 set innerHTML(value) {
2662 if (oldIe && plaintextParents[this.localName]) {
2663 this.textContent = value;
2666 var removedNodes = snapshotNodeList(this.childNodes);
2667 if (this.invalidateShadowRenderer()) {
2668 if (this instanceof wrappers.HTMLTemplateElement) setInnerHTML(this.content, value); else setInnerHTML(this, value, this.tagName);
2669 } else if (!OriginalHTMLTemplateElement && this instanceof wrappers.HTMLTemplateElement) {
2670 setInnerHTML(this.content, value);
2672 unsafeUnwrap(this).innerHTML = value;
2674 var addedNodes = snapshotNodeList(this.childNodes);
2675 enqueueMutation(this, "childList", {
2676 addedNodes: addedNodes,
2677 removedNodes: removedNodes
2679 nodesWereRemoved(removedNodes);
2680 nodesWereAdded(addedNodes, this);
2683 return getOuterHTML(this, this.parentNode);
2685 set outerHTML(value) {
2686 var p = this.parentNode;
2688 p.invalidateShadowRenderer();
2689 var df = frag(p, value);
2690 p.replaceChild(df, this);
2693 insertAdjacentHTML: function(position, text) {
2694 var contextElement, refNode;
2695 switch (String(position).toLowerCase()) {
2697 contextElement = this.parentNode;
2702 contextElement = this.parentNode;
2703 refNode = this.nextSibling;
2707 contextElement = this;
2708 refNode = this.firstChild;
2712 contextElement = this;
2719 var df = frag(contextElement, text);
2720 contextElement.insertBefore(df, refNode);
2723 return this.hasAttribute("hidden");
2727 this.setAttribute("hidden", "");
2729 this.removeAttribute("hidden");
2733 function frag(contextElement, html) {
2734 var p = unwrap(contextElement.cloneNode(false));
2736 var df = unwrap(document.createDocumentFragment());
2738 while (c = p.firstChild) {
2743 function getter(name) {
2745 scope.renderAllPending();
2746 return unsafeUnwrap(this)[name];
2749 function getterRequiresRendering(name) {
2750 defineGetter(HTMLElement, name, getter(name));
2752 [ "clientHeight", "clientLeft", "clientTop", "clientWidth", "offsetHeight", "offsetLeft", "offsetTop", "offsetWidth", "scrollHeight", "scrollWidth" ].forEach(getterRequiresRendering);
2753 function getterAndSetterRequiresRendering(name) {
2754 Object.defineProperty(HTMLElement.prototype, name, {
2757 scope.renderAllPending();
2758 unsafeUnwrap(this)[name] = v;
2764 [ "scrollLeft", "scrollTop" ].forEach(getterAndSetterRequiresRendering);
2765 function methodRequiresRendering(name) {
2766 Object.defineProperty(HTMLElement.prototype, name, {
2768 scope.renderAllPending();
2769 return unsafeUnwrap(this)[name].apply(unsafeUnwrap(this), arguments);
2775 [ "focus", "getBoundingClientRect", "getClientRects", "scrollIntoView" ].forEach(methodRequiresRendering);
2776 registerWrapper(OriginalHTMLElement, HTMLElement, document.createElement("b"));
2777 scope.wrappers.HTMLElement = HTMLElement;
2778 scope.getInnerHTML = getInnerHTML;
2779 scope.setInnerHTML = setInnerHTML;
2780 })(window.ShadowDOMPolyfill);
2783 var HTMLElement = scope.wrappers.HTMLElement;
2784 var mixin = scope.mixin;
2785 var registerWrapper = scope.registerWrapper;
2786 var unsafeUnwrap = scope.unsafeUnwrap;
2787 var wrap = scope.wrap;
2788 var OriginalHTMLCanvasElement = window.HTMLCanvasElement;
2789 function HTMLCanvasElement(node) {
2790 HTMLElement.call(this, node);
2792 HTMLCanvasElement.prototype = Object.create(HTMLElement.prototype);
2793 mixin(HTMLCanvasElement.prototype, {
2794 getContext: function() {
2795 var context = unsafeUnwrap(this).getContext.apply(unsafeUnwrap(this), arguments);
2796 return context && wrap(context);
2799 registerWrapper(OriginalHTMLCanvasElement, HTMLCanvasElement, document.createElement("canvas"));
2800 scope.wrappers.HTMLCanvasElement = HTMLCanvasElement;
2801 })(window.ShadowDOMPolyfill);
2804 var HTMLElement = scope.wrappers.HTMLElement;
2805 var mixin = scope.mixin;
2806 var registerWrapper = scope.registerWrapper;
2807 var OriginalHTMLContentElement = window.HTMLContentElement;
2808 function HTMLContentElement(node) {
2809 HTMLElement.call(this, node);
2811 HTMLContentElement.prototype = Object.create(HTMLElement.prototype);
2812 mixin(HTMLContentElement.prototype, {
2813 constructor: HTMLContentElement,
2815 return this.getAttribute("select");
2818 this.setAttribute("select", value);
2820 setAttribute: function(n, v) {
2821 HTMLElement.prototype.setAttribute.call(this, n, v);
2822 if (String(n).toLowerCase() === "select") this.invalidateShadowRenderer(true);
2825 if (OriginalHTMLContentElement) registerWrapper(OriginalHTMLContentElement, HTMLContentElement);
2826 scope.wrappers.HTMLContentElement = HTMLContentElement;
2827 })(window.ShadowDOMPolyfill);
2830 var HTMLElement = scope.wrappers.HTMLElement;
2831 var mixin = scope.mixin;
2832 var registerWrapper = scope.registerWrapper;
2833 var wrapHTMLCollection = scope.wrapHTMLCollection;
2834 var unwrap = scope.unwrap;
2835 var OriginalHTMLFormElement = window.HTMLFormElement;
2836 function HTMLFormElement(node) {
2837 HTMLElement.call(this, node);
2839 HTMLFormElement.prototype = Object.create(HTMLElement.prototype);
2840 mixin(HTMLFormElement.prototype, {
2842 return wrapHTMLCollection(unwrap(this).elements);
2845 registerWrapper(OriginalHTMLFormElement, HTMLFormElement, document.createElement("form"));
2846 scope.wrappers.HTMLFormElement = HTMLFormElement;
2847 })(window.ShadowDOMPolyfill);
2850 var HTMLElement = scope.wrappers.HTMLElement;
2851 var registerWrapper = scope.registerWrapper;
2852 var unwrap = scope.unwrap;
2853 var rewrap = scope.rewrap;
2854 var OriginalHTMLImageElement = window.HTMLImageElement;
2855 function HTMLImageElement(node) {
2856 HTMLElement.call(this, node);
2858 HTMLImageElement.prototype = Object.create(HTMLElement.prototype);
2859 registerWrapper(OriginalHTMLImageElement, HTMLImageElement, document.createElement("img"));
2860 function Image(width, height) {
2861 if (!(this instanceof Image)) {
2862 throw new TypeError("DOM object constructor cannot be called as a function.");
2864 var node = unwrap(document.createElement("img"));
2865 HTMLElement.call(this, node);
2867 if (width !== undefined) node.width = width;
2868 if (height !== undefined) node.height = height;
2870 Image.prototype = HTMLImageElement.prototype;
2871 scope.wrappers.HTMLImageElement = HTMLImageElement;
2872 scope.wrappers.Image = Image;
2873 })(window.ShadowDOMPolyfill);
2876 var HTMLElement = scope.wrappers.HTMLElement;
2877 var mixin = scope.mixin;
2878 var NodeList = scope.wrappers.NodeList;
2879 var registerWrapper = scope.registerWrapper;
2880 var OriginalHTMLShadowElement = window.HTMLShadowElement;
2881 function HTMLShadowElement(node) {
2882 HTMLElement.call(this, node);
2884 HTMLShadowElement.prototype = Object.create(HTMLElement.prototype);
2885 HTMLShadowElement.prototype.constructor = HTMLShadowElement;
2886 if (OriginalHTMLShadowElement) registerWrapper(OriginalHTMLShadowElement, HTMLShadowElement);
2887 scope.wrappers.HTMLShadowElement = HTMLShadowElement;
2888 })(window.ShadowDOMPolyfill);
2891 var HTMLElement = scope.wrappers.HTMLElement;
2892 var mixin = scope.mixin;
2893 var registerWrapper = scope.registerWrapper;
2894 var unsafeUnwrap = scope.unsafeUnwrap;
2895 var unwrap = scope.unwrap;
2896 var wrap = scope.wrap;
2897 var contentTable = new WeakMap();
2898 var templateContentsOwnerTable = new WeakMap();
2899 function getTemplateContentsOwner(doc) {
2900 if (!doc.defaultView) return doc;
2901 var d = templateContentsOwnerTable.get(doc);
2903 d = doc.implementation.createHTMLDocument("");
2904 while (d.lastChild) {
2905 d.removeChild(d.lastChild);
2907 templateContentsOwnerTable.set(doc, d);
2911 function extractContent(templateElement) {
2912 var doc = getTemplateContentsOwner(templateElement.ownerDocument);
2913 var df = unwrap(doc.createDocumentFragment());
2915 while (child = templateElement.firstChild) {
2916 df.appendChild(child);
2920 var OriginalHTMLTemplateElement = window.HTMLTemplateElement;
2921 function HTMLTemplateElement(node) {
2922 HTMLElement.call(this, node);
2923 if (!OriginalHTMLTemplateElement) {
2924 var content = extractContent(node);
2925 contentTable.set(this, wrap(content));
2928 HTMLTemplateElement.prototype = Object.create(HTMLElement.prototype);
2929 mixin(HTMLTemplateElement.prototype, {
2930 constructor: HTMLTemplateElement,
2932 if (OriginalHTMLTemplateElement) return wrap(unsafeUnwrap(this).content);
2933 return contentTable.get(this);
2936 if (OriginalHTMLTemplateElement) registerWrapper(OriginalHTMLTemplateElement, HTMLTemplateElement);
2937 scope.wrappers.HTMLTemplateElement = HTMLTemplateElement;
2938 })(window.ShadowDOMPolyfill);
2941 var HTMLElement = scope.wrappers.HTMLElement;
2942 var registerWrapper = scope.registerWrapper;
2943 var OriginalHTMLMediaElement = window.HTMLMediaElement;
2944 if (!OriginalHTMLMediaElement) return;
2945 function HTMLMediaElement(node) {
2946 HTMLElement.call(this, node);
2948 HTMLMediaElement.prototype = Object.create(HTMLElement.prototype);
2949 registerWrapper(OriginalHTMLMediaElement, HTMLMediaElement, document.createElement("audio"));
2950 scope.wrappers.HTMLMediaElement = HTMLMediaElement;
2951 })(window.ShadowDOMPolyfill);
2954 var HTMLMediaElement = scope.wrappers.HTMLMediaElement;
2955 var registerWrapper = scope.registerWrapper;
2956 var unwrap = scope.unwrap;
2957 var rewrap = scope.rewrap;
2958 var OriginalHTMLAudioElement = window.HTMLAudioElement;
2959 if (!OriginalHTMLAudioElement) return;
2960 function HTMLAudioElement(node) {
2961 HTMLMediaElement.call(this, node);
2963 HTMLAudioElement.prototype = Object.create(HTMLMediaElement.prototype);
2964 registerWrapper(OriginalHTMLAudioElement, HTMLAudioElement, document.createElement("audio"));
2965 function Audio(src) {
2966 if (!(this instanceof Audio)) {
2967 throw new TypeError("DOM object constructor cannot be called as a function.");
2969 var node = unwrap(document.createElement("audio"));
2970 HTMLMediaElement.call(this, node);
2972 node.setAttribute("preload", "auto");
2973 if (src !== undefined) node.setAttribute("src", src);
2975 Audio.prototype = HTMLAudioElement.prototype;
2976 scope.wrappers.HTMLAudioElement = HTMLAudioElement;
2977 scope.wrappers.Audio = Audio;
2978 })(window.ShadowDOMPolyfill);
2981 var HTMLElement = scope.wrappers.HTMLElement;
2982 var mixin = scope.mixin;
2983 var registerWrapper = scope.registerWrapper;
2984 var rewrap = scope.rewrap;
2985 var unwrap = scope.unwrap;
2986 var wrap = scope.wrap;
2987 var OriginalHTMLOptionElement = window.HTMLOptionElement;
2988 function trimText(s) {
2989 return s.replace(/\s+/g, " ").trim();
2991 function HTMLOptionElement(node) {
2992 HTMLElement.call(this, node);
2994 HTMLOptionElement.prototype = Object.create(HTMLElement.prototype);
2995 mixin(HTMLOptionElement.prototype, {
2997 return trimText(this.textContent);
3000 this.textContent = trimText(String(value));
3003 return wrap(unwrap(this).form);
3006 registerWrapper(OriginalHTMLOptionElement, HTMLOptionElement, document.createElement("option"));
3007 function Option(text, value, defaultSelected, selected) {
3008 if (!(this instanceof Option)) {
3009 throw new TypeError("DOM object constructor cannot be called as a function.");
3011 var node = unwrap(document.createElement("option"));
3012 HTMLElement.call(this, node);
3014 if (text !== undefined) node.text = text;
3015 if (value !== undefined) node.setAttribute("value", value);
3016 if (defaultSelected === true) node.setAttribute("selected", "");
3017 node.selected = selected === true;
3019 Option.prototype = HTMLOptionElement.prototype;
3020 scope.wrappers.HTMLOptionElement = HTMLOptionElement;
3021 scope.wrappers.Option = Option;
3022 })(window.ShadowDOMPolyfill);
3025 var HTMLElement = scope.wrappers.HTMLElement;
3026 var mixin = scope.mixin;
3027 var registerWrapper = scope.registerWrapper;
3028 var unwrap = scope.unwrap;
3029 var wrap = scope.wrap;
3030 var OriginalHTMLSelectElement = window.HTMLSelectElement;
3031 function HTMLSelectElement(node) {
3032 HTMLElement.call(this, node);
3034 HTMLSelectElement.prototype = Object.create(HTMLElement.prototype);
3035 mixin(HTMLSelectElement.prototype, {
3036 add: function(element, before) {
3037 if (typeof before === "object") before = unwrap(before);
3038 unwrap(this).add(unwrap(element), before);
3040 remove: function(indexOrNode) {
3041 if (indexOrNode === undefined) {
3042 HTMLElement.prototype.remove.call(this);
3045 if (typeof indexOrNode === "object") indexOrNode = unwrap(indexOrNode);
3046 unwrap(this).remove(indexOrNode);
3049 return wrap(unwrap(this).form);
3052 registerWrapper(OriginalHTMLSelectElement, HTMLSelectElement, document.createElement("select"));
3053 scope.wrappers.HTMLSelectElement = HTMLSelectElement;
3054 })(window.ShadowDOMPolyfill);
3057 var HTMLElement = scope.wrappers.HTMLElement;
3058 var mixin = scope.mixin;
3059 var registerWrapper = scope.registerWrapper;
3060 var unwrap = scope.unwrap;
3061 var wrap = scope.wrap;
3062 var wrapHTMLCollection = scope.wrapHTMLCollection;
3063 var OriginalHTMLTableElement = window.HTMLTableElement;
3064 function HTMLTableElement(node) {
3065 HTMLElement.call(this, node);
3067 HTMLTableElement.prototype = Object.create(HTMLElement.prototype);
3068 mixin(HTMLTableElement.prototype, {
3070 return wrap(unwrap(this).caption);
3072 createCaption: function() {
3073 return wrap(unwrap(this).createCaption());
3076 return wrap(unwrap(this).tHead);
3078 createTHead: function() {
3079 return wrap(unwrap(this).createTHead());
3081 createTFoot: function() {
3082 return wrap(unwrap(this).createTFoot());
3085 return wrap(unwrap(this).tFoot);
3088 return wrapHTMLCollection(unwrap(this).tBodies);
3090 createTBody: function() {
3091 return wrap(unwrap(this).createTBody());
3094 return wrapHTMLCollection(unwrap(this).rows);
3096 insertRow: function(index) {
3097 return wrap(unwrap(this).insertRow(index));
3100 registerWrapper(OriginalHTMLTableElement, HTMLTableElement, document.createElement("table"));
3101 scope.wrappers.HTMLTableElement = HTMLTableElement;
3102 })(window.ShadowDOMPolyfill);
3105 var HTMLElement = scope.wrappers.HTMLElement;
3106 var mixin = scope.mixin;
3107 var registerWrapper = scope.registerWrapper;
3108 var wrapHTMLCollection = scope.wrapHTMLCollection;
3109 var unwrap = scope.unwrap;
3110 var wrap = scope.wrap;
3111 var OriginalHTMLTableSectionElement = window.HTMLTableSectionElement;
3112 function HTMLTableSectionElement(node) {
3113 HTMLElement.call(this, node);
3115 HTMLTableSectionElement.prototype = Object.create(HTMLElement.prototype);
3116 mixin(HTMLTableSectionElement.prototype, {
3117 constructor: HTMLTableSectionElement,
3119 return wrapHTMLCollection(unwrap(this).rows);
3121 insertRow: function(index) {
3122 return wrap(unwrap(this).insertRow(index));
3125 registerWrapper(OriginalHTMLTableSectionElement, HTMLTableSectionElement, document.createElement("thead"));
3126 scope.wrappers.HTMLTableSectionElement = HTMLTableSectionElement;
3127 })(window.ShadowDOMPolyfill);
3130 var HTMLElement = scope.wrappers.HTMLElement;
3131 var mixin = scope.mixin;
3132 var registerWrapper = scope.registerWrapper;
3133 var wrapHTMLCollection = scope.wrapHTMLCollection;
3134 var unwrap = scope.unwrap;
3135 var wrap = scope.wrap;
3136 var OriginalHTMLTableRowElement = window.HTMLTableRowElement;
3137 function HTMLTableRowElement(node) {
3138 HTMLElement.call(this, node);
3140 HTMLTableRowElement.prototype = Object.create(HTMLElement.prototype);
3141 mixin(HTMLTableRowElement.prototype, {
3143 return wrapHTMLCollection(unwrap(this).cells);
3145 insertCell: function(index) {
3146 return wrap(unwrap(this).insertCell(index));
3149 registerWrapper(OriginalHTMLTableRowElement, HTMLTableRowElement, document.createElement("tr"));
3150 scope.wrappers.HTMLTableRowElement = HTMLTableRowElement;
3151 })(window.ShadowDOMPolyfill);
3154 var HTMLContentElement = scope.wrappers.HTMLContentElement;
3155 var HTMLElement = scope.wrappers.HTMLElement;
3156 var HTMLShadowElement = scope.wrappers.HTMLShadowElement;
3157 var HTMLTemplateElement = scope.wrappers.HTMLTemplateElement;
3158 var mixin = scope.mixin;
3159 var registerWrapper = scope.registerWrapper;
3160 var OriginalHTMLUnknownElement = window.HTMLUnknownElement;
3161 function HTMLUnknownElement(node) {
3162 switch (node.localName) {
3164 return new HTMLContentElement(node);
3167 return new HTMLShadowElement(node);
3170 return new HTMLTemplateElement(node);
3172 HTMLElement.call(this, node);
3174 HTMLUnknownElement.prototype = Object.create(HTMLElement.prototype);
3175 registerWrapper(OriginalHTMLUnknownElement, HTMLUnknownElement);
3176 scope.wrappers.HTMLUnknownElement = HTMLUnknownElement;
3177 })(window.ShadowDOMPolyfill);
3180 var Element = scope.wrappers.Element;
3181 var HTMLElement = scope.wrappers.HTMLElement;
3182 var registerWrapper = scope.registerWrapper;
3183 var defineWrapGetter = scope.defineWrapGetter;
3184 var unsafeUnwrap = scope.unsafeUnwrap;
3185 var wrap = scope.wrap;
3186 var mixin = scope.mixin;
3187 var SVG_NS = "http://www.w3.org/2000/svg";
3188 var OriginalSVGElement = window.SVGElement;
3189 var svgTitleElement = document.createElementNS(SVG_NS, "title");
3190 if (!("classList" in svgTitleElement)) {
3191 var descr = Object.getOwnPropertyDescriptor(Element.prototype, "classList");
3192 Object.defineProperty(HTMLElement.prototype, "classList", descr);
3193 delete Element.prototype.classList;
3195 function SVGElement(node) {
3196 Element.call(this, node);
3198 SVGElement.prototype = Object.create(Element.prototype);
3199 mixin(SVGElement.prototype, {
3200 get ownerSVGElement() {
3201 return wrap(unsafeUnwrap(this).ownerSVGElement);
3204 registerWrapper(OriginalSVGElement, SVGElement, document.createElementNS(SVG_NS, "title"));
3205 scope.wrappers.SVGElement = SVGElement;
3206 })(window.ShadowDOMPolyfill);
3209 var mixin = scope.mixin;
3210 var registerWrapper = scope.registerWrapper;
3211 var unwrap = scope.unwrap;
3212 var wrap = scope.wrap;
3213 var OriginalSVGUseElement = window.SVGUseElement;
3214 var SVG_NS = "http://www.w3.org/2000/svg";
3215 var gWrapper = wrap(document.createElementNS(SVG_NS, "g"));
3216 var useElement = document.createElementNS(SVG_NS, "use");
3217 var SVGGElement = gWrapper.constructor;
3218 var parentInterfacePrototype = Object.getPrototypeOf(SVGGElement.prototype);
3219 var parentInterface = parentInterfacePrototype.constructor;
3220 function SVGUseElement(impl) {
3221 parentInterface.call(this, impl);
3223 SVGUseElement.prototype = Object.create(parentInterfacePrototype);
3224 if ("instanceRoot" in useElement) {
3225 mixin(SVGUseElement.prototype, {
3226 get instanceRoot() {
3227 return wrap(unwrap(this).instanceRoot);
3229 get animatedInstanceRoot() {
3230 return wrap(unwrap(this).animatedInstanceRoot);
3234 registerWrapper(OriginalSVGUseElement, SVGUseElement, useElement);
3235 scope.wrappers.SVGUseElement = SVGUseElement;
3236 })(window.ShadowDOMPolyfill);
3239 var EventTarget = scope.wrappers.EventTarget;
3240 var mixin = scope.mixin;
3241 var registerWrapper = scope.registerWrapper;
3242 var unsafeUnwrap = scope.unsafeUnwrap;
3243 var wrap = scope.wrap;
3244 var OriginalSVGElementInstance = window.SVGElementInstance;
3245 if (!OriginalSVGElementInstance) return;
3246 function SVGElementInstance(impl) {
3247 EventTarget.call(this, impl);
3249 SVGElementInstance.prototype = Object.create(EventTarget.prototype);
3250 mixin(SVGElementInstance.prototype, {
3251 get correspondingElement() {
3252 return wrap(unsafeUnwrap(this).correspondingElement);
3254 get correspondingUseElement() {
3255 return wrap(unsafeUnwrap(this).correspondingUseElement);
3258 return wrap(unsafeUnwrap(this).parentNode);
3261 throw new Error("Not implemented");
3264 return wrap(unsafeUnwrap(this).firstChild);
3267 return wrap(unsafeUnwrap(this).lastChild);
3269 get previousSibling() {
3270 return wrap(unsafeUnwrap(this).previousSibling);
3273 return wrap(unsafeUnwrap(this).nextSibling);
3276 registerWrapper(OriginalSVGElementInstance, SVGElementInstance);
3277 scope.wrappers.SVGElementInstance = SVGElementInstance;
3278 })(window.ShadowDOMPolyfill);
3281 var mixin = scope.mixin;
3282 var registerWrapper = scope.registerWrapper;
3283 var setWrapper = scope.setWrapper;
3284 var unsafeUnwrap = scope.unsafeUnwrap;
3285 var unwrap = scope.unwrap;
3286 var unwrapIfNeeded = scope.unwrapIfNeeded;
3287 var wrap = scope.wrap;
3288 var OriginalCanvasRenderingContext2D = window.CanvasRenderingContext2D;
3289 function CanvasRenderingContext2D(impl) {
3290 setWrapper(impl, this);
3292 mixin(CanvasRenderingContext2D.prototype, {
3294 return wrap(unsafeUnwrap(this).canvas);
3296 drawImage: function() {
3297 arguments[0] = unwrapIfNeeded(arguments[0]);
3298 unsafeUnwrap(this).drawImage.apply(unsafeUnwrap(this), arguments);
3300 createPattern: function() {
3301 arguments[0] = unwrap(arguments[0]);
3302 return unsafeUnwrap(this).createPattern.apply(unsafeUnwrap(this), arguments);
3305 registerWrapper(OriginalCanvasRenderingContext2D, CanvasRenderingContext2D, document.createElement("canvas").getContext("2d"));
3306 scope.wrappers.CanvasRenderingContext2D = CanvasRenderingContext2D;
3307 })(window.ShadowDOMPolyfill);
3310 var addForwardingProperties = scope.addForwardingProperties;
3311 var mixin = scope.mixin;
3312 var registerWrapper = scope.registerWrapper;
3313 var setWrapper = scope.setWrapper;
3314 var unsafeUnwrap = scope.unsafeUnwrap;
3315 var unwrapIfNeeded = scope.unwrapIfNeeded;
3316 var wrap = scope.wrap;
3317 var OriginalWebGLRenderingContext = window.WebGLRenderingContext;
3318 if (!OriginalWebGLRenderingContext) return;
3319 function WebGLRenderingContext(impl) {
3320 setWrapper(impl, this);
3322 mixin(WebGLRenderingContext.prototype, {
3324 return wrap(unsafeUnwrap(this).canvas);
3326 texImage2D: function() {
3327 arguments[5] = unwrapIfNeeded(arguments[5]);
3328 unsafeUnwrap(this).texImage2D.apply(unsafeUnwrap(this), arguments);
3330 texSubImage2D: function() {
3331 arguments[6] = unwrapIfNeeded(arguments[6]);
3332 unsafeUnwrap(this).texSubImage2D.apply(unsafeUnwrap(this), arguments);
3335 var OriginalWebGLRenderingContextBase = Object.getPrototypeOf(OriginalWebGLRenderingContext.prototype);
3336 if (OriginalWebGLRenderingContextBase !== Object.prototype) {
3337 addForwardingProperties(OriginalWebGLRenderingContextBase, WebGLRenderingContext.prototype);
3339 var instanceProperties = /WebKit/.test(navigator.userAgent) ? {
3340 drawingBufferHeight: null,
3341 drawingBufferWidth: null
3343 registerWrapper(OriginalWebGLRenderingContext, WebGLRenderingContext, instanceProperties);
3344 scope.wrappers.WebGLRenderingContext = WebGLRenderingContext;
3345 })(window.ShadowDOMPolyfill);
3348 var Node = scope.wrappers.Node;
3349 var GetElementsByInterface = scope.GetElementsByInterface;
3350 var NonElementParentNodeInterface = scope.NonElementParentNodeInterface;
3351 var ParentNodeInterface = scope.ParentNodeInterface;
3352 var SelectorsInterface = scope.SelectorsInterface;
3353 var mixin = scope.mixin;
3354 var registerObject = scope.registerObject;
3355 var registerWrapper = scope.registerWrapper;
3356 var OriginalDocumentFragment = window.DocumentFragment;
3357 function DocumentFragment(node) {
3358 Node.call(this, node);
3360 DocumentFragment.prototype = Object.create(Node.prototype);
3361 mixin(DocumentFragment.prototype, ParentNodeInterface);
3362 mixin(DocumentFragment.prototype, SelectorsInterface);
3363 mixin(DocumentFragment.prototype, GetElementsByInterface);
3364 mixin(DocumentFragment.prototype, NonElementParentNodeInterface);
3365 registerWrapper(OriginalDocumentFragment, DocumentFragment, document.createDocumentFragment());
3366 scope.wrappers.DocumentFragment = DocumentFragment;
3367 var Comment = registerObject(document.createComment(""));
3368 scope.wrappers.Comment = Comment;
3369 })(window.ShadowDOMPolyfill);
3372 var DocumentFragment = scope.wrappers.DocumentFragment;
3373 var TreeScope = scope.TreeScope;
3374 var elementFromPoint = scope.elementFromPoint;
3375 var getInnerHTML = scope.getInnerHTML;
3376 var getTreeScope = scope.getTreeScope;
3377 var mixin = scope.mixin;
3378 var rewrap = scope.rewrap;
3379 var setInnerHTML = scope.setInnerHTML;
3380 var unsafeUnwrap = scope.unsafeUnwrap;
3381 var unwrap = scope.unwrap;
3382 var wrap = scope.wrap;
3383 var shadowHostTable = new WeakMap();
3384 var nextOlderShadowTreeTable = new WeakMap();
3385 function ShadowRoot(hostWrapper) {
3386 var node = unwrap(unsafeUnwrap(hostWrapper).ownerDocument.createDocumentFragment());
3387 DocumentFragment.call(this, node);
3389 var oldShadowRoot = hostWrapper.shadowRoot;
3390 nextOlderShadowTreeTable.set(this, oldShadowRoot);
3391 this.treeScope_ = new TreeScope(this, getTreeScope(oldShadowRoot || hostWrapper));
3392 shadowHostTable.set(this, hostWrapper);
3394 ShadowRoot.prototype = Object.create(DocumentFragment.prototype);
3395 mixin(ShadowRoot.prototype, {
3396 constructor: ShadowRoot,
3398 return getInnerHTML(this);
3400 set innerHTML(value) {
3401 setInnerHTML(this, value);
3402 this.invalidateShadowRenderer();
3404 get olderShadowRoot() {
3405 return nextOlderShadowTreeTable.get(this) || null;
3408 return shadowHostTable.get(this) || null;
3410 invalidateShadowRenderer: function() {
3411 return shadowHostTable.get(this).invalidateShadowRenderer();
3413 elementFromPoint: function(x, y) {
3414 return elementFromPoint(this, this.ownerDocument, x, y);
3416 getSelection: function() {
3417 return document.getSelection();
3419 get activeElement() {
3420 var unwrappedActiveElement = unwrap(this).ownerDocument.activeElement;
3421 if (!unwrappedActiveElement || !unwrappedActiveElement.nodeType) return null;
3422 var activeElement = wrap(unwrappedActiveElement);
3423 if (activeElement === this.host) {
3426 while (!this.contains(activeElement) && !this.host.contains(activeElement)) {
3427 while (activeElement.parentNode) {
3428 activeElement = activeElement.parentNode;
3430 if (activeElement.host) {
3431 activeElement = activeElement.host;
3436 return activeElement;
3439 scope.wrappers.ShadowRoot = ShadowRoot;
3440 })(window.ShadowDOMPolyfill);
3443 var registerWrapper = scope.registerWrapper;
3444 var setWrapper = scope.setWrapper;
3445 var unsafeUnwrap = scope.unsafeUnwrap;
3446 var unwrap = scope.unwrap;
3447 var unwrapIfNeeded = scope.unwrapIfNeeded;
3448 var wrap = scope.wrap;
3449 var getTreeScope = scope.getTreeScope;
3450 var OriginalRange = window.Range;
3451 var ShadowRoot = scope.wrappers.ShadowRoot;
3452 function getHost(node) {
3453 var root = getTreeScope(node).root;
3454 if (root instanceof ShadowRoot) {
3459 function hostNodeToShadowNode(refNode, offset) {
3460 if (refNode.shadowRoot) {
3461 offset = Math.min(refNode.childNodes.length - 1, offset);
3462 var child = refNode.childNodes[offset];
3464 var insertionPoint = scope.getDestinationInsertionPoints(child);
3465 if (insertionPoint.length > 0) {
3466 var parentNode = insertionPoint[0].parentNode;
3467 if (parentNode.nodeType == Node.ELEMENT_NODE) {
3468 refNode = parentNode;
3475 function shadowNodeToHostNode(node) {
3477 return getHost(node) || node;
3479 function Range(impl) {
3480 setWrapper(impl, this);
3483 get startContainer() {
3484 return shadowNodeToHostNode(unsafeUnwrap(this).startContainer);
3486 get endContainer() {
3487 return shadowNodeToHostNode(unsafeUnwrap(this).endContainer);
3489 get commonAncestorContainer() {
3490 return shadowNodeToHostNode(unsafeUnwrap(this).commonAncestorContainer);
3492 setStart: function(refNode, offset) {
3493 refNode = hostNodeToShadowNode(refNode, offset);
3494 unsafeUnwrap(this).setStart(unwrapIfNeeded(refNode), offset);
3496 setEnd: function(refNode, offset) {
3497 refNode = hostNodeToShadowNode(refNode, offset);
3498 unsafeUnwrap(this).setEnd(unwrapIfNeeded(refNode), offset);
3500 setStartBefore: function(refNode) {
3501 unsafeUnwrap(this).setStartBefore(unwrapIfNeeded(refNode));
3503 setStartAfter: function(refNode) {
3504 unsafeUnwrap(this).setStartAfter(unwrapIfNeeded(refNode));
3506 setEndBefore: function(refNode) {
3507 unsafeUnwrap(this).setEndBefore(unwrapIfNeeded(refNode));
3509 setEndAfter: function(refNode) {
3510 unsafeUnwrap(this).setEndAfter(unwrapIfNeeded(refNode));
3512 selectNode: function(refNode) {
3513 unsafeUnwrap(this).selectNode(unwrapIfNeeded(refNode));
3515 selectNodeContents: function(refNode) {
3516 unsafeUnwrap(this).selectNodeContents(unwrapIfNeeded(refNode));
3518 compareBoundaryPoints: function(how, sourceRange) {
3519 return unsafeUnwrap(this).compareBoundaryPoints(how, unwrap(sourceRange));
3521 extractContents: function() {
3522 return wrap(unsafeUnwrap(this).extractContents());
3524 cloneContents: function() {
3525 return wrap(unsafeUnwrap(this).cloneContents());
3527 insertNode: function(node) {
3528 unsafeUnwrap(this).insertNode(unwrapIfNeeded(node));
3530 surroundContents: function(newParent) {
3531 unsafeUnwrap(this).surroundContents(unwrapIfNeeded(newParent));
3533 cloneRange: function() {
3534 return wrap(unsafeUnwrap(this).cloneRange());
3536 isPointInRange: function(node, offset) {
3537 return unsafeUnwrap(this).isPointInRange(unwrapIfNeeded(node), offset);
3539 comparePoint: function(node, offset) {
3540 return unsafeUnwrap(this).comparePoint(unwrapIfNeeded(node), offset);
3542 intersectsNode: function(node) {
3543 return unsafeUnwrap(this).intersectsNode(unwrapIfNeeded(node));
3545 toString: function() {
3546 return unsafeUnwrap(this).toString();
3549 if (OriginalRange.prototype.createContextualFragment) {
3550 Range.prototype.createContextualFragment = function(html) {
3551 return wrap(unsafeUnwrap(this).createContextualFragment(html));
3554 registerWrapper(window.Range, Range, document.createRange());
3555 scope.wrappers.Range = Range;
3556 })(window.ShadowDOMPolyfill);
3559 var Element = scope.wrappers.Element;
3560 var HTMLContentElement = scope.wrappers.HTMLContentElement;
3561 var HTMLShadowElement = scope.wrappers.HTMLShadowElement;
3562 var Node = scope.wrappers.Node;
3563 var ShadowRoot = scope.wrappers.ShadowRoot;
3564 var assert = scope.assert;
3565 var getTreeScope = scope.getTreeScope;
3566 var mixin = scope.mixin;
3567 var oneOf = scope.oneOf;
3568 var unsafeUnwrap = scope.unsafeUnwrap;
3569 var unwrap = scope.unwrap;
3570 var wrap = scope.wrap;
3571 var ArraySplice = scope.ArraySplice;
3572 function updateWrapperUpAndSideways(wrapper) {
3573 wrapper.previousSibling_ = wrapper.previousSibling;
3574 wrapper.nextSibling_ = wrapper.nextSibling;
3575 wrapper.parentNode_ = wrapper.parentNode;
3577 function updateWrapperDown(wrapper) {
3578 wrapper.firstChild_ = wrapper.firstChild;
3579 wrapper.lastChild_ = wrapper.lastChild;
3581 function updateAllChildNodes(parentNodeWrapper) {
3582 assert(parentNodeWrapper instanceof Node);
3583 for (var childWrapper = parentNodeWrapper.firstChild; childWrapper; childWrapper = childWrapper.nextSibling) {
3584 updateWrapperUpAndSideways(childWrapper);
3586 updateWrapperDown(parentNodeWrapper);
3588 function insertBefore(parentNodeWrapper, newChildWrapper, refChildWrapper) {
3589 var parentNode = unwrap(parentNodeWrapper);
3590 var newChild = unwrap(newChildWrapper);
3591 var refChild = refChildWrapper ? unwrap(refChildWrapper) : null;
3592 remove(newChildWrapper);
3593 updateWrapperUpAndSideways(newChildWrapper);
3594 if (!refChildWrapper) {
3595 parentNodeWrapper.lastChild_ = parentNodeWrapper.lastChild;
3596 if (parentNodeWrapper.lastChild === parentNodeWrapper.firstChild) parentNodeWrapper.firstChild_ = parentNodeWrapper.firstChild;
3597 var lastChildWrapper = wrap(parentNode.lastChild);
3598 if (lastChildWrapper) lastChildWrapper.nextSibling_ = lastChildWrapper.nextSibling;
3600 if (parentNodeWrapper.firstChild === refChildWrapper) parentNodeWrapper.firstChild_ = refChildWrapper;
3601 refChildWrapper.previousSibling_ = refChildWrapper.previousSibling;
3603 scope.originalInsertBefore.call(parentNode, newChild, refChild);
3605 function remove(nodeWrapper) {
3606 var node = unwrap(nodeWrapper);
3607 var parentNode = node.parentNode;
3608 if (!parentNode) return;
3609 var parentNodeWrapper = wrap(parentNode);
3610 updateWrapperUpAndSideways(nodeWrapper);
3611 if (nodeWrapper.previousSibling) nodeWrapper.previousSibling.nextSibling_ = nodeWrapper;
3612 if (nodeWrapper.nextSibling) nodeWrapper.nextSibling.previousSibling_ = nodeWrapper;
3613 if (parentNodeWrapper.lastChild === nodeWrapper) parentNodeWrapper.lastChild_ = nodeWrapper;
3614 if (parentNodeWrapper.firstChild === nodeWrapper) parentNodeWrapper.firstChild_ = nodeWrapper;
3615 scope.originalRemoveChild.call(parentNode, node);
3617 var distributedNodesTable = new WeakMap();
3618 var destinationInsertionPointsTable = new WeakMap();
3619 var rendererForHostTable = new WeakMap();
3620 function resetDistributedNodes(insertionPoint) {
3621 distributedNodesTable.set(insertionPoint, []);
3623 function getDistributedNodes(insertionPoint) {
3624 var rv = distributedNodesTable.get(insertionPoint);
3625 if (!rv) distributedNodesTable.set(insertionPoint, rv = []);
3628 function getChildNodesSnapshot(node) {
3629 var result = [], i = 0;
3630 for (var child = node.firstChild; child; child = child.nextSibling) {
3631 result[i++] = child;
3635 var request = oneOf(window, [ "requestAnimationFrame", "mozRequestAnimationFrame", "webkitRequestAnimationFrame", "setTimeout" ]);
3636 var pendingDirtyRenderers = [];
3638 function renderAllPending() {
3639 for (var i = 0; i < pendingDirtyRenderers.length; i++) {
3640 var renderer = pendingDirtyRenderers[i];
3641 var parentRenderer = renderer.parentRenderer;
3642 if (parentRenderer && parentRenderer.dirty) continue;
3645 pendingDirtyRenderers = [];
3647 function handleRequestAnimationFrame() {
3651 function getRendererForHost(host) {
3652 var renderer = rendererForHostTable.get(host);
3654 renderer = new ShadowRenderer(host);
3655 rendererForHostTable.set(host, renderer);
3659 function getShadowRootAncestor(node) {
3660 var root = getTreeScope(node).root;
3661 if (root instanceof ShadowRoot) return root;
3664 function getRendererForShadowRoot(shadowRoot) {
3665 return getRendererForHost(shadowRoot.host);
3667 var spliceDiff = new ArraySplice();
3668 spliceDiff.equals = function(renderNode, rawNode) {
3669 return unwrap(renderNode.node) === rawNode;
3671 function RenderNode(node) {
3674 this.childNodes = [];
3676 RenderNode.prototype = {
3677 append: function(node) {
3678 var rv = new RenderNode(node);
3679 this.childNodes.push(rv);
3682 sync: function(opt_added) {
3683 if (this.skip) return;
3684 var nodeWrapper = this.node;
3685 var newChildren = this.childNodes;
3686 var oldChildren = getChildNodesSnapshot(unwrap(nodeWrapper));
3687 var added = opt_added || new WeakMap();
3688 var splices = spliceDiff.calculateSplices(newChildren, oldChildren);
3689 var newIndex = 0, oldIndex = 0;
3691 for (var i = 0; i < splices.length; i++) {
3692 var splice = splices[i];
3693 for (;lastIndex < splice.index; lastIndex++) {
3695 newChildren[newIndex++].sync(added);
3697 var removedCount = splice.removed.length;
3698 for (var j = 0; j < removedCount; j++) {
3699 var wrapper = wrap(oldChildren[oldIndex++]);
3700 if (!added.get(wrapper)) remove(wrapper);
3702 var addedCount = splice.addedCount;
3703 var refNode = oldChildren[oldIndex] && wrap(oldChildren[oldIndex]);
3704 for (var j = 0; j < addedCount; j++) {
3705 var newChildRenderNode = newChildren[newIndex++];
3706 var newChildWrapper = newChildRenderNode.node;
3707 insertBefore(nodeWrapper, newChildWrapper, refNode);
3708 added.set(newChildWrapper, true);
3709 newChildRenderNode.sync(added);
3711 lastIndex += addedCount;
3713 for (var i = lastIndex; i < newChildren.length; i++) {
3714 newChildren[i].sync(added);
3718 function ShadowRenderer(host) {
3721 this.invalidateAttributes();
3722 this.associateNode(host);
3724 ShadowRenderer.prototype = {
3725 render: function(opt_renderNode) {
3726 if (!this.dirty) return;
3727 this.invalidateAttributes();
3728 var host = this.host;
3729 this.distribution(host);
3730 var renderNode = opt_renderNode || new RenderNode(host);
3731 this.buildRenderTree(renderNode, host);
3732 var topMostRenderer = !opt_renderNode;
3733 if (topMostRenderer) renderNode.sync();
3736 get parentRenderer() {
3737 return getTreeScope(this.host).renderer;
3739 invalidate: function() {
3742 var parentRenderer = this.parentRenderer;
3743 if (parentRenderer) parentRenderer.invalidate();
3744 pendingDirtyRenderers.push(this);
3745 if (renderTimer) return;
3746 renderTimer = window[request](handleRequestAnimationFrame, 0);
3749 distribution: function(root) {
3750 this.resetAllSubtrees(root);
3751 this.distributionResolution(root);
3753 resetAll: function(node) {
3754 if (isInsertionPoint(node)) resetDistributedNodes(node); else resetDestinationInsertionPoints(node);
3755 this.resetAllSubtrees(node);
3757 resetAllSubtrees: function(node) {
3758 for (var child = node.firstChild; child; child = child.nextSibling) {
3759 this.resetAll(child);
3761 if (node.shadowRoot) this.resetAll(node.shadowRoot);
3762 if (node.olderShadowRoot) this.resetAll(node.olderShadowRoot);
3764 distributionResolution: function(node) {
3765 if (isShadowHost(node)) {
3766 var shadowHost = node;
3767 var pool = poolPopulation(shadowHost);
3768 var shadowTrees = getShadowTrees(shadowHost);
3769 for (var i = 0; i < shadowTrees.length; i++) {
3770 this.poolDistribution(shadowTrees[i], pool);
3772 for (var i = shadowTrees.length - 1; i >= 0; i--) {
3773 var shadowTree = shadowTrees[i];
3774 var shadow = getShadowInsertionPoint(shadowTree);
3776 var olderShadowRoot = shadowTree.olderShadowRoot;
3777 if (olderShadowRoot) {
3778 pool = poolPopulation(olderShadowRoot);
3780 for (var j = 0; j < pool.length; j++) {
3781 destributeNodeInto(pool[j], shadow);
3784 this.distributionResolution(shadowTree);
3787 for (var child = node.firstChild; child; child = child.nextSibling) {
3788 this.distributionResolution(child);
3791 poolDistribution: function(node, pool) {
3792 if (node instanceof HTMLShadowElement) return;
3793 if (node instanceof HTMLContentElement) {
3795 this.updateDependentAttributes(content.getAttribute("select"));
3796 var anyDistributed = false;
3797 for (var i = 0; i < pool.length; i++) {
3799 if (!node) continue;
3800 if (matches(node, content)) {
3801 destributeNodeInto(node, content);
3802 pool[i] = undefined;
3803 anyDistributed = true;
3806 if (!anyDistributed) {
3807 for (var child = content.firstChild; child; child = child.nextSibling) {
3808 destributeNodeInto(child, content);
3813 for (var child = node.firstChild; child; child = child.nextSibling) {
3814 this.poolDistribution(child, pool);
3817 buildRenderTree: function(renderNode, node) {
3818 var children = this.compose(node);
3819 for (var i = 0; i < children.length; i++) {
3820 var child = children[i];
3821 var childRenderNode = renderNode.append(child);
3822 this.buildRenderTree(childRenderNode, child);
3824 if (isShadowHost(node)) {
3825 var renderer = getRendererForHost(node);
3826 renderer.dirty = false;
3829 compose: function(node) {
3831 var p = node.shadowRoot || node;
3832 for (var child = p.firstChild; child; child = child.nextSibling) {
3833 if (isInsertionPoint(child)) {
3834 this.associateNode(p);
3835 var distributedNodes = getDistributedNodes(child);
3836 for (var j = 0; j < distributedNodes.length; j++) {
3837 var distributedNode = distributedNodes[j];
3838 if (isFinalDestination(child, distributedNode)) children.push(distributedNode);
3841 children.push(child);
3846 invalidateAttributes: function() {
3847 this.attributes = Object.create(null);
3849 updateDependentAttributes: function(selector) {
3850 if (!selector) return;
3851 var attributes = this.attributes;
3852 if (/\.\w+/.test(selector)) attributes["class"] = true;
3853 if (/#\w+/.test(selector)) attributes["id"] = true;
3854 selector.replace(/\[\s*([^\s=\|~\]]+)/g, function(_, name) {
3855 attributes[name] = true;
3858 dependsOnAttribute: function(name) {
3859 return this.attributes[name];
3861 associateNode: function(node) {
3862 unsafeUnwrap(node).polymerShadowRenderer_ = this;
3865 function poolPopulation(node) {
3867 for (var child = node.firstChild; child; child = child.nextSibling) {
3868 if (isInsertionPoint(child)) {
3869 pool.push.apply(pool, getDistributedNodes(child));
3876 function getShadowInsertionPoint(node) {
3877 if (node instanceof HTMLShadowElement) return node;
3878 if (node instanceof HTMLContentElement) return null;
3879 for (var child = node.firstChild; child; child = child.nextSibling) {
3880 var res = getShadowInsertionPoint(child);
3881 if (res) return res;
3885 function destributeNodeInto(child, insertionPoint) {
3886 getDistributedNodes(insertionPoint).push(child);
3887 var points = destinationInsertionPointsTable.get(child);
3888 if (!points) destinationInsertionPointsTable.set(child, [ insertionPoint ]); else points.push(insertionPoint);
3890 function getDestinationInsertionPoints(node) {
3891 return destinationInsertionPointsTable.get(node);
3893 function resetDestinationInsertionPoints(node) {
3894 destinationInsertionPointsTable.set(node, undefined);
3896 var selectorStartCharRe = /^(:not\()?[*.#[a-zA-Z_|]/;
3897 function matches(node, contentElement) {
3898 var select = contentElement.getAttribute("select");
3899 if (!select) return true;
3900 select = select.trim();
3901 if (!select) return true;
3902 if (!(node instanceof Element)) return false;
3903 if (!selectorStartCharRe.test(select)) return false;
3905 return node.matches(select);
3910 function isFinalDestination(insertionPoint, node) {
3911 var points = getDestinationInsertionPoints(node);
3912 return points && points[points.length - 1] === insertionPoint;
3914 function isInsertionPoint(node) {
3915 return node instanceof HTMLContentElement || node instanceof HTMLShadowElement;
3917 function isShadowHost(shadowHost) {
3918 return shadowHost.shadowRoot;
3920 function getShadowTrees(host) {
3922 for (var tree = host.shadowRoot; tree; tree = tree.olderShadowRoot) {
3927 function render(host) {
3928 new ShadowRenderer(host).render();
3930 Node.prototype.invalidateShadowRenderer = function(force) {
3931 var renderer = unsafeUnwrap(this).polymerShadowRenderer_;
3933 renderer.invalidate();
3938 HTMLContentElement.prototype.getDistributedNodes = HTMLShadowElement.prototype.getDistributedNodes = function() {
3940 return getDistributedNodes(this);
3942 Element.prototype.getDestinationInsertionPoints = function() {
3944 return getDestinationInsertionPoints(this) || [];
3946 HTMLContentElement.prototype.nodeIsInserted_ = HTMLShadowElement.prototype.nodeIsInserted_ = function() {
3947 this.invalidateShadowRenderer();
3948 var shadowRoot = getShadowRootAncestor(this);
3950 if (shadowRoot) renderer = getRendererForShadowRoot(shadowRoot);
3951 unsafeUnwrap(this).polymerShadowRenderer_ = renderer;
3952 if (renderer) renderer.invalidate();
3954 scope.getRendererForHost = getRendererForHost;
3955 scope.getShadowTrees = getShadowTrees;
3956 scope.renderAllPending = renderAllPending;
3957 scope.getDestinationInsertionPoints = getDestinationInsertionPoints;
3959 insertBefore: insertBefore,
3962 })(window.ShadowDOMPolyfill);
3965 var HTMLElement = scope.wrappers.HTMLElement;
3966 var assert = scope.assert;
3967 var mixin = scope.mixin;
3968 var registerWrapper = scope.registerWrapper;
3969 var unwrap = scope.unwrap;
3970 var wrap = scope.wrap;
3971 var elementsWithFormProperty = [ "HTMLButtonElement", "HTMLFieldSetElement", "HTMLInputElement", "HTMLKeygenElement", "HTMLLabelElement", "HTMLLegendElement", "HTMLObjectElement", "HTMLOutputElement", "HTMLTextAreaElement" ];
3972 function createWrapperConstructor(name) {
3973 if (!window[name]) return;
3974 assert(!scope.wrappers[name]);
3975 var GeneratedWrapper = function(node) {
3976 HTMLElement.call(this, node);
3978 GeneratedWrapper.prototype = Object.create(HTMLElement.prototype);
3979 mixin(GeneratedWrapper.prototype, {
3981 return wrap(unwrap(this).form);
3984 registerWrapper(window[name], GeneratedWrapper, document.createElement(name.slice(4, -7)));
3985 scope.wrappers[name] = GeneratedWrapper;
3987 elementsWithFormProperty.forEach(createWrapperConstructor);
3988 })(window.ShadowDOMPolyfill);
3991 var registerWrapper = scope.registerWrapper;
3992 var setWrapper = scope.setWrapper;
3993 var unsafeUnwrap = scope.unsafeUnwrap;
3994 var unwrap = scope.unwrap;
3995 var unwrapIfNeeded = scope.unwrapIfNeeded;
3996 var wrap = scope.wrap;
3997 var OriginalSelection = window.Selection;
3998 function Selection(impl) {
3999 setWrapper(impl, this);
4001 Selection.prototype = {
4003 return wrap(unsafeUnwrap(this).anchorNode);
4006 return wrap(unsafeUnwrap(this).focusNode);
4008 addRange: function(range) {
4009 unsafeUnwrap(this).addRange(unwrapIfNeeded(range));
4011 collapse: function(node, index) {
4012 unsafeUnwrap(this).collapse(unwrapIfNeeded(node), index);
4014 containsNode: function(node, allowPartial) {
4015 return unsafeUnwrap(this).containsNode(unwrapIfNeeded(node), allowPartial);
4017 getRangeAt: function(index) {
4018 return wrap(unsafeUnwrap(this).getRangeAt(index));
4020 removeRange: function(range) {
4021 unsafeUnwrap(this).removeRange(unwrap(range));
4023 selectAllChildren: function(node) {
4024 unsafeUnwrap(this).selectAllChildren(node instanceof ShadowRoot ? unsafeUnwrap(node.host) : unwrapIfNeeded(node));
4026 toString: function() {
4027 return unsafeUnwrap(this).toString();
4030 if (OriginalSelection.prototype.extend) {
4031 Selection.prototype.extend = function(node, offset) {
4032 unsafeUnwrap(this).extend(unwrapIfNeeded(node), offset);
4035 registerWrapper(window.Selection, Selection, window.getSelection());
4036 scope.wrappers.Selection = Selection;
4037 })(window.ShadowDOMPolyfill);
4040 var registerWrapper = scope.registerWrapper;
4041 var setWrapper = scope.setWrapper;
4042 var unsafeUnwrap = scope.unsafeUnwrap;
4043 var unwrapIfNeeded = scope.unwrapIfNeeded;
4044 var wrap = scope.wrap;
4045 var OriginalTreeWalker = window.TreeWalker;
4046 function TreeWalker(impl) {
4047 setWrapper(impl, this);
4049 TreeWalker.prototype = {
4051 return wrap(unsafeUnwrap(this).root);
4054 return wrap(unsafeUnwrap(this).currentNode);
4056 set currentNode(node) {
4057 unsafeUnwrap(this).currentNode = unwrapIfNeeded(node);
4060 return unsafeUnwrap(this).filter;
4062 parentNode: function() {
4063 return wrap(unsafeUnwrap(this).parentNode());
4065 firstChild: function() {
4066 return wrap(unsafeUnwrap(this).firstChild());
4068 lastChild: function() {
4069 return wrap(unsafeUnwrap(this).lastChild());
4071 previousSibling: function() {
4072 return wrap(unsafeUnwrap(this).previousSibling());
4074 previousNode: function() {
4075 return wrap(unsafeUnwrap(this).previousNode());
4077 nextNode: function() {
4078 return wrap(unsafeUnwrap(this).nextNode());
4081 registerWrapper(OriginalTreeWalker, TreeWalker);
4082 scope.wrappers.TreeWalker = TreeWalker;
4083 })(window.ShadowDOMPolyfill);
4086 var GetElementsByInterface = scope.GetElementsByInterface;
4087 var Node = scope.wrappers.Node;
4088 var ParentNodeInterface = scope.ParentNodeInterface;
4089 var NonElementParentNodeInterface = scope.NonElementParentNodeInterface;
4090 var Selection = scope.wrappers.Selection;
4091 var SelectorsInterface = scope.SelectorsInterface;
4092 var ShadowRoot = scope.wrappers.ShadowRoot;
4093 var TreeScope = scope.TreeScope;
4094 var cloneNode = scope.cloneNode;
4095 var defineGetter = scope.defineGetter;
4096 var defineWrapGetter = scope.defineWrapGetter;
4097 var elementFromPoint = scope.elementFromPoint;
4098 var forwardMethodsToWrapper = scope.forwardMethodsToWrapper;
4099 var matchesNames = scope.matchesNames;
4100 var mixin = scope.mixin;
4101 var registerWrapper = scope.registerWrapper;
4102 var renderAllPending = scope.renderAllPending;
4103 var rewrap = scope.rewrap;
4104 var setWrapper = scope.setWrapper;
4105 var unsafeUnwrap = scope.unsafeUnwrap;
4106 var unwrap = scope.unwrap;
4107 var wrap = scope.wrap;
4108 var wrapEventTargetMethods = scope.wrapEventTargetMethods;
4109 var wrapNodeList = scope.wrapNodeList;
4110 var implementationTable = new WeakMap();
4111 function Document(node) {
4112 Node.call(this, node);
4113 this.treeScope_ = new TreeScope(this, null);
4115 Document.prototype = Object.create(Node.prototype);
4116 defineWrapGetter(Document, "documentElement");
4117 defineWrapGetter(Document, "body");
4118 defineWrapGetter(Document, "head");
4119 defineGetter(Document, "activeElement", function() {
4120 var unwrappedActiveElement = unwrap(this).activeElement;
4121 if (!unwrappedActiveElement || !unwrappedActiveElement.nodeType) return null;
4122 var activeElement = wrap(unwrappedActiveElement);
4123 while (!this.contains(activeElement)) {
4124 while (activeElement.parentNode) {
4125 activeElement = activeElement.parentNode;
4127 if (activeElement.host) {
4128 activeElement = activeElement.host;
4133 return activeElement;
4135 function wrapMethod(name) {
4136 var original = document[name];
4137 Document.prototype[name] = function() {
4138 return wrap(original.apply(unsafeUnwrap(this), arguments));
4141 [ "createComment", "createDocumentFragment", "createElement", "createElementNS", "createEvent", "createEventNS", "createRange", "createTextNode" ].forEach(wrapMethod);
4142 var originalAdoptNode = document.adoptNode;
4143 function adoptNodeNoRemove(node, doc) {
4144 originalAdoptNode.call(unsafeUnwrap(doc), unwrap(node));
4145 adoptSubtree(node, doc);
4147 function adoptSubtree(node, doc) {
4148 if (node.shadowRoot) doc.adoptNode(node.shadowRoot);
4149 if (node instanceof ShadowRoot) adoptOlderShadowRoots(node, doc);
4150 for (var child = node.firstChild; child; child = child.nextSibling) {
4151 adoptSubtree(child, doc);
4154 function adoptOlderShadowRoots(shadowRoot, doc) {
4155 var oldShadowRoot = shadowRoot.olderShadowRoot;
4156 if (oldShadowRoot) doc.adoptNode(oldShadowRoot);
4158 var originalGetSelection = document.getSelection;
4159 mixin(Document.prototype, {
4160 adoptNode: function(node) {
4161 if (node.parentNode) node.parentNode.removeChild(node);
4162 adoptNodeNoRemove(node, this);
4165 elementFromPoint: function(x, y) {
4166 return elementFromPoint(this, this, x, y);
4168 importNode: function(node, deep) {
4169 return cloneNode(node, deep, unsafeUnwrap(this));
4171 getSelection: function() {
4173 return new Selection(originalGetSelection.call(unwrap(this)));
4175 getElementsByName: function(name) {
4176 return SelectorsInterface.querySelectorAll.call(this, "[name=" + JSON.stringify(String(name)) + "]");
4179 var originalCreateTreeWalker = document.createTreeWalker;
4180 var TreeWalkerWrapper = scope.wrappers.TreeWalker;
4181 Document.prototype.createTreeWalker = function(root, whatToShow, filter, expandEntityReferences) {
4182 var newFilter = null;
4184 if (filter.acceptNode && typeof filter.acceptNode === "function") {
4186 acceptNode: function(node) {
4187 return filter.acceptNode(wrap(node));
4190 } else if (typeof filter === "function") {
4191 newFilter = function(node) {
4192 return filter(wrap(node));
4196 return new TreeWalkerWrapper(originalCreateTreeWalker.call(unwrap(this), unwrap(root), whatToShow, newFilter, expandEntityReferences));
4198 if (document.registerElement) {
4199 var originalRegisterElement = document.registerElement;
4200 Document.prototype.registerElement = function(tagName, object) {
4201 var prototype, extendsOption;
4202 if (object !== undefined) {
4203 prototype = object.prototype;
4204 extendsOption = object.extends;
4206 if (!prototype) prototype = Object.create(HTMLElement.prototype);
4207 if (scope.nativePrototypeTable.get(prototype)) {
4208 throw new Error("NotSupportedError");
4210 var proto = Object.getPrototypeOf(prototype);
4211 var nativePrototype;
4212 var prototypes = [];
4214 nativePrototype = scope.nativePrototypeTable.get(proto);
4215 if (nativePrototype) break;
4216 prototypes.push(proto);
4217 proto = Object.getPrototypeOf(proto);
4219 if (!nativePrototype) {
4220 throw new Error("NotSupportedError");
4222 var newPrototype = Object.create(nativePrototype);
4223 for (var i = prototypes.length - 1; i >= 0; i--) {
4224 newPrototype = Object.create(newPrototype);
4226 [ "createdCallback", "attachedCallback", "detachedCallback", "attributeChangedCallback" ].forEach(function(name) {
4227 var f = prototype[name];
4229 newPrototype[name] = function() {
4230 if (!(wrap(this) instanceof CustomElementConstructor)) {
4233 f.apply(wrap(this), arguments);
4237 prototype: newPrototype
4239 if (extendsOption) p.extends = extendsOption;
4240 function CustomElementConstructor(node) {
4242 if (extendsOption) {
4243 return document.createElement(extendsOption, tagName);
4245 return document.createElement(tagName);
4248 setWrapper(node, this);
4250 CustomElementConstructor.prototype = prototype;
4251 CustomElementConstructor.prototype.constructor = CustomElementConstructor;
4252 scope.constructorTable.set(newPrototype, CustomElementConstructor);
4253 scope.nativePrototypeTable.set(prototype, newPrototype);
4254 var nativeConstructor = originalRegisterElement.call(unwrap(this), tagName, p);
4255 return CustomElementConstructor;
4257 forwardMethodsToWrapper([ window.HTMLDocument || window.Document ], [ "registerElement" ]);
4259 forwardMethodsToWrapper([ window.HTMLBodyElement, window.HTMLDocument || window.Document, window.HTMLHeadElement, window.HTMLHtmlElement ], [ "appendChild", "compareDocumentPosition", "contains", "getElementsByClassName", "getElementsByTagName", "getElementsByTagNameNS", "insertBefore", "querySelector", "querySelectorAll", "removeChild", "replaceChild" ]);
4260 forwardMethodsToWrapper([ window.HTMLBodyElement, window.HTMLHeadElement, window.HTMLHtmlElement ], matchesNames);
4261 forwardMethodsToWrapper([ window.HTMLDocument || window.Document ], [ "adoptNode", "importNode", "contains", "createComment", "createDocumentFragment", "createElement", "createElementNS", "createEvent", "createEventNS", "createRange", "createTextNode", "createTreeWalker", "elementFromPoint", "getElementById", "getElementsByName", "getSelection" ]);
4262 mixin(Document.prototype, GetElementsByInterface);
4263 mixin(Document.prototype, ParentNodeInterface);
4264 mixin(Document.prototype, SelectorsInterface);
4265 mixin(Document.prototype, NonElementParentNodeInterface);
4266 mixin(Document.prototype, {
4267 get implementation() {
4268 var implementation = implementationTable.get(this);
4269 if (implementation) return implementation;
4270 implementation = new DOMImplementation(unwrap(this).implementation);
4271 implementationTable.set(this, implementation);
4272 return implementation;
4275 return wrap(unwrap(this).defaultView);
4278 registerWrapper(window.Document, Document, document.implementation.createHTMLDocument(""));
4279 if (window.HTMLDocument) registerWrapper(window.HTMLDocument, Document);
4280 wrapEventTargetMethods([ window.HTMLBodyElement, window.HTMLDocument || window.Document, window.HTMLHeadElement ]);
4281 function DOMImplementation(impl) {
4282 setWrapper(impl, this);
4284 var originalCreateDocument = document.implementation.createDocument;
4285 DOMImplementation.prototype.createDocument = function() {
4286 arguments[2] = unwrap(arguments[2]);
4287 return wrap(originalCreateDocument.apply(unsafeUnwrap(this), arguments));
4289 function wrapImplMethod(constructor, name) {
4290 var original = document.implementation[name];
4291 constructor.prototype[name] = function() {
4292 return wrap(original.apply(unsafeUnwrap(this), arguments));
4295 function forwardImplMethod(constructor, name) {
4296 var original = document.implementation[name];
4297 constructor.prototype[name] = function() {
4298 return original.apply(unsafeUnwrap(this), arguments);
4301 wrapImplMethod(DOMImplementation, "createDocumentType");
4302 wrapImplMethod(DOMImplementation, "createHTMLDocument");
4303 forwardImplMethod(DOMImplementation, "hasFeature");
4304 registerWrapper(window.DOMImplementation, DOMImplementation);
4305 forwardMethodsToWrapper([ window.DOMImplementation ], [ "createDocument", "createDocumentType", "createHTMLDocument", "hasFeature" ]);
4306 scope.adoptNodeNoRemove = adoptNodeNoRemove;
4307 scope.wrappers.DOMImplementation = DOMImplementation;
4308 scope.wrappers.Document = Document;
4309 })(window.ShadowDOMPolyfill);
4312 var EventTarget = scope.wrappers.EventTarget;
4313 var Selection = scope.wrappers.Selection;
4314 var mixin = scope.mixin;
4315 var registerWrapper = scope.registerWrapper;
4316 var renderAllPending = scope.renderAllPending;
4317 var unwrap = scope.unwrap;
4318 var unwrapIfNeeded = scope.unwrapIfNeeded;
4319 var wrap = scope.wrap;
4320 var OriginalWindow = window.Window;
4321 var originalGetComputedStyle = window.getComputedStyle;
4322 var originalGetDefaultComputedStyle = window.getDefaultComputedStyle;
4323 var originalGetSelection = window.getSelection;
4324 function Window(impl) {
4325 EventTarget.call(this, impl);
4327 Window.prototype = Object.create(EventTarget.prototype);
4328 OriginalWindow.prototype.getComputedStyle = function(el, pseudo) {
4329 return wrap(this || window).getComputedStyle(unwrapIfNeeded(el), pseudo);
4331 if (originalGetDefaultComputedStyle) {
4332 OriginalWindow.prototype.getDefaultComputedStyle = function(el, pseudo) {
4333 return wrap(this || window).getDefaultComputedStyle(unwrapIfNeeded(el), pseudo);
4336 OriginalWindow.prototype.getSelection = function() {
4337 return wrap(this || window).getSelection();
4339 delete window.getComputedStyle;
4340 delete window.getDefaultComputedStyle;
4341 delete window.getSelection;
4342 [ "addEventListener", "removeEventListener", "dispatchEvent" ].forEach(function(name) {
4343 OriginalWindow.prototype[name] = function() {
4344 var w = wrap(this || window);
4345 return w[name].apply(w, arguments);
4347 delete window[name];
4349 mixin(Window.prototype, {
4350 getComputedStyle: function(el, pseudo) {
4352 return originalGetComputedStyle.call(unwrap(this), unwrapIfNeeded(el), pseudo);
4354 getSelection: function() {
4356 return new Selection(originalGetSelection.call(unwrap(this)));
4359 return wrap(unwrap(this).document);
4362 if (originalGetDefaultComputedStyle) {
4363 Window.prototype.getDefaultComputedStyle = function(el, pseudo) {
4365 return originalGetDefaultComputedStyle.call(unwrap(this), unwrapIfNeeded(el), pseudo);
4368 registerWrapper(OriginalWindow, Window, window);
4369 scope.wrappers.Window = Window;
4370 })(window.ShadowDOMPolyfill);
4373 var unwrap = scope.unwrap;
4374 var OriginalDataTransfer = window.DataTransfer || window.Clipboard;
4375 var OriginalDataTransferSetDragImage = OriginalDataTransfer.prototype.setDragImage;
4376 if (OriginalDataTransferSetDragImage) {
4377 OriginalDataTransfer.prototype.setDragImage = function(image, x, y) {
4378 OriginalDataTransferSetDragImage.call(this, unwrap(image), x, y);
4381 })(window.ShadowDOMPolyfill);
4384 var registerWrapper = scope.registerWrapper;
4385 var setWrapper = scope.setWrapper;
4386 var unwrap = scope.unwrap;
4387 var OriginalFormData = window.FormData;
4388 if (!OriginalFormData) return;
4389 function FormData(formElement) {
4391 if (formElement instanceof OriginalFormData) {
4394 impl = new OriginalFormData(formElement && unwrap(formElement));
4396 setWrapper(impl, this);
4398 registerWrapper(OriginalFormData, FormData, new OriginalFormData());
4399 scope.wrappers.FormData = FormData;
4400 })(window.ShadowDOMPolyfill);
4403 var unwrapIfNeeded = scope.unwrapIfNeeded;
4404 var originalSend = XMLHttpRequest.prototype.send;
4405 XMLHttpRequest.prototype.send = function(obj) {
4406 return originalSend.call(this, unwrapIfNeeded(obj));
4408 })(window.ShadowDOMPolyfill);
4411 var isWrapperFor = scope.isWrapperFor;
4413 a: "HTMLAnchorElement",
4414 area: "HTMLAreaElement",
4415 audio: "HTMLAudioElement",
4416 base: "HTMLBaseElement",
4417 body: "HTMLBodyElement",
4418 br: "HTMLBRElement",
4419 button: "HTMLButtonElement",
4420 canvas: "HTMLCanvasElement",
4421 caption: "HTMLTableCaptionElement",
4422 col: "HTMLTableColElement",
4423 content: "HTMLContentElement",
4424 data: "HTMLDataElement",
4425 datalist: "HTMLDataListElement",
4426 del: "HTMLModElement",
4427 dir: "HTMLDirectoryElement",
4428 div: "HTMLDivElement",
4429 dl: "HTMLDListElement",
4430 embed: "HTMLEmbedElement",
4431 fieldset: "HTMLFieldSetElement",
4432 font: "HTMLFontElement",
4433 form: "HTMLFormElement",
4434 frame: "HTMLFrameElement",
4435 frameset: "HTMLFrameSetElement",
4436 h1: "HTMLHeadingElement",
4437 head: "HTMLHeadElement",
4438 hr: "HTMLHRElement",
4439 html: "HTMLHtmlElement",
4440 iframe: "HTMLIFrameElement",
4441 img: "HTMLImageElement",
4442 input: "HTMLInputElement",
4443 keygen: "HTMLKeygenElement",
4444 label: "HTMLLabelElement",
4445 legend: "HTMLLegendElement",
4446 li: "HTMLLIElement",
4447 link: "HTMLLinkElement",
4448 map: "HTMLMapElement",
4449 marquee: "HTMLMarqueeElement",
4450 menu: "HTMLMenuElement",
4451 menuitem: "HTMLMenuItemElement",
4452 meta: "HTMLMetaElement",
4453 meter: "HTMLMeterElement",
4454 object: "HTMLObjectElement",
4455 ol: "HTMLOListElement",
4456 optgroup: "HTMLOptGroupElement",
4457 option: "HTMLOptionElement",
4458 output: "HTMLOutputElement",
4459 p: "HTMLParagraphElement",
4460 param: "HTMLParamElement",
4461 pre: "HTMLPreElement",
4462 progress: "HTMLProgressElement",
4463 q: "HTMLQuoteElement",
4464 script: "HTMLScriptElement",
4465 select: "HTMLSelectElement",
4466 shadow: "HTMLShadowElement",
4467 source: "HTMLSourceElement",
4468 span: "HTMLSpanElement",
4469 style: "HTMLStyleElement",
4470 table: "HTMLTableElement",
4471 tbody: "HTMLTableSectionElement",
4472 template: "HTMLTemplateElement",
4473 textarea: "HTMLTextAreaElement",
4474 thead: "HTMLTableSectionElement",
4475 time: "HTMLTimeElement",
4476 title: "HTMLTitleElement",
4477 tr: "HTMLTableRowElement",
4478 track: "HTMLTrackElement",
4479 ul: "HTMLUListElement",
4480 video: "HTMLVideoElement"
4482 function overrideConstructor(tagName) {
4483 var nativeConstructorName = elements[tagName];
4484 var nativeConstructor = window[nativeConstructorName];
4485 if (!nativeConstructor) return;
4486 var element = document.createElement(tagName);
4487 var wrapperConstructor = element.constructor;
4488 window[nativeConstructorName] = wrapperConstructor;
4490 Object.keys(elements).forEach(overrideConstructor);
4491 Object.getOwnPropertyNames(scope.wrappers).forEach(function(name) {
4492 window[name] = scope.wrappers[name];
4494 })(window.ShadowDOMPolyfill);
4497 strictStyling: false,
4499 shimStyling: function(root, name, extendsName) {
4500 var scopeStyles = this.prepareRoot(root, name, extendsName);
4501 var typeExtension = this.isTypeExtension(extendsName);
4502 var scopeSelector = this.makeScopeSelector(name, typeExtension);
4503 var cssText = stylesToCssText(scopeStyles, true);
4504 cssText = this.scopeCssText(cssText, scopeSelector);
4506 root.shimmedStyle = cssText;
4508 this.addCssToDocument(cssText, name);
4510 shimStyle: function(style, selector) {
4511 return this.shimCssText(style.textContent, selector);
4513 shimCssText: function(cssText, selector) {
4514 cssText = this.insertDirectives(cssText);
4515 return this.scopeCssText(cssText, selector);
4517 makeScopeSelector: function(name, typeExtension) {
4519 return typeExtension ? "[is=" + name + "]" : name;
4523 isTypeExtension: function(extendsName) {
4524 return extendsName && extendsName.indexOf("-") < 0;
4526 prepareRoot: function(root, name, extendsName) {
4527 var def = this.registerRoot(root, name, extendsName);
4528 this.replaceTextInStyles(def.rootStyles, this.insertDirectives);
4529 this.removeStyles(root, def.rootStyles);
4530 if (this.strictStyling) {
4531 this.applyScopeToContent(root, name);
4533 return def.scopeStyles;
4535 removeStyles: function(root, styles) {
4536 for (var i = 0, l = styles.length, s; i < l && (s = styles[i]); i++) {
4537 s.parentNode.removeChild(s);
4540 registerRoot: function(root, name, extendsName) {
4541 var def = this.registry[name] = {
4544 extendsName: extendsName
4546 var styles = this.findStyles(root);
4547 def.rootStyles = styles;
4548 def.scopeStyles = def.rootStyles;
4549 var extendee = this.registry[def.extendsName];
4551 def.scopeStyles = extendee.scopeStyles.concat(def.scopeStyles);
4555 findStyles: function(root) {
4559 var styles = root.querySelectorAll("style");
4560 return Array.prototype.filter.call(styles, function(s) {
4561 return !s.hasAttribute(NO_SHIM_ATTRIBUTE);
4564 applyScopeToContent: function(root, name) {
4566 Array.prototype.forEach.call(root.querySelectorAll("*"), function(node) {
4567 node.setAttribute(name, "");
4569 Array.prototype.forEach.call(root.querySelectorAll("template"), function(template) {
4570 this.applyScopeToContent(template.content, name);
4574 insertDirectives: function(cssText) {
4575 cssText = this.insertPolyfillDirectivesInCssText(cssText);
4576 return this.insertPolyfillRulesInCssText(cssText);
4578 insertPolyfillDirectivesInCssText: function(cssText) {
4579 cssText = cssText.replace(cssCommentNextSelectorRe, function(match, p1) {
4580 return p1.slice(0, -2) + "{";
4582 return cssText.replace(cssContentNextSelectorRe, function(match, p1) {
4586 insertPolyfillRulesInCssText: function(cssText) {
4587 cssText = cssText.replace(cssCommentRuleRe, function(match, p1) {
4588 return p1.slice(0, -1);
4590 return cssText.replace(cssContentRuleRe, function(match, p1, p2, p3) {
4591 var rule = match.replace(p1, "").replace(p2, "");
4595 scopeCssText: function(cssText, scopeSelector) {
4596 var unscoped = this.extractUnscopedRulesFromCssText(cssText);
4597 cssText = this.insertPolyfillHostInCssText(cssText);
4598 cssText = this.convertColonHost(cssText);
4599 cssText = this.convertColonHostContext(cssText);
4600 cssText = this.convertShadowDOMSelectors(cssText);
4601 if (scopeSelector) {
4602 var self = this, cssText;
4603 withCssRules(cssText, function(rules) {
4604 cssText = self.scopeRules(rules, scopeSelector);
4607 cssText = cssText + "\n" + unscoped;
4608 return cssText.trim();
4610 extractUnscopedRulesFromCssText: function(cssText) {
4612 while (m = cssCommentUnscopedRuleRe.exec(cssText)) {
4613 r += m[1].slice(0, -1) + "\n\n";
4615 while (m = cssContentUnscopedRuleRe.exec(cssText)) {
4616 r += m[0].replace(m[2], "").replace(m[1], m[3]) + "\n\n";
4620 convertColonHost: function(cssText) {
4621 return this.convertColonRule(cssText, cssColonHostRe, this.colonHostPartReplacer);
4623 convertColonHostContext: function(cssText) {
4624 return this.convertColonRule(cssText, cssColonHostContextRe, this.colonHostContextPartReplacer);
4626 convertColonRule: function(cssText, regExp, partReplacer) {
4627 return cssText.replace(regExp, function(m, p1, p2, p3) {
4628 p1 = polyfillHostNoCombinator;
4630 var parts = p2.split(","), r = [];
4631 for (var i = 0, l = parts.length, p; i < l && (p = parts[i]); i++) {
4633 r.push(partReplacer(p1, p, p3));
4641 colonHostContextPartReplacer: function(host, part, suffix) {
4642 if (part.match(polyfillHost)) {
4643 return this.colonHostPartReplacer(host, part, suffix);
4645 return host + part + suffix + ", " + part + " " + host + suffix;
4648 colonHostPartReplacer: function(host, part, suffix) {
4649 return host + part.replace(polyfillHost, "") + suffix;
4651 convertShadowDOMSelectors: function(cssText) {
4652 for (var i = 0; i < shadowDOMSelectorsRe.length; i++) {
4653 cssText = cssText.replace(shadowDOMSelectorsRe[i], " ");
4657 scopeRules: function(cssRules, scopeSelector) {
4660 Array.prototype.forEach.call(cssRules, function(rule) {
4661 if (rule.selectorText && (rule.style && rule.style.cssText !== undefined)) {
4662 cssText += this.scopeSelector(rule.selectorText, scopeSelector, this.strictStyling) + " {\n ";
4663 cssText += this.propertiesFromRule(rule) + "\n}\n\n";
4664 } else if (rule.type === CSSRule.MEDIA_RULE) {
4665 cssText += "@media " + rule.media.mediaText + " {\n";
4666 cssText += this.scopeRules(rule.cssRules, scopeSelector);
4667 cssText += "\n}\n\n";
4671 cssText += rule.cssText + "\n\n";
4674 if (rule.type === CSSRule.KEYFRAMES_RULE && rule.cssRules) {
4675 cssText += this.ieSafeCssTextFromKeyFrameRule(rule);
4683 ieSafeCssTextFromKeyFrameRule: function(rule) {
4684 var cssText = "@keyframes " + rule.name + " {";
4685 Array.prototype.forEach.call(rule.cssRules, function(rule) {
4686 cssText += " " + rule.keyText + " {" + rule.style.cssText + "}";
4691 scopeSelector: function(selector, scopeSelector, strict) {
4692 var r = [], parts = selector.split(",");
4693 parts.forEach(function(p) {
4695 if (this.selectorNeedsScoping(p, scopeSelector)) {
4696 p = strict && !p.match(polyfillHostNoCombinator) ? this.applyStrictSelectorScope(p, scopeSelector) : this.applySelectorScope(p, scopeSelector);
4700 return r.join(", ");
4702 selectorNeedsScoping: function(selector, scopeSelector) {
4703 if (Array.isArray(scopeSelector)) {
4706 var re = this.makeScopeMatcher(scopeSelector);
4707 return !selector.match(re);
4709 makeScopeMatcher: function(scopeSelector) {
4710 scopeSelector = scopeSelector.replace(/\[/g, "\\[").replace(/\]/g, "\\]");
4711 return new RegExp("^(" + scopeSelector + ")" + selectorReSuffix, "m");
4713 applySelectorScope: function(selector, selectorScope) {
4714 return Array.isArray(selectorScope) ? this.applySelectorScopeList(selector, selectorScope) : this.applySimpleSelectorScope(selector, selectorScope);
4716 applySelectorScopeList: function(selector, scopeSelectorList) {
4718 for (var i = 0, s; s = scopeSelectorList[i]; i++) {
4719 r.push(this.applySimpleSelectorScope(selector, s));
4721 return r.join(", ");
4723 applySimpleSelectorScope: function(selector, scopeSelector) {
4724 if (selector.match(polyfillHostRe)) {
4725 selector = selector.replace(polyfillHostNoCombinator, scopeSelector);
4726 return selector.replace(polyfillHostRe, scopeSelector + " ");
4728 return scopeSelector + " " + selector;
4731 applyStrictSelectorScope: function(selector, scopeSelector) {
4732 scopeSelector = scopeSelector.replace(/\[is=([^\]]*)\]/g, "$1");
4733 var splits = [ " ", ">", "+", "~" ], scoped = selector, attrName = "[" + scopeSelector + "]";
4734 splits.forEach(function(sep) {
4735 var parts = scoped.split(sep);
4736 scoped = parts.map(function(p) {
4737 var t = p.trim().replace(polyfillHostRe, "");
4738 if (t && splits.indexOf(t) < 0 && t.indexOf(attrName) < 0) {
4739 p = t.replace(/([^:]*)(:*)(.*)/, "$1" + attrName + "$2$3");
4746 insertPolyfillHostInCssText: function(selector) {
4747 return selector.replace(colonHostContextRe, polyfillHostContext).replace(colonHostRe, polyfillHost);
4749 propertiesFromRule: function(rule) {
4750 var cssText = rule.style.cssText;
4751 if (rule.style.content && !rule.style.content.match(/['"]+|attr/)) {
4752 cssText = cssText.replace(/content:[^;]*;/g, "content: '" + rule.style.content + "';");
4754 var style = rule.style;
4755 for (var i in style) {
4756 if (style[i] === "initial") {
4757 cssText += i + ": initial; ";
4762 replaceTextInStyles: function(styles, action) {
4763 if (styles && action) {
4764 if (!(styles instanceof Array)) {
4765 styles = [ styles ];
4767 Array.prototype.forEach.call(styles, function(s) {
4768 s.textContent = action.call(this, s.textContent);
4772 addCssToDocument: function(cssText, name) {
4773 if (cssText.match("@import")) {
4774 addOwnSheet(cssText, name);
4776 addCssToDocument(cssText);
4780 var selectorRe = /([^{]*)({[\s\S]*?})/gim, cssCommentRe = /\/\*[^*]*\*+([^\/*][^*]*\*+)*\//gim, cssCommentNextSelectorRe = /\/\*\s*@polyfill ([^*]*\*+([^\/*][^*]*\*+)*\/)([^{]*?){/gim, cssContentNextSelectorRe = /polyfill-next-selector[^}]*content\:[\s]*?['"](.*?)['"][;\s]*}([^{]*?){/gim, cssCommentRuleRe = /\/\*\s@polyfill-rule([^*]*\*+([^\/*][^*]*\*+)*)\//gim, cssContentRuleRe = /(polyfill-rule)[^}]*(content\:[\s]*['"](.*?)['"])[;\s]*[^}]*}/gim, cssCommentUnscopedRuleRe = /\/\*\s@polyfill-unscoped-rule([^*]*\*+([^\/*][^*]*\*+)*)\//gim, cssContentUnscopedRuleRe = /(polyfill-unscoped-rule)[^}]*(content\:[\s]*['"](.*?)['"])[;\s]*[^}]*}/gim, cssPseudoRe = /::(x-[^\s{,(]*)/gim, cssPartRe = /::part\(([^)]*)\)/gim, polyfillHost = "-shadowcsshost", polyfillHostContext = "-shadowcsscontext", parenSuffix = ")(?:\\((" + "(?:\\([^)(]*\\)|[^)(]*)+?" + ")\\))?([^,{]*)";
4781 var cssColonHostRe = new RegExp("(" + polyfillHost + parenSuffix, "gim"), cssColonHostContextRe = new RegExp("(" + polyfillHostContext + parenSuffix, "gim"), selectorReSuffix = "([>\\s~+[.,{:][\\s\\S]*)?$", colonHostRe = /\:host/gim, colonHostContextRe = /\:host-context/gim, polyfillHostNoCombinator = polyfillHost + "-no-combinator", polyfillHostRe = new RegExp(polyfillHost, "gim"), polyfillHostContextRe = new RegExp(polyfillHostContext, "gim"), shadowDOMSelectorsRe = [ />>>/g, /::shadow/g, /::content/g, /\/deep\//g, /\/shadow\//g, /\/shadow-deep\//g, /\^\^/g, /\^/g ];
4782 function stylesToCssText(styles, preserveComments) {
4784 Array.prototype.forEach.call(styles, function(s) {
4785 cssText += s.textContent + "\n\n";
4787 if (!preserveComments) {
4788 cssText = cssText.replace(cssCommentRe, "");
4792 function cssTextToStyle(cssText) {
4793 var style = document.createElement("style");
4794 style.textContent = cssText;
4797 function cssToRules(cssText) {
4798 var style = cssTextToStyle(cssText);
4799 document.head.appendChild(style);
4803 rules = style.sheet.cssRules;
4806 console.warn("sheet not found", style);
4808 style.parentNode.removeChild(style);
4811 var frame = document.createElement("iframe");
4812 frame.style.display = "none";
4813 function initFrame() {
4814 frame.initialized = true;
4815 document.body.appendChild(frame);
4816 var doc = frame.contentDocument;
4817 var base = doc.createElement("base");
4818 base.href = document.baseURI;
4819 doc.head.appendChild(base);
4821 function inFrame(fn) {
4822 if (!frame.initialized) {
4825 document.body.appendChild(frame);
4826 fn(frame.contentDocument);
4827 document.body.removeChild(frame);
4829 var isChrome = navigator.userAgent.match("Chrome");
4830 function withCssRules(cssText, callback) {
4835 if (cssText.match("@import") && isChrome) {
4836 var style = cssTextToStyle(cssText);
4837 inFrame(function(doc) {
4838 doc.head.appendChild(style.impl);
4839 rules = Array.prototype.slice.call(style.sheet.cssRules, 0);
4843 rules = cssToRules(cssText);
4847 function rulesToCss(cssRules) {
4848 for (var i = 0, css = []; i < cssRules.length; i++) {
4849 css.push(cssRules[i].cssText);
4851 return css.join("\n\n");
4853 function addCssToDocument(cssText) {
4855 getSheet().appendChild(document.createTextNode(cssText));
4858 function addOwnSheet(cssText, name) {
4859 var style = cssTextToStyle(cssText);
4860 style.setAttribute(name, "");
4861 style.setAttribute(SHIMMED_ATTRIBUTE, "");
4862 document.head.appendChild(style);
4864 var SHIM_ATTRIBUTE = "shim-shadowdom";
4865 var SHIMMED_ATTRIBUTE = "shim-shadowdom-css";
4866 var NO_SHIM_ATTRIBUTE = "no-shim";
4868 function getSheet() {
4870 sheet = document.createElement("style");
4871 sheet.setAttribute(SHIMMED_ATTRIBUTE, "");
4872 sheet[SHIMMED_ATTRIBUTE] = true;
4876 if (window.ShadowDOMPolyfill) {
4877 addCssToDocument("style { display: none !important; }\n");
4878 var doc = ShadowDOMPolyfill.wrap(document);
4879 var head = doc.querySelector("head");
4880 head.insertBefore(getSheet(), head.childNodes[0]);
4881 document.addEventListener("DOMContentLoaded", function() {
4882 var urlResolver = scope.urlResolver;
4883 if (window.HTMLImports && !HTMLImports.useNative) {
4884 var SHIM_SHEET_SELECTOR = "link[rel=stylesheet]" + "[" + SHIM_ATTRIBUTE + "]";
4885 var SHIM_STYLE_SELECTOR = "style[" + SHIM_ATTRIBUTE + "]";
4886 HTMLImports.importer.documentPreloadSelectors += "," + SHIM_SHEET_SELECTOR;
4887 HTMLImports.importer.importsPreloadSelectors += "," + SHIM_SHEET_SELECTOR;
4888 HTMLImports.parser.documentSelectors = [ HTMLImports.parser.documentSelectors, SHIM_SHEET_SELECTOR, SHIM_STYLE_SELECTOR ].join(",");
4889 var originalParseGeneric = HTMLImports.parser.parseGeneric;
4890 HTMLImports.parser.parseGeneric = function(elt) {
4891 if (elt[SHIMMED_ATTRIBUTE]) {
4894 var style = elt.__importElement || elt;
4895 if (!style.hasAttribute(SHIM_ATTRIBUTE)) {
4896 originalParseGeneric.call(this, elt);
4899 if (elt.__resource) {
4900 style = elt.ownerDocument.createElement("style");
4901 style.textContent = elt.__resource;
4903 HTMLImports.path.resolveUrlsInStyle(style, elt.href);
4904 style.textContent = ShadowCSS.shimStyle(style);
4905 style.removeAttribute(SHIM_ATTRIBUTE, "");
4906 style.setAttribute(SHIMMED_ATTRIBUTE, "");
4907 style[SHIMMED_ATTRIBUTE] = true;
4908 if (style.parentNode !== head) {
4909 if (elt.parentNode === head) {
4910 head.replaceChild(style, elt);
4912 this.addElementToDocument(style);
4915 style.__importParsed = true;
4916 this.markParsingComplete(elt);
4919 var hasResource = HTMLImports.parser.hasResource;
4920 HTMLImports.parser.hasResource = function(node) {
4921 if (node.localName === "link" && node.rel === "stylesheet" && node.hasAttribute(SHIM_ATTRIBUTE)) {
4922 return node.__resource;
4924 return hasResource.call(this, node);
4930 scope.ShadowCSS = ShadowCSS;
4931 })(window.WebComponents);
4935 if (window.ShadowDOMPolyfill) {
4936 window.wrap = ShadowDOMPolyfill.wrapIfNeeded;
4937 window.unwrap = ShadowDOMPolyfill.unwrapIfNeeded;
4939 window.wrap = window.unwrap = function(n) {
4943 })(window.WebComponents);
4947 var hasWorkingUrl = false;
4948 if (!scope.forceJURL) {
4950 var u = new URL("b", "http://a");
4951 u.pathname = "c%20d";
4952 hasWorkingUrl = u.href === "http://a/c%20d";
4955 if (hasWorkingUrl) return;
4956 var relative = Object.create(null);
4957 relative["ftp"] = 21;
4958 relative["file"] = 0;
4959 relative["gopher"] = 70;
4960 relative["http"] = 80;
4961 relative["https"] = 443;
4962 relative["ws"] = 80;
4963 relative["wss"] = 443;
4964 var relativePathDotMapping = Object.create(null);
4965 relativePathDotMapping["%2e"] = ".";
4966 relativePathDotMapping[".%2e"] = "..";
4967 relativePathDotMapping["%2e."] = "..";
4968 relativePathDotMapping["%2e%2e"] = "..";
4969 function isRelativeScheme(scheme) {
4970 return relative[scheme] !== undefined;
4972 function invalid() {
4974 this._isInvalid = true;
4976 function IDNAToASCII(h) {
4980 return h.toLowerCase();
4982 function percentEscape(c) {
4983 var unicode = c.charCodeAt(0);
4984 if (unicode > 32 && unicode < 127 && [ 34, 35, 60, 62, 63, 96 ].indexOf(unicode) == -1) {
4987 return encodeURIComponent(c);
4989 function percentEscapeQuery(c) {
4990 var unicode = c.charCodeAt(0);
4991 if (unicode > 32 && unicode < 127 && [ 34, 35, 60, 62, 96 ].indexOf(unicode) == -1) {
4994 return encodeURIComponent(c);
4996 var EOF = undefined, ALPHA = /[a-zA-Z]/, ALPHANUMERIC = /[a-zA-Z0-9\+\-\.]/;
4997 function parse(input, stateOverride, base) {
4998 function err(message) {
4999 errors.push(message);
5001 var state = stateOverride || "scheme start", cursor = 0, buffer = "", seenAt = false, seenBracket = false, errors = [];
5002 loop: while ((input[cursor - 1] != EOF || cursor == 0) && !this._isInvalid) {
5003 var c = input[cursor];
5005 case "scheme start":
5006 if (c && ALPHA.test(c)) {
5007 buffer += c.toLowerCase();
5009 } else if (!stateOverride) {
5011 state = "no scheme";
5014 err("Invalid scheme.");
5020 if (c && ALPHANUMERIC.test(c)) {
5021 buffer += c.toLowerCase();
5022 } else if (":" == c) {
5023 this._scheme = buffer;
5025 if (stateOverride) {
5028 if (isRelativeScheme(this._scheme)) {
5029 this._isRelative = true;
5031 if ("file" == this._scheme) {
5033 } else if (this._isRelative && base && base._scheme == this._scheme) {
5034 state = "relative or authority";
5035 } else if (this._isRelative) {
5036 state = "authority first slash";
5038 state = "scheme data";
5040 } else if (!stateOverride) {
5043 state = "no scheme";
5045 } else if (EOF == c) {
5048 err("Code point not allowed in scheme: " + c);
5057 } else if ("#" == c) {
5058 this._fragment = "#";
5061 if (EOF != c && " " != c && "\n" != c && "\r" != c) {
5062 this._schemeData += percentEscape(c);
5068 if (!base || !isRelativeScheme(base._scheme)) {
5069 err("Missing scheme.");
5077 case "relative or authority":
5078 if ("/" == c && "/" == input[cursor + 1]) {
5079 state = "authority ignore slashes";
5081 err("Expected /, got: " + c);
5088 this._isRelative = true;
5089 if ("file" != this._scheme) this._scheme = base._scheme;
5091 this._host = base._host;
5092 this._port = base._port;
5093 this._path = base._path.slice();
5094 this._query = base._query;
5095 this._username = base._username;
5096 this._password = base._password;
5098 } else if ("/" == c || "\\" == c) {
5099 if ("\\" == c) err("\\ is an invalid code point.");
5100 state = "relative slash";
5101 } else if ("?" == c) {
5102 this._host = base._host;
5103 this._port = base._port;
5104 this._path = base._path.slice();
5106 this._username = base._username;
5107 this._password = base._password;
5109 } else if ("#" == c) {
5110 this._host = base._host;
5111 this._port = base._port;
5112 this._path = base._path.slice();
5113 this._query = base._query;
5114 this._fragment = "#";
5115 this._username = base._username;
5116 this._password = base._password;
5119 var nextC = input[cursor + 1];
5120 var nextNextC = input[cursor + 2];
5121 if ("file" != this._scheme || !ALPHA.test(c) || nextC != ":" && nextC != "|" || EOF != nextNextC && "/" != nextNextC && "\\" != nextNextC && "?" != nextNextC && "#" != nextNextC) {
5122 this._host = base._host;
5123 this._port = base._port;
5124 this._username = base._username;
5125 this._password = base._password;
5126 this._path = base._path.slice();
5129 state = "relative path";
5134 case "relative slash":
5135 if ("/" == c || "\\" == c) {
5137 err("\\ is an invalid code point.");
5139 if ("file" == this._scheme) {
5140 state = "file host";
5142 state = "authority ignore slashes";
5145 if ("file" != this._scheme) {
5146 this._host = base._host;
5147 this._port = base._port;
5148 this._username = base._username;
5149 this._password = base._password;
5151 state = "relative path";
5156 case "authority first slash":
5158 state = "authority second slash";
5160 err("Expected '/', got: " + c);
5161 state = "authority ignore slashes";
5166 case "authority second slash":
5167 state = "authority ignore slashes";
5169 err("Expected '/', got: " + c);
5174 case "authority ignore slashes":
5175 if ("/" != c && "\\" != c) {
5176 state = "authority";
5179 err("Expected authority, got: " + c);
5186 err("@ already seen.");
5190 for (var i = 0; i < buffer.length; i++) {
5192 if (" " == cp || "\n" == cp || "\r" == cp) {
5193 err("Invalid whitespace in authority.");
5196 if (":" == cp && null === this._password) {
5197 this._password = "";
5200 var tempC = percentEscape(cp);
5201 null !== this._password ? this._password += tempC : this._username += tempC;
5204 } else if (EOF == c || "/" == c || "\\" == c || "?" == c || "#" == c) {
5205 cursor -= buffer.length;
5215 if (EOF == c || "/" == c || "\\" == c || "?" == c || "#" == c) {
5216 if (buffer.length == 2 && ALPHA.test(buffer[0]) && (buffer[1] == ":" || buffer[1] == "|")) {
5217 state = "relative path";
5218 } else if (buffer.length == 0) {
5219 state = "relative path start";
5221 this._host = IDNAToASCII.call(this, buffer);
5223 state = "relative path start";
5226 } else if (" " == c || "\n" == c || "\r" == c) {
5227 err("Invalid whitespace in file host.");
5235 if (":" == c && !seenBracket) {
5236 this._host = IDNAToASCII.call(this, buffer);
5239 if ("hostname" == stateOverride) {
5242 } else if (EOF == c || "/" == c || "\\" == c || "?" == c || "#" == c) {
5243 this._host = IDNAToASCII.call(this, buffer);
5245 state = "relative path start";
5246 if (stateOverride) {
5250 } else if (" " != c && "\n" != c && "\r" != c) {
5253 } else if ("]" == c) {
5254 seenBracket = false;
5258 err("Invalid code point in host/hostname: " + c);
5263 if (/[0-9]/.test(c)) {
5265 } else if (EOF == c || "/" == c || "\\" == c || "?" == c || "#" == c || stateOverride) {
5267 var temp = parseInt(buffer, 10);
5268 if (temp != relative[this._scheme]) {
5269 this._port = temp + "";
5273 if (stateOverride) {
5276 state = "relative path start";
5278 } else if (" " == c || "\n" == c || "\r" == c) {
5279 err("Invalid code point in port: " + c);
5285 case "relative path start":
5286 if ("\\" == c) err("'\\' not allowed in path.");
5287 state = "relative path";
5288 if ("/" != c && "\\" != c) {
5293 case "relative path":
5294 if (EOF == c || "/" == c || "\\" == c || !stateOverride && ("?" == c || "#" == c)) {
5296 err("\\ not allowed in relative path.");
5299 if (tmp = relativePathDotMapping[buffer.toLowerCase()]) {
5302 if (".." == buffer) {
5304 if ("/" != c && "\\" != c) {
5305 this._path.push("");
5307 } else if ("." == buffer && "/" != c && "\\" != c) {
5308 this._path.push("");
5309 } else if ("." != buffer) {
5310 if ("file" == this._scheme && this._path.length == 0 && buffer.length == 2 && ALPHA.test(buffer[0]) && buffer[1] == "|") {
5311 buffer = buffer[0] + ":";
5313 this._path.push(buffer);
5319 } else if ("#" == c) {
5320 this._fragment = "#";
5323 } else if (" " != c && "\n" != c && "\r" != c) {
5324 buffer += percentEscape(c);
5329 if (!stateOverride && "#" == c) {
5330 this._fragment = "#";
5332 } else if (EOF != c && " " != c && "\n" != c && "\r" != c) {
5333 this._query += percentEscapeQuery(c);
5338 if (EOF != c && " " != c && "\n" != c && "\r" != c) {
5339 this._fragment += c;
5348 this._schemeData = "";
5349 this._username = "";
5350 this._password = null;
5355 this._fragment = "";
5356 this._isInvalid = false;
5357 this._isRelative = false;
5359 function jURL(url, base) {
5360 if (base !== undefined && !(base instanceof jURL)) base = new jURL(String(base));
5363 var input = url.replace(/^[ \t\r\n\f]+|[ \t\r\n\f]+$/g, "");
5364 parse.call(this, input, null, base);
5367 toString: function() {
5371 if (this._isInvalid) return this._url;
5373 if ("" != this._username || null != this._password) {
5374 authority = this._username + (null != this._password ? ":" + this._password : "") + "@";
5376 return this.protocol + (this._isRelative ? "//" + authority + this.host : "") + this.pathname + this._query + this._fragment;
5380 parse.call(this, href);
5383 return this._scheme + ":";
5385 set protocol(protocol) {
5386 if (this._isInvalid) return;
5387 parse.call(this, protocol + ":", "scheme start");
5390 return this._isInvalid ? "" : this._port ? this._host + ":" + this._port : this._host;
5393 if (this._isInvalid || !this._isRelative) return;
5394 parse.call(this, host, "host");
5399 set hostname(hostname) {
5400 if (this._isInvalid || !this._isRelative) return;
5401 parse.call(this, hostname, "hostname");
5407 if (this._isInvalid || !this._isRelative) return;
5408 parse.call(this, port, "port");
5411 return this._isInvalid ? "" : this._isRelative ? "/" + this._path.join("/") : this._schemeData;
5413 set pathname(pathname) {
5414 if (this._isInvalid || !this._isRelative) return;
5416 parse.call(this, pathname, "relative path start");
5419 return this._isInvalid || !this._query || "?" == this._query ? "" : this._query;
5421 set search(search) {
5422 if (this._isInvalid || !this._isRelative) return;
5424 if ("?" == search[0]) search = search.slice(1);
5425 parse.call(this, search, "query");
5428 return this._isInvalid || !this._fragment || "#" == this._fragment ? "" : this._fragment;
5431 if (this._isInvalid) return;
5432 this._fragment = "#";
5433 if ("#" == hash[0]) hash = hash.slice(1);
5434 parse.call(this, hash, "fragment");
5438 if (this._isInvalid || !this._scheme) {
5441 switch (this._scheme) {
5452 return this._scheme + "://" + host;
5455 var OriginalURL = scope.URL;
5457 jURL.createObjectURL = function(blob) {
5458 return OriginalURL.createObjectURL.apply(OriginalURL, arguments);
5460 jURL.revokeObjectURL = function(url) {
5461 OriginalURL.revokeObjectURL(url);
5468 if (global.JsMutationObserver) {
5471 var registrationsTable = new WeakMap();
5473 if (/Trident|Edge/.test(navigator.userAgent)) {
5474 setImmediate = setTimeout;
5475 } else if (window.setImmediate) {
5476 setImmediate = window.setImmediate;
5478 var setImmediateQueue = [];
5479 var sentinel = String(Math.random());
5480 window.addEventListener("message", function(e) {
5481 if (e.data === sentinel) {
5482 var queue = setImmediateQueue;
5483 setImmediateQueue = [];
5484 queue.forEach(function(func) {
5489 setImmediate = function(func) {
5490 setImmediateQueue.push(func);
5491 window.postMessage(sentinel, "*");
5494 var isScheduled = false;
5495 var scheduledObservers = [];
5496 function scheduleCallback(observer) {
5497 scheduledObservers.push(observer);
5500 setImmediate(dispatchCallbacks);
5503 function wrapIfNeeded(node) {
5504 return window.ShadowDOMPolyfill && window.ShadowDOMPolyfill.wrapIfNeeded(node) || node;
5506 function dispatchCallbacks() {
5507 isScheduled = false;
5508 var observers = scheduledObservers;
5509 scheduledObservers = [];
5510 observers.sort(function(o1, o2) {
5511 return o1.uid_ - o2.uid_;
5513 var anyNonEmpty = false;
5514 observers.forEach(function(observer) {
5515 var queue = observer.takeRecords();
5516 removeTransientObserversFor(observer);
5518 observer.callback_(queue, observer);
5522 if (anyNonEmpty) dispatchCallbacks();
5524 function removeTransientObserversFor(observer) {
5525 observer.nodes_.forEach(function(node) {
5526 var registrations = registrationsTable.get(node);
5527 if (!registrations) return;
5528 registrations.forEach(function(registration) {
5529 if (registration.observer === observer) registration.removeTransientObservers();
5533 function forEachAncestorAndObserverEnqueueRecord(target, callback) {
5534 for (var node = target; node; node = node.parentNode) {
5535 var registrations = registrationsTable.get(node);
5536 if (registrations) {
5537 for (var j = 0; j < registrations.length; j++) {
5538 var registration = registrations[j];
5539 var options = registration.options;
5540 if (node !== target && !options.subtree) continue;
5541 var record = callback(options);
5542 if (record) registration.enqueue(record);
5548 function JsMutationObserver(callback) {
5549 this.callback_ = callback;
5552 this.uid_ = ++uidCounter;
5554 JsMutationObserver.prototype = {
5555 observe: function(target, options) {
5556 target = wrapIfNeeded(target);
5557 if (!options.childList && !options.attributes && !options.characterData || options.attributeOldValue && !options.attributes || options.attributeFilter && options.attributeFilter.length && !options.attributes || options.characterDataOldValue && !options.characterData) {
5558 throw new SyntaxError();
5560 var registrations = registrationsTable.get(target);
5561 if (!registrations) registrationsTable.set(target, registrations = []);
5563 for (var i = 0; i < registrations.length; i++) {
5564 if (registrations[i].observer === this) {
5565 registration = registrations[i];
5566 registration.removeListeners();
5567 registration.options = options;
5571 if (!registration) {
5572 registration = new Registration(this, target, options);
5573 registrations.push(registration);
5574 this.nodes_.push(target);
5576 registration.addListeners();
5578 disconnect: function() {
5579 this.nodes_.forEach(function(node) {
5580 var registrations = registrationsTable.get(node);
5581 for (var i = 0; i < registrations.length; i++) {
5582 var registration = registrations[i];
5583 if (registration.observer === this) {
5584 registration.removeListeners();
5585 registrations.splice(i, 1);
5592 takeRecords: function() {
5593 var copyOfRecords = this.records_;
5595 return copyOfRecords;
5598 function MutationRecord(type, target) {
5600 this.target = target;
5601 this.addedNodes = [];
5602 this.removedNodes = [];
5603 this.previousSibling = null;
5604 this.nextSibling = null;
5605 this.attributeName = null;
5606 this.attributeNamespace = null;
5607 this.oldValue = null;
5609 function copyMutationRecord(original) {
5610 var record = new MutationRecord(original.type, original.target);
5611 record.addedNodes = original.addedNodes.slice();
5612 record.removedNodes = original.removedNodes.slice();
5613 record.previousSibling = original.previousSibling;
5614 record.nextSibling = original.nextSibling;
5615 record.attributeName = original.attributeName;
5616 record.attributeNamespace = original.attributeNamespace;
5617 record.oldValue = original.oldValue;
5620 var currentRecord, recordWithOldValue;
5621 function getRecord(type, target) {
5622 return currentRecord = new MutationRecord(type, target);
5624 function getRecordWithOldValue(oldValue) {
5625 if (recordWithOldValue) return recordWithOldValue;
5626 recordWithOldValue = copyMutationRecord(currentRecord);
5627 recordWithOldValue.oldValue = oldValue;
5628 return recordWithOldValue;
5630 function clearRecords() {
5631 currentRecord = recordWithOldValue = undefined;
5633 function recordRepresentsCurrentMutation(record) {
5634 return record === recordWithOldValue || record === currentRecord;
5636 function selectRecord(lastRecord, newRecord) {
5637 if (lastRecord === newRecord) return lastRecord;
5638 if (recordWithOldValue && recordRepresentsCurrentMutation(lastRecord)) return recordWithOldValue;
5641 function Registration(observer, target, options) {
5642 this.observer = observer;
5643 this.target = target;
5644 this.options = options;
5645 this.transientObservedNodes = [];
5647 Registration.prototype = {
5648 enqueue: function(record) {
5649 var records = this.observer.records_;
5650 var length = records.length;
5651 if (records.length > 0) {
5652 var lastRecord = records[length - 1];
5653 var recordToReplaceLast = selectRecord(lastRecord, record);
5654 if (recordToReplaceLast) {
5655 records[length - 1] = recordToReplaceLast;
5659 scheduleCallback(this.observer);
5661 records[length] = record;
5663 addListeners: function() {
5664 this.addListeners_(this.target);
5666 addListeners_: function(node) {
5667 var options = this.options;
5668 if (options.attributes) node.addEventListener("DOMAttrModified", this, true);
5669 if (options.characterData) node.addEventListener("DOMCharacterDataModified", this, true);
5670 if (options.childList) node.addEventListener("DOMNodeInserted", this, true);
5671 if (options.childList || options.subtree) node.addEventListener("DOMNodeRemoved", this, true);
5673 removeListeners: function() {
5674 this.removeListeners_(this.target);
5676 removeListeners_: function(node) {
5677 var options = this.options;
5678 if (options.attributes) node.removeEventListener("DOMAttrModified", this, true);
5679 if (options.characterData) node.removeEventListener("DOMCharacterDataModified", this, true);
5680 if (options.childList) node.removeEventListener("DOMNodeInserted", this, true);
5681 if (options.childList || options.subtree) node.removeEventListener("DOMNodeRemoved", this, true);
5683 addTransientObserver: function(node) {
5684 if (node === this.target) return;
5685 this.addListeners_(node);
5686 this.transientObservedNodes.push(node);
5687 var registrations = registrationsTable.get(node);
5688 if (!registrations) registrationsTable.set(node, registrations = []);
5689 registrations.push(this);
5691 removeTransientObservers: function() {
5692 var transientObservedNodes = this.transientObservedNodes;
5693 this.transientObservedNodes = [];
5694 transientObservedNodes.forEach(function(node) {
5695 this.removeListeners_(node);
5696 var registrations = registrationsTable.get(node);
5697 for (var i = 0; i < registrations.length; i++) {
5698 if (registrations[i] === this) {
5699 registrations.splice(i, 1);
5705 handleEvent: function(e) {
5706 e.stopImmediatePropagation();
5708 case "DOMAttrModified":
5709 var name = e.attrName;
5710 var namespace = e.relatedNode.namespaceURI;
5711 var target = e.target;
5712 var record = new getRecord("attributes", target);
5713 record.attributeName = name;
5714 record.attributeNamespace = namespace;
5715 var oldValue = e.attrChange === MutationEvent.ADDITION ? null : e.prevValue;
5716 forEachAncestorAndObserverEnqueueRecord(target, function(options) {
5717 if (!options.attributes) return;
5718 if (options.attributeFilter && options.attributeFilter.length && options.attributeFilter.indexOf(name) === -1 && options.attributeFilter.indexOf(namespace) === -1) {
5721 if (options.attributeOldValue) return getRecordWithOldValue(oldValue);
5726 case "DOMCharacterDataModified":
5727 var target = e.target;
5728 var record = getRecord("characterData", target);
5729 var oldValue = e.prevValue;
5730 forEachAncestorAndObserverEnqueueRecord(target, function(options) {
5731 if (!options.characterData) return;
5732 if (options.characterDataOldValue) return getRecordWithOldValue(oldValue);
5737 case "DOMNodeRemoved":
5738 this.addTransientObserver(e.target);
5740 case "DOMNodeInserted":
5741 var changedNode = e.target;
5742 var addedNodes, removedNodes;
5743 if (e.type === "DOMNodeInserted") {
5744 addedNodes = [ changedNode ];
5748 removedNodes = [ changedNode ];
5750 var previousSibling = changedNode.previousSibling;
5751 var nextSibling = changedNode.nextSibling;
5752 var record = getRecord("childList", e.target.parentNode);
5753 record.addedNodes = addedNodes;
5754 record.removedNodes = removedNodes;
5755 record.previousSibling = previousSibling;
5756 record.nextSibling = nextSibling;
5757 forEachAncestorAndObserverEnqueueRecord(e.relatedNode, function(options) {
5758 if (!options.childList) return;
5765 global.JsMutationObserver = JsMutationObserver;
5766 if (!global.MutationObserver) {
5767 global.MutationObserver = JsMutationObserver;
5768 JsMutationObserver._isPolyfilled = true;
5774 if (!window.performance) {
5775 var start = Date.now();
5776 window.performance = {
5778 return Date.now() - start;
5782 if (!window.requestAnimationFrame) {
5783 window.requestAnimationFrame = function() {
5784 var nativeRaf = window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame;
5785 return nativeRaf ? function(callback) {
5786 return nativeRaf(function() {
5787 callback(performance.now());
5789 } : function(callback) {
5790 return window.setTimeout(callback, 1e3 / 60);
5794 if (!window.cancelAnimationFrame) {
5795 window.cancelAnimationFrame = function() {
5796 return window.webkitCancelAnimationFrame || window.mozCancelAnimationFrame || function(id) {
5801 var workingDefaultPrevented = function() {
5802 var e = document.createEvent("Event");
5803 e.initEvent("foo", true, true);
5805 return e.defaultPrevented;
5807 if (!workingDefaultPrevented) {
5808 var origPreventDefault = Event.prototype.preventDefault;
5809 Event.prototype.preventDefault = function() {
5810 if (!this.cancelable) {
5813 origPreventDefault.call(this);
5814 Object.defineProperty(this, "defaultPrevented", {
5822 var isIE = /Trident/.test(navigator.userAgent);
5823 if (!window.CustomEvent || isIE && typeof window.CustomEvent !== "function") {
5824 window.CustomEvent = function(inType, params) {
5825 params = params || {};
5826 var e = document.createEvent("CustomEvent");
5827 e.initCustomEvent(inType, Boolean(params.bubbles), Boolean(params.cancelable), params.detail);
5830 window.CustomEvent.prototype = window.Event.prototype;
5832 if (!window.Event || isIE && typeof window.Event !== "function") {
5833 var origEvent = window.Event;
5834 window.Event = function(inType, params) {
5835 params = params || {};
5836 var e = document.createEvent("Event");
5837 e.initEvent(inType, Boolean(params.bubbles), Boolean(params.cancelable));
5840 window.Event.prototype = origEvent.prototype;
5842 })(window.WebComponents);
5844 window.HTMLImports = window.HTMLImports || {
5849 var IMPORT_LINK_TYPE = "import";
5850 var useNative = Boolean(IMPORT_LINK_TYPE in document.createElement("link"));
5851 var hasShadowDOMPolyfill = Boolean(window.ShadowDOMPolyfill);
5852 var wrap = function(node) {
5853 return hasShadowDOMPolyfill ? window.ShadowDOMPolyfill.wrapIfNeeded(node) : node;
5855 var rootDocument = wrap(document);
5856 var currentScriptDescriptor = {
5858 var script = window.HTMLImports.currentScript || document.currentScript || (document.readyState !== "complete" ? document.scripts[document.scripts.length - 1] : null);
5859 return wrap(script);
5863 Object.defineProperty(document, "_currentScript", currentScriptDescriptor);
5864 Object.defineProperty(rootDocument, "_currentScript", currentScriptDescriptor);
5865 var isIE = /Trident/.test(navigator.userAgent);
5866 function whenReady(callback, doc) {
5867 doc = doc || rootDocument;
5868 whenDocumentReady(function() {
5869 watchImportsLoad(callback, doc);
5872 var requiredReadyState = isIE ? "complete" : "interactive";
5873 var READY_EVENT = "readystatechange";
5874 function isDocumentReady(doc) {
5875 return doc.readyState === "complete" || doc.readyState === requiredReadyState;
5877 function whenDocumentReady(callback, doc) {
5878 if (!isDocumentReady(doc)) {
5879 var checkReady = function() {
5880 if (doc.readyState === "complete" || doc.readyState === requiredReadyState) {
5881 doc.removeEventListener(READY_EVENT, checkReady);
5882 whenDocumentReady(callback, doc);
5885 doc.addEventListener(READY_EVENT, checkReady);
5886 } else if (callback) {
5890 function markTargetLoaded(event) {
5891 event.target.__loaded = true;
5893 function watchImportsLoad(callback, doc) {
5894 var imports = doc.querySelectorAll("link[rel=import]");
5895 var parsedCount = 0, importCount = imports.length, newImports = [], errorImports = [];
5896 function checkDone() {
5897 if (parsedCount == importCount && callback) {
5899 allImports: imports,
5900 loadedImports: newImports,
5901 errorImports: errorImports
5905 function loadedImport(e) {
5906 markTargetLoaded(e);
5907 newImports.push(this);
5911 function errorLoadingImport(e) {
5912 errorImports.push(this);
5917 for (var i = 0, imp; i < importCount && (imp = imports[i]); i++) {
5918 if (isImportLoaded(imp)) {
5919 newImports.push(this);
5923 imp.addEventListener("load", loadedImport);
5924 imp.addEventListener("error", errorLoadingImport);
5931 function isImportLoaded(link) {
5932 return useNative ? link.__loaded || link.import && link.import.readyState !== "loading" : link.__importParsed;
5935 new MutationObserver(function(mxns) {
5936 for (var i = 0, l = mxns.length, m; i < l && (m = mxns[i]); i++) {
5938 handleImports(m.addedNodes);
5941 }).observe(document.head, {
5944 function handleImports(nodes) {
5945 for (var i = 0, l = nodes.length, n; i < l && (n = nodes[i]); i++) {
5951 function isImport(element) {
5952 return element.localName === "link" && element.rel === "import";
5954 function handleImport(element) {
5955 var loaded = element.import;
5961 element.addEventListener("load", markTargetLoaded);
5962 element.addEventListener("error", markTargetLoaded);
5966 if (document.readyState === "loading") {
5967 var imports = document.querySelectorAll("link[rel=import]");
5968 for (var i = 0, l = imports.length, imp; i < l && (imp = imports[i]); i++) {
5974 whenReady(function(detail) {
5975 window.HTMLImports.ready = true;
5976 window.HTMLImports.readyTime = new Date().getTime();
5977 var evt = rootDocument.createEvent("CustomEvent");
5978 evt.initCustomEvent("HTMLImportsLoaded", true, true, detail);
5979 rootDocument.dispatchEvent(evt);
5981 scope.IMPORT_LINK_TYPE = IMPORT_LINK_TYPE;
5982 scope.useNative = useNative;
5983 scope.rootDocument = rootDocument;
5984 scope.whenReady = whenReady;
5986 })(window.HTMLImports);
5990 var addModule = function(module) {
5991 modules.push(module);
5993 var initializeModules = function() {
5994 modules.forEach(function(module) {
5998 scope.addModule = addModule;
5999 scope.initializeModules = initializeModules;
6000 })(window.HTMLImports);
6002 window.HTMLImports.addModule(function(scope) {
6003 var CSS_URL_REGEXP = /(url\()([^)]*)(\))/g;
6004 var CSS_IMPORT_REGEXP = /(@import[\s]+(?!url\())([^;]*)(;)/g;
6006 resolveUrlsInStyle: function(style, linkUrl) {
6007 var doc = style.ownerDocument;
6008 var resolver = doc.createElement("a");
6009 style.textContent = this.resolveUrlsInCssText(style.textContent, linkUrl, resolver);
6012 resolveUrlsInCssText: function(cssText, linkUrl, urlObj) {
6013 var r = this.replaceUrls(cssText, urlObj, linkUrl, CSS_URL_REGEXP);
6014 r = this.replaceUrls(r, urlObj, linkUrl, CSS_IMPORT_REGEXP);
6017 replaceUrls: function(text, urlObj, linkUrl, regexp) {
6018 return text.replace(regexp, function(m, pre, url, post) {
6019 var urlPath = url.replace(/["']/g, "");
6021 urlPath = new URL(urlPath, linkUrl).href;
6023 urlObj.href = urlPath;
6024 urlPath = urlObj.href;
6025 return pre + "'" + urlPath + "'" + post;
6032 window.HTMLImports.addModule(function(scope) {
6035 ok: function(request) {
6036 return request.status >= 200 && request.status < 300 || request.status === 304 || request.status === 0;
6038 load: function(url, next, nextContext) {
6039 var request = new XMLHttpRequest();
6040 if (scope.flags.debug || scope.flags.bust) {
6041 url += "?" + Math.random();
6043 request.open("GET", url, xhr.async);
6044 request.addEventListener("readystatechange", function(e) {
6045 if (request.readyState === 4) {
6046 var redirectedUrl = null;
6048 var locationHeader = request.getResponseHeader("Location");
6049 if (locationHeader) {
6050 redirectedUrl = locationHeader.substr(0, 1) === "/" ? location.origin + locationHeader : locationHeader;
6053 console.error(e.message);
6055 next.call(nextContext, !xhr.ok(request) && request, request.response || request.responseText, redirectedUrl);
6061 loadDocument: function(url, next, nextContext) {
6062 this.load(url, next, nextContext).responseType = "document";
6068 window.HTMLImports.addModule(function(scope) {
6069 var xhr = scope.xhr;
6070 var flags = scope.flags;
6071 var Loader = function(onLoad, onComplete) {
6073 this.onload = onLoad;
6074 this.oncomplete = onComplete;
6078 Loader.prototype = {
6079 addNodes: function(nodes) {
6080 this.inflight += nodes.length;
6081 for (var i = 0, l = nodes.length, n; i < l && (n = nodes[i]); i++) {
6086 addNode: function(node) {
6091 require: function(elt) {
6092 var url = elt.src || elt.href;
6093 elt.__nodeUrl = url;
6094 if (!this.dedupe(url, elt)) {
6095 this.fetch(url, elt);
6098 dedupe: function(url, elt) {
6099 if (this.pending[url]) {
6100 this.pending[url].push(elt);
6104 if (this.cache[url]) {
6105 this.onload(url, elt, this.cache[url]);
6109 this.pending[url] = [ elt ];
6112 fetch: function(url, elt) {
6113 flags.load && console.log("fetch", url, elt);
6115 setTimeout(function() {
6116 this.receive(url, elt, {
6117 error: "href must be specified"
6120 } else if (url.match(/^data:/)) {
6121 var pieces = url.split(",");
6122 var header = pieces[0];
6123 var body = pieces[1];
6124 if (header.indexOf(";base64") > -1) {
6127 body = decodeURIComponent(body);
6129 setTimeout(function() {
6130 this.receive(url, elt, null, body);
6133 var receiveXhr = function(err, resource, redirectedUrl) {
6134 this.receive(url, elt, err, resource, redirectedUrl);
6136 xhr.load(url, receiveXhr);
6139 receive: function(url, elt, err, resource, redirectedUrl) {
6140 this.cache[url] = resource;
6141 var $p = this.pending[url];
6142 for (var i = 0, l = $p.length, p; i < l && (p = $p[i]); i++) {
6143 this.onload(url, p, resource, err, redirectedUrl);
6146 this.pending[url] = null;
6152 checkDone: function() {
6153 if (!this.inflight) {
6158 scope.Loader = Loader;
6161 window.HTMLImports.addModule(function(scope) {
6162 var Observer = function(addCallback) {
6163 this.addCallback = addCallback;
6164 this.mo = new MutationObserver(this.handler.bind(this));
6166 Observer.prototype = {
6167 handler: function(mutations) {
6168 for (var i = 0, l = mutations.length, m; i < l && (m = mutations[i]); i++) {
6169 if (m.type === "childList" && m.addedNodes.length) {
6170 this.addedNodes(m.addedNodes);
6174 addedNodes: function(nodes) {
6175 if (this.addCallback) {
6176 this.addCallback(nodes);
6178 for (var i = 0, l = nodes.length, n, loading; i < l && (n = nodes[i]); i++) {
6179 if (n.children && n.children.length) {
6180 this.addedNodes(n.children);
6184 observe: function(root) {
6185 this.mo.observe(root, {
6191 scope.Observer = Observer;
6194 window.HTMLImports.addModule(function(scope) {
6195 var path = scope.path;
6196 var rootDocument = scope.rootDocument;
6197 var flags = scope.flags;
6198 var isIE = scope.isIE;
6199 var IMPORT_LINK_TYPE = scope.IMPORT_LINK_TYPE;
6200 var IMPORT_SELECTOR = "link[rel=" + IMPORT_LINK_TYPE + "]";
6201 var importParser = {
6202 documentSelectors: IMPORT_SELECTOR,
6203 importsSelectors: [ IMPORT_SELECTOR, "link[rel=stylesheet]:not([type])", "style:not([type])", "script:not([type])", 'script[type="application/javascript"]', 'script[type="text/javascript"]' ].join(","),
6206 script: "parseScript",
6209 dynamicElements: [],
6210 parseNext: function() {
6211 var next = this.nextToParse();
6216 parse: function(elt) {
6217 if (this.isParsed(elt)) {
6218 flags.parse && console.log("[%s] is already parsed", elt.localName);
6221 var fn = this[this.map[elt.localName]];
6223 this.markParsing(elt);
6227 parseDynamic: function(elt, quiet) {
6228 this.dynamicElements.push(elt);
6233 markParsing: function(elt) {
6234 flags.parse && console.log("parsing", elt);
6235 this.parsingElement = elt;
6237 markParsingComplete: function(elt) {
6238 elt.__importParsed = true;
6239 this.markDynamicParsingComplete(elt);
6240 if (elt.__importElement) {
6241 elt.__importElement.__importParsed = true;
6242 this.markDynamicParsingComplete(elt.__importElement);
6244 this.parsingElement = null;
6245 flags.parse && console.log("completed", elt);
6247 markDynamicParsingComplete: function(elt) {
6248 var i = this.dynamicElements.indexOf(elt);
6250 this.dynamicElements.splice(i, 1);
6253 parseImport: function(elt) {
6254 elt.import = elt.__doc;
6255 if (window.HTMLImports.__importsParsingHook) {
6256 window.HTMLImports.__importsParsingHook(elt);
6259 elt.import.__importParsed = true;
6261 this.markParsingComplete(elt);
6262 if (elt.__resource && !elt.__error) {
6263 elt.dispatchEvent(new CustomEvent("load", {
6267 elt.dispatchEvent(new CustomEvent("error", {
6271 if (elt.__pending) {
6273 while (elt.__pending.length) {
6274 fn = elt.__pending.shift();
6284 parseLink: function(linkElt) {
6285 if (nodeIsImport(linkElt)) {
6286 this.parseImport(linkElt);
6288 linkElt.href = linkElt.href;
6289 this.parseGeneric(linkElt);
6292 parseStyle: function(elt) {
6294 elt = cloneStyle(elt);
6295 src.__appliedElement = elt;
6296 elt.__importElement = src;
6297 this.parseGeneric(elt);
6299 parseGeneric: function(elt) {
6300 this.trackElement(elt);
6301 this.addElementToDocument(elt);
6303 rootImportForElement: function(elt) {
6305 while (n.ownerDocument.__importLink) {
6306 n = n.ownerDocument.__importLink;
6310 addElementToDocument: function(elt) {
6311 var port = this.rootImportForElement(elt.__importElement || elt);
6312 port.parentNode.insertBefore(elt, port);
6314 trackElement: function(elt, callback) {
6316 var done = function(e) {
6317 elt.removeEventListener("load", done);
6318 elt.removeEventListener("error", done);
6322 self.markParsingComplete(elt);
6325 elt.addEventListener("load", done);
6326 elt.addEventListener("error", done);
6327 if (isIE && elt.localName === "style") {
6328 var fakeLoad = false;
6329 if (elt.textContent.indexOf("@import") == -1) {
6331 } else if (elt.sheet) {
6333 var csr = elt.sheet.cssRules;
6334 var len = csr ? csr.length : 0;
6335 for (var i = 0, r; i < len && (r = csr[i]); i++) {
6336 if (r.type === CSSRule.IMPORT_RULE) {
6337 fakeLoad = fakeLoad && Boolean(r.styleSheet);
6342 setTimeout(function() {
6343 elt.dispatchEvent(new CustomEvent("load", {
6350 parseScript: function(scriptElt) {
6351 var script = document.createElement("script");
6352 script.__importElement = scriptElt;
6353 script.src = scriptElt.src ? scriptElt.src : generateScriptDataUrl(scriptElt);
6354 scope.currentScript = scriptElt;
6355 this.trackElement(script, function(e) {
6356 if (script.parentNode) {
6357 script.parentNode.removeChild(script);
6359 scope.currentScript = null;
6361 this.addElementToDocument(script);
6363 nextToParse: function() {
6364 this._mayParse = [];
6365 return !this.parsingElement && (this.nextToParseInDoc(rootDocument) || this.nextToParseDynamic());
6367 nextToParseInDoc: function(doc, link) {
6368 if (doc && this._mayParse.indexOf(doc) < 0) {
6369 this._mayParse.push(doc);
6370 var nodes = doc.querySelectorAll(this.parseSelectorsForNode(doc));
6371 for (var i = 0, l = nodes.length, p = 0, n; i < l && (n = nodes[i]); i++) {
6372 if (!this.isParsed(n)) {
6373 if (this.hasResource(n)) {
6374 return nodeIsImport(n) ? this.nextToParseInDoc(n.__doc, n) : n;
6383 nextToParseDynamic: function() {
6384 return this.dynamicElements[0];
6386 parseSelectorsForNode: function(node) {
6387 var doc = node.ownerDocument || node;
6388 return doc === rootDocument ? this.documentSelectors : this.importsSelectors;
6390 isParsed: function(node) {
6391 return node.__importParsed;
6393 needsDynamicParsing: function(elt) {
6394 return this.dynamicElements.indexOf(elt) >= 0;
6396 hasResource: function(node) {
6397 if (nodeIsImport(node) && node.__doc === undefined) {
6403 function nodeIsImport(elt) {
6404 return elt.localName === "link" && elt.rel === IMPORT_LINK_TYPE;
6406 function generateScriptDataUrl(script) {
6407 var scriptContent = generateScriptContent(script);
6408 return "data:text/javascript;charset=utf-8," + encodeURIComponent(scriptContent);
6410 function generateScriptContent(script) {
6411 return script.textContent + generateSourceMapHint(script);
6413 function generateSourceMapHint(script) {
6414 var owner = script.ownerDocument;
6415 owner.__importedScripts = owner.__importedScripts || 0;
6416 var moniker = script.ownerDocument.baseURI;
6417 var num = owner.__importedScripts ? "-" + owner.__importedScripts : "";
6418 owner.__importedScripts++;
6419 return "\n//# sourceURL=" + moniker + num + ".js\n";
6421 function cloneStyle(style) {
6422 var clone = style.ownerDocument.createElement("style");
6423 clone.textContent = style.textContent;
6424 path.resolveUrlsInStyle(clone);
6427 scope.parser = importParser;
6428 scope.IMPORT_SELECTOR = IMPORT_SELECTOR;
6431 window.HTMLImports.addModule(function(scope) {
6432 var flags = scope.flags;
6433 var IMPORT_LINK_TYPE = scope.IMPORT_LINK_TYPE;
6434 var IMPORT_SELECTOR = scope.IMPORT_SELECTOR;
6435 var rootDocument = scope.rootDocument;
6436 var Loader = scope.Loader;
6437 var Observer = scope.Observer;
6438 var parser = scope.parser;
6441 documentPreloadSelectors: IMPORT_SELECTOR,
6442 importsPreloadSelectors: [ IMPORT_SELECTOR ].join(","),
6443 loadNode: function(node) {
6444 importLoader.addNode(node);
6446 loadSubtree: function(parent) {
6447 var nodes = this.marshalNodes(parent);
6448 importLoader.addNodes(nodes);
6450 marshalNodes: function(parent) {
6451 return parent.querySelectorAll(this.loadSelectorsForNode(parent));
6453 loadSelectorsForNode: function(node) {
6454 var doc = node.ownerDocument || node;
6455 return doc === rootDocument ? this.documentPreloadSelectors : this.importsPreloadSelectors;
6457 loaded: function(url, elt, resource, err, redirectedUrl) {
6458 flags.load && console.log("loaded", url, elt);
6459 elt.__resource = resource;
6461 if (isImportLink(elt)) {
6462 var doc = this.documents[url];
6463 if (doc === undefined) {
6464 doc = err ? null : makeDocument(resource, redirectedUrl || url);
6466 doc.__importLink = elt;
6467 this.bootDocument(doc);
6469 this.documents[url] = doc;
6475 bootDocument: function(doc) {
6476 this.loadSubtree(doc);
6477 this.observer.observe(doc);
6480 loadedAll: function() {
6484 var importLoader = new Loader(importer.loaded.bind(importer), importer.loadedAll.bind(importer));
6485 importer.observer = new Observer();
6486 function isImportLink(elt) {
6487 return isLinkRel(elt, IMPORT_LINK_TYPE);
6489 function isLinkRel(elt, rel) {
6490 return elt.localName === "link" && elt.getAttribute("rel") === rel;
6492 function hasBaseURIAccessor(doc) {
6493 return !!Object.getOwnPropertyDescriptor(doc, "baseURI");
6495 function makeDocument(resource, url) {
6496 var doc = document.implementation.createHTMLDocument(IMPORT_LINK_TYPE);
6498 var base = doc.createElement("base");
6499 base.setAttribute("href", url);
6500 if (!doc.baseURI && !hasBaseURIAccessor(doc)) {
6501 Object.defineProperty(doc, "baseURI", {
6505 var meta = doc.createElement("meta");
6506 meta.setAttribute("charset", "utf-8");
6507 doc.head.appendChild(meta);
6508 doc.head.appendChild(base);
6509 doc.body.innerHTML = resource;
6510 if (window.HTMLTemplateElement && HTMLTemplateElement.bootstrap) {
6511 HTMLTemplateElement.bootstrap(doc);
6515 if (!document.baseURI) {
6516 var baseURIDescriptor = {
6518 var base = document.querySelector("base");
6519 return base ? base.href : window.location.href;
6523 Object.defineProperty(document, "baseURI", baseURIDescriptor);
6524 Object.defineProperty(rootDocument, "baseURI", baseURIDescriptor);
6526 scope.importer = importer;
6527 scope.importLoader = importLoader;
6530 window.HTMLImports.addModule(function(scope) {
6531 var parser = scope.parser;
6532 var importer = scope.importer;
6534 added: function(nodes) {
6535 var owner, parsed, loading;
6536 for (var i = 0, l = nodes.length, n; i < l && (n = nodes[i]); i++) {
6538 owner = n.ownerDocument;
6539 parsed = parser.isParsed(owner);
6541 loading = this.shouldLoadNode(n);
6543 importer.loadNode(n);
6545 if (this.shouldParseNode(n) && parsed) {
6546 parser.parseDynamic(n, loading);
6550 shouldLoadNode: function(node) {
6551 return node.nodeType === 1 && matches.call(node, importer.loadSelectorsForNode(node));
6553 shouldParseNode: function(node) {
6554 return node.nodeType === 1 && matches.call(node, parser.parseSelectorsForNode(node));
6557 importer.observer.addCallback = dynamic.added.bind(dynamic);
6558 var matches = HTMLElement.prototype.matches || HTMLElement.prototype.matchesSelector || HTMLElement.prototype.webkitMatchesSelector || HTMLElement.prototype.mozMatchesSelector || HTMLElement.prototype.msMatchesSelector;
6562 var initializeModules = scope.initializeModules;
6563 var isIE = scope.isIE;
6564 if (scope.useNative) {
6567 initializeModules();
6568 var rootDocument = scope.rootDocument;
6569 function bootstrap() {
6570 window.HTMLImports.importer.bootDocument(rootDocument);
6572 if (document.readyState === "complete" || document.readyState === "interactive" && !window.attachEvent) {
6575 document.addEventListener("DOMContentLoaded", bootstrap);
6577 })(window.HTMLImports);
6579 window.CustomElements = window.CustomElements || {
6584 var flags = scope.flags;
6586 var addModule = function(module) {
6587 modules.push(module);
6589 var initializeModules = function() {
6590 modules.forEach(function(module) {
6594 scope.addModule = addModule;
6595 scope.initializeModules = initializeModules;
6596 scope.hasNative = Boolean(document.registerElement);
6597 scope.isIE = /Trident/.test(navigator.userAgent);
6598 scope.useNative = !flags.register && scope.hasNative && !window.ShadowDOMPolyfill && (!window.HTMLImports || window.HTMLImports.useNative);
6599 })(window.CustomElements);
6601 window.CustomElements.addModule(function(scope) {
6602 var IMPORT_LINK_TYPE = window.HTMLImports ? window.HTMLImports.IMPORT_LINK_TYPE : "none";
6603 function forSubtree(node, cb) {
6604 findAllElements(node, function(e) {
6612 function findAllElements(node, find, data) {
6613 var e = node.firstElementChild;
6615 e = node.firstChild;
6616 while (e && e.nodeType !== Node.ELEMENT_NODE) {
6621 if (find(e, data) !== true) {
6622 findAllElements(e, find, data);
6624 e = e.nextElementSibling;
6628 function forRoots(node, cb) {
6629 var root = node.shadowRoot;
6631 forSubtree(root, cb);
6632 root = root.olderShadowRoot;
6635 function forDocumentTree(doc, cb) {
6636 _forDocumentTree(doc, cb, []);
6638 function _forDocumentTree(doc, cb, processingDocuments) {
6639 doc = window.wrap(doc);
6640 if (processingDocuments.indexOf(doc) >= 0) {
6643 processingDocuments.push(doc);
6644 var imports = doc.querySelectorAll("link[rel=" + IMPORT_LINK_TYPE + "]");
6645 for (var i = 0, l = imports.length, n; i < l && (n = imports[i]); i++) {
6647 _forDocumentTree(n.import, cb, processingDocuments);
6652 scope.forDocumentTree = forDocumentTree;
6653 scope.forSubtree = forSubtree;
6656 window.CustomElements.addModule(function(scope) {
6657 var flags = scope.flags;
6658 var forSubtree = scope.forSubtree;
6659 var forDocumentTree = scope.forDocumentTree;
6660 function addedNode(node, isAttached) {
6661 return added(node, isAttached) || addedSubtree(node, isAttached);
6663 function added(node, isAttached) {
6664 if (scope.upgrade(node, isAttached)) {
6671 function addedSubtree(node, isAttached) {
6672 forSubtree(node, function(e) {
6673 if (added(e, isAttached)) {
6678 var hasThrottledAttached = window.MutationObserver._isPolyfilled && flags["throttle-attached"];
6679 scope.hasPolyfillMutations = hasThrottledAttached;
6680 scope.hasThrottledAttached = hasThrottledAttached;
6681 var isPendingMutations = false;
6682 var pendingMutations = [];
6683 function deferMutation(fn) {
6684 pendingMutations.push(fn);
6685 if (!isPendingMutations) {
6686 isPendingMutations = true;
6687 setTimeout(takeMutations);
6690 function takeMutations() {
6691 isPendingMutations = false;
6692 var $p = pendingMutations;
6693 for (var i = 0, l = $p.length, p; i < l && (p = $p[i]); i++) {
6696 pendingMutations = [];
6698 function attached(element) {
6699 if (hasThrottledAttached) {
6700 deferMutation(function() {
6707 function _attached(element) {
6708 if (element.__upgraded__ && !element.__attached) {
6709 element.__attached = true;
6710 if (element.attachedCallback) {
6711 element.attachedCallback();
6715 function detachedNode(node) {
6717 forSubtree(node, function(e) {
6721 function detached(element) {
6722 if (hasThrottledAttached) {
6723 deferMutation(function() {
6730 function _detached(element) {
6731 if (element.__upgraded__ && element.__attached) {
6732 element.__attached = false;
6733 if (element.detachedCallback) {
6734 element.detachedCallback();
6738 function inDocument(element) {
6740 var doc = window.wrap(document);
6745 p = p.parentNode || p.nodeType === Node.DOCUMENT_FRAGMENT_NODE && p.host;
6748 function watchShadow(node) {
6749 if (node.shadowRoot && !node.shadowRoot.__watched) {
6750 flags.dom && console.log("watching shadow-root for: ", node.localName);
6751 var root = node.shadowRoot;
6754 root = root.olderShadowRoot;
6758 function handler(root, mutations) {
6760 var mx = mutations[0];
6761 if (mx && mx.type === "childList" && mx.addedNodes) {
6762 if (mx.addedNodes) {
6763 var d = mx.addedNodes[0];
6764 while (d && d !== document && !d.host) {
6767 var u = d && (d.URL || d._URL || d.host && d.host.localName) || "";
6768 u = u.split("/?").shift().split("/").pop();
6771 console.group("mutations (%d) [%s]", mutations.length, u || "");
6773 var isAttached = inDocument(root);
6774 mutations.forEach(function(mx) {
6775 if (mx.type === "childList") {
6776 forEach(mx.addedNodes, function(n) {
6780 addedNode(n, isAttached);
6782 forEach(mx.removedNodes, function(n) {
6790 flags.dom && console.groupEnd();
6792 function takeRecords(node) {
6793 node = window.wrap(node);
6795 node = window.wrap(document);
6797 while (node.parentNode) {
6798 node = node.parentNode;
6800 var observer = node.__observer;
6802 handler(node, observer.takeRecords());
6806 var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);
6807 function observe(inRoot) {
6808 if (inRoot.__observer) {
6811 var observer = new MutationObserver(handler.bind(this, inRoot));
6812 observer.observe(inRoot, {
6816 inRoot.__observer = observer;
6818 function upgradeDocument(doc) {
6819 doc = window.wrap(doc);
6820 flags.dom && console.group("upgradeDocument: ", doc.baseURI.split("/").pop());
6821 var isMainDocument = doc === window.wrap(document);
6822 addedNode(doc, isMainDocument);
6824 flags.dom && console.groupEnd();
6826 function upgradeDocumentTree(doc) {
6827 forDocumentTree(doc, upgradeDocument);
6829 var originalCreateShadowRoot = Element.prototype.createShadowRoot;
6830 if (originalCreateShadowRoot) {
6831 Element.prototype.createShadowRoot = function() {
6832 var root = originalCreateShadowRoot.call(this);
6833 window.CustomElements.watchShadow(this);
6837 scope.watchShadow = watchShadow;
6838 scope.upgradeDocumentTree = upgradeDocumentTree;
6839 scope.upgradeDocument = upgradeDocument;
6840 scope.upgradeSubtree = addedSubtree;
6841 scope.upgradeAll = addedNode;
6842 scope.attached = attached;
6843 scope.takeRecords = takeRecords;
6846 window.CustomElements.addModule(function(scope) {
6847 var flags = scope.flags;
6848 function upgrade(node, isAttached) {
6849 if (node.localName === "template") {
6850 if (window.HTMLTemplateElement && HTMLTemplateElement.decorate) {
6851 HTMLTemplateElement.decorate(node);
6854 if (!node.__upgraded__ && node.nodeType === Node.ELEMENT_NODE) {
6855 var is = node.getAttribute("is");
6856 var definition = scope.getRegisteredDefinition(node.localName) || scope.getRegisteredDefinition(is);
6858 if (is && definition.tag == node.localName || !is && !definition.extends) {
6859 return upgradeWithDefinition(node, definition, isAttached);
6864 function upgradeWithDefinition(element, definition, isAttached) {
6865 flags.upgrade && console.group("upgrade:", element.localName);
6866 if (definition.is) {
6867 element.setAttribute("is", definition.is);
6869 implementPrototype(element, definition);
6870 element.__upgraded__ = true;
6873 scope.attached(element);
6875 scope.upgradeSubtree(element, isAttached);
6876 flags.upgrade && console.groupEnd();
6879 function implementPrototype(element, definition) {
6880 if (Object.__proto__) {
6881 element.__proto__ = definition.prototype;
6883 customMixin(element, definition.prototype, definition.native);
6884 element.__proto__ = definition.prototype;
6887 function customMixin(inTarget, inSrc, inNative) {
6890 while (p !== inNative && p !== HTMLElement.prototype) {
6891 var keys = Object.getOwnPropertyNames(p);
6892 for (var i = 0, k; k = keys[i]; i++) {
6894 Object.defineProperty(inTarget, k, Object.getOwnPropertyDescriptor(p, k));
6898 p = Object.getPrototypeOf(p);
6901 function created(element) {
6902 if (element.createdCallback) {
6903 element.createdCallback();
6906 scope.upgrade = upgrade;
6907 scope.upgradeWithDefinition = upgradeWithDefinition;
6908 scope.implementPrototype = implementPrototype;
6911 window.CustomElements.addModule(function(scope) {
6912 var isIE = scope.isIE;
6913 var upgradeDocumentTree = scope.upgradeDocumentTree;
6914 var upgradeAll = scope.upgradeAll;
6915 var upgradeWithDefinition = scope.upgradeWithDefinition;
6916 var implementPrototype = scope.implementPrototype;
6917 var useNative = scope.useNative;
6918 function register(name, options) {
6919 var definition = options || {};
6921 throw new Error("document.registerElement: first argument `name` must not be empty");
6923 if (name.indexOf("-") < 0) {
6924 throw new Error("document.registerElement: first argument ('name') must contain a dash ('-'). Argument provided was '" + String(name) + "'.");
6926 if (isReservedTag(name)) {
6927 throw new Error("Failed to execute 'registerElement' on 'Document': Registration failed for type '" + String(name) + "'. The type name is invalid.");
6929 if (getRegisteredDefinition(name)) {
6930 throw new Error("DuplicateDefinitionError: a type with name '" + String(name) + "' is already registered");
6932 if (!definition.prototype) {
6933 definition.prototype = Object.create(HTMLElement.prototype);
6935 definition.__name = name.toLowerCase();
6936 definition.lifecycle = definition.lifecycle || {};
6937 definition.ancestry = ancestry(definition.extends);
6938 resolveTagName(definition);
6939 resolvePrototypeChain(definition);
6940 overrideAttributeApi(definition.prototype);
6941 registerDefinition(definition.__name, definition);
6942 definition.ctor = generateConstructor(definition);
6943 definition.ctor.prototype = definition.prototype;
6944 definition.prototype.constructor = definition.ctor;
6946 upgradeDocumentTree(document);
6948 return definition.ctor;
6950 function overrideAttributeApi(prototype) {
6951 if (prototype.setAttribute._polyfilled) {
6954 var setAttribute = prototype.setAttribute;
6955 prototype.setAttribute = function(name, value) {
6956 changeAttribute.call(this, name, value, setAttribute);
6958 var removeAttribute = prototype.removeAttribute;
6959 prototype.removeAttribute = function(name) {
6960 changeAttribute.call(this, name, null, removeAttribute);
6962 prototype.setAttribute._polyfilled = true;
6964 function changeAttribute(name, value, operation) {
6965 name = name.toLowerCase();
6966 var oldValue = this.getAttribute(name);
6967 operation.apply(this, arguments);
6968 var newValue = this.getAttribute(name);
6969 if (this.attributeChangedCallback && newValue !== oldValue) {
6970 this.attributeChangedCallback(name, oldValue, newValue);
6973 function isReservedTag(name) {
6974 for (var i = 0; i < reservedTagList.length; i++) {
6975 if (name === reservedTagList[i]) {
6980 var reservedTagList = [ "annotation-xml", "color-profile", "font-face", "font-face-src", "font-face-uri", "font-face-format", "font-face-name", "missing-glyph" ];
6981 function ancestry(extnds) {
6982 var extendee = getRegisteredDefinition(extnds);
6984 return ancestry(extendee.extends).concat([ extendee ]);
6988 function resolveTagName(definition) {
6989 var baseTag = definition.extends;
6990 for (var i = 0, a; a = definition.ancestry[i]; i++) {
6991 baseTag = a.is && a.tag;
6993 definition.tag = baseTag || definition.__name;
6995 definition.is = definition.__name;
6998 function resolvePrototypeChain(definition) {
6999 if (!Object.__proto__) {
7000 var nativePrototype = HTMLElement.prototype;
7001 if (definition.is) {
7002 var inst = document.createElement(definition.tag);
7003 nativePrototype = Object.getPrototypeOf(inst);
7005 var proto = definition.prototype, ancestor;
7006 var foundPrototype = false;
7008 if (proto == nativePrototype) {
7009 foundPrototype = true;
7011 ancestor = Object.getPrototypeOf(proto);
7013 proto.__proto__ = ancestor;
7017 if (!foundPrototype) {
7018 console.warn(definition.tag + " prototype not found in prototype chain for " + definition.is);
7020 definition.native = nativePrototype;
7023 function instantiate(definition) {
7024 return upgradeWithDefinition(domCreateElement(definition.tag), definition);
7027 function getRegisteredDefinition(name) {
7029 return registry[name.toLowerCase()];
7032 function registerDefinition(name, definition) {
7033 registry[name] = definition;
7035 function generateConstructor(definition) {
7037 return instantiate(definition);
7040 var HTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
7041 function createElementNS(namespace, tag, typeExtension) {
7042 if (namespace === HTML_NAMESPACE) {
7043 return createElement(tag, typeExtension);
7045 return domCreateElementNS(namespace, tag);
7048 function createElement(tag, typeExtension) {
7050 tag = tag.toLowerCase();
7052 if (typeExtension) {
7053 typeExtension = typeExtension.toLowerCase();
7055 var definition = getRegisteredDefinition(typeExtension || tag);
7057 if (tag == definition.tag && typeExtension == definition.is) {
7058 return new definition.ctor();
7060 if (!typeExtension && !definition.is) {
7061 return new definition.ctor();
7065 if (typeExtension) {
7066 element = createElement(tag);
7067 element.setAttribute("is", typeExtension);
7070 element = domCreateElement(tag);
7071 if (tag.indexOf("-") >= 0) {
7072 implementPrototype(element, HTMLElement);
7076 var domCreateElement = document.createElement.bind(document);
7077 var domCreateElementNS = document.createElementNS.bind(document);
7079 if (!Object.__proto__ && !useNative) {
7080 isInstance = function(obj, ctor) {
7081 if (obj instanceof ctor) {
7086 if (p === ctor.prototype) {
7094 isInstance = function(obj, base) {
7095 return obj instanceof base;
7098 function wrapDomMethodToForceUpgrade(obj, methodName) {
7099 var orig = obj[methodName];
7100 obj[methodName] = function() {
7101 var n = orig.apply(this, arguments);
7106 wrapDomMethodToForceUpgrade(Node.prototype, "cloneNode");
7107 wrapDomMethodToForceUpgrade(document, "importNode");
7110 var importNode = document.importNode;
7111 document.importNode = function() {
7112 var n = importNode.apply(document, arguments);
7113 if (n.nodeType == n.DOCUMENT_FRAGMENT_NODE) {
7114 var f = document.createDocumentFragment();
7123 document.registerElement = register;
7124 document.createElement = createElement;
7125 document.createElementNS = createElementNS;
7126 scope.registry = registry;
7127 scope.instanceof = isInstance;
7128 scope.reservedTagList = reservedTagList;
7129 scope.getRegisteredDefinition = getRegisteredDefinition;
7130 document.register = document.registerElement;
7134 var useNative = scope.useNative;
7135 var initializeModules = scope.initializeModules;
7136 var isIE = scope.isIE;
7138 var nop = function() {};
7139 scope.watchShadow = nop;
7140 scope.upgrade = nop;
7141 scope.upgradeAll = nop;
7142 scope.upgradeDocumentTree = nop;
7143 scope.upgradeSubtree = nop;
7144 scope.takeRecords = nop;
7145 scope.instanceof = function(obj, base) {
7146 return obj instanceof base;
7149 initializeModules();
7151 var upgradeDocumentTree = scope.upgradeDocumentTree;
7152 var upgradeDocument = scope.upgradeDocument;
7154 if (window.ShadowDOMPolyfill) {
7155 window.wrap = window.ShadowDOMPolyfill.wrapIfNeeded;
7156 window.unwrap = window.ShadowDOMPolyfill.unwrapIfNeeded;
7158 window.wrap = window.unwrap = function(node) {
7163 if (window.HTMLImports) {
7164 window.HTMLImports.__importsParsingHook = function(elt) {
7166 upgradeDocument(wrap(elt.import));
7170 function bootstrap() {
7171 upgradeDocumentTree(window.wrap(document));
7172 window.CustomElements.ready = true;
7173 var requestAnimationFrame = window.requestAnimationFrame || function(f) {
7176 requestAnimationFrame(function() {
7177 setTimeout(function() {
7178 window.CustomElements.readyTime = Date.now();
7179 if (window.HTMLImports) {
7180 window.CustomElements.elapsed = window.CustomElements.readyTime - window.HTMLImports.readyTime;
7182 document.dispatchEvent(new CustomEvent("WebComponentsReady", {
7188 if (document.readyState === "complete" || scope.flags.eager) {
7190 } else if (document.readyState === "interactive" && !window.attachEvent && (!window.HTMLImports || window.HTMLImports.ready)) {
7193 var loadEvent = window.HTMLImports && !window.HTMLImports.ready ? "HTMLImportsLoaded" : "DOMContentLoaded";
7194 window.addEventListener(loadEvent, bootstrap);
7196 })(window.CustomElements);
7199 if (!Function.prototype.bind) {
7200 Function.prototype.bind = function(scope) {
7202 var args = Array.prototype.slice.call(arguments, 1);
7204 var args2 = args.slice();
7205 args2.push.apply(args2, arguments);
7206 return self.apply(scope, args2);
7210 })(window.WebComponents);
7213 var style = document.createElement("style");
7214 style.textContent = "" + "body {" + "transition: opacity ease-in 0.2s;" + " } \n" + "body[unresolved] {" + "opacity: 0; display: block; overflow: hidden; position: relative;" + " } \n";
7215 var head = document.querySelector("head");
7216 head.insertBefore(style, head.firstChild);
7217 })(window.WebComponents);
7220 window.Platform = scope;
7221 })(window.WebComponents);