Proyectos de Subversion Moodle

Rev

Rev 1 | Autoría | Comparar con el anterior | Ultima modificación | Ver Log |

{"version":3,"file":"dialog.min.js","sources":["../../../src/local/dropdown/dialog.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Dropdown status JS controls.\n *\n * @module      core/local/dropdown/dialog\n * @copyright   2023 Ferran Recio <ferran@moodle.com>\n * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Dropdown from 'theme_boost/bootstrap/dropdown';\nimport {\n    firstFocusableElement,\n    lastFocusableElement,\n    previousFocusableElement,\n    nextFocusableElement,\n} from 'core/pagehelpers';\nimport Pending from 'core/pending';\nimport EventHandler from 'theme_boost/bootstrap/dom/event-handler';\n\nconst Selectors = {\n    dropdownButton: '[data-for=\"dropdowndialog_button\"]',\n    dropdownDialog: '[data-for=\"dropdowndialog_dialog\"]',\n};\n\n/**\n * Dropdown dialog class.\n * @private\n */\nexport class DropdownDialog {\n    /**\n     * Constructor.\n     * @param {HTMLElement} element The element to initialize.\n     */\n    constructor(element) {\n        this.element = element;\n        this.button = element.querySelector(Selectors.dropdownButton);\n        this.panel = element.querySelector(Selectors.dropdownDialog);\n    }\n\n    /**\n     * Initialize the subpanel element.\n     *\n     * This method adds the event listeners to the subpanel and the position classes.\n     */\n    init() {\n        if (this.element.dataset.dropdownDialogInitialized) {\n            return;\n        }\n\n        // Use the Bootstrap key handler for the Dropdown button key handler.\n        // This will avoid Boostrap Dropdown handler to prevent the propagation to the dialog.\n        // Menu Item events.\n        const dialogButtonSelector = `#${this.element.id} ${Selectors.dropdownButton}`;\n        EventHandler.on(document, 'keydown', dialogButtonSelector, this._buttonKeyHandler.bind(this));\n        // Subpanel content events.\n        const dialogSelector = `#${this.element.id} ${Selectors.dropdownDialog}`;\n        EventHandler.on(document, 'keydown', dialogSelector, this._contentKeyHandler.bind(this));\n\n        this.element.dataset.dropdownDialogInitialized = true;\n    }\n\n    /**\n     * Dropdown button key handler.\n     * @param {Event} event\n     * @private\n     */\n    _buttonKeyHandler(event) {\n        if (event.key === 'ArrowUp' || event.key === 'ArrowLeft') {\n            event.stopPropagation();\n            event.preventDefault();\n            this.setVisible(false);\n            return;\n        }\n\n        if (event.key === 'ArrowDown' || event.key === 'ArrowRight') {\n            event.stopPropagation();\n            event.preventDefault();\n            this.setVisible(true);\n            this._focusPanelContent();\n        }\n    }\n\n    /**\n     * Sub panel content key handler.\n     * @param {Event} event\n     * @private\n     */\n    _contentKeyHandler(event) {\n        let newFocus = null;\n\n        if (event.key === 'End') {\n            newFocus = lastFocusableElement(this.panel);\n        }\n        if (event.key === 'Home') {\n            newFocus = firstFocusableElement(this.panel);\n        }\n        if (event.key === 'ArrowUp' || event.key === 'ArrowLeft') {\n            newFocus = previousFocusableElement(this.panel, false);\n            if (!newFocus) {\n                newFocus = this.button;\n            }\n        }\n        if (event.key === 'ArrowDown' || event.key === 'ArrowRight') {\n            newFocus = nextFocusableElement(this.panel, false);\n        }\n        if (newFocus !== null) {\n            event.stopPropagation();\n            event.preventDefault();\n            newFocus.focus();\n        }\n    }\n\n    /**\n     * Focus on the first focusable element of the subpanel.\n     * @private\n     */\n    _focusPanelContent() {\n        const pendingPromise = new Pending('core/dropdown/dialog:focuscontent');\n        // Some Bootstrap events are triggered after the click event.\n        // To prevent this from affecting the focus we wait a bit.\n        setTimeout(() => {\n            const firstFocusable = firstFocusableElement(this.panel);\n            if (firstFocusable) {\n                firstFocusable.focus();\n            }\n            pendingPromise.resolve();\n        }, 100);\n    }\n\n    /**\n     * Set the visibility of a subpanel.\n     * @param {Boolean} visible true if the subpanel should be visible.\n     */\n    setVisible(visible) {\n        if (visible === this.isVisible()) {\n            return;\n        }\n        Dropdown.getOrCreateInstance(this.button).toggle();\n    }\n\n    /**\n     * Get the visibility of a subpanel.\n     * @returns {Boolean} true if the subpanel is visible.\n     */\n    isVisible() {\n        return this.button.getAttribute('aria-expanded') === 'true';\n    }\n\n    /**\n     * Set the content of the button.\n     * @param {String} content\n     */\n    setButtonContent(content) {\n        this.button.innerHTML = content;\n    }\n\n    /**\n     * Set the disabled state of the button.\n     * @param {Boolean} disabled\n     */\n    setButtonDisabled(disabled) {\n        if (disabled) {\n            this.button.setAttribute('disabled', 'disabled');\n        } else {\n            this.button.removeAttribute('disabled');\n        }\n    }\n\n    /**\n     * Return the main dropdown HTML element.\n     * @returns {HTMLElement} The element.\n     */\n    getElement() {\n        return this.element;\n    }\n}\n\n/**\n * Get the dropdown dialog instance from a selector.\n * @param {string} selector The query selector to init.\n * @returns {DropdownDialog|null} The dropdown dialog instance if any.\n */\nexport const getDropdownDialog = (selector) => {\n    const dropdownElement = document.querySelector(selector);\n    if (!dropdownElement) {\n        return null;\n    }\n    return new DropdownDialog(dropdownElement);\n};\n\n/**\n * Initialize module.\n *\n * @method\n * @param {string} selector The query selector to init.\n */\nexport const init = (selector) => {\n    const dropdown = getDropdownDialog(selector);\n    if (!dropdown) {\n        throw new Error(`Dopdown dialog element not found: ${selector}`);\n    }\n    dropdown.init();\n};\n"],"names":["Selectors","DropdownDialog","constructor","element","button","querySelector","panel","init","this","dataset","dropdownDialogInitialized","dialogButtonSelector","id","on","document","_buttonKeyHandler","bind","dialogSelector","_contentKeyHandler","event","key","stopPropagation","preventDefault","setVisible","_focusPanelContent","newFocus","focus","pendingPromise","Pending","setTimeout","firstFocusable","resolve","visible","isVisible","getOrCreateInstance","toggle","getAttribute","setButtonContent","content","innerHTML","setButtonDisabled","disabled","setAttribute","removeAttribute","getElement","getDropdownDialog","selector","dropdownElement","dropdown","Error"],"mappings":";;;;;;;qRAiCMA,yBACc,qCADdA,yBAEc,2CAOPC,eAKTC,YAAYC,cACHA,QAAUA,aACVC,OAASD,QAAQE,cAAcL,+BAC/BM,MAAQH,QAAQE,cAAcL,0BAQvCO,UACQC,KAAKL,QAAQM,QAAQC,uCAOnBC,gCAA2BH,KAAKL,QAAQS,eAAMZ,gDACvCa,GAAGC,SAAU,UAAWH,qBAAsBH,KAAKO,kBAAkBC,KAAKR,aAEjFS,0BAAqBT,KAAKL,QAAQS,eAAMZ,gDACjCa,GAAGC,SAAU,UAAWG,eAAgBT,KAAKU,mBAAmBF,KAAKR,YAE7EL,QAAQM,QAAQC,2BAA4B,EAQrDK,kBAAkBI,UACI,YAAdA,MAAMC,KAAmC,cAAdD,MAAMC,WACjCD,MAAME,kBACNF,MAAMG,2BACDC,YAAW,GAIF,cAAdJ,MAAMC,KAAqC,eAAdD,MAAMC,MACnCD,MAAME,kBACNF,MAAMG,sBACDC,YAAW,QACXC,sBASbN,mBAAmBC,WACXM,SAAW,KAEG,QAAdN,MAAMC,MACNK,UAAW,qCAAqBjB,KAAKF,QAEvB,SAAda,MAAMC,MACNK,UAAW,sCAAsBjB,KAAKF,QAExB,YAAda,MAAMC,KAAmC,cAAdD,MAAMC,MACjCK,UAAW,yCAAyBjB,KAAKF,OAAO,GAC3CmB,WACDA,SAAWjB,KAAKJ,SAGN,cAAde,MAAMC,KAAqC,eAAdD,MAAMC,MACnCK,UAAW,qCAAqBjB,KAAKF,OAAO,IAE/B,OAAbmB,WACAN,MAAME,kBACNF,MAAMG,iBACNG,SAASC,SAQjBF,2BACUG,eAAiB,IAAIC,iBAAQ,qCAGnCC,YAAW,WACDC,gBAAiB,sCAAsBtB,KAAKF,OAC9CwB,gBACAA,eAAeJ,QAEnBC,eAAeI,YAChB,KAOPR,WAAWS,SACHA,UAAYxB,KAAKyB,+BAGZC,oBAAoB1B,KAAKJ,QAAQ+B,SAO9CF,kBACyD,SAA9CzB,KAAKJ,OAAOgC,aAAa,iBAOpCC,iBAAiBC,cACRlC,OAAOmC,UAAYD,QAO5BE,kBAAkBC,UACVA,cACKrC,OAAOsC,aAAa,WAAY,iBAEhCtC,OAAOuC,gBAAgB,YAQpCC,oBACWpC,KAAKL,sDASP0C,kBAAqBC,iBACxBC,gBAAkBjC,SAAST,cAAcyC,iBAC1CC,gBAGE,IAAI9C,eAAe8C,iBAFf,iEAWMD,iBACXE,SAAWH,kBAAkBC,cAC9BE,eACK,IAAIC,kDAA2CH,WAEzDE,SAASzC"}