Proyectos de Subversion Moodle

Rev

Autoría | Ultima modificación | Ver Log |

{"version":3,"file":"overlay.min.js","sources":["../../../src/local/reactive/overlay.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 * Element overlay methods.\n *\n * This module is used to create overlay information on components. For example\n * to generate or destroy file drop-zones.\n *\n * @module     core/local/reactive/overlay\n * @copyright  2022 Ferran Recio <ferran@moodle.com>\n * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Templates from 'core/templates';\nimport Prefetch from 'core/prefetch';\n\n// Prefetch the overlay html.\nconst overlayTemplate = 'core/local/reactive/overlay';\nPrefetch.prefetchTemplate(overlayTemplate);\n\n/**\n * @var {boolean} isInitialized if the module is capturing the proper page events.\n */\nlet isInitialized = false;\n\n/**\n * @var {Object} isInitialized if the module is capturing the proper page events.\n */\nconst selectors = {\n    OVERLAY: \"[data-overlay]\",\n    REPOSITION: \"[data-overlay-dynamic]\",\n    NAVBAR: \"nav.navbar.fixed-top\",\n};\n\n/**\n * Adds an overlay to a specific page element.\n *\n * @param {Object} definition the overlay definition.\n * @param {String|Promise} definition.content an optional overlay content.\n * @param {String|Promise} definition.icon an optional icon content.\n * @param {String} definition.classes an optional CSS classes\n * @param {HTMLElement} parent the parent object\n * @return {HTMLElement|undefined} the new page element.\n */\nexport const addOverlay = async(definition, parent) => {\n    // Validate non of the passed params is a promise.\n    if (definition.content && typeof definition.content !== 'string') {\n        definition.content = await definition.content;\n    }\n    if (definition.icon && typeof definition.icon !== 'string') {\n        definition.icon = await definition.icon;\n    }\n    const data = {\n        content: definition.content,\n        css: definition.classes ?? 'file-drop-zone',\n    };\n    const {html, js} = await Templates.renderForPromise(overlayTemplate, data);\n    Templates.appendNodeContents(parent, html, js);\n    const overlay = parent.querySelector(selectors.OVERLAY);\n    rePositionPreviewInfoElement(overlay);\n    init();\n    return overlay;\n};\n\n/**\n * Adds an overlay to a specific page element.\n *\n * @param {HTMLElement} overlay the parent object\n */\nexport const removeOverlay = (overlay) => {\n    if (!overlay || !overlay.parentNode) {\n        return;\n    }\n    // Remove any forced parentNode position.\n    if (overlay.dataset?.overlayPosition) {\n        delete overlay.parentNode.style.position;\n    }\n    overlay.parentNode.removeChild(overlay);\n};\n\nexport const removeAllOverlays = () => {\n    document.querySelectorAll(selectors.OVERLAY).forEach(\n        (overlay) => {\n            removeOverlay(overlay);\n        }\n    );\n};\n\n/**\n * Re-position the preview information element by calculating the section position.\n *\n * @param {Object} overlay the overlay element.\n */\nconst rePositionPreviewInfoElement = function(overlay) {\n    if (!overlay) {\n        throw new Error('Inexistent overlay element');\n    }\n    // Add relative position to the parent object.\n    if (!overlay.parentNode?.style?.position) {\n        overlay.parentNode.style.position = 'relative';\n        overlay.dataset.overlayPosition = \"true\";\n    }\n    // Get the element to reposition.\n    const target = overlay.querySelector(selectors.REPOSITION);\n    if (!target) {\n        return;\n    }\n    // Get the new bounds.\n    const rect = overlay.getBoundingClientRect();\n    const sectionHeight = parseInt(window.getComputedStyle(overlay).height, 10);\n    const sectionOffset = rect.top;\n    const previewHeight = parseInt(window.getComputedStyle(target).height, 10) +\n        (2 * parseInt(window.getComputedStyle(target).padding, 10));\n    // Calculate the new target position.\n    let top, bottom;\n    if (sectionOffset < 0) {\n        if (sectionHeight + sectionOffset >= previewHeight) {\n            // We have enough space here, just stick the preview to the top.\n            let offSetTop = 0 - sectionOffset;\n            const navBar = document.querySelector(selectors.NAVBAR);\n            if (navBar) {\n                offSetTop = offSetTop + navBar.offsetHeight;\n            }\n            top = offSetTop + 'px';\n            bottom = 'unset';\n        } else {\n            // We do not have enough space here, just stick the preview to the bottom.\n            top = 'unset';\n            bottom = 0;\n        }\n    } else {\n        top = 0;\n        bottom = 'unset';\n    }\n\n    target.style.top = top;\n    target.style.bottom = bottom;\n};\n\n// Update overlays when the page scrolls.\nconst init = () => {\n    if (isInitialized) {\n        return;\n    }\n    // Add scroll events.\n    document.addEventListener('scroll', () => {\n        document.querySelectorAll(selectors.OVERLAY).forEach(\n            (overlay) => {\n                rePositionPreviewInfoElement(overlay);\n            }\n        );\n    }, true);\n};\n"],"names":["prefetchTemplate","selectors","async","definition","parent","content","icon","data","css","classes","html","js","Templates","renderForPromise","appendNodeContents","overlay","querySelector","rePositionPreviewInfoElement","init","removeOverlay","parentNode","dataset","_overlay$dataset","overlayPosition","style","position","removeChild","document","querySelectorAll","forEach","Error","_overlay$parentNode","_overlay$parentNode$s","target","rect","getBoundingClientRect","sectionHeight","parseInt","window","getComputedStyle","height","sectionOffset","top","previewHeight","padding","bottom","offSetTop","navBar","offsetHeight","addEventListener"],"mappings":";;;;;;;;;;sPA+BSA,iBADe,qCAWlBC,kBACO,iBADPA,qBAEU,yBAFVA,iBAGM,2CAacC,MAAMC,WAAYC,kCAEpCD,WAAWE,SAAyC,iBAAvBF,WAAWE,UACxCF,WAAWE,cAAgBF,WAAWE,SAEtCF,WAAWG,MAAmC,iBAApBH,WAAWG,OACrCH,WAAWG,WAAaH,WAAWG,YAEjCC,KAAO,CACTF,QAASF,WAAWE,QACpBG,gCAAKL,WAAWM,2DAAW,mBAEzBC,KAACA,KAADC,GAAOA,UAAYC,mBAAUC,iBAvCf,8BAuCiDN,yBAC3DO,mBAAmBV,OAAQM,KAAMC,UACrCI,QAAUX,OAAOY,cAAcf,0BACrCgB,6BAA6BF,SAC7BG,OACOH,eAQEI,cAAiBJ,+BACrBA,SAAYA,QAAQK,sCAIrBL,QAAQM,qCAARC,iBAAiBC,wBACVR,QAAQK,WAAWI,MAAMC,SAEpCV,QAAQK,WAAWM,YAAYX,2EAGF,KAC7BY,SAASC,iBAAiB3B,mBAAmB4B,SACxCd,UACGI,cAAcJ,mBAUpBE,6BAA+B,SAASF,2DACrCA,cACK,IAAIe,MAAM,0DAGff,QAAQK,yEAARW,oBAAoBP,wCAApBQ,sBAA2BP,WAC5BV,QAAQK,WAAWI,MAAMC,SAAW,WACpCV,QAAQM,QAAQE,gBAAkB,cAGhCU,OAASlB,QAAQC,cAAcf,0BAChCgC,oBAICC,KAAOnB,QAAQoB,wBACfC,cAAgBC,SAASC,OAAOC,iBAAiBxB,SAASyB,OAAQ,IAClEC,cAAgBP,KAAKQ,IACrBC,cAAgBN,SAASC,OAAOC,iBAAiBN,QAAQO,OAAQ,IAClE,EAAIH,SAASC,OAAOC,iBAAiBN,QAAQW,QAAS,QAEvDF,IAAKG,UACLJ,cAAgB,KACZL,cAAgBK,eAAiBE,cAAe,KAE5CG,UAAY,EAAIL,oBACdM,OAASpB,SAASX,cAAcf,kBAClC8C,SACAD,WAAwBC,OAAOC,cAEnCN,IAAMI,UAAY,KAClBD,OAAS,aAGTH,IAAM,QACNG,OAAS,OAGbH,IAAM,EACNG,OAAS,QAGbZ,OAAOT,MAAMkB,IAAMA,IACnBT,OAAOT,MAAMqB,OAASA,QAIpB3B,KAAO,KAKTS,SAASsB,iBAAiB,UAAU,KAChCtB,SAASC,iBAAiB3B,mBAAmB4B,SACxCd,UACGE,6BAA6BF,eAGtC"}