baseframe-js
Version:
Baseframe JS is a comprehensive suite of modular plugins and utilities designed for front-end development
140 lines (139 loc) • 4.83 kB
JavaScript
import $be from "base-elem-js";
import { getDataOptions, setParams, oa } from "./util/helpers";
import Store from "./core/Store";
const VERSION = "1.0.0";
const DATA_NAME = 'Toastr';
const EVENT_NAME = 'toastr';
const DEFAULTS = {
duration: 3000,
appendTo: document.body,
animationDuration: 500,
content: '',
outerCss: 'toastr',
enabledCss: 'toastr--enabled',
dismissCss: 'toastr--dismiss',
btnDismissCss: 'toastr__btn-dismiss',
closeIconCss: 'ico i-close',
ariaLive: 'polite',
closeTextCopy: 'Dismiss',
cssGroupKey: 'std',
oneOnly: false
};
const toastContainers = new Map();
const { make } = $be;
let currentlyToastingGlobal = false;
export default class Toastr {
static defaults = DEFAULTS;
static version = VERSION;
static pluginName = DATA_NAME;
static DismissedEventName = 'toastDismissed';
toastrFinallyTimer;
active;
toasterBodyBuilt;
$element;
$toastrBody;
$toastrWrap;
params;
constructor(element, options) {
const s = this;
const dataOptions = getDataOptions(element, EVENT_NAME);
//state
s.$element = $be(element);
s.toastrFinallyTimer = null;
s.$toastrBody = null;
s.$toastrWrap = null;
s.active = false;
s.params = setParams(Toastr.defaults, options, dataOptions);
s.$element.on([`click.${EVENT_NAME}`, `[${EVENT_NAME}]`], () => s.launch());
return s;
}
dismiss() {
const s = this;
const p = s.params;
s.toastrFinallyTimer && clearTimeout(s.toastrFinallyTimer);
s.$toastrWrap.addClass(p.dismissCss);
setTimeout(() => {
const $toatrContainer = s.#getToasterContainer();
s.$toastrWrap.rmClass(p.dismissCss).remove();
if (!$toatrContainer.find('div').hasEls) {
s.#getToasterContainer().remove();
}
s.active = false;
currentlyToastingGlobal = false;
}, p.animationDuration);
}
setContent(content, updateNow = false) {
const s = this;
oa(s.params, { content });
if (updateNow) {
s.#updateContent(s.params.content);
}
}
launch() {
const s = this;
const p = s.params;
if (!s.active) {
if (currentlyToastingGlobal && p.oneOnly) {
return;
}
if (!s.toasterBodyBuilt)
s.#buildElems();
s.$toastrWrap.rmClass([p.dismissCss, p.enabledCss]);
s.#updateContent(p.content);
$be(document.body).insert(s.#getToasterContainer().insert(s.$toastrWrap));
setTimeout(() => s.$toastrWrap.addClass(p.enabledCss), 0);
// Auto remove if not dismissed
s.toastrFinallyTimer = setTimeout(() => s.dismiss(), p.duration);
s.active = true;
currentlyToastingGlobal = true;
}
}
#getToasterContainer() {
const { cssGroupKey, outerCss } = this.params;
const toasterWrapCss = `${outerCss}-wrap ${outerCss}-wrap--${cssGroupKey}`;
if (!toastContainers.has(toasterWrapCss)) {
toastContainers.set(toasterWrapCss, $be(make(`div.${toasterWrapCss}`)));
}
return toastContainers.get(toasterWrapCss);
}
#buildElems() {
const s = this;
const p = s.params;
const $btn = $be(make(`button.${p.btnDismissCss}`, { type: 'button' }));
const $icon = $be(make(`i.${p.closeIconCss}`, `<span class="sr-only">${p.closeTextCopy}</span>`));
s.$toastrBody = $be(make(`div.${p.outerCss}__body`));
s.$toastrWrap = $be(make(`div.${p.outerCss}`, { role: 'alert', ariaLive: p.ariaLive })).insert([
s.$toastrBody,
$btn.insert($icon)
]);
s.toasterBodyBuilt = true;
// click event to dismiss
s.$toastrWrap.on('click.dismiss', () => s.dismiss(), 'button');
}
#updateContent(content) {
const s = this;
if (s.$toastrBody) {
s.$toastrBody.empty();
if ('string' === typeof content) {
s.$toastrBody.html(content);
}
else
s.$toastrBody.insert(content);
}
}
static setContent(element, content, updateNow = false) {
$be(element).each((elem) => {
const s = Store(elem, DATA_NAME);
Object.assign(s.params, { content });
if (updateNow)
s.#updateContent(s.params.content);
});
}
static remove(element, plugin) {
$be(element).each((elem) => {
const s = plugin || Store(elem, DATA_NAME);
s.$element.off([`click.${EVENT_NAME}`, `[${EVENT_NAME}]`]);
Store(elem, DATA_NAME, null);
});
}
}