'use strict';
/**
* Messages component.
* @namespace messages
* @memberof UCASDesignFramework
* @param {object} global - UCASDesignFramework object.
* @param {object} _u - UCASUtilities object.
*/
(function (global, _u) {
var alertsContainer
var messages = {}
/**
* Message.
* @class
* @memberof! UCASDesignFramework.messages
*/
var Message = {
init: function (params, messagesList) {
// If any more params are needed then a polyfill for Object.assign might be a good idea to support IE.
this.type = params.type || 'info'
this.message = params.message
this.closeButton = params.closeButton === undefined ? true : params.closeButton
this.deleteAfterClose = params.deleteAfterClose === undefined ? true : params.deleteAfterClose
this.id = params.id === undefined ? 'message' + _u.unique.genId() : params.id
this.static = params.static === undefined ? false : params.static
this.duration = params.duration || 5000
// Create the generic message container.
this.containerDiv = document.createElement('div')
this.containerDiv.classList.add('message')
// Create the generic message content.
this.contentDiv = document.createElement('div')
this.contentDiv.classList.add('message--content')
this.contentDiv.textContent = this.message
this.contentDiv.setAttribute('role', 'alert')
// Put them together.
this.containerDiv.appendChild(this.contentDiv)
// Deal with optional parameters.
if (this.closeButton) { addCloseButton(this) }
if (this.static) { this.containerDiv.classList.add('message-static') } else {
this.timeout = window.setTimeout(function () {
destroyMessage(this.id)
}.bind(this), this.duration)
}
switch (this.type) {
case 'info':
this.containerDiv.classList.add('message--information')
break
case 'warning':
this.containerDiv.classList.add('message--warning')
break
case 'success':
this.containerDiv.classList.add('message--success')
break
case 'error':
this.containerDiv.classList.add('message--error')
break
}
// Add to the messages list.
messagesList[this.id] = this
},
destroy: function (messagesList) {
if (this.containerDiv instanceof Node) {
this.containerDiv.classList.add('message--disappearing')
window.setTimeout(function () { alertsContainer.removeChild(this.containerDiv) }.bind(this), 550)
}
if (this.timeout) {
window.clearTimeout(this.timeout)
}
// Remove from messages list.
delete messagesList[this.id]
}
}
/**
* Initialise the messages plugin.
* @function init
* @memberof! UCASDesignFramework.messages
* @public
*/
function init () {
// Handle any existing messages in the markup.
document.querySelectorAll('.message:not(.message--static)').forEach(
function (div) {
// This is to support legacy behaviour. Not creating a full object, here.
addCloseButton({ containerDiv: div, deleteAfterClose: false })
}
)
}
/**
* Add the close button to a message.
* @param {Message} message - The message object.
*/
function addCloseButton (message) {
var button = document.createElement('span')
var closeMessage = function () {
if (message.deleteAfterClose) {
destroyMessage(message.id)
} else {
// I can't remember why this happens, but it's the legacy behaviour so I'm leaving it for now.
message.containerDiv.classList.add('message__closed')
}
}
button.classList.add('message__close-button')
message.containerDiv.appendChild(button)
button.addEventListener('click', closeMessage)
}
/**
* Create a message or update the message if it already exists.
* @public
* @param {Object} params - message params.
* @param {String} params.message - the message text.
* @param {('error'|'warning'|'success'|'info')} [params.type='info'] - the message type.
* @param {Boolean} [params.closeButton=true] - true to add a close button.
* @param {Boolean} [params.deleteAfterClose=true] - true to delete the message after close instead of just hiding it.
* @param {Boolean} [params.static=false] - true to keep the message on the screen.
* @param {Number} [params.duration=5000] - number of milliseconds to keep the messsage on the screen.
* @return {String} the id of the message object.
*/
function createMessage (params) {
if (params === null || typeof params !== 'object' || !params.message) {
_u.log.warn('message params needs to be an object')
return
}
var message
// Check if message already exists.
if (params.id && messages[params.id]) {
message = messages[params.id]
message.contentDiv.innerText = params.message
} else {
message = Object.create(Message)
message.init(params, messages)
alertsContainer || createAlertsContainer()
alertsContainer.appendChild(message.containerDiv)
}
return message.id
}
/**
* Destroy a message.
* @public
* @param {String} id - the id of the message
*/
function destroyMessage (id) {
if (messages[id]) {
messages[id].destroy(messages)
}
}
/**
* Destroy all messages.
* @public
*/
function destroyAllMessages () {
Object.keys(messages).forEach(function (id) {
destroyMessage(id)
})
}
/**
* Create the alerts container.
*/
function createAlertsContainer () {
alertsContainer = document.createElement('div')
alertsContainer.id = 'alerts-container'
alertsContainer.classList.add('wrapper')
document.body.appendChild(alertsContainer)
}
// Expose public methods and properties.
global.messages = {
addSubscriptions: true,
init: init,
create: createMessage,
destroy: destroyMessage,
destroyAll: destroyAllMessages
}
})(UCASDesignFramework, UCASUtilities)