UNPKG

@atlassian/aui

Version:

Atlassian User Interface Framework

315 lines (266 loc) 12.6 kB
(function (global, factory) { if (typeof define === "function" && define.amd) { define(['module', 'exports', './jquery', './internal/deprecation', './internal/log', './internal/globalize', './key-code', './internal/skate', './template'], factory); } else if (typeof exports !== "undefined") { factory(module, exports, require('./jquery'), require('./internal/deprecation'), require('./internal/log'), require('./internal/globalize'), require('./key-code'), require('./internal/skate'), require('./template')); } else { var mod = { exports: {} }; factory(mod, mod.exports, global.jquery, global.deprecation, global.log, global.globalize, global.keyCode, global.skate, global.template); global.messages = mod.exports; } })(this, function (module, exports, _jquery, _deprecation, _log, _globalize, _keyCode, _skate, _template) { 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _jquery2 = _interopRequireDefault(_jquery); var deprecate = _interopRequireWildcard(_deprecation); var logger = _interopRequireWildcard(_log); var _globalize2 = _interopRequireDefault(_globalize); var _keyCode2 = _interopRequireDefault(_keyCode); var _skate2 = _interopRequireDefault(_skate); var _template2 = _interopRequireDefault(_template); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var DEFAULT_FADEOUT_DURATION = 500; var DEFAULT_FADEOUT_DELAY = 5000; var FADEOUT_RESTORE_DURATION = 100; var MESSAGE_TEMPLATE = '<div class="aui-message aui-message-{type} {closeable} {shadowed} {fadeout}">' + '<p class="title">' + '<strong>{title}</strong>' + '</p>' + '{body}<!-- .aui-message -->' + '</div>'; var MESSAGE_WITHOUT_TITLE_TEMPLATE = '<div class="aui-message aui-message-{type} {closeable} {shadowed} {fadeout}">' + '{body}<!-- .aui-message -->' + '</div>'; function createMessageConstructor(type) { /** * * @param context * @param {Object} obj - message configuration * @param {String} [obj.id] - ID to add to the message. * @param {String} [obj.title] - Plain-text title of the message. If provided, will appear above the message body. * @param {String} obj.body - Content of the message. Can be HTML content. * @param {boolean} [obj.closeable] - If true, the message can be manually closed by the end-user via the UI. * @param {boolean} [obj.shadowed] * @param {boolean} [obj.fadeout] * @param {boolean} [obj.duration] * @param {boolean} [obj.delay] * @returns {*|HTMLElement} */ messages[type] = function (context, obj) { if (!obj) { obj = context; context = '#aui-message-bar'; } // Set up our template options obj.closeable = obj.closeable !== null && obj.closeable !== false; // shadowed no longer does anything but left in so it doesn't break obj.shadowed = obj.shadowed !== null && obj.shadowed !== false; var title = (obj.title || '').toString().trim(); var $message = renderMessageElement(title ? this.template : this.templateAlt, obj, type); insertMessageIntoContext($message, obj.insert, context); // Attach the optional extra behaviours if (obj.closeable) { makeCloseable($message); } if (obj.fadeout) { makeFadeout($message, obj.delay, obj.duration); } return $message; }; } function makeCloseable(message) { (0, _jquery2.default)(message || 'div.aui-message.closeable').each(function () { var $this = (0, _jquery2.default)(this); var $closeIcons = $this.find('.aui-icon.icon-close'); var $icon = $closeIcons.length > 0 ? $closeIcons.first() : (0, _jquery2.default)('<span class="aui-icon icon-close" role="button" tabindex="0"></span>'); $this.addClass('closeable'); $this.append($icon); initCloseMessageBoxOnClickAndKeypress($this); }); } function makeFadeout(message, delay, duration) { delay = typeof delay !== 'undefined' ? delay : DEFAULT_FADEOUT_DELAY; duration = typeof duration !== 'undefined' ? duration : DEFAULT_FADEOUT_DURATION; (0, _jquery2.default)(message || 'div.aui-message.fadeout').each(function () { var $this = (0, _jquery2.default)(this); //Store the component state to avoid collisions between animations var hasFocus = false; var isHover = false; //Small functions to keep the code easier to read and avoid code duplication function fadeOut() { //Algorithm: //1. Stop all running animations (first arg), including any fade animation and delay // Do not jump to the end of the animation (second arg). This prevents the message to abruptly // jump to opacity:0 or opacity:1 //2. Wait <delay> ms before starting the fadeout //3. Start the fadeout with a duration of <duration> ms //4. Close the message at the end of the animation $this.stop(true, false).delay(delay).fadeOut(duration, function () { $this.closeMessage(); }); } function resetFadeOut() { //Algorithm: //1. Stop all running animations (first arg), including any fade animation and delay // Do not jump to the end of the animation (second arg). This prevents the message to abruptly // jump to opacity:0 or opacity:1 //2. Fast animation to opacity:1 $this.stop(true, false).fadeTo(FADEOUT_RESTORE_DURATION, 1); } function shouldStartFadeOut() { return !hasFocus && !isHover; } //Attach handlers for user interactions (focus and hover) $this.focusin(function () { hasFocus = true; resetFadeOut(); }).focusout(function () { hasFocus = false; if (shouldStartFadeOut()) { fadeOut(); } }).hover(function () { //should be called .hoverin(), but jQuery does not implement that method isHover = true; resetFadeOut(); }, function () { //should be called .hoverout(), but jQuery does not implement that method isHover = false; if (shouldStartFadeOut()) { fadeOut(); } }); //Initial animation fadeOut(); }); } /** * Utility methods to display different message types to the user. * Usage: * <pre> * messages.info("#container", { * title: "Info", * body: "You can choose to have messages without Close functionality.", * closeable: false, * shadowed: false * }); * </pre> */ var messages = { setup: function setup() { makeCloseable(); makeFadeout(); }, makeCloseable: makeCloseable, makeFadeout: makeFadeout, template: MESSAGE_TEMPLATE, templateAlt: MESSAGE_WITHOUT_TITLE_TEMPLATE, createMessage: createMessageConstructor }; function initCloseMessageBoxOnClickAndKeypress($message) { $message.on('click', '.aui-icon.icon-close', function (e) { (0, _jquery2.default)(e.target).closest('.aui-message').closeMessage(); }).on('keydown', '.aui-icon.icon-close', function (e) { if (e.which === _keyCode2.default.ENTER || e.which === _keyCode2.default.SPACE) { (0, _jquery2.default)(e.target).closest('.aui-message').closeMessage(); e.preventDefault(); // this is especially important when handling the space bar, as we don't want to page down } }); } function insertMessageIntoContext($message, insertWhere, context) { if (insertWhere === 'prepend') { $message.prependTo(context); } else { $message.appendTo(context); } } function renderMessageElement(templateString, options, type) { // Append the message using template var $message = (0, _jquery2.default)((0, _template2.default)(templateString).fill({ type: type, closeable: options.closeable ? 'closeable' : '', shadowed: options.shadowed ? 'shadowed' : '', fadeout: options.fadeout ? 'fadeout' : '', title: options.title || '', 'body:html': options.body || '' }).toString()); // Add ID if supplied if (options.id) { if (/[#\'\"\.\s]/g.test(options.id)) { // reject IDs that don't comply with style guide (ie. they'll break stuff) logger.warn('Messages error: ID rejected, must not include spaces, hashes, dots or quotes.'); } else { $message.attr('id', options.id); } } return $message; } _jquery2.default.fn.closeMessage = function () { var $message = (0, _jquery2.default)(this); if ($message.hasClass('aui-message') && $message.hasClass('closeable')) { $message.stop(true); //Stop any running animation $message.trigger('messageClose', [this]).remove(); //messageClose event Deprecated as of 5.3 (0, _jquery2.default)(document).trigger('aui-message-close', [this]); //must trigger on document since the element has been removed } }; createMessageConstructor('generic'); //Deprecated Oct 2017 createMessageConstructor('error'); createMessageConstructor('warning'); createMessageConstructor('info'); createMessageConstructor('success'); createMessageConstructor('hint'); //Deprecated Oct 2017 (0, _skate2.default)('aui-message', { created: function created(element) { var body = element.innerHTML; var type = element.getAttribute('type') || 'info'; element.innerHTML = ''; messages[type](element, { body: body, closeable: element.getAttribute('closeable'), delay: element.getAttribute('delay'), duration: element.getAttribute('duration'), fadeout: element.getAttribute('fadeout'), title: element.getAttribute('title') }); } }); (0, _jquery2.default)(function () { messages.setup(); }); deprecate.prop(messages, 'makeCloseable', { extraInfo: 'Use the "closeable" option in the constructor instead. Docs: https://docs.atlassian.com/aui/latest/docs/messages.html' }); deprecate.prop(messages, 'createMessage', { extraInfo: 'Use the provided convenience methods instead e.g. messages.info(). Docs: https://docs.atlassian.com/aui/latest/docs/messages.html' }); deprecate.prop(messages, 'makeFadeout', { extraInfo: 'Use the "fadeout" option in the constructor instead. Docs: https://docs.atlassian.com/aui/latest/docs/messages.html' }); deprecate.prop(messages, 'generic', { extraInfo: 'use the messages.info() method instead. Docs: https://docs.atlassian.com/aui/latest/docs/messages.html' }); deprecate.prop(messages, 'hint', { extraInfo: 'use the messages.info() method instead. Docs: https://docs.atlassian.com/aui/latest/docs/messages.html' }); // Exporting // --------- (0, _globalize2.default)('messages', messages); exports.default = messages; module.exports = exports['default']; }); //# sourceMappingURL=messages.js.map