@atlassian/aui
Version:
Atlassian User Interface library
178 lines (147 loc) • 5.14 kB
JavaScript
import $ from './jquery';
import { defaults } from 'underscore';
import { recomputeStyle } from './internal/animation';
import amdify from './internal/amdify';
import globalize from './internal/globalize';
import keyCode from './key-code';
import CustomEvent from './polyfills/custom-event';
import escapeHtml from './escape-html';
import { CLOSE_BUTTON } from './close-button';
import { FOCUSABLE_QUERY } from './internal/a11y/focusable-query';
import getFocusManager from './focus-manager';
import { I18n } from './i18n';
const AUTO_CLOSE_TIME = 8000;
const ID_FLAG_CONTAINER = 'aui-flag-container';
const DEFAULT_OPTIONS = {
body: '',
close: 'manual',
title: '',
type: 'info',
duration: AUTO_CLOSE_TIME,
ariaLive: 'polite',
};
function flag(flagOptions) {
const options = defaults(flagOptions, DEFAULT_OPTIONS);
options.title = (options.title || '').toString().trim();
const $flag = renderFlagElement(options);
extendFlagElement($flag);
if (options.close === 'auto') {
makeCloseable($flag);
if ($flag.attr('role') === 'alert') {
makeAutoClosable($flag, options.duration);
}
} else if (options.close === 'manual') {
makeCloseable($flag);
}
handleFlagContainer();
insertFlag($flag);
setTimeout(function () {
if ($flag.attr('role') === 'alertdialog') {
getFocusManager.global.enter($flag);
}
}, 0);
return $flag.get(0);
}
function extendFlagElement($flag) {
const flag = $flag[0];
flag.close = function () {
closeFlag($flag);
};
}
function getDefaultAriaLabelForFlagType(type) {
switch (type) {
case 'success':
return I18n.getText('aui.flag.default-aria-label.success');
case 'warning':
return I18n.getText('aui.flag.default-aria-label.warning');
case 'error':
return I18n.getText('aui.flag.default-aria-label.error');
default:
return I18n.getText('aui.flag.default-aria-label.info');
}
}
function renderFlagElement({ body, title, close, type, ariaLive, ariaLabel, ariaDescription }) {
const titleHtml = title ? `<p class="title"><strong>${escapeHtml(title)}</strong></p>` : '';
const html = `<div class="aui-message">${titleHtml}</div>`;
if (!ariaLabel) {
ariaLabel = getDefaultAriaLabelForFlagType(type);
}
if (!ariaDescription) {
ariaDescription = '';
}
const $message = $(html)
.append($.parseHTML(body || ''))
.addClass(close === 'never' ? '' : 'closeable')
.addClass(`aui-message-${type}`);
const isFocusable = $message.find(FOCUSABLE_QUERY).length > 0;
const ariaRole = isFocusable ? 'alertdialog' : 'alert';
return $('<div class="aui-flag"></div>')
.attr({
'aria-label': escapeHtml(ariaLabel),
'aria-hidden': 'false',
'aria-live': escapeHtml(ariaLive),
'role': ariaRole,
...(isFocusable
? {
'data-aui-focus-selector': FOCUSABLE_QUERY.split(', ')
.map((item) => `.aui-message ${item}`)
.join(', '),
'data-aui-focus': 'true',
}
: {}),
...(!!ariaDescription ? { 'aria-description': escapeHtml(ariaDescription) } : {}),
})
.append($message);
}
function makeCloseable($flag) {
const $icon = $(CLOSE_BUTTON);
$icon.on('click', function () {
closeFlag($flag);
});
$icon.on('keypress', function (e) {
if (e.which === keyCode.ENTER || e.which === keyCode.SPACE) {
closeFlag($flag);
e.preventDefault();
}
});
return $flag.find('.aui-message').append($icon)[0];
}
function makeAutoClosable($flag, duration) {
$flag.find('.aui-message').addClass('aui-will-close');
setTimeout(function () {
$flag[0].close();
}, duration);
}
function closeFlag($flagToClose) {
const flag = $flagToClose.get(0);
if ($flagToClose.attr('role') === 'alertdialog') {
getFocusManager.global.exit($flagToClose);
}
flag.removeAttribute('open');
flag.setAttribute('inert', '');
flag.setAttribute('aria-hidden', true);
flag.style.display = 'none';
flag.dispatchEvent(new CustomEvent('aui-flag-close', { bubbles: true }));
return flag;
}
function handleFlagContainer() {
const container = findContainer();
if (container) {
const closedFlags = container.querySelectorAll('.aui-flag:not([open])');
Array.from(closedFlags).map((flag) => flag.parentNode.removeChild(flag));
} else {
$('body').prepend('<div id="' + ID_FLAG_CONTAINER + '"></div>');
}
}
function findContainer() {
return document.getElementById(ID_FLAG_CONTAINER);
}
function insertFlag($flag) {
const flagContainer = findContainer();
$flag.appendTo(flagContainer);
recomputeStyle($flag);
$flag.removeAttr('hidden').attr('open', '');
}
amdify('aui/flag', flag);
globalize('flag', flag);
export default flag;