framework7
Version:
Full featured mobile HTML framework for building iOS & Android apps
223 lines (215 loc) • 6.69 kB
JavaScript
import { extend, nextTick } from '../../shared/utils.js';
import History from '../../shared/history.js';
import asyncComponent from './async-component.js';
function modalLoad(modalType, route, loadOptions, direction) {
if (loadOptions === void 0) {
loadOptions = {};
}
const router = this;
const app = router.app;
const isPanel = modalType === 'panel';
const modalOrPanel = isPanel ? 'panel' : 'modal';
const options = extend({
animate: router.params.animate,
browserHistory: true,
history: true,
on: {},
once: {}
}, loadOptions);
const modalParams = extend({}, route.route[modalType]);
const modalRoute = route.route;
const routeCallback = (modal, name) => {
const {
on,
once
} = options;
let callback;
if (name === 'open') {
callback = on.modalOpen || once.modalOpen || on.panelOpen || once.panelOpen;
}
if (name === 'close') {
callback = on.modalClose || once.modalClose || on.panelClose || once.panelClose;
}
if (name === 'closed') {
callback = on.modalClosed || once.modalClosed || on.panelClosed || once.panelClosed;
}
if (callback) callback(modal);
};
function onModalLoaded() {
// Create Modal
const modal = app[modalType].create(modalParams);
modalRoute.modalInstance = modal;
const hasEl = modal.el;
function closeOnSwipeBack() {
modal.close();
}
modal.on(`${modalOrPanel}Open`, () => {
if (!hasEl) {
// Remove theme elements
router.removeThemeElements(modal.el);
// Emit events
modal.$el.trigger(`${modalType.toLowerCase()}:init ${modalType.toLowerCase()}:mounted`, route, modal);
router.emit(`${!isPanel ? 'modalInit' : ''} ${modalType}Init ${modalType}Mounted`, modal.el, route, modal);
}
router.once('swipeBackMove', closeOnSwipeBack);
routeCallback(modal, 'open');
});
modal.on(`${modalOrPanel}Close`, () => {
router.off('swipeBackMove', closeOnSwipeBack);
if (!modal.closeByRouter) {
router.back();
}
routeCallback(modal, 'close');
});
modal.on(`${modalOrPanel}Closed`, () => {
modal.$el.trigger(`${modalType.toLowerCase()}:beforeremove`, route, modal);
modal.emit(`${!isPanel ? 'modalBeforeRemove ' : ''}${modalType}BeforeRemove`, modal.el, route, modal);
const modalComponent = modal.el.f7Component;
routeCallback(modal, 'closed');
if (modalComponent) {
modalComponent.destroy();
}
nextTick(() => {
if (modalComponent || modalParams.component || modalParams.asyncComponent || modalParams.async) {
router.removeModal(modal.el);
}
modal.destroy();
delete modal.route;
delete modalRoute.modalInstance;
});
});
if (options.route) {
// Update Browser History
if (router.params.browserHistory && options.browserHistory) {
History.push(router.view.id, {
url: options.route.url,
modal: modalType
}, (router.params.browserHistoryRoot || '') + router.params.browserHistorySeparator + options.route.url);
}
// Set Route
if (options.route !== router.currentRoute) {
modal.route = extend(options.route, {
modal
});
router.currentRoute = modal.route;
}
// Update Router History
if (options.history && !options.reloadCurrent) {
router.history.push(options.route.url);
router.saveHistory();
}
}
if (hasEl) {
// Remove theme elements
router.removeThemeElements(modal.el);
// Emit events
modal.$el.trigger(`${modalType.toLowerCase()}:init ${modalType.toLowerCase()}:mounted`, route, modal);
router.emit(`${modalOrPanel}Init ${modalType}Init ${modalType}Mounted`, modal.el, route, modal);
}
// Open
modal.open(options.animate === false || options.animate === true ? options.animate : undefined);
}
// Load Modal Content
function loadModal(loadModalParams, loadModalOptions) {
// Load Modal Props
const {
url,
content,
component,
componentUrl
} = loadModalParams;
// Component/Template Callbacks
function resolve(contentEl) {
if (contentEl) {
if (typeof contentEl === 'string') {
modalParams.content = contentEl;
} else if (contentEl.f7Component) {
contentEl.f7Component.mount(componentEl => {
modalParams.el = componentEl;
app.$el.append(componentEl);
});
} else {
modalParams.el = contentEl;
}
onModalLoaded();
}
}
function reject() {
router.allowPageChange = true;
return router;
}
if (content) {
resolve(content);
} else if (component || componentUrl) {
// Load from component (F7/Vue/React/...)
try {
router.modalComponentLoader({
rootEl: app.el,
component,
componentUrl,
options: loadModalOptions,
resolve,
reject
});
} catch (err) {
router.allowPageChange = true;
throw err;
}
} else if (url) {
// Load using XHR
if (router.xhrAbortController) {
router.xhrAbortController.abort();
router.xhrAbortController = false;
}
router.xhrRequest(url, loadModalOptions).then(modalContent => {
modalParams.content = modalContent;
onModalLoaded();
}).catch(() => {
router.allowPageChange = true;
});
} else {
onModalLoaded();
}
}
let foundLoadProp;
'url content component el componentUrl template'.split(' ').forEach(modalLoadProp => {
if (modalParams[modalLoadProp] && !foundLoadProp) {
foundLoadProp = true;
loadModal({
[modalLoadProp]: modalParams[modalLoadProp]
}, options);
}
});
if (!foundLoadProp && modalType === 'actions') {
onModalLoaded();
}
// Async
function asyncResolve(resolveParams, resolveOptions) {
loadModal(resolveParams, extend(options, resolveOptions));
}
function asyncReject() {
router.allowPageChange = true;
}
if (modalParams.async) {
modalParams.async.call(router, {
router,
to: options.route,
from: router.currentRoute,
resolve: asyncResolve,
reject: asyncReject,
direction,
app
});
}
if (modalParams.asyncComponent) {
asyncComponent(router, modalParams.asyncComponent, asyncResolve, asyncReject);
}
return router;
}
function modalRemove(modal) {
extend(modal, {
closeByRouter: true
});
modal.close();
}
export { modalLoad, modalRemove };