framework7
Version:
Full featured mobile HTML framework for building iOS & Android apps
143 lines (131 loc) • 3.8 kB
JavaScript
import { window, document } from 'ssr-window';
import $ from 'dom7';
import Utils from './utils';
const History = {
queue: [],
clearQueue() {
if (History.queue.length === 0) return;
const currentQueue = History.queue.shift();
currentQueue();
},
routerQueue: [],
clearRouterQueue() {
if (History.routerQueue.length === 0) return;
const currentQueue = History.routerQueue.pop();
const { router, stateUrl, action } = currentQueue;
let animate = router.params.animate;
if (router.params.pushStateAnimate === false) animate = false;
if (action === 'back') {
router.back({ animate, pushState: false });
}
if (action === 'load') {
router.navigate(stateUrl, { animate, pushState: false });
}
},
handle(e) {
if (History.blockPopstate) return;
const app = this;
// const mainView = app.views.main;
let state = e.state;
History.previousState = History.state;
History.state = state;
History.allowChange = true;
History.clearQueue();
state = History.state;
if (!state) state = {};
app.views.forEach((view) => {
const router = view.router;
let viewState = state[view.id];
if (!viewState && view.params.pushState) {
viewState = {
url: view.router.history[0],
};
}
if (!viewState) return;
const stateUrl = viewState.url || undefined;
let animate = router.params.animate;
if (router.params.pushStateAnimate === false) animate = false;
if (stateUrl !== router.url) {
if (router.history.indexOf(stateUrl) >= 0) {
// Go Back
if (router.allowPageChange) {
router.back({ animate, pushState: false });
} else {
History.routerQueue.push({
action: 'back',
router,
});
}
} else if (router.allowPageChange) {
// Load page
router.navigate(stateUrl, { animate, pushState: false });
} else {
History.routerQueue.unshift({
action: 'load',
stateUrl,
router,
});
}
}
});
},
initViewState(viewId, viewState) {
const newState = Utils.extend({}, (History.state || {}), {
[viewId]: viewState,
});
History.state = newState;
window.history.replaceState(newState, '');
},
push(viewId, viewState, url) {
if (!History.allowChange) {
History.queue.push(() => {
History.push(viewId, viewState, url);
});
return;
}
History.previousState = History.state;
const newState = Utils.extend({}, (History.previousState || {}), {
[viewId]: viewState,
});
History.state = newState;
window.history.pushState(newState, '', url);
},
replace(viewId, viewState, url) {
if (!History.allowChange) {
History.queue.push(() => {
History.replace(viewId, viewState, url);
});
return;
}
History.previousState = History.state;
const newState = Utils.extend({}, (History.previousState || {}), {
[viewId]: viewState,
});
History.state = newState;
window.history.replaceState(newState, '', url);
},
go(index) {
History.allowChange = false;
window.history.go(index);
},
back() {
History.allowChange = false;
window.history.back();
},
allowChange: true,
previousState: {},
state: window.history.state,
blockPopstate: true,
init(app) {
$(window).on('load', () => {
setTimeout(() => {
History.blockPopstate = false;
}, 0);
});
if (document.readyState && document.readyState === 'complete') {
History.blockPopstate = false;
}
$(window).on('popstate', History.handle.bind(app));
},
};
export default History;