2015-06-19 09:36:51 -07:00
|
|
|
/**
|
|
|
|
* @license
|
|
|
|
* Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
|
|
|
|
* This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
|
|
|
* The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
|
|
|
* The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
|
|
|
* Code distributed by Google as part of the polymer project is also
|
|
|
|
* subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
|
|
|
*/
|
2015-08-20 20:27:11 -07:00
|
|
|
// @version 0.7.12
|
2015-06-19 09:36:51 -07:00
|
|
|
if (typeof WeakMap === "undefined") {
|
|
|
|
(function() {
|
|
|
|
var defineProperty = Object.defineProperty;
|
|
|
|
var counter = Date.now() % 1e9;
|
|
|
|
var WeakMap = function() {
|
|
|
|
this.name = "__st" + (Math.random() * 1e9 >>> 0) + (counter++ + "__");
|
|
|
|
};
|
|
|
|
WeakMap.prototype = {
|
|
|
|
set: function(key, value) {
|
|
|
|
var entry = key[this.name];
|
|
|
|
if (entry && entry[0] === key) entry[1] = value; else defineProperty(key, this.name, {
|
|
|
|
value: [ key, value ],
|
|
|
|
writable: true
|
|
|
|
});
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
get: function(key) {
|
|
|
|
var entry;
|
|
|
|
return (entry = key[this.name]) && entry[0] === key ? entry[1] : undefined;
|
|
|
|
},
|
|
|
|
"delete": function(key) {
|
|
|
|
var entry = key[this.name];
|
|
|
|
if (!entry || entry[0] !== key) return false;
|
|
|
|
entry[0] = entry[1] = undefined;
|
|
|
|
return true;
|
|
|
|
},
|
|
|
|
has: function(key) {
|
|
|
|
var entry = key[this.name];
|
|
|
|
if (!entry) return false;
|
|
|
|
return entry[0] === key;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
window.WeakMap = WeakMap;
|
|
|
|
})();
|
|
|
|
}
|
|
|
|
|
|
|
|
(function(global) {
|
|
|
|
var registrationsTable = new WeakMap();
|
|
|
|
var setImmediate;
|
|
|
|
if (/Trident|Edge/.test(navigator.userAgent)) {
|
|
|
|
setImmediate = setTimeout;
|
|
|
|
} else if (window.setImmediate) {
|
|
|
|
setImmediate = window.setImmediate;
|
|
|
|
} else {
|
|
|
|
var setImmediateQueue = [];
|
|
|
|
var sentinel = String(Math.random());
|
|
|
|
window.addEventListener("message", function(e) {
|
|
|
|
if (e.data === sentinel) {
|
|
|
|
var queue = setImmediateQueue;
|
|
|
|
setImmediateQueue = [];
|
|
|
|
queue.forEach(function(func) {
|
|
|
|
func();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
setImmediate = function(func) {
|
|
|
|
setImmediateQueue.push(func);
|
|
|
|
window.postMessage(sentinel, "*");
|
|
|
|
};
|
|
|
|
}
|
|
|
|
var isScheduled = false;
|
|
|
|
var scheduledObservers = [];
|
|
|
|
function scheduleCallback(observer) {
|
|
|
|
scheduledObservers.push(observer);
|
|
|
|
if (!isScheduled) {
|
|
|
|
isScheduled = true;
|
|
|
|
setImmediate(dispatchCallbacks);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
function wrapIfNeeded(node) {
|
|
|
|
return window.ShadowDOMPolyfill && window.ShadowDOMPolyfill.wrapIfNeeded(node) || node;
|
|
|
|
}
|
|
|
|
function dispatchCallbacks() {
|
|
|
|
isScheduled = false;
|
|
|
|
var observers = scheduledObservers;
|
|
|
|
scheduledObservers = [];
|
|
|
|
observers.sort(function(o1, o2) {
|
|
|
|
return o1.uid_ - o2.uid_;
|
|
|
|
});
|
|
|
|
var anyNonEmpty = false;
|
|
|
|
observers.forEach(function(observer) {
|
|
|
|
var queue = observer.takeRecords();
|
|
|
|
removeTransientObserversFor(observer);
|
|
|
|
if (queue.length) {
|
|
|
|
observer.callback_(queue, observer);
|
|
|
|
anyNonEmpty = true;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
if (anyNonEmpty) dispatchCallbacks();
|
|
|
|
}
|
|
|
|
function removeTransientObserversFor(observer) {
|
|
|
|
observer.nodes_.forEach(function(node) {
|
|
|
|
var registrations = registrationsTable.get(node);
|
|
|
|
if (!registrations) return;
|
|
|
|
registrations.forEach(function(registration) {
|
|
|
|
if (registration.observer === observer) registration.removeTransientObservers();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
function forEachAncestorAndObserverEnqueueRecord(target, callback) {
|
|
|
|
for (var node = target; node; node = node.parentNode) {
|
|
|
|
var registrations = registrationsTable.get(node);
|
|
|
|
if (registrations) {
|
|
|
|
for (var j = 0; j < registrations.length; j++) {
|
|
|
|
var registration = registrations[j];
|
|
|
|
var options = registration.options;
|
|
|
|
if (node !== target && !options.subtree) continue;
|
|
|
|
var record = callback(options);
|
|
|
|
if (record) registration.enqueue(record);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
var uidCounter = 0;
|
|
|
|
function JsMutationObserver(callback) {
|
|
|
|
this.callback_ = callback;
|
|
|
|
this.nodes_ = [];
|
|
|
|
this.records_ = [];
|
|
|
|
this.uid_ = ++uidCounter;
|
|
|
|
}
|
|
|
|
JsMutationObserver.prototype = {
|
|
|
|
observe: function(target, options) {
|
|
|
|
target = wrapIfNeeded(target);
|
|
|
|
if (!options.childList && !options.attributes && !options.characterData || options.attributeOldValue && !options.attributes || options.attributeFilter && options.attributeFilter.length && !options.attributes || options.characterDataOldValue && !options.characterData) {
|
|
|
|
throw new SyntaxError();
|
|
|
|
}
|
|
|
|
var registrations = registrationsTable.get(target);
|
|
|
|
if (!registrations) registrationsTable.set(target, registrations = []);
|
|
|
|
var registration;
|
|
|
|
for (var i = 0; i < registrations.length; i++) {
|
|
|
|
if (registrations[i].observer === this) {
|
|
|
|
registration = registrations[i];
|
|
|
|
registration.removeListeners();
|
|
|
|
registration.options = options;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!registration) {
|
|
|
|
registration = new Registration(this, target, options);
|
|
|
|
registrations.push(registration);
|
|
|
|
this.nodes_.push(target);
|
|
|
|
}
|
|
|
|
registration.addListeners();
|
|
|
|
},
|
|
|
|
disconnect: function() {
|
|
|
|
this.nodes_.forEach(function(node) {
|
|
|
|
var registrations = registrationsTable.get(node);
|
|
|
|
for (var i = 0; i < registrations.length; i++) {
|
|
|
|
var registration = registrations[i];
|
|
|
|
if (registration.observer === this) {
|
|
|
|
registration.removeListeners();
|
|
|
|
registrations.splice(i, 1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}, this);
|
|
|
|
this.records_ = [];
|
|
|
|
},
|
|
|
|
takeRecords: function() {
|
|
|
|
var copyOfRecords = this.records_;
|
|
|
|
this.records_ = [];
|
|
|
|
return copyOfRecords;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
function MutationRecord(type, target) {
|
|
|
|
this.type = type;
|
|
|
|
this.target = target;
|
|
|
|
this.addedNodes = [];
|
|
|
|
this.removedNodes = [];
|
|
|
|
this.previousSibling = null;
|
|
|
|
this.nextSibling = null;
|
|
|
|
this.attributeName = null;
|
|
|
|
this.attributeNamespace = null;
|
|
|
|
this.oldValue = null;
|
|
|
|
}
|
|
|
|
function copyMutationRecord(original) {
|
|
|
|
var record = new MutationRecord(original.type, original.target);
|
|
|
|
record.addedNodes = original.addedNodes.slice();
|
|
|
|
record.removedNodes = original.removedNodes.slice();
|
|
|
|
record.previousSibling = original.previousSibling;
|
|
|
|
record.nextSibling = original.nextSibling;
|
|
|
|
record.attributeName = original.attributeName;
|
|
|
|
record.attributeNamespace = original.attributeNamespace;
|
|
|
|
record.oldValue = original.oldValue;
|
|
|
|
return record;
|
|
|
|
}
|
|
|
|
var currentRecord, recordWithOldValue;
|
|
|
|
function getRecord(type, target) {
|
|
|
|
return currentRecord = new MutationRecord(type, target);
|
|
|
|
}
|
|
|
|
function getRecordWithOldValue(oldValue) {
|
|
|
|
if (recordWithOldValue) return recordWithOldValue;
|
|
|
|
recordWithOldValue = copyMutationRecord(currentRecord);
|
|
|
|
recordWithOldValue.oldValue = oldValue;
|
|
|
|
return recordWithOldValue;
|
|
|
|
}
|
|
|
|
function clearRecords() {
|
|
|
|
currentRecord = recordWithOldValue = undefined;
|
|
|
|
}
|
|
|
|
function recordRepresentsCurrentMutation(record) {
|
|
|
|
return record === recordWithOldValue || record === currentRecord;
|
|
|
|
}
|
|
|
|
function selectRecord(lastRecord, newRecord) {
|
|
|
|
if (lastRecord === newRecord) return lastRecord;
|
|
|
|
if (recordWithOldValue && recordRepresentsCurrentMutation(lastRecord)) return recordWithOldValue;
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
function Registration(observer, target, options) {
|
|
|
|
this.observer = observer;
|
|
|
|
this.target = target;
|
|
|
|
this.options = options;
|
|
|
|
this.transientObservedNodes = [];
|
|
|
|
}
|
|
|
|
Registration.prototype = {
|
|
|
|
enqueue: function(record) {
|
|
|
|
var records = this.observer.records_;
|
|
|
|
var length = records.length;
|
|
|
|
if (records.length > 0) {
|
|
|
|
var lastRecord = records[length - 1];
|
|
|
|
var recordToReplaceLast = selectRecord(lastRecord, record);
|
|
|
|
if (recordToReplaceLast) {
|
|
|
|
records[length - 1] = recordToReplaceLast;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
scheduleCallback(this.observer);
|
|
|
|
}
|
|
|
|
records[length] = record;
|
|
|
|
},
|
|
|
|
addListeners: function() {
|
|
|
|
this.addListeners_(this.target);
|
|
|
|
},
|
|
|
|
addListeners_: function(node) {
|
|
|
|
var options = this.options;
|
|
|
|
if (options.attributes) node.addEventListener("DOMAttrModified", this, true);
|
|
|
|
if (options.characterData) node.addEventListener("DOMCharacterDataModified", this, true);
|
|
|
|
if (options.childList) node.addEventListener("DOMNodeInserted", this, true);
|
|
|
|
if (options.childList || options.subtree) node.addEventListener("DOMNodeRemoved", this, true);
|
|
|
|
},
|
|
|
|
removeListeners: function() {
|
|
|
|
this.removeListeners_(this.target);
|
|
|
|
},
|
|
|
|
removeListeners_: function(node) {
|
|
|
|
var options = this.options;
|
|
|
|
if (options.attributes) node.removeEventListener("DOMAttrModified", this, true);
|
|
|
|
if (options.characterData) node.removeEventListener("DOMCharacterDataModified", this, true);
|
|
|
|
if (options.childList) node.removeEventListener("DOMNodeInserted", this, true);
|
|
|
|
if (options.childList || options.subtree) node.removeEventListener("DOMNodeRemoved", this, true);
|
|
|
|
},
|
|
|
|
addTransientObserver: function(node) {
|
|
|
|
if (node === this.target) return;
|
|
|
|
this.addListeners_(node);
|
|
|
|
this.transientObservedNodes.push(node);
|
|
|
|
var registrations = registrationsTable.get(node);
|
|
|
|
if (!registrations) registrationsTable.set(node, registrations = []);
|
|
|
|
registrations.push(this);
|
|
|
|
},
|
|
|
|
removeTransientObservers: function() {
|
|
|
|
var transientObservedNodes = this.transientObservedNodes;
|
|
|
|
this.transientObservedNodes = [];
|
|
|
|
transientObservedNodes.forEach(function(node) {
|
|
|
|
this.removeListeners_(node);
|
|
|
|
var registrations = registrationsTable.get(node);
|
|
|
|
for (var i = 0; i < registrations.length; i++) {
|
|
|
|
if (registrations[i] === this) {
|
|
|
|
registrations.splice(i, 1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}, this);
|
|
|
|
},
|
|
|
|
handleEvent: function(e) {
|
|
|
|
e.stopImmediatePropagation();
|
|
|
|
switch (e.type) {
|
|
|
|
case "DOMAttrModified":
|
|
|
|
var name = e.attrName;
|
|
|
|
var namespace = e.relatedNode.namespaceURI;
|
|
|
|
var target = e.target;
|
|
|
|
var record = new getRecord("attributes", target);
|
|
|
|
record.attributeName = name;
|
|
|
|
record.attributeNamespace = namespace;
|
|
|
|
var oldValue = e.attrChange === MutationEvent.ADDITION ? null : e.prevValue;
|
|
|
|
forEachAncestorAndObserverEnqueueRecord(target, function(options) {
|
|
|
|
if (!options.attributes) return;
|
|
|
|
if (options.attributeFilter && options.attributeFilter.length && options.attributeFilter.indexOf(name) === -1 && options.attributeFilter.indexOf(namespace) === -1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (options.attributeOldValue) return getRecordWithOldValue(oldValue);
|
|
|
|
return record;
|
|
|
|
});
|
|
|
|
break;
|
|
|
|
|
|
|
|
case "DOMCharacterDataModified":
|
|
|
|
var target = e.target;
|
|
|
|
var record = getRecord("characterData", target);
|
|
|
|
var oldValue = e.prevValue;
|
|
|
|
forEachAncestorAndObserverEnqueueRecord(target, function(options) {
|
|
|
|
if (!options.characterData) return;
|
|
|
|
if (options.characterDataOldValue) return getRecordWithOldValue(oldValue);
|
|
|
|
return record;
|
|
|
|
});
|
|
|
|
break;
|
|
|
|
|
|
|
|
case "DOMNodeRemoved":
|
|
|
|
this.addTransientObserver(e.target);
|
|
|
|
|
|
|
|
case "DOMNodeInserted":
|
|
|
|
var changedNode = e.target;
|
|
|
|
var addedNodes, removedNodes;
|
|
|
|
if (e.type === "DOMNodeInserted") {
|
|
|
|
addedNodes = [ changedNode ];
|
|
|
|
removedNodes = [];
|
|
|
|
} else {
|
|
|
|
addedNodes = [];
|
|
|
|
removedNodes = [ changedNode ];
|
|
|
|
}
|
|
|
|
var previousSibling = changedNode.previousSibling;
|
|
|
|
var nextSibling = changedNode.nextSibling;
|
|
|
|
var record = getRecord("childList", e.target.parentNode);
|
|
|
|
record.addedNodes = addedNodes;
|
|
|
|
record.removedNodes = removedNodes;
|
|
|
|
record.previousSibling = previousSibling;
|
|
|
|
record.nextSibling = nextSibling;
|
|
|
|
forEachAncestorAndObserverEnqueueRecord(e.relatedNode, function(options) {
|
|
|
|
if (!options.childList) return;
|
|
|
|
return record;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
clearRecords();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
global.JsMutationObserver = JsMutationObserver;
|
|
|
|
if (!global.MutationObserver) global.MutationObserver = JsMutationObserver;
|
2015-08-20 20:27:11 -07:00
|
|
|
})(window);
|
2015-06-19 09:36:51 -07:00
|
|
|
|
|
|
|
window.CustomElements = window.CustomElements || {
|
|
|
|
flags: {}
|
|
|
|
};
|
|
|
|
|
|
|
|
(function(scope) {
|
|
|
|
var flags = scope.flags;
|
|
|
|
var modules = [];
|
|
|
|
var addModule = function(module) {
|
|
|
|
modules.push(module);
|
|
|
|
};
|
|
|
|
var initializeModules = function() {
|
|
|
|
modules.forEach(function(module) {
|
|
|
|
module(scope);
|
|
|
|
});
|
|
|
|
};
|
|
|
|
scope.addModule = addModule;
|
|
|
|
scope.initializeModules = initializeModules;
|
|
|
|
scope.hasNative = Boolean(document.registerElement);
|
2015-08-20 20:27:11 -07:00
|
|
|
scope.isIE = /Trident/.test(navigator.userAgent);
|
2015-06-19 09:36:51 -07:00
|
|
|
scope.useNative = !flags.register && scope.hasNative && !window.ShadowDOMPolyfill && (!window.HTMLImports || window.HTMLImports.useNative);
|
|
|
|
})(window.CustomElements);
|
|
|
|
|
|
|
|
window.CustomElements.addModule(function(scope) {
|
|
|
|
var IMPORT_LINK_TYPE = window.HTMLImports ? window.HTMLImports.IMPORT_LINK_TYPE : "none";
|
|
|
|
function forSubtree(node, cb) {
|
|
|
|
findAllElements(node, function(e) {
|
|
|
|
if (cb(e)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
forRoots(e, cb);
|
|
|
|
});
|
|
|
|
forRoots(node, cb);
|
|
|
|
}
|
|
|
|
function findAllElements(node, find, data) {
|
|
|
|
var e = node.firstElementChild;
|
|
|
|
if (!e) {
|
|
|
|
e = node.firstChild;
|
|
|
|
while (e && e.nodeType !== Node.ELEMENT_NODE) {
|
|
|
|
e = e.nextSibling;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (e) {
|
|
|
|
if (find(e, data) !== true) {
|
|
|
|
findAllElements(e, find, data);
|
|
|
|
}
|
|
|
|
e = e.nextElementSibling;
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
function forRoots(node, cb) {
|
|
|
|
var root = node.shadowRoot;
|
|
|
|
while (root) {
|
|
|
|
forSubtree(root, cb);
|
|
|
|
root = root.olderShadowRoot;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
function forDocumentTree(doc, cb) {
|
|
|
|
_forDocumentTree(doc, cb, []);
|
|
|
|
}
|
|
|
|
function _forDocumentTree(doc, cb, processingDocuments) {
|
|
|
|
doc = window.wrap(doc);
|
|
|
|
if (processingDocuments.indexOf(doc) >= 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
processingDocuments.push(doc);
|
|
|
|
var imports = doc.querySelectorAll("link[rel=" + IMPORT_LINK_TYPE + "]");
|
|
|
|
for (var i = 0, l = imports.length, n; i < l && (n = imports[i]); i++) {
|
|
|
|
if (n.import) {
|
|
|
|
_forDocumentTree(n.import, cb, processingDocuments);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cb(doc);
|
|
|
|
}
|
|
|
|
scope.forDocumentTree = forDocumentTree;
|
|
|
|
scope.forSubtree = forSubtree;
|
|
|
|
});
|
|
|
|
|
|
|
|
window.CustomElements.addModule(function(scope) {
|
|
|
|
var flags = scope.flags;
|
|
|
|
var forSubtree = scope.forSubtree;
|
|
|
|
var forDocumentTree = scope.forDocumentTree;
|
2015-07-09 20:00:03 -07:00
|
|
|
function addedNode(node, isAttached) {
|
|
|
|
return added(node, isAttached) || addedSubtree(node, isAttached);
|
2015-06-19 09:36:51 -07:00
|
|
|
}
|
2015-07-09 20:00:03 -07:00
|
|
|
function added(node, isAttached) {
|
|
|
|
if (scope.upgrade(node, isAttached)) {
|
2015-06-19 09:36:51 -07:00
|
|
|
return true;
|
|
|
|
}
|
2015-07-09 20:00:03 -07:00
|
|
|
if (isAttached) {
|
|
|
|
attached(node);
|
|
|
|
}
|
2015-06-19 09:36:51 -07:00
|
|
|
}
|
2015-07-09 20:00:03 -07:00
|
|
|
function addedSubtree(node, isAttached) {
|
2015-06-19 09:36:51 -07:00
|
|
|
forSubtree(node, function(e) {
|
2015-07-09 20:00:03 -07:00
|
|
|
if (added(e, isAttached)) {
|
2015-06-19 09:36:51 -07:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
var hasPolyfillMutations = !window.MutationObserver || window.MutationObserver === window.JsMutationObserver;
|
|
|
|
scope.hasPolyfillMutations = hasPolyfillMutations;
|
|
|
|
var isPendingMutations = false;
|
|
|
|
var pendingMutations = [];
|
|
|
|
function deferMutation(fn) {
|
|
|
|
pendingMutations.push(fn);
|
|
|
|
if (!isPendingMutations) {
|
|
|
|
isPendingMutations = true;
|
|
|
|
setTimeout(takeMutations);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
function takeMutations() {
|
|
|
|
isPendingMutations = false;
|
|
|
|
var $p = pendingMutations;
|
|
|
|
for (var i = 0, l = $p.length, p; i < l && (p = $p[i]); i++) {
|
|
|
|
p();
|
|
|
|
}
|
|
|
|
pendingMutations = [];
|
|
|
|
}
|
|
|
|
function attached(element) {
|
|
|
|
if (hasPolyfillMutations) {
|
|
|
|
deferMutation(function() {
|
|
|
|
_attached(element);
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
_attached(element);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
function _attached(element) {
|
2015-07-09 20:00:03 -07:00
|
|
|
if (element.__upgraded__ && !element.__attached) {
|
|
|
|
element.__attached = true;
|
|
|
|
if (element.attachedCallback) {
|
|
|
|
element.attachedCallback();
|
2015-06-19 09:36:51 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
function detachedNode(node) {
|
|
|
|
detached(node);
|
|
|
|
forSubtree(node, function(e) {
|
|
|
|
detached(e);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
function detached(element) {
|
|
|
|
if (hasPolyfillMutations) {
|
|
|
|
deferMutation(function() {
|
|
|
|
_detached(element);
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
_detached(element);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
function _detached(element) {
|
2015-07-09 20:00:03 -07:00
|
|
|
if (element.__upgraded__ && element.__attached) {
|
|
|
|
element.__attached = false;
|
|
|
|
if (element.detachedCallback) {
|
|
|
|
element.detachedCallback();
|
2015-06-19 09:36:51 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
function inDocument(element) {
|
|
|
|
var p = element;
|
2015-07-09 20:00:03 -07:00
|
|
|
var doc = window.wrap(document);
|
2015-06-19 09:36:51 -07:00
|
|
|
while (p) {
|
|
|
|
if (p == doc) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
p = p.parentNode || p.nodeType === Node.DOCUMENT_FRAGMENT_NODE && p.host;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
function watchShadow(node) {
|
|
|
|
if (node.shadowRoot && !node.shadowRoot.__watched) {
|
|
|
|
flags.dom && console.log("watching shadow-root for: ", node.localName);
|
|
|
|
var root = node.shadowRoot;
|
|
|
|
while (root) {
|
|
|
|
observe(root);
|
|
|
|
root = root.olderShadowRoot;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-07-09 20:00:03 -07:00
|
|
|
function handler(root, mutations) {
|
2015-06-19 09:36:51 -07:00
|
|
|
if (flags.dom) {
|
|
|
|
var mx = mutations[0];
|
|
|
|
if (mx && mx.type === "childList" && mx.addedNodes) {
|
|
|
|
if (mx.addedNodes) {
|
|
|
|
var d = mx.addedNodes[0];
|
|
|
|
while (d && d !== document && !d.host) {
|
|
|
|
d = d.parentNode;
|
|
|
|
}
|
|
|
|
var u = d && (d.URL || d._URL || d.host && d.host.localName) || "";
|
|
|
|
u = u.split("/?").shift().split("/").pop();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
console.group("mutations (%d) [%s]", mutations.length, u || "");
|
|
|
|
}
|
2015-07-09 20:00:03 -07:00
|
|
|
var isAttached = inDocument(root);
|
2015-06-19 09:36:51 -07:00
|
|
|
mutations.forEach(function(mx) {
|
|
|
|
if (mx.type === "childList") {
|
|
|
|
forEach(mx.addedNodes, function(n) {
|
|
|
|
if (!n.localName) {
|
|
|
|
return;
|
|
|
|
}
|
2015-07-09 20:00:03 -07:00
|
|
|
addedNode(n, isAttached);
|
2015-06-19 09:36:51 -07:00
|
|
|
});
|
|
|
|
forEach(mx.removedNodes, function(n) {
|
|
|
|
if (!n.localName) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
detachedNode(n);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
flags.dom && console.groupEnd();
|
|
|
|
}
|
|
|
|
function takeRecords(node) {
|
|
|
|
node = window.wrap(node);
|
|
|
|
if (!node) {
|
|
|
|
node = window.wrap(document);
|
|
|
|
}
|
|
|
|
while (node.parentNode) {
|
|
|
|
node = node.parentNode;
|
|
|
|
}
|
|
|
|
var observer = node.__observer;
|
|
|
|
if (observer) {
|
2015-07-09 20:00:03 -07:00
|
|
|
handler(node, observer.takeRecords());
|
2015-06-19 09:36:51 -07:00
|
|
|
takeMutations();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);
|
|
|
|
function observe(inRoot) {
|
|
|
|
if (inRoot.__observer) {
|
|
|
|
return;
|
|
|
|
}
|
2015-07-09 20:00:03 -07:00
|
|
|
var observer = new MutationObserver(handler.bind(this, inRoot));
|
2015-06-19 09:36:51 -07:00
|
|
|
observer.observe(inRoot, {
|
|
|
|
childList: true,
|
|
|
|
subtree: true
|
|
|
|
});
|
|
|
|
inRoot.__observer = observer;
|
|
|
|
}
|
|
|
|
function upgradeDocument(doc) {
|
|
|
|
doc = window.wrap(doc);
|
|
|
|
flags.dom && console.group("upgradeDocument: ", doc.baseURI.split("/").pop());
|
2015-07-09 20:00:03 -07:00
|
|
|
var isMainDocument = doc === window.wrap(document);
|
|
|
|
addedNode(doc, isMainDocument);
|
2015-06-19 09:36:51 -07:00
|
|
|
observe(doc);
|
|
|
|
flags.dom && console.groupEnd();
|
|
|
|
}
|
|
|
|
function upgradeDocumentTree(doc) {
|
|
|
|
forDocumentTree(doc, upgradeDocument);
|
|
|
|
}
|
|
|
|
var originalCreateShadowRoot = Element.prototype.createShadowRoot;
|
|
|
|
if (originalCreateShadowRoot) {
|
|
|
|
Element.prototype.createShadowRoot = function() {
|
|
|
|
var root = originalCreateShadowRoot.call(this);
|
|
|
|
window.CustomElements.watchShadow(this);
|
|
|
|
return root;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
scope.watchShadow = watchShadow;
|
|
|
|
scope.upgradeDocumentTree = upgradeDocumentTree;
|
2015-08-03 17:09:54 -07:00
|
|
|
scope.upgradeDocument = upgradeDocument;
|
2015-06-19 09:36:51 -07:00
|
|
|
scope.upgradeSubtree = addedSubtree;
|
|
|
|
scope.upgradeAll = addedNode;
|
2015-07-09 20:00:03 -07:00
|
|
|
scope.attached = attached;
|
2015-06-19 09:36:51 -07:00
|
|
|
scope.takeRecords = takeRecords;
|
|
|
|
});
|
|
|
|
|
|
|
|
window.CustomElements.addModule(function(scope) {
|
|
|
|
var flags = scope.flags;
|
2015-07-09 20:00:03 -07:00
|
|
|
function upgrade(node, isAttached) {
|
2015-06-19 09:36:51 -07:00
|
|
|
if (!node.__upgraded__ && node.nodeType === Node.ELEMENT_NODE) {
|
|
|
|
var is = node.getAttribute("is");
|
2015-08-03 17:09:54 -07:00
|
|
|
var definition = scope.getRegisteredDefinition(node.localName) || scope.getRegisteredDefinition(is);
|
2015-06-19 09:36:51 -07:00
|
|
|
if (definition) {
|
2015-08-03 17:09:54 -07:00
|
|
|
if (is && definition.tag == node.localName || !is && !definition.extends) {
|
2015-07-09 20:00:03 -07:00
|
|
|
return upgradeWithDefinition(node, definition, isAttached);
|
2015-06-19 09:36:51 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-07-09 20:00:03 -07:00
|
|
|
function upgradeWithDefinition(element, definition, isAttached) {
|
2015-06-19 09:36:51 -07:00
|
|
|
flags.upgrade && console.group("upgrade:", element.localName);
|
|
|
|
if (definition.is) {
|
|
|
|
element.setAttribute("is", definition.is);
|
|
|
|
}
|
|
|
|
implementPrototype(element, definition);
|
|
|
|
element.__upgraded__ = true;
|
|
|
|
created(element);
|
2015-07-09 20:00:03 -07:00
|
|
|
if (isAttached) {
|
|
|
|
scope.attached(element);
|
|
|
|
}
|
|
|
|
scope.upgradeSubtree(element, isAttached);
|
2015-06-19 09:36:51 -07:00
|
|
|
flags.upgrade && console.groupEnd();
|
|
|
|
return element;
|
|
|
|
}
|
|
|
|
function implementPrototype(element, definition) {
|
|
|
|
if (Object.__proto__) {
|
|
|
|
element.__proto__ = definition.prototype;
|
|
|
|
} else {
|
|
|
|
customMixin(element, definition.prototype, definition.native);
|
|
|
|
element.__proto__ = definition.prototype;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
function customMixin(inTarget, inSrc, inNative) {
|
|
|
|
var used = {};
|
|
|
|
var p = inSrc;
|
|
|
|
while (p !== inNative && p !== HTMLElement.prototype) {
|
|
|
|
var keys = Object.getOwnPropertyNames(p);
|
|
|
|
for (var i = 0, k; k = keys[i]; i++) {
|
|
|
|
if (!used[k]) {
|
|
|
|
Object.defineProperty(inTarget, k, Object.getOwnPropertyDescriptor(p, k));
|
|
|
|
used[k] = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
p = Object.getPrototypeOf(p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
function created(element) {
|
|
|
|
if (element.createdCallback) {
|
|
|
|
element.createdCallback();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
scope.upgrade = upgrade;
|
|
|
|
scope.upgradeWithDefinition = upgradeWithDefinition;
|
|
|
|
scope.implementPrototype = implementPrototype;
|
|
|
|
});
|
|
|
|
|
|
|
|
window.CustomElements.addModule(function(scope) {
|
2015-08-20 20:27:11 -07:00
|
|
|
var isIE = scope.isIE;
|
2015-06-19 09:36:51 -07:00
|
|
|
var upgradeDocumentTree = scope.upgradeDocumentTree;
|
|
|
|
var upgradeAll = scope.upgradeAll;
|
|
|
|
var upgradeWithDefinition = scope.upgradeWithDefinition;
|
|
|
|
var implementPrototype = scope.implementPrototype;
|
|
|
|
var useNative = scope.useNative;
|
|
|
|
function register(name, options) {
|
|
|
|
var definition = options || {};
|
|
|
|
if (!name) {
|
|
|
|
throw new Error("document.registerElement: first argument `name` must not be empty");
|
|
|
|
}
|
|
|
|
if (name.indexOf("-") < 0) {
|
|
|
|
throw new Error("document.registerElement: first argument ('name') must contain a dash ('-'). Argument provided was '" + String(name) + "'.");
|
|
|
|
}
|
|
|
|
if (isReservedTag(name)) {
|
|
|
|
throw new Error("Failed to execute 'registerElement' on 'Document': Registration failed for type '" + String(name) + "'. The type name is invalid.");
|
|
|
|
}
|
|
|
|
if (getRegisteredDefinition(name)) {
|
|
|
|
throw new Error("DuplicateDefinitionError: a type with name '" + String(name) + "' is already registered");
|
|
|
|
}
|
|
|
|
if (!definition.prototype) {
|
|
|
|
definition.prototype = Object.create(HTMLElement.prototype);
|
|
|
|
}
|
|
|
|
definition.__name = name.toLowerCase();
|
|
|
|
definition.lifecycle = definition.lifecycle || {};
|
|
|
|
definition.ancestry = ancestry(definition.extends);
|
|
|
|
resolveTagName(definition);
|
|
|
|
resolvePrototypeChain(definition);
|
|
|
|
overrideAttributeApi(definition.prototype);
|
|
|
|
registerDefinition(definition.__name, definition);
|
|
|
|
definition.ctor = generateConstructor(definition);
|
|
|
|
definition.ctor.prototype = definition.prototype;
|
|
|
|
definition.prototype.constructor = definition.ctor;
|
|
|
|
if (scope.ready) {
|
|
|
|
upgradeDocumentTree(document);
|
|
|
|
}
|
|
|
|
return definition.ctor;
|
|
|
|
}
|
|
|
|
function overrideAttributeApi(prototype) {
|
|
|
|
if (prototype.setAttribute._polyfilled) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
var setAttribute = prototype.setAttribute;
|
|
|
|
prototype.setAttribute = function(name, value) {
|
|
|
|
changeAttribute.call(this, name, value, setAttribute);
|
|
|
|
};
|
|
|
|
var removeAttribute = prototype.removeAttribute;
|
|
|
|
prototype.removeAttribute = function(name) {
|
|
|
|
changeAttribute.call(this, name, null, removeAttribute);
|
|
|
|
};
|
|
|
|
prototype.setAttribute._polyfilled = true;
|
|
|
|
}
|
|
|
|
function changeAttribute(name, value, operation) {
|
|
|
|
name = name.toLowerCase();
|
|
|
|
var oldValue = this.getAttribute(name);
|
|
|
|
operation.apply(this, arguments);
|
|
|
|
var newValue = this.getAttribute(name);
|
|
|
|
if (this.attributeChangedCallback && newValue !== oldValue) {
|
|
|
|
this.attributeChangedCallback(name, oldValue, newValue);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
function isReservedTag(name) {
|
|
|
|
for (var i = 0; i < reservedTagList.length; i++) {
|
|
|
|
if (name === reservedTagList[i]) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
var reservedTagList = [ "annotation-xml", "color-profile", "font-face", "font-face-src", "font-face-uri", "font-face-format", "font-face-name", "missing-glyph" ];
|
|
|
|
function ancestry(extnds) {
|
|
|
|
var extendee = getRegisteredDefinition(extnds);
|
|
|
|
if (extendee) {
|
|
|
|
return ancestry(extendee.extends).concat([ extendee ]);
|
|
|
|
}
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
function resolveTagName(definition) {
|
|
|
|
var baseTag = definition.extends;
|
|
|
|
for (var i = 0, a; a = definition.ancestry[i]; i++) {
|
|
|
|
baseTag = a.is && a.tag;
|
|
|
|
}
|
|
|
|
definition.tag = baseTag || definition.__name;
|
|
|
|
if (baseTag) {
|
|
|
|
definition.is = definition.__name;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
function resolvePrototypeChain(definition) {
|
|
|
|
if (!Object.__proto__) {
|
|
|
|
var nativePrototype = HTMLElement.prototype;
|
|
|
|
if (definition.is) {
|
|
|
|
var inst = document.createElement(definition.tag);
|
2015-07-16 16:55:16 -07:00
|
|
|
nativePrototype = Object.getPrototypeOf(inst);
|
2015-06-19 09:36:51 -07:00
|
|
|
}
|
|
|
|
var proto = definition.prototype, ancestor;
|
2015-07-16 16:55:16 -07:00
|
|
|
var foundPrototype = false;
|
|
|
|
while (proto) {
|
|
|
|
if (proto == nativePrototype) {
|
|
|
|
foundPrototype = true;
|
|
|
|
}
|
2015-06-19 09:36:51 -07:00
|
|
|
ancestor = Object.getPrototypeOf(proto);
|
2015-07-16 16:55:16 -07:00
|
|
|
if (ancestor) {
|
|
|
|
proto.__proto__ = ancestor;
|
|
|
|
}
|
2015-06-19 09:36:51 -07:00
|
|
|
proto = ancestor;
|
|
|
|
}
|
2015-07-16 16:55:16 -07:00
|
|
|
if (!foundPrototype) {
|
|
|
|
console.warn(definition.tag + " prototype not found in prototype chain for " + definition.is);
|
|
|
|
}
|
2015-06-19 09:36:51 -07:00
|
|
|
definition.native = nativePrototype;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
function instantiate(definition) {
|
|
|
|
return upgradeWithDefinition(domCreateElement(definition.tag), definition);
|
|
|
|
}
|
|
|
|
var registry = {};
|
|
|
|
function getRegisteredDefinition(name) {
|
|
|
|
if (name) {
|
|
|
|
return registry[name.toLowerCase()];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
function registerDefinition(name, definition) {
|
|
|
|
registry[name] = definition;
|
|
|
|
}
|
|
|
|
function generateConstructor(definition) {
|
|
|
|
return function() {
|
|
|
|
return instantiate(definition);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
var HTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
|
|
|
|
function createElementNS(namespace, tag, typeExtension) {
|
|
|
|
if (namespace === HTML_NAMESPACE) {
|
|
|
|
return createElement(tag, typeExtension);
|
|
|
|
} else {
|
|
|
|
return domCreateElementNS(namespace, tag);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
function createElement(tag, typeExtension) {
|
|
|
|
if (tag) {
|
|
|
|
tag = tag.toLowerCase();
|
|
|
|
}
|
|
|
|
if (typeExtension) {
|
|
|
|
typeExtension = typeExtension.toLowerCase();
|
|
|
|
}
|
|
|
|
var definition = getRegisteredDefinition(typeExtension || tag);
|
|
|
|
if (definition) {
|
|
|
|
if (tag == definition.tag && typeExtension == definition.is) {
|
|
|
|
return new definition.ctor();
|
|
|
|
}
|
|
|
|
if (!typeExtension && !definition.is) {
|
|
|
|
return new definition.ctor();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
var element;
|
|
|
|
if (typeExtension) {
|
|
|
|
element = createElement(tag);
|
|
|
|
element.setAttribute("is", typeExtension);
|
|
|
|
return element;
|
|
|
|
}
|
|
|
|
element = domCreateElement(tag);
|
|
|
|
if (tag.indexOf("-") >= 0) {
|
|
|
|
implementPrototype(element, HTMLElement);
|
|
|
|
}
|
|
|
|
return element;
|
|
|
|
}
|
|
|
|
var domCreateElement = document.createElement.bind(document);
|
|
|
|
var domCreateElementNS = document.createElementNS.bind(document);
|
|
|
|
var isInstance;
|
|
|
|
if (!Object.__proto__ && !useNative) {
|
|
|
|
isInstance = function(obj, ctor) {
|
2015-07-16 16:55:16 -07:00
|
|
|
if (obj instanceof ctor) {
|
|
|
|
return true;
|
|
|
|
}
|
2015-06-19 09:36:51 -07:00
|
|
|
var p = obj;
|
|
|
|
while (p) {
|
|
|
|
if (p === ctor.prototype) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
p = p.__proto__;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
} else {
|
|
|
|
isInstance = function(obj, base) {
|
|
|
|
return obj instanceof base;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
function wrapDomMethodToForceUpgrade(obj, methodName) {
|
|
|
|
var orig = obj[methodName];
|
|
|
|
obj[methodName] = function() {
|
|
|
|
var n = orig.apply(this, arguments);
|
|
|
|
upgradeAll(n);
|
|
|
|
return n;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
wrapDomMethodToForceUpgrade(Node.prototype, "cloneNode");
|
|
|
|
wrapDomMethodToForceUpgrade(document, "importNode");
|
2015-08-20 20:27:11 -07:00
|
|
|
if (isIE) {
|
2015-06-19 09:36:51 -07:00
|
|
|
(function() {
|
|
|
|
var importNode = document.importNode;
|
|
|
|
document.importNode = function() {
|
|
|
|
var n = importNode.apply(document, arguments);
|
|
|
|
if (n.nodeType == n.DOCUMENT_FRAGMENT_NODE) {
|
|
|
|
var f = document.createDocumentFragment();
|
|
|
|
f.appendChild(n);
|
|
|
|
return f;
|
|
|
|
} else {
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
})();
|
|
|
|
}
|
|
|
|
document.registerElement = register;
|
|
|
|
document.createElement = createElement;
|
|
|
|
document.createElementNS = createElementNS;
|
|
|
|
scope.registry = registry;
|
|
|
|
scope.instanceof = isInstance;
|
|
|
|
scope.reservedTagList = reservedTagList;
|
|
|
|
scope.getRegisteredDefinition = getRegisteredDefinition;
|
|
|
|
document.register = document.registerElement;
|
|
|
|
});
|
|
|
|
|
|
|
|
(function(scope) {
|
|
|
|
var useNative = scope.useNative;
|
|
|
|
var initializeModules = scope.initializeModules;
|
2015-08-20 20:27:11 -07:00
|
|
|
var isIE = scope.isIE;
|
2015-06-19 09:36:51 -07:00
|
|
|
if (useNative) {
|
|
|
|
var nop = function() {};
|
|
|
|
scope.watchShadow = nop;
|
|
|
|
scope.upgrade = nop;
|
|
|
|
scope.upgradeAll = nop;
|
|
|
|
scope.upgradeDocumentTree = nop;
|
|
|
|
scope.upgradeSubtree = nop;
|
|
|
|
scope.takeRecords = nop;
|
|
|
|
scope.instanceof = function(obj, base) {
|
|
|
|
return obj instanceof base;
|
|
|
|
};
|
|
|
|
} else {
|
|
|
|
initializeModules();
|
|
|
|
}
|
|
|
|
var upgradeDocumentTree = scope.upgradeDocumentTree;
|
2015-08-03 17:09:54 -07:00
|
|
|
var upgradeDocument = scope.upgradeDocument;
|
2015-06-19 09:36:51 -07:00
|
|
|
if (!window.wrap) {
|
|
|
|
if (window.ShadowDOMPolyfill) {
|
|
|
|
window.wrap = window.ShadowDOMPolyfill.wrapIfNeeded;
|
|
|
|
window.unwrap = window.ShadowDOMPolyfill.unwrapIfNeeded;
|
|
|
|
} else {
|
|
|
|
window.wrap = window.unwrap = function(node) {
|
|
|
|
return node;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
2015-08-03 17:09:54 -07:00
|
|
|
if (window.HTMLImports) {
|
|
|
|
window.HTMLImports.__importsParsingHook = function(elt) {
|
|
|
|
if (elt.import) {
|
|
|
|
upgradeDocument(wrap(elt.import));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
2015-06-19 09:36:51 -07:00
|
|
|
function bootstrap() {
|
|
|
|
upgradeDocumentTree(window.wrap(document));
|
|
|
|
window.CustomElements.ready = true;
|
2015-08-20 20:27:11 -07:00
|
|
|
var requestAnimationFrame = window.requestAnimationFrame || function(f) {
|
|
|
|
setTimeout(f, 16);
|
|
|
|
};
|
2015-08-05 18:25:27 -07:00
|
|
|
requestAnimationFrame(function() {
|
|
|
|
setTimeout(function() {
|
|
|
|
window.CustomElements.readyTime = Date.now();
|
|
|
|
if (window.HTMLImports) {
|
|
|
|
window.CustomElements.elapsed = window.CustomElements.readyTime - window.HTMLImports.readyTime;
|
|
|
|
}
|
|
|
|
document.dispatchEvent(new CustomEvent("WebComponentsReady", {
|
|
|
|
bubbles: true
|
|
|
|
}));
|
|
|
|
});
|
2015-06-19 09:36:51 -07:00
|
|
|
});
|
|
|
|
}
|
2015-08-20 20:27:11 -07:00
|
|
|
if (isIE && typeof window.CustomEvent !== "function") {
|
2015-06-19 09:36:51 -07:00
|
|
|
window.CustomEvent = function(inType, params) {
|
|
|
|
params = params || {};
|
|
|
|
var e = document.createEvent("CustomEvent");
|
|
|
|
e.initCustomEvent(inType, Boolean(params.bubbles), Boolean(params.cancelable), params.detail);
|
|
|
|
e.preventDefault = function() {
|
|
|
|
Object.defineProperty(this, "defaultPrevented", {
|
|
|
|
get: function() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
return e;
|
|
|
|
};
|
|
|
|
window.CustomEvent.prototype = window.Event.prototype;
|
|
|
|
}
|
|
|
|
if (document.readyState === "complete" || scope.flags.eager) {
|
|
|
|
bootstrap();
|
|
|
|
} else if (document.readyState === "interactive" && !window.attachEvent && (!window.HTMLImports || window.HTMLImports.ready)) {
|
|
|
|
bootstrap();
|
|
|
|
} else {
|
|
|
|
var loadEvent = window.HTMLImports && !window.HTMLImports.ready ? "HTMLImportsLoaded" : "DOMContentLoaded";
|
|
|
|
window.addEventListener(loadEvent, bootstrap);
|
|
|
|
}
|
|
|
|
})(window.CustomElements);
|