// Composited file - DO NOT EDIT (function(global) { 'use strict'; if (!('window' in global && 'document' in global)) return; //---------------------------------------------------------------------- // // HTML // https://html.spec.whatwg.org // //---------------------------------------------------------------------- // document.head attribute // Needed for: IE8- if (!('head' in document)) document.head = document.getElementsByTagName('head')[0]; // Ensure correct parsing of newish elements ("shiv") // Needed for: IE8- [ 'abbr', 'article', 'aside', 'audio', 'bdi', 'canvas', 'data', 'datalist', 'details', 'dialog', 'figcaption', 'figure', 'footer', 'header', 'hgroup', 'main', 'mark', 'meter', 'nav', 'output', 'picture', 'progress', 'section', 'summary', 'template', 'time', 'video'].forEach(function(tag) { document.createElement(tag); }); // HTMLElement.dataset // Needed for: IE10- if (!('dataset' in document.createElement('span')) && 'Element' in global && Element.prototype && Object.defineProperty) { Object.defineProperty(Element.prototype, 'dataset', { get: function() { var result = Object.create(null); for (var i = 0; i < this.attributes.length; ++i) { var attr = this.attributes[i]; if (attr.specified && attr.name.substring(0, 5) === 'data-') { (function(element, name) { var prop = name.replace(/-([a-z])/g, function(m, p) { return p.toUpperCase(); }); result[prop] = element.getAttribute('data-' + name); // Read-only, for IE8- Object.defineProperty(result, prop, { get: function() { return element.getAttribute('data-' + name); }, set: function(value) { element.setAttribute('data-' + name, value); }}); }(this, attr.name.substring(5))); } } return result; }}); } // Base64 utility methods // Needed for: IE9- (function() { if ('atob' in global && 'btoa' in global) return; var B64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; function atob(input) { input = String(input); var position = 0, output = [], buffer = 0, bits = 0, n; input = input.replace(/\s/g, ''); if ((input.length % 4) === 0) { input = input.replace(/=+$/, ''); } if ((input.length % 4) === 1) { throw Error("InvalidCharacterError"); } if (/[^+/0-9A-Za-z]/.test(input)) { throw Error("InvalidCharacterError"); } while (position < input.length) { n = B64_ALPHABET.indexOf(input.charAt(position)); buffer = (buffer << 6) | n; bits += 6; if (bits === 24) { output.push(String.fromCharCode((buffer >> 16) & 0xFF)); output.push(String.fromCharCode((buffer >> 8) & 0xFF)); output.push(String.fromCharCode(buffer & 0xFF)); bits = 0; buffer = 0; } position += 1; } if (bits === 12) { buffer = buffer >> 4; output.push(String.fromCharCode(buffer & 0xFF)); } else if (bits === 18) { buffer = buffer >> 2; output.push(String.fromCharCode((buffer >> 8) & 0xFF)); output.push(String.fromCharCode(buffer & 0xFF)); } return output.join(''); }; function btoa(input) { input = String(input); var position = 0, out = [], o1, o2, o3, e1, e2, e3, e4; if (/[^\x00-\xFF]/.test(input)) { throw Error("InvalidCharacterError"); } while (position < input.length) { o1 = input.charCodeAt(position++); o2 = input.charCodeAt(position++); o3 = input.charCodeAt(position++); // 111111 112222 222233 333333 e1 = o1 >> 2; e2 = ((o1 & 0x3) << 4) | (o2 >> 4); e3 = ((o2 & 0xf) << 2) | (o3 >> 6); e4 = o3 & 0x3f; if (position === input.length + 2) { e3 = 64; e4 = 64; } else if (position === input.length + 1) { e4 = 64; } out.push(B64_ALPHABET.charAt(e1), B64_ALPHABET.charAt(e2), B64_ALPHABET.charAt(e3), B64_ALPHABET.charAt(e4)); } return out.join(''); }; global.atob = atob; global.btoa = btoa; }()); // requestAnimationFrame - needed for IE9- (function() { if ('requestAnimationFrame' in global) return; var TARGET_FPS = 60, requests = Object.create(null), raf_handle = 0, timeout_handle = -1; function isVisible(element) { return element.offsetWidth > 0 && element.offsetHeight > 0; } function onFrameTimer() { var cur_requests = requests; requests = Object.create(null); timeout_handle = -1; Object.keys(cur_requests).forEach(function(id) { var request = cur_requests[id]; if (!request.element || isVisible(request.element)) request.callback(Date.now()); }); } function requestAnimationFrame(callback, element) { var cb_handle = ++raf_handle; requests[cb_handle] = {callback: callback, element: element}; if (timeout_handle === -1) timeout_handle = global.setTimeout(onFrameTimer, 1000 / TARGET_FPS); return cb_handle; } function cancelAnimationFrame(handle) { delete requests[handle]; if (Object.keys(requests).length === 0) { global.clearTimeout(timeout_handle); timeout_handle = -1; } } global.requestAnimationFrame = requestAnimationFrame; global.cancelAnimationFrame = cancelAnimationFrame; }()); }(self)); (function(global) { 'use strict'; if (!('window' in global && 'document' in global)) return; //---------------------------------------------------------------------- // // DOM // https://dom.spec.whatwg.org/ // //---------------------------------------------------------------------- // Document.querySelectorAll method // http://ajaxian.com/archives/creating-a-queryselector-for-ie-that-runs-at-native-speed // Needed for: IE7- if (!document.querySelectorAll) { document.querySelectorAll = function(selectors) { var style = document.createElement('style'), elements = [], element; document.documentElement.firstChild.appendChild(style); document._qsa = []; style.styleSheet.cssText = selectors + '{x-qsa:expression(document._qsa && document._qsa.push(this))}'; window.scrollBy(0, 0); style.parentNode.removeChild(style); while (document._qsa.length) { element = document._qsa.shift(); element.style.removeAttribute('x-qsa'); elements.push(element); } document._qsa = null; return elements; }; } // Document.querySelector method // Needed for: IE7- if (!document.querySelector) { document.querySelector = function(selectors) { var elements = document.querySelectorAll(selectors); return (elements.length) ? elements[0] : null; }; } // Document.getElementsByClassName method // Needed for: IE8- if (!document.getElementsByClassName) { document.getElementsByClassName = function(classNames) { classNames = String(classNames).replace(/^|\s+/g, '.'); return document.querySelectorAll(classNames); }; } // Node interface constants // Needed for: IE8- global.Node = global.Node || function() { throw TypeError("Illegal constructor"); }; [ ['ELEMENT_NODE', 1], ['ATTRIBUTE_NODE', 2], ['TEXT_NODE', 3], ['CDATA_SECTION_NODE', 4], ['ENTITY_REFERENCE_NODE', 5], ['ENTITY_NODE', 6], ['PROCESSING_INSTRUCTION_NODE', 7], ['COMMENT_NODE', 8], ['DOCUMENT_NODE', 9], ['DOCUMENT_TYPE_NODE', 10], ['DOCUMENT_FRAGMENT_NODE', 11], ['NOTATION_NODE', 12] ].forEach(function(p) { if (!(p[0] in global.Node)) global.Node[p[0]] = p[1]; }); // DOMException constants // Needed for: IE8- global.DOMException = global.DOMException || function() { throw TypeError("Illegal constructor"); }; [ ['INDEX_SIZE_ERR', 1], ['DOMSTRING_SIZE_ERR', 2], ['HIERARCHY_REQUEST_ERR', 3], ['WRONG_DOCUMENT_ERR', 4], ['INVALID_CHARACTER_ERR', 5], ['NO_DATA_ALLOWED_ERR', 6], ['NO_MODIFICATION_ALLOWED_ERR', 7], ['NOT_FOUND_ERR', 8], ['NOT_SUPPORTED_ERR', 9], ['INUSE_ATTRIBUTE_ERR', 10], ['INVALID_STATE_ERR', 11], ['SYNTAX_ERR', 12], ['INVALID_MODIFICATION_ERR', 13], ['NAMESPACE_ERR', 14], ['INVALID_ACCESS_ERR', 15] ].forEach(function(p) { if (!(p[0] in global.DOMException)) global.DOMException[p[0]] = p[1]; }); // Event and EventTargets interfaces // Needed for: IE8 (function(){ if (!('Element' in global) || Element.prototype.addEventListener || !Object.defineProperty) return; // interface Event // PhaseType (const unsigned short) Event.CAPTURING_PHASE = 1; Event.AT_TARGET = 2; Event.BUBBLING_PHASE = 3; Object.defineProperties(Event.prototype, { CAPTURING_PHASE: { get: function() { return 1; } }, AT_TARGET: { get: function() { return 2; } }, BUBBLING_PHASE: { get: function() { return 3; } }, target: { get: function() { return this.srcElement; }}, currentTarget: { get: function() { return this._currentTarget; }}, eventPhase: { get: function() { return (this.srcElement === this.currentTarget) ? Event.AT_TARGET : Event.BUBBLING_PHASE; }}, bubbles: { get: function() { switch (this.type) { // Mouse case 'click': case 'dblclick': case 'mousedown': case 'mouseup': case 'mouseover': case 'mousemove': case 'mouseout': case 'mousewheel': // Keyboard case 'keydown': case 'keypress': case 'keyup': // Frame/Object case 'resize': case 'scroll': // Form case 'select': case 'change': case 'submit': case 'reset': return true; } return false; }}, cancelable: { get: function() { switch (this.type) { // Mouse case 'click': case 'dblclick': case 'mousedown': case 'mouseup': case 'mouseover': case 'mouseout': case 'mousewheel': // Keyboard case 'keydown': case 'keypress': case 'keyup': // Form case 'submit': return true; } return false; }}, timeStamp: { get: function() { return this._timeStamp; }}, stopPropagation: { value: function() { this.cancelBubble = true; }}, preventDefault: { value: function() { this.returnValue = false; }}, defaultPrevented: { get: function() { return this.returnValue === false; }} }); // interface EventTarget function addEventListener(type, listener, useCapture) { if (typeof listener !== 'function') return; if (type === 'DOMContentLoaded') type = 'load'; var target = this; var f = function(e) { e._timeStamp = Date.now(); e._currentTarget = target; listener.call(this, e); e._currentTarget = null; }; this['_' + type + listener] = f; this.attachEvent('on' + type, f); } function removeEventListener(type, listener, useCapture) { if (typeof listener !== 'function') return; if (type === 'DOMContentLoaded') type = 'load'; var f = this['_' + type + listener]; if (f) { this.detachEvent('on' + type, f); this['_' + type + listener] = null; } } [Window, HTMLDocument, Element].forEach(function(o) { o.prototype.addEventListener = addEventListener; o.prototype.removeEventListener = removeEventListener; }); }()); // CustomEvent // https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent // Needed for: IE (function () { if ('CustomEvent' in global && typeof global.CustomEvent === "function") return; function CustomEvent ( event, params ) { params = params || { bubbles: false, cancelable: false, detail: undefined }; var evt = document.createEvent( 'CustomEvent' ); evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail ); return evt; } CustomEvent.prototype = global.Event.prototype; global.CustomEvent = CustomEvent; })(); // Shim for DOM Events for IE7- // http://www.quirksmode.org/blog/archives/2005/10/_and_the_winner_1.html // Use addEvent(object, event, handler) instead of object.addEventListener(event, handler) window.addEvent = function(obj, type, fn) { if (obj.addEventListener) { obj.addEventListener(type, fn, false); } else if (obj.attachEvent) { obj["e" + type + fn] = fn; obj[type + fn] = function() { var e = window.event; e.currentTarget = obj; e.preventDefault = function() { e.returnValue = false; }; e.stopPropagation = function() { e.cancelBubble = true; }; e.target = e.srcElement; e.timeStamp = Date.now(); obj["e" + type + fn].call(this, e); }; obj.attachEvent("on" + type, obj[type + fn]); } }; window.removeEvent = function(obj, type, fn) { if (obj.removeEventListener) { obj.removeEventListener(type, fn, false); } else if (obj.detachEvent) { obj.detachEvent("on" + type, obj[type + fn]); obj[type + fn] = null; obj["e" + type + fn] = null; } }; function addToElementPrototype(p, f) { if ('Element' in global && Element.prototype && Object.defineProperty) { Object.defineProperty(Element.prototype, p, { get: f }); } } // DOMTokenList interface and Element.classList / Element.relList // Needed for: IE9- // Use getClassList(elem) instead of elem.classList() if IE7- support is needed // Use getRelList(elem) instead of elem.relList() if IE7- support is needed (function() { function DOMTokenListShim(o, p) { function split(s) { return s.length ? s.split(/\s+/g) : []; } // NOTE: This does not exactly match the spec. function removeTokenFromString(token, string) { var tokens = split(string), index = tokens.indexOf(token); if (index !== -1) { tokens.splice(index, 1); } return tokens.join(' '); } Object.defineProperties( this, { length: { get: function() { return split(o[p]).length; } }, item: { value: function(idx) { var tokens = split(o[p]); return 0 <= idx && idx < tokens.length ? tokens[idx] : null; } }, contains: { value: function(token) { token = String(token); var tokens = split(o[p]); return tokens.indexOf(token) !== -1; } }, add: { value: function(/*tokens...*/) { var tokens = Array.prototype.slice.call(arguments).map(String); if (tokens.some(function(token) { return token.length === 0; })) { throw SyntaxError(); } if (tokens.some(function(token) { return (/\s/).test(token); })) { throw Error("InvalidCharacterError"); } try { var underlying_string = o[p]; var token_list = split(underlying_string); tokens = tokens.filter(function(token) { return token_list.indexOf(token) === -1; }); if (tokens.length === 0) { return; } if (underlying_string.length !== 0 && !(/\s$/).test(underlying_string)) { underlying_string += ' '; } underlying_string += tokens.join(' '); o[p] = underlying_string; } finally { var length = split(o[p]).length; if (this.length !== length) { this.length = length; } } } }, remove: { value: function(/*tokens...*/) { var tokens = Array.prototype.slice.call(arguments).map(String); if (tokens.some(function(token) { return token.length === 0; })) { throw SyntaxError(); } if (tokens.some(function(token) { return (/\s/).test(token); })) { throw Error("InvalidCharacterError"); } try { var underlying_string = o[p]; tokens.forEach(function(token) { underlying_string = removeTokenFromString(token, underlying_string); }); o[p] = underlying_string; } finally { var length = split(o[p]).length; if (this.length !== length) { this.length = length; } } } }, toggle: { value: function(token/*, force*/) { var force = arguments[1]; try { token = String(token); if (token.length === 0) { throw SyntaxError(); } if (/\s/.test(token)) { throw Error("InvalidCharacterError"); } var tokens = split(o[p]), index = tokens.indexOf(token); if (index !== -1 && (!force || force === (void 0))) { o[p] = removeTokenFromString(token, o[p]); return false; } if (index !== -1 && force) { return true; } var underlying_string = o[p]; if (underlying_string.length !== 0 && !/\s$/.test(underlying_string)) { underlying_string += ' '; } underlying_string += token; o[p] = underlying_string; return true; } finally { var length = split(o[p]).length; if (this.length !== length) { this.length = length; } } } }, toString: { value: function() { return o[p]; } } }); if (!('length' in this)) { // In case getters are not supported this.length = split(o[p]).length; } else { // If they are, shim in index getters (up to 100) for (var i = 0; i < 100; ++i) { Object.defineProperty(this, String(i), { get: (function(n) { return function() { return this.item(n); }; }(i)) }); } } } // HTML - https://html.spec.whatwg.org // Element.classList if ('classList' in document.createElement('span')) { window.getClassList = function(elem) { return elem.classList; }; } else { window.getClassList = function(elem) { return new DOMTokenListShim(elem, 'className'); }; addToElementPrototype('classList', function() { return new DOMTokenListShim(this, 'className'); } ); } // HTML - https://html.spec.whatwg.org // HTMLAnchorElement.relList // HTMLLinkElement.relList if ('relList' in document.createElement('link')) { window.getRelList = function(elem) { return elem.relList; }; } else { window.getRelList = function(elem) { return new DOMTokenListShim(elem, 'rel'); }; addToElementPrototype('relList', function() { return new DOMTokenListShim(this, 'rel'); } ); } // Add second argument to native DOMTokenList.toggle() if necessary (function() { if (!('DOMTokenList' in global)) return; var e = document.createElement('span'); if (!('classList' in e)) return; e.classList.toggle('x', false); if (!e.classList.contains('x')) return; global.DOMTokenList.prototype.toggle = function toggle(token/*, force*/) { var force = arguments[1]; if (force === undefined) { var add = !this.contains(token); this[add ? 'add' : 'remove'](token); return add; } force = !!force; this[force ? 'add' : 'remove'](token); return force; }; }()); }()); // Interface NonDocumentTypeChildNode // previousElementSibling / nextElementSibling - for IE8 if (!('previousElementSibling' in document.documentElement)) { addToElementPrototype('previousElementSibling', function() { var n = this.previousSibling; while (n && n.nodeType !== Node.ELEMENT_NODE) n = n.previousSibling; return n; }); } if (!('nextElementSibling' in document.documentElement)) { addToElementPrototype('nextElementSibling', function() { var n = this.nextSibling; while (n && n.nodeType !== Node.ELEMENT_NODE) n = n.nextSibling; return n; }); } // Element.matches // https://developer.mozilla.org/en/docs/Web/API/Element/matches // Needed for: IE, Firefox 3.6, early Webkit and Opera 15.0 // Use msMatchesSelector(selector) for IE // Use oMatchesSelector(selector) for Opera 15.0 // Use mozMatchesSelector(selector) for Firefox 3.6 // Use webkitMatchesSelector(selector) for early Webkit // Use polyfill if no matches() support, but querySelectorAll() support if ('Element' in global && !Element.prototype.matches) { if (Element.prototype.msMatchesSelector) { Element.prototype.matches = Element.prototype.msMatchesSelector; } else if (Element.prototype.oMatchesSelector) { Element.prototype.matches = Element.prototype.oMatchesSelector; } else if (Element.prototype.mozMatchesSelector) { Element.prototype.matches = Element.prototype.mozMatchesSelector; } else if (Element.prototype.webkitMatchesSelector) { Element.prototype.matches = Element.prototype.webkitMatchesSelector; } else if (document.querySelectorAll) { Element.prototype.matches = function matches(selector) { var matches = (this.document || this.ownerDocument).querySelectorAll(selector), i = matches.length; while (--i >= 0 && matches.item(i) !== this) {} return i > -1; }; } } // Element.closest // https://developer.mozilla.org/en-US/docs/Web/API/Element/closest if (window.Element && !Element.prototype.closest) { Element.prototype.closest = function(s) { var matches = (this.document || this.ownerDocument).querySelectorAll(s), i, el = this; do { i = matches.length; while (--i >= 0 && matches.item(i) !== el) {}; } while ((i < 0) && (el = el.parentElement)); return el; }; } function mixin(o, ps) { if (!o) return; Object.keys(ps).forEach(function(p) { if ((p in o) || (p in o.prototype)) return; try { Object.defineProperty( o.prototype, p, Object.getOwnPropertyDescriptor(ps, p) ); } catch (ex) { // Throws in IE8; just copy it o[p] = ps[p]; } }); } // Mixin ParentNode // https://dom.spec.whatwg.org/#interface-parentnode function convertNodesIntoANode(nodes) { var node = null; nodes = nodes.map(function(node) { return !(node instanceof Node) ? document.createTextNode(node) : node; }); if (nodes.length === 1) { node = nodes[0]; } else { node = document.createDocumentFragment(); nodes.forEach(function(n) { node.appendChild(n); }); } return node; } var ParentNode = { prepend: function(/*...nodes*/) { var nodes = [].slice.call(arguments); nodes = convertNodesIntoANode(nodes); this.insertBefore(nodes, this.firstChild); }, append: function(/*...nodes*/) { var nodes = [].slice.call(arguments); nodes = convertNodesIntoANode(nodes); this.appendChild(nodes); } }; mixin(global.Document || global.HTMLDocument, ParentNode); // HTMLDocument for IE8 mixin(global.DocumentFragment, ParentNode); mixin(global.Element, ParentNode); // Attributes for IE8 if (!('firstElementChild' in document.documentElement)) { addToElementPrototype('firstElementChild', function() { for (var nodes = this.children, i = 0, l = nodes.length; i < l; ++i) { var n = nodes[i]; if (n.nodeType === Node.ELEMENT_NODE) return n; } return null; }); } if (!('lastElementChild' in document.documentElement)) { addToElementPrototype('lastElementChild', function() { for (var nodes = this.children, i = nodes.length - 1; i >= 0; --i) { var n = nodes[i]; if (n.nodeType === Node.ELEMENT_NODE) return n; } return null; }); } if (!('childElementCount' in document.documentElement)) { addToElementPrototype('childElementCount', function() { for (var c = 0, nodes = this.children, i = 0, l = nodes.length; i < l; ++i) { if (nodes[i].nodeType === Node.ELEMENT_NODE) ++c; } return c; }); } // Mixin ChildNode // https://dom.spec.whatwg.org/#interface-childnode var ChildNode = { before: function(/*...nodes*/) { var nodes = [].slice.call(arguments); var parent = this.parentNode; if (!parent) return; var viablePreviousSibling = this.previousSibling; while (nodes.indexOf(viablePreviousSibling) !== -1) viablePreviousSibling = viablePreviousSibling.previousSibling; var node = convertNodesIntoANode(nodes); parent.insertBefore(node, viablePreviousSibling ? viablePreviousSibling.nextSibling : parent.firstChild); }, after: function(/*...nodes*/) { var nodes = [].slice.call(arguments); var parent = this.parentNode; if (!parent) return; var viableNextSibling = this.nextSibling; while (nodes.indexOf(viableNextSibling) !== -1) viableNextSibling = viableNextSibling.nextSibling; var node = convertNodesIntoANode(nodes); parent.insertBefore(node, viableNextSibling); }, replaceWith: function(/*...nodes*/) { var nodes = [].slice.call(arguments); var parent = this.parentNode; if (!parent) return; var viableNextSibling = this.nextSibling; while (nodes.indexOf(viableNextSibling) !== -1) viableNextSibling = viableNextSibling.nextSibling; var node = convertNodesIntoANode(nodes); if (this.parentNode === parent) parent.replaceChild(node, this); else parent.insertBefore(node, viableNextSibling); }, remove: function() { if (!this.parentNode) return; this.parentNode.removeChild(this); } }; mixin(global.DocumentType, ChildNode); mixin(global.Element, ChildNode); mixin(global.CharacterData, ChildNode); }(self)); (function(global) { 'use strict'; if (!('window' in global && 'document' in global)) return; //---------------------------------------------------------------------- // // XMLHttpRequest // https://xhr.spec.whatwg.org // //---------------------------------------------------------------------- // XMLHttpRequest interface // Needed for: IE7- global.XMLHttpRequest = global.XMLHttpRequest || function() { try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } catch (_) { } try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } catch (_) { } try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (_) { } throw Error("This browser does not support XMLHttpRequest."); }; // XMLHttpRequest interface constants // Needed for IE8- [ ['UNSENT', 0], ['OPENED', 1], ['HEADERS_RECEIVED', 2], ['LOADING', 3], ['DONE', 4], ].forEach(function(p) { if (!(p[0] in global.XMLHttpRequest)) global.XMLHttpRequest[p[0]] = p[1]; }); // FormData interface // Needed for: IE9- (function() { if ('FormData' in global) return; function FormData(form) { this._data = []; if (!form) return; for (var i = 0; i < form.elements.length; ++i) { var element = form.elements[i]; if (element.name !== '') this.append(element.name, element.value); } } FormData.prototype = { append: function(name, value /*, filename */) { if ('Blob' in global && value instanceof global.Blob) throw TypeError("Blob not supported"); name = String(name); this._data.push([name, value]); }, toString: function() { return this._data.map(function(pair) { return encodeURIComponent(pair[0]) + '=' + encodeURIComponent(pair[1]); }).join('&'); } }; global.FormData = FormData; var send = global.XMLHttpRequest.prototype.send; global.XMLHttpRequest.prototype.send = function(body) { if (body instanceof FormData) { this.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); arguments[0] = body.toString(); } return send.apply(this, arguments); }; }()); }(self)); (function(global) { 'use strict'; if (!('window' in global && 'document' in global)) return; //---------------------------------------------------------------------- // // CSSOM View Module // https://dev.w3.org/csswg/cssom-view/ // //---------------------------------------------------------------------- // Fix for IE8-'s Element.getBoundingClientRect() if ('TextRectangle' in global && !('width' in global.TextRectangle.prototype)) { Object.defineProperties(global.TextRectangle.prototype, { width: { get: function() { return this.right - this.left; } }, height: { get: function() { return this.bottom - this.top; } } }); } }(self)); // URL Polyfill // Draft specification: https://url.spec.whatwg.org // Notes: // - Primarily useful for parsing URLs and modifying query parameters // - Should work in IE8+ and everything more modern, with es5.js polyfills (function (global) { 'use strict'; function isSequence(o) { if (!o) return false; if ('Symbol' in global && 'iterator' in global.Symbol && typeof o[Symbol.iterator] === 'function') return true; if (Array.isArray(o)) return true; return false; } function toArray(iter) { return ('from' in Array) ? Array.from(iter) : Array.prototype.slice.call(iter); } (function() { // Browsers may have: // * No global URL object // * URL with static methods only - may have a dummy constructor // * URL with members except searchParams // * Full URL API support var origURL = global.URL; var nativeURL; try { if (origURL) { nativeURL = new global.URL('http://example.com'); if ('searchParams' in nativeURL) return; if (!('href' in nativeURL)) nativeURL = undefined; } } catch (_) {} // NOTE: Doesn't do the encoding/decoding dance function urlencoded_serialize(pairs) { var output = '', first = true; pairs.forEach(function (pair) { var name = encodeURIComponent(pair.name); var value = encodeURIComponent(pair.value); if (!first) output += '&'; output += name + '=' + value; first = false; }); return output.replace(/%20/g, '+'); } // NOTE: Doesn't do the encoding/decoding dance function urlencoded_parse(input, isindex) { var sequences = input.split('&'); if (isindex && sequences[0].indexOf('=') === -1) sequences[0] = '=' + sequences[0]; var pairs = []; sequences.forEach(function (bytes) { if (bytes.length === 0) return; var index = bytes.indexOf('='); if (index !== -1) { var name = bytes.substring(0, index); var value = bytes.substring(index + 1); } else { name = bytes; value = ''; } name = name.replace(/\+/g, ' '); value = value.replace(/\+/g, ' '); pairs.push({ name: name, value: value }); }); var output = []; pairs.forEach(function (pair) { output.push({ name: decodeURIComponent(pair.name), value: decodeURIComponent(pair.value) }); }); return output; } function URLUtils(url) { if (nativeURL) return new origURL(url); var anchor = document.createElement('a'); anchor.href = url; return anchor; } function URLSearchParams(init) { var $this = this; this._list = []; if (init === undefined || init === null) { // no-op } else if (init instanceof URLSearchParams) { // In ES6 init would be a sequence, but special case for ES5. this._list = urlencoded_parse(String(init)); } else if (typeof init === 'object' && isSequence(init)) { toArray(init).forEach(function(e) { if (!isSequence(e)) throw TypeError(); var nv = toArray(e); if (nv.length !== 2) throw TypeError(); $this._list.push({name: String(nv[0]), value: String(nv[1])}); }); } else if (typeof init === 'object' && init) { Object.keys(init).forEach(function(key) { $this._list.push({name: String(key), value: String(init[key])}); }); } else { init = String(init); if (init.substring(0, 1) === '?') init = init.substring(1); this._list = urlencoded_parse(init); } this._url_object = null; this._setList = function (list) { if (!updating) $this._list = list; }; var updating = false; this._update_steps = function() { if (updating) return; updating = true; if (!$this._url_object) return; // Partial workaround for IE issue with 'about:' if ($this._url_object.protocol === 'about:' && $this._url_object.pathname.indexOf('?') !== -1) { $this._url_object.pathname = $this._url_object.pathname.split('?')[0]; } $this._url_object.search = urlencoded_serialize($this._list); updating = false; }; } Object.defineProperties(URLSearchParams.prototype, { append: { value: function (name, value) { this._list.push({ name: name, value: value }); this._update_steps(); }, writable: true, enumerable: true, configurable: true }, 'delete': { value: function (name) { for (var i = 0; i < this._list.length;) { if (this._list[i].name === name) this._list.splice(i, 1); else ++i; } this._update_steps(); }, writable: true, enumerable: true, configurable: true }, get: { value: function (name) { for (var i = 0; i < this._list.length; ++i) { if (this._list[i].name === name) return this._list[i].value; } return null; }, writable: true, enumerable: true, configurable: true }, getAll: { value: function (name) { var result = []; for (var i = 0; i < this._list.length; ++i) { if (this._list[i].name === name) result.push(this._list[i].value); } return result; }, writable: true, enumerable: true, configurable: true }, has: { value: function (name) { for (var i = 0; i < this._list.length; ++i) { if (this._list[i].name === name) return true; } return false; }, writable: true, enumerable: true, configurable: true }, set: { value: function (name, value) { var found = false; for (var i = 0; i < this._list.length;) { if (this._list[i].name === name) { if (!found) { this._list[i].value = value; found = true; ++i; } else { this._list.splice(i, 1); } } else { ++i; } } if (!found) this._list.push({ name: name, value: value }); this._update_steps(); }, writable: true, enumerable: true, configurable: true }, entries: { value: function() { return new Iterator(this._list, 'key+value'); }, writable: true, enumerable: true, configurable: true }, keys: { value: function() { return new Iterator(this._list, 'key'); }, writable: true, enumerable: true, configurable: true }, values: { value: function() { return new Iterator(this._list, 'value'); }, writable: true, enumerable: true, configurable: true }, forEach: { value: function(callback) { var thisArg = (arguments.length > 1) ? arguments[1] : undefined; this._list.forEach(function(pair, index) { callback.call(thisArg, pair.value, pair.name); }); }, writable: true, enumerable: true, configurable: true }, toString: { value: function () { return urlencoded_serialize(this._list); }, writable: true, enumerable: false, configurable: true } }); function Iterator(source, kind) { var index = 0; this['next'] = function() { if (index >= source.length) return {done: true, value: undefined}; var pair = source[index++]; return {done: false, value: kind === 'key' ? pair.name : kind === 'value' ? pair.value : [pair.name, pair.value]}; }; } if ('Symbol' in global && 'iterator' in global.Symbol) { Object.defineProperty(URLSearchParams.prototype, global.Symbol.iterator, { value: URLSearchParams.prototype.entries, writable: true, enumerable: true, configurable: true}); Object.defineProperty(Iterator.prototype, global.Symbol.iterator, { value: function() { return this; }, writable: true, enumerable: true, configurable: true}); } function URL(url, base) { if (!(this instanceof global.URL)) throw new TypeError("Failed to construct 'URL': Please use the 'new' operator."); if (base) { url = (function () { if (nativeURL) return new origURL(url, base).href; var iframe; try { var doc; // Use another document/base tag/anchor for relative URL resolution, if possible if (Object.prototype.toString.call(window.operamini) === "[object OperaMini]") { iframe = document.createElement('iframe'); iframe.style.display = 'none'; document.documentElement.appendChild(iframe); doc = iframe.contentWindow.document; } else if (document.implementation && document.implementation.createHTMLDocument) { doc = document.implementation.createHTMLDocument(''); } else if (document.implementation && document.implementation.createDocument) { doc = document.implementation.createDocument('http://www.w3.org/1999/xhtml', 'html', null); doc.documentElement.appendChild(doc.createElement('head')); doc.documentElement.appendChild(doc.createElement('body')); } else if (window.ActiveXObject) { doc = new window.ActiveXObject('htmlfile'); doc.write('<\/head><\/body>'); doc.close(); } if (!doc) throw Error('base not supported'); var baseTag = doc.createElement('base'); baseTag.href = base; doc.getElementsByTagName('head')[0].appendChild(baseTag); var anchor = doc.createElement('a'); anchor.href = url; return anchor.href; } finally { if (iframe) iframe.parentNode.removeChild(iframe); } }()); } // An inner object implementing URLUtils (either a native URL // object or an HTMLAnchorElement instance) is used to perform the // URL algorithms. With full ES5 getter/setter support, return a // regular object For IE8's limited getter/setter support, a // different HTMLAnchorElement is returned with properties // overridden var instance = URLUtils(url || ''); // Detect for ES5 getter/setter support // (an Object.defineProperties polyfill that doesn't support getters/setters may throw) var ES5_GET_SET = (function() { if (!('defineProperties' in Object)) return false; try { var obj = {}; Object.defineProperties(obj, { prop: { 'get': function () { return true; } } }); return obj.prop; } catch (_) { return false; } })(); var self = ES5_GET_SET ? this : document.createElement('a'); var query_object = new URLSearchParams( instance.search ? instance.search.substring(1) : null); query_object._url_object = self; Object.defineProperties(self, { href: { get: function () { return instance.href; }, set: function (v) { instance.href = v; tidy_instance(); update_steps(); }, enumerable: true, configurable: true }, origin: { get: function () { if ('origin' in instance) return instance.origin; return this.protocol + '//' + this.host; }, enumerable: true, configurable: true }, protocol: { get: function () { return instance.protocol; }, set: function (v) { instance.protocol = v; }, enumerable: true, configurable: true }, username: { get: function () { return instance.username; }, set: function (v) { instance.username = v; }, enumerable: true, configurable: true }, password: { get: function () { return instance.password; }, set: function (v) { instance.password = v; }, enumerable: true, configurable: true }, host: { get: function () { // IE returns default port in |host| var re = {'http:': /:80$/, 'https:': /:443$/, 'ftp:': /:21$/}[instance.protocol]; return re ? instance.host.replace(re, '') : instance.host; }, set: function (v) { instance.host = v; }, enumerable: true, configurable: true }, hostname: { get: function () { return instance.hostname; }, set: function (v) { instance.hostname = v; }, enumerable: true, configurable: true }, port: { get: function () { return instance.port; }, set: function (v) { instance.port = v; }, enumerable: true, configurable: true }, pathname: { get: function () { // IE does not include leading '/' in |pathname| if (instance.pathname.charAt(0) !== '/') return '/' + instance.pathname; return instance.pathname; }, set: function (v) { instance.pathname = v; }, enumerable: true, configurable: true }, search: { get: function () { return instance.search; }, set: function (v) { if (instance.search === v) return; instance.search = v; tidy_instance(); update_steps(); }, enumerable: true, configurable: true }, searchParams: { get: function () { return query_object; }, enumerable: true, configurable: true }, hash: { get: function () { return instance.hash; }, set: function (v) { instance.hash = v; tidy_instance(); }, enumerable: true, configurable: true }, toString: { value: function() { return instance.toString(); }, enumerable: false, configurable: true }, valueOf: { value: function() { return instance.valueOf(); }, enumerable: false, configurable: true } }); function tidy_instance() { var href = instance.href.replace(/#$|\?$|\?(?=#)/g, ''); if (instance.href !== href) instance.href = href; } function update_steps() { query_object._setList(instance.search ? urlencoded_parse(instance.search.substring(1)) : []); query_object._update_steps(); }; return self; } if (origURL) { for (var i in origURL) { if (origURL.hasOwnProperty(i) && typeof origURL[i] === 'function') URL[i] = origURL[i]; } } global.URL = URL; global.URLSearchParams = URLSearchParams; }()); // Patch native URLSearchParams constructor to handle sequences/records // if necessary. (function() { if (new global.URLSearchParams([['a', 1]]).get('a') === '1' && new global.URLSearchParams({a: 1}).get('a') === '1') return; var orig = global.URLSearchParams; global.URLSearchParams = function(init) { if (init && typeof init === 'object' && isSequence(init)) { var o = new orig(); toArray(init).forEach(function(e) { if (!isSequence(e)) throw TypeError(); var nv = toArray(e); if (nv.length !== 2) throw TypeError(); o.append(nv[0], nv[1]); }); return o; } else if (init && typeof init === 'object') { o = new orig(); Object.keys(init).forEach(function(key) { o.set(key, init[key]); }); return o; } else { return new orig(init); } }; }()); }(self)); // Work-In-Progress 'prollyfill' for Fetch API // Standard: https://fetch.spec.whatwg.org/#fetch-api // // As usual, the intent is to produce a forward-compatible // subset so that code can be written using future standard // functionality; not every case is considered or supported. // Requires ES2015: Promise, Symbol.iterator (or polyfill) // Requires: URL (or polyfill) // Example: // fetch('README.md') // .then(function(response) { return response.text(); }) // .then(function(text) { alert(text); }); (function(global) { 'use strict'; // Web IDL concepts // https://heycam.github.io/webidl/#idl-ByteString function ByteString(value) { value = String(value); if (value.match(/[^\x00-\xFF]/)) throw TypeError('Not a valid ByteString'); return value; } // https://heycam.github.io/webidl/#idl-USVString function USVString(value) { value = String(value); return value.replace( /([\u0000-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDFFF])/g, function (c) { if (/^[\uD800-\uDFFF]$/.test(c)) return '\uFFFD'; return c; }); } function ushort(x) { return x & 0xFFFF; } // 2 Terminology function byteLowerCase(s) { return String(s).replace(/[A-Z]/g, function(c) { return c.toLowerCase(); }); } function byteUpperCase(s) { return String(s).replace(/[a-z]/g, function(c) { return c.toUpperCase(); }); } function byteCaseInsensitiveMatch(a, b) { return byteLowerCase(a) === byteLowerCase(b); } // 2.1 HTTP // 2.1.1 Methods function isForbiddenMethod(m) { m = byteUpperCase(m); return m === 'CONNECT' || m === 'TRACE' || m === 'TRACK'; } function normalizeMethod(m) { var u = byteUpperCase(m); if (u === 'DELETE' || u === 'GET' || u === 'HEAD' || u === 'OPTIONS' || u === 'POST' || u === 'PUT') return u; return m; } function isName(s) { return /^[!#$%&'*+\-.0-9A-Z^_`a-z|~]+$/.test(s); } function isValue(s) { // TODO: Implement me return true; } function isForbiddenHeaderName(n) { n = String(n).toLowerCase(); var forbidden = { 'accept-charset': true, 'accept-encoding': true, 'access-control-request-headers': true, 'access-control-request-method': true, 'connection': true, 'content-length': true, 'cookie': true, 'cookie2': true, 'date': true, 'dnt': true, 'expect': true, 'host': true, 'keep-alive': true, 'origin': true, 'referer': true, 'te': true, 'trailer': true, 'transfer-encoding': true, 'upgrade': true, 'user-agent': true, 'via': true }; return forbidden[n] || n.substring(0, 6) === 'proxy-' || n.substring(0, 4) === 'sec-'; } function isForbiddenResponseHeaderName(n) { n = String(n).toLowerCase(); var forbidden = { 'set-cookie': true, 'set-cookie2': true }; return forbidden[n]; } function isSimpleHeader(name, value) { name = String(name).toLowerCase(); return name === 'accept' || name === 'accept-language' || name === 'content-language' || (name === 'content-type' && ['application/x-www-form-encoded', 'multipart/form-data', 'text/plain'].indexOf(value) !== -1); } // // 5.1 Headers class // // typedef (Headers or sequence> or OpenEndedDictionary) HeadersInit; // Constructor(optional HeadersInit init) function Headers(init) { this._guard = 'none'; this._headerList = []; if (init) fill(this, init); } function fill(headers, init) { if (init instanceof Headers) { init._headerList.forEach(function(header) { headers.append(header[0], header[1]); }); } else if (Array.isArray(init)) { init.forEach(function(header) { if (!Array.isArray(header) || header.length !== 2) throw TypeError(); headers.append(header[0], header[1]); }); } else { init = Object(init); Object.keys(init).forEach(function(key) { headers.append(key, init[key]); }); } } // interface Headers Headers.prototype = { // void append(ByteString name, ByteString value); append: function append(name, value) { name = ByteString(name); if (!isName(name) || !isValue(value)) throw TypeError(); if (this._guard === 'immutable') throw TypeError(); else if (this._guard === 'request' && isForbiddenHeaderName(name)) return; else if (this._guard === 'request-no-CORS' && !isSimpleHeader(name, value)) return; else if (this._guard === 'response' && isForbiddenResponseHeaderName(name)) return; name = name.toLowerCase(); this._headerList.push([name, value]); }, // void delete(ByteString name); 'delete': function delete_(name) { name = ByteString(name); if (!isName(name)) throw TypeError(); if (this._guard === 'immutable') throw TypeError(); else if (this._guard === 'request' && isForbiddenHeaderName(name)) return; else if (this._guard === 'request-no-CORS' && !isSimpleHeader(name, 'invalid')) return; else if (this._guard === 'response' && isForbiddenResponseHeaderName(name)) return; name = name.toLowerCase(); var index = 0; while (index < this._headerList.length) { if (this._headerList[index][0] === name) this._headerList.splice(index, 1); else ++index; } }, // ByteString? get(ByteString name); get: function get(name) { name = ByteString(name); if (!isName(name)) throw TypeError(); name = name.toLowerCase(); for (var index = 0; index < this._headerList.length; ++index) { if (this._headerList[index][0] === name) return this._headerList[index][1]; } return null; }, // sequence getAll(ByteString name); getAll: function getAll(name) { name = ByteString(name); if (!isName(name)) throw TypeError(); name = name.toLowerCase(); var sequence = []; for (var index = 0; index < this._headerList.length; ++index) { if (this._headerList[index][0] === name) sequence.push(this._headerList[index][1]); } return sequence; }, // boolean has(ByteString name); has: function has(name) { name = ByteString(name); if (!isName(name)) throw TypeError(); name = name.toLowerCase(); for (var index = 0; index < this._headerList.length; ++index) { if (this._headerList[index][0] === name) return true; } return false; }, // void set(ByteString name, ByteString value); set: function set(name, value) { name = ByteString(name); if (!isName(name) || !isValue(value)) throw TypeError(); if (this._guard === 'immutable') throw TypeError(); else if (this._guard === 'request' && isForbiddenHeaderName(name)) return; else if (this._guard === 'request-no-CORS' && !isSimpleHeader(name, value)) return; else if (this._guard === 'response' && isForbiddenResponseHeaderName(name)) return; name = name.toLowerCase(); for (var index = 0; index < this._headerList.length; ++index) { if (this._headerList[index][0] === name) { this._headerList[index++][1] = value; while (index < this._headerList.length) { if (this._headerList[index][0] === name) this._headerList.splice(index, 1); else ++index; } return; } } this._headerList.push([name, value]); } }; Headers.prototype[Symbol.iterator] = function() { return new HeadersIterator(this); }; function HeadersIterator(headers) { this._headers = headers; this._index = 0; } HeadersIterator.prototype = {}; HeadersIterator.prototype.next = function() { if (this._index >= this._headers._headerList.length) return { value: undefined, done: true }; return { value: this._headers._headerList[this._index++], done: false }; }; HeadersIterator.prototype[Symbol.iterator] = function() { return this; }; // // 5.2 Body mixin // function Body(_stream) { // TODO: Handle initialization from other types this._stream = _stream; this.bodyUsed = false; } // interface FetchBodyStream Body.prototype = { // Promise arrayBuffer(); arrayBuffer: function() { if (this.bodyUsed) return Promise.reject(TypeError()); this.bodyUsed = true; if (this._stream instanceof ArrayBuffer) return Promise.resolve(this._stream); var value = this._stream; return new Promise(function(resolve, reject) { var octets = unescape(encodeURIComponent(value)).split('').map(function(c) { return c.charCodeAt(0); }); resolve(new Uint8Array(octets).buffer); }); }, // Promise blob(); blob: function() { if (this.bodyUsed) return Promise.reject(TypeError()); this.bodyUsed = true; if (this._stream instanceof Blob) return Promise.resolve(this._stream); return Promise.resolve(new Blob([this._stream])); }, // Promise formData(); formData: function() { if (this.bodyUsed) return Promise.reject(TypeError()); this.bodyUsed = true; if (this._stream instanceof FormData) return Promise.resolve(this._stream); return Promise.reject(Error('Not yet implemented')); }, // Promise json(); json: function() { if (this.bodyUsed) return Promise.reject(TypeError()); this.bodyUsed = true; var that = this; return new Promise(function(resolve, reject) { resolve(JSON.parse(that._stream)); }); }, // Promise text(); text: function() { if (this.bodyUsed) return Promise.reject(TypeError()); this.bodyUsed = true; return Promise.resolve(String(this._stream)); } }; // // 5.3 Request class // // typedef (Request or USVString) RequestInfo; // Constructor(RequestInfo input, optional RequestInit init) function Request(input, init) { if (arguments.length < 1) throw TypeError('Not enough arguments'); Body.call(this, null); // readonly attribute ByteString method; this.method = 'GET'; // readonly attribute USVString url; this.url = ''; // readonly attribute Headers headers; this.headers = new Headers(); this.headers._guard = 'request'; // readonly attribute DOMString referrer; this.referrer = null; // TODO: Implement. // readonly attribute RequestMode mode; this.mode = null; // TODO: Implement. // readonly attribute RequestCredentials credentials; this.credentials = 'omit'; if (input instanceof Request) { if (input.bodyUsed) throw TypeError(); input.bodyUsed = true; this.method = input.method; this.url = input.url; this.headers = new Headers(input.headers); this.headers._guard = input.headers._guard; this.credentials = input.credentials; this._stream = input._stream; } else { input = USVString(input); this.url = String(new URL(input, self.location)); } init = Object(init); if ('method' in init) { var method = ByteString(init.method); if (isForbiddenMethod(method)) throw TypeError(); this.method = normalizeMethod(method); } if ('headers' in init) { this.headers = new Headers(); fill(this.headers, init.headers); } if ('body' in init) this._stream = init.body; if ('credentials' in init && (['omit', 'same-origin', 'include'].indexOf(init.credentials) !== -1)) this.credentials = init.credentials; } // interface Request Request.prototype = Body.prototype; // // 5.4 Response class // // Constructor(optional FetchBodyInit body, optional ResponseInit init) function Response(body, init) { if (arguments.length < 1) body = ''; this.headers = new Headers(); this.headers._guard = 'response'; // Internal if (body instanceof XMLHttpRequest && '_url' in body) { var xhr = body; this.type = 'basic'; // TODO: ResponseType this.url = USVString(xhr._url); this.status = xhr.status; this.ok = 200 <= this.status && this.status <= 299; this.statusText = xhr.statusText; xhr.getAllResponseHeaders() .split(/\r?\n/) .filter(function(header) { return header.length; }) .forEach(function(header) { var i = header.indexOf(':'); this.headers.append(header.substring(0, i), header.substring(i + 2)); }, this); Body.call(this, xhr.responseText); return; } Body.call(this, body); init = Object(init) || {}; // readonly attribute USVString url; this.url = ''; // readonly attribute unsigned short status; var status = 'status' in init ? ushort(init.status) : 200; if (status < 200 || status > 599) throw RangeError(); this.status = status; // readonly attribute boolean ok; this.ok = 200 <= this.status && this.status <= 299; // readonly attribute ByteString statusText; var statusText = 'statusText' in init ? String(init.statusText) : 'OK'; if (/[^\x00-\xFF]/.test(statusText)) throw TypeError(); this.statusText = statusText; // readonly attribute Headers headers; if ('headers' in init) fill(this.headers, init); // TODO: Implement these // readonly attribute ResponseType type; this.type = 'basic'; // TODO: ResponseType } // interface Response Response.prototype = Body.prototype; Response.redirect = function() { // TODO: Implement? throw Error('Not supported'); }; // // 5.5 Structured cloning of Headers, FetchBodyStream, Request, Response // // // 5.6 Fetch method // // Promise fetch(RequestInfo input, optional RequestInit init); function fetch(input, init) { return new Promise(function(resolve, reject) { var r = new Request(input, init); var xhr = new XMLHttpRequest(), async = true; xhr._url = r.url; try { xhr.open(r.method, r.url, async); } catch (e) { throw TypeError(e.message); } for (var iter = r.headers[Symbol.iterator](), step = iter.next(); !step.done; step = iter.next()) xhr.setRequestHeader(step.value[0], step.value[1]); if (r.credentials === 'include') xhr.withCredentials = true; xhr.onreadystatechange = function() { if (xhr.readyState !== XMLHttpRequest.DONE) return; if (xhr.status === 0) reject(new TypeError('Network error')); else resolve(new Response(xhr)); }; xhr.send(r._stream); }); } // Exported if (!('fetch' in global)) { global.Headers = Headers; global.Request = Request; global.Response = Response; global.fetch = fetch; } }(self));