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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cae7853c501aeb7070d48dc192630be72b063cf9
4
- data.tar.gz: ca7ee6eb9b78c601c45775f5d7c17fdb267f9a62
3
+ metadata.gz: 7b6a280ee516de13bb19b02a57d8e81a379ff692
4
+ data.tar.gz: 3d3b67557ab7f491d273404f749b4429fe61d77c
5
5
  SHA512:
6
- metadata.gz: 94e3c47c7b7355c4a793c29aa8cc5c873765f0eb461eeb146142079b72dca67682ab1a17866c8a0a1a5c8999e7fd70693a856e3f0e6d37e4ac1c6e0e27184f82
7
- data.tar.gz: 9dd014f34fb3627e69bef90a3d5cccb3a742da8ba02ec5694402fadcab50015ffa2034fe1e208c6252e761b232809485493188ffc91401ff5083b3d905a8da2c
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]) == OBJECT && !("tag" in args[1]) && !("subtree" in 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] == "" && 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] == "[") {
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) == ARRAY) {
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 == classAttrName) cell.attrs[attrName] = (cell.attrs[attrName] || "") + " " + attrs[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
- if (data == null) data = "";
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 != dataType) {
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 == ARRAY ? data : cached.nodes).length;
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 == ARRAY) {
112
+ if (dataType === ARRAY) {
112
113
  //recursively flatten array
113
- for (var i = 0; i < data.length; i++) {
114
- if (type.call(data[i]) == ARRAY) {
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
- for (var i = 0; i < data.length; i++) {
138
- if (data[i] && data[i].attrs) {
139
- if (data[i].attrs.key != null) {
140
- var key = data[i].attrs.key;
141
- if (!existing[key]) existing[key] = {action: INSERTION, index: i};
142
- else existing[key] = {
143
- action: MOVE,
144
- index: i,
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
- var actions = Object.keys(existing).map(function(key) {return existing[key]});
153
- var changes = actions.sort(function(a, b) {return a.action - b.action || a.index - b.index});
154
- var newCached = cached.slice();
155
-
156
- for (var i = 0, change; change = changes[i]; i++) {
157
- if (change.action == DELETION) {
158
- clear(cached[change.index].nodes, cached[change.index]);
159
- newCached.splice(change.index, 1)
160
- }
161
- if (change.action == INSERTION) {
162
- var dummy = $document.createElement("div");
163
- dummy.key = data[change.index].attrs.key;
164
- parentElement.insertBefore(dummy, parentElement.childNodes[change.index] || null);
165
- newCached.splice(change.index, 0, {attrs: {key: data[change.index].attrs.key}, nodes: [dummy]})
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
- if (change.action == MOVE) {
169
- if (parentElement.childNodes[change.index] !== change.element && change.element !== null) {
170
- parentElement.insertBefore(change.element, parentElement.childNodes[change.index] || null)
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; i < data.length; i++) {
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) == ARRAY ? item.length : 1;
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; i < data.length; i++) {
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 == OBJECT) {
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 == FUNCTION) 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: dataAttrKeys.length ? setAttributes(node, data.tag, data.attrs, {}, namespace) : {},
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 == "select" && data.attrs.value) setAttributes(node, data.tag, {value: data.attrs.value}, {}, namespace);
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 (dataAttrKeys.length) setAttributes(node, data.tag, data.attrs, cached.attrs, namespace);
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"] == FUNCTION) {
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 == 1 || nodes.length > 1) { //was a trusted string
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
- //we don't ignore `key` because it must be unique and having it on the DOM helps debugging
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 == FUNCTION && attrName.indexOf("on") == 0) {
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) == OBJECT) {
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 == "list" || attrName == "style" || attrName == "form" || attrName == "type")) {
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] != dataAttr) node[attrName] = dataAttr
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 == FUNCTION) 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) == ARRAY) {
379
- for (var i = 0; i < cached.children.length; i++) unload(cached.children[i])
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
- m.endComputation()
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 == $document;
437
- var node = isDocumentRoot || root == $document.documentElement ? documentNode : 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; i < configs.length; i++) configs[i]()
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) == OBJECT) || typeof store == FUNCTION) && typeof store.then == FUNCTION) {
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 == FUNCTION) {
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 == topModule) {
513
+ if (currentModule === topModule) {
498
514
  controllers[index] = controller;
499
515
  modules[index] = module
500
516
  }
501
- m.endComputation();
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 == window.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 mode = m.redraw.strategy();
524
- for (var i = 0; i < roots.length; i++) {
525
- if (controllers[i] && mode != "none") {
526
- m.render(roots[i], modules[i].view(controllers[i]), mode == "all")
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 == 0) m.redraw()
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]) == STRING) {
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 == "hash" ? "onhashchange" : "onpopstate";
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]) == STRING) {
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 == 3 ? arguments[2] : arguments[1]) === true;
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 == path) {
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; i < keys.length; i++) routeParams[keys[i].replace(/:|\./g, "")] = decodeURIComponent(values[i])
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 == 2) return;
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 == "pathname" && currentTarget.search ? parseQueryString(currentTarget.search.slice(1)) : {};
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) == OBJECT ? buildQueryString(value, key) : encodeURIComponent(key) + "=" + encodeURIComponent(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; i < pairs.length; i++) {
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 == RESOLVED) {
750
+ if (state === RESOLVED) {
728
751
  deferred.resolve(promiseValue)
729
752
  }
730
- else if (state == REJECTED) {
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 == RESOLVED && deferred.resolve(promiseValue) || deferred.reject(promiseValue)
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) == OBJECT) || typeof promiseValue == FUNCTION) && typeof then == FUNCTION) {
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 == RESOLVING && typeof successCallback == FUNCTION) {
814
+ if (state === RESOLVING && typeof successCallback === FUNCTION) {
792
815
  promiseValue = successCallback(promiseValue)
793
816
  }
794
- else if (state == REJECTING && typeof failureCallback == "function") {
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 == self) {
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 == RESOLVING && RESOLVED)
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) == "[object Error]" && !e.constructor.toString().match(/ Error/)) throw 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 == 0) {
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 == JSON.stringify && options.data && options.method != "GET") {
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 == JSON.parse) {
928
+ if (options.deserialize === JSON.parse) {
906
929
  xhr.setRequestHeader("Accept", "application/json, text/*");
907
930
  }
908
- if (typeof options.config == FUNCTION) {
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 == "GET" || !options.data ? "" : options.data
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 == "GET" && xhrOptions.dataType != "jsonp") {
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 == "load" ? xhrOptions.unwrapSuccess : xhrOptions.unwrapError) || identity;
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 == "load") {
959
- if (type.call(response) == ARRAY && xhrOptions.type) {
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 == "load" ? "resolve" : "reject"](response)
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 == "function" && define.amd) define(function() {return m});
1012
+ else if (typeof define === "function" && define.amd) define(function() {return m});
@@ -1,3 +1,3 @@
1
1
  module MithrilRails
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5"
3
3
  end
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
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: 2014-12-05 00:00:00.000000000 Z
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: '0'
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: '0'
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: 4.1.0
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: 4.1.0
40
+ version: 3.2.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: sqlite3
43
43
  requirement: !ruby/object:Gem::Requirement