420 lines
8.4 KiB
JavaScript
420 lines
8.4 KiB
JavaScript
import * as Utils from 'utils'
|
|
|
|
export let PageHidden = false
|
|
export let DocModalCount = 0
|
|
|
|
const DocTitleProps = {
|
|
originalTitle: null,
|
|
count: 0,
|
|
changed: false,
|
|
timer: -1
|
|
}
|
|
|
|
export const docTitle = {
|
|
increment: () => {
|
|
DocTitleProps.count++
|
|
|
|
docTitle._update()
|
|
},
|
|
|
|
decrement: () => {
|
|
DocTitleProps.count--
|
|
|
|
if (DocTitleProps.count <= 0) {
|
|
docTitle._clear()
|
|
return
|
|
}
|
|
|
|
docTitle._update()
|
|
},
|
|
|
|
_update: () => {
|
|
let title = document.title
|
|
|
|
if (!DocTitleProps.changed) {
|
|
DocTitleProps.originalTitle = title
|
|
document.title = `(${DocTitleProps.count}) ${title}`
|
|
DocTitleProps.changed = true
|
|
} else {
|
|
document.title = `(${DocTitleProps.count}) ${DocTitleProps.originalTitle}`
|
|
}
|
|
},
|
|
|
|
_clear: () => {
|
|
if (DocTitleProps.changed) {
|
|
DocTitleProps.count = 0
|
|
document.title = DocTitleProps.originalTitle
|
|
DocTitleProps.changed = false
|
|
}
|
|
}
|
|
}
|
|
|
|
export const DefaultMaxVisible = 5
|
|
|
|
export const Queues = {
|
|
global: {
|
|
maxVisible: DefaultMaxVisible,
|
|
queue: []
|
|
}
|
|
}
|
|
|
|
export const Store = {}
|
|
|
|
export let Defaults = {
|
|
type: 'alert',
|
|
layout: 'topRight',
|
|
theme: 'mint',
|
|
text: '',
|
|
timeout: false,
|
|
progressBar: true,
|
|
closeWith: ['click'],
|
|
animation: {
|
|
open: 'noty_effects_open',
|
|
close: 'noty_effects_close'
|
|
},
|
|
id: false,
|
|
force: false,
|
|
killer: false,
|
|
queue: 'global',
|
|
container: false,
|
|
buttons: [],
|
|
callbacks: {
|
|
beforeShow: null,
|
|
onShow: null,
|
|
afterShow: null,
|
|
onClose: null,
|
|
afterClose: null,
|
|
onClick: null,
|
|
onHover: null,
|
|
onTemplate: null
|
|
},
|
|
sounds: {
|
|
sources: [],
|
|
volume: 1,
|
|
conditions: []
|
|
},
|
|
titleCount: {
|
|
conditions: []
|
|
},
|
|
modal: false,
|
|
visibilityControl: false
|
|
}
|
|
|
|
/**
|
|
* @param {string} queueName
|
|
* @return {object}
|
|
*/
|
|
export function getQueueCounts (queueName = 'global') {
|
|
let count = 0
|
|
let max = DefaultMaxVisible
|
|
|
|
if (Queues.hasOwnProperty(queueName)) {
|
|
max = Queues[queueName].maxVisible
|
|
Object.keys(Store).forEach(i => {
|
|
if (Store[i].options.queue === queueName && !Store[i].closed) count++
|
|
})
|
|
}
|
|
|
|
return {
|
|
current: count,
|
|
maxVisible: max
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {Noty} ref
|
|
* @return {void}
|
|
*/
|
|
export function addToQueue (ref) {
|
|
if (!Queues.hasOwnProperty(ref.options.queue)) {
|
|
Queues[ref.options.queue] = {maxVisible: DefaultMaxVisible, queue: []}
|
|
}
|
|
|
|
Queues[ref.options.queue].queue.push(ref)
|
|
}
|
|
|
|
/**
|
|
* @param {Noty} ref
|
|
* @return {void}
|
|
*/
|
|
export function removeFromQueue (ref) {
|
|
if (Queues.hasOwnProperty(ref.options.queue)) {
|
|
const queue = []
|
|
Object.keys(Queues[ref.options.queue].queue).forEach(i => {
|
|
if (Queues[ref.options.queue].queue[i].id !== ref.id) {
|
|
queue.push(Queues[ref.options.queue].queue[i])
|
|
}
|
|
})
|
|
Queues[ref.options.queue].queue = queue
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {string} queueName
|
|
* @return {void}
|
|
*/
|
|
export function queueRender (queueName = 'global') {
|
|
if (Queues.hasOwnProperty(queueName)) {
|
|
const noty = Queues[queueName].queue.shift()
|
|
|
|
if (noty) noty.show()
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return {void}
|
|
*/
|
|
export function queueRenderAll () {
|
|
Object.keys(Queues).forEach(queueName => {
|
|
queueRender(queueName)
|
|
})
|
|
}
|
|
|
|
/**
|
|
* @param {Noty} ref
|
|
* @return {void}
|
|
*/
|
|
export function ghostFix (ref) {
|
|
const ghostID = Utils.generateID('ghost')
|
|
let ghost = document.createElement('div')
|
|
ghost.setAttribute('id', ghostID)
|
|
Utils.css(ghost, {
|
|
height: Utils.outerHeight(ref.barDom) + 'px'
|
|
})
|
|
|
|
ref.barDom.insertAdjacentHTML('afterend', ghost.outerHTML)
|
|
|
|
Utils.remove(ref.barDom)
|
|
ghost = document.getElementById(ghostID)
|
|
Utils.addClass(ghost, 'noty_fix_effects_height')
|
|
Utils.addListener(ghost, Utils.animationEndEvents, () => {
|
|
Utils.remove(ghost)
|
|
})
|
|
}
|
|
|
|
/**
|
|
* @param {Noty} ref
|
|
* @return {void}
|
|
*/
|
|
export function build (ref) {
|
|
findOrCreateContainer(ref)
|
|
|
|
const markup = `<div class="noty_body">${ref.options.text}</div>${buildButtons(ref)}<div class="noty_progressbar"></div>`
|
|
|
|
ref.barDom = document.createElement('div')
|
|
ref.barDom.setAttribute('id', ref.id)
|
|
Utils.addClass(
|
|
ref.barDom,
|
|
`noty_bar noty_type__${ref.options.type} noty_theme__${ref.options.theme}`
|
|
)
|
|
|
|
ref.barDom.innerHTML = markup
|
|
|
|
fire(ref, 'onTemplate')
|
|
}
|
|
|
|
/**
|
|
* @param {Noty} ref
|
|
* @return {boolean}
|
|
*/
|
|
export function hasButtons (ref) {
|
|
return !!(ref.options.buttons && Object.keys(ref.options.buttons).length)
|
|
}
|
|
|
|
/**
|
|
* @param {Noty} ref
|
|
* @return {string}
|
|
*/
|
|
function buildButtons (ref) {
|
|
if (hasButtons(ref)) {
|
|
let buttons = document.createElement('div')
|
|
Utils.addClass(buttons, 'noty_buttons')
|
|
|
|
Object.keys(ref.options.buttons).forEach(key => {
|
|
buttons.appendChild(ref.options.buttons[key].dom)
|
|
})
|
|
|
|
ref.options.buttons.forEach(btn => {
|
|
buttons.appendChild(btn.dom)
|
|
})
|
|
return buttons.outerHTML
|
|
}
|
|
return ''
|
|
}
|
|
|
|
/**
|
|
* @param {Noty} ref
|
|
* @return {void}
|
|
*/
|
|
export function handleModal (ref) {
|
|
if (ref.options.modal) {
|
|
if (DocModalCount === 0) {
|
|
createModal(ref)
|
|
}
|
|
|
|
DocModalCount++
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {Noty} ref
|
|
* @return {void}
|
|
*/
|
|
export function handleModalClose (ref) {
|
|
if (ref.options.modal && DocModalCount > 0) {
|
|
DocModalCount--
|
|
|
|
if (DocModalCount <= 0) {
|
|
const modal = document.querySelector('.noty_modal')
|
|
|
|
if (modal) {
|
|
Utils.removeClass(modal, 'noty_modal_open')
|
|
Utils.addClass(modal, 'noty_modal_close')
|
|
Utils.addListener(modal, Utils.animationEndEvents, () => {
|
|
Utils.remove(modal)
|
|
})
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return {void}
|
|
*/
|
|
function createModal () {
|
|
const body = document.querySelector('body')
|
|
const modal = document.createElement('div')
|
|
Utils.addClass(modal, 'noty_modal')
|
|
body.insertBefore(modal, body.firstChild)
|
|
Utils.addClass(modal, 'noty_modal_open')
|
|
|
|
Utils.addListener(modal, Utils.animationEndEvents, () => {
|
|
Utils.removeClass(modal, 'noty_modal_open')
|
|
})
|
|
}
|
|
|
|
/**
|
|
* @param {Noty} ref
|
|
* @return {void}
|
|
*/
|
|
function findOrCreateContainer (ref) {
|
|
if (ref.options.container) {
|
|
ref.layoutDom = document.querySelector(ref.options.container)
|
|
return
|
|
}
|
|
|
|
const layoutID = `noty_layout__${ref.options.layout}`
|
|
ref.layoutDom = document.querySelector(`div#${layoutID}`)
|
|
|
|
if (!ref.layoutDom) {
|
|
ref.layoutDom = document.createElement('div')
|
|
ref.layoutDom.setAttribute('id', layoutID)
|
|
ref.layoutDom.setAttribute('role', 'alert')
|
|
ref.layoutDom.setAttribute('aria-live', 'polite')
|
|
Utils.addClass(ref.layoutDom, 'noty_layout')
|
|
document.querySelector('body').appendChild(ref.layoutDom)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {Noty} ref
|
|
* @return {void}
|
|
*/
|
|
export function queueClose (ref) {
|
|
if (ref.options.timeout) {
|
|
if (ref.options.progressBar && ref.progressDom) {
|
|
Utils.css(ref.progressDom, {
|
|
transition: `width ${ref.options.timeout}ms linear`,
|
|
width: '0%'
|
|
})
|
|
}
|
|
|
|
clearTimeout(ref.closeTimer)
|
|
|
|
ref.closeTimer = setTimeout(
|
|
() => {
|
|
ref.close()
|
|
},
|
|
ref.options.timeout
|
|
)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {Noty} ref
|
|
* @return {void}
|
|
*/
|
|
export function dequeueClose (ref) {
|
|
if (ref.options.timeout && ref.closeTimer) {
|
|
clearTimeout(ref.closeTimer)
|
|
ref.closeTimer = -1
|
|
|
|
if (ref.options.progressBar && ref.progressDom) {
|
|
Utils.css(ref.progressDom, {
|
|
transition: 'width 0ms linear',
|
|
width: '100%'
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {Noty} ref
|
|
* @param {string} eventName
|
|
* @return {void}
|
|
*/
|
|
export function fire (ref, eventName) {
|
|
if (ref.listeners.hasOwnProperty(eventName)) {
|
|
ref.listeners[eventName].forEach(cb => {
|
|
if (typeof cb === 'function') {
|
|
cb.apply(ref)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {Noty} ref
|
|
* @return {void}
|
|
*/
|
|
export function openFlow (ref) {
|
|
fire(ref, 'afterShow')
|
|
queueClose(ref)
|
|
|
|
Utils.addListener(ref.barDom, 'mouseenter', () => {
|
|
dequeueClose(ref)
|
|
})
|
|
|
|
Utils.addListener(ref.barDom, 'mouseleave', () => {
|
|
queueClose(ref)
|
|
})
|
|
}
|
|
|
|
/**
|
|
* @param {Noty} ref
|
|
* @return {void}
|
|
*/
|
|
export function closeFlow (ref) {
|
|
delete Store[ref.id]
|
|
ref.closing = false
|
|
fire(ref, 'afterClose')
|
|
|
|
Utils.remove(ref.barDom)
|
|
|
|
if (
|
|
ref.layoutDom.querySelectorAll('.noty_bar').length === 0 &&
|
|
!ref.options.container
|
|
) {
|
|
Utils.remove(ref.layoutDom)
|
|
}
|
|
|
|
if (
|
|
Utils.inArray('docVisible', ref.options.titleCount.conditions) ||
|
|
Utils.inArray('docHidden', ref.options.titleCount.conditions)
|
|
) {
|
|
docTitle.decrement()
|
|
}
|
|
|
|
queueRender(ref.options.queue)
|
|
}
|