UNPKG

skinny-widgets

Version:

skinnable web components widgets collection

1,278 lines (1,113 loc) 1.46 MB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global = global || self, global.dialogPolyfill = factory()); }(this, function () { 'use strict'; // nb. This is for IE10 and lower _only_. var supportCustomEvent = window.CustomEvent; if (!supportCustomEvent || typeof supportCustomEvent === 'object') { supportCustomEvent = function CustomEvent(event, x) { x = x || {}; var ev = document.createEvent('CustomEvent'); ev.initCustomEvent(event, !!x.bubbles, !!x.cancelable, x.detail || null); return ev; }; supportCustomEvent.prototype = window.Event.prototype; } /** * @param {Element} el to check for stacking context * @return {boolean} whether this el or its parents creates a stacking context */ function createsStackingContext(el) { while (el && el !== document.body) { var s = window.getComputedStyle(el); var invalid = function(k, ok) { return !(s[k] === undefined || s[k] === ok); }; if (s.opacity < 1 || invalid('zIndex', 'auto') || invalid('transform', 'none') || invalid('mixBlendMode', 'normal') || invalid('filter', 'none') || invalid('perspective', 'none') || s['isolation'] === 'isolate' || s.position === 'fixed' || s.webkitOverflowScrolling === 'touch') { return true; } el = el.parentElement; } return false; } /** * Finds the nearest <dialog> from the passed element. * * @param {Element} el to search from * @return {HTMLDialogElement} dialog found */ function findNearestDialog(el) { while (el) { if (el.localName === 'dialog') { return /** @type {HTMLDialogElement} */ (el); } el = el.parentElement; } return null; } /** * Blur the specified element, as long as it's not the HTML body element. * This works around an IE9/10 bug - blurring the body causes Windows to * blur the whole application. * * @param {Element} el to blur */ function safeBlur(el) { if (el && el.blur && el !== document.body) { el.blur(); } } /** * @param {!NodeList} nodeList to search * @param {Node} node to find * @return {boolean} whether node is inside nodeList */ function inNodeList(nodeList, node) { for (var i = 0; i < nodeList.length; ++i) { if (nodeList[i] === node) { return true; } } return false; } /** * @param {HTMLFormElement} el to check * @return {boolean} whether this form has method="dialog" */ function isFormMethodDialog(el) { if (!el || !el.hasAttribute('method')) { return false; } return el.getAttribute('method').toLowerCase() === 'dialog'; } /** * @param {!HTMLDialogElement} dialog to upgrade * @constructor */ function dialogPolyfillInfo(dialog) { this.dialog_ = dialog; this.replacedStyleTop_ = false; this.openAsModal_ = false; // Set a11y role. Browsers that support dialog implicitly know this already. if (!dialog.hasAttribute('role')) { dialog.setAttribute('role', 'dialog'); } dialog.show = this.show.bind(this); dialog.showModal = this.showModal.bind(this); dialog.close = this.close.bind(this); if (!('returnValue' in dialog)) { dialog.returnValue = ''; } if ('MutationObserver' in window) { var mo = new MutationObserver(this.maybeHideModal.bind(this)); mo.observe(dialog, {attributes: true, attributeFilter: ['open']}); } else { // IE10 and below support. Note that DOMNodeRemoved etc fire _before_ removal. They also // seem to fire even if the element was removed as part of a parent removal. Use the removed // events to force downgrade (useful if removed/immediately added). var removed = false; var cb = function() { removed ? this.downgradeModal() : this.maybeHideModal(); removed = false; }.bind(this); var timeout; var delayModel = function(ev) { if (ev.target !== dialog) { return; } // not for a child element var cand = 'DOMNodeRemoved'; removed |= (ev.type.substr(0, cand.length) === cand); window.clearTimeout(timeout); timeout = window.setTimeout(cb, 0); }; ['DOMAttrModified', 'DOMNodeRemoved', 'DOMNodeRemovedFromDocument'].forEach(function(name) { dialog.addEventListener(name, delayModel); }); } // Note that the DOM is observed inside DialogManager while any dialog // is being displayed as a modal, to catch modal removal from the DOM. Object.defineProperty(dialog, 'open', { set: this.setOpen.bind(this), get: dialog.hasAttribute.bind(dialog, 'open') }); this.backdrop_ = document.createElement('div'); this.backdrop_.className = 'backdrop'; this.backdrop_.addEventListener('click', this.backdropClick_.bind(this)); } dialogPolyfillInfo.prototype = { get dialog() { return this.dialog_; }, /** * Maybe remove this dialog from the modal top layer. This is called when * a modal dialog may no longer be tenable, e.g., when the dialog is no * longer open or is no longer part of the DOM. */ maybeHideModal: function() { if (this.dialog_.hasAttribute('open') && document.body.contains(this.dialog_)) { return; } this.downgradeModal(); }, /** * Remove this dialog from the modal top layer, leaving it as a non-modal. */ downgradeModal: function() { if (!this.openAsModal_) { return; } this.openAsModal_ = false; this.dialog_.style.zIndex = ''; // This won't match the native <dialog> exactly because if the user set top on a centered // polyfill dialog, that top gets thrown away when the dialog is closed. Not sure it's // possible to polyfill this perfectly. if (this.replacedStyleTop_) { this.dialog_.style.top = ''; this.replacedStyleTop_ = false; } // Clear the backdrop and remove from the manager. this.backdrop_.parentNode && this.backdrop_.parentNode.removeChild(this.backdrop_); dialogPolyfill.dm.removeDialog(this); }, /** * @param {boolean} value whether to open or close this dialog */ setOpen: function(value) { if (value) { this.dialog_.hasAttribute('open') || this.dialog_.setAttribute('open', ''); } else { this.dialog_.removeAttribute('open'); this.maybeHideModal(); // nb. redundant with MutationObserver } }, /** * Handles clicks on the fake .backdrop element, redirecting them as if * they were on the dialog itself. * * @param {!Event} e to redirect */ backdropClick_: function(e) { if (!this.dialog_.hasAttribute('tabindex')) { // Clicking on the backdrop should move the implicit cursor, even if dialog cannot be // focused. Create a fake thing to focus on. If the backdrop was _before_ the dialog, this // would not be needed - clicks would move the implicit cursor there. var fake = document.createElement('div'); this.dialog_.insertBefore(fake, this.dialog_.firstChild); fake.tabIndex = -1; fake.focus(); this.dialog_.removeChild(fake); } else { this.dialog_.focus(); } var redirectedEvent = document.createEvent('MouseEvents'); redirectedEvent.initMouseEvent(e.type, e.bubbles, e.cancelable, window, e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, e.button, e.relatedTarget); this.dialog_.dispatchEvent(redirectedEvent); e.stopPropagation(); }, /** * Focuses on the first focusable element within the dialog. This will always blur the current * focus, even if nothing within the dialog is found. */ focus_: function() { // Find element with `autofocus` attribute, or fall back to the first form/tabindex control. var target = this.dialog_.querySelector('[autofocus]:not([disabled])'); if (!target && this.dialog_.tabIndex >= 0) { target = this.dialog_; } if (!target) { // Note that this is 'any focusable area'. This list is probably not exhaustive, but the // alternative involves stepping through and trying to focus everything. var opts = ['button', 'input', 'keygen', 'select', 'textarea']; var query = opts.map(function(el) { return el + ':not([disabled])'; }); // TODO(samthor): tabindex values that are not numeric are not focusable. query.push('[tabindex]:not([disabled]):not([tabindex=""])'); // tabindex != "", not disabled target = this.dialog_.querySelector(query.join(', ')); } safeBlur(document.activeElement); target && target.focus(); }, /** * Sets the zIndex for the backdrop and dialog. * * @param {number} dialogZ * @param {number} backdropZ */ updateZIndex: function(dialogZ, backdropZ) { if (dialogZ < backdropZ) { throw new Error('dialogZ should never be < backdropZ'); } this.dialog_.style.zIndex = dialogZ; this.backdrop_.style.zIndex = backdropZ; }, /** * Shows the dialog. If the dialog is already open, this does nothing. */ show: function() { if (!this.dialog_.open) { this.setOpen(true); this.focus_(); } }, /** * Show this dialog modally. */ showModal: function() { if (this.dialog_.hasAttribute('open')) { throw new Error('Failed to execute \'showModal\' on dialog: The element is already open, and therefore cannot be opened modally.'); } if (!document.body.contains(this.dialog_)) { throw new Error('Failed to execute \'showModal\' on dialog: The element is not in a Document.'); } if (!dialogPolyfill.dm.pushDialog(this)) { throw new Error('Failed to execute \'showModal\' on dialog: There are too many open modal dialogs.'); } if (createsStackingContext(this.dialog_.parentElement)) { console.warn('A dialog is being shown inside a stacking context. ' + 'This may cause it to be unusable. For more information, see this link: ' + 'https://github.com/GoogleChrome/dialog-polyfill/#stacking-context'); } this.setOpen(true); this.openAsModal_ = true; // Optionally center vertically, relative to the current viewport. if (dialogPolyfill.needsCentering(this.dialog_)) { dialogPolyfill.reposition(this.dialog_); this.replacedStyleTop_ = true; } else { this.replacedStyleTop_ = false; } // Insert backdrop. this.dialog_.parentNode.insertBefore(this.backdrop_, this.dialog_.nextSibling); // Focus on whatever inside the dialog. this.focus_(); }, /** * Closes this HTMLDialogElement. This is optional vs clearing the open * attribute, however this fires a 'close' event. * * @param {string=} opt_returnValue to use as the returnValue */ close: function(opt_returnValue) { if (!this.dialog_.hasAttribute('open')) { throw new Error('Failed to execute \'close\' on dialog: The element does not have an \'open\' attribute, and therefore cannot be closed.'); } this.setOpen(false); // Leave returnValue untouched in case it was set directly on the element if (opt_returnValue !== undefined) { this.dialog_.returnValue = opt_returnValue; } // Triggering "close" event for any attached listeners on the <dialog>. var closeEvent = new supportCustomEvent('close', { bubbles: false, cancelable: false }); // If we have an onclose handler assigned and it's a function, call it if(this.dialog_.onclose instanceof Function) { this.dialog_.onclose(closeEvent); } // Dispatch the event as normal this.dialog_.dispatchEvent(closeEvent); } }; var dialogPolyfill = {}; dialogPolyfill.reposition = function(element) { var scrollTop = document.body.scrollTop || document.documentElement.scrollTop; var topValue = scrollTop + (window.innerHeight - element.offsetHeight) / 2; element.style.top = Math.max(scrollTop, topValue) + 'px'; }; dialogPolyfill.isInlinePositionSetByStylesheet = function(element) { for (var i = 0; i < document.styleSheets.length; ++i) { var styleSheet = document.styleSheets[i]; var cssRules = null; // Some browsers throw on cssRules. try { cssRules = styleSheet.cssRules; } catch (e) {} if (!cssRules) { continue; } for (var j = 0; j < cssRules.length; ++j) { var rule = cssRules[j]; var selectedNodes = null; // Ignore errors on invalid selector texts. try { selectedNodes = document.querySelectorAll(rule.selectorText); } catch(e) {} if (!selectedNodes || !inNodeList(selectedNodes, element)) { continue; } var cssTop = rule.style.getPropertyValue('top'); var cssBottom = rule.style.getPropertyValue('bottom'); if ((cssTop && cssTop !== 'auto') || (cssBottom && cssBottom !== 'auto')) { return true; } } } return false; }; dialogPolyfill.needsCentering = function(dialog) { var computedStyle = window.getComputedStyle(dialog); if (computedStyle.position !== 'absolute') { return false; } // We must determine whether the top/bottom specified value is non-auto. In // WebKit/Blink, checking computedStyle.top == 'auto' is sufficient, but // Firefox returns the used value. So we do this crazy thing instead: check // the inline style and then go through CSS rules. if ((dialog.style.top !== 'auto' && dialog.style.top !== '') || (dialog.style.bottom !== 'auto' && dialog.style.bottom !== '')) { return false; } return !dialogPolyfill.isInlinePositionSetByStylesheet(dialog); }; /** * @param {!Element} element to force upgrade */ dialogPolyfill.forceRegisterDialog = function(element) { if (window.HTMLDialogElement || element.showModal) { console.warn('This browser already supports <dialog>, the polyfill ' + 'may not work correctly', element); } if (element.localName !== 'dialog') { throw new Error('Failed to register dialog: The element is not a dialog.'); } new dialogPolyfillInfo(/** @type {!HTMLDialogElement} */ (element)); }; /** * @param {!Element} element to upgrade, if necessary */ dialogPolyfill.registerDialog = function(element) { if (!element.showModal) { dialogPolyfill.forceRegisterDialog(element); } }; /** * @constructor */ dialogPolyfill.DialogManager = function() { /** @type {!Array<!dialogPolyfillInfo>} */ this.pendingDialogStack = []; var checkDOM = this.checkDOM_.bind(this); // The overlay is used to simulate how a modal dialog blocks the document. // The blocking dialog is positioned on top of the overlay, and the rest of // the dialogs on the pending dialog stack are positioned below it. In the // actual implementation, the modal dialog stacking is controlled by the // top layer, where z-index has no effect. this.overlay = document.createElement('div'); this.overlay.className = '_dialog_overlay'; this.overlay.addEventListener('click', function(e) { this.forwardTab_ = undefined; e.stopPropagation(); checkDOM([]); // sanity-check DOM }.bind(this)); this.handleKey_ = this.handleKey_.bind(this); this.handleFocus_ = this.handleFocus_.bind(this); this.zIndexLow_ = 100000; this.zIndexHigh_ = 100000 + 150; this.forwardTab_ = undefined; if ('MutationObserver' in window) { this.mo_ = new MutationObserver(function(records) { var removed = []; records.forEach(function(rec) { for (var i = 0, c; c = rec.removedNodes[i]; ++i) { if (!(c instanceof Element)) { continue; } else if (c.localName === 'dialog') { removed.push(c); } removed = removed.concat(c.querySelectorAll('dialog')); } }); removed.length && checkDOM(removed); }); } }; /** * Called on the first modal dialog being shown. Adds the overlay and related * handlers. */ dialogPolyfill.DialogManager.prototype.blockDocument = function() { document.documentElement.addEventListener('focus', this.handleFocus_, true); document.addEventListener('keydown', this.handleKey_); this.mo_ && this.mo_.observe(document, {childList: true, subtree: true}); }; /** * Called on the first modal dialog being removed, i.e., when no more modal * dialogs are visible. */ dialogPolyfill.DialogManager.prototype.unblockDocument = function() { document.documentElement.removeEventListener('focus', this.handleFocus_, true); document.removeEventListener('keydown', this.handleKey_); this.mo_ && this.mo_.disconnect(); }; /** * Updates the stacking of all known dialogs. */ dialogPolyfill.DialogManager.prototype.updateStacking = function() { var zIndex = this.zIndexHigh_; for (var i = 0, dpi; dpi = this.pendingDialogStack[i]; ++i) { dpi.updateZIndex(--zIndex, --zIndex); if (i === 0) { this.overlay.style.zIndex = --zIndex; } } // Make the overlay a sibling of the dialog itself. var last = this.pendingDialogStack[0]; if (last) { var p = last.dialog.parentNode || document.body; p.appendChild(this.overlay); } else if (this.overlay.parentNode) { this.overlay.parentNode.removeChild(this.overlay); } }; /** * @param {Element} candidate to check if contained or is the top-most modal dialog * @return {boolean} whether candidate is contained in top dialog */ dialogPolyfill.DialogManager.prototype.containedByTopDialog_ = function(candidate) { while (candidate = findNearestDialog(candidate)) { for (var i = 0, dpi; dpi = this.pendingDialogStack[i]; ++i) { if (dpi.dialog === candidate) { return i === 0; // only valid if top-most } } candidate = candidate.parentElement; } return false; }; dialogPolyfill.DialogManager.prototype.handleFocus_ = function(event) { if (this.containedByTopDialog_(event.target)) { return; } if (document.activeElement === document.documentElement) { return; } event.preventDefault(); event.stopPropagation(); safeBlur(/** @type {Element} */ (event.target)); if (this.forwardTab_ === undefined) { return; } // move focus only from a tab key var dpi = this.pendingDialogStack[0]; var dialog = dpi.dialog; var position = dialog.compareDocumentPosition(event.target); if (position & Node.DOCUMENT_POSITION_PRECEDING) { if (this.forwardTab_) { // forward dpi.focus_(); } else if (event.target !== document.documentElement) { // backwards if we're not already focused on <html> document.documentElement.focus(); } } return false; }; dialogPolyfill.DialogManager.prototype.handleKey_ = function(event) { this.forwardTab_ = undefined; if (event.keyCode === 27) { event.preventDefault(); event.stopPropagation(); var cancelEvent = new supportCustomEvent('cancel', { bubbles: false, cancelable: true }); var dpi = this.pendingDialogStack[0]; if (dpi && dpi.dialog.dispatchEvent(cancelEvent)) { dpi.dialog.close(); } } else if (event.keyCode === 9) { this.forwardTab_ = !event.shiftKey; } }; /** * Finds and downgrades any known modal dialogs that are no longer displayed. Dialogs that are * removed and immediately readded don't stay modal, they become normal. * * @param {!Array<!HTMLDialogElement>} removed that have definitely been removed */ dialogPolyfill.DialogManager.prototype.checkDOM_ = function(removed) { // This operates on a clone because it may cause it to change. Each change also calls // updateStacking, which only actually needs to happen once. But who removes many modal dialogs // at a time?! var clone = this.pendingDialogStack.slice(); clone.forEach(function(dpi) { if (removed.indexOf(dpi.dialog) !== -1) { dpi.downgradeModal(); } else { dpi.maybeHideModal(); } }); }; /** * @param {!dialogPolyfillInfo} dpi * @return {boolean} whether the dialog was allowed */ dialogPolyfill.DialogManager.prototype.pushDialog = function(dpi) { var allowed = (this.zIndexHigh_ - this.zIndexLow_) / 2 - 1; if (this.pendingDialogStack.length >= allowed) { return false; } if (this.pendingDialogStack.unshift(dpi) === 1) { this.blockDocument(); } this.updateStacking(); return true; }; /** * @param {!dialogPolyfillInfo} dpi */ dialogPolyfill.DialogManager.prototype.removeDialog = function(dpi) { var index = this.pendingDialogStack.indexOf(dpi); if (index === -1) { return; } this.pendingDialogStack.splice(index, 1); if (this.pendingDialogStack.length === 0) { this.unblockDocument(); } this.updateStacking(); }; dialogPolyfill.dm = new dialogPolyfill.DialogManager(); dialogPolyfill.formSubmitter = null; dialogPolyfill.useValue = null; /** * Installs global handlers, such as click listers and native method overrides. These are needed * even if a no dialog is registered, as they deal with <form method="dialog">. */ if (window.HTMLDialogElement === undefined) { /** * If HTMLFormElement translates method="DIALOG" into 'get', then replace the descriptor with * one that returns the correct value. */ var testForm = document.createElement('form'); testForm.setAttribute('method', 'dialog'); if (testForm.method !== 'dialog') { var methodDescriptor = Object.getOwnPropertyDescriptor(HTMLFormElement.prototype, 'method'); if (methodDescriptor) { // nb. Some older iOS and older PhantomJS fail to return the descriptor. Don't do anything // and don't bother to update the element. var realGet = methodDescriptor.get; methodDescriptor.get = function() { if (isFormMethodDialog(this)) { return 'dialog'; } return realGet.call(this); }; var realSet = methodDescriptor.set; methodDescriptor.set = function(v) { if (typeof v === 'string' && v.toLowerCase() === 'dialog') { return this.setAttribute('method', v); } return realSet.call(this, v); }; Object.defineProperty(HTMLFormElement.prototype, 'method', methodDescriptor); } } /** * Global 'click' handler, to capture the <input type="submit"> or <button> element which has * submitted a <form method="dialog">. Needed as Safari and others don't report this inside * document.activeElement. */ document.addEventListener('click', function(ev) { dialogPolyfill.formSubmitter = null; dialogPolyfill.useValue = null; if (ev.defaultPrevented) { return; } // e.g. a submit which prevents default submission var target = /** @type {Element} */ (ev.target); if (!target || !isFormMethodDialog(target.form)) { return; } var valid = (target.type === 'submit' && ['button', 'input'].indexOf(target.localName) > -1); if (!valid) { if (!(target.localName === 'input' && target.type === 'image')) { return; } // this is a <input type="image">, which can submit forms dialogPolyfill.useValue = ev.offsetX + ',' + ev.offsetY; } var dialog = findNearestDialog(target); if (!dialog) { return; } dialogPolyfill.formSubmitter = target; }, false); /** * Replace the native HTMLFormElement.submit() method, as it won't fire the * submit event and give us a chance to respond. */ var nativeFormSubmit = HTMLFormElement.prototype.submit; var replacementFormSubmit = function () { if (!isFormMethodDialog(this)) { return nativeFormSubmit.call(this); } var dialog = findNearestDialog(this); dialog && dialog.close(); }; HTMLFormElement.prototype.submit = replacementFormSubmit; /** * Global form 'dialog' method handler. Closes a dialog correctly on submit * and possibly sets its return value. */ document.addEventListener('submit', function(ev) { if (ev.defaultPrevented) { return; } // e.g. a submit which prevents default submission var form = /** @type {HTMLFormElement} */ (ev.target); if (!isFormMethodDialog(form)) { return; } ev.preventDefault(); var dialog = findNearestDialog(form); if (!dialog) { return; } // Forms can only be submitted via .submit() or a click (?), but anyway: sanity-check that // the submitter is correct before using its value as .returnValue. var s = dialogPolyfill.formSubmitter; if (s && s.form === form) { dialog.close(dialogPolyfill.useValue || s.value); } else { dialog.close(); } dialogPolyfill.formSubmitter = null; }, false); } return dialogPolyfill; })); (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (factory((global.WHATWGFetch = {}))); }(this, (function (exports) { 'use strict'; var support = { searchParams: 'URLSearchParams' in self, iterable: 'Symbol' in self && 'iterator' in Symbol, blob: 'FileReader' in self && 'Blob' in self && (function() { try { new Blob(); return true } catch (e) { return false } })(), formData: 'FormData' in self, arrayBuffer: 'ArrayBuffer' in self }; function isDataView(obj) { return obj && DataView.prototype.isPrototypeOf(obj) } if (support.arrayBuffer) { var viewClasses = [ '[object Int8Array]', '[object Uint8Array]', '[object Uint8ClampedArray]', '[object Int16Array]', '[object Uint16Array]', '[object Int32Array]', '[object Uint32Array]', '[object Float32Array]', '[object Float64Array]' ]; var isArrayBufferView = ArrayBuffer.isView || function(obj) { return obj && viewClasses.indexOf(Object.prototype.toString.call(obj)) > -1 }; } function normalizeName(name) { if (typeof name !== 'string') { name = String(name); } if (/[^a-z0-9\-#$%&'*+.^_`|~]/i.test(name)) { throw new TypeError('Invalid character in header field name') } return name.toLowerCase() } function normalizeValue(value) { if (typeof value !== 'string') { value = String(value); } return value } // Build a destructive iterator for the value list function iteratorFor(items) { var iterator = { next: function() { var value = items.shift(); return {done: value === undefined, value: value} } }; if (support.iterable) { iterator[Symbol.iterator] = function() { return iterator }; } return iterator } function Headers(headers) { this.map = {}; if (headers instanceof Headers) { headers.forEach(function(value, name) { this.append(name, value); }, this); } else if (Array.isArray(headers)) { headers.forEach(function(header) { this.append(header[0], header[1]); }, this); } else if (headers) { Object.getOwnPropertyNames(headers).forEach(function(name) { this.append(name, headers[name]); }, this); } } Headers.prototype.append = function(name, value) { name = normalizeName(name); value = normalizeValue(value); var oldValue = this.map[name]; this.map[name] = oldValue ? oldValue + ', ' + value : value; }; Headers.prototype['delete'] = function(name) { delete this.map[normalizeName(name)]; }; Headers.prototype.get = function(name) { name = normalizeName(name); return this.has(name) ? this.map[name] : null }; Headers.prototype.has = function(name) { return this.map.hasOwnProperty(normalizeName(name)) }; Headers.prototype.set = function(name, value) { this.map[normalizeName(name)] = normalizeValue(value); }; Headers.prototype.forEach = function(callback, thisArg) { for (var name in this.map) { if (this.map.hasOwnProperty(name)) { callback.call(thisArg, this.map[name], name, this); } } }; Headers.prototype.keys = function() { var items = []; this.forEach(function(value, name) { items.push(name); }); return iteratorFor(items) }; Headers.prototype.values = function() { var items = []; this.forEach(function(value) { items.push(value); }); return iteratorFor(items) }; Headers.prototype.entries = function() { var items = []; this.forEach(function(value, name) { items.push([name, value]); }); return iteratorFor(items) }; if (support.iterable) { Headers.prototype[Symbol.iterator] = Headers.prototype.entries; } function consumed(body) { if (body.bodyUsed) { return Promise.reject(new TypeError('Already read')) } body.bodyUsed = true; } function fileReaderReady(reader) { return new Promise(function(resolve, reject) { reader.onload = function() { resolve(reader.result); }; reader.onerror = function() { reject(reader.error); }; }) } function readBlobAsArrayBuffer(blob) { var reader = new FileReader(); var promise = fileReaderReady(reader); reader.readAsArrayBuffer(blob); return promise } function readBlobAsText(blob) { var reader = new FileReader(); var promise = fileReaderReady(reader); reader.readAsText(blob); return promise } function readArrayBufferAsText(buf) { var view = new Uint8Array(buf); var chars = new Array(view.length); for (var i = 0; i < view.length; i++) { chars[i] = String.fromCharCode(view[i]); } return chars.join('') } function bufferClone(buf) { if (buf.slice) { return buf.slice(0) } else { var view = new Uint8Array(buf.byteLength); view.set(new Uint8Array(buf)); return view.buffer } } function Body() { this.bodyUsed = false; this._initBody = function(body) { this._bodyInit = body; if (!body) { this._bodyText = ''; } else if (typeof body === 'string') { this._bodyText = body; } else if (support.blob && Blob.prototype.isPrototypeOf(body)) { this._bodyBlob = body; } else if (support.formData && FormData.prototype.isPrototypeOf(body)) { this._bodyFormData = body; } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) { this._bodyText = body.toString(); } else if (support.arrayBuffer && support.blob && isDataView(body)) { this._bodyArrayBuffer = bufferClone(body.buffer); // IE 10-11 can't handle a DataView body. this._bodyInit = new Blob([this._bodyArrayBuffer]); } else if (support.arrayBuffer && (ArrayBuffer.prototype.isPrototypeOf(body) || isArrayBufferView(body))) { this._bodyArrayBuffer = bufferClone(body); } else { throw new Error('unsupported BodyInit type') } if (!this.headers.get('content-type')) { if (typeof body === 'string') { this.headers.set('content-type', 'text/plain;charset=UTF-8'); } else if (this._bodyBlob && this._bodyBlob.type) { this.headers.set('content-type', this._bodyBlob.type); } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) { this.headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8'); } } }; if (support.blob) { this.blob = function() { var rejected = consumed(this); if (rejected) { return rejected } if (this._bodyBlob) { return Promise.resolve(this._bodyBlob) } else if (this._bodyArrayBuffer) { return Promise.resolve(new Blob([this._bodyArrayBuffer])) } else if (this._bodyFormData) { throw new Error('could not read FormData body as blob') } else { return Promise.resolve(new Blob([this._bodyText])) } }; this.arrayBuffer = function() { if (this._bodyArrayBuffer) { return consumed(this) || Promise.resolve(this._bodyArrayBuffer) } else { return this.blob().then(readBlobAsArrayBuffer) } }; } this.text = function() { var rejected = consumed(this); if (rejected) { return rejected } if (this._bodyBlob) { return readBlobAsText(this._bodyBlob) } else if (this._bodyArrayBuffer) { return Promise.resolve(readArrayBufferAsText(this._bodyArrayBuffer)) } else if (this._bodyFormData) { throw new Error('could not read FormData body as text') } else { return Promise.resolve(this._bodyText) } }; if (support.formData) { this.formData = function() { return this.text().then(decode) }; } this.json = function() { return this.text().then(JSON.parse) }; return this } // HTTP methods whose capitalization should be normalized var methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT']; function normalizeMethod(method) { var upcased = method.toUpperCase(); return methods.indexOf(upcased) > -1 ? upcased : method } function Request(input, options) { options = options || {}; var body = options.body; if (input instanceof Request) { if (input.bodyUsed) { throw new TypeError('Already read') } this.url = input.url; this.credentials = input.credentials; if (!options.headers) { this.headers = new Headers(input.headers); } this.method = input.method; this.mode = input.mode; this.signal = input.signal; if (!body && input._bodyInit != null) { body = input._bodyInit; input.bodyUsed = true; } } else { this.url = String(input); } this.credentials = options.credentials || this.credentials || 'omit'; if (options.headers || !this.headers) { this.headers = new Headers(options.headers); } this.method = normalizeMethod(options.method || this.method || 'GET'); this.mode = options.mode || this.mode || null; this.signal = options.signal || this.signal; this.referrer = null; if ((this.method === 'GET' || this.method === 'HEAD') && body) { throw new TypeError('Body not allowed for GET or HEAD requests') } this._initBody(body); } Request.prototype.clone = function() { return new Request(this, {body: this._bodyInit}) }; function decode(body) { var form = new FormData(); body .trim() .split('&') .forEach(function(bytes) { if (bytes) { var split = bytes.split('='); var name = split.shift().replace(/\+/g, ' '); var value = split.join('=').replace(/\+/g, ' '); form.append(decodeURIComponent(name), decodeURIComponent(value)); } }); return form } function parseHeaders(rawHeaders) { var headers = new Headers(); // Replace instances of \r\n and \n followed by at least one space or horizontal tab with a space // https://tools.ietf.org/html/rfc7230#section-3.2 var preProcessedHeaders = rawHeaders.replace(/\r?\n[\t ]+/g, ' '); preProcessedHeaders.split(/\r?\n/).forEach(function(line) { var parts = line.split(':'); var key = parts.shift().trim(); if (key) { var value = parts.join(':').trim(); headers.append(key, value); } }); return headers } Body.call(Request.prototype); function Response(bodyInit, options) { if (!options) { options = {}; } this.type = 'default'; this.status = options.status === undefined ? 200 : options.status; this.ok = this.status >= 200 && this.status < 300; this.statusText = 'statusText' in options ? options.statusText : 'OK'; this.headers = new Headers(options.headers); this.url = options.url || ''; this._initBody(bodyInit); } Body.call(Response.prototype); Response.prototype.clone = function() { return new Response(this._bodyInit, { status: this.status, statusText: this.statusText, headers: new Headers(this.headers), url: this.url }) }; Response.error = function() { var response = new Response(null, {status: 0, statusText: ''}); response.type = 'error'; return response }; var redirectStatuses = [301, 302, 303, 307, 308]; Response.redirect = function(url, status) { if (redirectStatuses.indexOf(status) === -1) { throw new RangeError('Invalid status code') } return new Response(null, {status: status, headers: {location: url}}) }; exports.DOMException = self.DOMException; try { new exports.DOMException(); } catch (err) { exports.DOMException = function(message, name) { this.message = message; this.name = name; var error = Error(message); this.stack = error.stack; }; exports.DOMException.prototype = Object.create(Error.prototype); exports.DOMException.prototype.constructor = exports.DOMException; } function fetch(input, init) { return new Promise(function(resolve, reject) { var request = new Request(input, init); if (request.signal && request.signal.aborted) { return reject(new exports.DOMException('Aborted', 'AbortError')) } var xhr = new XMLHttpRequest(); function abortXhr() { xhr.abort(); } xhr.onload = function() { var options = { status: xhr.status, statusText: xhr.statusText, headers: parseHeaders(xhr.getAllResponseHeaders() || '') }; options.url = 'responseURL' in xhr ? xhr.responseURL : options.headers.get('X-Request-URL'); var body = 'response' in xhr ? xhr.response : xhr.responseText; resolve(new Response(body, options)); }; xhr.onerror = function() { reject(new TypeError('Network request failed')); }; xhr.ontimeout = function() { reject(new TypeError('Network request failed')); }; xhr.onabort = function() { reject(new exports.DOMException('Aborted', 'AbortError')); }; xhr.open(request.method, request.url, true); if (request.credentials === 'include') { xhr.withCredentials = true; } else if (request.credentials === 'omit') { xhr.withCredentials = false; } if ('responseType' in xhr && support.blob) { xhr.responseType = 'blob'; } request.headers.forEach(function(value, name) { xhr.setRequestHeader(name, value); }); if (request.signal) { request.signal.addEventListener('abort', abortXhr); xhr.onreadystatechange = function() { // DONE (success or failure) if (xhr.readyState === 4) { request.signal.removeEventListener('abort', abortXhr); } }; } xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit); }) } fetch.polyfill = true; if (!self.fetch) { self.fetch = fetch; self.Headers = Headers; self.Request = Request; self.Response = Response; } exports.Headers = Headers; exports.Request = Request; exports.Response = Response; exports.fetch = fetch; Object.defineProperty(exports, '__esModule', { value: true }); }))); !function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var c="function"==typeof require&&require;if(!u&&c)return c(o,!0);if(i)return i(o,!0);var a=new Error("Cannot find module '"+o+"'");throw a.code="MODULE_NOT_FOUND",a}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(n){var r=t[o][1][n];return s(r||n)},f,f.exports,e,t,n,r)}return n[o].exports}for(var i="function"==typeof require&&require,o=0;o<r.length;o++)s(r[o]);return s}({1:[function(t,n,r){(function(n){"use strict";function define(t,n,e){t[n]||Object[r](t,n,{writable:!0,configurable:!0,value:e})}if(t(327),t(328),t(2),n._babelPolyfill)throw new Error("only one instance of babel-polyfill is allowed");n._babelPolyfill=!0;var r="defineProperty";define(String.prototype,"padLeft","".padStart),define(String.prototype,"padRight","".padEnd),"pop,reverse,shift,keys,values,entries,indexOf,every,some,forEach,map,filter,find,findIndex,includes,join,slice,concat,push,splice,unshift,sort,lastIndexOf,reduce,reduceRight,copyWithin,fill".split(",").forEach(function(t){[][t]&&define(Array,t,Function.call.bind([][t]))})}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{2:2,327:327,328:328}],2:[function(t,n,r){t(130),n.exports=t(23).RegExp.escape},{130:130,23:23}],3:[function(t,n,r){n.exports=function(t){if("function"!=typeof t)throw TypeError(t+" is not a function!");return t}},{}],4:[function(t,n,r){var e=t(18);n.exports=function(t,n){if("number"!=typeof t&&"Number"!=e(t))throw TypeError(n);return+t}},{18:18}],5:[function(t,n,r){var e=t(128)("unscopables"),i=Array.prototype;void 0==i[e]&&t(42)(i,e,{}),n.exports=function(t){i[e][t]=!0}},{128:128,42:42}],6:[function(t,n,r){n.exports=function(t,n,r,e){if(!(t instanceof n)||void 0!==e&&e in t)throw TypeError(r+": incorrect invocation!");return t}},{}],7:[function(t,n,r){var e=t(51);n.exports=function(t){if(!e(t))throw TypeError(t+" is not an object!");return t}},{51:51}],8:[function(t,n,r){"use strict";var e=t(119),i=t(114),o=t(118);n.exports=[].copyWithin||function copyWithin(t,n){var r=e(this),u=o(r.length),c=i(t,u),a=i(n,u),f=arguments.length>2?arguments[2]:void 0,s=Math.min((void 0===f?u:i(f,u))-a,u-c),l=1;for(a<c&&c<a+s&&(l=-1,a+=s-1,c+=s-1);s-- >0;)a in r?r[c]=r[a]:delete r[c],c+=l,a+=l;return r}},{114:114,118:118,119:119}],9:[function(t,n,r){"use strict";var e=t(119),i=t(114),o=t(118);n.exports=function fill(t){for(var n=e(this),r=o(n.length),u=arguments.length,c=i(u>1?arguments[1]:void 0,r),a=u>2?arguments[2]:void 0,f=void 0===a?r:i(a,r);f>c;)n[c++]=t;return n}},{114:114,118:118,119:119}],10:[function(t,n,r){var e=t(39);n.exports=function(t,n){var r=[];return e(t,!1,r.push,r,n),r}},{39:39}],11:[function(t,n,r){var e=t(117),i=t(118),o=t(114);n.exports=function(t){return function(n,r,u){var c,a=e(n),f=i(a.length),s=o(u,f);if(t&&r!=r){for(;f>s;)if((c=a[s++])!=c)return!0}else for(;f>s;s++)if((t||s in a)&&a[s]===r)return t||s||0;return!t&&-1}}},{114:114,117:117,118:118}],12:[function(t,n,r){var e=t(25),i=t(47),o=t(119),u=t(118),c=t(15);n.exports=function(t,n){var r=1==t,a=2==t,f=3==t,s=4==t,l=6==t,h=5==t||l,v=n||c;return function(n,c,p){for(var d,y,g=o(n),m=i(g),b=e(c,p,3),x=u(m.length),S=0,w=r?v(n,x):a?v(n,0):void 0;x>S;S++)if((h||S in m)&&(d=m[S],y=b(d,S,g),t))if(r)w[S]=y;else if(y)switch(t){case 3:return!0;case 5:return d;case 6:return S;case 2:w.push(d)}else if(s)return!1;return l?-1:f||s?s:w}}},{118:118,119:119,15:15,25:25,47:47}],13:[function(t,n,r){var e=t(3),i=t(119),o=t(47),u=t(118);n.exports=function(t,n,r,c,a){e(n);var f=i(t),s=o(f),l=u(f.length),h=a?l-1:0,v=a?-1:1;if(r<2)for(;;){if(h in s){c=s[h],h+=v;break}if(h+=v,a?h<0:l<=h)throw TypeError("Reduce of empty array with no initial value")}for(;a?h>=0:l>h;h+=v)h in s&&(c=n(c,s[h],h,f));return c}},{118:118,119:119,3:3,47:47}],14:[function(t,n,r){var e=t(51),i=t(49),o=t(128)("species");n.exports=function(t){var n;return i(t)&&(n=t.constructor,"function"!=typeof n||n!==Array&&!i(n.prototype)||(n=void 0),e(n)&&null===(n=n[o])&&(n=void 0)),void 0===n?Array:n}},{128:128,49:49,51:51}],15:[function(t,n,r){var e=t(14);n.exports=function(t,n){return new(e(t))(n)}},{14:14}],16:[function(t,n,r){"use strict";var e=t(3),i=t(51),o=t(46),u=[].slice,c={},a=function(t,n,r){if(!(n in c)){for(var e=[],i=0;i<n;i++)e[i]="a["+i+"]";c[n]=Function("F,a","return new F("+e.join(",")+")")}return c[n](t,r)};n.exports=Function.bind||function bind(t){var n=e(this),r=u.call(arguments,1),c=function(){var e=r.concat(u.call(arguments));return this instanceof c?a(n,e.length,e):o(n,e,t)};return i(n.prototype)&&(c.prototype=n.prototype),c}},{3:3,46:46,51:51}],17:[function(t,n,r){var e=t(18),i=t(128)("toStringTag"),o="Arguments"==e(function(){return arguments}()),u=function(t,n){try{return t[n]}catch(t){}};n.exports=function(t){var n,r,c;return void 0===t?"Undefined":null===t?"Null":"string"==typeof(r=u(n=Object(t),i))?r:o?e(n):"Object"==(c=e(n))&&"function"==typeof n.callee?"Arguments":c}},{128:128,18:18}],18:[function(t,n,r){var e={}.toString;n.exports=function(t){return e.call(t).slice(8,-1)}},{}],19:[function(t,n,r){"use strict";var e=t(72).f,i=t(71),o=t(93),u=t(25),c=t(6),a=t(39),f=t(55),s=t(57),l=t(100),h=t(29),v=t(66).fastKey,p=t(125),d=h?"_s":"size",y=function(t,n){var r,e=v(n);if("F"!==e)return t._i[e];for(r=t._f;r;r=r.n)if(r.k==n)return r};n.exports={getConstructor:function(t,n,r,f){var s=t(function(t,e){c(t,s,n,"_i"),t._t=n,t._i=i(null),t._f=void 0,t._l=void 0,t[d]=0,void 0!=e&&a(e,r,t[f],t)});return o(s.prototype,{clear:function clear(){for(var t=p(this,n),r=t._i,e=t._f;e;e=e.n)e.r=!0,e.p&&(e.p=e.p.n=void 0),delete r[e.i];t._f=t._l=void 0,t[d]=0},delete:function(t){var r=p(this,n),e=y(r,t);if(e){var i=e.n,o=e.p;delete r._i[e.i],e.r=!0,o&&(o.n=i),i&&(i.p=o),r._f==e&&(r._f=i),r._l==e&&(r._l=o),r[d]--}return!!e},forEach:function forEach(t){p(this,n);for(var r,e=u(t,arguments.length>1?arguments[1]:void 0,3);r=r?r.n:this._f;)for(e(r.v,r.k,this);r&&r.r;)r=r.p},has:function has(t){return!!y(p(this,n),t)}}),h&&e(s.prototype,"size",{get:function(){return p(this,n)[d]}}),s},def:function(t,n,r){var e,i,o=y(t,n);return o?o.v=r:(t._l=o={i:i=v(n,!0),k:n,v:r,p:e=t._l,n:void 0,r:!1},t._f||(t._f=o),e&&(e.n=o),t[d]++,"F"!==i&&(t._i[i]=o)),t},getEntry:y,setStrong:function(t,n,r){f(t,n,function(t,r){this._t=p(t,n),this._k=r,this._l=void 0},function(){for(var t=this,n=t._k,r=t._l;r&&r.r;)r=r.p;return t._t&&(t._l=r=r?r.n:t._t._f)?"keys"==n?s(0,r.k):"values"==n?s(0,r.v):s(0,[r.k,r.v]):(t._t=void 0,s(1))},r?"entries":"values",!r,!0),l(n)}}},{100:100,125:125,25:25,29:29,39:39,55:55,57:57,6:6,66:66,71:71,72:72,93:93}],20:[function(t,n,r){var e=t(17),i=t(10);n.exports=function(t){return function toJSON(){if(e(this)!=t)throw TypeError(t+"#toJSON isn't generic");return i(this)}}},{10:10,17:17}],21:[function(t,n,r){"use strict";var e=t(93),i=t(66).getWeak,o=t(7),u=t(51),c=t(6),a=t(39),f=t(12),s=t(41),l=t(125),h=f(5),v=f(6),p=0,d=function(t){return t._l||(t._l=new y)},y=function(){this.a=[]},g=function(t,n){return h(t.a,function(t){return t[0]===n})};y.prototype={get:function(t){var n=g(this,t);if(n)return n[1]},has:function(t){return!!g(this,t)},set:function(t,n){var r=g(this,t);r?r[1]=n:this.a.push([t,n])},delete:function(t){var n=v(this.a,function(n){return n[0]===t});return~n&&this.a.splice(n,1),!!~n}},n.exports={getConstructor:function(t,n,r,o){var f=t(function(t,e){c(t,f,n,"_i"),t._t=n,t._i=p++,t._l=void 0,void 0!=e&&a(e,r,t[o],t)});return e(f.prototype,{delete:function(t){if(!u(t))return!1;var r=i(t);return!0===r?d(l(this,n)).delete(t):r&&s(r,this._i)&&delete r[this._i]},has:function has(t){if(!u(t))return!1;var r=i(t);return!0===r?d(l(this,n)).has(t):r&&s(r,this._i)}}),f},def:function(t,n,r){var e=i(o(n),!0);return!0===e?d(t).set(n,r):e[t._i]=r,t},ufstore:d}},{12:12,125:125,39:39,41:41,51:51,6:6,66:66,7:7,93:93}],22:[function(t,n,r){"use strict";var e=t(40),i=t(33),o=t(94),u=t(93),c=t(66),a=t(39),f=t(6),s=t(51),l=t(35),h=t(56),v=t(101),p=t(45);n.exports=function(t,n,r,d,y,g){var m=e[t],b=m,x=y?"set":"add",S=b&&b.prototype,w={},_=function(t){var n=S[t];o(S,t,"delete"==t?function(t){return!(g&&!s(t))&&n.call(this,0===t?0:t)}:"has"==t?function has(t){return!(g&&!s(t))&&n.call(this,0===t?0:t)}:"get"==t?function get(t){return g&&!s(t)?void 0:n.call(this,0===t?0:t)}:"add"==t?function add(t){return n.call(this,0===t?0:t),this}:function set(t,r){return n.call(this,0===t?0:t,r),this})};if("function"==typeof b&&(g||S.forEach&&!l(function(){(new b).entries().next()}))){var E=new b,O=E[x](g?{}:-0,1)!=E,P=l(function(){E.has(1)}),M=h(function(t){new b(t)}),F=!g&&l(function(){for(var t=new b,n=5;n--;)t[x](n,n);return!t.has(-0)});M||(b=n(function(n,r){f(n,b,t);var e=p(new m,n,b);return void 0!=r&&a(r,y,e[x],e),e}),b.prototype=S,S.constructor=b),(P||F)&&(_("delete"),_("has"),y&&_("get")),(F||O)&&_(x),g&&S.clear&&delete S.clear}else b=d.getConstructor(n,t,y,x),u(b.prototype,r),c.NEED=!0;return v(b,t),w[t]=b,i(i.G+i.W+i.F*(b!=m),w),g||d.setStrong(b,t,y),b}},{101:101,33:33,35:35,39:39,40:40,45:45,51:51,56:56,6:6,66:66,93:93,94:94}],23:[function(t,n,r){var e=n.exports={version:"2.5.0"};"number"==typeof __e&&(__e=e)},{}],24:[function(t,n,r){"use strict";var e=t(72),i=t(92);n.exports=function(t,n,r){n in t?e.f(t,n,i(0,r)):t[n]=r}},{72:72,92:92}],25:[function(t,n,r){var e=t(3);n.exports=function(t,n,r){if(e(t),void 0===n)return t;switch(r){case 1:return function(r){return t.call(n,r)};case 2:return function(r,e){return t.call(n,r,e)};case