simplyview 2.1.1 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/simply.app.js +1120 -0
- package/dist/simply.app.js.map +7 -0
- package/dist/simply.app.min.js +2 -0
- package/dist/simply.app.min.js.map +7 -0
- package/dist/simply.everything.js +1583 -2013
- package/dist/simply.everything.js.map +7 -0
- package/dist/simply.everything.min.js +2 -0
- package/dist/simply.everything.min.js.map +7 -0
- package/package.json +10 -4
- package/src/action.mjs +12 -0
- package/src/activate.mjs +63 -0
- package/src/app.mjs +40 -0
- package/src/bind.mjs +572 -0
- package/src/changes.md +18 -0
- package/src/command.mjs +125 -0
- package/src/everything.mjs +27 -0
- package/src/include.mjs +191 -0
- package/src/key.mjs +55 -0
- package/src/model.mjs +151 -0
- package/src/route.mjs +222 -0
- package/src/state.mjs +536 -0
- package/js/.eslintrc.json +0 -29
- package/js/simply.action.js +0 -115
- package/js/simply.activate.js +0 -79
- package/js/simply.api.js +0 -228
- package/js/simply.app.js +0 -63
- package/js/simply.collect.js +0 -72
- package/js/simply.command.js +0 -196
- package/js/simply.include.js +0 -216
- package/js/simply.keyboard.js +0 -62
- package/js/simply.modules.js +0 -22
- package/js/simply.observe.js +0 -349
- package/js/simply.path.js +0 -48
- package/js/simply.render.js +0 -125
- package/js/simply.resize.js +0 -80
- package/js/simply.route.js +0 -234
- package/js/simply.view.js +0 -35
- package/js/simply.viewmodel.js +0 -189
- /package/{js/simply.include.next.js → src/include.next.js} +0 -0
package/src/route.mjs
ADDED
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
export function routes(options) {
|
|
2
|
+
return new SimplyRoute(options)
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
class SimplyRoute {
|
|
6
|
+
constructor(options={}) {
|
|
7
|
+
this.root = options.root || '/'
|
|
8
|
+
this.app = options.app
|
|
9
|
+
this.clear()
|
|
10
|
+
if (options.routes) {
|
|
11
|
+
this.load(options.routes)
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
load(routes) {
|
|
16
|
+
parseRoutes(routes, this.routeInfo)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
clear() {
|
|
20
|
+
this.routeInfo = []
|
|
21
|
+
this.listeners = {
|
|
22
|
+
match: {},
|
|
23
|
+
call: {},
|
|
24
|
+
finish: {}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
match(path, options) {
|
|
29
|
+
let args = {
|
|
30
|
+
path,
|
|
31
|
+
options
|
|
32
|
+
}
|
|
33
|
+
args = this.runListeners('match',args)
|
|
34
|
+
path = args.path ? args.path : path;
|
|
35
|
+
|
|
36
|
+
let matches;
|
|
37
|
+
if (!path) {
|
|
38
|
+
if (this.match(document.location.pathname+document.location.hash)) {
|
|
39
|
+
return true;
|
|
40
|
+
} else {
|
|
41
|
+
return this.match(document.location.pathname);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
path = getPath(path);
|
|
45
|
+
for ( let route of this.routeInfo) {
|
|
46
|
+
matches = route.match.exec(path)
|
|
47
|
+
if (matches && matches.length) {
|
|
48
|
+
var params = {};
|
|
49
|
+
route.params.forEach((key, i) => {
|
|
50
|
+
if (key=='*') {
|
|
51
|
+
key = 'remainder'
|
|
52
|
+
}
|
|
53
|
+
params[key] = matches[i+1]
|
|
54
|
+
})
|
|
55
|
+
Object.assign(params, options)
|
|
56
|
+
args.route = route
|
|
57
|
+
args.params = params
|
|
58
|
+
args = this.runListeners('call', args)
|
|
59
|
+
params = args.params ? args.params : params
|
|
60
|
+
args.result = route.action.call(route, params)
|
|
61
|
+
this.runListeners('finish', args)
|
|
62
|
+
return args.result
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (path && path[path.length-1]!='/') {
|
|
66
|
+
return this.match(path+'/', options)
|
|
67
|
+
}
|
|
68
|
+
return false
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
runListeners(action, params) {
|
|
72
|
+
if (!Object.keys(this.listeners[action])) {
|
|
73
|
+
return
|
|
74
|
+
}
|
|
75
|
+
Object.keys(this.listeners[action]).forEach((route) => {
|
|
76
|
+
var routeRe = getRegexpFromRoute(route);
|
|
77
|
+
if (routeRe.exec(params.path)) {
|
|
78
|
+
var result;
|
|
79
|
+
for (let callback of this.listeners[action][route]) {
|
|
80
|
+
result = callback.call(this.app, params)
|
|
81
|
+
if (result) {
|
|
82
|
+
params = result
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
})
|
|
87
|
+
return params
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
handleEvents() {
|
|
91
|
+
globalThis.addEventListener('popstate', () => {
|
|
92
|
+
if (this.match(getPath(document.location.pathname + document.location.hash, this.root)) === false) {
|
|
93
|
+
this.match(getPath(document.location.pathname, this.root))
|
|
94
|
+
}
|
|
95
|
+
})
|
|
96
|
+
globalThis.document.addEventListener('click', (evt) => {
|
|
97
|
+
if (evt.ctrlKey) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
if (evt.which != 1) {
|
|
101
|
+
return; // not a 'left' mouse click
|
|
102
|
+
}
|
|
103
|
+
var link = evt.target;
|
|
104
|
+
while (link && link.tagName!='A') {
|
|
105
|
+
link = link.parentElement;
|
|
106
|
+
}
|
|
107
|
+
if (link
|
|
108
|
+
&& link.pathname
|
|
109
|
+
&& link.hostname==globalThis.location.hostname
|
|
110
|
+
&& !link.link
|
|
111
|
+
&& !link.dataset.simplyCommand
|
|
112
|
+
) {
|
|
113
|
+
let path = getPath(link.pathname+link.hash, this.root);
|
|
114
|
+
if ( !this.has(path) ) {
|
|
115
|
+
path = getPath(link.pathname, this.root);
|
|
116
|
+
}
|
|
117
|
+
if ( this.has(path) ) {
|
|
118
|
+
let params = this.runListeners('goto', { path: path});
|
|
119
|
+
if (params.path) {
|
|
120
|
+
this.goto(params.path);
|
|
121
|
+
}
|
|
122
|
+
evt.preventDefault();
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
})
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
goto(path) {
|
|
130
|
+
history.pushState({},'',getURL(path))
|
|
131
|
+
return this.match(path)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
has(path) {
|
|
135
|
+
path = getPath(path, this.root)
|
|
136
|
+
for (let route of this.routeInfo) {
|
|
137
|
+
var matches = route.match.exec(path)
|
|
138
|
+
if (matches && matches.length) {
|
|
139
|
+
return true
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return false
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
addListener(action, route, callback) {
|
|
146
|
+
if (['goto','match','call','finish'].indexOf(action)==-1) {
|
|
147
|
+
throw new Error('Unknown action '+action)
|
|
148
|
+
}
|
|
149
|
+
if (!this.listeners[action][route]) {
|
|
150
|
+
this.listeners[action][route] = []
|
|
151
|
+
}
|
|
152
|
+
this.listeners[action][route].push(callback)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
removeListener(action, route, callback) {
|
|
156
|
+
if (['match','call','finish'].indexOf(action)==-1) {
|
|
157
|
+
throw new Error('Unknown action '+action)
|
|
158
|
+
}
|
|
159
|
+
if (!this.listeners[action][route]) {
|
|
160
|
+
return
|
|
161
|
+
}
|
|
162
|
+
this.listeners[action][route] = this.listeners[action][route].filter((listener) => {
|
|
163
|
+
return listener != callback
|
|
164
|
+
})
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
init(options) {
|
|
168
|
+
if (options.root) {
|
|
169
|
+
this.root = options.root
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function getPath(path, root='/') {
|
|
175
|
+
if (path.substring(0,root.length)==root
|
|
176
|
+
||
|
|
177
|
+
( root[root.length-1]=='/'
|
|
178
|
+
&& path.length==(root.length-1)
|
|
179
|
+
&& path == root.substring(0,path.length)
|
|
180
|
+
)
|
|
181
|
+
) {
|
|
182
|
+
path = path.substring(root.length)
|
|
183
|
+
}
|
|
184
|
+
if (path[0]!='/' && path[0]!='#') {
|
|
185
|
+
path = '/'+path
|
|
186
|
+
}
|
|
187
|
+
return path
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function getURL(path, root) {
|
|
191
|
+
path = getPath(path, root)
|
|
192
|
+
if (root[root.length-1]==='/' && path[0]==='/') {
|
|
193
|
+
path = path.substring(1)
|
|
194
|
+
}
|
|
195
|
+
return root + path;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function getRegexpFromRoute(route) {
|
|
199
|
+
return new RegExp('^'+route.replace(/:\w+/g, '([^/]+)').replace(/:\*/, '(.*)'));
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function parseRoutes(routes) {
|
|
203
|
+
let routeInfo = []
|
|
204
|
+
const paths = Object.keys(routes)
|
|
205
|
+
const matchParams = /:(\w+|\*)/g
|
|
206
|
+
for (let path of paths) {
|
|
207
|
+
let matches = []
|
|
208
|
+
let params = []
|
|
209
|
+
do {
|
|
210
|
+
matches = matchParams.exec(path)
|
|
211
|
+
if (matches) {
|
|
212
|
+
params.push(matches[1])
|
|
213
|
+
}
|
|
214
|
+
} while(matches)
|
|
215
|
+
routeInfo.push({
|
|
216
|
+
match: getRegexpFromRoute(path),
|
|
217
|
+
params: params,
|
|
218
|
+
action: routes[path]
|
|
219
|
+
})
|
|
220
|
+
}
|
|
221
|
+
return routeInfo
|
|
222
|
+
}
|