mithril_rails 0.0.4 → 0.0.5
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 +4 -4
- data/app/assets/javascripts/mithril.js +139 -116
- data/lib/mithril_rails/version.rb +1 -1
- metadata +10 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7b6a280ee516de13bb19b02a57d8e81a379ff692
|
4
|
+
data.tar.gz: 3d3b67557ab7f491d273404f749b4429fe61d77c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b209e73c2b7385d1ead06e2f5f53706045b2b1b1864eeeb3a02af97516cb735fbedab792ddd4637399ec6aea70028dbec34348e18e49d1fdfd3ac6432b2c7285
|
7
|
+
data.tar.gz: 10cfd7659cff335878713bec7bbe4221685fbecac7b6ade88ae8d68e31f988d4d2857dc3b523929b7c72979567fba5cdf088f748635ce4d33d1718bf46def39c
|
@@ -33,17 +33,17 @@ var m = (function app(window, undefined) {
|
|
33
33
|
*/
|
34
34
|
function m() {
|
35
35
|
var args = [].slice.call(arguments);
|
36
|
-
var hasAttrs = args[1] != null && type.call(args[1])
|
36
|
+
var hasAttrs = args[1] != null && type.call(args[1]) === OBJECT && !("tag" in args[1]) && !("subtree" in args[1]);
|
37
37
|
var attrs = hasAttrs ? args[1] : {};
|
38
38
|
var classAttrName = "class" in attrs ? "class" : "className";
|
39
39
|
var cell = {tag: "div", attrs: {}};
|
40
40
|
var match, classes = [];
|
41
41
|
if (type.call(args[0]) != STRING) throw new Error("selector in m(selector, attrs, children) should be a string")
|
42
42
|
while (match = parser.exec(args[0])) {
|
43
|
-
if (match[1]
|
44
|
-
else if (match[1]
|
45
|
-
else if (match[1]
|
46
|
-
else if (match[3][0]
|
43
|
+
if (match[1] === "" && match[2]) cell.tag = match[2];
|
44
|
+
else if (match[1] === "#") cell.attrs.id = match[2];
|
45
|
+
else if (match[1] === ".") classes.push(match[2]);
|
46
|
+
else if (match[3][0] === "[") {
|
47
47
|
var pair = attrParser.exec(match[3]);
|
48
48
|
cell.attrs[pair[1]] = pair[3] || (pair[2] ? "" :true)
|
49
49
|
}
|
@@ -52,7 +52,7 @@ var m = (function app(window, undefined) {
|
|
52
52
|
|
53
53
|
|
54
54
|
var children = hasAttrs ? args[2] : args[1];
|
55
|
-
if (type.call(children)
|
55
|
+
if (type.call(children) === ARRAY) {
|
56
56
|
cell.children = children
|
57
57
|
}
|
58
58
|
else {
|
@@ -60,7 +60,7 @@ var m = (function app(window, undefined) {
|
|
60
60
|
}
|
61
61
|
|
62
62
|
for (var attrName in attrs) {
|
63
|
-
if (attrName
|
63
|
+
if (attrName === classAttrName) cell.attrs[attrName] = (cell.attrs[attrName] || "") + " " + attrs[attrName];
|
64
64
|
else cell.attrs[attrName] = attrs[attrName]
|
65
65
|
}
|
66
66
|
return cell
|
@@ -91,14 +91,15 @@ var m = (function app(window, undefined) {
|
|
91
91
|
//there's logic that relies on the assumption that null and undefined data are equivalent to empty strings
|
92
92
|
//- this prevents lifecycle surprises from procedural helpers that mix implicit and explicit return statements (e.g. function foo() {if (cond) return m("div")}
|
93
93
|
//- it simplifies diffing code
|
94
|
-
|
94
|
+
//data.toString() is null if data is the return value of Console.log in Firefox
|
95
|
+
if (data == null || data.toString() == null) data = "";
|
95
96
|
if (data.subtree === "retain") return cached;
|
96
97
|
var cachedType = type.call(cached), dataType = type.call(data);
|
97
|
-
if (cached == null || cachedType
|
98
|
+
if (cached == null || cachedType !== dataType) {
|
98
99
|
if (cached != null) {
|
99
100
|
if (parentCache && parentCache.nodes) {
|
100
101
|
var offset = index - parentIndex;
|
101
|
-
var end = offset + (dataType
|
102
|
+
var end = offset + (dataType === ARRAY ? data : cached.nodes).length;
|
102
103
|
clear(parentCache.nodes.slice(offset, end), parentCache.slice(offset, end))
|
103
104
|
}
|
104
105
|
else if (cached.nodes) clear(cached.nodes, cached)
|
@@ -108,10 +109,10 @@ var m = (function app(window, undefined) {
|
|
108
109
|
cached.nodes = []
|
109
110
|
}
|
110
111
|
|
111
|
-
if (dataType
|
112
|
+
if (dataType === ARRAY) {
|
112
113
|
//recursively flatten array
|
113
|
-
for (var i = 0
|
114
|
-
if (type.call(data[i])
|
114
|
+
for (var i = 0, len = data.length; i < len; i++) {
|
115
|
+
if (type.call(data[i]) === ARRAY) {
|
115
116
|
data = data.concat.apply([], data);
|
116
117
|
i-- //check current index again and flatten until there are no more nested arrays at that index
|
117
118
|
}
|
@@ -134,56 +135,70 @@ var m = (function app(window, undefined) {
|
|
134
135
|
}
|
135
136
|
}
|
136
137
|
if (shouldMaintainIdentities) {
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
from: existing[key].index,
|
146
|
-
element: parentElement.childNodes[existing[key].index] || $document.createElement("div")
|
147
|
-
}
|
148
|
-
}
|
149
|
-
else unkeyed.push({index: i, element: parentElement.childNodes[i] || $document.createElement("div")})
|
138
|
+
if (data.indexOf(null) > -1) data = data.filter(function(x) {return x != null})
|
139
|
+
|
140
|
+
var keysDiffer = false
|
141
|
+
if (data.length != cached.length) keysDiffer = true
|
142
|
+
else for (var i = 0, cachedCell, dataCell; cachedCell = cached[i], dataCell = data[i]; i++) {
|
143
|
+
if (cachedCell.attrs && dataCell.attrs && cachedCell.attrs.key != dataCell.attrs.key) {
|
144
|
+
keysDiffer = true
|
145
|
+
break
|
150
146
|
}
|
151
147
|
}
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
148
|
+
|
149
|
+
if (keysDiffer) {
|
150
|
+
for (var i = 0, len = data.length; i < len; i++) {
|
151
|
+
if (data[i] && data[i].attrs) {
|
152
|
+
if (data[i].attrs.key != null) {
|
153
|
+
var key = data[i].attrs.key;
|
154
|
+
if (!existing[key]) existing[key] = {action: INSERTION, index: i};
|
155
|
+
else existing[key] = {
|
156
|
+
action: MOVE,
|
157
|
+
index: i,
|
158
|
+
from: existing[key].index,
|
159
|
+
element: parentElement.childNodes[existing[key].index] || $document.createElement("div")
|
160
|
+
}
|
161
|
+
}
|
162
|
+
else unkeyed.push({index: i, element: parentElement.childNodes[i] || $document.createElement("div")})
|
163
|
+
}
|
166
164
|
}
|
165
|
+
var actions = []
|
166
|
+
for (var prop in existing) actions.push(existing[prop])
|
167
|
+
var changes = actions.sort(sortChanges);
|
168
|
+
var newCached = new Array(cached.length)
|
169
|
+
|
170
|
+
for (var i = 0, change; change = changes[i]; i++) {
|
171
|
+
if (change.action === DELETION) {
|
172
|
+
clear(cached[change.index].nodes, cached[change.index]);
|
173
|
+
newCached.splice(change.index, 1)
|
174
|
+
}
|
175
|
+
if (change.action === INSERTION) {
|
176
|
+
var dummy = $document.createElement("div");
|
177
|
+
dummy.key = data[change.index].attrs.key;
|
178
|
+
parentElement.insertBefore(dummy, parentElement.childNodes[change.index] || null);
|
179
|
+
newCached.splice(change.index, 0, {attrs: {key: data[change.index].attrs.key}, nodes: [dummy]})
|
180
|
+
}
|
167
181
|
|
168
|
-
|
169
|
-
|
170
|
-
|
182
|
+
if (change.action === MOVE) {
|
183
|
+
if (parentElement.childNodes[change.index] !== change.element && change.element !== null) {
|
184
|
+
parentElement.insertBefore(change.element, parentElement.childNodes[change.index] || null)
|
185
|
+
}
|
186
|
+
newCached[change.index] = cached[change.from]
|
171
187
|
}
|
172
|
-
newCached[change.index] = cached[change.from]
|
173
188
|
}
|
189
|
+
for (var i = 0, len = unkeyed.length; i < len; i++) {
|
190
|
+
var change = unkeyed[i];
|
191
|
+
parentElement.insertBefore(change.element, parentElement.childNodes[change.index] || null);
|
192
|
+
newCached[change.index] = cached[change.index]
|
193
|
+
}
|
194
|
+
cached = newCached;
|
195
|
+
cached.nodes = new Array(parentElement.childNodes.length);
|
196
|
+
for (var i = 0, child; child = parentElement.childNodes[i]; i++) cached.nodes[i] = child
|
174
197
|
}
|
175
|
-
for (var i = 0; i < unkeyed.length; i++) {
|
176
|
-
var change = unkeyed[i];
|
177
|
-
parentElement.insertBefore(change.element, parentElement.childNodes[change.index] || null);
|
178
|
-
newCached[change.index] = cached[change.index]
|
179
|
-
}
|
180
|
-
cached = newCached;
|
181
|
-
cached.nodes = [];
|
182
|
-
for (var i = 0, child; child = parentElement.childNodes[i]; i++) cached.nodes.push(child)
|
183
198
|
}
|
184
199
|
//end key algorithm
|
185
200
|
|
186
|
-
for (var i = 0, cacheCount = 0
|
201
|
+
for (var i = 0, cacheCount = 0, len = data.length; i < len; i++) {
|
187
202
|
//diff each item in the array
|
188
203
|
var item = build(parentElement, parentTag, cached, index, data[i], cached[cacheCount], shouldReattach, index + subArrayCount || subArrayCount, editable, namespace, configs);
|
189
204
|
if (item === undefined) continue;
|
@@ -194,14 +209,14 @@ var m = (function app(window, undefined) {
|
|
194
209
|
//the second clause (after the pipe) matches text nodes
|
195
210
|
subArrayCount += (item.match(/<[^\/]|\>\s*[^<]/g) || []).length
|
196
211
|
}
|
197
|
-
else subArrayCount += type.call(item)
|
212
|
+
else subArrayCount += type.call(item) === ARRAY ? item.length : 1;
|
198
213
|
cached[cacheCount++] = item
|
199
214
|
}
|
200
215
|
if (!intact) {
|
201
216
|
//diff the array itself
|
202
217
|
|
203
218
|
//update the list of DOM nodes by collecting the nodes from each item
|
204
|
-
for (var i = 0
|
219
|
+
for (var i = 0, len = data.length; i < len; i++) {
|
205
220
|
if (cached[i] != null) nodes.push.apply(nodes, cached[i].nodes)
|
206
221
|
}
|
207
222
|
//remove items from the end of the array if the new array is shorter than the old one
|
@@ -213,16 +228,16 @@ var m = (function app(window, undefined) {
|
|
213
228
|
cached.nodes = nodes
|
214
229
|
}
|
215
230
|
}
|
216
|
-
else if (data != null && dataType
|
231
|
+
else if (data != null && dataType === OBJECT) {
|
217
232
|
if (!data.attrs) data.attrs = {};
|
218
233
|
if (!cached.attrs) cached.attrs = {};
|
219
234
|
|
220
|
-
var dataAttrKeys = Object.keys(data.attrs)
|
235
|
+
var dataAttrKeys = Object.keys(data.attrs)
|
221
236
|
var hasKeys = dataAttrKeys.length > ("key" in data.attrs ? 1 : 0)
|
222
237
|
//if an element is different enough from the one in cache, recreate it
|
223
238
|
if (data.tag != cached.tag || dataAttrKeys.join() != Object.keys(cached.attrs).join() || data.attrs.id != cached.attrs.id) {
|
224
239
|
if (cached.nodes.length) clear(cached.nodes);
|
225
|
-
if (cached.configContext && typeof cached.configContext.onunload
|
240
|
+
if (cached.configContext && typeof cached.configContext.onunload === FUNCTION) cached.configContext.onunload()
|
226
241
|
}
|
227
242
|
if (type.call(data.tag) != STRING) return;
|
228
243
|
|
@@ -236,7 +251,7 @@ var m = (function app(window, undefined) {
|
|
236
251
|
cached = {
|
237
252
|
tag: data.tag,
|
238
253
|
//set attributes first, then create children
|
239
|
-
attrs:
|
254
|
+
attrs: hasKeys ? setAttributes(node, data.tag, data.attrs, {}, namespace) : data.attrs,
|
240
255
|
children: data.children != null && data.children.length > 0 ?
|
241
256
|
build(node, data.tag, undefined, undefined, data.children, cached.children, true, 0, data.attrs.contenteditable ? node : editable, namespace, configs) :
|
242
257
|
data.children,
|
@@ -244,18 +259,18 @@ var m = (function app(window, undefined) {
|
|
244
259
|
};
|
245
260
|
if (cached.children && !cached.children.nodes) cached.children.nodes = [];
|
246
261
|
//edge case: setting value on <select> doesn't work before children exist, so set it again after children have been created
|
247
|
-
if (data.tag
|
262
|
+
if (data.tag === "select" && data.attrs.value) setAttributes(node, data.tag, {value: data.attrs.value}, {}, namespace);
|
248
263
|
parentElement.insertBefore(node, parentElement.childNodes[index] || null)
|
249
264
|
}
|
250
265
|
else {
|
251
266
|
node = cached.nodes[0];
|
252
|
-
if (
|
267
|
+
if (hasKeys) setAttributes(node, data.tag, data.attrs, cached.attrs, namespace);
|
253
268
|
cached.children = build(node, data.tag, undefined, undefined, data.children, cached.children, false, 0, data.attrs.contenteditable ? node : editable, namespace, configs);
|
254
269
|
cached.nodes.intact = true;
|
255
270
|
if (shouldReattach === true && node != null) parentElement.insertBefore(node, parentElement.childNodes[index] || null)
|
256
271
|
}
|
257
272
|
//schedule configs to be called. They are called after `build` finishes running
|
258
|
-
if (typeof data.attrs["config"]
|
273
|
+
if (typeof data.attrs["config"] === FUNCTION) {
|
259
274
|
var context = cached.configContext = cached.configContext || {};
|
260
275
|
|
261
276
|
// bind
|
@@ -294,7 +309,7 @@ var m = (function app(window, undefined) {
|
|
294
309
|
if (parentTag === "textarea") parentElement.value = data;
|
295
310
|
else if (editable) editable.innerHTML = data;
|
296
311
|
else {
|
297
|
-
if (nodes[0].nodeType
|
312
|
+
if (nodes[0].nodeType === 1 || nodes.length > 1) { //was a trusted string
|
298
313
|
clear(cached.nodes, cached);
|
299
314
|
nodes = [$document.createTextNode(data)]
|
300
315
|
}
|
@@ -311,6 +326,7 @@ var m = (function app(window, undefined) {
|
|
311
326
|
|
312
327
|
return cached
|
313
328
|
}
|
329
|
+
function sortChanges(a, b) {return a.action - b.action || a.index - b.index}
|
314
330
|
function setAttributes(node, tag, dataAttrs, cachedAttrs, namespace) {
|
315
331
|
for (var attrName in dataAttrs) {
|
316
332
|
var dataAttr = dataAttrs[attrName];
|
@@ -319,14 +335,13 @@ var m = (function app(window, undefined) {
|
|
319
335
|
cachedAttrs[attrName] = dataAttr;
|
320
336
|
try {
|
321
337
|
//`config` isn't a real attributes, so ignore it
|
322
|
-
|
323
|
-
if (attrName === "config") continue;
|
338
|
+
if (attrName === "config" || attrName == "key") continue;
|
324
339
|
//hook event handlers to the auto-redrawing system
|
325
|
-
else if (typeof dataAttr
|
340
|
+
else if (typeof dataAttr === FUNCTION && attrName.indexOf("on") === 0) {
|
326
341
|
node[attrName] = autoredraw(dataAttr, node)
|
327
342
|
}
|
328
343
|
//handle `style: {...}`
|
329
|
-
else if (attrName === "style" && dataAttr != null && type.call(dataAttr)
|
344
|
+
else if (attrName === "style" && dataAttr != null && type.call(dataAttr) === OBJECT) {
|
330
345
|
for (var rule in dataAttr) {
|
331
346
|
if (cachedAttr == null || cachedAttr[rule] !== dataAttr[rule]) node.style[rule] = dataAttr[rule]
|
332
347
|
}
|
@@ -343,9 +358,9 @@ var m = (function app(window, undefined) {
|
|
343
358
|
//handle cases that are properties (but ignore cases where we should use setAttribute instead)
|
344
359
|
//- list and form are typically used as strings, but are DOM element references in js
|
345
360
|
//- when using CSS selectors (e.g. `m("[style='']")`), style is used as a string, but it's an object in js
|
346
|
-
else if (attrName in node && !(attrName
|
361
|
+
else if (attrName in node && !(attrName === "list" || attrName === "style" || attrName === "form" || attrName === "type")) {
|
347
362
|
//#348 don't set the value if not needed otherwise cursor placement breaks in Chrome
|
348
|
-
if (node[attrName]
|
363
|
+
if (tag !== "input" || node[attrName] !== dataAttr) node[attrName] = dataAttr
|
349
364
|
}
|
350
365
|
else node.setAttribute(attrName, dataAttr)
|
351
366
|
}
|
@@ -373,10 +388,10 @@ var m = (function app(window, undefined) {
|
|
373
388
|
if (nodes.length != 0) nodes.length = 0
|
374
389
|
}
|
375
390
|
function unload(cached) {
|
376
|
-
if (cached.configContext && typeof cached.configContext.onunload
|
391
|
+
if (cached.configContext && typeof cached.configContext.onunload === FUNCTION) cached.configContext.onunload();
|
377
392
|
if (cached.children) {
|
378
|
-
if (type.call(cached.children)
|
379
|
-
for (var i = 0;
|
393
|
+
if (type.call(cached.children) === ARRAY) {
|
394
|
+
for (var i = 0, child; child = cached.children[i]; i++) unload(child)
|
380
395
|
}
|
381
396
|
else if (cached.children.tag) unload(cached.children)
|
382
397
|
}
|
@@ -408,7 +423,7 @@ var m = (function app(window, undefined) {
|
|
408
423
|
m.startComputation();
|
409
424
|
try {return callback.call(object, e)}
|
410
425
|
finally {
|
411
|
-
|
426
|
+
endFirstComputation()
|
412
427
|
}
|
413
428
|
}
|
414
429
|
}
|
@@ -433,13 +448,13 @@ var m = (function app(window, undefined) {
|
|
433
448
|
var configs = [];
|
434
449
|
if (!root) throw new Error("Please ensure the DOM element exists before rendering a template into it.");
|
435
450
|
var id = getCellCacheKey(root);
|
436
|
-
var isDocumentRoot = root
|
437
|
-
var node = isDocumentRoot || root
|
451
|
+
var isDocumentRoot = root === $document;
|
452
|
+
var node = isDocumentRoot || root === $document.documentElement ? documentNode : root;
|
438
453
|
if (isDocumentRoot && cell.tag != "html") cell = {tag: "html", attrs: {}, children: cell};
|
439
454
|
if (cellCache[id] === undefined) clear(node.childNodes);
|
440
455
|
if (forceRecreation === true) reset(root);
|
441
456
|
cellCache[id] = build(node, null, undefined, undefined, cell, cellCache[id], false, 0, null, undefined, configs);
|
442
|
-
for (var i = 0
|
457
|
+
for (var i = 0, len = configs.length; i < len; i++) configs[i]()
|
443
458
|
};
|
444
459
|
function getCellCacheKey(element) {
|
445
460
|
var index = nodeCache.indexOf(element);
|
@@ -467,7 +482,7 @@ var m = (function app(window, undefined) {
|
|
467
482
|
|
468
483
|
m.prop = function (store) {
|
469
484
|
//note: using non-strict equality check here because we're checking if store is null OR undefined
|
470
|
-
if (((store != null && type.call(store)
|
485
|
+
if (((store != null && type.call(store) === OBJECT) || typeof store === FUNCTION) && typeof store.then === FUNCTION) {
|
471
486
|
return propify(store)
|
472
487
|
}
|
473
488
|
|
@@ -477,10 +492,11 @@ var m = (function app(window, undefined) {
|
|
477
492
|
var roots = [], modules = [], controllers = [], lastRedrawId = null, lastRedrawCallTime = 0, computePostRedrawHook = null, prevented = false, topModule;
|
478
493
|
var FRAME_BUDGET = 16; //60 frames per second = 1 call per 16 ms
|
479
494
|
m.module = function(root, module) {
|
495
|
+
if (!root) throw new Error("Please ensure the DOM element exists before rendering a template into it.");
|
480
496
|
var index = roots.indexOf(root);
|
481
497
|
if (index < 0) index = roots.length;
|
482
498
|
var isPrevented = false;
|
483
|
-
if (controllers[index] && typeof controllers[index].onunload
|
499
|
+
if (controllers[index] && typeof controllers[index].onunload === FUNCTION) {
|
484
500
|
var event = {
|
485
501
|
preventDefault: function() {isPrevented = true}
|
486
502
|
};
|
@@ -494,11 +510,11 @@ var m = (function app(window, undefined) {
|
|
494
510
|
var controller = new module.controller;
|
495
511
|
//controllers may call m.module recursively (via m.route redirects, for example)
|
496
512
|
//this conditional ensures only the last recursive m.module call is applied
|
497
|
-
if (currentModule
|
513
|
+
if (currentModule === topModule) {
|
498
514
|
controllers[index] = controller;
|
499
515
|
modules[index] = module
|
500
516
|
}
|
501
|
-
|
517
|
+
endFirstComputation();
|
502
518
|
return controllers[index]
|
503
519
|
}
|
504
520
|
};
|
@@ -508,7 +524,7 @@ var m = (function app(window, undefined) {
|
|
508
524
|
if (lastRedrawId && force !== true) {
|
509
525
|
//when setTimeout: only reschedule redraw if time between now and previous redraw is bigger than a frame, otherwise keep currently scheduled timeout
|
510
526
|
//when rAF: always reschedule redraw
|
511
|
-
if (new Date - lastRedrawCallTime > FRAME_BUDGET || $requestAnimationFrame
|
527
|
+
if (new Date - lastRedrawCallTime > FRAME_BUDGET || $requestAnimationFrame === window.requestAnimationFrame) {
|
512
528
|
if (lastRedrawId > 0) $cancelAnimationFrame(lastRedrawId);
|
513
529
|
lastRedrawId = $requestAnimationFrame(redraw, FRAME_BUDGET)
|
514
530
|
}
|
@@ -520,10 +536,10 @@ var m = (function app(window, undefined) {
|
|
520
536
|
};
|
521
537
|
m.redraw.strategy = m.prop();
|
522
538
|
function redraw() {
|
523
|
-
var
|
524
|
-
for (var i = 0;
|
525
|
-
if (controllers[i]
|
526
|
-
m.render(
|
539
|
+
var forceRedraw = m.redraw.strategy() === "all";
|
540
|
+
for (var i = 0, root; root = roots[i]; i++) {
|
541
|
+
if (controllers[i]) {
|
542
|
+
m.render(root, modules[i].view(controllers[i]), forceRedraw)
|
527
543
|
}
|
528
544
|
}
|
529
545
|
//after rendering within a routed context, we need to scroll back to the top, and fetch the document title for history.pushState
|
@@ -540,8 +556,15 @@ var m = (function app(window, undefined) {
|
|
540
556
|
m.startComputation = function() {pendingRequests++};
|
541
557
|
m.endComputation = function() {
|
542
558
|
pendingRequests = Math.max(pendingRequests - 1, 0);
|
543
|
-
if (pendingRequests
|
559
|
+
if (pendingRequests === 0) m.redraw()
|
544
560
|
};
|
561
|
+
var endFirstComputation = function() {
|
562
|
+
if (m.redraw.strategy() == "none") {
|
563
|
+
pendingRequests--
|
564
|
+
m.redraw.strategy("diff")
|
565
|
+
}
|
566
|
+
else m.endComputation();
|
567
|
+
}
|
545
568
|
|
546
569
|
m.withAttr = function(prop, withAttrCallback) {
|
547
570
|
return function(e) {
|
@@ -558,7 +581,7 @@ var m = (function app(window, undefined) {
|
|
558
581
|
//m.route()
|
559
582
|
if (arguments.length === 0) return currentRoute;
|
560
583
|
//m.route(el, defaultRoute, routes)
|
561
|
-
else if (arguments.length === 3 && type.call(arguments[1])
|
584
|
+
else if (arguments.length === 3 && type.call(arguments[1]) === STRING) {
|
562
585
|
var root = arguments[0], defaultRoute = arguments[1], router = arguments[2];
|
563
586
|
redirect = function(source) {
|
564
587
|
var path = currentRoute = normalizeRoute(source);
|
@@ -566,7 +589,7 @@ var m = (function app(window, undefined) {
|
|
566
589
|
m.route(defaultRoute, true)
|
567
590
|
}
|
568
591
|
};
|
569
|
-
var listener = m.route.mode
|
592
|
+
var listener = m.route.mode === "hash" ? "onhashchange" : "onpopstate";
|
570
593
|
window[listener] = function() {
|
571
594
|
if (currentRoute != normalizeRoute($location[m.route.mode])) {
|
572
595
|
redirect($location[m.route.mode])
|
@@ -585,7 +608,7 @@ var m = (function app(window, undefined) {
|
|
585
608
|
element.addEventListener("click", routeUnobtrusive)
|
586
609
|
}
|
587
610
|
//m.route(route, params)
|
588
|
-
else if (type.call(arguments[0])
|
611
|
+
else if (type.call(arguments[0]) === STRING) {
|
589
612
|
currentRoute = arguments[0];
|
590
613
|
var args = arguments[1] || {}
|
591
614
|
var queryIndex = currentRoute.indexOf("?")
|
@@ -595,7 +618,7 @@ var m = (function app(window, undefined) {
|
|
595
618
|
var currentPath = queryIndex > -1 ? currentRoute.slice(0, queryIndex) : currentRoute
|
596
619
|
if (querystring) currentRoute = currentPath + (currentPath.indexOf("?") === -1 ? "?" : "&") + querystring;
|
597
620
|
|
598
|
-
var shouldReplaceHistoryEntry = (arguments.length
|
621
|
+
var shouldReplaceHistoryEntry = (arguments.length === 3 ? arguments[2] : arguments[1]) === true;
|
599
622
|
|
600
623
|
if (window.history.pushState) {
|
601
624
|
computePostRedrawHook = function() {
|
@@ -623,7 +646,7 @@ var m = (function app(window, undefined) {
|
|
623
646
|
}
|
624
647
|
|
625
648
|
for (var route in router) {
|
626
|
-
if (route
|
649
|
+
if (route === path) {
|
627
650
|
m.module(root, router[route]);
|
628
651
|
return true
|
629
652
|
}
|
@@ -634,7 +657,7 @@ var m = (function app(window, undefined) {
|
|
634
657
|
path.replace(matcher, function() {
|
635
658
|
var keys = route.match(/:[^\/]+/g) || [];
|
636
659
|
var values = [].slice.call(arguments, 1, -2);
|
637
|
-
for (var i = 0
|
660
|
+
for (var i = 0, len = keys.length; i < len; i++) routeParams[keys[i].replace(/:|\./g, "")] = decodeURIComponent(values[i])
|
638
661
|
m.module(root, router[route])
|
639
662
|
});
|
640
663
|
return true
|
@@ -643,11 +666,11 @@ var m = (function app(window, undefined) {
|
|
643
666
|
}
|
644
667
|
function routeUnobtrusive(e) {
|
645
668
|
e = e || event;
|
646
|
-
if (e.ctrlKey || e.metaKey || e.which
|
669
|
+
if (e.ctrlKey || e.metaKey || e.which === 2) return;
|
647
670
|
if (e.preventDefault) e.preventDefault();
|
648
671
|
else e.returnValue = false;
|
649
672
|
var currentTarget = e.currentTarget || this;
|
650
|
-
var args = m.route.mode
|
673
|
+
var args = m.route.mode === "pathname" && currentTarget.search ? parseQueryString(currentTarget.search.slice(1)) : {};
|
651
674
|
m.route(currentTarget[m.route.mode].slice(modes[m.route.mode].length), args)
|
652
675
|
}
|
653
676
|
function setScroll() {
|
@@ -658,13 +681,13 @@ var m = (function app(window, undefined) {
|
|
658
681
|
var str = [];
|
659
682
|
for(var prop in object) {
|
660
683
|
var key = prefix ? prefix + "[" + prop + "]" : prop, value = object[prop];
|
661
|
-
str.push(value != null && type.call(value)
|
684
|
+
str.push(value != null && type.call(value) === OBJECT ? buildQueryString(value, key) : encodeURIComponent(key) + "=" + encodeURIComponent(value))
|
662
685
|
}
|
663
686
|
return str.join("&")
|
664
687
|
}
|
665
688
|
function parseQueryString(str) {
|
666
689
|
var pairs = str.split("&"), params = {};
|
667
|
-
for (var i = 0
|
690
|
+
for (var i = 0, len = pairs.length; i < len; i++) {
|
668
691
|
var pair = pairs[i].split("=");
|
669
692
|
params[decodeSpace(pair[0])] = pair[1] ? decodeSpace(pair[1]) : ""
|
670
693
|
}
|
@@ -724,10 +747,10 @@ var m = (function app(window, undefined) {
|
|
724
747
|
|
725
748
|
self.promise["then"] = function(successCallback, failureCallback) {
|
726
749
|
var deferred = new Deferred(successCallback, failureCallback);
|
727
|
-
if (state
|
750
|
+
if (state === RESOLVED) {
|
728
751
|
deferred.resolve(promiseValue)
|
729
752
|
}
|
730
|
-
else if (state
|
753
|
+
else if (state === REJECTED) {
|
731
754
|
deferred.reject(promiseValue)
|
732
755
|
}
|
733
756
|
else {
|
@@ -739,12 +762,12 @@ var m = (function app(window, undefined) {
|
|
739
762
|
function finish(type) {
|
740
763
|
state = type || REJECTED;
|
741
764
|
next.map(function(deferred) {
|
742
|
-
state
|
765
|
+
state === RESOLVED && deferred.resolve(promiseValue) || deferred.reject(promiseValue)
|
743
766
|
})
|
744
767
|
}
|
745
768
|
|
746
769
|
function thennable(then, successCallback, failureCallback, notThennableCallback) {
|
747
|
-
if (((promiseValue != null && type.call(promiseValue)
|
770
|
+
if (((promiseValue != null && type.call(promiseValue) === OBJECT) || typeof promiseValue === FUNCTION) && typeof then === FUNCTION) {
|
748
771
|
try {
|
749
772
|
// count protects against abuse calls from spec checker
|
750
773
|
var count = 0;
|
@@ -788,10 +811,10 @@ var m = (function app(window, undefined) {
|
|
788
811
|
fire()
|
789
812
|
}, function() {
|
790
813
|
try {
|
791
|
-
if (state
|
814
|
+
if (state === RESOLVING && typeof successCallback === FUNCTION) {
|
792
815
|
promiseValue = successCallback(promiseValue)
|
793
816
|
}
|
794
|
-
else if (state
|
817
|
+
else if (state === REJECTING && typeof failureCallback === "function") {
|
795
818
|
promiseValue = failureCallback(promiseValue);
|
796
819
|
state = RESOLVING
|
797
820
|
}
|
@@ -802,7 +825,7 @@ var m = (function app(window, undefined) {
|
|
802
825
|
return finish()
|
803
826
|
}
|
804
827
|
|
805
|
-
if (promiseValue
|
828
|
+
if (promiseValue === self) {
|
806
829
|
promiseValue = TypeError();
|
807
830
|
finish()
|
808
831
|
}
|
@@ -810,14 +833,14 @@ var m = (function app(window, undefined) {
|
|
810
833
|
thennable(then, function () {
|
811
834
|
finish(RESOLVED)
|
812
835
|
}, finish, function () {
|
813
|
-
finish(state
|
836
|
+
finish(state === RESOLVING && RESOLVED)
|
814
837
|
})
|
815
838
|
}
|
816
839
|
})
|
817
840
|
}
|
818
841
|
}
|
819
842
|
m.deferred.onerror = function(e) {
|
820
|
-
if (type.call(e)
|
843
|
+
if (type.call(e) === "[object Error]" && !e.constructor.toString().match(/ Error/)) throw e
|
821
844
|
};
|
822
845
|
|
823
846
|
m.sync = function(args) {
|
@@ -826,7 +849,7 @@ var m = (function app(window, undefined) {
|
|
826
849
|
return function(value) {
|
827
850
|
results[pos] = value;
|
828
851
|
if (!resolved) method = "reject";
|
829
|
-
if (--outstanding
|
852
|
+
if (--outstanding === 0) {
|
830
853
|
deferred.promise(results);
|
831
854
|
deferred[method](results)
|
832
855
|
}
|
@@ -899,18 +922,18 @@ var m = (function app(window, undefined) {
|
|
899
922
|
else options.onerror({type: "error", target: xhr})
|
900
923
|
}
|
901
924
|
};
|
902
|
-
if (options.serialize
|
925
|
+
if (options.serialize === JSON.stringify && options.data && options.method !== "GET") {
|
903
926
|
xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8")
|
904
927
|
}
|
905
|
-
if (options.deserialize
|
928
|
+
if (options.deserialize === JSON.parse) {
|
906
929
|
xhr.setRequestHeader("Accept", "application/json, text/*");
|
907
930
|
}
|
908
|
-
if (typeof options.config
|
931
|
+
if (typeof options.config === FUNCTION) {
|
909
932
|
var maybeXhr = options.config(xhr, options);
|
910
933
|
if (maybeXhr != null) xhr = maybeXhr
|
911
934
|
}
|
912
935
|
|
913
|
-
var data = options.method
|
936
|
+
var data = options.method === "GET" || !options.data ? "" : options.data
|
914
937
|
if (data && (type.call(data) != STRING && data.constructor != window.FormData)) {
|
915
938
|
throw "Request data should be either be a string or FormData. Check the `serialize` option in `m.request`";
|
916
939
|
}
|
@@ -919,7 +942,7 @@ var m = (function app(window, undefined) {
|
|
919
942
|
}
|
920
943
|
}
|
921
944
|
function bindData(xhrOptions, data, serialize) {
|
922
|
-
if (xhrOptions.method
|
945
|
+
if (xhrOptions.method === "GET" && xhrOptions.dataType != "jsonp") {
|
923
946
|
var prefix = xhrOptions.url.indexOf("?") < 0 ? "?" : "&";
|
924
947
|
var querystring = buildQueryString(data);
|
925
948
|
xhrOptions.url = xhrOptions.url + (querystring ? prefix + querystring : "")
|
@@ -953,15 +976,15 @@ var m = (function app(window, undefined) {
|
|
953
976
|
xhrOptions.onload = xhrOptions.onerror = function(e) {
|
954
977
|
try {
|
955
978
|
e = e || event;
|
956
|
-
var unwrap = (e.type
|
979
|
+
var unwrap = (e.type === "load" ? xhrOptions.unwrapSuccess : xhrOptions.unwrapError) || identity;
|
957
980
|
var response = unwrap(deserialize(extract(e.target, xhrOptions)));
|
958
|
-
if (e.type
|
959
|
-
if (type.call(response)
|
981
|
+
if (e.type === "load") {
|
982
|
+
if (type.call(response) === ARRAY && xhrOptions.type) {
|
960
983
|
for (var i = 0; i < response.length; i++) response[i] = new xhrOptions.type(response[i])
|
961
984
|
}
|
962
985
|
else if (xhrOptions.type) response = new xhrOptions.type(response)
|
963
986
|
}
|
964
|
-
deferred[e.type
|
987
|
+
deferred[e.type === "load" ? "resolve" : "reject"](response)
|
965
988
|
}
|
966
989
|
catch (e) {
|
967
990
|
m.deferred.onerror(e);
|
@@ -986,4 +1009,4 @@ var m = (function app(window, undefined) {
|
|
986
1009
|
})(typeof window != "undefined" ? window : {});
|
987
1010
|
|
988
1011
|
if (typeof module != "undefined" && module !== null && module.exports) module.exports = m;
|
989
|
-
else if (typeof define
|
1012
|
+
else if (typeof define === "function" && define.amd) define(function() {return m});
|
metadata
CHANGED
@@ -1,43 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mithril_rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jordan Humphreys
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-01-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: execjs
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 2.2.2
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 2.2.2
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rails
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 3.2.0
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 3.2.0
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: sqlite3
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|