UNPKG

@pi0/framework7

Version:

Full featured mobile HTML framework for building iOS & Android apps

225 lines (203 loc) 5.95 kB
import $ from 'dom7'; import Utils from '../../utils/utils'; import Framework7Class from '../../utils/class'; const openedModals = []; const dialogsQueue = []; function clearDialogsQueue() { if (dialogsQueue.length === 0) return; const dialog = dialogsQueue.shift(); dialog.open(); } class Modal extends Framework7Class { constructor(app, params) { super(params, [app]); const modal = this; const defaults = {}; // Extend defaults with modules params modal.useModulesParams(defaults); modal.params = Utils.extend(defaults, params); // Install Modules modal.useModules(); return this; } onOpen() { const modal = this; openedModals.push(modal); $('html').addClass(`with-modal-${modal.type.toLowerCase()}`); modal.$el.trigger(`modal:open ${modal.type.toLowerCase()}:open`, modal); modal.emit(`local::open modalOpen ${modal.type}Open`, modal); } onOpened() { const modal = this; modal.$el.trigger(`modal:opened ${modal.type.toLowerCase()}:opened`, modal); modal.emit(`local::opened modalOpened ${modal.type}Opened`, modal); } onClose() { const modal = this; if (!modal.type || !modal.$el) return; openedModals.splice(openedModals.indexOf(modal), 1); $('html').removeClass(`with-modal-${modal.type.toLowerCase()}`); modal.$el.trigger(`modal:close ${modal.type.toLowerCase()}:close`, modal); modal.emit(`local::close modalClose ${modal.type}Close`, modal); } onClosed() { const modal = this; if (!modal.type || !modal.$el) return; modal.$el.removeClass('modal-out'); modal.$el.hide(); modal.$el.trigger(`modal:closed ${modal.type.toLowerCase()}:closed`, modal); modal.emit(`local::closed modalClosed ${modal.type}Closed`, modal); } open(animateModal) { const modal = this; const app = modal.app; const $el = modal.$el; const $backdropEl = modal.$backdropEl; const type = modal.type; let animate = true; if (typeof animateModal !== 'undefined') animate = animateModal; else if (typeof modal.params.animate !== 'undefined') { animate = modal.params.animate; } if (!$el || $el.hasClass('modal-in')) { return modal; } if (type === 'dialog' && app.params.modal.queueDialogs) { let pushToQueue; if ($('.dialog.modal-in').length > 0) { pushToQueue = true; } else if (openedModals.length > 0) { openedModals.forEach((openedModal) => { if (openedModal.type === 'dialog') pushToQueue = true; }); } if (pushToQueue) { dialogsQueue.push(modal); return modal; } } const $modalParentEl = $el.parent(); const wasInDom = $el.parents(document).length > 0; if (app.params.modal.moveToRoot && !$modalParentEl.is(app.root)) { app.root.append($el); modal.once(`${type}Closed`, () => { if (wasInDom) { $modalParentEl.append($el); } else { $el.remove(); } }); } // Show Modal $el.show(); // Set Dialog offset if (type === 'dialog') { $el.css({ marginTop: `${-Math.round($el.outerHeight() / 2)}px`, }); } // Emit open /* eslint no-underscore-dangle: ["error", { "allow": ["_clientLeft"] }] */ modal._clientLeft = $el[0].clientLeft; // Backdrop if ($backdropEl) { $backdropEl[animate ? 'removeClass' : 'addClass']('not-animated'); $backdropEl.addClass('backdrop-in'); } // Modal function transitionEnd() { if ($el.hasClass('modal-out')) { modal.onClosed(); } else { modal.onOpened(); } } if (animate) { $el .animationEnd(() => { transitionEnd(); }); $el .transitionEnd(() => { transitionEnd(); }); $el .removeClass('modal-out not-animated') .addClass('modal-in'); modal.onOpen(); } else { $el.removeClass('modal-out').addClass('modal-in not-animated'); modal.onOpen(); modal.onOpened(); } return modal; } close(animateModal) { const modal = this; const $el = modal.$el; const $backdropEl = modal.$backdropEl; let animate = true; if (typeof animateModal !== 'undefined') animate = animateModal; else if (typeof modal.params.animate !== 'undefined') { animate = modal.params.animate; } if (!$el || !$el.hasClass('modal-in')) { return modal; } // backdrop if ($backdropEl) { $backdropEl[animate ? 'removeClass' : 'addClass']('not-animated'); $backdropEl.removeClass('backdrop-in'); } // Modal $el[animate ? 'removeClass' : 'addClass']('not-animated'); function transitionEnd() { if ($el.hasClass('modal-out')) { modal.onClosed(); } else { modal.onOpened(); } } if (animate) { $el .animationEnd(() => { transitionEnd(); }); $el .transitionEnd(() => { transitionEnd(); }); $el .removeClass('modal-in') .addClass('modal-out'); // Emit close modal.onClose(); } else { $el .addClass('not-animated') .removeClass('modal-in') .addClass('modal-out'); // Emit close modal.onClose(); modal.onClosed(); } if (modal.type === 'dialog') { clearDialogsQueue(); } return modal; } destroy() { const modal = this; if (modal.destroyed) return; modal.emit(`local::beforeDestroy modalBeforeDestroy ${modal.type}BeforeDestroy`, modal); if (modal.$el) { modal.$el.trigger(`modal:beforedestroy ${modal.type.toLowerCase()}:beforedestroy`, modal); if (modal.$el.length && modal.$el[0].f7Modal) { delete modal.$el[0].f7Modal; } } Utils.deleteProps(modal); modal.destroyed = true; } } export default Modal;