mirror of
https://github.com/joomla/joomla-cms.git
synced 2024-06-25 14:53:01 +00:00
[4.0] Decouple messages from core.js (#32747)
This commit is contained in:
parent
21965f7cf7
commit
56f88c45f3
|
@ -23,6 +23,29 @@
|
|||
"defer": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "messages-legacy",
|
||||
"type": "script",
|
||||
"uri": "system/messages-es5.min.js",
|
||||
"attributes": {
|
||||
"nomodule": true,
|
||||
"defer": true
|
||||
},
|
||||
"dependencies": [
|
||||
"core"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "messages",
|
||||
"type": "script",
|
||||
"uri": "system/messages.min.js",
|
||||
"attributes": {
|
||||
"type": "module"
|
||||
},
|
||||
"dependencies": [
|
||||
"messages-legacy"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "template.active",
|
||||
"type": "style",
|
||||
|
|
|
@ -3,6 +3,45 @@
|
|||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
import { sanitizeHtml } from 'bootstrap/js/src/util/sanitizer.js';
|
||||
|
||||
const ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i;
|
||||
const DATA_ATTRIBUTE_PATTERN = /^data-[\w-]*$/i;
|
||||
|
||||
const DefaultAllowlist = {
|
||||
// Global attributes allowed on any supplied element below.
|
||||
'*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN, DATA_ATTRIBUTE_PATTERN],
|
||||
a: ['target', 'href', 'title', 'rel'],
|
||||
area: [],
|
||||
b: [],
|
||||
br: [],
|
||||
col: [],
|
||||
code: [],
|
||||
div: [],
|
||||
em: [],
|
||||
hr: [],
|
||||
h1: [],
|
||||
h2: [],
|
||||
h3: [],
|
||||
h4: [],
|
||||
h5: [],
|
||||
h6: [],
|
||||
i: [],
|
||||
img: ['src', 'srcset', 'alt', 'title', 'width', 'height'],
|
||||
li: [],
|
||||
ol: [],
|
||||
p: [],
|
||||
pre: [],
|
||||
s: [],
|
||||
small: [],
|
||||
span: [],
|
||||
sub: [],
|
||||
sup: [],
|
||||
strong: [],
|
||||
u: [],
|
||||
ul: [],
|
||||
};
|
||||
|
||||
// Only define the Joomla namespace if not defined.
|
||||
window.Joomla = window.Joomla || {};
|
||||
|
||||
|
@ -625,112 +664,17 @@ window.Joomla.Modal = window.Joomla.Modal || {
|
|||
};
|
||||
|
||||
/**
|
||||
* Render messages send via JSON
|
||||
* Used by some javascripts such as validate.js
|
||||
* PLEASE NOTE: do NOT use user supplied input in messages as potential HTML markup is NOT
|
||||
* sanitized!
|
||||
*
|
||||
* @param {object} messages JavaScript object containing the messages to render.
|
||||
* Example:
|
||||
* const messages = {
|
||||
* "message": ["This will be a green message", "So will this"],
|
||||
* "error": ["This will be a red message", "So will this"],
|
||||
* "info": ["This will be a blue message", "So will this"],
|
||||
* "notice": ["This will be same as info message", "So will this"],
|
||||
* "warning": ["This will be a orange message", "So will this"],
|
||||
* "my_custom_type": ["This will be same as info message", "So will this"]
|
||||
* };
|
||||
* @param {string} selector The selector of the container where the message will be rendered
|
||||
* @param {bool} keepOld If we shall discard old messages
|
||||
* @param {int} timeout The milliseconds before the message self destruct
|
||||
* @return void
|
||||
* @param {string} unsafeHtml The html for sanitization
|
||||
* @param {object} allowList The list of HTMLElements with an array of allowed attributes
|
||||
* @param {function} sanitizeFn A custom sanitization function
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
Joomla.renderMessages = (messages, selector, keepOld, timeout) => {
|
||||
let messageContainer;
|
||||
let typeMessages;
|
||||
let messagesBox;
|
||||
let title;
|
||||
let titleWrapper;
|
||||
let messageWrapper;
|
||||
let alertClass;
|
||||
|
||||
if (typeof selector === 'undefined' || (selector && selector === '#system-message-container')) {
|
||||
messageContainer = document.getElementById('system-message-container');
|
||||
} else {
|
||||
messageContainer = document.querySelector(selector);
|
||||
}
|
||||
|
||||
if (typeof keepOld === 'undefined' || (keepOld && keepOld === false)) {
|
||||
Joomla.removeMessages(messageContainer);
|
||||
}
|
||||
|
||||
[].slice.call(Object.keys(messages)).forEach((type) => {
|
||||
// Array of messages of this type
|
||||
typeMessages = messages[type];
|
||||
messagesBox = document.createElement('joomla-alert');
|
||||
|
||||
if (['notice', 'message', 'error', 'warning'].indexOf(type) > -1) {
|
||||
alertClass = (type === 'notice') ? 'info' : type;
|
||||
alertClass = (type === 'message') ? 'success' : alertClass;
|
||||
alertClass = (type === 'error') ? 'danger' : alertClass;
|
||||
alertClass = (type === 'warning') ? 'warning' : alertClass;
|
||||
} else {
|
||||
alertClass = 'info';
|
||||
}
|
||||
|
||||
messagesBox.setAttribute('type', alertClass);
|
||||
messagesBox.setAttribute('dismiss', 'true');
|
||||
|
||||
if (timeout && parseInt(timeout, 10) > 0) {
|
||||
messagesBox.setAttribute('auto-dismiss', timeout);
|
||||
}
|
||||
|
||||
// Title
|
||||
title = Joomla.Text._(type);
|
||||
|
||||
// Skip titles with untranslated strings
|
||||
if (typeof title !== 'undefined') {
|
||||
titleWrapper = document.createElement('div');
|
||||
titleWrapper.className = 'alert-heading';
|
||||
titleWrapper.innerHTML = `<span class="${type}"></span><span class="visually-hidden">${Joomla.Text._(type) ? Joomla.Text._(type) : type}</span>`;
|
||||
messagesBox.appendChild(titleWrapper);
|
||||
}
|
||||
|
||||
// Add messages to the message box
|
||||
messageWrapper = document.createElement('div');
|
||||
messageWrapper.className = 'alert-wrapper';
|
||||
typeMessages.forEach((typeMessage) => {
|
||||
messageWrapper.innerHTML += `<div class="alert-message">${typeMessage}</div>`;
|
||||
});
|
||||
messagesBox.appendChild(messageWrapper);
|
||||
|
||||
messageContainer.appendChild(messagesBox);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove messages
|
||||
*
|
||||
* @param {element} container The element of the container of the message
|
||||
* to be removed
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
Joomla.removeMessages = (container) => {
|
||||
let messageContainer;
|
||||
|
||||
if (container) {
|
||||
messageContainer = container;
|
||||
} else {
|
||||
messageContainer = document.getElementById('system-message-container');
|
||||
}
|
||||
|
||||
const alerts = [].slice.call(messageContainer.querySelectorAll('joomla-alert'));
|
||||
if (alerts.length) {
|
||||
alerts.forEach((alert) => {
|
||||
alert.close();
|
||||
});
|
||||
}
|
||||
Joomla.sanitizeHtml = (unsafeHtml, allowList, sanitizeFn) => {
|
||||
const allowed = (allowList === undefined || allowList === null)
|
||||
? DefaultAllowlist : { ...DefaultAllowlist, ...allowList };
|
||||
return sanitizeHtml(unsafeHtml, allowed, sanitizeFn);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
123
build/media_source/system/js/messages.es6.js
Normal file
123
build/media_source/system/js/messages.es6.js
Normal file
|
@ -0,0 +1,123 @@
|
|||
/**
|
||||
* @copyright (C) 2020 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
// Import the Alert Custom Element
|
||||
import 'joomla-ui-custom-elements/src/js/alert/alert.js';
|
||||
|
||||
/**
|
||||
* Returns the container of the Messages
|
||||
*
|
||||
* @param {string|HTMLElement} container The container
|
||||
*
|
||||
* @returns {HTMLElement}
|
||||
*/
|
||||
const getMessageContainer = (container) => {
|
||||
let messageContainer;
|
||||
|
||||
if (container instanceof HTMLElement) {
|
||||
return container;
|
||||
}
|
||||
if (typeof container === 'undefined' || (container && container === '#system-message-container')) {
|
||||
messageContainer = document.getElementById('system-message-container');
|
||||
} else {
|
||||
messageContainer = document.querySelector(container);
|
||||
}
|
||||
|
||||
return messageContainer;
|
||||
};
|
||||
|
||||
/**
|
||||
* Render messages send via JSON
|
||||
* Used by some javascripts such as validate.js
|
||||
*
|
||||
* @param {object} messages JavaScript object containing the messages to render.
|
||||
* Example:
|
||||
* const messages = {
|
||||
* "message": ["This will be a green message", "So will this"],
|
||||
* "error": ["This will be a red message", "So will this"],
|
||||
* "info": ["This will be a blue message", "So will this"],
|
||||
* "notice": ["This will be same as info message", "So will this"],
|
||||
* "warning": ["This will be a orange message", "So will this"],
|
||||
* "my_custom_type": ["This will be same as info message", "So will this"]
|
||||
* };
|
||||
* @param {string} selector The selector of the container where the message will be rendered
|
||||
* @param {bool} keepOld If we shall discard old messages
|
||||
* @param {int} timeout The milliseconds before the message self destruct
|
||||
* @return void
|
||||
*/
|
||||
Joomla.renderMessages = (messages, selector, keepOld, timeout) => {
|
||||
const messageContainer = getMessageContainer(selector);
|
||||
if (typeof keepOld === 'undefined' || (keepOld && keepOld === false)) {
|
||||
Joomla.removeMessages(messageContainer);
|
||||
}
|
||||
|
||||
[].slice.call(Object.keys(messages)).forEach((type) => {
|
||||
let alertClass = type;
|
||||
|
||||
// Array of messages of this type
|
||||
const typeMessages = messages[type];
|
||||
const messagesBox = document.createElement('joomla-alert');
|
||||
|
||||
if (['success', 'info', 'danger', 'warning'].indexOf(type) < 0) {
|
||||
alertClass = (type === 'notice') ? 'info' : type;
|
||||
alertClass = (type === 'message') ? 'success' : alertClass;
|
||||
alertClass = (type === 'error') ? 'danger' : alertClass;
|
||||
alertClass = (type === 'warning') ? 'warning' : alertClass;
|
||||
}
|
||||
|
||||
messagesBox.setAttribute('type', alertClass);
|
||||
messagesBox.setAttribute('dismiss', true);
|
||||
|
||||
if (timeout && parseInt(timeout, 10) > 0) {
|
||||
messagesBox.setAttribute('auto-dismiss', timeout);
|
||||
}
|
||||
|
||||
// Title
|
||||
const title = Joomla.Text._(type);
|
||||
|
||||
// Skip titles with untranslated strings
|
||||
if (typeof title !== 'undefined') {
|
||||
const titleWrapper = document.createElement('div');
|
||||
titleWrapper.className = 'alert-heading';
|
||||
titleWrapper.innerHTML = Joomla.sanitizeHtml(`<span class="${type}"></span><span class="visually-hidden">${Joomla.Text._(type) ? Joomla.Text._(type) : type}</span>`);
|
||||
messagesBox.appendChild(titleWrapper);
|
||||
}
|
||||
|
||||
// Add messages to the message box
|
||||
const messageWrapper = document.createElement('div');
|
||||
messageWrapper.className = 'alert-wrapper';
|
||||
typeMessages.forEach((typeMessage) => {
|
||||
messageWrapper.innerHTML += Joomla.sanitizeHtml(`<div class="alert-message">${typeMessage}</div>`);
|
||||
});
|
||||
messagesBox.appendChild(messageWrapper);
|
||||
messageContainer.appendChild(messagesBox);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove messages
|
||||
*
|
||||
* @param {element} container The element of the container of the message
|
||||
* to be removed
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
Joomla.removeMessages = (container) => {
|
||||
const messageContainer = getMessageContainer(container);
|
||||
const alerts = [].slice.call(messageContainer.querySelectorAll('joomla-alert'));
|
||||
if (alerts.length) {
|
||||
alerts.forEach((alert) => {
|
||||
alert.close();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const messages = Joomla.getOptions('joomla.messages');
|
||||
if (messages) {
|
||||
Object.keys(messages)
|
||||
.map((message) => Joomla.renderMessages(messages[message], undefined, true, undefined));
|
||||
}
|
||||
});
|
|
@ -21,7 +21,7 @@ $this->getWebAssetManager()
|
|||
|
||||
$this->getWebAssetManager()
|
||||
->useStyle('webcomponent.joomla-alert')
|
||||
->useScript('webcomponent.joomla-alert');
|
||||
->useScript('messages');
|
||||
|
||||
// Add script options
|
||||
$this->addScriptOptions('system.installation', ['url' => Route::_('index.php')]);
|
||||
|
|
|
@ -25,7 +25,7 @@ $this->getWebAssetManager()
|
|||
|
||||
$this->getWebAssetManager()
|
||||
->useStyle('webcomponent.joomla-alert')
|
||||
->useScript('webcomponent.joomla-alert')
|
||||
->useScript('messages')
|
||||
->useScript('webcomponent.core-loader');
|
||||
|
||||
|
||||
|
|
|
@ -13,10 +13,11 @@ use Joomla\CMS\Application\CMSApplication;
|
|||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Language\Text;
|
||||
|
||||
/* @var $displayData array */
|
||||
$msgList = $displayData['msgList'];
|
||||
$document = Factory::getDocument();
|
||||
$msgOutput = '';
|
||||
|
||||
$alert = [
|
||||
$alert = [
|
||||
CMSApplication::MSG_EMERGENCY => 'danger',
|
||||
CMSApplication::MSG_ALERT => 'danger',
|
||||
CMSApplication::MSG_CRITICAL => 'danger',
|
||||
|
@ -40,26 +41,34 @@ Text::script('JOK');
|
|||
Text::script('JOPEN');
|
||||
|
||||
// Alerts progressive enhancement
|
||||
Factory::getDocument()->getWebAssetManager()
|
||||
$document->getWebAssetManager()
|
||||
->useStyle('webcomponent.joomla-alert')
|
||||
->useScript('webcomponent.joomla-alert');
|
||||
->useScript('messages');
|
||||
|
||||
if (is_array($msgList) && !empty($msgList)) :
|
||||
foreach ($msgList as $type => $msgs) :
|
||||
$msgOutput .= '<joomla-alert type="' . ($alert[$type] ?? $type) . '" dismiss="true">';
|
||||
if (!empty($msgs)) :
|
||||
$msgOutput .= '<div class="alert-heading">';
|
||||
$msgOutput .= '<span class="' . $type . '"></span>';
|
||||
$msgOutput .= '<span class="visually-hidden">' . Text::_($type) . '</span>';
|
||||
$msgOutput .= '</div>';
|
||||
$msgOutput .= '<div class="alert-wrapper">';
|
||||
if (is_array($msgList) && !empty($msgList))
|
||||
{
|
||||
$messages = [];
|
||||
|
||||
foreach ($msgList as $type => $msgs)
|
||||
{
|
||||
// JS loaded messages
|
||||
$messages[] = [$alert[$type] ?? $type => $msgs];
|
||||
// Noscript fallback
|
||||
if (!empty($msgs)) {
|
||||
$msgOutput .= '<div class="alert alert-' . ($alert[$type] ?? $type) . '">';
|
||||
foreach ($msgs as $msg) :
|
||||
$msgOutput .= '<div class="alert-message">' . $msg . '</div>';
|
||||
$msgOutput .= $msg;
|
||||
endforeach;
|
||||
$msgOutput .= '</div>';
|
||||
endif;
|
||||
$msgOutput .= '</joomla-alert>';
|
||||
endforeach;
|
||||
endif;
|
||||
}
|
||||
}
|
||||
|
||||
if ($msgOutput !== '')
|
||||
{
|
||||
$msgOutput = '<noscript>' . $msgOutput . '</noscript>';
|
||||
}
|
||||
|
||||
$document->addScriptOptions('joomla.messages', $messages);
|
||||
}
|
||||
?>
|
||||
<div id="system-message-container" aria-live="polite"><?php echo $msgOutput; ?></div>
|
||||
|
|
Loading…
Reference in New Issue
Block a user