import './popup.css'; import { Ut } from '../../utils/Ut'; import { El } from '../../utils/dom'; import { Overlay } from '../overlay'; import { Stack } from '../../core/Stack'; import { Render } from '../../core/Render'; //////////////////// // Popup Widget //////////////////// export class Popup { /** * Popup, Constructor */ constructor(target, opts) { let that = this; this.target = target; if (this.target.dxData('popup')) { return; } this.target.dxData('popup', this); this.opts = { ... { scrollBar : true, marginTop : 50, marginBottom : 50, multiple : false, width : 800, height : 'auto', modal : true, cls : null }, ... opts }; this.opened = false; if (!this.opts.multiple) { Stack.widgets.Popup?.forEach((popup, key) => { if (key == this.ekey - 1) { that.opened = true; popup.destroy(_ => that.init()); } else { popup.destroy(); } }); } if (!this.opened) { this.opened = true; this.init(); } } /** * Popup, Init */ init() { Stack.add(this); this._plugins = []; this.create(); this.setEvents(); } /** * Popup, Create */ create() { this.card = { ui: Render.makeCardElement({ title: this.opts.title || this.target.dataset.title, descr: this.opts.descr || this.target.dataset.descr, scrollbar : this.opts.scrollBar || this.target.scrollbar }, null) }; this.card.toolbar = this.card.ui.dxFind('.top-bar-inner'); this.card.container = this.card.ui.dxFind('.container'); this.target.classList.add('popup-container'); this.card.container.append(this.target); if (this.opts.toolbar) { if (!this.card.toolbar) { this.card.toolbar = El('div', { className: 'top-bar-inner' }); this.card.ui.prepend(El('div', { className: 'top-bar' }, this.card.toolbar)); } this.card.toolbar.append(this.opts.toolbar); } if (this.card.toolbar) { this.card.toolbar.append( El('a', { className: 'ic-close' }) ); } this.card.ui.classList.add('sp-popup'); if (this.opts.cls) { this.card.ui.classList.add(this.opts.cls); } this.card.ui.style.width = this.opts.width + 'px'; this.card.container.style.height = this.opts.height + 'px'; if (this.opts.scrollBar) { this.card.container.classList.add('sp-scrollbar'); } this.scrollTop = window.screenY; if (Ut.device.isMobile) { document.body.dxCss({ position: 'fixed', top: '-' + this.scrollTop + 'px' }) } document.body.append(this.card.ui); if (this.opts.modal) { Overlay.showModal(this.card.ui); } this.resize(); this.card.ui.dxCss({ top: this.opts.marginTop + 'px', opacity: 1 }); Ut.trigger(this.opts.onInit, this); } /** * Popup, Set Title */ setTitle(text) { let title = this.card.toolbar.dxFind('h2.title'); title.textContent = text; title.classList.remove('hide'); } /** * Popup, resize */ resize() { if (this.opts.scrollBar) { this.card.container.dxCss('max-height', ( window.innerHeight - this.card.toolbar.clientHeight - this.opts.marginTop - this.opts.marginBottom ) + 'px' ); } Ut.trigger(this.opts.onResize, this, this.card.container.clientWidth, this.card.container.clientHeight ); } /** * Popup, Set Events */ setEvents() { let that = this; if (this.opts.scrollBar) { let tm = null; window.dxOn('resize.popup' + this.ekey + ' orientationchange.popup' + this.ekey, function() { if (tm) { clearTimeout(tm); tm = null; } tm = setTimeout(function() { that.resize(); }, 300); }); } this.card.toolbar.dxOn('click', '.ic-close', function() { that.destroy(); }); document.dxOn('keyup.popup' + this.ekey, function(e) { if (e.key == 'Escape') { that.destroy(); } }); } /** * Popup, Destroy */ destroy(callback) { const that = this; this.card.ui.addEventListener('transitionend', function(e) { document.dxOff('keyup.popup' + that.ekey + ' resize.popup' + that.ekey + ' orientationchange.popup' + that.ekey); if (that.opts.modal) { Overlay.hideModal(that.card.ui); } that.card.ui.remove(); if (Ut.device.isMobile) { document.body.dxCss({ position: '', top: '' }); document.body.scrollTop = that.scrollTop; } that._plugins.forEach(widget => widget.destroy()); Stack.delete(this); that.target.dxRemoveData('popup'); Ut.trigger(callback); Ut.trigger(that.opts.onDestroy); }, { once: true }); this.card.ui.dxCss({ top: '-25%', opacity: 0 }); } }