'use strict'; // Polyfills import './polyfills/classList'; import { append, createElement, createParagraph, isString } from './helpers'; (function Notifications(window) { // Default notification options const defaultOptions = { closeOnClick: true, displayCloseButton: false, positionClass: 'nfc-top-right', onclick: false, showDuration: 3500, theme: 'success' }; function configureOptions(options) { // Create a copy of options and merge with defaults options = Object.assign({}, defaultOptions, options); // Validate position class function validatePositionClass(className) { const validPositions = [ 'nfc-top-left', 'nfc-top-right', 'nfc-bottom-left', 'nfc-bottom-right' ]; return validPositions.indexOf(className) > -1; } // Verify position, if invalid reset to default if (!validatePositionClass(options.positionClass)) { console.warn('An invalid notification position class has been specified.'); options.positionClass = defaultOptions.positionClass; } // Verify onClick is a function if (options.onclick && typeof options.onclick !== 'function') { console.warn('Notification on click must be a function.'); options.onclick = defaultOptions.onclick; } // Verify show duration if(typeof options.showDuration !== 'number') { options.showDuration = defaultOptions.showDuration; } // Verify theme if(!isString(options.theme) || options.theme.length === 0) { console.warn('Notification theme must be a string with length'); options.theme = defaultOptions.theme; } return options; } // Create a new notification instance function createNotification(options) { // Validate options and set defaults options = configureOptions(options); // Return a notification function return function notification({ title, message } = {}) { const container = createNotificationContainer(options.positionClass); if(!title && !message) { return console.warn('Notification must contain a title or a message!'); } // Create the notification wrapper const notificationEl = createElement('div', 'ncf', options.theme); // Close on click if(options.closeOnClick === true) { notificationEl.addEventListener('click', () => container.removeChild(notificationEl)); } // Custom click callback if(options.onclick) { notificationEl.addEventListener('click', (e) => options.onclick(e)); } // Display close button if(options.displayCloseButton) { const closeButton = createElement('button'); closeButton.innerText = 'X'; // Use the wrappers close on click to avoid useless event listeners if(options.closeOnClick === false){ closeButton.addEventListener('click', () =>container.removeChild(notificationEl)); } append(notificationEl, closeButton); } // Append title and message isString(title) && title.length && append(notificationEl, createParagraph('ncf-title')(title)); isString(message) && message.length && append(notificationEl, createParagraph('nfc-message')(message)); // Append to container append(container, notificationEl); // Remove element after duration if(options.showDuration && options.showDuration > 0) { const timeout = setTimeout(() => { container.removeChild(notificationEl); // Remove container if empty if(container.querySelectorAll('.ncf').length === 0) { document.body.removeChild(container); } }, options.showDuration); // If close on click is enabled and the user clicks, cancel timeout if(options.closeOnClick || options.displayCloseButton) { notificationEl.addEventListener('click', () => clearTimeout(timeout)); } } }; } function createNotificationContainer(position) { let container = document.querySelector(`.${position}`); if(!container) { container = createElement('div', 'ncf-container', position); append(document.body, container); } return container; } // Add Notifications to window to make globally accessible if (window.createNotification) { console.warn('Window already contains a create notification function. Have you included the script twice?'); } else { window.createNotification = createNotification; } })(window);