From 2df54f13001fd3019179ea27e16703816de99845 Mon Sep 17 00:00:00 2001 From: Richard Klees Date: Wed, 26 Jun 2024 17:28:49 +0200 Subject: [PATCH] UI: JS for dropdown --- components/ILIAS/UI/UI.php | 2 +- .../UI/resources/js/Dropdown/dist/dropdown.js | 15 ++ .../UI/resources/js/Dropdown/dropdown.js | 14 -- .../UI/resources/js/Dropdown/rollup.config.js | 27 ++++ .../js/Dropdown/src/dropdown.class.js | 129 ++++++++++++++++++ .../UI/resources/js/Dropdown/src/dropdown.js | 23 ++++ .../Component/Dropdown/Renderer.php | 5 + .../default/Dropdown/tpl.standard.html | 2 +- 8 files changed, 201 insertions(+), 16 deletions(-) create mode 100644 components/ILIAS/UI/resources/js/Dropdown/dist/dropdown.js delete mode 100755 components/ILIAS/UI/resources/js/Dropdown/dropdown.js create mode 100644 components/ILIAS/UI/resources/js/Dropdown/rollup.config.js create mode 100644 components/ILIAS/UI/resources/js/Dropdown/src/dropdown.class.js create mode 100644 components/ILIAS/UI/resources/js/Dropdown/src/dropdown.js diff --git a/components/ILIAS/UI/UI.php b/components/ILIAS/UI/UI.php index 2b00ee377859..906f9496113c 100644 --- a/components/ILIAS/UI/UI.php +++ b/components/ILIAS/UI/UI.php @@ -41,7 +41,7 @@ public function init( $contribute[Component\Resource\PublicAsset::class] = fn() => new Component\Resource\ComponentJS($this, "js/Counter/dist/counter.js"); $contribute[Component\Resource\PublicAsset::class] = fn() => - new Component\Resource\ComponentJS($this, "js/Dropdown/dropdown.js"); + new Component\Resource\ComponentJS($this, "js/Dropdown/dist/dropdown.js"); $contribute[Component\Resource\PublicAsset::class] = fn() => new Component\Resource\NodeModule("dropzone/dist/min/dropzone.min.js"); diff --git a/components/ILIAS/UI/resources/js/Dropdown/dist/dropdown.js b/components/ILIAS/UI/resources/js/Dropdown/dist/dropdown.js new file mode 100644 index 000000000000..facf2de26c7f --- /dev/null +++ b/components/ILIAS/UI/resources/js/Dropdown/dist/dropdown.js @@ -0,0 +1,15 @@ +/** + * This file is part of ILIAS, a powerful learning management system + * published by ILIAS open source e-Learning e.V. + * + * ILIAS is licensed with the GPL-3.0, + * see https://www.gnu.org/licenses/gpl-3.0.en.html + * You should have received a copy of said license along with the + * source code, too. + * + * If this is not the case or you just want to try ILIAS, you'll find + * us at: + * https://www.ilias.de + * https://github.com/ILIAS-eLearning + */ +!function(e,t){"use strict";function i(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var n=i(e),s=i(t);class l{#e;#t;#i;#n;#s;#l;#o;constructor(e,t){this.#e=e,this.#t=t;const i=this.#t.querySelectorAll(":scope > button");if(1!==i.length)return void console.log("Dropdown: Expected exactly one button in dropdown element.",this.#t);this.#i=i[0];const n=this.#t.querySelectorAll(":scope > ul");1===n.length?(this.#n=n[0],this.initEvents()):console.log("Dropdown: Expected exactly one ul in dropdown element.",this.#t)}initEvents(){const e=this;this.#i.addEventListener("keydown",(t=>{13===t.which&&(t.preventDefault(),e.toggleVisibility())})),this.#s=function(t){27===t.which&&(t.preventDefault(),e.makeInvisible())},this.#l=function(t){t.preventDefault(),t.stopPropagation(),e.makeVisible()},this.#i.addEventListener("click",this.#l),this.#o=function(){e.makeInvisible()}}toggleVisibility(){"block"===this.#n.style.display?this.makeInvisible():this.makeVisible()}makeVisible(){this.#n.style.display="block",this.#i.setAttribute("aria-expanded","true"),this.#e.addEventListener("keydown",this.#s),this.#e.addEventListener("click",this.#o),this.#i.removeEventListener("click",this.#l)}makeInvisible(){this.#n.style.display="none",this.#i.setAttribute("aria-expanded","false"),this.#e.removeEventListener("keydown",this.#s),this.#e.removeEventListener("click",this.#o),this.#i.addEventListener("click",this.#l)}}n.default.UI=n.default.UI||{},n.default.UI.dropdown=function(e){new l(s.default,e)}}(il,document); diff --git a/components/ILIAS/UI/resources/js/Dropdown/dropdown.js b/components/ILIAS/UI/resources/js/Dropdown/dropdown.js deleted file mode 100755 index 2a61cf0310dd..000000000000 --- a/components/ILIAS/UI/resources/js/Dropdown/dropdown.js +++ /dev/null @@ -1,14 +0,0 @@ -(function($) { - $(document).on('shown.bs.dropdown', function(event) { - var dropdown = $(event.target); - dropdown.find('.dropdown-toggle').attr('aria-expanded', true); - //Fit Dropdowns correctly to page, omit for legacy component, add new Item, see #30856 - il.UI.page.fit(dropdown.find('.dropdown-menu:not(#il-add-new-item-gl)')); - }); - - // on close - $(document).on('hidden.bs.dropdown', function(event) { - var dropdown = $(event.target); - dropdown.find('.dropdown-toggle').attr('aria-expanded', false); - }); -})($); \ No newline at end of file diff --git a/components/ILIAS/UI/resources/js/Dropdown/rollup.config.js b/components/ILIAS/UI/resources/js/Dropdown/rollup.config.js new file mode 100644 index 000000000000..c8a9d8cbe049 --- /dev/null +++ b/components/ILIAS/UI/resources/js/Dropdown/rollup.config.js @@ -0,0 +1,27 @@ +import terser from '@rollup/plugin-terser'; +import copyright from '../../../../../../scripts/Copyright-Checker/copyright'; +import preserveCopyright from '../../../../../../scripts/Copyright-Checker/preserveCopyright'; + +export default { + external: [ + 'document', + 'ilias', + ], + input: './src/dropdown.js', + output: { + file: './dist/dropdown.js', + format: 'iife', + banner: copyright, + globals: { + document: 'document', + ilias: 'il', + }, + plugins: [ + terser({ + format: { + comments: preserveCopyright, + }, + }), + ], + }, +}; diff --git a/components/ILIAS/UI/resources/js/Dropdown/src/dropdown.class.js b/components/ILIAS/UI/resources/js/Dropdown/src/dropdown.class.js new file mode 100644 index 000000000000..ffbf5709513b --- /dev/null +++ b/components/ILIAS/UI/resources/js/Dropdown/src/dropdown.class.js @@ -0,0 +1,129 @@ +/** +* This file is part of ILIAS, a powerful learning management system +* published by ILIAS open source e-Learning e.V. +* +* ILIAS is licensed with the GPL-3.0, +* see https://www.gnu.org/licenses/gpl-3.0.en.html +* You should have received a copy of said license along with the +* source code, too. +* +* If this is not the case or you just want to try ILIAS, you'll find +* us at: +* https://www.ilias.de +* https://github.com/ILIAS-eLearning +*/ + +export default class Dropdown { + /** + * @type {DOMDocument} + */ + #document; + + /** + * @type {HTMLElement} + */ + #element; + + /** + * @type {HTMLElement} + */ + #button; + + /** + * @type {HTMLElement} + */ + #list; + + /** + * @type {function} + */ + #makeInvisibleOnEscape; + + /** + * @type {function} + */ + #makeVisibleOnClick; + + /** + * @type {function} + */ + #makeInvisibleOnClick; + + /** + * @param {DOMDocument} document + * @param {HTMLElement} element + */ + constructor(document, element) { + this.#document = document; + this.#element = element; + + const buttons = this.#element.querySelectorAll(':scope > button'); + if (buttons.length !== 1) { + console.log('Dropdown: Expected exactly one button in dropdown element.', this.#element); + return; + } + [this.#button] = buttons; + + const lists = this.#element.querySelectorAll(':scope > ul'); + if (lists.length !== 1) { + console.log('Dropdown: Expected exactly one ul in dropdown element.', this.#element); + return; + } + [this.#list] = lists; + + this.initEvents(); + } + + initEvents() { + const self = this; + this.#button.addEventListener('keydown', (event) => { + if (event.which === 13) { // Enter + event.preventDefault(); + self.toggleVisibility(); + } + }); + + this.#makeInvisibleOnEscape = function (event) { + if (event.which === 27) { // ESCAPE + event.preventDefault(); + self.makeInvisible(); + } + }; + + this.#makeVisibleOnClick = function (event) { + event.preventDefault(); + event.stopPropagation(); + self.makeVisible(); + }; + this.#button.addEventListener('click', this.#makeVisibleOnClick); + + this.#makeInvisibleOnClick = function () { + self.makeInvisible(); + }; + } + + toggleVisibility() { + const visible = this.#list.style.display === 'block'; + if (visible) { + this.makeInvisible(); + } else { + this.makeVisible(); + } + } + + makeVisible() { + this.#list.style.display = 'block'; + this.#button.setAttribute('aria-expanded', 'true'); + this.#document.addEventListener('keydown', this.#makeInvisibleOnEscape); + this.#document.addEventListener('click', this.#makeInvisibleOnClick); + this.#button.removeEventListener('click', this.#makeVisibleOnClick); + } + + makeInvisible() { + this.#list.style.display = 'none'; + this.#button.setAttribute('aria-expanded', 'false'); + this.#document.removeEventListener('keydown', this.#makeInvisibleOnEscape); + this.#document.removeEventListener('click', this.#makeInvisibleOnClick); + this.#button.addEventListener('click', this.#makeVisibleOnClick); + } +} diff --git a/components/ILIAS/UI/resources/js/Dropdown/src/dropdown.js b/components/ILIAS/UI/resources/js/Dropdown/src/dropdown.js new file mode 100644 index 000000000000..d8533157e791 --- /dev/null +++ b/components/ILIAS/UI/resources/js/Dropdown/src/dropdown.js @@ -0,0 +1,23 @@ +/** + * This file is part of ILIAS, a powerful learning management system + * published by ILIAS open source e-Learning e.V. + * + * ILIAS is licensed with the GPL-3.0, + * see https://www.gnu.org/licenses/gpl-3.0.en.html + * You should have received a copy of said license along with the + * source code, too. + * + * If this is not the case or you just want to try ILIAS, you'll find + * us at: + * https://www.ilias.de + * https://github.com/ILIAS-eLearning + */ + +import il from 'ilias'; +import document from 'document'; +import Dropdown from './dropdown.class'; + +il.UI = il.UI || {}; +il.UI.dropdown = function (htmlElement) { + new Dropdown(document, htmlElement); +}; diff --git a/components/ILIAS/UI/src/Implementation/Component/Dropdown/Renderer.php b/components/ILIAS/UI/src/Implementation/Component/Dropdown/Renderer.php index 00d2770d3038..b01fad526ff0 100755 --- a/components/ILIAS/UI/src/Implementation/Component/Dropdown/Renderer.php +++ b/components/ILIAS/UI/src/Implementation/Component/Dropdown/Renderer.php @@ -74,6 +74,11 @@ protected function renderDropdown(Dropdown $component, RendererInterface $defaul $tpl->parseCurrentBlock(); } + $component = $component->withAdditionalOnLoadCode( + fn($id) => + "il.UI.dropdown(document.getElementById(\"$id\"));" + ); + $this->renderId($component, $tpl); return $tpl->get(); diff --git a/components/ILIAS/UI/src/templates/default/Dropdown/tpl.standard.html b/components/ILIAS/UI/src/templates/default/Dropdown/tpl.standard.html index f2a0520d5acc..d141db0c606f 100755 --- a/components/ILIAS/UI/src/templates/default/Dropdown/tpl.standard.html +++ b/components/ILIAS/UI/src/templates/default/Dropdown/tpl.standard.html @@ -1,4 +1,4 @@ -