/** * @file * @copyright 2013 Andrea Giammarchi, WebReflection * @license MIT */ /* eslint-disable */ (function(window){ 'use strict'; /* jshint loopfunc: true, noempty: false*/ // http://www.w3.org/TR/dom/#element function createDocumentFragment() { return document.createDocumentFragment(); } function createElement(nodeName) { return document.createElement(nodeName); } function enoughArguments(length, name) { if (!length) throw new Error( 'Failed to construct ' + name + ': 1 argument required, but only 0 present.' ); } function mutationMacro(nodes) { if (nodes.length === 1) { return textNodeIfPrimitive(nodes[0]); } for (var fragment = createDocumentFragment(), list = slice.call(nodes), i = 0; i < nodes.length; i++ ) { fragment.appendChild(textNodeIfPrimitive(list[i])); } return fragment; } function textNodeIfPrimitive(node) { return typeof node === 'object' ? node : document.createTextNode(node); } for(var head, property, TemporaryPrototype, TemporaryTokenList, wrapVerifyToken, document = window.document, hOP = Object.prototype.hasOwnProperty, defineProperty = Object.defineProperty || function (object, property, descriptor) { if (hOP.call(descriptor, 'value')) { object[property] = descriptor.value; } else { if (hOP.call(descriptor, 'get')) object.__defineGetter__(property, descriptor.get); if (hOP.call(descriptor, 'set')) object.__defineSetter__(property, descriptor.set); } return object; }, indexOf = [].indexOf || function indexOf(value){ var length = this.length; while(length--) { if (this[length] === value) { break; } } return length; }, // http://www.w3.org/TR/domcore/#domtokenlist verifyToken = function (token) { if (!token) { throw 'SyntaxError'; } else if (spaces.test(token)) { throw 'InvalidCharacterError'; } return token; }, DOMTokenList = function (node) { var noClassName = typeof node.className === 'undefined', className = noClassName ? (node.getAttribute('class') || '') : node.className, isSVG = noClassName || typeof className === 'object', value = (isSVG ? (noClassName ? className : className.baseVal) : className ).replace(trim, '') ; if (value.length) { properties.push.apply( this, value.split(spaces) ); } this._isSVG = isSVG; this._ = node; }, classListDescriptor = { get: function get() { return new DOMTokenList(this); }, set: function(){} }, trim = /^\s+|\s+$/g, spaces = /\s+/, SPACE = '\x20', CLASS_LIST = 'classList', toggle = function toggle(token, force) { if (this.contains(token)) { if (!force) { // force is not true (either false or omitted) this.remove(token); } } else if(force === undefined || force) { force = true; this.add(token); } return !!force; }, DocumentFragmentPrototype = window.DocumentFragment && DocumentFragment.prototype, Node = window.Node, NodePrototype = (Node || Element).prototype, CharacterData = window.CharacterData || Node, CharacterDataPrototype = CharacterData && CharacterData.prototype, DocumentType = window.DocumentType, DocumentTypePrototype = DocumentType && DocumentType.prototype, ElementPrototype = (window.Element || Node || window.HTMLElement).prototype, HTMLSelectElement = window.HTMLSelectElement || createElement('select').constructor, selectRemove = HTMLSelectElement.prototype.remove, SVGElement = window.SVGElement, properties = [ 'matches', ( ElementPrototype.matchesSelector || ElementPrototype.webkitMatchesSelector || ElementPrototype.khtmlMatchesSelector || ElementPrototype.mozMatchesSelector || ElementPrototype.msMatchesSelector || ElementPrototype.oMatchesSelector || function matches(selector) { var parentNode = this.parentNode; return !!parentNode && -1 < indexOf.call( parentNode.querySelectorAll(selector), this ); } ), 'closest', function closest(selector) { var parentNode = this, matches; while ( // document has no .matches (matches = parentNode && parentNode.matches) && !parentNode.matches(selector) ) { parentNode = parentNode.parentNode; } return matches ? parentNode : null; }, 'prepend', function prepend() { var firstChild = this.firstChild, node = mutationMacro(arguments); if (firstChild) { this.insertBefore(node, firstChild); } else { this.appendChild(node); } }, 'append', function append() { this.appendChild(mutationMacro(arguments)); }, 'before', function before() { var parentNode = this.parentNode; if (parentNode) { parentNode.insertBefore( mutationMacro(arguments), this ); } }, 'after', function after() { var parentNode = this.parentNode, nextSibling = this.nextSibling, node = mutationMacro(arguments); if (parentNode) { if (nextSibling) { parentNode.insertBefore(node, nextSibling); } else { parentNode.appendChild(node); } } }, // https://dom.spec.whatwg.org/#dom-element-toggleattribute 'toggleAttribute', function toggleAttribute(name, force) { var had = this.hasAttribute(name); if (1 < arguments.length) { if (had && !force) this.removeAttribute(name); else if (force && !had) this.setAttribute(name, ""); } else if (had) this.removeAttribute(name); else this.setAttribute(name, ""); return this.hasAttribute(name); }, // WARNING - DEPRECATED - use .replaceWith() instead 'replace', function replace() { this.replaceWith.apply(this, arguments); }, 'replaceWith', function replaceWith() { var parentNode = this.parentNode; if (parentNode) { parentNode.replaceChild( mutationMacro(arguments), this ); } }, 'remove', function remove() { var parentNode = this.parentNode; if (parentNode) { parentNode.removeChild(this); } } ], slice = properties.slice, i = properties.length; i; i -= 2 ) { property = properties[i - 2]; if (!(property in ElementPrototype)) { ElementPrototype[property] = properties[i - 1]; } // avoid unnecessary re-patch when the script is included // gazillion times without any reason whatsoever // https://github.com/WebReflection/dom4/pull/48 if (property === 'remove' && !selectRemove._dom4) { // see https://github.com/WebReflection/dom4/issues/19 (HTMLSelectElement.prototype[property] = function () { return 0 < arguments.length ? selectRemove.apply(this, arguments) : ElementPrototype.remove.call(this); })._dom4 = true; } // see https://github.com/WebReflection/dom4/issues/18 if (/^(?:before|after|replace|replaceWith|remove)$/.test(property)) { if (CharacterData && !(property in CharacterDataPrototype)) { CharacterDataPrototype[property] = properties[i - 1]; } if (DocumentType && !(property in DocumentTypePrototype)) { DocumentTypePrototype[property] = properties[i - 1]; } } // see https://github.com/WebReflection/dom4/pull/26 if (/^(?:append|prepend)$/.test(property)) { if (DocumentFragmentPrototype) { if (!(property in DocumentFragmentPrototype)) { DocumentFragmentPrototype[property] = properties[i - 1]; } } else { try { createDocumentFragment().constructor.prototype[property] = properties[i - 1]; } catch(o_O) {} } } } // most likely an IE9 only issue // see https://github.com/WebReflection/dom4/issues/6 if (!createElement('a').matches('a')) { ElementPrototype[property] = function(matches){ return function (selector) { return matches.call( this.parentNode ? this : createDocumentFragment().appendChild(this), selector ); }; }(ElementPrototype[property]); } // used to fix both old webkit and SVG DOMTokenList.prototype = { length: 0, add: function add() { for(var j = 0, token; j < arguments.length; j++) { token = arguments[j]; if(!this.contains(token)) { properties.push.call(this, property); } } if (this._isSVG) { this._.setAttribute('class', '' + this); } else { this._.className = '' + this; } }, contains: (function(indexOf){ return function contains(token) { i = indexOf.call(this, property = verifyToken(token)); return -1 < i; }; }([].indexOf || function (token) { i = this.length; while(i-- && this[i] !== token){} return i; })), item: function item(i) { return this[i] || null; }, remove: function remove() { for(var j = 0, token; j < arguments.length; j++) { token = arguments[j]; if(this.contains(token)) { properties.splice.call(this, i, 1); } } if (this._isSVG) { this._.setAttribute('class', '' + this); } else { this._.className = '' + this; } }, toggle: toggle, toString: function toString() { return properties.join.call(this, SPACE); } }; if (SVGElement && !(CLASS_LIST in SVGElement.prototype)) { defineProperty(SVGElement.prototype, CLASS_LIST, classListDescriptor); } // http://www.w3.org/TR/dom/#domtokenlist // iOS 5.1 has completely screwed this property // classList in ElementPrototype is false // but it's actually there as getter if (!(CLASS_LIST in document.documentElement)) { defineProperty(ElementPrototype, CLASS_LIST, classListDescriptor); } else { // iOS 5.1 and Nokia ASHA do not support multiple add or remove // trying to detect and fix that in here TemporaryTokenList = createElement('div')[CLASS_LIST]; TemporaryTokenList.add('a', 'b', 'a'); if ('a\x20b' != TemporaryTokenList) { // no other way to reach original methods in iOS 5.1 TemporaryPrototype = TemporaryTokenList.constructor.prototype; if (!('add' in TemporaryPrototype)) { // ASHA double fails in here TemporaryPrototype = window.TemporaryTokenList.prototype; } wrapVerifyToken = function (original) { return function () { var i = 0; while (i < arguments.length) { original.call(this, arguments[i++]); } }; }; TemporaryPrototype.add = wrapVerifyToken(TemporaryPrototype.add); TemporaryPrototype.remove = wrapVerifyToken(TemporaryPrototype.remove); // toggle is broken too ^_^ ... let's fix it TemporaryPrototype.toggle = toggle; } } if (!('contains' in NodePrototype)) { defineProperty(NodePrototype, 'contains', { value: function (el) { while (el && el !== this) el = el.parentNode; return this === el; } }); } if (!('head' in document)) { defineProperty(document, 'head', { get: function () { return head || ( head = document.getElementsByTagName('head')[0] ); } }); } // requestAnimationFrame partial polyfill (function () { for (var raf, rAF = window.requestAnimationFrame, cAF = window.cancelAnimationFrame, prefixes = ['o', 'ms', 'moz', 'webkit'], i = prefixes.length; !cAF && i--; ) { rAF = rAF || window[prefixes[i] + 'RequestAnimationFrame']; cAF = window[prefixes[i] + 'CancelAnimationFrame'] || window[prefixes[i] + 'CancelRequestAnimationFrame']; } if (!cAF) { // some FF apparently implemented rAF but no cAF if (rAF) { raf = rAF; rAF = function (callback) { var goOn = true; raf(function () { if (goOn) callback.apply(this, arguments); }); return function () { goOn = false; }; }; cAF = function (id) { id(); }; } else { rAF = function (callback) { return setTimeout(callback, 15, 15); }; cAF = function (id) { clearTimeout(id); }; } } window.requestAnimationFrame = rAF; window.cancelAnimationFrame = cAF; }()); // http://www.w3.org/TR/dom/#customevent try{new window.CustomEvent('?');}catch(o_O){ window.CustomEvent = function( eventName, defaultInitDict ){ // the infamous substitute function CustomEvent(type, eventInitDict) { /*jshint eqnull:true */ var event = document.createEvent(eventName); if (typeof type != 'string') { throw new Error('An event name must be provided'); } if (eventName == 'Event') { event.initCustomEvent = initCustomEvent; } if (eventInitDict == null) { eventInitDict = defaultInitDict; } event.initCustomEvent( type, eventInitDict.bubbles, eventInitDict.cancelable, eventInitDict.detail ); return event; } // attached at runtime function initCustomEvent( type, bubbles, cancelable, detail ) { /*jshint validthis:true*/ this.initEvent(type, bubbles, cancelable); this.detail = detail; } // that's it return CustomEvent; }( // is this IE9 or IE10 ? // where CustomEvent is there // but not usable as construtor ? window.CustomEvent ? // use the CustomEvent interface in such case 'CustomEvent' : 'Event', // otherwise the common compatible one { bubbles: false, cancelable: false, detail: null } ); } // window.Event as constructor try { new Event('_'); } catch (o_O) { /* jshint -W022 */ o_O = (function ($Event) { function Event(type, init) { enoughArguments(arguments.length, 'Event'); var out = document.createEvent('Event'); if (!init) init = {}; out.initEvent( type, !!init.bubbles, !!init.cancelable ); return out; } Event.prototype = $Event.prototype; return Event; }(window.Event || function Event() {})); defineProperty(window, 'Event', {value: o_O}); // Android 4 gotcha if (Event !== o_O) Event = o_O; } // window.KeyboardEvent as constructor try { new KeyboardEvent('_', {}); } catch (o_O) { /* jshint -W022 */ o_O = (function ($KeyboardEvent) { // code inspired by https://gist.github.com/termi/4654819 var initType = 0, defaults = { char: '', key: '', location: 0, ctrlKey: false, shiftKey: false, altKey: false, metaKey: false, altGraphKey: false, repeat: false, locale: navigator.language, detail: 0, bubbles: false, cancelable: false, keyCode: 0, charCode: 0, which: 0 }, eventType ; try { var e = document.createEvent('KeyboardEvent'); e.initKeyboardEvent( 'keyup', false, false, window, '+', 3, true, false, true, false, false ); initType = ( (e.keyIdentifier || e.key) == '+' && (e.keyLocation || e.location) == 3 ) && ( e.ctrlKey ? e.altKey ? 1 : 3 : e.shiftKey ? 2 : 4 ) || 9; } catch(o_O) {} eventType = 0 < initType ? 'KeyboardEvent' : 'Event'; function getModifier(init) { for (var out = [], keys = [ 'ctrlKey', 'Control', 'shiftKey', 'Shift', 'altKey', 'Alt', 'metaKey', 'Meta', 'altGraphKey', 'AltGraph' ], i = 0; i < keys.length; i += 2 ) { if (init[keys[i]]) out.push(keys[i + 1]); } return out.join(' '); } function withDefaults(target, source) { for (var key in source) { if ( source.hasOwnProperty(key) && !source.hasOwnProperty.call(target, key) ) target[key] = source[key]; } return target; } function withInitValues(key, out, init) { try { out[key] = init[key]; } catch(o_O) {} } function KeyboardEvent(type, init) { enoughArguments(arguments.length, 'KeyboardEvent'); init = withDefaults(init || {}, defaults); var out = document.createEvent(eventType), ctrlKey = init.ctrlKey, shiftKey = init.shiftKey, altKey = init.altKey, metaKey = init.metaKey, altGraphKey = init.altGraphKey, modifiers = initType > 3 ? getModifier(init) : null, key = String(init.key), chr = String(init.char), location = init.location, keyCode = init.keyCode || ( (init.keyCode = key) && key.charCodeAt(0) ) || 0, charCode = init.charCode || ( (init.charCode = chr) && chr.charCodeAt(0) ) || 0, bubbles = init.bubbles, cancelable = init.cancelable, repeat = init.repeat, locale = init.locale, view = init.view || window, args ; if (!init.which) init.which = init.keyCode; if ('initKeyEvent' in out) { out.initKeyEvent( type, bubbles, cancelable, view, ctrlKey, altKey, shiftKey, metaKey, keyCode, charCode ); } else if (0 < initType && 'initKeyboardEvent' in out) { args = [type, bubbles, cancelable, view]; switch (initType) { case 1: args.push(key, location, ctrlKey, shiftKey, altKey, metaKey, altGraphKey); break; case 2: args.push(ctrlKey, altKey, shiftKey, metaKey, keyCode, charCode); break; case 3: args.push(key, location, ctrlKey, altKey, shiftKey, metaKey, altGraphKey); break; case 4: args.push(key, location, modifiers, repeat, locale); break; default: args.push(char, key, location, modifiers, repeat, locale); } out.initKeyboardEvent.apply(out, args); } else { out.initEvent(type, bubbles, cancelable); } for (key in out) { if (defaults.hasOwnProperty(key) && out[key] !== init[key]) { withInitValues(key, out, init); } } return out; } KeyboardEvent.prototype = $KeyboardEvent.prototype; return KeyboardEvent; }(window.KeyboardEvent || function KeyboardEvent() {})); defineProperty(window, 'KeyboardEvent', {value: o_O}); // Android 4 gotcha if (KeyboardEvent !== o_O) KeyboardEvent = o_O; } // window.MouseEvent as constructor try { new MouseEvent('_', {}); } catch (o_O) { /* jshint -W022 */ o_O = (function ($MouseEvent) { function MouseEvent(type, init) { enoughArguments(arguments.length, 'MouseEvent'); var out = document.createEvent('MouseEvent'); if (!init) init = {}; out.initMouseEvent( type, !!init.bubbles, !!init.cancelable, init.view || window, init.detail || 1, init.screenX || 0, init.screenY || 0, init.clientX || 0, init.clientY || 0, !!init.ctrlKey, !!init.altKey, !!init.shiftKey, !!init.metaKey, init.button || 0, init.relatedTarget || null ); return out; } MouseEvent.prototype = $MouseEvent.prototype; return MouseEvent; }(window.MouseEvent || function MouseEvent() {})); defineProperty(window, 'MouseEvent', {value: o_O}); // Android 4 gotcha if (MouseEvent !== o_O) MouseEvent = o_O; } if (!document.querySelectorAll('*').forEach) { (function () { function patch(what) { var querySelectorAll = what.querySelectorAll; what.querySelectorAll = function qSA(css) { var result = querySelectorAll.call(this, css); result.forEach = Array.prototype.forEach; return result; }; } patch(document); patch(Element.prototype); }()); } try { // https://drafts.csswg.org/selectors-4/#the-scope-pseudo document.querySelector(':scope *'); } catch(o_O) { (function () { var dataScope = 'data-scope-' + (Math.random() * 1e9 >>> 0); var proto = Element.prototype; var querySelector = proto.querySelector; var querySelectorAll = proto.querySelectorAll; proto.querySelector = function qS(css) { return find(this, querySelector, css); }; proto.querySelectorAll = function qSA(css) { return find(this, querySelectorAll, css); }; function find(node, method, css) { node.setAttribute(dataScope, null); var result = method.call( node, String(css).replace( /(^|,\s*)(:scope([ >]|$))/g, function ($0, $1, $2, $3) { return $1 + '[' + dataScope + ']' + ($3 || ' '); } ) ); node.removeAttribute(dataScope); return result; } }()); } }(window)); (function (global){'use strict'; // a WeakMap fallback for DOM nodes only used as key var DOMMap = global.WeakMap || (function () { var counter = 0, dispatched = false, drop = false, value ; function dispatch(key, ce, shouldDrop) { drop = shouldDrop; dispatched = false; value = undefined; key.dispatchEvent(ce); } function Handler(value) { this.value = value; } Handler.prototype.handleEvent = function handleEvent(e) { dispatched = true; if (drop) { e.currentTarget.removeEventListener(e.type, this, false); } else { value = this.value; } }; function DOMMap() { counter++; // make id clashing highly improbable this.__ce__ = new Event(('@DOMMap:' + counter) + Math.random()); } DOMMap.prototype = { 'constructor': DOMMap, 'delete': function del(key) { return dispatch(key, this.__ce__, true), dispatched; }, 'get': function get(key) { dispatch(key, this.__ce__, false); var v = value; value = undefined; return v; }, 'has': function has(key) { return dispatch(key, this.__ce__, false), dispatched; }, 'set': function set(key, value) { dispatch(key, this.__ce__, true); key.addEventListener(this.__ce__.type, new Handler(value), false); return this; }, }; return DOMMap; }()); function Dict() {} Dict.prototype = (Object.create || Object)(null); // https://dom.spec.whatwg.org/#interface-eventtarget function createEventListener(type, callback, options) { function eventListener(e) { if (eventListener.once) { e.currentTarget.removeEventListener( e.type, callback, eventListener ); eventListener.removed = true; } if (eventListener.passive) { e.preventDefault = createEventListener.preventDefault; } if (typeof eventListener.callback === 'function') { /* jshint validthis: true */ eventListener.callback.call(this, e); } else if (eventListener.callback) { eventListener.callback.handleEvent(e); } if (eventListener.passive) { delete e.preventDefault; } } eventListener.type = type; eventListener.callback = callback; eventListener.capture = !!options.capture; eventListener.passive = !!options.passive; eventListener.once = !!options.once; // currently pointless but specs say to use it, so ... eventListener.removed = false; return eventListener; } createEventListener.preventDefault = function preventDefault() {}; var Event = global.CustomEvent, dE = global.dispatchEvent, aEL = global.addEventListener, rEL = global.removeEventListener, counter = 0, increment = function () { counter++; }, indexOf = [].indexOf || function indexOf(value){ var length = this.length; while(length--) { if (this[length] === value) { break; } } return length; }, getListenerKey = function (options) { return ''.concat( options.capture ? '1' : '0', options.passive ? '1' : '0', options.once ? '1' : '0' ); }, augment ; try { aEL('_', increment, {once: true}); dE(new Event('_')); dE(new Event('_')); rEL('_', increment, {once: true}); } catch(o_O) {} if (counter !== 1) { (function () { var dm = new DOMMap(); function createAEL(aEL) { return function addEventListener(type, handler, options) { if (options && typeof options !== 'boolean') { var info = dm.get(this), key = getListenerKey(options), i, tmp, wrap ; if (!info) dm.set(this, (info = new Dict())); if (!(type in info)) info[type] = { handler: [], wrap: [] }; tmp = info[type]; i = indexOf.call(tmp.handler, handler); if (i < 0) { i = tmp.handler.push(handler) - 1; tmp.wrap[i] = (wrap = new Dict()); } else { wrap = tmp.wrap[i]; } if (!(key in wrap)) { wrap[key] = createEventListener(type, handler, options); aEL.call(this, type, wrap[key], wrap[key].capture); } } else { aEL.call(this, type, handler, options); } }; } function createREL(rEL) { return function removeEventListener(type, handler, options) { if (options && typeof options !== 'boolean') { var info = dm.get(this), key, i, tmp, wrap ; if (info && (type in info)) { tmp = info[type]; i = indexOf.call(tmp.handler, handler); if (-1 < i) { key = getListenerKey(options); wrap = tmp.wrap[i]; if (key in wrap) { rEL.call(this, type, wrap[key], wrap[key].capture); delete wrap[key]; // return if there are other wraps for (key in wrap) return; // otherwise remove all the things tmp.handler.splice(i, 1); tmp.wrap.splice(i, 1); // if there are no other handlers if (tmp.handler.length === 0) // drop the info[type] entirely delete info[type]; } } } } else { rEL.call(this, type, handler, options); } }; } augment = function (Constructor) { if (!Constructor) return; var proto = Constructor.prototype; proto.addEventListener = createAEL(proto.addEventListener); proto.removeEventListener = createREL(proto.removeEventListener); }; if (global.EventTarget) { augment(EventTarget); } else { augment(global.Text); augment(global.Element || global.HTMLElement); augment(global.HTMLDocument); augment(global.Window || {prototype:global}); augment(global.XMLHttpRequest); } }()); } }(window));