ganeshpl-mithril_rails 1.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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/Rakefile +32 -0
- data/app/assets/javascripts/MSXTransformer.js +15920 -0
- data/app/assets/javascripts/mithril.js +1160 -0
- data/app/assets/javascripts/mithril_ujs.js +93 -0
- data/app/helpers/mithril_helper.rb +14 -0
- data/lib/mithril_rails.rb +2 -0
- data/lib/mithril_rails/msx.rb +31 -0
- data/lib/mithril_rails/msx/template.rb +17 -0
- data/lib/mithril_rails/rails.rb +2 -0
- data/lib/mithril_rails/rails/engine.rb +9 -0
- data/lib/mithril_rails/rails/railtie.rb +10 -0
- data/lib/mithril_rails/version.rb +3 -0
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +15 -0
- data/test/dummy/app/controllers/application_controller.rb +5 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +23 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +37 -0
- data/test/dummy/config/environments/production.rb +83 -0
- data/test/dummy/config/environments/test.rb +39 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +56 -0
- data/test/dummy/config/secrets.yml +22 -0
- data/test/dummy/public/404.html +67 -0
- data/test/dummy/public/422.html +67 -0
- data/test/dummy/public/500.html +66 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/mithril_rails_test.rb +7 -0
- data/test/test_helper.rb +15 -0
- metadata +183 -0
@@ -0,0 +1,1160 @@
|
|
1
|
+
new function() {
|
2
|
+
|
3
|
+
function Vnode(tag, key, attrs0, children, text, dom) {
|
4
|
+
return {tag: tag, key: key, attrs: attrs0, children: children, text: text, dom: dom, domSize: undefined, state: {}, events: undefined, instance: undefined, skip: false}
|
5
|
+
}
|
6
|
+
Vnode.normalize = function(node) {
|
7
|
+
if (Array.isArray(node)) return Vnode("[", undefined, undefined, Vnode.normalizeChildren(node), undefined, undefined)
|
8
|
+
if (node != null && typeof node !== "object") return Vnode("#", undefined, undefined, node === false ? "" : node, undefined, undefined)
|
9
|
+
return node
|
10
|
+
}
|
11
|
+
Vnode.normalizeChildren = function normalizeChildren(children) {
|
12
|
+
for (var i = 0; i < children.length; i++) {
|
13
|
+
children[i] = Vnode.normalize(children[i])
|
14
|
+
}
|
15
|
+
return children
|
16
|
+
}
|
17
|
+
var selectorParser = /(?:(^|#|\.)([^#\.\[\]]+))|(\[(.+?)(?:\s*=\s*("|'|)((?:\\["'\]]|.)*?)\5)?\])/g
|
18
|
+
var selectorCache = {}
|
19
|
+
function hyperscript(selector) {
|
20
|
+
if (selector == null || typeof selector !== "string" && typeof selector.view !== "function") {
|
21
|
+
throw Error("The selector must be either a string or a component.");
|
22
|
+
}
|
23
|
+
if (typeof selector === "string" && selectorCache[selector] === undefined) {
|
24
|
+
var match, tag, classes = [], attributes = {}
|
25
|
+
while (match = selectorParser.exec(selector)) {
|
26
|
+
var type = match[1], value = match[2]
|
27
|
+
if (type === "" && value !== "") tag = value
|
28
|
+
else if (type === "#") attributes.id = value
|
29
|
+
else if (type === ".") classes.push(value)
|
30
|
+
else if (match[3][0] === "[") {
|
31
|
+
var attrValue = match[6]
|
32
|
+
if (attrValue) attrValue = attrValue.replace(/\\(["'])/g, "$1").replace(/\\\\/g, "\\")
|
33
|
+
if (match[4] === "class") classes.push(attrValue)
|
34
|
+
else attributes[match[4]] = attrValue || true
|
35
|
+
}
|
36
|
+
}
|
37
|
+
if (classes.length > 0) attributes.className = classes.join(" ")
|
38
|
+
selectorCache[selector] = function(attrs, children) {
|
39
|
+
var hasAttrs = false, childList, text
|
40
|
+
var className = attrs.className || attrs.class
|
41
|
+
for (var key in attributes) attrs[key] = attributes[key]
|
42
|
+
if (className !== undefined) {
|
43
|
+
if (attrs.class !== undefined) {
|
44
|
+
attrs.class = undefined
|
45
|
+
attrs.className = className
|
46
|
+
}
|
47
|
+
if (attributes.className !== undefined) attrs.className = attributes.className + " " + className
|
48
|
+
}
|
49
|
+
for (var key in attrs) {
|
50
|
+
if (key !== "key") {
|
51
|
+
hasAttrs = true
|
52
|
+
break
|
53
|
+
}
|
54
|
+
}
|
55
|
+
if (Array.isArray(children) && children.length == 1 && children[0] != null && children[0].tag === "#") text = children[0].children
|
56
|
+
else childList = children
|
57
|
+
return Vnode(tag || "div", attrs.key, hasAttrs ? attrs : undefined, childList, text, undefined)
|
58
|
+
}
|
59
|
+
}
|
60
|
+
var attrs, children, childrenIndex
|
61
|
+
if (arguments[1] == null || typeof arguments[1] === "object" && arguments[1].tag === undefined && !Array.isArray(arguments[1])) {
|
62
|
+
attrs = arguments[1]
|
63
|
+
childrenIndex = 2
|
64
|
+
}
|
65
|
+
else childrenIndex = 1
|
66
|
+
if (arguments.length === childrenIndex + 1) {
|
67
|
+
children = Array.isArray(arguments[childrenIndex]) ? arguments[childrenIndex] : [arguments[childrenIndex]]
|
68
|
+
}
|
69
|
+
else {
|
70
|
+
children = []
|
71
|
+
for (var i = childrenIndex; i < arguments.length; i++) children.push(arguments[i])
|
72
|
+
}
|
73
|
+
if (typeof selector === "string") return selectorCache[selector](attrs || {}, Vnode.normalizeChildren(children))
|
74
|
+
return Vnode(selector, attrs && attrs.key, attrs || {}, Vnode.normalizeChildren(children), undefined, undefined)
|
75
|
+
}
|
76
|
+
hyperscript.trust = function(html) {
|
77
|
+
if (html == null) html = ""
|
78
|
+
return Vnode("<", undefined, undefined, html, undefined, undefined)
|
79
|
+
}
|
80
|
+
hyperscript.fragment = function(attrs1, children) {
|
81
|
+
return Vnode("[", attrs1.key, attrs1, Vnode.normalizeChildren(children), undefined, undefined)
|
82
|
+
}
|
83
|
+
var m = hyperscript
|
84
|
+
/** @constructor */
|
85
|
+
var PromisePolyfill = function(executor) {
|
86
|
+
if (!(this instanceof PromisePolyfill)) throw new Error("Promise must be called with `new`")
|
87
|
+
if (typeof executor !== "function") throw new TypeError("executor must be a function")
|
88
|
+
var self = this, resolvers = [], rejectors = [], resolveCurrent = handler(resolvers, true), rejectCurrent = handler(rejectors, false)
|
89
|
+
var instance = self._instance = {resolvers: resolvers, rejectors: rejectors}
|
90
|
+
var callAsync = typeof setImmediate === "function" ? setImmediate : setTimeout
|
91
|
+
function handler(list, shouldAbsorb) {
|
92
|
+
return function execute(value) {
|
93
|
+
var then
|
94
|
+
try {
|
95
|
+
if (shouldAbsorb && value != null && (typeof value === "object" || typeof value === "function") && typeof (then = value.then) === "function") {
|
96
|
+
if (value === self) throw new TypeError("Promise can't be resolved w/ itself")
|
97
|
+
executeOnce(then.bind(value))
|
98
|
+
}
|
99
|
+
else {
|
100
|
+
callAsync(function() {
|
101
|
+
if (!shouldAbsorb && list.length === 0) console.error("Possible unhandled promise rejection:", value)
|
102
|
+
for (var i = 0; i < list.length; i++) list[i](value)
|
103
|
+
resolvers.length = 0, rejectors.length = 0
|
104
|
+
instance.state = shouldAbsorb
|
105
|
+
instance.retry = function() {execute(value)}
|
106
|
+
})
|
107
|
+
}
|
108
|
+
}
|
109
|
+
catch (e) {
|
110
|
+
rejectCurrent(e)
|
111
|
+
}
|
112
|
+
}
|
113
|
+
}
|
114
|
+
function executeOnce(then) {
|
115
|
+
var runs = 0
|
116
|
+
function run(fn) {
|
117
|
+
return function(value) {
|
118
|
+
if (runs++ > 0) return
|
119
|
+
fn(value)
|
120
|
+
}
|
121
|
+
}
|
122
|
+
var onerror = run(rejectCurrent)
|
123
|
+
try {then(run(resolveCurrent), onerror)} catch (e) {onerror(e)}
|
124
|
+
}
|
125
|
+
executeOnce(executor)
|
126
|
+
}
|
127
|
+
PromisePolyfill.prototype.then = function(onFulfilled, onRejection) {
|
128
|
+
var self = this, instance = self._instance
|
129
|
+
function handle(callback, list, next, state) {
|
130
|
+
list.push(function(value) {
|
131
|
+
if (typeof callback !== "function") next(value)
|
132
|
+
else try {resolveNext(callback(value))} catch (e) {if (rejectNext) rejectNext(e)}
|
133
|
+
})
|
134
|
+
if (typeof instance.retry === "function" && state === instance.state) instance.retry()
|
135
|
+
}
|
136
|
+
var resolveNext, rejectNext
|
137
|
+
var promise = new PromisePolyfill(function(resolve, reject) {resolveNext = resolve, rejectNext = reject})
|
138
|
+
handle(onFulfilled, instance.resolvers, resolveNext, true), handle(onRejection, instance.rejectors, rejectNext, false)
|
139
|
+
return promise
|
140
|
+
}
|
141
|
+
PromisePolyfill.prototype.catch = function(onRejection) {
|
142
|
+
return this.then(null, onRejection)
|
143
|
+
}
|
144
|
+
PromisePolyfill.resolve = function(value) {
|
145
|
+
if (value instanceof PromisePolyfill) return value
|
146
|
+
return new PromisePolyfill(function(resolve) {resolve(value)})
|
147
|
+
}
|
148
|
+
PromisePolyfill.reject = function(value) {
|
149
|
+
return new PromisePolyfill(function(resolve, reject) {reject(value)})
|
150
|
+
}
|
151
|
+
PromisePolyfill.all = function(list) {
|
152
|
+
return new PromisePolyfill(function(resolve, reject) {
|
153
|
+
var total = list.length, count = 0, values = []
|
154
|
+
if (list.length === 0) resolve([])
|
155
|
+
else for (var i = 0; i < list.length; i++) {
|
156
|
+
(function(i) {
|
157
|
+
function consume(value) {
|
158
|
+
count++
|
159
|
+
values[i] = value
|
160
|
+
if (count === total) resolve(values)
|
161
|
+
}
|
162
|
+
if (list[i] != null && (typeof list[i] === "object" || typeof list[i] === "function") && typeof list[i].then === "function") {
|
163
|
+
list[i].then(consume, reject)
|
164
|
+
}
|
165
|
+
else consume(list[i])
|
166
|
+
})(i)
|
167
|
+
}
|
168
|
+
})
|
169
|
+
}
|
170
|
+
PromisePolyfill.race = function(list) {
|
171
|
+
return new PromisePolyfill(function(resolve, reject) {
|
172
|
+
for (var i = 0; i < list.length; i++) {
|
173
|
+
list[i].then(resolve, reject)
|
174
|
+
}
|
175
|
+
})
|
176
|
+
}
|
177
|
+
if (typeof window !== "undefined") {
|
178
|
+
if (typeof window.Promise === "undefined") window.Promise = PromisePolyfill
|
179
|
+
var PromisePolyfill = window.Promise
|
180
|
+
} else if (typeof global !== "undefined") {
|
181
|
+
if (typeof global.Promise === "undefined") global.Promise = PromisePolyfill
|
182
|
+
var PromisePolyfill = global.Promise
|
183
|
+
} else {
|
184
|
+
}
|
185
|
+
var buildQueryString = function(object) {
|
186
|
+
if (Object.prototype.toString.call(object) !== "[object Object]") return ""
|
187
|
+
var args = []
|
188
|
+
for (var key0 in object) {
|
189
|
+
destructure(key0, object[key0])
|
190
|
+
}
|
191
|
+
return args.join("&")
|
192
|
+
function destructure(key0, value) {
|
193
|
+
if (Array.isArray(value)) {
|
194
|
+
for (var i = 0; i < value.length; i++) {
|
195
|
+
destructure(key0 + "[" + i + "]", value[i])
|
196
|
+
}
|
197
|
+
}
|
198
|
+
else if (Object.prototype.toString.call(value) === "[object Object]") {
|
199
|
+
for (var i in value) {
|
200
|
+
destructure(key0 + "[" + i + "]", value[i])
|
201
|
+
}
|
202
|
+
}
|
203
|
+
else args.push(encodeURIComponent(key0) + (value != null && value !== "" ? "=" + encodeURIComponent(value) : ""))
|
204
|
+
}
|
205
|
+
}
|
206
|
+
var _8 = function($window, Promise) {
|
207
|
+
var callbackCount = 0
|
208
|
+
var oncompletion
|
209
|
+
function setCompletionCallback(callback) {oncompletion = callback}
|
210
|
+
function finalizer() {
|
211
|
+
var count = 0
|
212
|
+
function complete() {if (--count === 0 && typeof oncompletion === "function") oncompletion()}
|
213
|
+
return function finalize(promise0) {
|
214
|
+
var then0 = promise0.then
|
215
|
+
promise0.then = function() {
|
216
|
+
count++
|
217
|
+
var next = then0.apply(promise0, arguments)
|
218
|
+
next.then(complete, function(e) {
|
219
|
+
complete()
|
220
|
+
if (count === 0) throw e
|
221
|
+
})
|
222
|
+
return finalize(next)
|
223
|
+
}
|
224
|
+
return promise0
|
225
|
+
}
|
226
|
+
}
|
227
|
+
function normalize(args, extra) {
|
228
|
+
if (typeof args === "string") {
|
229
|
+
var url = args
|
230
|
+
args = extra || {}
|
231
|
+
if (args.url == null) args.url = url
|
232
|
+
}
|
233
|
+
return args
|
234
|
+
}
|
235
|
+
function request(args, extra) {
|
236
|
+
var finalize = finalizer()
|
237
|
+
args = normalize(args, extra)
|
238
|
+
var promise0 = new Promise(function(resolve, reject) {
|
239
|
+
if (args.method == null) args.method = "GET"
|
240
|
+
args.method = args.method.toUpperCase()
|
241
|
+
var useBody = typeof args.useBody === "boolean" ? args.useBody : args.method !== "GET" && args.method !== "TRACE"
|
242
|
+
if (typeof args.serialize !== "function") args.serialize = typeof FormData !== "undefined" && args.data instanceof FormData ? function(value) {return value} : JSON.stringify
|
243
|
+
if (typeof args.deserialize !== "function") args.deserialize = deserialize
|
244
|
+
if (typeof args.extract !== "function") args.extract = extract
|
245
|
+
args.url = interpolate(args.url, args.data)
|
246
|
+
if (useBody) args.data = args.serialize(args.data)
|
247
|
+
else args.url = assemble(args.url, args.data)
|
248
|
+
var xhr = new $window.XMLHttpRequest()
|
249
|
+
xhr.open(args.method, args.url, typeof args.async === "boolean" ? args.async : true, typeof args.user === "string" ? args.user : undefined, typeof args.password === "string" ? args.password : undefined)
|
250
|
+
if (args.serialize === JSON.stringify && useBody) {
|
251
|
+
xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8")
|
252
|
+
}
|
253
|
+
if (args.deserialize === deserialize) {
|
254
|
+
xhr.setRequestHeader("Accept", "application/json, text/*")
|
255
|
+
}
|
256
|
+
if (args.withCredentials) xhr.withCredentials = args.withCredentials
|
257
|
+
for (var key in args.headers) if ({}.hasOwnProperty.call(args.headers, key)) {
|
258
|
+
xhr.setRequestHeader(key, args.headers[key])
|
259
|
+
}
|
260
|
+
if (typeof args.config === "function") xhr = args.config(xhr, args) || xhr
|
261
|
+
xhr.onreadystatechange = function() {
|
262
|
+
// Don't throw errors on xhr.abort(). XMLHttpRequests ends up in a state of
|
263
|
+
// xhr.status == 0 and xhr.readyState == 4 if aborted after open, but before completion.
|
264
|
+
if (xhr.status && xhr.readyState === 4) {
|
265
|
+
try {
|
266
|
+
var response = (args.extract !== extract) ? args.extract(xhr, args) : args.deserialize(args.extract(xhr, args))
|
267
|
+
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
|
268
|
+
resolve(cast(args.type, response))
|
269
|
+
}
|
270
|
+
else {
|
271
|
+
var error = new Error(xhr.responseText)
|
272
|
+
for (var key in response) error[key] = response[key]
|
273
|
+
reject(error)
|
274
|
+
}
|
275
|
+
}
|
276
|
+
catch (e) {
|
277
|
+
reject(e)
|
278
|
+
}
|
279
|
+
}
|
280
|
+
}
|
281
|
+
if (useBody && (args.data != null)) xhr.send(args.data)
|
282
|
+
else xhr.send()
|
283
|
+
})
|
284
|
+
return args.background === true ? promise0 : finalize(promise0)
|
285
|
+
}
|
286
|
+
function jsonp(args, extra) {
|
287
|
+
var finalize = finalizer()
|
288
|
+
args = normalize(args, extra)
|
289
|
+
var promise0 = new Promise(function(resolve, reject) {
|
290
|
+
var callbackName = args.callbackName || "_mithril_" + Math.round(Math.random() * 1e16) + "_" + callbackCount++
|
291
|
+
var script = $window.document.createElement("script")
|
292
|
+
$window[callbackName] = function(data) {
|
293
|
+
script.parentNode.removeChild(script)
|
294
|
+
resolve(cast(args.type, data))
|
295
|
+
delete $window[callbackName]
|
296
|
+
}
|
297
|
+
script.onerror = function() {
|
298
|
+
script.parentNode.removeChild(script)
|
299
|
+
reject(new Error("JSONP request failed"))
|
300
|
+
delete $window[callbackName]
|
301
|
+
}
|
302
|
+
if (args.data == null) args.data = {}
|
303
|
+
args.url = interpolate(args.url, args.data)
|
304
|
+
args.data[args.callbackKey || "callback"] = callbackName
|
305
|
+
script.src = assemble(args.url, args.data)
|
306
|
+
$window.document.documentElement.appendChild(script)
|
307
|
+
})
|
308
|
+
return args.background === true? promise0 : finalize(promise0)
|
309
|
+
}
|
310
|
+
function interpolate(url, data) {
|
311
|
+
if (data == null) return url
|
312
|
+
var tokens = url.match(/:[^\/]+/gi) || []
|
313
|
+
for (var i = 0; i < tokens.length; i++) {
|
314
|
+
var key = tokens[i].slice(1)
|
315
|
+
if (data[key] != null) {
|
316
|
+
url = url.replace(tokens[i], data[key])
|
317
|
+
}
|
318
|
+
}
|
319
|
+
return url
|
320
|
+
}
|
321
|
+
function assemble(url, data) {
|
322
|
+
var querystring = buildQueryString(data)
|
323
|
+
if (querystring !== "") {
|
324
|
+
var prefix = url.indexOf("?") < 0 ? "?" : "&"
|
325
|
+
url += prefix + querystring
|
326
|
+
}
|
327
|
+
return url
|
328
|
+
}
|
329
|
+
function deserialize(data) {
|
330
|
+
try {return data !== "" ? JSON.parse(data) : null}
|
331
|
+
catch (e) {throw new Error(data)}
|
332
|
+
}
|
333
|
+
function extract(xhr) {return xhr.responseText}
|
334
|
+
function cast(type0, data) {
|
335
|
+
if (typeof type0 === "function") {
|
336
|
+
if (Array.isArray(data)) {
|
337
|
+
for (var i = 0; i < data.length; i++) {
|
338
|
+
data[i] = new type0(data[i])
|
339
|
+
}
|
340
|
+
}
|
341
|
+
else return new type0(data)
|
342
|
+
}
|
343
|
+
return data
|
344
|
+
}
|
345
|
+
return {request: request, jsonp: jsonp, setCompletionCallback: setCompletionCallback}
|
346
|
+
}
|
347
|
+
var requestService = _8(window, PromisePolyfill)
|
348
|
+
var coreRenderer = function($window) {
|
349
|
+
var $doc = $window.document
|
350
|
+
var $emptyFragment = $doc.createDocumentFragment()
|
351
|
+
var onevent
|
352
|
+
function setEventCallback(callback) {return onevent = callback}
|
353
|
+
//create
|
354
|
+
function createNodes(parent, vnodes, start, end, hooks, nextSibling, ns) {
|
355
|
+
for (var i = start; i < end; i++) {
|
356
|
+
var vnode = vnodes[i]
|
357
|
+
if (vnode != null) {
|
358
|
+
insertNode(parent, createNode(vnode, hooks, ns), nextSibling)
|
359
|
+
}
|
360
|
+
}
|
361
|
+
}
|
362
|
+
function createNode(vnode, hooks, ns) {
|
363
|
+
var tag = vnode.tag
|
364
|
+
if (vnode.attrs != null) initLifecycle(vnode.attrs, vnode, hooks)
|
365
|
+
if (typeof tag === "string") {
|
366
|
+
switch (tag) {
|
367
|
+
case "#": return createText(vnode)
|
368
|
+
case "<": return createHTML(vnode)
|
369
|
+
case "[": return createFragment(vnode, hooks, ns)
|
370
|
+
default: return createElement(vnode, hooks, ns)
|
371
|
+
}
|
372
|
+
}
|
373
|
+
else return createComponent(vnode, hooks, ns)
|
374
|
+
}
|
375
|
+
function createText(vnode) {
|
376
|
+
return vnode.dom = $doc.createTextNode(vnode.children)
|
377
|
+
}
|
378
|
+
function createHTML(vnode) {
|
379
|
+
var match1 = vnode.children.match(/^\s*?<(\w+)/im) || []
|
380
|
+
var parent = {caption: "table", thead: "table", tbody: "table", tfoot: "table", tr: "tbody", th: "tr", td: "tr", colgroup: "table", col: "colgroup"}[match1[1]] || "div"
|
381
|
+
var temp = $doc.createElement(parent)
|
382
|
+
temp.innerHTML = vnode.children
|
383
|
+
vnode.dom = temp.firstChild
|
384
|
+
vnode.domSize = temp.childNodes.length
|
385
|
+
var fragment = $doc.createDocumentFragment()
|
386
|
+
var child
|
387
|
+
while (child = temp.firstChild) {
|
388
|
+
fragment.appendChild(child)
|
389
|
+
}
|
390
|
+
return fragment
|
391
|
+
}
|
392
|
+
function createFragment(vnode, hooks, ns) {
|
393
|
+
var fragment = $doc.createDocumentFragment()
|
394
|
+
if (vnode.children != null) {
|
395
|
+
var children = vnode.children
|
396
|
+
createNodes(fragment, children, 0, children.length, hooks, null, ns)
|
397
|
+
}
|
398
|
+
vnode.dom = fragment.firstChild
|
399
|
+
vnode.domSize = fragment.childNodes.length
|
400
|
+
return fragment
|
401
|
+
}
|
402
|
+
function createElement(vnode, hooks, ns) {
|
403
|
+
var tag = vnode.tag
|
404
|
+
switch (vnode.tag) {
|
405
|
+
case "svg": ns = "http://www.w3.org/2000/svg"; break
|
406
|
+
case "math": ns = "http://www.w3.org/1998/Math/MathML"; break
|
407
|
+
}
|
408
|
+
var attrs2 = vnode.attrs
|
409
|
+
var is = attrs2 && attrs2.is
|
410
|
+
var element = ns ?
|
411
|
+
is ? $doc.createElementNS(ns, tag, {is: is}) : $doc.createElementNS(ns, tag) :
|
412
|
+
is ? $doc.createElement(tag, {is: is}) : $doc.createElement(tag)
|
413
|
+
vnode.dom = element
|
414
|
+
if (attrs2 != null) {
|
415
|
+
setAttrs(vnode, attrs2, ns)
|
416
|
+
}
|
417
|
+
if (vnode.attrs != null && vnode.attrs.contenteditable != null) {
|
418
|
+
setContentEditable(vnode)
|
419
|
+
}
|
420
|
+
else {
|
421
|
+
if (vnode.text != null) {
|
422
|
+
if (vnode.text !== "") element.textContent = vnode.text
|
423
|
+
else vnode.children = [Vnode("#", undefined, undefined, vnode.text, undefined, undefined)]
|
424
|
+
}
|
425
|
+
if (vnode.children != null) {
|
426
|
+
var children = vnode.children
|
427
|
+
createNodes(element, children, 0, children.length, hooks, null, ns)
|
428
|
+
setLateAttrs(vnode)
|
429
|
+
}
|
430
|
+
}
|
431
|
+
return element
|
432
|
+
}
|
433
|
+
function createComponent(vnode, hooks, ns) {
|
434
|
+
vnode.state = Object.create(vnode.tag)
|
435
|
+
var view = vnode.tag.view
|
436
|
+
if (view.reentrantLock != null) return $emptyFragment
|
437
|
+
view.reentrantLock = true
|
438
|
+
initLifecycle(vnode.tag, vnode, hooks)
|
439
|
+
vnode.instance = Vnode.normalize(view.call(vnode.state, vnode))
|
440
|
+
view.reentrantLock = null
|
441
|
+
if (vnode.instance != null) {
|
442
|
+
if (vnode.instance === vnode) throw Error("A view cannot return the vnode it received as arguments")
|
443
|
+
var element = createNode(vnode.instance, hooks, ns)
|
444
|
+
vnode.dom = vnode.instance.dom
|
445
|
+
vnode.domSize = vnode.dom != null ? vnode.instance.domSize : 0
|
446
|
+
return element
|
447
|
+
}
|
448
|
+
else {
|
449
|
+
vnode.domSize = 0
|
450
|
+
return $emptyFragment
|
451
|
+
}
|
452
|
+
}
|
453
|
+
//update
|
454
|
+
function updateNodes(parent, old, vnodes, hooks, nextSibling, ns) {
|
455
|
+
if (old === vnodes || old == null && vnodes == null) return
|
456
|
+
else if (old == null) createNodes(parent, vnodes, 0, vnodes.length, hooks, nextSibling, undefined)
|
457
|
+
else if (vnodes == null) removeNodes(old, 0, old.length, vnodes)
|
458
|
+
else {
|
459
|
+
if (old.length === vnodes.length) {
|
460
|
+
var isUnkeyed = false
|
461
|
+
for (var i = 0; i < vnodes.length; i++) {
|
462
|
+
if (vnodes[i] != null && old[i] != null) {
|
463
|
+
isUnkeyed = vnodes[i].key == null && old[i].key == null
|
464
|
+
break
|
465
|
+
}
|
466
|
+
}
|
467
|
+
if (isUnkeyed) {
|
468
|
+
for (var i = 0; i < old.length; i++) {
|
469
|
+
if (old[i] === vnodes[i]) continue
|
470
|
+
else if (old[i] == null && vnodes[i] != null) insertNode(parent, createNode(vnodes[i], hooks, ns), getNextSibling(old, i + 1, nextSibling))
|
471
|
+
else if (vnodes[i] == null) removeNodes(old, i, i + 1, vnodes)
|
472
|
+
else updateNode(parent, old[i], vnodes[i], hooks, getNextSibling(old, i + 1, nextSibling), false, ns)
|
473
|
+
}
|
474
|
+
return
|
475
|
+
}
|
476
|
+
}
|
477
|
+
var recycling = isRecyclable(old, vnodes)
|
478
|
+
if (recycling) old = old.concat(old.pool)
|
479
|
+
var oldStart = 0, start = 0, oldEnd = old.length - 1, end = vnodes.length - 1, map
|
480
|
+
while (oldEnd >= oldStart && end >= start) {
|
481
|
+
var o = old[oldStart], v = vnodes[start]
|
482
|
+
if (o === v && !recycling) oldStart++, start++
|
483
|
+
else if (o == null) oldStart++
|
484
|
+
else if (v == null) start++
|
485
|
+
else if (o.key === v.key) {
|
486
|
+
oldStart++, start++
|
487
|
+
updateNode(parent, o, v, hooks, getNextSibling(old, oldStart, nextSibling), recycling, ns)
|
488
|
+
if (recycling && o.tag === v.tag) insertNode(parent, toFragment(o), nextSibling)
|
489
|
+
}
|
490
|
+
else {
|
491
|
+
var o = old[oldEnd]
|
492
|
+
if (o === v && !recycling) oldEnd--, start++
|
493
|
+
else if (o == null) oldEnd--
|
494
|
+
else if (v == null) start++
|
495
|
+
else if (o.key === v.key) {
|
496
|
+
updateNode(parent, o, v, hooks, getNextSibling(old, oldEnd + 1, nextSibling), recycling, ns)
|
497
|
+
if (recycling || start < end) insertNode(parent, toFragment(o), getNextSibling(old, oldStart, nextSibling))
|
498
|
+
oldEnd--, start++
|
499
|
+
}
|
500
|
+
else break
|
501
|
+
}
|
502
|
+
}
|
503
|
+
while (oldEnd >= oldStart && end >= start) {
|
504
|
+
var o = old[oldEnd], v = vnodes[end]
|
505
|
+
if (o === v && !recycling) oldEnd--, end--
|
506
|
+
else if (o == null) oldEnd--
|
507
|
+
else if (v == null) end--
|
508
|
+
else if (o.key === v.key) {
|
509
|
+
updateNode(parent, o, v, hooks, getNextSibling(old, oldEnd + 1, nextSibling), recycling, ns)
|
510
|
+
if (recycling && o.tag === v.tag) insertNode(parent, toFragment(o), nextSibling)
|
511
|
+
if (o.dom != null) nextSibling = o.dom
|
512
|
+
oldEnd--, end--
|
513
|
+
}
|
514
|
+
else {
|
515
|
+
if (!map) map = getKeyMap(old, oldEnd)
|
516
|
+
if (v != null) {
|
517
|
+
var oldIndex = map[v.key]
|
518
|
+
if (oldIndex != null) {
|
519
|
+
var movable = old[oldIndex]
|
520
|
+
updateNode(parent, movable, v, hooks, getNextSibling(old, oldEnd + 1, nextSibling), recycling, ns)
|
521
|
+
insertNode(parent, toFragment(movable), nextSibling)
|
522
|
+
old[oldIndex].skip = true
|
523
|
+
if (movable.dom != null) nextSibling = movable.dom
|
524
|
+
}
|
525
|
+
else {
|
526
|
+
var dom = createNode(v, hooks, undefined)
|
527
|
+
insertNode(parent, dom, nextSibling)
|
528
|
+
nextSibling = dom
|
529
|
+
}
|
530
|
+
}
|
531
|
+
end--
|
532
|
+
}
|
533
|
+
if (end < start) break
|
534
|
+
}
|
535
|
+
createNodes(parent, vnodes, start, end + 1, hooks, nextSibling, ns)
|
536
|
+
removeNodes(old, oldStart, oldEnd + 1, vnodes)
|
537
|
+
}
|
538
|
+
}
|
539
|
+
function updateNode(parent, old, vnode, hooks, nextSibling, recycling, ns) {
|
540
|
+
var oldTag = old.tag, tag = vnode.tag
|
541
|
+
if (oldTag === tag) {
|
542
|
+
vnode.state = old.state
|
543
|
+
vnode.events = old.events
|
544
|
+
if (shouldUpdate(vnode, old)) return
|
545
|
+
if (vnode.attrs != null) {
|
546
|
+
updateLifecycle(vnode.attrs, vnode, hooks, recycling)
|
547
|
+
}
|
548
|
+
if (typeof oldTag === "string") {
|
549
|
+
switch (oldTag) {
|
550
|
+
case "#": updateText(old, vnode); break
|
551
|
+
case "<": updateHTML(parent, old, vnode, nextSibling); break
|
552
|
+
case "[": updateFragment(parent, old, vnode, hooks, nextSibling, ns); break
|
553
|
+
default: updateElement(old, vnode, hooks, ns)
|
554
|
+
}
|
555
|
+
}
|
556
|
+
else updateComponent(parent, old, vnode, hooks, nextSibling, recycling, ns)
|
557
|
+
}
|
558
|
+
else {
|
559
|
+
removeNode(old, null)
|
560
|
+
insertNode(parent, createNode(vnode, hooks, ns), nextSibling)
|
561
|
+
}
|
562
|
+
}
|
563
|
+
function updateText(old, vnode) {
|
564
|
+
if (old.children.toString() !== vnode.children.toString()) {
|
565
|
+
old.dom.nodeValue = vnode.children
|
566
|
+
}
|
567
|
+
vnode.dom = old.dom
|
568
|
+
}
|
569
|
+
function updateHTML(parent, old, vnode, nextSibling) {
|
570
|
+
if (old.children !== vnode.children) {
|
571
|
+
toFragment(old)
|
572
|
+
insertNode(parent, createHTML(vnode), nextSibling)
|
573
|
+
}
|
574
|
+
else vnode.dom = old.dom, vnode.domSize = old.domSize
|
575
|
+
}
|
576
|
+
function updateFragment(parent, old, vnode, hooks, nextSibling, ns) {
|
577
|
+
updateNodes(parent, old.children, vnode.children, hooks, nextSibling, ns)
|
578
|
+
var domSize = 0, children = vnode.children
|
579
|
+
vnode.dom = null
|
580
|
+
if (children != null) {
|
581
|
+
for (var i = 0; i < children.length; i++) {
|
582
|
+
var child = children[i]
|
583
|
+
if (child != null && child.dom != null) {
|
584
|
+
if (vnode.dom == null) vnode.dom = child.dom
|
585
|
+
domSize += child.domSize || 1
|
586
|
+
}
|
587
|
+
}
|
588
|
+
if (domSize !== 1) vnode.domSize = domSize
|
589
|
+
}
|
590
|
+
}
|
591
|
+
function updateElement(old, vnode, hooks, ns) {
|
592
|
+
var element = vnode.dom = old.dom
|
593
|
+
switch (vnode.tag) {
|
594
|
+
case "svg": ns = "http://www.w3.org/2000/svg"; break
|
595
|
+
case "math": ns = "http://www.w3.org/1998/Math/MathML"; break
|
596
|
+
}
|
597
|
+
if (vnode.tag === "textarea") {
|
598
|
+
if (vnode.attrs == null) vnode.attrs = {}
|
599
|
+
if (vnode.text != null) {
|
600
|
+
vnode.attrs.value = vnode.text //FIXME handle0 multiple children
|
601
|
+
vnode.text = undefined
|
602
|
+
}
|
603
|
+
}
|
604
|
+
updateAttrs(vnode, old.attrs, vnode.attrs, ns)
|
605
|
+
if (vnode.attrs != null && vnode.attrs.contenteditable != null) {
|
606
|
+
setContentEditable(vnode)
|
607
|
+
}
|
608
|
+
else if (old.text != null && vnode.text != null && vnode.text !== "") {
|
609
|
+
if (old.text.toString() !== vnode.text.toString()) old.dom.firstChild.nodeValue = vnode.text
|
610
|
+
}
|
611
|
+
else {
|
612
|
+
if (old.text != null) old.children = [Vnode("#", undefined, undefined, old.text, undefined, old.dom.firstChild)]
|
613
|
+
if (vnode.text != null) vnode.children = [Vnode("#", undefined, undefined, vnode.text, undefined, undefined)]
|
614
|
+
updateNodes(element, old.children, vnode.children, hooks, null, ns)
|
615
|
+
}
|
616
|
+
}
|
617
|
+
function updateComponent(parent, old, vnode, hooks, nextSibling, recycling, ns) {
|
618
|
+
vnode.instance = Vnode.normalize(vnode.tag.view.call(vnode.state, vnode))
|
619
|
+
updateLifecycle(vnode.tag, vnode, hooks, recycling)
|
620
|
+
if (vnode.instance != null) {
|
621
|
+
if (old.instance == null) insertNode(parent, createNode(vnode.instance, hooks, ns), nextSibling)
|
622
|
+
else updateNode(parent, old.instance, vnode.instance, hooks, nextSibling, recycling, ns)
|
623
|
+
vnode.dom = vnode.instance.dom
|
624
|
+
vnode.domSize = vnode.instance.domSize
|
625
|
+
}
|
626
|
+
else if (old.instance != null) {
|
627
|
+
removeNode(old.instance, null)
|
628
|
+
vnode.dom = undefined
|
629
|
+
vnode.domSize = 0
|
630
|
+
}
|
631
|
+
else {
|
632
|
+
vnode.dom = old.dom
|
633
|
+
vnode.domSize = old.domSize
|
634
|
+
}
|
635
|
+
}
|
636
|
+
function isRecyclable(old, vnodes) {
|
637
|
+
if (old.pool != null && Math.abs(old.pool.length - vnodes.length) <= Math.abs(old.length - vnodes.length)) {
|
638
|
+
var oldChildrenLength = old[0] && old[0].children && old[0].children.length || 0
|
639
|
+
var poolChildrenLength = old.pool[0] && old.pool[0].children && old.pool[0].children.length || 0
|
640
|
+
var vnodesChildrenLength = vnodes[0] && vnodes[0].children && vnodes[0].children.length || 0
|
641
|
+
if (Math.abs(poolChildrenLength - vnodesChildrenLength) <= Math.abs(oldChildrenLength - vnodesChildrenLength)) {
|
642
|
+
return true
|
643
|
+
}
|
644
|
+
}
|
645
|
+
return false
|
646
|
+
}
|
647
|
+
function getKeyMap(vnodes, end) {
|
648
|
+
var map = {}, i = 0
|
649
|
+
for (var i = 0; i < end; i++) {
|
650
|
+
var vnode = vnodes[i]
|
651
|
+
if (vnode != null) {
|
652
|
+
var key2 = vnode.key
|
653
|
+
if (key2 != null) map[key2] = i
|
654
|
+
}
|
655
|
+
}
|
656
|
+
return map
|
657
|
+
}
|
658
|
+
function toFragment(vnode) {
|
659
|
+
var count0 = vnode.domSize
|
660
|
+
if (count0 != null || vnode.dom == null) {
|
661
|
+
var fragment = $doc.createDocumentFragment()
|
662
|
+
if (count0 > 0) {
|
663
|
+
var dom = vnode.dom
|
664
|
+
while (--count0) fragment.appendChild(dom.nextSibling)
|
665
|
+
fragment.insertBefore(dom, fragment.firstChild)
|
666
|
+
}
|
667
|
+
return fragment
|
668
|
+
}
|
669
|
+
else return vnode.dom
|
670
|
+
}
|
671
|
+
function getNextSibling(vnodes, i, nextSibling) {
|
672
|
+
for (; i < vnodes.length; i++) {
|
673
|
+
if (vnodes[i] != null && vnodes[i].dom != null) return vnodes[i].dom
|
674
|
+
}
|
675
|
+
return nextSibling
|
676
|
+
}
|
677
|
+
function insertNode(parent, dom, nextSibling) {
|
678
|
+
if (nextSibling && nextSibling.parentNode) parent.insertBefore(dom, nextSibling)
|
679
|
+
else parent.appendChild(dom)
|
680
|
+
}
|
681
|
+
function setContentEditable(vnode) {
|
682
|
+
var children = vnode.children
|
683
|
+
if (children != null && children.length === 1 && children[0].tag === "<") {
|
684
|
+
var content = children[0].children
|
685
|
+
if (vnode.dom.innerHTML !== content) vnode.dom.innerHTML = content
|
686
|
+
}
|
687
|
+
else if (vnode.text != null || children != null && children.length !== 0) throw new Error("Child node of a contenteditable must be trusted")
|
688
|
+
}
|
689
|
+
//remove
|
690
|
+
function removeNodes(vnodes, start, end, context) {
|
691
|
+
for (var i = start; i < end; i++) {
|
692
|
+
var vnode = vnodes[i]
|
693
|
+
if (vnode != null) {
|
694
|
+
if (vnode.skip) vnode.skip = false
|
695
|
+
else removeNode(vnode, context)
|
696
|
+
}
|
697
|
+
}
|
698
|
+
}
|
699
|
+
function removeNode(vnode, context) {
|
700
|
+
var expected = 1, called = 0
|
701
|
+
if (vnode.attrs && vnode.attrs.onbeforeremove) {
|
702
|
+
var result = vnode.attrs.onbeforeremove.call(vnode.state, vnode)
|
703
|
+
if (result != null && typeof result.then === "function") {
|
704
|
+
expected++
|
705
|
+
result.then(continuation, continuation)
|
706
|
+
}
|
707
|
+
}
|
708
|
+
if (typeof vnode.tag !== "string" && vnode.tag.onbeforeremove) {
|
709
|
+
var result = vnode.tag.onbeforeremove.call(vnode.state, vnode)
|
710
|
+
if (result != null && typeof result.then === "function") {
|
711
|
+
expected++
|
712
|
+
result.then(continuation, continuation)
|
713
|
+
}
|
714
|
+
}
|
715
|
+
continuation()
|
716
|
+
function continuation() {
|
717
|
+
if (++called === expected) {
|
718
|
+
onremove(vnode)
|
719
|
+
if (vnode.dom) {
|
720
|
+
var count0 = vnode.domSize || 1
|
721
|
+
if (count0 > 1) {
|
722
|
+
var dom = vnode.dom
|
723
|
+
while (--count0) {
|
724
|
+
removeNodeFromDOM(dom.nextSibling)
|
725
|
+
}
|
726
|
+
}
|
727
|
+
removeNodeFromDOM(vnode.dom)
|
728
|
+
if (context != null && vnode.domSize == null && !hasIntegrationMethods(vnode.attrs) && typeof vnode.tag === "string") { //TODO test custom elements
|
729
|
+
if (!context.pool) context.pool = [vnode]
|
730
|
+
else context.pool.push(vnode)
|
731
|
+
}
|
732
|
+
}
|
733
|
+
}
|
734
|
+
}
|
735
|
+
}
|
736
|
+
function removeNodeFromDOM(node) {
|
737
|
+
var parent = node.parentNode
|
738
|
+
if (parent != null) parent.removeChild(node)
|
739
|
+
}
|
740
|
+
function onremove(vnode) {
|
741
|
+
if (vnode.attrs && vnode.attrs.onremove) vnode.attrs.onremove.call(vnode.state, vnode)
|
742
|
+
if (typeof vnode.tag !== "string" && vnode.tag.onremove) vnode.tag.onremove.call(vnode.state, vnode)
|
743
|
+
if (vnode.instance != null) onremove(vnode.instance)
|
744
|
+
else {
|
745
|
+
var children = vnode.children
|
746
|
+
if (Array.isArray(children)) {
|
747
|
+
for (var i = 0; i < children.length; i++) {
|
748
|
+
var child = children[i]
|
749
|
+
if (child != null) onremove(child)
|
750
|
+
}
|
751
|
+
}
|
752
|
+
}
|
753
|
+
}
|
754
|
+
//attrs2
|
755
|
+
function setAttrs(vnode, attrs2, ns) {
|
756
|
+
for (var key2 in attrs2) {
|
757
|
+
setAttr(vnode, key2, null, attrs2[key2], ns)
|
758
|
+
}
|
759
|
+
}
|
760
|
+
function setAttr(vnode, key2, old, value, ns) {
|
761
|
+
var element = vnode.dom
|
762
|
+
if (key2 === "key" || key2 === "is" || (old === value && !isFormAttribute(vnode, key2)) && typeof value !== "object" || typeof value === "undefined" || isLifecycleMethod(key2)) return
|
763
|
+
var nsLastIndex = key2.indexOf(":")
|
764
|
+
if (nsLastIndex > -1 && key2.substr(0, nsLastIndex) === "xlink") {
|
765
|
+
element.setAttributeNS("http://www.w3.org/1999/xlink", key2.slice(nsLastIndex + 1), value)
|
766
|
+
}
|
767
|
+
else if (key2[0] === "o" && key2[1] === "n" && typeof value === "function") updateEvent(vnode, key2, value)
|
768
|
+
else if (key2 === "style") updateStyle(element, old, value)
|
769
|
+
else if (key2 in element && !isAttribute(key2) && ns === undefined && !isCustomElement(vnode)) {
|
770
|
+
//setting input[value] to same value by typing on focused element moves cursor to end in Chrome
|
771
|
+
if (vnode.tag === "input" && key2 === "value" && vnode.dom.value === value && vnode.dom === $doc.activeElement) return
|
772
|
+
//setting select[value] to same value while having select open blinks select dropdown in Chrome
|
773
|
+
if (vnode.tag === "select" && key2 === "value" && vnode.dom.value === value && vnode.dom === $doc.activeElement) return
|
774
|
+
//setting option[value] to same value while having select open blinks select dropdown in Chrome
|
775
|
+
if (vnode.tag === "option" && key2 === "value" && vnode.dom.value === value) return
|
776
|
+
element[key2] = value
|
777
|
+
}
|
778
|
+
else {
|
779
|
+
if (typeof value === "boolean") {
|
780
|
+
if (value) element.setAttribute(key2, "")
|
781
|
+
else element.removeAttribute(key2)
|
782
|
+
}
|
783
|
+
else element.setAttribute(key2 === "className" ? "class" : key2, value)
|
784
|
+
}
|
785
|
+
}
|
786
|
+
function setLateAttrs(vnode) {
|
787
|
+
var attrs2 = vnode.attrs
|
788
|
+
if (vnode.tag === "select" && attrs2 != null) {
|
789
|
+
if ("value" in attrs2) setAttr(vnode, "value", null, attrs2.value, undefined)
|
790
|
+
if ("selectedIndex" in attrs2) setAttr(vnode, "selectedIndex", null, attrs2.selectedIndex, undefined)
|
791
|
+
}
|
792
|
+
}
|
793
|
+
function updateAttrs(vnode, old, attrs2, ns) {
|
794
|
+
if (attrs2 != null) {
|
795
|
+
for (var key2 in attrs2) {
|
796
|
+
setAttr(vnode, key2, old && old[key2], attrs2[key2], ns)
|
797
|
+
}
|
798
|
+
}
|
799
|
+
if (old != null) {
|
800
|
+
for (var key2 in old) {
|
801
|
+
if (attrs2 == null || !(key2 in attrs2)) {
|
802
|
+
if (key2 === "className") key2 = "class"
|
803
|
+
if (key2[0] === "o" && key2[1] === "n" && !isLifecycleMethod(key2)) updateEvent(vnode, key2, undefined)
|
804
|
+
else if (key2 !== "key") vnode.dom.removeAttribute(key2)
|
805
|
+
}
|
806
|
+
}
|
807
|
+
}
|
808
|
+
}
|
809
|
+
function isFormAttribute(vnode, attr) {
|
810
|
+
return attr === "value" || attr === "checked" || attr === "selectedIndex" || attr === "selected" && vnode.dom === $doc.activeElement
|
811
|
+
}
|
812
|
+
function isLifecycleMethod(attr) {
|
813
|
+
return attr === "oninit" || attr === "oncreate" || attr === "onupdate" || attr === "onremove" || attr === "onbeforeremove" || attr === "onbeforeupdate"
|
814
|
+
}
|
815
|
+
function isAttribute(attr) {
|
816
|
+
return attr === "href" || attr === "list" || attr === "form" || attr === "width" || attr === "height"// || attr === "type"
|
817
|
+
}
|
818
|
+
function isCustomElement(vnode){
|
819
|
+
return vnode.attrs.is || vnode.tag.indexOf("-") > -1
|
820
|
+
}
|
821
|
+
function hasIntegrationMethods(source) {
|
822
|
+
return source != null && (source.oncreate || source.onupdate || source.onbeforeremove || source.onremove)
|
823
|
+
}
|
824
|
+
//style
|
825
|
+
function updateStyle(element, old, style) {
|
826
|
+
if (old === style) element.style.cssText = "", old = null
|
827
|
+
if (style == null) element.style.cssText = ""
|
828
|
+
else if (typeof style === "string") element.style.cssText = style
|
829
|
+
else {
|
830
|
+
if (typeof old === "string") element.style.cssText = ""
|
831
|
+
for (var key2 in style) {
|
832
|
+
element.style[key2] = style[key2]
|
833
|
+
}
|
834
|
+
if (old != null && typeof old !== "string") {
|
835
|
+
for (var key2 in old) {
|
836
|
+
if (!(key2 in style)) element.style[key2] = ""
|
837
|
+
}
|
838
|
+
}
|
839
|
+
}
|
840
|
+
}
|
841
|
+
//event
|
842
|
+
function updateEvent(vnode, key2, value) {
|
843
|
+
var element = vnode.dom
|
844
|
+
var callback = typeof onevent !== "function" ? value : function(e) {
|
845
|
+
var result = value.call(element, e)
|
846
|
+
onevent.call(element, e)
|
847
|
+
return result
|
848
|
+
}
|
849
|
+
if (key2 in element) element[key2] = typeof value === "function" ? callback : null
|
850
|
+
else {
|
851
|
+
var eventName = key2.slice(2)
|
852
|
+
if (vnode.events === undefined) vnode.events = {}
|
853
|
+
if (vnode.events[key2] === callback) return
|
854
|
+
if (vnode.events[key2] != null) element.removeEventListener(eventName, vnode.events[key2], false)
|
855
|
+
if (typeof value === "function") {
|
856
|
+
vnode.events[key2] = callback
|
857
|
+
element.addEventListener(eventName, vnode.events[key2], false)
|
858
|
+
}
|
859
|
+
}
|
860
|
+
}
|
861
|
+
//lifecycle
|
862
|
+
function initLifecycle(source, vnode, hooks) {
|
863
|
+
if (typeof source.oninit === "function") source.oninit.call(vnode.state, vnode)
|
864
|
+
if (typeof source.oncreate === "function") hooks.push(source.oncreate.bind(vnode.state, vnode))
|
865
|
+
}
|
866
|
+
function updateLifecycle(source, vnode, hooks, recycling) {
|
867
|
+
if (recycling) initLifecycle(source, vnode, hooks)
|
868
|
+
else if (typeof source.onupdate === "function") hooks.push(source.onupdate.bind(vnode.state, vnode))
|
869
|
+
}
|
870
|
+
function shouldUpdate(vnode, old) {
|
871
|
+
var forceVnodeUpdate, forceComponentUpdate
|
872
|
+
if (vnode.attrs != null && typeof vnode.attrs.onbeforeupdate === "function") forceVnodeUpdate = vnode.attrs.onbeforeupdate.call(vnode.state, vnode, old)
|
873
|
+
if (typeof vnode.tag !== "string" && typeof vnode.tag.onbeforeupdate === "function") forceComponentUpdate = vnode.tag.onbeforeupdate.call(vnode.state, vnode, old)
|
874
|
+
if (!(forceVnodeUpdate === undefined && forceComponentUpdate === undefined) && !forceVnodeUpdate && !forceComponentUpdate) {
|
875
|
+
vnode.dom = old.dom
|
876
|
+
vnode.domSize = old.domSize
|
877
|
+
vnode.instance = old.instance
|
878
|
+
return true
|
879
|
+
}
|
880
|
+
return false
|
881
|
+
}
|
882
|
+
function render(dom, vnodes) {
|
883
|
+
if (!dom) throw new Error("Ensure the DOM element being passed to m.route/m.mount/m.render is not undefined.")
|
884
|
+
var hooks = []
|
885
|
+
var active = $doc.activeElement
|
886
|
+
// First time0 rendering into a node clears it out
|
887
|
+
if (dom.vnodes == null) dom.textContent = ""
|
888
|
+
if (!Array.isArray(vnodes)) vnodes = [vnodes]
|
889
|
+
updateNodes(dom, dom.vnodes, Vnode.normalizeChildren(vnodes), hooks, null, undefined)
|
890
|
+
dom.vnodes = vnodes
|
891
|
+
for (var i = 0; i < hooks.length; i++) hooks[i]()
|
892
|
+
if ($doc.activeElement !== active) active.focus()
|
893
|
+
}
|
894
|
+
return {render: render, setEventCallback: setEventCallback}
|
895
|
+
}
|
896
|
+
function throttle(callback) {
|
897
|
+
//60fps translates to 16.6ms, round it down since setTimeout requires int
|
898
|
+
var time = 16
|
899
|
+
var last = 0, pending = null
|
900
|
+
var timeout = typeof requestAnimationFrame === "function" ? requestAnimationFrame : setTimeout
|
901
|
+
return function() {
|
902
|
+
var now = Date.now()
|
903
|
+
if (last === 0 || now - last >= time) {
|
904
|
+
last = now
|
905
|
+
callback()
|
906
|
+
}
|
907
|
+
else if (pending === null) {
|
908
|
+
pending = timeout(function() {
|
909
|
+
pending = null
|
910
|
+
callback()
|
911
|
+
last = Date.now()
|
912
|
+
}, time - (now - last))
|
913
|
+
}
|
914
|
+
}
|
915
|
+
}
|
916
|
+
var _11 = function($window) {
|
917
|
+
var renderService = coreRenderer($window)
|
918
|
+
renderService.setEventCallback(function(e) {
|
919
|
+
if (e.redraw !== false) redraw()
|
920
|
+
})
|
921
|
+
|
922
|
+
var callbacks = []
|
923
|
+
function subscribe(key1, callback) {
|
924
|
+
unsubscribe(key1)
|
925
|
+
callbacks.push(key1, throttle(callback))
|
926
|
+
}
|
927
|
+
function unsubscribe(key1) {
|
928
|
+
var index = callbacks.indexOf(key1)
|
929
|
+
if (index > -1) callbacks.splice(index, 2)
|
930
|
+
}
|
931
|
+
function redraw() {
|
932
|
+
for (var i = 1; i < callbacks.length; i += 2) {
|
933
|
+
callbacks[i]()
|
934
|
+
}
|
935
|
+
}
|
936
|
+
return {subscribe: subscribe, unsubscribe: unsubscribe, redraw: redraw, render: renderService.render}
|
937
|
+
}
|
938
|
+
var redrawService = _11(window)
|
939
|
+
requestService.setCompletionCallback(redrawService.redraw)
|
940
|
+
var _16 = function(redrawService0) {
|
941
|
+
return function(root, component) {
|
942
|
+
if (component === null) {
|
943
|
+
redrawService0.render(root, [])
|
944
|
+
redrawService0.unsubscribe(root)
|
945
|
+
return
|
946
|
+
}
|
947
|
+
|
948
|
+
if (component.view == null) throw new Error("m.mount(element, component) expects a component, not a vnode")
|
949
|
+
|
950
|
+
var run0 = function() {
|
951
|
+
redrawService0.render(root, Vnode(component))
|
952
|
+
}
|
953
|
+
redrawService0.subscribe(root, run0)
|
954
|
+
redrawService0.redraw()
|
955
|
+
}
|
956
|
+
}
|
957
|
+
m.mount = _16(redrawService)
|
958
|
+
var Promise = PromisePolyfill
|
959
|
+
var parseQueryString = function(string) {
|
960
|
+
if (string === "" || string == null) return {}
|
961
|
+
if (string.charAt(0) === "?") string = string.slice(1)
|
962
|
+
var entries = string.split("&"), data0 = {}, counters = {}
|
963
|
+
for (var i = 0; i < entries.length; i++) {
|
964
|
+
var entry = entries[i].split("=")
|
965
|
+
var key5 = decodeURIComponent(entry[0])
|
966
|
+
var value = entry.length === 2 ? decodeURIComponent(entry[1]) : ""
|
967
|
+
if (value === "true") value = true
|
968
|
+
else if (value === "false") value = false
|
969
|
+
var levels = key5.split(/\]\[?|\[/)
|
970
|
+
var cursor = data0
|
971
|
+
if (key5.indexOf("[") > -1) levels.pop()
|
972
|
+
for (var j = 0; j < levels.length; j++) {
|
973
|
+
var level = levels[j], nextLevel = levels[j + 1]
|
974
|
+
var isNumber = nextLevel == "" || !isNaN(parseInt(nextLevel, 10))
|
975
|
+
var isValue = j === levels.length - 1
|
976
|
+
if (level === "") {
|
977
|
+
var key5 = levels.slice(0, j).join()
|
978
|
+
if (counters[key5] == null) counters[key5] = 0
|
979
|
+
level = counters[key5]++
|
980
|
+
}
|
981
|
+
if (cursor[level] == null) {
|
982
|
+
cursor[level] = isValue ? value : isNumber ? [] : {}
|
983
|
+
}
|
984
|
+
cursor = cursor[level]
|
985
|
+
}
|
986
|
+
}
|
987
|
+
return data0
|
988
|
+
}
|
989
|
+
var coreRouter = function($window) {
|
990
|
+
var supportsPushState = typeof $window.history.pushState === "function"
|
991
|
+
var callAsync0 = typeof setImmediate === "function" ? setImmediate : setTimeout
|
992
|
+
function normalize1(fragment0) {
|
993
|
+
var data = $window.location[fragment0].replace(/(?:%[a-f89][a-f0-9])+/gim, decodeURIComponent)
|
994
|
+
if (fragment0 === "pathname" && data[0] !== "/") data = "/" + data
|
995
|
+
return data
|
996
|
+
}
|
997
|
+
var asyncId
|
998
|
+
function debounceAsync(callback0) {
|
999
|
+
return function() {
|
1000
|
+
if (asyncId != null) return
|
1001
|
+
asyncId = callAsync0(function() {
|
1002
|
+
asyncId = null
|
1003
|
+
callback0()
|
1004
|
+
})
|
1005
|
+
}
|
1006
|
+
}
|
1007
|
+
function parsePath(path, queryData, hashData) {
|
1008
|
+
var queryIndex = path.indexOf("?")
|
1009
|
+
var hashIndex = path.indexOf("#")
|
1010
|
+
var pathEnd = queryIndex > -1 ? queryIndex : hashIndex > -1 ? hashIndex : path.length
|
1011
|
+
if (queryIndex > -1) {
|
1012
|
+
var queryEnd = hashIndex > -1 ? hashIndex : path.length
|
1013
|
+
var queryParams = parseQueryString(path.slice(queryIndex + 1, queryEnd))
|
1014
|
+
for (var key4 in queryParams) queryData[key4] = queryParams[key4]
|
1015
|
+
}
|
1016
|
+
if (hashIndex > -1) {
|
1017
|
+
var hashParams = parseQueryString(path.slice(hashIndex + 1))
|
1018
|
+
for (var key4 in hashParams) hashData[key4] = hashParams[key4]
|
1019
|
+
}
|
1020
|
+
return path.slice(0, pathEnd)
|
1021
|
+
}
|
1022
|
+
var router = {prefix: "#!"}
|
1023
|
+
router.getPath = function() {
|
1024
|
+
var type2 = router.prefix.charAt(0)
|
1025
|
+
switch (type2) {
|
1026
|
+
case "#": return normalize1("hash").slice(router.prefix.length)
|
1027
|
+
case "?": return normalize1("search").slice(router.prefix.length) + normalize1("hash")
|
1028
|
+
default: return normalize1("pathname").slice(router.prefix.length) + normalize1("search") + normalize1("hash")
|
1029
|
+
}
|
1030
|
+
}
|
1031
|
+
router.setPath = function(path, data, options) {
|
1032
|
+
var queryData = {}, hashData = {}
|
1033
|
+
path = parsePath(path, queryData, hashData)
|
1034
|
+
if (data != null) {
|
1035
|
+
for (var key4 in data) queryData[key4] = data[key4]
|
1036
|
+
path = path.replace(/:([^\/]+)/g, function(match2, token) {
|
1037
|
+
delete queryData[token]
|
1038
|
+
return data[token]
|
1039
|
+
})
|
1040
|
+
}
|
1041
|
+
var query = buildQueryString(queryData)
|
1042
|
+
if (query) path += "?" + query
|
1043
|
+
var hash = buildQueryString(hashData)
|
1044
|
+
if (hash) path += "#" + hash
|
1045
|
+
if (supportsPushState) {
|
1046
|
+
var state = options ? options.state : null
|
1047
|
+
var title = options ? options.title : null
|
1048
|
+
$window.onpopstate()
|
1049
|
+
if (options && options.replace) $window.history.replaceState(state, title, router.prefix + path)
|
1050
|
+
else $window.history.pushState(state, title, router.prefix + path)
|
1051
|
+
}
|
1052
|
+
else $window.location.href = router.prefix + path
|
1053
|
+
}
|
1054
|
+
router.defineRoutes = function(routes, resolve, reject) {
|
1055
|
+
function resolveRoute() {
|
1056
|
+
var path = router.getPath()
|
1057
|
+
var params = {}
|
1058
|
+
var pathname = parsePath(path, params, params)
|
1059
|
+
|
1060
|
+
var state = $window.history.state
|
1061
|
+
if (state != null) {
|
1062
|
+
for (var k in state) params[k] = state[k]
|
1063
|
+
}
|
1064
|
+
for (var route0 in routes) {
|
1065
|
+
var matcher = new RegExp("^" + route0.replace(/:[^\/]+?\.{3}/g, "(.*?)").replace(/:[^\/]+/g, "([^\\/]+)") + "\/?$")
|
1066
|
+
if (matcher.test(pathname)) {
|
1067
|
+
pathname.replace(matcher, function() {
|
1068
|
+
var keys = route0.match(/:[^\/]+/g) || []
|
1069
|
+
var values = [].slice.call(arguments, 1, -2)
|
1070
|
+
for (var i = 0; i < keys.length; i++) {
|
1071
|
+
params[keys[i].replace(/:|\./g, "")] = decodeURIComponent(values[i])
|
1072
|
+
}
|
1073
|
+
resolve(routes[route0], params, path, route0)
|
1074
|
+
})
|
1075
|
+
return
|
1076
|
+
}
|
1077
|
+
}
|
1078
|
+
reject(path, params)
|
1079
|
+
}
|
1080
|
+
|
1081
|
+
if (supportsPushState) $window.onpopstate = debounceAsync(resolveRoute)
|
1082
|
+
else if (router.prefix.charAt(0) === "#") $window.onhashchange = resolveRoute
|
1083
|
+
resolveRoute()
|
1084
|
+
}
|
1085
|
+
|
1086
|
+
return router
|
1087
|
+
}
|
1088
|
+
var _20 = function($window, redrawService0) {
|
1089
|
+
var routeService = coreRouter($window)
|
1090
|
+
var identity = function(v) {return v}
|
1091
|
+
var render1, component, attrs3, currentPath, lastUpdate
|
1092
|
+
var route = function(root, defaultRoute, routes) {
|
1093
|
+
if (root == null) throw new Error("Ensure the DOM element that was passed to `m.route` is not undefined")
|
1094
|
+
var run1 = function() {
|
1095
|
+
if (render1 != null) redrawService0.render(root, render1(Vnode(component, attrs3.key, attrs3)))
|
1096
|
+
}
|
1097
|
+
var bail = function() {
|
1098
|
+
routeService.setPath(defaultRoute, null, {replace: true})
|
1099
|
+
}
|
1100
|
+
routeService.defineRoutes(routes, function(payload, params, path) {
|
1101
|
+
var update = lastUpdate = function(routeResolver, comp) {
|
1102
|
+
if (update !== lastUpdate) return
|
1103
|
+
component = comp != null && typeof comp.view === "function" ? comp : "div", attrs3 = params, currentPath = path, lastUpdate = null
|
1104
|
+
render1 = (routeResolver.render || identity).bind(routeResolver)
|
1105
|
+
run1()
|
1106
|
+
}
|
1107
|
+
if (payload.view) update({}, payload)
|
1108
|
+
else {
|
1109
|
+
if (payload.onmatch) {
|
1110
|
+
Promise.resolve(payload.onmatch(params, path)).then(function(resolved) {
|
1111
|
+
update(payload, resolved)
|
1112
|
+
}, bail)
|
1113
|
+
}
|
1114
|
+
else update(payload, "div")
|
1115
|
+
}
|
1116
|
+
}, bail)
|
1117
|
+
redrawService0.subscribe(root, run1)
|
1118
|
+
}
|
1119
|
+
route.set = function(path, data, options) {
|
1120
|
+
if (lastUpdate != null) options = {replace: true}
|
1121
|
+
lastUpdate = null
|
1122
|
+
routeService.setPath(path, data, options)
|
1123
|
+
}
|
1124
|
+
route.get = function() {return currentPath}
|
1125
|
+
route.prefix = function(prefix0) {routeService.prefix = prefix0}
|
1126
|
+
route.link = function(vnode1) {
|
1127
|
+
vnode1.dom.setAttribute("href", routeService.prefix + vnode1.attrs.href)
|
1128
|
+
vnode1.dom.onclick = function(e) {
|
1129
|
+
if (e.ctrlKey || e.metaKey || e.shiftKey || e.which === 2) return
|
1130
|
+
e.preventDefault()
|
1131
|
+
e.redraw = false
|
1132
|
+
var href = this.getAttribute("href")
|
1133
|
+
if (href.indexOf(routeService.prefix) === 0) href = href.slice(routeService.prefix.length)
|
1134
|
+
route.set(href, undefined, undefined)
|
1135
|
+
}
|
1136
|
+
}
|
1137
|
+
route.param = function(key3) {
|
1138
|
+
if(typeof attrs3 !== "undefined" && typeof key3 !== "undefined") return attrs3[key3]
|
1139
|
+
return attrs3
|
1140
|
+
}
|
1141
|
+
return route
|
1142
|
+
}
|
1143
|
+
m.route = _20(window, redrawService)
|
1144
|
+
m.withAttr = function(attrName, callback1, context) {
|
1145
|
+
return function(e) {
|
1146
|
+
callback1.call(context || this, attrName in e.currentTarget ? e.currentTarget[attrName] : e.currentTarget.getAttribute(attrName))
|
1147
|
+
}
|
1148
|
+
}
|
1149
|
+
var _28 = coreRenderer(window)
|
1150
|
+
m.render = _28.render
|
1151
|
+
m.redraw = redrawService.redraw
|
1152
|
+
m.request = requestService.request
|
1153
|
+
m.jsonp = requestService.jsonp
|
1154
|
+
m.parseQueryString = parseQueryString
|
1155
|
+
m.buildQueryString = buildQueryString
|
1156
|
+
m.version = "1.0.0"
|
1157
|
+
m.vnode = Vnode
|
1158
|
+
if (typeof module !== "undefined") module["exports"] = m
|
1159
|
+
else window.m = m
|
1160
|
+
}
|