summaryrefslogtreecommitdiffstatshomepage
path: root/core/misc/message.js
diff options
context:
space:
mode:
Diffstat (limited to 'core/misc/message.js')
-rw-r--r--core/misc/message.js221
1 files changed, 178 insertions, 43 deletions
diff --git a/core/misc/message.js b/core/misc/message.js
index fd899e0ceba..9db487cd908 100644
--- a/core/misc/message.js
+++ b/core/misc/message.js
@@ -1,15 +1,27 @@
/**
-* DO NOT EDIT THIS FILE.
-* See the following change record for more information,
-* https://www.drupal.org/node/2815083
-* @preserve
-**/
-
-(Drupal => {
+ * @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() {
- let messageWrapper = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
-
+ constructor(messageWrapper = null) {
if (!messageWrapper) {
this.messageWrapper = Drupal.Message.defaultWrapper();
} else {
@@ -17,30 +29,65 @@
}
}
+ /**
+ * 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() {
let wrapper = document.querySelector('[data-drupal-messages]');
-
if (!wrapper) {
wrapper = document.querySelector('[data-drupal-messages-fallback]');
wrapper.removeAttribute('data-drupal-messages-fallback');
wrapper.setAttribute('data-drupal-messages', '');
wrapper.classList.remove('hidden');
}
-
- return wrapper.innerHTML === '' ? Drupal.Message.messageInternalWrapper(wrapper) : wrapper.firstElementChild;
+ 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')
+ warning: Drupal.t('Warning message'),
};
}
- add(message) {
- let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
-
+ /**
+ * 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: `'filevalidationerror'`
+ * or several values separated by a space: `'mymodule formvalidation'`
+ * 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';
}
@@ -49,71 +96,159 @@
throw new Error('Message must be a string.');
}
+ // Send message to screen reader.
Drupal.Message.announce(message, options);
- options.id = options.id ? String(options.id) : `${options.type}-${Math.random().toFixed(15).replace('0.', '')}`;
-
+ /**
+ * 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().`);
+ 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));
+ 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}"]`);
+ return this.messageWrapper.querySelector(
+ `[data-drupal-message-id^="${id}"]`,
+ );
}
+ /**
+ * Removes messages from the message area.
+ *
+ * @name Drupal.Message~messageDefinition.remove
+ *
+ * @param {string} id
+ * Index of the message to remove, as returned by
+ * {@link Drupal.Message~messageDefinition.add}.
+ *
+ * @return {number}
+ * Number of removed messages.
+ */
remove(id) {
return this.messageWrapper.removeChild(this.select(id));
}
+ /**
+ * Removes all messages from the message area.
+ *
+ * @name Drupal.Message~messageDefinition.clear
+ */
clear() {
- Array.prototype.forEach.call(this.messageWrapper.querySelectorAll('[data-drupal-message-id]'), message => {
- this.messageWrapper.removeChild(message);
- });
+ Array.prototype.forEach.call(
+ this.messageWrapper.querySelectorAll('[data-drupal-message-id]'),
+ (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')) {
+ 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;
}
-
};
- Drupal.theme.message = (_ref, _ref2) => {
- let {
- text
- } = _ref;
- let {
- type,
- id
- } = _ref2;
+ /**
+ * 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(
+ '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); \ No newline at end of file
+})(Drupal);