{ | |
"version": 3, | |
"sources": ["../../third_party/dialog-polyfill/dialog-polyfill.esm.js", "../shared/header/header.ts", "../shared/clipboard/clipboard.ts", "../shared/tooltip/tooltip.ts", "../shared/outline/select.ts", "../shared/modal/modal.ts", "../shared/analytics/analytics.ts", "../shared/keyboard/keyboard.ts", "../shared/shared.ts", "frontend.ts"], | |
"sourcesContent": ["// nb. This is for IE10 and lower _only_.\nvar supportCustomEvent = window.CustomEvent;\nif (!supportCustomEvent || typeof supportCustomEvent === 'object') {\n supportCustomEvent = function CustomEvent(event, x) {\n x = x || {};\n var ev = document.createEvent('CustomEvent');\n ev.initCustomEvent(event, !!x.bubbles, !!x.cancelable, x.detail || null);\n return ev;\n };\n supportCustomEvent.prototype = window.Event.prototype;\n}\n\n/**\n * @param {Element} el to check for stacking context\n * @return {boolean} whether this el or its parents creates a stacking context\n */\nfunction createsStackingContext(el) {\n while (el && el !== document.body) {\n var s = window.getComputedStyle(el);\n var invalid = function(k, ok) {\n return !(s[k] === undefined || s[k] === ok);\n };\n\n if (s.opacity < 1 ||\n invalid('zIndex', 'auto') ||\n invalid('transform', 'none') ||\n invalid('mixBlendMode', 'normal') ||\n invalid('filter', 'none') ||\n invalid('perspective', 'none') ||\n s['isolation'] === 'isolate' ||\n s.position === 'fixed' ||\n s.webkitOverflowScrolling === 'touch') {\n return true;\n }\n el = el.parentElement;\n }\n return false;\n}\n\n/**\n * Finds the nearest <dialog> from the passed element.\n *\n * @param {Element} el to search from\n * @return {HTMLDialogElement} dialog found\n */\nfunction findNearestDialog(el) {\n while (el) {\n if (el.localName === 'dialog') {\n return /** @type {HTMLDialogElement} */ (el);\n }\n el = el.parentElement;\n }\n return null;\n}\n\n/**\n * Blur the specified element, as long as it's not the HTML body element.\n * This works around an IE9/10 bug - blurring the body causes Windows to\n * blur the whole application.\n *\n * @param {Element} el to blur\n */\nfunction safeBlur(el) {\n if (el && el.blur && el !== document.body) {\n el.blur();\n }\n}\n\n/**\n * @param {!NodeList} nodeList to search\n * @param {Node} node to find\n * @return {boolean} whether node is inside nodeList\n */\nfunction inNodeList(nodeList, node) {\n for (var i = 0; i < nodeList.length; ++i) {\n if (nodeList[i] === node) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * @param {HTMLFormElement} el to check\n * @return {boolean} whether this form has method=\"dialog\"\n */\nfunction isFormMethodDialog(el) {\n if (!el || !el.hasAttribute('method')) {\n return false;\n }\n return el.getAttribute('method').toLowerCase() === 'dialog';\n}\n\n/**\n * @param {!HTMLDialogElement} dialog to upgrade\n * @constructor\n */\nfunction dialogPolyfillInfo(dialog) {\n this.dialog_ = dialog;\n this.replacedStyleTop_ = false;\n this.openAsModal_ = false;\n\n // Set a11y role. Browsers that support dialog implicitly know this already.\n if (!dialog.hasAttribute('role')) {\n dialog.setAttribute('role', 'dialog');\n }\n\n dialog.show = this.show.bind(this);\n dialog.showModal = this.showModal.bind(this);\n dialog.close = this.close.bind(this);\n\n if (!('returnValue' in dialog)) {\n dialog.returnValue = '';\n }\n\n if ('MutationObserver' in window) {\n var mo = new MutationObserver(this.maybeHideModal.bind(this));\n mo.observe(dialog, {attributes: true, attributeFilter: ['open']});\n } else {\n // IE10 and below support. Note that DOMNodeRemoved etc fire _before_ removal. They also\n // seem to fire even if the element was removed as part of a parent removal. Use the removed\n // events to force downgrade (useful if removed/immediately added).\n var removed = false;\n var cb = function() {\n removed ? this.downgradeModal() : this.maybeHideModal();\n removed = false;\n }.bind(this);\n var timeout;\n var delayModel = function(ev) {\n if (ev.target !== dialog) { return; } // not for a child element\n var cand = 'DOMNodeRemoved';\n removed |= (ev.type.substr(0, cand.length) === cand);\n window.clearTimeout(timeout);\n timeout = window.setTimeout(cb, 0);\n };\n ['DOMAttrModified', 'DOMNodeRemoved', 'DOMNodeRemovedFromDocument'].forEach(function(name) {\n dialog.addEventListener(name, delayModel);\n });\n }\n // Note that the DOM is observed inside DialogManager while any dialog\n // is being displayed as a modal, to catch modal removal from the DOM.\n\n Object.defineProperty(dialog, 'open', {\n set: this.setOpen.bind(this),\n get: dialog.hasAttribute.bind(dialog, 'open')\n });\n\n this.backdrop_ = document.createElement('div');\n this.backdrop_.className = 'backdrop';\n this.backdrop_.addEventListener('click', this.backdropClick_.bind(this));\n}\n\ndialogPolyfillInfo.prototype = {\n\n get dialog() {\n return this.dialog_;\n },\n\n /**\n * Maybe remove this dialog from the modal top layer. This is called when\n * a modal dialog may no longer be tenable, e.g., when the dialog is no\n * longer open or is no longer part of the DOM.\n */\n maybeHideModal: function() {\n if (this.dialog_.hasAttribute('open') && document.body.contains(this.dialog_)) { return; }\n this.downgradeModal();\n },\n\n /**\n * Remove this dialog from the modal top layer, leaving it as a non-modal.\n */\n downgradeModal: function() {\n if (!this.openAsModal_) { return; }\n this.openAsModal_ = false;\n this.dialog_.style.zIndex = '';\n\n // This won't match the native <dialog> exactly because if the user set top on a centered\n // polyfill dialog, that top gets thrown away when the dialog is closed. Not sure it's\n // possible to polyfill this perfectly.\n if (this.replacedStyleTop_) {\n this.dialog_.style.top = '';\n this.replacedStyleTop_ = false;\n }\n\n // Clear the backdrop and remove from the manager.\n this.backdrop_.parentNode && this.backdrop_.parentNode.removeChild(this.backdrop_);\n dialogPolyfill.dm.removeDialog(this);\n },\n\n /**\n * @param {boolean} value whether to open or close this dialog\n */\n setOpen: function(value) {\n if (value) {\n this.dialog_.hasAttribute('open') || this.dialog_.setAttribute('open', '');\n } else {\n this.dialog_.removeAttribute('open');\n this.maybeHideModal(); // nb. redundant with MutationObserver\n }\n },\n\n /**\n * Handles clicks on the fake .backdrop element, redirecting them as if\n * they were on the dialog itself.\n *\n * @param {!Event} e to redirect\n */\n backdropClick_: function(e) {\n if (!this.dialog_.hasAttribute('tabindex')) {\n // Clicking on the backdrop should move the implicit cursor, even if dialog cannot be\n // focused. Create a fake thing to focus on. If the backdrop was _before_ the dialog, this\n // would not be needed - clicks would move the implicit cursor there.\n var fake = document.createElement('div');\n this.dialog_.insertBefore(fake, this.dialog_.firstChild);\n fake.tabIndex = -1;\n fake.focus();\n this.dialog_.removeChild(fake);\n } else {\n this.dialog_.focus();\n }\n\n var redirectedEvent = document.createEvent('MouseEvents');\n redirectedEvent.initMouseEvent(e.type, e.bubbles, e.cancelable, window,\n e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey,\n e.altKey, e.shiftKey, e.metaKey, e.button, e.relatedTarget);\n this.dialog_.dispatchEvent(redirectedEvent);\n e.stopPropagation();\n },\n\n /**\n * Focuses on the first focusable element within the dialog. This will always blur the current\n * focus, even if nothing within the dialog is found.\n */\n focus_: function() {\n // Find element with `autofocus` attribute, or fall back to the first form/tabindex control.\n var target = this.dialog_.querySelector('[autofocus]:not([disabled])');\n if (!target && this.dialog_.tabIndex >= 0) {\n target = this.dialog_;\n }\n if (!target) {\n // Note that this is 'any focusable area'. This list is probably not exhaustive, but the\n // alternative involves stepping through and trying to focus everything.\n var opts = ['button', 'input', 'keygen', 'select', 'textarea'];\n var query = opts.map(function(el) {\n return el + ':not([disabled])';\n });\n // TODO(samthor): tabindex values that are not numeric are not focusable.\n query.push('[tabindex]:not([disabled]):not([tabindex=\"\"])'); // tabindex != \"\", not disabled\n target = this.dialog_.querySelector(query.join(', '));\n }\n safeBlur(document.activeElement);\n target && target.focus();\n },\n\n /**\n * Sets the zIndex for the backdrop and dialog.\n *\n * @param {number} dialogZ\n * @param {number} backdropZ\n */\n updateZIndex: function(dialogZ, backdropZ) {\n if (dialogZ < backdropZ) {\n throw new Error('dialogZ should never be < backdropZ');\n }\n this.dialog_.style.zIndex = dialogZ;\n this.backdrop_.style.zIndex = backdropZ;\n },\n\n /**\n * Shows the dialog. If the dialog is already open, this does nothing.\n */\n show: function() {\n if (!this.dialog_.open) {\n this.setOpen(true);\n this.focus_();\n }\n },\n\n /**\n * Show this dialog modally.\n */\n showModal: function() {\n if (this.dialog_.hasAttribute('open')) {\n throw new Error('Failed to execute \\'showModal\\' on dialog: The element is already open, and therefore cannot be opened modally.');\n }\n if (!document.body.contains(this.dialog_)) {\n throw new Error('Failed to execute \\'showModal\\' on dialog: The element is not in a Document.');\n }\n if (!dialogPolyfill.dm.pushDialog(this)) {\n throw new Error('Failed to execute \\'showModal\\' on dialog: There are too many open modal dialogs.');\n }\n\n if (createsStackingContext(this.dialog_.parentElement)) {\n console.warn('A dialog is being shown inside a stacking context. ' +\n 'This may cause it to be unusable. For more information, see this link: ' +\n 'https://github.com/GoogleChrome/dialog-polyfill/#stacking-context');\n }\n\n this.setOpen(true);\n this.openAsModal_ = true;\n\n // Optionally center vertically, relative to the current viewport.\n if (dialogPolyfill.needsCentering(this.dialog_)) {\n dialogPolyfill.reposition(this.dialog_);\n this.replacedStyleTop_ = true;\n } else {\n this.replacedStyleTop_ = false;\n }\n\n // Insert backdrop.\n this.dialog_.parentNode.insertBefore(this.backdrop_, this.dialog_.nextSibling);\n\n // Focus on whatever inside the dialog.\n this.focus_();\n },\n\n /**\n * Closes this HTMLDialogElement. This is optional vs clearing the open\n * attribute, however this fires a 'close' event.\n *\n * @param {string=} opt_returnValue to use as the returnValue\n */\n close: function(opt_returnValue) {\n if (!this.dialog_.hasAttribute('open')) {\n throw new Error('Failed to execute \\'close\\' on dialog: The element does not have an \\'open\\' attribute, and therefore cannot be closed.');\n }\n this.setOpen(false);\n\n // Leave returnValue untouched in case it was set directly on the element\n if (opt_returnValue !== undefined) {\n this.dialog_.returnValue = opt_returnValue;\n }\n\n // Triggering \"close\" event for any attached listeners on the <dialog>.\n var closeEvent = new supportCustomEvent('close', {\n bubbles: false,\n cancelable: false\n });\n this.dialog_.dispatchEvent(closeEvent);\n }\n\n};\n\nvar dialogPolyfill = {};\n\ndialogPolyfill.reposition = function(element) {\n var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;\n var topValue = scrollTop + (window.innerHeight - element.offsetHeight) / 2;\n element.style.top = Math.max(scrollTop, topValue) + 'px';\n};\n\ndialogPolyfill.isInlinePositionSetByStylesheet = function(element) {\n for (var i = 0; i < document.styleSheets.length; ++i) {\n var styleSheet = document.styleSheets[i];\n var cssRules = null;\n // Some browsers throw on cssRules.\n try {\n cssRules = styleSheet.cssRules;\n } catch (e) {}\n if (!cssRules) { continue; }\n for (var j = 0; j < cssRules.length; ++j) {\n var rule = cssRules[j];\n var selectedNodes = null;\n // Ignore errors on invalid selector texts.\n try {\n selectedNodes = document.querySelectorAll(rule.selectorText);\n } catch(e) {}\n if (!selectedNodes || !inNodeList(selectedNodes, element)) {\n continue;\n }\n var cssTop = rule.style.getPropertyValue('top');\n var cssBottom = rule.style.getPropertyValue('bottom');\n if ((cssTop && cssTop !== 'auto') || (cssBottom && cssBottom !== 'auto')) {\n return true;\n }\n }\n }\n return false;\n};\n\ndialogPolyfill.needsCentering = function(dialog) {\n var computedStyle = window.getComputedStyle(dialog);\n if (computedStyle.position !== 'absolute') {\n return false;\n }\n\n // We must determine whether the top/bottom specified value is non-auto. In\n // WebKit/Blink, checking computedStyle.top == 'auto' is sufficient, but\n // Firefox returns the used value. So we do this crazy thing instead: check\n // the inline style and then go through CSS rules.\n if ((dialog.style.top !== 'auto' && dialog.style.top !== '') ||\n (dialog.style.bottom !== 'auto' && dialog.style.bottom !== '')) {\n return false;\n }\n return !dialogPolyfill.isInlinePositionSetByStylesheet(dialog);\n};\n\n/**\n * @param {!Element} element to force upgrade\n */\ndialogPolyfill.forceRegisterDialog = function(element) {\n if (window.HTMLDialogElement || element.showModal) {\n console.warn('This browser already supports <dialog>, the polyfill ' +\n 'may not work correctly', element);\n }\n if (element.localName !== 'dialog') {\n throw new Error('Failed to register dialog: The element is not a dialog.');\n }\n new dialogPolyfillInfo(/** @type {!HTMLDialogElement} */ (element));\n};\n\n/**\n * @param {!Element} element to upgrade, if necessary\n */\ndialogPolyfill.registerDialog = function(element) {\n if (!element.showModal) {\n dialogPolyfill.forceRegisterDialog(element);\n }\n};\n\n/**\n * @constructor\n */\ndialogPolyfill.DialogManager = function() {\n /** @type {!Array<!dialogPolyfillInfo>} */\n this.pendingDialogStack = [];\n\n var checkDOM = this.checkDOM_.bind(this);\n\n // The overlay is used to simulate how a modal dialog blocks the document.\n // The blocking dialog is positioned on top of the overlay, and the rest of\n // the dialogs on the pending dialog stack are positioned below it. In the\n // actual implementation, the modal dialog stacking is controlled by the\n // top layer, where z-index has no effect.\n this.overlay = document.createElement('div');\n this.overlay.className = '_dialog_overlay';\n this.overlay.addEventListener('click', function(e) {\n this.forwardTab_ = undefined;\n e.stopPropagation();\n checkDOM([]); // sanity-check DOM\n }.bind(this));\n\n this.handleKey_ = this.handleKey_.bind(this);\n this.handleFocus_ = this.handleFocus_.bind(this);\n\n this.zIndexLow_ = 100000;\n this.zIndexHigh_ = 100000 + 150;\n\n this.forwardTab_ = undefined;\n\n if ('MutationObserver' in window) {\n this.mo_ = new MutationObserver(function(records) {\n var removed = [];\n records.forEach(function(rec) {\n for (var i = 0, c; c = rec.removedNodes[i]; ++i) {\n if (!(c instanceof Element)) {\n continue;\n } else if (c.localName === 'dialog') {\n removed.push(c);\n }\n removed = removed.concat(c.querySelectorAll('dialog'));\n }\n });\n removed.length && checkDOM(removed);\n });\n }\n};\n\n/**\n * Called on the first modal dialog being shown. Adds the overlay and related\n * handlers.\n */\ndialogPolyfill.DialogManager.prototype.blockDocument = function() {\n document.documentElement.addEventListener('focus', this.handleFocus_, true);\n document.addEventListener('keydown', this.handleKey_);\n this.mo_ && this.mo_.observe(document, {childList: true, subtree: true});\n};\n\n/**\n * Called on the first modal dialog being removed, i.e., when no more modal\n * dialogs are visible.\n */\ndialogPolyfill.DialogManager.prototype.unblockDocument = function() {\n document.documentElement.removeEventListener('focus', this.handleFocus_, true);\n document.removeEventListener('keydown', this.handleKey_);\n this.mo_ && this.mo_.disconnect();\n};\n\n/**\n * Updates the stacking of all known dialogs.\n */\ndialogPolyfill.DialogManager.prototype.updateStacking = function() {\n var zIndex = this.zIndexHigh_;\n\n for (var i = 0, dpi; dpi = this.pendingDialogStack[i]; ++i) {\n dpi.updateZIndex(--zIndex, --zIndex);\n if (i === 0) {\n this.overlay.style.zIndex = --zIndex;\n }\n }\n\n // Make the overlay a sibling of the dialog itself.\n var last = this.pendingDialogStack[0];\n if (last) {\n var p = last.dialog.parentNode || document.body;\n p.appendChild(this.overlay);\n } else if (this.overlay.parentNode) {\n this.overlay.parentNode.removeChild(this.overlay);\n }\n};\n\n/**\n * @param {Element} candidate to check if contained or is the top-most modal dialog\n * @return {boolean} whether candidate is contained in top dialog\n */\ndialogPolyfill.DialogManager.prototype.containedByTopDialog_ = function(candidate) {\n while (candidate = findNearestDialog(candidate)) {\n for (var i = 0, dpi; dpi = this.pendingDialogStack[i]; ++i) {\n if (dpi.dialog === candidate) {\n return i === 0; // only valid if top-most\n }\n }\n candidate = candidate.parentElement;\n }\n return false;\n};\n\ndialogPolyfill.DialogManager.prototype.handleFocus_ = function(event) {\n if (this.containedByTopDialog_(event.target)) { return; }\n\n if (document.activeElement === document.documentElement) { return; }\n\n event.preventDefault();\n event.stopPropagation();\n safeBlur(/** @type {Element} */ (event.target));\n\n if (this.forwardTab_ === undefined) { return; } // move focus only from a tab key\n\n var dpi = this.pendingDialogStack[0];\n var dialog = dpi.dialog;\n var position = dialog.compareDocumentPosition(event.target);\n if (position & Node.DOCUMENT_POSITION_PRECEDING) {\n if (this.forwardTab_) {\n // forward\n dpi.focus_();\n } else if (event.target !== document.documentElement) {\n // backwards if we're not already focused on <html>\n document.documentElement.focus();\n }\n }\n\n return false;\n};\n\ndialogPolyfill.DialogManager.prototype.handleKey_ = function(event) {\n this.forwardTab_ = undefined;\n if (event.keyCode === 27) {\n event.preventDefault();\n event.stopPropagation();\n var cancelEvent = new supportCustomEvent('cancel', {\n bubbles: false,\n cancelable: true\n });\n var dpi = this.pendingDialogStack[0];\n if (dpi && dpi.dialog.dispatchEvent(cancelEvent)) {\n dpi.dialog.close();\n }\n } else if (event.keyCode === 9) {\n this.forwardTab_ = !event.shiftKey;\n }\n};\n\n/**\n * Finds and downgrades any known modal dialogs that are no longer displayed. Dialogs that are\n * removed and immediately readded don't stay modal, they become normal.\n *\n * @param {!Array<!HTMLDialogElement>} removed that have definitely been removed\n */\ndialogPolyfill.DialogManager.prototype.checkDOM_ = function(removed) {\n // This operates on a clone because it may cause it to change. Each change also calls\n // updateStacking, which only actually needs to happen once. But who removes many modal dialogs\n // at a time?!\n var clone = this.pendingDialogStack.slice();\n clone.forEach(function(dpi) {\n if (removed.indexOf(dpi.dialog) !== -1) {\n dpi.downgradeModal();\n } else {\n dpi.maybeHideModal();\n }\n });\n};\n\n/**\n * @param {!dialogPolyfillInfo} dpi\n * @return {boolean} whether the dialog was allowed\n */\ndialogPolyfill.DialogManager.prototype.pushDialog = function(dpi) {\n var allowed = (this.zIndexHigh_ - this.zIndexLow_) / 2 - 1;\n if (this.pendingDialogStack.length >= allowed) {\n return false;\n }\n if (this.pendingDialogStack.unshift(dpi) === 1) {\n this.blockDocument();\n }\n this.updateStacking();\n return true;\n};\n\n/**\n * @param {!dialogPolyfillInfo} dpi\n */\ndialogPolyfill.DialogManager.prototype.removeDialog = function(dpi) {\n var index = this.pendingDialogStack.indexOf(dpi);\n if (index === -1) { return; }\n\n this.pendingDialogStack.splice(index, 1);\n if (this.pendingDialogStack.length === 0) {\n this.unblockDocument();\n }\n this.updateStacking();\n};\n\ndialogPolyfill.dm = new dialogPolyfill.DialogManager();\ndialogPolyfill.formSubmitter = null;\ndialogPolyfill.useValue = null;\n\n/**\n * Installs global handlers, such as click listers and native method overrides. These are needed\n * even if a no dialog is registered, as they deal with <form method=\"dialog\">.\n */\nif (window.HTMLDialogElement === undefined) {\n\n /**\n * If HTMLFormElement translates method=\"DIALOG\" into 'get', then replace the descriptor with\n * one that returns the correct value.\n */\n var testForm = document.createElement('form');\n testForm.setAttribute('method', 'dialog');\n if (testForm.method !== 'dialog') {\n var methodDescriptor = Object.getOwnPropertyDescriptor(HTMLFormElement.prototype, 'method');\n if (methodDescriptor) {\n // nb. Some older iOS and older PhantomJS fail to return the descriptor. Don't do anything\n // and don't bother to update the element.\n var realGet = methodDescriptor.get;\n methodDescriptor.get = function() {\n if (isFormMethodDialog(this)) {\n return 'dialog';\n }\n return realGet.call(this);\n };\n var realSet = methodDescriptor.set;\n methodDescriptor.set = function(v) {\n if (typeof v === 'string' && v.toLowerCase() === 'dialog') {\n return this.setAttribute('method', v);\n }\n return realSet.call(this, v);\n };\n Object.defineProperty(HTMLFormElement.prototype, 'method', methodDescriptor);\n }\n }\n\n /**\n * Global 'click' handler, to capture the <input type=\"submit\"> or <button> element which has\n * submitted a <form method=\"dialog\">. Needed as Safari and others don't report this inside\n * document.activeElement.\n */\n document.addEventListener('click', function(ev) {\n dialogPolyfill.formSubmitter = null;\n dialogPolyfill.useValue = null;\n if (ev.defaultPrevented) { return; } // e.g. a submit which prevents default submission\n\n var target = /** @type {Element} */ (ev.target);\n if (!target || !isFormMethodDialog(target.form)) { return; }\n\n var valid = (target.type === 'submit' && ['button', 'input'].indexOf(target.localName) > -1);\n if (!valid) {\n if (!(target.localName === 'input' && target.type === 'image')) { return; }\n // this is a <input type=\"image\">, which can submit forms\n dialogPolyfill.useValue = ev.offsetX + ',' + ev.offsetY;\n }\n\n var dialog = findNearestDialog(target);\n if (!dialog) { return; }\n\n dialogPolyfill.formSubmitter = target;\n\n }, false);\n\n /**\n * Replace the native HTMLFormElement.submit() method, as it won't fire the\n * submit event and give us a chance to respond.\n */\n var nativeFormSubmit = HTMLFormElement.prototype.submit;\n var replacementFormSubmit = function () {\n if (!isFormMethodDialog(this)) {\n return nativeFormSubmit.call(this);\n }\n var dialog = findNearestDialog(this);\n dialog && dialog.close();\n };\n HTMLFormElement.prototype.submit = replacementFormSubmit;\n\n /**\n * Global form 'dialog' method handler. Closes a dialog correctly on submit\n * and possibly sets its return value.\n */\n document.addEventListener('submit', function(ev) {\n if (ev.defaultPrevented) { return; } // e.g. a submit which prevents default submission\n\n var form = /** @type {HTMLFormElement} */ (ev.target);\n if (!isFormMethodDialog(form)) { return; }\n ev.preventDefault();\n\n var dialog = findNearestDialog(form);\n if (!dialog) { return; }\n\n // Forms can only be submitted via .submit() or a click (?), but anyway: sanity-check that\n // the submitter is correct before using its value as .returnValue.\n var s = dialogPolyfill.formSubmitter;\n if (s && s.form === form) {\n dialog.close(dialogPolyfill.useValue || s.value);\n } else {\n dialog.close();\n }\n dialogPolyfill.formSubmitter = null;\n\n }, false);\n}\n\nexport default dialogPolyfill;\n", "function registerHeaderListeners() {\n const header = document.querySelector('.js-header');\n const menuButtons = document.querySelectorAll('.js-headerMenuButton');\n menuButtons.forEach(button => {\n button.addEventListener('click', e => {\n e.preventDefault();\n header?.classList.toggle('is-active');\n button.setAttribute('aria-expanded', String(header?.classList.contains('is-active')));\n });\n });\n\n const scrim = document.querySelector('.js-scrim');\n scrim?.addEventListener('click', e => {\n e.preventDefault();\n header?.classList.remove('is-active');\n menuButtons.forEach(button => {\n button.setAttribute('aria-expanded', String(header?.classList.contains('is-active')));\n });\n });\n}\n\nfunction registerSearchFormListeners() {\n const searchForm = document.querySelector('.js-searchForm');\n const expandSearch = document.querySelector('.js-expandSearch');\n const input = searchForm?.querySelector('input');\n const headerLogo = document.querySelector('.js-headerLogo');\n const menuButton = document.querySelector('.js-headerMenuButton');\n expandSearch?.addEventListener('click', () => {\n searchForm?.classList.add('go-SearchForm--expanded');\n headerLogo?.classList.add('go-Header-logo--hidden');\n menuButton?.classList.add('go-Header-navOpen--hidden');\n input?.focus();\n });\n document?.addEventListener('click', e => {\n if (!searchForm?.contains(e.target as Node)) {\n searchForm?.classList.remove('go-SearchForm--expanded');\n headerLogo?.classList.remove('go-Header-logo--hidden');\n menuButton?.classList.remove('go-Header-navOpen--hidden');\n }\n });\n}\n\nregisterHeaderListeners();\nregisterSearchFormListeners();\n", "/**\n * @license\n * Copyright 2021 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/**\n * This class decorates an element to copy arbitrary data attached via a data-\n * attribute to the clipboard.\n */\nexport class ClipboardController {\n /**\n * The data to be copied to the clipboard.\n */\n private data: string;\n\n /**\n * @param el The element that will trigger copying text to the clipboard. The text is\n * expected to be within its data-to-copy attribute.\n */\n constructor(private el: HTMLButtonElement) {\n this.data = el.dataset['toCopy'] ?? el.innerText;\n // if data-to-copy is empty and the button is part of an input group\n // capture the value of the input.\n if (!this.data && el.parentElement?.classList.contains('go-InputGroup')) {\n this.data = (this.data || el.parentElement?.querySelector('input')?.value) ?? '';\n }\n el.addEventListener('click', e => this.handleCopyClick(e));\n }\n\n /**\n * Handles when the primary element is clicked.\n */\n handleCopyClick(e: MouseEvent): void {\n e.preventDefault();\n const TOOLTIP_SHOW_DURATION_MS = 1000;\n\n // This API is not available on iOS.\n if (!navigator.clipboard) {\n this.showTooltipText('Unable to copy', TOOLTIP_SHOW_DURATION_MS);\n return;\n }\n navigator.clipboard\n .writeText(this.data)\n .then(() => {\n this.showTooltipText('Copied!', TOOLTIP_SHOW_DURATION_MS);\n })\n .catch(() => {\n this.showTooltipText('Unable to copy', TOOLTIP_SHOW_DURATION_MS);\n });\n }\n\n /**\n * Shows the given text in a tooltip for a specified amount of time, in milliseconds.\n */\n showTooltipText(text: string, durationMs: number): void {\n this.el.setAttribute('data-tooltip', text);\n setTimeout(() => this.el.setAttribute('data-tooltip', ''), durationMs);\n }\n}\n", "/**\n * @license\n * Copyright 2021 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/**\n * ToolTipController handles closing tooltips on external clicks.\n */\nexport class ToolTipController {\n constructor(private el: HTMLDetailsElement) {\n document.addEventListener('click', e => {\n const insideTooltip = this.el.contains(e.target as Element);\n if (!insideTooltip) {\n this.el.removeAttribute('open');\n }\n });\n }\n}\n", "/**\n * @license\n * Copyright 2021 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\nimport { TreeNavController } from './tree.js';\n\nexport class SelectNavController {\n constructor(private el: Element) {\n this.el.addEventListener('change', e => {\n const target = e.target as HTMLSelectElement;\n let href = target.value;\n if (!target.value.startsWith('/')) {\n href = '/' + href;\n }\n window.location.href = href;\n });\n }\n}\n\nexport function makeSelectNav(tree: TreeNavController): HTMLLabelElement {\n const label = document.createElement('label');\n label.classList.add('go-Label');\n label.setAttribute('aria-label', 'Menu');\n const select = document.createElement('select');\n select.classList.add('go-Select', 'js-selectNav');\n label.appendChild(select);\n const outline = document.createElement('optgroup');\n outline.label = 'Outline';\n select.appendChild(outline);\n const groupMap: Record<string, HTMLOptGroupElement> = {};\n let group: HTMLOptGroupElement;\n for (const t of tree.treeitems) {\n if (Number(t.depth) > 4) continue;\n if (t.groupTreeitem) {\n group = groupMap[t.groupTreeitem.label];\n if (!group) {\n group = groupMap[t.groupTreeitem.label] = document.createElement('optgroup');\n group.label = t.groupTreeitem.label;\n select.appendChild(group);\n }\n } else {\n group = outline;\n }\n const o = document.createElement('option');\n o.label = t.label;\n o.textContent = t.label;\n o.value = (t.el as HTMLAnchorElement).href.replace(window.location.origin, '').replace('/', '');\n group.appendChild(o);\n }\n tree.addObserver(t => {\n const hash = (t.el as HTMLAnchorElement).hash;\n const value = select.querySelector<HTMLOptionElement>(`[value$=\"${hash}\"]`)?.value;\n if (value) {\n select.value = value;\n }\n }, 50);\n return label;\n}\n", "/**\n * @license\n * Copyright 2021 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/**\n * ModalController registers a dialog element with the polyfill if\n * necessary for the current browser, add adds event listeners to\n * close and open modals.\n */\nexport class ModalController {\n constructor(private el: HTMLDialogElement) {\n // Only load the dialog polyfill if necessary for the environment.\n if (!window.HTMLDialogElement && !el.showModal) {\n import('../../../third_party/dialog-polyfill/dialog-polyfill.esm.js').then(\n ({ default: polyfill }) => {\n polyfill.registerDialog(el);\n }\n );\n }\n const id = el.id;\n const button = document.querySelector<HTMLButtonElement>(`[aria-controls=\"${id}\"]`);\n if (button) {\n button.addEventListener('click', () => {\n if (this.el.showModal) {\n this.el.showModal();\n } else {\n this.el.open = true;\n }\n el.querySelector('input')?.focus();\n });\n }\n for (const close of this.el.querySelectorAll<HTMLButtonElement>('[data-modal-close]')) {\n close.addEventListener('click', () => {\n if (this.el.close) {\n this.el.close();\n } else {\n this.el.open = false;\n }\n });\n }\n }\n}\n", "interface TagManagerEvent {\n /**\n * event is the name of the event, used to filter events in\n * Google Analytics.\n */\n event: string;\n\n /**\n * event_category is a name that you supply as a way to group objects\n * that to analyze. Typically, you will use the same category name\n * multiple times over related UI elements (buttons, links, etc).\n */\n event_category?: string;\n\n /**\n * event_action is used to name the type of event or interaction you\n * want to measure for a particular web object. For example, with a\n * single \"form\" category, you can analyze a number of specific events\n * with this parameter, such as: form entered, form submitted.\n */\n event_action?: string;\n\n /**\n * event_label provide additional information for events that you want\n * to analyze, such as the text label of a link.\n */\n event_label?: string;\n\n /**\n * gtm.start is used to initialize Google Tag Manager.\n */\n 'gtm.start'?: number;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\ndeclare global {\n interface Window {\n dataLayer?: (TagManagerEvent | VoidFunction)[];\n ga?: unknown;\n }\n}\n\n/**\n * track sends events to Google Tag Manager.\n */\nexport function track(\n event: string | TagManagerEvent,\n category?: string,\n action?: string,\n label?: string\n): void {\n window.dataLayer ??= [];\n if (typeof event === 'string') {\n window.dataLayer.push({\n event,\n event_category: category,\n event_action: action,\n event_label: label,\n });\n } else {\n window.dataLayer.push(event);\n }\n}\n\n/**\n * func adds functions to run sequentionally after\n * Google Tag Manager is ready.\n */\nexport function func(fn: () => void): void {\n window.dataLayer ??= [];\n window.dataLayer.push(fn);\n}\n", "/*!\n * @license\n * Copyright 2019-2020 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\nimport { track } from '../analytics/analytics';\n\n/**\n * Options are keyhandler callback options.\n */\ninterface Options {\n /**\n * target is the element the key event should filter on. The\n * default target is the document.\n */\n target?: Element;\n\n /**\n * withMeta specifies if the event callback should fire when\n * the key is pressed with a meta key (ctrl, alt, etc). By\n * default meta keypresses are ignored.\n */\n withMeta?: boolean;\n}\n\n/**\n * KeyHandler is the config for a keyboard event callback.\n */\ninterface KeyHandler extends Options {\n description: string;\n callback: (e: KeyboardEvent) => void;\n}\n\n/**\n * KeyboardController controls event callbacks for sitewide\n * keyboard events. Multiple callbacks can be registered for\n * a single key and by default the controller ignores events\n * for text input targets.\n */\nclass KeyboardController {\n handlers: Record<string, Set<KeyHandler>>;\n\n constructor() {\n this.handlers = {};\n document.addEventListener('keydown', e => this.handleKeyPress(e));\n }\n\n /**\n * on registers keyboard event callbacks.\n * @param key the key to register.\n * @param description name of the event.\n * @param callback event callback.\n * @param options set target and withMeta options to override the default behaviors.\n */\n on(key: string, description: string, callback: (e: KeyboardEvent) => void, options?: Options) {\n this.handlers[key] ??= new Set();\n this.handlers[key].add({ description, callback, ...options });\n return this;\n }\n\n private handleKeyPress(e: KeyboardEvent) {\n for (const handler of this.handlers[e.key.toLowerCase()] ?? new Set()) {\n if (handler.target && handler.target !== e.target) {\n return;\n }\n const t = e.target as HTMLElement | null;\n if (\n !handler.target &&\n (t?.tagName === 'INPUT' || t?.tagName === 'SELECT' || t?.tagName === 'TEXTAREA')\n ) {\n return;\n }\n if (t?.isContentEditable) {\n return;\n }\n if (\n (handler.withMeta && !(e.ctrlKey || e.metaKey)) ||\n (!handler.withMeta && (e.ctrlKey || e.metaKey))\n ) {\n return;\n }\n track('keypress', 'hotkeys', `${e.key} pressed`, handler.description);\n handler.callback(e);\n }\n }\n}\n\nexport const keyboard = new KeyboardController();\n", "/**\n * @license\n * Copyright 2020 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\nimport './header/header';\nimport { ClipboardController } from './clipboard/clipboard';\nimport { ToolTipController } from './tooltip/tooltip';\nimport { SelectNavController } from './outline/select';\nimport { ModalController } from './modal/modal';\n\nexport { keyboard } from './keyboard/keyboard';\nexport * as analytics from './analytics/analytics';\n\nfor (const el of document.querySelectorAll<HTMLButtonElement>('.js-clipboard')) {\n new ClipboardController(el);\n}\n\nfor (const el of document.querySelectorAll<HTMLDialogElement>('.js-modal')) {\n new ModalController(el);\n}\n\nfor (const t of document.querySelectorAll<HTMLDetailsElement>('.js-tooltip')) {\n new ToolTipController(t);\n}\n\nfor (const el of document.querySelectorAll<HTMLSelectElement>('.js-selectNav')) {\n new SelectNavController(el);\n}\n", "/**\n * @license\n * Copyright 2020 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\nimport { analytics, keyboard } from '../shared/shared';\n\n// Temporary shortcut for testing out the dark theme.\nkeyboard.on('t', 'toggle theme', () => {\n let nextTheme = 'dark';\n const theme = document.documentElement.getAttribute('data-theme');\n if (theme === 'dark') {\n nextTheme = 'light';\n } else if (theme === 'light') {\n nextTheme = 'auto';\n }\n document.documentElement.setAttribute('data-theme', nextTheme);\n document.cookie = `prefers-color-scheme=${nextTheme};path=/;max-age=31536000;`;\n});\n\n// Pressing '/' focuses the search box\nkeyboard.on('/', 'focus search', e => {\n const searchInput = Array.from(\n document.querySelectorAll<HTMLInputElement>('.js-searchFocus')\n ).pop();\n // Favoring the Firefox quick find feature over search input\n // focus. See: https://github.com/golang/go/issues/41093.\n if (searchInput && !window.navigator.userAgent.includes('Firefox')) {\n e.preventDefault();\n searchInput.focus();\n }\n});\n\n// Pressing 'y' changes the browser URL to the canonical URL\n// without triggering a reload.\nkeyboard.on('y', 'set canonical url', () => {\n const canonicalURLPath = document.querySelector<HTMLDivElement>('.js-canonicalURLPath')?.dataset[\n 'canonicalUrlPath'\n ];\n if (canonicalURLPath && canonicalURLPath !== '') {\n window.history.replaceState(null, '', canonicalURLPath);\n }\n});\n\n/**\n * setupGoogleTagManager intializes Google Tag Manager.\n */\n(function setupGoogleTagManager() {\n analytics.track({\n 'gtm.start': new Date().getTime(),\n event: 'gtm.js',\n });\n})();\n\n/**\n * removeUTMSource removes the utm_source GET parameter if present.\n * This is done using JavaScript, so that the utm_source is still\n * captured by Google Analytics.\n */\nfunction removeUTMSource() {\n const urlParams = new URLSearchParams(window.location.search);\n const utmSource = urlParams.get('utm_source');\n if (utmSource !== 'gopls' && utmSource !== 'godoc' && utmSource !== 'pkggodev') {\n return;\n }\n\n /** Strip the utm_source query parameter and replace the URL. **/\n const newURL = new URL(window.location.href);\n urlParams.delete('utm_source');\n newURL.search = urlParams.toString();\n window.history.replaceState(null, '', newURL.toString());\n}\n\nif (document.querySelector<HTMLElement>('.js-gtmID')?.dataset.gtmid && window.dataLayer) {\n analytics.func(function () {\n removeUTMSource();\n });\n} else {\n removeUTMSource();\n}\n"], | |
"mappings": "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", | |
"names": [] | |
} |