-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPage.js
More file actions
138 lines (131 loc) · 5.14 KB
/
Page.js
File metadata and controls
138 lines (131 loc) · 5.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import { MCComponent } from "./Component.js";
import { edm } from "./EventDispatcher.js";
import { FSM } from "./FiniteStateMachine.js";
edm.getOrNewEventDispatcher("mc.preload")
.addEventListener("done", () => {
// 设一层空的历史记录作为拦截
history.pushState(null, document.title);
// 如果点击了历史回退或手机上按了返回按钮
window.addEventListener("popstate", e => {
// 把退掉的空历史记录再加回去
history.pushState(null, document.title);
// 在 window 上发送 back 事件
window.dispatchEvent(new Event("back"));
}, false);
// 当接收到 exit 事件则绕过上面的拦截,视为真正的回退
window.addEventListener("exit", e => {
history.go(-2);
});
}, { once: true, });
class PageManager extends FSM {
constructor() {
super({
id: "pageManager",
initial: "preload",
});
edm.addEventDispatcher("mc.page", this);
};
getCurrentPage() { return document.body.lastChild; };
getPageByID(pageID) {
pageID = "mcpage-" + pageID;
let page = [...document.body.childNodes].reverse().find(page => page.pageID == pageID);
return page || null;
};
openPageByID(pageID, ...data) {
if (pageID === "*pop") return this.closeCurrentPage();
let currentPage = this.getCurrentPage();
let page = document.createElement("mcpage-" + pageID);
document.body.appendChild(page);
this.dispatchEvent("opened", page, ...data);
this.transition(pageID, currentPage, page, ...data);
return page;
};
closePage(pageID, ...data) {
if (pageID === "*pop") return this.closeCurrentPage(...data);
let page = this.getPageByID(pageID);
if (!page) return null;
if (page === this.getCurrentPage()) return this.closeCurrentPage(...data);
document.body.removeChild(page);
this.dispatchEvent("closed", page, ...data);
return page;
};
closeCurrentPage(...data) {
let page = this.getCurrentPage();
document.body.removeChild(page);
this.dispatchEvent("closed", page, ...data);
let nowPage = this.getCurrentPage();
this.transition(nowPage.shortPageID, page, nowPage, ...data);
return page;
};
};
const pageManager = new PageManager();
let pageStyle = document.createElement("style");
pageStyle.innerHTML = `
:host {
width: 100vw;
height: 100vh;
position: absolute;
top: 0; left: 0;
}
`;
pageStyle.id = "pageStyle";
class Page extends MCComponent {
static get pm() { return pageManager; };
static get pageManager() { return pageManager; };
static get shortPageID() { return super.componentName.replace(/-page$/, ""); };
static get pageID() { return "mcpage-" + this.shortPageID; };
static get componentName() { return this.pageID; };
static get templateUrlPrefix() { return "./"; };
static get outdegree() { return []; };
get shortPageID() { return this.constructor.shortPageID; };
get pageID() { return this.constructor.pageID; };
get outdegree() { return this.constructor.outdegree; };
constructor() {
super();
if (new.target.name === "Page")
throw "Class 'Page' cannot be instantiated!";
pageManager.addTransitions(this.outdegree.map(to => ({
from: this.shortPageID, to,
})));
this.onHistoryBack = this.onHistoryBack.bind(this);
this._transitionedCallbackID =
pageManager.addEventListener("transitioned", (from, to, eventName, fromPage, toPage, ...data) => {
this.onTransitioned(from, to, eventName, fromPage, toPage, ...data);
if (fromPage === this) {
this.onTransitionedFromThis(to, eventName, toPage, ...data);
window.removeEventListener("back", this.onHistoryBack);
}
else if (toPage === this) {
this.onTransitionedToThis(from, eventName, fromPage, ...data);
window.addEventListener("back", this.onHistoryBack);
}
});
};
onTransitioned(from, to, eventName, fromPage, toPage, ...data) {};
onTransitionedFromThis(to, eventName, toPage, ...data) {};
onTransitionedToThis(from, eventName, fromPage, ...data) {};
onHistoryBack() {};
async disconnectedCallback() {
await super.disconnectedCallback();
pageManager.removeEventListenerByID(this._transitionedCallbackID);
window.removeEventListener("back", this.onHistoryBack);
};
appendTemplate(template = this.template) {
let tmp = super.appendTemplate(template);
if (!tmp) return;
this.shadowRoot.prepend(pageStyle.cloneNode(true));
customElements.whenDefined("mc-full-screen-button").then(_ => {
this.shadowRoot.append(document.createElement("mc-full-screen-button"));
});
return tmp;
};
close(...data) {
// pageManager.dispatchEvent("close", this);
// this.parentElement.removeChild(this);
pageManager.closePage(this.shortPageID, ...data);
};
};
export {
Page,
pageManager, pageManager as pm,
};