Initial Drupal 11 with DDEV setup
This commit is contained in:
267
web/core/misc/message.js
Normal file
267
web/core/misc/message.js
Normal file
@ -0,0 +1,267 @@
|
||||
/**
|
||||
* @file
|
||||
* Message API.
|
||||
*/
|
||||
((Drupal) => {
|
||||
/**
|
||||
* @typedef {class} Drupal.Message~messageDefinition
|
||||
*/
|
||||
|
||||
/**
|
||||
* Constructs a new instance of the Drupal.Message class.
|
||||
*
|
||||
* This provides a uniform interface for adding and removing messages to a
|
||||
* specific location on the page.
|
||||
*
|
||||
* @param {HTMLElement} messageWrapper
|
||||
* The zone where to add messages. If no element is provided an attempt is
|
||||
* made to determine a default location.
|
||||
*
|
||||
* @return {Drupal.Message~messageDefinition}
|
||||
* Class to add and remove messages.
|
||||
*/
|
||||
Drupal.Message = class {
|
||||
constructor(messageWrapper = null) {
|
||||
if (!messageWrapper) {
|
||||
this.messageWrapper = Drupal.Message.defaultWrapper();
|
||||
} else {
|
||||
this.messageWrapper = messageWrapper;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to determine the default location for
|
||||
* inserting JavaScript messages or create one if needed.
|
||||
*
|
||||
* @return {HTMLElement}
|
||||
* The default destination for JavaScript messages.
|
||||
*/
|
||||
static defaultWrapper() {
|
||||
// Search for the element with '[data-drupal-messages]' selector.
|
||||
// If not found then only try to search for fallback element.
|
||||
let wrapper =
|
||||
document.querySelector('[data-drupal-messages]') ||
|
||||
document.querySelector('[data-drupal-messages-fallback]');
|
||||
if (!wrapper) {
|
||||
// If no status messages element is found, a fallback element is created to prevent
|
||||
// execution-breaking JS errors when attempting to report a problem.
|
||||
// This scenario can occur on any page that does not include a status_messages
|
||||
// render element.
|
||||
wrapper = document.createElement('div');
|
||||
document.body.appendChild(wrapper);
|
||||
}
|
||||
|
||||
if (wrapper.hasAttribute('data-drupal-messages-fallback')) {
|
||||
// Remove the fallback attribute if it exists.
|
||||
wrapper.removeAttribute('data-drupal-messages-fallback');
|
||||
wrapper.classList.remove('hidden');
|
||||
}
|
||||
wrapper.setAttribute('data-drupal-messages', '');
|
||||
|
||||
return wrapper.innerHTML === ''
|
||||
? Drupal.Message.messageInternalWrapper(wrapper)
|
||||
: wrapper.firstElementChild;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide an object containing the available message types.
|
||||
*
|
||||
* @return {Object}
|
||||
* An object containing message type strings.
|
||||
*/
|
||||
static getMessageTypeLabels() {
|
||||
return {
|
||||
status: Drupal.t('Status message'),
|
||||
error: Drupal.t('Error message'),
|
||||
warning: Drupal.t('Warning message'),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Sequentially adds a message to the message area.
|
||||
*
|
||||
* @name Drupal.Message~messageDefinition.add
|
||||
*
|
||||
* @param {string} message
|
||||
* The message to display
|
||||
* @param {object} [options]
|
||||
* The context of the message.
|
||||
* @param {string} [options.id]
|
||||
* The message ID, it can be a simple value: `'file_validation_error'`
|
||||
* or several values separated by a space: `'my_module form_validation'`
|
||||
* which can be used as an explicit selector for a message.
|
||||
* @param {string} [options.type=status]
|
||||
* Message type, can be either 'status', 'error' or 'warning'.
|
||||
* @param {string} [options.announce]
|
||||
* Screen-reader version of the message if necessary. To prevent a message
|
||||
* being sent to Drupal.announce() this should be an empty string.
|
||||
* @param {string} [options.priority]
|
||||
* Priority of the message for Drupal.announce().
|
||||
*
|
||||
* @return {string}
|
||||
* ID of message.
|
||||
*/
|
||||
add(message, options = {}) {
|
||||
if (!options.hasOwnProperty('type')) {
|
||||
options.type = 'status';
|
||||
}
|
||||
|
||||
if (typeof message !== 'string') {
|
||||
throw new Error('Message must be a string.');
|
||||
}
|
||||
|
||||
// Send message to screen reader.
|
||||
Drupal.Message.announce(message, options);
|
||||
/**
|
||||
* Use the provided index for the message or generate a pseudo-random key
|
||||
* to allow message deletion.
|
||||
*/
|
||||
options.id = options.id
|
||||
? String(options.id)
|
||||
: `${options.type}-${Math.random().toFixed(15).replace('0.', '')}`;
|
||||
|
||||
// Throw an error if an unexpected message type is used.
|
||||
if (!Drupal.Message.getMessageTypeLabels().hasOwnProperty(options.type)) {
|
||||
const { type } = options;
|
||||
throw new Error(
|
||||
`The message type, ${type}, is not present in Drupal.Message.getMessageTypeLabels().`,
|
||||
);
|
||||
}
|
||||
|
||||
this.messageWrapper.appendChild(
|
||||
Drupal.theme('message', { text: message }, options),
|
||||
);
|
||||
|
||||
return options.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select a message based on id.
|
||||
*
|
||||
* @name Drupal.Message~messageDefinition.select
|
||||
*
|
||||
* @param {string} id
|
||||
* The message id to delete from the area.
|
||||
*
|
||||
* @return {Element}
|
||||
* Element found.
|
||||
*/
|
||||
select(id) {
|
||||
return this.messageWrapper.querySelector(
|
||||
`[data-drupal-message-id^="${id}"]`,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a message element from the message area.
|
||||
*
|
||||
* @name Drupal.Message~messageDefinition.remove
|
||||
*
|
||||
* @param {string} id
|
||||
* The unique identifier of the message to remove, as returned by
|
||||
* {@link Drupal.Message~messageDefinition.add}.
|
||||
*
|
||||
* @return {Element}
|
||||
* Returns the removed message element.
|
||||
*/
|
||||
remove(id) {
|
||||
return this.messageWrapper.removeChild(this.select(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all messages from the message area.
|
||||
*
|
||||
* @name Drupal.Message~messageDefinition.clear
|
||||
*/
|
||||
clear() {
|
||||
this.messageWrapper
|
||||
.querySelectorAll('[data-drupal-message-id]')
|
||||
.forEach((message) => {
|
||||
this.messageWrapper.removeChild(message);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to call Drupal.announce() with the right parameters.
|
||||
*
|
||||
* @param {string} message
|
||||
* Displayed message.
|
||||
* @param {object} options
|
||||
* Additional data.
|
||||
* @param {string} [options.announce]
|
||||
* Screen-reader version of the message if necessary. To prevent a message
|
||||
* being sent to Drupal.announce() this should be `''`.
|
||||
* @param {string} [options.priority]
|
||||
* Priority of the message for Drupal.announce().
|
||||
* @param {string} [options.type]
|
||||
* Message type, can be either 'status', 'error' or 'warning'.
|
||||
*/
|
||||
static announce(message, options) {
|
||||
if (
|
||||
!options.priority &&
|
||||
(options.type === 'warning' || options.type === 'error')
|
||||
) {
|
||||
options.priority = 'assertive';
|
||||
}
|
||||
/**
|
||||
* If screen reader message is not disabled announce screen reader
|
||||
* specific text or fallback to the displayed message.
|
||||
*/
|
||||
if (options.announce !== '') {
|
||||
Drupal.announce(options.announce || message, options.priority);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function for creating the internal message wrapper element.
|
||||
*
|
||||
* @param {HTMLElement} messageWrapper
|
||||
* The message wrapper.
|
||||
*
|
||||
* @return {HTMLElement}
|
||||
* The internal wrapper DOM element.
|
||||
*/
|
||||
static messageInternalWrapper(messageWrapper) {
|
||||
const innerWrapper = document.createElement('div');
|
||||
innerWrapper.setAttribute('class', 'messages__wrapper');
|
||||
messageWrapper.insertAdjacentElement('afterbegin', innerWrapper);
|
||||
return innerWrapper;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Theme function for a message.
|
||||
*
|
||||
* @param {object} message
|
||||
* The message object.
|
||||
* @param {string} message.text
|
||||
* The message text.
|
||||
* @param {object} options
|
||||
* The message context.
|
||||
* @param {string} options.type
|
||||
* The message type.
|
||||
* @param {string} options.id
|
||||
* ID of the message, for reference.
|
||||
*
|
||||
* @return {HTMLElement}
|
||||
* A DOM Node.
|
||||
*/
|
||||
Drupal.theme.message = ({ text }, { type, id }) => {
|
||||
const messagesTypes = Drupal.Message.getMessageTypeLabels();
|
||||
const messageWrapper = document.createElement('div');
|
||||
|
||||
messageWrapper.setAttribute('class', `messages messages--${type}`);
|
||||
messageWrapper.setAttribute(
|
||||
'role',
|
||||
type === 'error' || type === 'warning' ? 'alert' : 'status',
|
||||
);
|
||||
messageWrapper.setAttribute('data-drupal-message-id', id);
|
||||
messageWrapper.setAttribute('data-drupal-message-type', type);
|
||||
|
||||
messageWrapper.setAttribute('aria-label', messagesTypes[type]);
|
||||
|
||||
messageWrapper.innerHTML = `${text}`;
|
||||
|
||||
return messageWrapper;
|
||||
};
|
||||
})(Drupal);
|
||||
Reference in New Issue
Block a user