UNPKG

aurelia-pal-browser

Version:

The browser-specific implementation of Aurelia's platform abstraction layer.

561 lines (470 loc) 15.3 kB
import { initializePAL, isInitialized } from 'aurelia-pal'; export const _PLATFORM = { location: window.location, history: window.history, addEventListener(eventName, callback, capture) { this.global.addEventListener(eventName, callback, capture); }, removeEventListener(eventName, callback, capture) { this.global.removeEventListener(eventName, callback, capture); }, performance: window.performance, requestAnimationFrame(callback) { return this.global.requestAnimationFrame(callback); } }; if (typeof FEATURE_NO_IE === 'undefined') { function test() {} if (test.name === undefined) { Object.defineProperty(Function.prototype, 'name', { get: function () { let name = this.toString().match(/^\s*function\s*(\S*)\s*\(/)[1]; Object.defineProperty(this, 'name', { value: name }); return name; } }); } } if (typeof FEATURE_NO_IE === 'undefined') { if (!('classList' in document.createElement('_')) || document.createElementNS && !('classList' in document.createElementNS('http://www.w3.org/2000/svg', 'g'))) { let protoProp = 'prototype'; let strTrim = String.prototype.trim; let arrIndexOf = Array.prototype.indexOf; let emptyArray = []; let DOMEx = function (type, message) { this.name = type; this.code = DOMException[type]; this.message = message; }; let checkTokenAndGetIndex = function (classList, token) { if (token === '') { throw new DOMEx('SYNTAX_ERR', 'An invalid or illegal string was specified'); } if (/\s/.test(token)) { throw new DOMEx('INVALID_CHARACTER_ERR', 'String contains an invalid character'); } return arrIndexOf.call(classList, token); }; let ClassList = function (elem) { let trimmedClasses = strTrim.call(elem.getAttribute('class') || ''); let classes = trimmedClasses ? trimmedClasses.split(/\s+/) : emptyArray; for (let i = 0, ii = classes.length; i < ii; ++i) { this.push(classes[i]); } this._updateClassName = function () { elem.setAttribute('class', this.toString()); }; }; let classListProto = ClassList[protoProp] = []; DOMEx[protoProp] = Error[protoProp]; classListProto.item = function (i) { return this[i] || null; }; classListProto.contains = function (token) { token += ''; return checkTokenAndGetIndex(this, token) !== -1; }; classListProto.add = function () { let tokens = arguments; let i = 0; let ii = tokens.length; let token; let updated = false; do { token = tokens[i] + ''; if (checkTokenAndGetIndex(this, token) === -1) { this.push(token); updated = true; } } while (++i < ii); if (updated) { this._updateClassName(); } }; classListProto.remove = function () { let tokens = arguments; let i = 0; let ii = tokens.length; let token; let updated = false; let index; do { token = tokens[i] + ''; index = checkTokenAndGetIndex(this, token); while (index !== -1) { this.splice(index, 1); updated = true; index = checkTokenAndGetIndex(this, token); } } while (++i < ii); if (updated) { this._updateClassName(); } }; classListProto.toggle = function (token, force) { token += ''; let result = this.contains(token); let method = result ? force !== true && 'remove' : force !== false && 'add'; if (method) { this[method](token); } if (force === true || force === false) { return force; } return !result; }; classListProto.toString = function () { return this.join(' '); }; Object.defineProperty(Element.prototype, 'classList', { get: function () { return new ClassList(this); }, enumerable: true, configurable: true }); } else { let testElement = document.createElement('_'); testElement.classList.add('c1', 'c2'); if (!testElement.classList.contains('c2')) { let createMethod = function (method) { let original = DOMTokenList.prototype[method]; DOMTokenList.prototype[method] = function (token) { for (let i = 0, ii = arguments.length; i < ii; ++i) { token = arguments[i]; original.call(this, token); } }; }; createMethod('add'); createMethod('remove'); } testElement.classList.toggle('c3', false); if (testElement.classList.contains('c3')) { let _toggle = DOMTokenList.prototype.toggle; DOMTokenList.prototype.toggle = function (token, force) { if (1 in arguments && !this.contains(token) === !force) { return force; } return _toggle.call(this, token); }; } testElement = null; } } if (typeof FEATURE_NO_IE === 'undefined') { // @license http://opensource.org/licenses/MIT if ('performance' in window === false) { window.performance = {}; } if ('now' in window.performance === false) { let nowOffset = Date.now(); if (performance.timing && performance.timing.navigationStart) { nowOffset = performance.timing.navigationStart; } window.performance.now = function now() { return Date.now() - nowOffset; }; } const startOffset = Date.now ? Date.now() : +new Date(); const _entries = []; const _marksIndex = {}; function _filterEntries(key, value) { var i = 0, n = _entries.length, result = []; for (; i < n; i++) { if (_entries[i][key] == value) { result.push(_entries[i]); } } return result; } function _clearEntries(type, name) { var i = _entries.length, entry; while (i--) { entry = _entries[i]; if (entry.entryType == type && (name === void 0 || entry.name == name)) { _entries.splice(i, 1); } } }; if (!window.performance.mark) { window.performance.mark = window.performance.webkitMark || function (name) { const mark = { name, entryType: "mark", startTime: window.performance.now(), duration: 0 }; _entries.push(mark); _marksIndex[name] = mark; }; } if (!window.performance.measure) { window.performance.measure = window.performance.webkitMeasure || function (name, startMark, endMark) { startMark = _marksIndex[startMark].startTime; endMark = _marksIndex[endMark].startTime; _entries.push({ name, entryType: "measure", startTime: startMark, duration: endMark - startMark }); }; } if (!window.performance.getEntriesByType) { window.performance.getEntriesByType = window.performance.webkitGetEntriesByType || function (type) { return _filterEntries("entryType", type); }; } if (!window.performance.getEntriesByName) { window.performance.getEntriesByName = window.performance.webkitGetEntriesByName || function (name) { return _filterEntries("name", name); }; } if (!window.performance.clearMarks) { window.performance.clearMarks = window.performance.webkitClearMarks || function (name) { _clearEntries("mark", name); }; } if (!window.performance.clearMeasures) { window.performance.clearMeasures = window.performance.webkitClearMeasures || function (name) { _clearEntries("measure", name); }; } _PLATFORM.performance = window.performance; } if (typeof FEATURE_NO_IE === 'undefined') { let con = window.console = window.console || {}; let nop = function () {}; if (!con.memory) con.memory = {}; ('assert,clear,count,debug,dir,dirxml,error,exception,group,' + 'groupCollapsed,groupEnd,info,log,markTimeline,profile,profiles,profileEnd,' + 'show,table,time,timeEnd,timeline,timelineEnd,timeStamp,trace,warn').split(',').forEach(m => { if (!con[m]) con[m] = nop; }); if (typeof con.log === 'object') { 'log,info,warn,error,assert,dir,clear,profile,profileEnd'.split(',').forEach(function (method) { console[method] = this.bind(console[method], console); }, Function.prototype.call); } } if (typeof FEATURE_NO_IE === 'undefined') { if (!window.CustomEvent || typeof window.CustomEvent !== 'function') { let CustomEvent = function (event, params) { params = params || { bubbles: false, cancelable: false, detail: undefined }; let evt = document.createEvent('CustomEvent'); evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail); return evt; }; CustomEvent.prototype = window.Event.prototype; window.CustomEvent = CustomEvent; } } if (Element && !Element.prototype.matches) { let proto = Element.prototype; proto.matches = proto.matchesSelector || proto.mozMatchesSelector || proto.msMatchesSelector || proto.oMatchesSelector || proto.webkitMatchesSelector; } export const _FEATURE = { shadowDOM: !!HTMLElement.prototype.attachShadow, scopedCSS: 'scoped' in document.createElement('style'), htmlTemplateElement: function () { let d = document.createElement('div'); d.innerHTML = '<template></template>'; return 'content' in d.children[0]; }(), mutationObserver: !!(window.MutationObserver || window.WebKitMutationObserver), ensureHTMLTemplateElement: t => t }; if (typeof FEATURE_NO_IE === 'undefined') { function isSVGTemplate(el) { return el.tagName === 'template' && el.namespaceURI === 'http://www.w3.org/2000/svg'; } function fixSVGTemplateElement(el) { let template = el.ownerDocument.createElement('template'); let attrs = el.attributes; let length = attrs.length; let attr; el.parentNode.insertBefore(template, el); while (length-- > 0) { attr = attrs[length]; template.setAttribute(attr.name, attr.value); el.removeAttribute(attr.name); } el.parentNode.removeChild(el); return fixHTMLTemplateElement(template); } function fixHTMLTemplateElement(template) { let content = template.content = document.createDocumentFragment(); let child; while (child = template.firstChild) { content.appendChild(child); } return template; } function fixHTMLTemplateElementRoot(template) { let content = fixHTMLTemplateElement(template).content; let childTemplates = content.querySelectorAll('template'); for (let i = 0, ii = childTemplates.length; i < ii; ++i) { let child = childTemplates[i]; if (isSVGTemplate(child)) { fixSVGTemplateElement(child); } else { fixHTMLTemplateElement(child); } } return template; } if (!_FEATURE.htmlTemplateElement) { _FEATURE.ensureHTMLTemplateElement = fixHTMLTemplateElementRoot; } } let shadowPoly = window.ShadowDOMPolyfill || null; export const _DOM = { Element: Element, NodeList: NodeList, SVGElement: SVGElement, boundary: 'aurelia-dom-boundary', addEventListener(eventName, callback, capture) { document.addEventListener(eventName, callback, capture); }, removeEventListener(eventName, callback, capture) { document.removeEventListener(eventName, callback, capture); }, adoptNode(node) { return document.adoptNode(node); }, createAttribute(name) { return document.createAttribute(name); }, createElement(tagName) { return document.createElement(tagName); }, createTextNode(text) { return document.createTextNode(text); }, createComment(text) { return document.createComment(text); }, createDocumentFragment() { return document.createDocumentFragment(); }, createTemplateElement() { let template = document.createElement('template'); return _FEATURE.ensureHTMLTemplateElement(template); }, createMutationObserver(callback) { return new (window.MutationObserver || window.WebKitMutationObserver)(callback); }, createCustomEvent(eventType, options) { return new window.CustomEvent(eventType, options); }, dispatchEvent(evt) { document.dispatchEvent(evt); }, getComputedStyle(element) { return window.getComputedStyle(element); }, getElementById(id) { return document.getElementById(id); }, querySelector(query) { return document.querySelector(query); }, querySelectorAll(query) { return document.querySelectorAll(query); }, nextElementSibling(element) { if (element.nextElementSibling) { return element.nextElementSibling; } do { element = element.nextSibling; } while (element && element.nodeType !== 1); return element; }, createTemplateFromMarkup(markup) { let parser = document.createElement('div'); parser.innerHTML = markup; let temp = parser.firstElementChild; if (!temp || temp.nodeName !== 'TEMPLATE') { throw new Error('Template markup must be wrapped in a <template> element e.g. <template> <!-- markup here --> </template>'); } return _FEATURE.ensureHTMLTemplateElement(temp); }, appendNode(newNode, parentNode) { (parentNode || document.body).appendChild(newNode); }, replaceNode(newNode, node, parentNode) { if (node.parentNode) { node.parentNode.replaceChild(newNode, node); } else if (shadowPoly !== null) { shadowPoly.unwrap(parentNode).replaceChild(shadowPoly.unwrap(newNode), shadowPoly.unwrap(node)); } else { parentNode.replaceChild(newNode, node); } }, removeNode(node, parentNode) { if (node.parentNode) { node.parentNode.removeChild(node); } else if (parentNode) { if (shadowPoly !== null) { shadowPoly.unwrap(parentNode).removeChild(shadowPoly.unwrap(node)); } else { parentNode.removeChild(node); } } }, injectStyles(styles, destination, prepend, id) { if (id) { let oldStyle = document.getElementById(id); if (oldStyle) { let isStyleTag = oldStyle.tagName.toLowerCase() === 'style'; if (isStyleTag) { oldStyle.innerHTML = styles; return; } throw new Error('The provided id does not indicate a style tag.'); } } let node = document.createElement('style'); node.innerHTML = styles; node.type = 'text/css'; if (id) { node.id = id; } destination = destination || document.head; if (prepend && destination.childNodes.length > 0) { destination.insertBefore(node, destination.childNodes[0]); } else { destination.appendChild(node); } return node; } }; export function initialize() { if (isInitialized) { return; } initializePAL((platform, feature, dom) => { Object.assign(platform, _PLATFORM); Object.assign(feature, _FEATURE); Object.assign(dom, _DOM); Object.defineProperty(dom, 'title', { get: () => document.title, set: value => { document.title = value; } }); Object.defineProperty(dom, 'activeElement', { get: () => document.activeElement }); Object.defineProperty(platform, 'XMLHttpRequest', { get: () => platform.global.XMLHttpRequest }); }); }