Proyectos de Subversion Moodle

Rev

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

{"version":3,"file":"stickycolspan.min.js","sources":["../src/stickycolspan.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 * Javascript module for fixing the position of sticky headers with multiple colspans\n *\n * @module      gradereport_grader/stickycolspan\n * @copyright   2022 Bas Brands <bas@moodle.com>\n * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {SELECTORS as stickyFooterSelectors, eventTypes as stickyFooterEvents} from 'core/sticky-footer';\n\nconst SELECTORS = {\n    GRADEPARENT: '.gradeparent',\n    STUDENTHEADER: '#studentheader',\n    TABLEHEADER: 'th.header',\n    BEHAT: 'body.behat-site',\n    USERDROPDOWN: '.userrow th .dropdown',\n    LASTROW: '.lastrow',\n};\n\n/**\n * Initialize module\n */\nexport const init = () => {\n    // The sticky positioning attributed to the user column cells affects the stacking context and makes the dropdowns\n    // within these cells to be cut off. To solve this problem, whenever one of these action menus (dropdowns) is opened\n    // we need to manually bump up the z-index value of the parent container element and revert once closed.\n    document.querySelectorAll(SELECTORS.USERDROPDOWN).forEach((dropdown) => {\n        dropdown.addEventListener('show.bs.dropdown', (e) => {\n            // The closest heading element has sticky positioning which affects the stacking context in this case.\n            e.target.closest(SELECTORS.TABLEHEADER).classList.add('actions-menu-active');\n        });\n        dropdown.addEventListener('hide.bs.dropdown', (e) => {\n            e.target.closest(SELECTORS.TABLEHEADER).classList.remove('actions-menu-active');\n        });\n    });\n\n    defineLastRowIntersectionObserver(true);\n    // Add an event listener to the sticky footer toggled event to re-define the average row intersection observer\n    // accordingly. This is needed as on narrow screens when scrolling vertically the sticky footer is enabled and\n    // disabled dynamically.\n    document.addEventListener(stickyFooterEvents.stickyFooterStateChanged, (e) => {\n        defineLastRowIntersectionObserver(e.detail.enabled);\n    });\n\n    if (!document.querySelector(SELECTORS.BEHAT)) {\n        const grader = document.querySelector(SELECTORS.GRADEPARENT);\n        const tableHeaders = grader.querySelectorAll(SELECTORS.TABLEHEADER);\n        const studentHeader = grader.querySelector(SELECTORS.STUDENTHEADER);\n        const leftOffset = getComputedStyle(studentHeader).getPropertyValue('left');\n        const rightOffset = getComputedStyle(studentHeader).getPropertyValue('right');\n\n        tableHeaders.forEach((tableHeader) => {\n            if (tableHeader.colSpan > 1) {\n                const addOffset = (tableHeader.offsetWidth - studentHeader.offsetWidth);\n                if (window.right_to_left()) {\n                    tableHeader.style.right = 'calc(' + rightOffset + ' - ' + addOffset + 'px )';\n                } else {\n                    tableHeader.style.left = 'calc(' + leftOffset + ' - ' + addOffset + 'px )';\n                }\n            }\n        });\n    }\n};\n\n/**\n * Define the intersection observer that will make sure that the last row is properly pinned.\n *\n * In certain scenarios, such as when both 'Overall average' and 'Range' are set not to be shown in the Grader report,\n * a user row will end up being the last row in the Grader report table. In this particular case, we want to avoid\n * pinning the last row.\n *\n * @param {boolean} stickyFooterEnabled Whether the page shows a sticky footer or not.\n */\nconst defineLastRowIntersectionObserver = (stickyFooterEnabled) => {\n    const lastRow = document.querySelector(SELECTORS.LASTROW);\n    // Ensure that the last row is not a user row before defining the intersection observer.\n    if (!lastRow.classList.contains('userrow')) {\n        const stickyFooterHeight = stickyFooterEnabled ?\n            document.querySelector(stickyFooterSelectors.STICKYFOOTER).offsetHeight : null;\n        // Register an observer that will bump up the z-index value of the last row when it's pinned to prevent the row\n        // being cut-off by the user column cells or other components within the report table that have higher z-index\n        // values. If the page has a sticky footer, we need to make sure that the bottom root margin of the observer\n        // subtracts the height of the sticky footer to prevent the row being cut-off by the footer.\n        const intersectionObserver = new IntersectionObserver(\n            ([e]) => lastRow.classList.toggle('pinned', e.intersectionRatio < 1),\n            {\n                rootMargin: stickyFooterHeight ? `0px 0px -${stickyFooterHeight}px 0px` : \"0px\",\n                threshold: [1]\n            }\n        );\n        intersectionObserver.observe(lastRow.querySelector('th'));\n    }\n};\n"],"names":["SELECTORS","document","querySelectorAll","forEach","dropdown","addEventListener","e","target","closest","classList","add","remove","defineLastRowIntersectionObserver","stickyFooterEvents","stickyFooterStateChanged","detail","enabled","querySelector","grader","tableHeaders","studentHeader","leftOffset","getComputedStyle","getPropertyValue","rightOffset","tableHeader","colSpan","addOffset","offsetWidth","window","right_to_left","style","right","left","stickyFooterEnabled","lastRow","contains","stickyFooterHeight","stickyFooterSelectors","STICKYFOOTER","offsetHeight","IntersectionObserver","_ref","toggle","intersectionRatio","rootMargin","threshold","observe"],"mappings":";;;;;;;;MAyBMA,sBACW,eADXA,wBAEa,iBAFbA,sBAGW,YAHXA,gBAIK,kBAJLA,uBAKY,wBALZA,kBAMO,yBAMO,QAIhBC,SAASC,iBAAiBF,wBAAwBG,SAASC,WACvDA,SAASC,iBAAiB,oBAAqBC,IAE3CA,EAAEC,OAAOC,QAAQR,uBAAuBS,UAAUC,IAAI,0BAE1DN,SAASC,iBAAiB,oBAAqBC,IAC3CA,EAAEC,OAAOC,QAAQR,uBAAuBS,UAAUE,OAAO,6BAIjEC,mCAAkC,GAIlCX,SAASI,iBAAiBQ,yBAAmBC,0BAA2BR,IACpEM,kCAAkCN,EAAES,OAAOC,aAG1Cf,SAASgB,cAAcjB,iBAAkB,OACpCkB,OAASjB,SAASgB,cAAcjB,uBAChCmB,aAAeD,OAAOhB,iBAAiBF,uBACvCoB,cAAgBF,OAAOD,cAAcjB,yBACrCqB,WAAaC,iBAAiBF,eAAeG,iBAAiB,QAC9DC,YAAcF,iBAAiBF,eAAeG,iBAAiB,SAErEJ,aAAahB,SAASsB,iBACdA,YAAYC,QAAU,EAAG,OACnBC,UAAaF,YAAYG,YAAcR,cAAcQ,YACvDC,OAAOC,gBACPL,YAAYM,MAAMC,MAAQ,QAAUR,YAAc,MAAQG,UAAY,OAEtEF,YAAYM,MAAME,KAAO,QAAUZ,WAAa,MAAQM,UAAY,mBAgBlFf,kCAAqCsB,4BACjCC,QAAUlC,SAASgB,cAAcjB,uBAElCmC,QAAQ1B,UAAU2B,SAAS,WAAY,OAClCC,mBAAqBH,oBACvBjC,SAASgB,cAAcqB,wBAAsBC,cAAcC,aAAe,KAKjD,IAAIC,sBAC7BC,WAAEpC,eAAO6B,QAAQ1B,UAAUkC,OAAO,SAAUrC,EAAEsC,kBAAoB,KAClE,CACIC,WAAYR,sCAAiCA,6BAA6B,MAC1ES,UAAW,CAAC,KAGCC,QAAQZ,QAAQlB,cAAc"}