diff --git a/administrator/components/com_content/tmpl/articles/default.php b/administrator/components/com_content/tmpl/articles/default.php index 1cb2e2cbe0d4b..dd8b9eba43527 100644 --- a/administrator/components/com_content/tmpl/articles/default.php +++ b/administrator/components/com_content/tmpl/articles/default.php @@ -26,6 +26,9 @@ HTMLHelper::_('behavior.multiselect'); +// Just for the tests :( +HTMLHelper::_('jquery.framework'); + $app = Factory::getApplication(); $user = Factory::getUser(); $userId = $user->get('id'); diff --git a/administrator/components/com_fields/tmpl/fields/default.php b/administrator/components/com_fields/tmpl/fields/default.php index fefd4b33848a4..b5dc679539f30 100644 --- a/administrator/components/com_fields/tmpl/fields/default.php +++ b/administrator/components/com_fields/tmpl/fields/default.php @@ -20,6 +20,9 @@ HTMLHelper::_('behavior.multiselect'); +// Just for the tests :( +HTMLHelper::_('jquery.framework'); + $app = Factory::getApplication(); $user = Factory::getUser(); $userId = $user->get('id'); diff --git a/administrator/components/com_joomlaupdate/tmpl/update/default.php b/administrator/components/com_joomlaupdate/tmpl/update/default.php index 474a52ed3f334..f1aaf9b569eb7 100644 --- a/administrator/components/com_joomlaupdate/tmpl/update/default.php +++ b/administrator/components/com_joomlaupdate/tmpl/update/default.php @@ -16,6 +16,7 @@ /** @var Joomla\CMS\WebAsset\WebAssetManager $wa */ $wa = $this->document->getWebAssetManager(); $wa->useScript('core') + ->useScript('jquery') ->useScript('com_joomlaupdate.encryption') ->useScript('com_joomlaupdate.update') ->useScript('com_joomlaupdate.admin-update'); diff --git a/administrator/components/com_joomlaupdate/tmpl/upload/captive.php b/administrator/components/com_joomlaupdate/tmpl/upload/captive.php index 9ee1118249fbb..bc7b120d29d23 100644 --- a/administrator/components/com_joomlaupdate/tmpl/upload/captive.php +++ b/administrator/components/com_joomlaupdate/tmpl/upload/captive.php @@ -20,6 +20,7 @@ /** @var Joomla\CMS\WebAsset\WebAssetManager $wa */ $wa = $this->document->getWebAssetManager(); $wa->useScript('core') + ->useScript('jquery') ->useScript('form.validate') ->useScript('keepalive') ->useScript('field.passwordview'); diff --git a/administrator/components/com_mails/tmpl/templates/default.php b/administrator/components/com_mails/tmpl/templates/default.php index 79b5a09079555..93a901cbc87e3 100644 --- a/administrator/components/com_mails/tmpl/templates/default.php +++ b/administrator/components/com_mails/tmpl/templates/default.php @@ -14,6 +14,8 @@ use Joomla\CMS\Layout\LayoutHelper; use Joomla\CMS\Router\Route; +HTMLHelper::_('bootstrap.dropdown'); + $listOrder = $this->escape($this->state->get('list.ordering')); $listDirn = $this->escape($this->state->get('list.direction')); ?> diff --git a/administrator/components/com_templates/tmpl/template/default.php b/administrator/components/com_templates/tmpl/template/default.php index 816b566f857d0..adb24ed855799 100644 --- a/administrator/components/com_templates/tmpl/template/default.php +++ b/administrator/components/com_templates/tmpl/template/default.php @@ -376,7 +376,7 @@ ); ?>
- +
type != 'home') : ?> @@ -391,7 +391,7 @@ ); ?>
- +
@@ -406,7 +406,7 @@ 'body' => $this->loadTemplate('modal_delete_body') ); ?> - + $this->loadTemplate('modal_file_body') ); ?> - + 'folderModal', @@ -437,7 +437,7 @@ 'body' => $this->loadTemplate('modal_folder_body') ); ?> - + type == 'image') : ?>
- +
diff --git a/build/build-modules-js/build-bootstrap-js.es6.js b/build/build-modules-js/build-bootstrap-js.es6.js new file mode 100644 index 0000000000000..fae0380489f06 --- /dev/null +++ b/build/build-modules-js/build-bootstrap-js.es6.js @@ -0,0 +1,155 @@ +const { + readdir, readFile, rename, writeFile, rm, +} = require('fs').promises; +const { resolve } = require('path'); +const { minify } = require('terser'); +const rimraf = require('rimraf'); +const rollup = require('rollup'); +const { nodeResolve } = require('@rollup/plugin-node-resolve'); +const replace = require('@rollup/plugin-replace'); +const { babel } = require('@rollup/plugin-babel'); + +const tasks = []; +const inputFolder = 'build/media_source/vendor/bootstrap/js'; +const outputFolder = 'media/vendor/bootstrap/js'; + +const createMinified = async (file) => { + const initial = await readFile(resolve(outputFolder, file), { encoding: 'utf8' }); + const mini = await minify(initial); + await rename(resolve(outputFolder, file), resolve(outputFolder, `${file.split('-')[0]}.es6.js`)); + await writeFile(resolve(outputFolder, `${file.split('-')[0]}.es6.min.js`), mini.code, { encoding: 'utf8' }); +}; + +const build = async () => { + // eslint-disable-next-line no-console + console.log('Building ES6 Components...'); + + const bundle = await rollup.rollup({ + input: resolve(inputFolder, 'index.es6.js'), + plugins: [ + nodeResolve(), + replace({ + 'process.env.NODE_ENV': '\'production\'', + }), + ], + external: [ + './base-component.js', + './dom/data.js', + './event-handler.js', + './dom/manipulator.js', + './selector-engine.js', + './util/index.js', + ], + manualChunks: { + alert: ['build/media_source/vendor/bootstrap/js/alert.es6.js'], + button: ['build/media_source/vendor/bootstrap/js/button.es6.js'], + carousel: ['build/media_source/vendor/bootstrap/js/carousel.es6.js'], + collapse: ['build/media_source/vendor/bootstrap/js/collapse.es6.js'], + dropdown: ['build/media_source/vendor/bootstrap/js/dropdown.es6.js'], + modal: ['build/media_source/vendor/bootstrap/js/modal.es6.js'], + popover: ['build/media_source/vendor/bootstrap/js/popover.es6.js'], + scrollspy: ['build/media_source/vendor/bootstrap/js/scrollspy.es6.js'], + tab: ['build/media_source/vendor/bootstrap/js/tab.es6.js'], + toast: ['build/media_source/vendor/bootstrap/js/toast.es6.js'], + popper: ['@popperjs/core'], + dom: [ + 'node_modules/bootstrap/js/src/base-component.js', + 'node_modules/bootstrap/js/src/dom/data.js', + 'node_modules/bootstrap/js/src/dom/event-handler.js', + 'node_modules/bootstrap/js/src/dom/manipulator.js', + 'node_modules/bootstrap/js/src/dom/selector-engine.js', + 'node_modules/bootstrap/js/src/util/index.js', + ], + }, + }); + + await bundle.write({ + format: 'es', + sourcemap: false, + dir: outputFolder, + }); +}; + +const buildLegacy = async () => { + // eslint-disable-next-line no-console + console.log('Building Legacy...'); + + const bundle = await rollup.rollup({ + input: resolve(inputFolder, 'index.es6.js'), + plugins: [ + nodeResolve(), + replace({ + 'process.env.NODE_ENV': '\'production\'', + }), + babel({ + exclude: 'node_modules/core-js/**', + babelHelpers: 'bundled', + babelrc: false, + presets: [ + [ + '@babel/preset-env', + { + corejs: '3.8', + useBuiltIns: 'usage', + targets: { + chrome: '58', + ie: '11', + }, + loose: true, + bugfixes: true, + modules: false, + }, + ], + ], + }), + ], + external: [], + }); + + await bundle.write({ + format: 'iife', + sourcemap: false, + name: 'Bootstrap', + file: resolve(outputFolder, 'bootstrap.es5.js'), + }); +}; + +(async () => { + rimraf.sync(resolve(outputFolder)); + + try { + await build(resolve(inputFolder, 'index.es6.js')); + await rm(resolve(outputFolder, 'index.es6.js')); + } catch (error) { + // eslint-disable-next-line no-console + console.error(error); + process.exit(1); + } + + (await readdir(outputFolder)).forEach((file) => { + if (!(file.startsWith('dom-') || file.startsWith('popper-'))) { + tasks.push(createMinified(file)); + } + }); + + await Promise.all(tasks).catch((er) => { + // eslint-disable-next-line no-console + console.log(er); + process.exit(1); + }); + // eslint-disable-next-line no-console + console.log('ES6 components ready ✅'); + + try { + await buildLegacy(inputFolder, 'index.es6.js'); + const es5File = await readFile(resolve(outputFolder, 'bootstrap.es5.js'), { encoding: 'utf8' }); + const mini = await minify(es5File); + await writeFile(resolve(outputFolder, 'bootstrap.es5.min.js'), mini.code, { encoding: 'utf8' }); + // eslint-disable-next-line no-console + console.log('Legacy done! ✅'); + } catch (error) { + // eslint-disable-next-line no-console + console.error(error); + process.exit(1); + } +})(); diff --git a/build/build-modules-js/compilejs.es6.js b/build/build-modules-js/compilejs.es6.js index e4cf2c3bd6581..d79c201236c01 100644 --- a/build/build-modules-js/compilejs.es6.js +++ b/build/build-modules-js/compilejs.es6.js @@ -1,4 +1,5 @@ const Fs = require('fs'); +const { sep } = require('path'); const Recurs = require('recursive-readdir'); const HandleFile = require('./javascript/handle-file.es6.js'); @@ -45,6 +46,9 @@ module.exports.compileJS = (options, path) => { (files) => { files.forEach( (file) => { + if (file.includes(`build${sep}media_source${sep}vendor${sep}bootstrap${sep}js`)) { + return; + } HandleFile.run(file); }, (error) => { diff --git a/build/build-modules-js/settings.json b/build/build-modules-js/settings.json index c12c0e4de3d16..51e58b3cdcd6e 100644 --- a/build/build-modules-js/settings.json +++ b/build/build-modules-js/settings.json @@ -39,13 +39,6 @@ }, "bootstrap": { "name": "bootstrap", - "js": { - "dist/js/bootstrap.js": "js/bootstrap.js", - "dist/js/bootstrap.min.js": "js/bootstrap.min.js", - "dist/js/bootstrap.bundle.js": "js/bootstrap.bundle.js", - "dist/js/bootstrap.bundle.min.js": "js/bootstrap.bundle.min.js", - "dist/js/bootstrap.bundle.min.js.map": "js/bootstrap.bundle.min.js.map" - }, "css": { "dist/css/bootstrap.css": "css/bootstrap.css", "dist/css/bootstrap.min.css": "css/bootstrap.min.css", @@ -76,22 +69,6 @@ "dependencies": [ "bootstrap.css" ] - }, - { - "name": "bootstrap.js", - "type": "script", - "uri": "bootstrap.min.js", - "dependencies": [ - "jquery" - ] - }, - { - "name": "bootstrap.js.bundle", - "type": "script", - "uri": "bootstrap.bundle.min.js", - "dependencies": [ - "jquery" - ] } ], "dependencies": [], diff --git a/build/media_source/com_joomlaupdate/joomla.asset.json b/build/media_source/com_joomlaupdate/joomla.asset.json index 0f3f6d679889a..73ee972cc431f 100644 --- a/build/media_source/com_joomlaupdate/joomla.asset.json +++ b/build/media_source/com_joomlaupdate/joomla.asset.json @@ -10,7 +10,8 @@ "type": "script", "uri": "com_joomlaupdate/admin-update-default.min.js", "dependencies": [ - "core" + "core", + "jquery" ], "attributes": { "defer": true @@ -21,7 +22,8 @@ "type": "script", "uri": "com_joomlaupdate/default.min.js", "dependencies": [ - "core" + "core", + "jquery" ], "attributes": { "defer": true diff --git a/build/media_source/com_workflow/js/admin-items-workflow-buttons.es6.js b/build/media_source/com_workflow/js/admin-items-workflow-buttons.es6.js index d8ed9104948a5..b5bf3af1c168f 100644 --- a/build/media_source/com_workflow/js/admin-items-workflow-buttons.es6.js +++ b/build/media_source/com_workflow/js/admin-items-workflow-buttons.es6.js @@ -38,7 +38,7 @@ Joomla.toggleAllNextElements = (element, className) => { 'use strict'; document.addEventListener('DOMContentLoaded', () => { - const dropDownBtn = document.getElementById('toolbar-dropdown-status-group'); + const dropDownBtn = document.getElementById('toolbar-status-group'); const transitions = [].slice.call(dropDownBtn.querySelectorAll('.button-transition')); const headline = dropDownBtn.querySelector('.button-transition-headline'); const separator = dropDownBtn.querySelector('.button-transition-separator'); diff --git a/build/media_source/legacy/js/bootstrap-init.es5.js b/build/media_source/legacy/js/bootstrap-init.es5.js deleted file mode 100644 index fcddb5a673e9e..0000000000000 --- a/build/media_source/legacy/js/bootstrap-init.es5.js +++ /dev/null @@ -1,219 +0,0 @@ -Joomla = window.Joomla || {}; - -(function(Joomla) { - "use strict"; - - /** - * Method to invoke a click on button inside an iframe - * - * @param {object} options Object with the css selector for the parent element of an iframe - * and the selector of the button in the iframe that will be clicked - * { iframeSelector: '', buttonSelector: '' } - * @returns {boolean} - * - * @since 4.0 - */ - Joomla.iframeButtonClick = function(options) { - if (!options.iframeSelector || !options.buttonSelector) { - throw new Error('Selector is missing'); - } - - var iframe = document.querySelector(options.iframeSelector + ' iframe'); - if (iframe) { - var button = iframe.contentWindow.document.querySelector(options.buttonSelector); - if (button) { - button.click(); - } - } - }; - - jQuery(document).ready(function($) { - Joomla.Bootstrap = {}; - - // Initialize some variables - var accordion = Joomla.getOptions('bootstrap.accordion'), - alert = Joomla.getOptions('bootstrap.alert'), - button = Joomla.getOptions('bootstrap.button'), - carousel = Joomla.getOptions('bootstrap.carousel'), - dropdown = Joomla.getOptions('bootstrap.dropdown'), - modals = [].slice.call(document.querySelectorAll('.joomla-modal')), - popover = Joomla.getOptions('bootstrap.popover'), - scrollspy = Joomla.getOptions('bootstrap.scrollspy'), - tabs = Joomla.getOptions('bootstrap.tabs'), - tooltip = Joomla.getOptions('bootstrap.tooltip'); - - Joomla.Bootstrap.initModal = function(element) { - var $self = $(element); - - // Comply with the Joomla API - // Bound element.open() - if (element) { - element.open = function () { - return $self.modal('show'); - }; - - // Bound element.close() - element.close = function () { - return $self.modal('hide'); - }; - } - - $self.on('show.bs.modal', function() { - // Comply with the Joomla API - // Set the current Modal ID - Joomla.Modal.setCurrent(element); - - // @TODO throw the standard Joomla event - if ($self.data('url')) { - var modalBody = $self.find('.modal-body'); - var el; - modalBody.find('iframe').remove(); - - // Hacks because com_associations and field modals use pure javascript in the url! - if ($self.data('iframe').indexOf("document.getElementById") > 0){ - var iframeTextArr = $self.data('iframe').split('+'); - var idFieldArr = iframeTextArr[1].split('"'); - - idFieldArr[0] = idFieldArr[0].replace(/"/g,'"'); - - if (!document.getElementById(idFieldArr[1])) { - el = eval(idFieldArr[0]); - } else { - el = document.getElementById(idFieldArr[1]).value; - } - - var data_iframe = iframeTextArr[0] + el + iframeTextArr[2]; - modalBody.prepend(data_iframe); - } else { - modalBody.prepend($self.data('iframe')); - } - } - }).on('shown.bs.modal', function() { - var modalHeight = $('div.modal:visible').outerHeight(true), - modalHeaderHeight = $('div.modal-header:visible').outerHeight(true), - modalBodyHeightOuter = $('div.modal-body:visible').outerHeight(true), - modalBodyHeight = $('div.modal-body:visible').height(), - modalFooterHeight = $('div.modal-footer:visible').outerHeight(true), - padding = $self.offsetTop, - maxModalHeight = ($(window).height()-(padding*2)), - modalBodyPadding = (modalBodyHeightOuter-modalBodyHeight), - maxModalBodyHeight = maxModalHeight-(modalHeaderHeight+modalFooterHeight+modalBodyPadding); - if ($self.data('url')) { - var iframeHeight = $('.iframe').height(); - if (iframeHeight > maxModalBodyHeight){ - $('.modal-body').css({'max-height': maxModalBodyHeight, 'overflow-y': 'auto'}); - $('.iframe').css('max-height', maxModalBodyHeight-modalBodyPadding); - } - } - // @TODO throw the standard Joomla event - }).on('hide.bs.modal', function() { - $('.modal-body').css({'max-height': 'initial'}); - $('.modalTooltip').tooltip('dispose'); - // @TODO throw the standard Joomla event - }).on('hidden.bs.modal', function() { - // Comply with the Joomla API - // Remove the current Modal ID - Joomla.Modal.setCurrent(''); - // @TODO throw the standard Joomla event - }); - }; - - /** Accordion **/ - if (accordion) { - $.each(accordion, function(index, value) { - $('#' + index).collapse( - { - parent:value.parent, - toggle:value.toggle - } - ).on("show", new Function(value.onShow)()) - .on("shown", new Function(value.onShown)()) - .on("hideme", new Function(value.onHide)()) - .on("hidden", new Function(value.onHidden)()); - }); - } - - /** Alert **/ - if (alert) { - $.each(alert, function(index, value) { - $('#' + index).alert(); - }); - } - - /** Button **/ - if (button) { - $.each(button, function(index, value) { - $('#' + index).button(); - }); - } - - /** Carousel **/ - if (carousel) { - $.each(carousel, function(index, value) { - $('#' + index).carousel( - { - interval: value.interval ? value.interval : 5000, - pause: value.pause ? value.pause : 'hover' - } - ); - }); - } - - /** Dropdown menu **/ - if (dropdown) { - $.each(dropdown, function(index, value) { - $('#' + index).dropdown(); - }); - } - - /** Modals **/ - if (modals.length) { - modals.forEach(function(modal){ Joomla.Bootstrap.initModal(modal); }); - } - - /** Popover **/ - if (popover) { - $.each(popover, function(index, value) { - value.constraints = [value.constraints]; - $(index).popover(value); - }); - } - - /** Scrollspy **/ - if (scrollspy) { - $.each(scrollspy, function(index, value) { - $('#' + index).scrollspy(value); - }); - } - - /** Tabs **/ - if (tabs) { - $.each(tabs, function(index, value) { - - $.each($('#' + index + 'Content').children('.tab-pane'), function(i, v) { - var titleAttribute = $(v).data('title'); - var activeAttribute = $(v).data('active'); - var idAttribute = $(v).data('id'); - - if (titleAttribute) { - var classLink = (activeAttribute != '') ? 'class="nav-link ' + activeAttribute + '"' : 'class="nav-link"'; - - $('#' + index + 'Tabs').append(''); - } - }); - }); - } - - /** Tooltip **/ - if (tooltip) { - $.each(tooltip, function(index, value) { - value.constraints = [value.constraints]; - $(index).tooltip(value) - .on("show.bs.tooltip", new Function(value.onShow)()) - .on("shown.bs.tooltip", new Function(value.onShown)()) - .on("hide.bs.tooltip", new Function(value.onHide)()) - .on("hidden.bs.tooltip", new Function(value.onHidden)()); - }); - } - }); -})(Joomla); diff --git a/build/media_source/mod_multilangstatus/js/admin-multilangstatus.es6.js b/build/media_source/mod_multilangstatus/js/admin-multilangstatus.es6.js index fe6a8f5704619..6ed4c77f5a18b 100644 --- a/build/media_source/mod_multilangstatus/js/admin-multilangstatus.es6.js +++ b/build/media_source/mod_multilangstatus/js/admin-multilangstatus.es6.js @@ -19,6 +19,9 @@ // Append clone before closing body tag document.body.appendChild(clone); + + // Modal was moved so it needs to be re initialised + Joomla.Bootstrap.Initialise.Modal(clone); } }); })(); diff --git a/build/media_source/system/js/fields/joomla-field-media.w-c.es6.js b/build/media_source/system/js/fields/joomla-field-media.w-c.es6.js index ddef064859ad8..0bd84616a5663 100644 --- a/build/media_source/system/js/fields/joomla-field-media.w-c.es6.js +++ b/build/media_source/system/js/fields/joomla-field-media.w-c.es6.js @@ -102,7 +102,7 @@ && Joomla.Bootstrap.Instances && Joomla.Bootstrap.Instances.Modal && Joomla.Bootstrap.Instances.Modal.get(this.modalElement) === undefined) { - Joomla.Bootstrap.Methods.initModal(this.modalElement); + Joomla.Bootstrap.Initialise.Modal(this.modalElement, { isJoomla: true }); } if (this.buttonClearEl) { diff --git a/build/media_source/system/js/fields/joomla-field-user.w-c.es6.js b/build/media_source/system/js/fields/joomla-field-user.w-c.es6.js index 491dcf6f3156c..4716b1895cd2f 100644 --- a/build/media_source/system/js/fields/joomla-field-user.w-c.es6.js +++ b/build/media_source/system/js/fields/joomla-field-user.w-c.es6.js @@ -59,7 +59,7 @@ && Joomla.Bootstrap.Instances && Joomla.Bootstrap.Instances.Modal && Joomla.Bootstrap.Instances.Modal.get(this.modal) === undefined) { - Joomla.Bootstrap.Methods.initModal(this.modal); + Joomla.Bootstrap.Initialise.Modal(this.modal, { isJoomla: true }); } if (this.buttonSelect) { diff --git a/build/media_source/vendor/bootstrap/js/alert.es6.js b/build/media_source/vendor/bootstrap/js/alert.es6.js new file mode 100644 index 0000000000000..c677fd9024bd6 --- /dev/null +++ b/build/media_source/vendor/bootstrap/js/alert.es6.js @@ -0,0 +1,39 @@ +import Alert from '../../../../../node_modules/bootstrap/js/src/alert'; + +Joomla = Joomla || {}; +Joomla.Bootstrap = Joomla.Bootstrap || {}; +Joomla.Bootstrap.Initialise = Joomla.Bootstrap.Initialise || {}; +Joomla.Bootstrap.Instances = Joomla.Bootstrap.Instances || {}; +Joomla.Bootstrap.Instances.Alert = new WeakMap(); + +/** + * Initialise the Alert iteractivity + * + * @param {HTMLElement} el The element that will become an Alert + */ +Joomla.Bootstrap.Initialise.Alert = (el) => { + if (!(el instanceof Element)) { + return; + } + if (Joomla.Bootstrap.Instances.Alert.get(el) && el.dispose) { + el.dispose(); + } + Joomla.Bootstrap.Instances.Alert.set(el, new Alert(el)); +}; + +// Ensure vanilla mode, for consistency of the events +if (!Object.prototype.hasOwnProperty.call(document.body.dataset, 'bsNoJquery')) { + document.body.dataset.bsNoJquery = ''; +} + +// Get the elements/configurations from the PHP +const alerts = Joomla.getOptions('bootstrap.alert'); +// Initialise the elements +if (alerts && alerts.length) { + alerts.forEach((selector) => { + Array.from(document.querySelectorAll(selector)) + .map((el) => Joomla.Bootstrap.Initialise.Alert(el)); + }); +} + +export default Alert; diff --git a/build/media_source/vendor/bootstrap/js/button.es6.js b/build/media_source/vendor/bootstrap/js/button.es6.js new file mode 100644 index 0000000000000..2384f2af28748 --- /dev/null +++ b/build/media_source/vendor/bootstrap/js/button.es6.js @@ -0,0 +1,39 @@ +import Button from '../../../../../node_modules/bootstrap/js/src/button'; + +Joomla = Joomla || {}; +Joomla.Bootstrap = Joomla.Bootstrap || {}; +Joomla.Bootstrap.Initialise = Joomla.Bootstrap.Initialise || {}; +Joomla.Bootstrap.Instances = Joomla.Bootstrap.Instances || {}; +Joomla.Bootstrap.Instances.Button = new WeakMap(); + +/** + * Initialise the Button iteractivity + * + * @param {HTMLElement} el The element that will become an Button + */ +Joomla.Bootstrap.Initialise.Button = (el) => { + if (!(el instanceof Element)) { + return; + } + if (Joomla.Bootstrap.Instances.Button.get(el) && el.dispose) { + el.dispose(); + } + Joomla.Bootstrap.Instances.Button.set(el, new Button(el)); +}; + +// Ensure vanilla mode, for consistency of the events +if (!Object.prototype.hasOwnProperty.call(document.body.dataset, 'bsNoJquery')) { + document.body.dataset.bsNoJquery = ''; +} + +// Get the elements/configurations from the PHP +const buttons = Joomla.getOptions('bootstrap.button'); +// Initialise the elements +if (buttons && buttons.length) { + buttons.forEach((selector) => { + Array.from(document.querySelectorAll(selector)) + .map((el) => Joomla.Bootstrap.Initialise.Button(el)); + }); +} + +export default Button; diff --git a/build/media_source/vendor/bootstrap/js/carousel.es6.js b/build/media_source/vendor/bootstrap/js/carousel.es6.js new file mode 100644 index 0000000000000..6392fd1a0ba8e --- /dev/null +++ b/build/media_source/vendor/bootstrap/js/carousel.es6.js @@ -0,0 +1,52 @@ +import Carousel from '../../../../../node_modules/bootstrap/js/src/carousel'; + +Joomla = Joomla || {}; +Joomla.Bootstrap = Joomla.Bootstrap || {}; +Joomla.Bootstrap.Initialise = Joomla.Bootstrap.Initialise || {}; +Joomla.Bootstrap.Instances = Joomla.Bootstrap.Instances || {}; +Joomla.Bootstrap.Instances.Carousel = new WeakMap(); + +/** + * Initialise the Carousel iteractivity + * + * @param {HTMLElement} el The element that will become an Carousel + * @param {object} options The options for this carousel + */ +Joomla.Bootstrap.Initialise.Carousel = (el, options) => { + if (!(el instanceof Element)) { + return; + } + if (Joomla.Bootstrap.Instances.Carousel.get(el) && el.dispose) { + el.dispose(); + } + Joomla.Bootstrap.Instances.Carousel.set(el, new Carousel(el, options)); +}; + +// Get the elements/configurations from the PHP +const carousels = Joomla.getOptions('bootstrap.carousel'); + +// Force Vanilla mode! +if (!Object.prototype.hasOwnProperty.call(document.body.dataset, 'bsNoJquery')) { + document.body.dataset.bsNoJquery = ''; +} +// Initialise the elements +if (typeof carousels === 'object' && carousels !== null) { + Object.keys(carousels).forEach((carousel) => { + const opt = carousels[carousel]; + const options = { + interval: opt.interval ? opt.interval : 5000, + keyboard: opt.keyboard ? opt.keyboard : true, + pause: opt.pause ? opt.pause : 'hover', + slide: opt.slide ? opt.slide : false, + wrap: opt.wrap ? opt.wrap : true, + touch: opt.touch ? opt.touch : true, + }; + + const elements = Array.from(document.querySelectorAll(carousel)); + if (elements.length) { + elements.map((el) => Joomla.Bootstrap.Initialise.Carousel(el, options)); + } + }); +} + +export default Carousel; diff --git a/build/media_source/vendor/bootstrap/js/collapse.es6.js b/build/media_source/vendor/bootstrap/js/collapse.es6.js new file mode 100644 index 0000000000000..567c999821f57 --- /dev/null +++ b/build/media_source/vendor/bootstrap/js/collapse.es6.js @@ -0,0 +1,51 @@ +import Collapse from '../../../../../node_modules/bootstrap/js/src/collapse'; + +Joomla = Joomla || {}; +Joomla.Bootstrap = Joomla.Bootstrap || {}; +Joomla.Bootstrap.Initialise = Joomla.Bootstrap.Initialise || {}; +Joomla.Bootstrap.Instances = Joomla.Bootstrap.Instances || {}; +Joomla.Bootstrap.Instances.Collapse = new WeakMap(); + +/** + * Initialise the Collapse iteractivity + * + * @param {HTMLElement} el The element that will become an collapse + * @param {object} options The options for this collapse + */ +Joomla.Bootstrap.Initialise.Collapse = (el, options) => { + if (!(el instanceof Element)) { + return; + } + if (Joomla.Bootstrap.Instances.Collapse.get(el) && el.dispose) { + el.dispose(); + } + Joomla.Bootstrap.Instances.Collapse.set(el, new Collapse(el, options)); +}; + +// Ensure vanilla mode, for consistency of the events +if (!Object.prototype.hasOwnProperty.call(document.body.dataset, 'bsNoJquery')) { + document.body.dataset.bsNoJquery = ''; +} + +// Get the elements/configurations from the PHP +const collapses = { ...Joomla.getOptions('bootstrap.collapse'), ...Joomla.getOptions('bootstrap.accordion') }; +// Initialise the elements +if (typeof collapses === 'object' && collapses !== null) { + Object.keys(collapses).forEach((collapse) => { + const opt = collapses[collapse]; + const options = { + toggle: opt.toggle ? opt.toggle : true, + }; + + if (opt.parent) { + options.parent = opt.parent; + } + + const elements = Array.from(document.querySelectorAll(collapse)); + if (elements.length) { + elements.map((el) => Joomla.Bootstrap.Initialise.Collapse(el, options)); + } + }); +} + +export default Collapse; diff --git a/build/media_source/vendor/bootstrap/js/dropdown.es6.js b/build/media_source/vendor/bootstrap/js/dropdown.es6.js new file mode 100644 index 0000000000000..8cba264334d30 --- /dev/null +++ b/build/media_source/vendor/bootstrap/js/dropdown.es6.js @@ -0,0 +1,48 @@ +import Dropdown from '../../../../../node_modules/bootstrap/js/src/dropdown'; + +Joomla = Joomla || {}; +Joomla.Bootstrap = Joomla.Bootstrap || {}; +Joomla.Bootstrap.Initialise = Joomla.Bootstrap.Initialise || {}; +Joomla.Bootstrap.Instances = Joomla.Bootstrap.Instances || {}; +Joomla.Bootstrap.Instances.Dropdown = new WeakMap(); + +/** + * Initialise the iteractivity + * + * @param {HTMLElement} el The element that will become an dropdown + * @param {object} options The options for this dropdown + */ +Joomla.Bootstrap.Initialise.Dropdown = (el, options) => { + if (!(el instanceof Element)) { + return; + } + if (Joomla.Bootstrap.Instances.Dropdown.get(el) && el.dispose) { + el.dispose(); + } + Joomla.Bootstrap.Instances.Dropdown.set(el, new Dropdown(el, options)); +}; + +// Ensure vanilla mode, for consistency of the events +if (!Object.prototype.hasOwnProperty.call(document.body.dataset, 'bsNoJquery')) { + document.body.dataset.bsNoJquery = ''; +} + +// Get the elements/configurations from the PHP +const dropdowns = Joomla.getOptions('bootstrap.dropdown'); +// Initialise the elements +if (typeof dropdowns === 'object' && dropdowns !== null) { + Object.keys(dropdowns).forEach((dropdown) => { + const opt = dropdowns[dropdown]; + const options = { + interval: opt.interval ? opt.interval : 5000, + pause: opt.pause ? opt.pause : 'hover', + }; + + const elements = Array.from(document.querySelectorAll(dropdown)); + if (elements.length) { + elements.map((el) => Joomla.Bootstrap.Initialise.Dropdown(el, options)); + } + }); +} + +export default Dropdown; diff --git a/build/media_source/vendor/bootstrap/js/index.es6.js b/build/media_source/vendor/bootstrap/js/index.es6.js new file mode 100644 index 0000000000000..9585ae01838ae --- /dev/null +++ b/build/media_source/vendor/bootstrap/js/index.es6.js @@ -0,0 +1,23 @@ +import Alert from './alert.es6'; +import Button from './button.es6'; +import Collapse from './collapse.es6'; +import Carousel from './carousel.es6'; +import Dropdown from './dropdown.es6'; +import Modal from './modal.es6'; +import { Popover } from './popover.es6'; +import Scrollspy from './scrollspy.es6'; +import Tab from './tab.es6'; +import Toast from './toast.es6'; + +export { + Alert, + Button, + Collapse, + Carousel, + Dropdown, + Modal, + Popover, + Scrollspy, + Tab, + Toast, +}; diff --git a/build/media_source/vendor/bootstrap/js/modal.es6.js b/build/media_source/vendor/bootstrap/js/modal.es6.js new file mode 100644 index 0000000000000..b8da50cc82ac8 --- /dev/null +++ b/build/media_source/vendor/bootstrap/js/modal.es6.js @@ -0,0 +1,162 @@ +import Modal from '../../../../../node_modules/bootstrap/js/src/modal'; + +Joomla = Joomla || {}; +Joomla.Bootstrap = Joomla.Bootstrap || {}; +Joomla.Bootstrap.Initialise = Joomla.Bootstrap.Initialise || {}; +Joomla.Bootstrap.Instances = Joomla.Bootstrap.Instances || {}; +Joomla.Bootstrap.Instances.Modal = new WeakMap(); + +Joomla.Bootstrap.Initialise.Modal = (modal, options) => { + if (!(modal instanceof Element)) { + return; + } + if (Joomla.Bootstrap.Instances.Modal.get(modal) && modal.dispose) { + modal.dispose(); + } + Joomla.Bootstrap.Instances.Modal.set(modal, new Modal(modal, options)); + + // Comply with the Joomla API - Bound element.open/close + modal.open = () => { Joomla.Bootstrap.Instances.Modal.get(modal).show(modal); }; + modal.close = () => { Joomla.Bootstrap.Instances.Modal.get(modal).hide(); }; + + // Do some Joomla specific changes + modal.addEventListener('show.bs.modal', () => { + // Comply with the Joomla API - Set the current Modal ID + Joomla.Modal.setCurrent(modal); + + if (modal.dataset.url) { + const modalBody = modal.querySelector('.modal-body'); + const iframe = modalBody.querySelector('iframe'); + + if (iframe) { + const addData = modal.querySelector('joomla-field-mediamore'); + + if (addData) { + addData.parentNode.removeChild(addData); + } + + iframe.parentNode.removeChild(iframe); + } + + // @todo merge https://github.com/joomla/joomla-cms/pull/20788 + // Hacks because com_associations and field modals use pure javascript in the url! + if (modal.dataset.iframe.indexOf('document.getElementById') > 0) { + const iframeTextArr = modal.dataset.iframe.split('+'); + const idFieldArr = iframeTextArr[1].split('"'); + let el; + + idFieldArr[0] = idFieldArr[0].replace(/"/g, '"'); + + if (!document.getElementById(idFieldArr[1])) { + // eslint-disable-next-line no-new-func + el = new Function(idFieldArr[0]); // This is UNSAFE!!!! + } else { + el = document.getElementById(idFieldArr[1]).value; + } + + modalBody.insertAdjacentHTML('afterbegin', `${iframeTextArr[0]}${el}${iframeTextArr[2]}`); + } else { + modalBody.insertAdjacentHTML('afterbegin', modal.dataset.iframe); + } + } + }); + + modal.addEventListener('shown.bs.modal', () => { + const modalBody = modal.querySelector('.modal-body'); + const modalHeader = modal.querySelector('.modal-header'); + const modalFooter = modal.querySelector('.modal-footer'); + let modalHeaderHeight = 0; + let modalFooterHeight = 0; + let maxModalBodyHeight = 0; + let modalBodyPadding = 0; + let modalBodyHeightOuter = 0; + + if (modalBody) { + if (modalHeader) { + const modalHeaderRects = modalHeader.getBoundingClientRect(); + modalHeaderHeight = modalHeaderRects.height; + modalBodyHeightOuter = modalBody.offsetHeight; + } + if (modalFooter) { + modalFooterHeight = parseFloat(getComputedStyle(modalFooter, null).height.replace('px', '')); + } + + const modalBodyHeight = parseFloat(getComputedStyle(modalBody, null).height.replace('px', '')); + const padding = modalBody.offsetTop; + const maxModalHeight = parseFloat(getComputedStyle(document.body, null).height.replace('px', '')) - (padding * 2); + modalBodyPadding = modalBodyHeightOuter - modalBodyHeight; + // eslint-disable-next-line max-len + maxModalBodyHeight = maxModalHeight - (modalHeaderHeight + modalFooterHeight + modalBodyPadding); + } + + if (modal.dataset.url) { + const iframeEl = modal.querySelector('iframe'); + const iframeHeight = parseFloat(getComputedStyle(iframeEl, null).height.replace('px', '')); + if (iframeHeight > maxModalBodyHeight) { + modalBody.style.maxHeight = maxModalBodyHeight; + modalBody.style.overflowY = 'auto'; + iframeEl.style.maxHeight = maxModalBodyHeight - modalBodyPadding; + } + } + }); + + modal.addEventListener('hide.bs.modal', () => { + const modalBody = modal.querySelector('.modal-body'); + modalBody.style.maxHeight = 'initial'; + }); + + modal.addEventListener('hidden.bs.modal', () => { + // Comply with the Joomla API - Remove the current Modal ID + Joomla.Modal.setCurrent(''); + }); +}; + +/** + * Method to invoke a click on button inside an iframe + * + * @param {object} options Object with the css selector for the parent element of an iframe + * and the selector of the button in the iframe that will be clicked + * { iframeSelector: '', buttonSelector: '' } + * @returns {boolean} + * + * @since 4.0 + */ +Joomla.iframeButtonClick = (options) => { + if (!options.iframeSelector || !options.buttonSelector) { + throw new Error('Selector is missing'); + } + + const iframe = document.querySelector(`${options.iframeSelector} iframe`); + if (iframe) { + const button = iframe.contentWindow.document.querySelector(options.buttonSelector); + if (button) { + button.click(); + } + } +}; + +// Ensure vanilla mode, for consistency of the events +if (!Object.prototype.hasOwnProperty.call(document.body.dataset, 'bsNoJquery')) { + document.body.dataset.bsNoJquery = ''; +} + +// Get the elements/configurations from the PHP +const modals = Joomla.getOptions('bootstrap.modal'); +// Initialise the elements +if (typeof modals === 'object' && modals !== null) { + Object.keys(modals).forEach((modal) => { + const modalEl = document.querySelector(modal); + const opt = modals[modal]; + const options = { + backdrop: opt.backdrop ? opt.backdrop : true, + keyboard: opt.keyboard ? opt.keyboard : true, + focus: opt.focus ? opt.focus : true, + }; + + if (modalEl) { + Joomla.Bootstrap.Initialise.Modal(modalEl, options); + } + }); +} + +export default Modal; diff --git a/build/media_source/vendor/bootstrap/js/popover.es6.js b/build/media_source/vendor/bootstrap/js/popover.es6.js new file mode 100644 index 0000000000000..e47c49150d9c8 --- /dev/null +++ b/build/media_source/vendor/bootstrap/js/popover.es6.js @@ -0,0 +1,121 @@ +import Popover from '../../../../../node_modules/bootstrap/js/src/popover'; +import Tooltip from '../../../../../node_modules/bootstrap/js/src/tooltip'; + +Joomla = Joomla || {}; +Joomla.Bootstrap = Joomla.Bootstrap || {}; +Joomla.Bootstrap.Initialise = Joomla.Bootstrap.Initialise || {}; +Joomla.Bootstrap.Instances = Joomla.Bootstrap.Instances || {}; +Joomla.Bootstrap.Instances.Popover = new WeakMap(); +Joomla.Bootstrap.Instances.Tooltip = new WeakMap(); + +/** + * Initialise the Popover iteractivity + * + * @param {HTMLElement} el The element that will become an popover + * @param {object} options The options for this popover + */ +Joomla.Bootstrap.Initialise.Popover = (el, options) => { + if (!(el instanceof Element)) { + return; + } + if (Joomla.Bootstrap.Instances.Popover.get(el) && el.dispose) { + el.dispose(); + } + Joomla.Bootstrap.Instances.Popover.set(el, new Popover(el, options)); +}; + +/** + * Initialise the Tooltip iteractivity + * + * @param {HTMLElement} el The element that will become an tooltip + * @param {object} options The options for this tooltip + */ +Joomla.Bootstrap.Initialise.Tooltip = (el, options) => { + if (Joomla.Bootstrap.Instances.Tooltip.get(el) && el.dispose) { + el.dispose(); + } + Joomla.Bootstrap.Instances.Tooltip.set(el, new Tooltip(el, options)); +}; + +// Ensure vanilla mode, for consistency of the events +if (!Object.prototype.hasOwnProperty.call(document.body.dataset, 'bsNoJquery')) { + document.body.dataset.bsNoJquery = ''; +} + +// Get the elements/configurations from the PHP +const tooltips = Joomla.getOptions('bootstrap.tooltip'); +const popovers = Joomla.getOptions('bootstrap.popover'); +// Initialise the elements +if (typeof popovers === 'object' && popovers !== null) { + Object.keys(popovers).forEach((popover) => { + const opt = popovers[popover]; + const options = { + animation: opt.animation ? opt.animation : true, + container: opt.container ? opt.container : false, + content: opt.content ? opt.content : '', + delay: opt.delay ? opt.delay : 0, + html: opt.html ? opt.html : false, + placement: opt.placement ? opt.placement : 'top', + selector: opt.selector ? opt.selector : false, + title: opt.title ? opt.title : '', + trigger: opt.trigger ? opt.trigger : 'click', + offset: opt.offset ? opt.offset : 0, + fallbackPlacement: opt.fallbackPlacement ? opt.fallbackPlacement : 'flip', + boundary: opt.boundary ? opt.boundary : 'scrollParent', + customClass: opt.customClass ? opt.customClass : '', + sanitize: opt.sanitize ? opt.sanitize : true, + sanitizeFn: opt.sanitizeFn ? opt.sanitizeFn : null, + popperConfig: opt.popperConfig ? opt.popperConfig : null, + }; + + if (opt.template) { + options.template = opt.template; + } + if (opt.allowList) { + options.allowList = opt.allowList; + } + + const elements = Array.from(document.querySelectorAll(popover)); + if (elements.length) { + elements.map((el) => Joomla.Bootstrap.Initialise.Popover(el, options)); + } + }); +} +// Initialise the elements +if (typeof tooltips === 'object' && tooltips !== null) { + Object.keys(tooltips).forEach((tooltip) => { + const opt = tooltips[tooltip]; + const options = { + animation: opt.animation ? opt.animation : true, + container: opt.container ? opt.container : false, + delay: opt.delay ? opt.delay : 0, + html: opt.html ? opt.html : false, + selector: opt.selector ? opt.selector : false, + trigger: opt.trigger ? opt.trigger : 'hover focus', + fallbackPlacement: opt.fallbackPlacement ? opt.fallbackPlacement : null, + boundary: opt.boundary ? opt.boundary : 'clippingParents', + title: opt.title ? opt.title : '', + customClass: opt.customClass ? opt.customClass : '', + sanitize: opt.sanitize ? opt.sanitize : true, + sanitizeFn: opt.sanitizeFn ? opt.sanitizeFn : null, + popperConfig: opt.popperConfig ? opt.popperConfig : null, + }; + + if (opt.placement) { + options.placement = opt.placement; + } + if (opt.template) { + options.template = opt.template; + } + if (opt.allowList) { + options.allowList = opt.allowList; + } + + const elements = Array.from(document.querySelectorAll(tooltip)); + if (elements.length) { + elements.map((el) => Joomla.Bootstrap.Initialise.Tooltip(el, options)); + } + }); +} + +export { Tooltip, Popover }; diff --git a/build/media_source/vendor/bootstrap/js/scrollspy.es6.js b/build/media_source/vendor/bootstrap/js/scrollspy.es6.js new file mode 100644 index 0000000000000..db650453ce118 --- /dev/null +++ b/build/media_source/vendor/bootstrap/js/scrollspy.es6.js @@ -0,0 +1,52 @@ +import Scrollspy from '../../../../../node_modules/bootstrap/js/src/scrollspy'; + +Joomla = Joomla || {}; +Joomla.Bootstrap = Joomla.Bootstrap || {}; +Joomla.Bootstrap.Initialise = Joomla.Bootstrap.Initialise || {}; +Joomla.Bootstrap.Instances = Joomla.Bootstrap.Instances || {}; +Joomla.Bootstrap.Instances.Scrollspy = new WeakMap(); + +/** + * Initialise the Scrollspy iteractivity + * + * @param {HTMLElement} el The element that will become a scrollspy + * @param {object} options The options for this scrollspy + */ +Joomla.Bootstrap.Initialise.Scrollspy = (el, options) => { + if (!(el instanceof Element)) { + return; + } + if (Joomla.Bootstrap.Instances.Scrollspy.get(el) && el.dispose) { + el.dispose(); + } + Joomla.Bootstrap.Instances.Scrollspy.set(el, new Scrollspy(el, options)); +}; + +// Ensure vanilla mode, for consistency of the events +if (!Object.prototype.hasOwnProperty.call(document.body.dataset, 'bsNoJquery')) { + document.body.dataset.bsNoJquery = ''; +} + +// Get the elements/configurations from the PHP +const scrollspys = Joomla.getOptions('bootstrap.scrollspy'); +// Initialise the elements +if (typeof scrollspys === 'object' && scrollspys !== null) { + Object.keys(scrollspys).forEach((scrollspy) => { + const opt = scrollspys[scrollspy]; + const options = { + offset: opt.offset ? opt.offset : 10, + method: opt.method ? opt.method : 'auto', + }; + + if (opt.target) { + options.target = opt.target; + } + + const elements = Array.from(document.querySelectorAll(scrollspy)); + if (elements.length) { + elements.map((el) => Joomla.Bootstrap.Initialise.Scrollspy(el, options)); + } + }); +} + +export default Scrollspy; diff --git a/build/media_source/vendor/bootstrap/js/tab.es6.js b/build/media_source/vendor/bootstrap/js/tab.es6.js new file mode 100644 index 0000000000000..9293cb9df1d34 --- /dev/null +++ b/build/media_source/vendor/bootstrap/js/tab.es6.js @@ -0,0 +1,96 @@ +import Tab from '../../../../../node_modules/bootstrap/js/src/tab'; + +Joomla = Joomla || {}; +Joomla.Bootstrap = Joomla.Bootstrap || {}; +Joomla.Bootstrap.Initialise = Joomla.Bootstrap.Initialise || {}; +Joomla.Bootstrap.Instances = Joomla.Bootstrap.Instances || {}; +Joomla.Bootstrap.Instances.Tab = new WeakMap(); + +/** + * Initialise the Tabs interactivity + * + * @param {HTMLElement} el The element that will become an collapse + * @param {object} options The options for this collapse + */ +Joomla.Bootstrap.Initialise.Tab = (el, options) => { + if (!(el instanceof Element) && options.isJoomla) { + const nSelector = el.split('.')[1]; + if (!nSelector) { + throw new Error('The selector is invalid, check your PHP side'); + } + const tab = document.querySelector(`#${nSelector}Content`); + if (tab) { + const related = Array.from(tab.children); + + // Build the navigation + if (related.length) { + related.forEach((element) => { + if (!element.classList.contains('tab-pane')) { + return; + } + + const isActive = element.dataset.active !== ''; + const ul = document.querySelector(`#${nSelector}Tabs`); + + if (ul) { + const link = document.createElement('a'); + link.href = `#${element.dataset.id}`; + link.classList.add('nav-link'); + if (isActive) { + link.classList.add('active'); + } + + link.dataset.bsToggle = 'tab'; + link.setAttribute('role', 'tab'); + link.setAttribute('aria-controls', element.dataset.id); + link.setAttribute('aria-selected', element.dataset.id); + + /** + * As we are re-rendering text already displayed on the page we judge that there isn't + * a risk of XSS attacks + */ + link.innerHTML = element.dataset.title; + + const li = document.createElement('li'); + li.classList.add('nav-item'); + li.setAttribute('role', 'presentation'); + li.appendChild(link); + + ul.appendChild(li); + } + }); + } + + if (Joomla.Bootstrap.Instances.Tab.get(tab) && tab.dispose) { + tab.dispose(); + } + + Joomla.Bootstrap.Instances.Tab.set(tab, new Tab(tab)); + } + } else { + if (!(el instanceof Element)) { + return; + } + if (Joomla.Bootstrap.Instances.Tab.get(el) && el.dispose) { + el.dispose(); + } + + Joomla.Bootstrap.Instances.Tab.set(el, new Tab(el, options)); + } +}; + +// Ensure vanilla mode, for consistency of the events +if (!Object.prototype.hasOwnProperty.call(document.body.dataset, 'bsNoJquery')) { + document.body.dataset.bsNoJquery = ''; +} + +// Get the elements/configurations from the PHP +const tabs = Joomla.getOptions('bootstrap.tabs'); +// Initialise the elements +if (typeof tabs === 'object' && tabs !== null) { + Object.keys(tabs).forEach((tab) => { + Joomla.Bootstrap.Initialise.Tab(tab, tabs[tab]); + }); +} + +export default Tab; diff --git a/build/media_source/vendor/bootstrap/js/toast.es6.js b/build/media_source/vendor/bootstrap/js/toast.es6.js new file mode 100644 index 0000000000000..4bc561ae8a9e0 --- /dev/null +++ b/build/media_source/vendor/bootstrap/js/toast.es6.js @@ -0,0 +1,49 @@ +import Toast from '../../../../../node_modules/bootstrap/js/src/toast'; + +Joomla = Joomla || {}; +Joomla.Bootstrap = Joomla.Bootstrap || {}; +Joomla.Bootstrap.Initialise = Joomla.Bootstrap.Initialise || {}; +Joomla.Bootstrap.Instances = Joomla.Bootstrap.Instances || {}; +Joomla.Bootstrap.Instances.Toast = new WeakMap(); + +/** + * Initialise the iteractivity + * + * @param {HTMLElement} el The element that will become an toast + * @param {object} options The options for this toast + */ +Joomla.Bootstrap.Initialise.Toast = (el, options) => { + if (!(el instanceof Element)) { + return; + } + if (Joomla.Bootstrap.Instances.Toast.get(el) && el.dispose) { + el.dispose(); + } + Joomla.Bootstrap.Instances.Toast.set(el, new Toast(el, options)); +}; + +// Ensure vanilla mode, for consistency of the events +if (!Object.prototype.hasOwnProperty.call(document.body.dataset, 'bsNoJquery')) { + document.body.dataset.bsNoJquery = ''; +} + +// Get the elements/configurations from the PHP +const toasts = Joomla.getOptions('bootstrap.toast'); +// Initialise the elements +if (typeof toasts === 'object' && toasts !== null) { + Object.keys(toasts).forEach((toast) => { + const opt = toasts[toast]; + const options = { + animation: opt.animation ? opt.animation : true, + autohide: opt.autohide ? opt.autohide : true, + delay: opt.delay ? opt.delay : 5000, + }; + + const elements = Array.from(document.querySelectorAll(toast)); + if (elements.length) { + elements.map((el) => Joomla.Bootstrap.Initialise.Toast(el, options)); + } + }); +} + +export default Toast; diff --git a/components/com_finder/tmpl/search/default_form.php b/components/com_finder/tmpl/search/default_form.php index 5f4ee128fcfa3..dcd213e8469d1 100644 --- a/components/com_finder/tmpl/search/default_form.php +++ b/components/com_finder/tmpl/search/default_form.php @@ -41,7 +41,7 @@ params->get('show_advanced', 1)) : ?> - + diff --git a/layouts/joomla/form/field/contenthistory.php b/layouts/joomla/form/field/contenthistory.php index e695f962b2a83..19d97183f43d5 100644 --- a/layouts/joomla/form/field/contenthistory.php +++ b/layouts/joomla/form/field/contenthistory.php @@ -68,9 +68,10 @@ ?> diff --git a/layouts/joomla/toolbar/dropdown.php b/layouts/joomla/toolbar/dropdown.php index de05e387d0907..71b43bff715a4 100644 --- a/layouts/joomla/toolbar/dropdown.php +++ b/layouts/joomla/toolbar/dropdown.php @@ -39,16 +39,18 @@ - -