joosy 1.2.0.alpha.73 → 1.2.0.beta.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.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/Gruntfile.coffee +56 -18
  3. data/bower.json +1 -1
  4. data/build/joosy/form.js +1 -0
  5. data/build/joosy/resources.js +1 -0
  6. data/build/joosy.js +2 -2774
  7. data/package.json +5 -4
  8. data/source/joosy/application.coffee +9 -7
  9. data/source/joosy/{extensions/resources-form/form.coffee → form.coffee} +58 -51
  10. data/source/joosy/helpers/form.coffee +241 -0
  11. data/source/joosy/helpers/index.coffee +3 -0
  12. data/source/joosy/helpers/routes.coffee +3 -1
  13. data/source/joosy/helpers/view.coffee +9 -9
  14. data/source/joosy/joosy.coffee +3 -5
  15. data/source/joosy/module.coffee +9 -4
  16. data/source/joosy/modules/dom.coffee +33 -31
  17. data/source/joosy/modules/events.coffee +24 -20
  18. data/source/joosy/modules/filters.coffee +38 -35
  19. data/source/joosy/modules/page/title.coffee +3 -3
  20. data/source/joosy/modules/renderer.coffee +23 -18
  21. data/source/joosy/modules/resources/identity_map.coffee +45 -0
  22. data/source/joosy/modules/resources/model.coffee +146 -0
  23. data/source/joosy/modules/widgets_manager.coffee +8 -8
  24. data/source/joosy/resources/array.coffee +0 -5
  25. data/source/joosy/resources/hash.coffee +8 -13
  26. data/source/joosy/resources/index.coffee +2 -0
  27. data/source/joosy/{extensions/resources → resources}/rest.coffee +48 -19
  28. data/source/joosy/resources/scalar.coffee +8 -10
  29. data/source/joosy/router.coffee +13 -12
  30. data/source/joosy/templaters/jst.coffee +3 -2
  31. data/source/joosy/widget.coffee +17 -15
  32. data/source/joosy.coffee +2 -0
  33. data/source/vendor/es5-shim.js +1316 -0
  34. data/source/vendor/inflections.js +598 -0
  35. data/source/vendor/metamorph.js +457 -0
  36. data/spec/helpers/matchers.coffee +4 -4
  37. data/spec/joosy/core/application_spec.coffee +1 -1
  38. data/spec/joosy/core/helpers/view_spec.coffee +2 -2
  39. data/spec/joosy/core/joosy_spec.coffee +8 -4
  40. data/spec/joosy/core/modules/dom_spec.coffee +7 -7
  41. data/spec/joosy/core/modules/events_spec.coffee +2 -2
  42. data/spec/joosy/core/modules/filters_spec.coffee +7 -8
  43. data/spec/joosy/core/modules/module_spec.coffee +5 -5
  44. data/spec/joosy/core/router_spec.coffee +3 -3
  45. data/spec/joosy/core/widget_spec.coffee +6 -6
  46. data/spec/joosy/environments/amd_spec.coffee +4 -2
  47. data/spec/joosy/environments/global_spec.coffee +1 -1
  48. data/spec/joosy/{extensions/form → form}/form_spec.coffee +9 -16
  49. data/spec/joosy/{extensions/form → form}/helpers/forms_spec.coffee +5 -5
  50. data/spec/joosy/{core/resources → resources}/array_spec.coffee +2 -2
  51. data/spec/joosy/{core/resources → resources}/hash_spec.coffee +0 -8
  52. data/spec/joosy/{core/modules/resources → resources/modules}/cacher_spec.coffee +0 -0
  53. data/spec/joosy/resources/modules/identity_map_spec.coffee +47 -0
  54. data/spec/joosy/{extensions/resources/base_spec.coffee → resources/modules/model_spec.coffee} +28 -48
  55. data/spec/joosy/{extensions/resources → resources}/rest_spec.coffee +29 -22
  56. data/spec/joosy/{core/resources → resources}/scalar_spec.coffee +8 -8
  57. data/templates/application/application.coffee.tt +0 -2
  58. data/templates/environment/app/haml/index.haml +2 -2
  59. data/templates/environment/package.json +1 -1
  60. metadata +23 -19
  61. data/build/joosy/extensions/resources-form.js +0 -590
  62. data/build/joosy/extensions/resources.js +0 -561
  63. data/source/joosy/extensions/resources/base.coffee +0 -282
  64. data/source/joosy/extensions/resources/index.coffee +0 -1
  65. data/source/joosy/extensions/resources-form/helpers/form.coffee +0 -104
  66. data/source/joosy/extensions/resources-form/index.coffee +0 -1
  67. data/source/metamorph.coffee +0 -410
@@ -0,0 +1,457 @@
1
+ // ==========================================================================
2
+ // Project: metamorph
3
+ // Copyright: ©2013 Tilde, Inc. All rights reserved.
4
+ // ==========================================================================
5
+
6
+ (function(window) {
7
+
8
+ var K = function(){},
9
+ guid = 0,
10
+ document = window.document,
11
+ disableRange = ('undefined' === typeof ENV ? {} : ENV).DISABLE_RANGE_API,
12
+
13
+ // Feature-detect the W3C range API, the extended check is for IE9 which only partially supports ranges
14
+ supportsRange = (!disableRange) && document && ('createRange' in document) && (typeof Range !== 'undefined') && Range.prototype.createContextualFragment,
15
+
16
+ // Internet Explorer prior to 9 does not allow setting innerHTML if the first element
17
+ // is a "zero-scope" element. This problem can be worked around by making
18
+ // the first node an invisible text node. We, like Modernizr, use ­
19
+ needsShy = document && (function(){
20
+ var testEl = document.createElement('div');
21
+ testEl.innerHTML = "<div></div>";
22
+ testEl.firstChild.innerHTML = "<script></script>";
23
+ return testEl.firstChild.innerHTML === '';
24
+ })(),
25
+
26
+
27
+ // IE 8 (and likely earlier) likes to move whitespace preceeding
28
+ // a script tag to appear after it. This means that we can
29
+ // accidentally remove whitespace when updating a morph.
30
+ movesWhitespace = document && (function() {
31
+ var testEl = document.createElement('div');
32
+ testEl.innerHTML = "Test: <script type='text/x-placeholder'></script>Value";
33
+ return testEl.childNodes[0].nodeValue === 'Test:' &&
34
+ testEl.childNodes[2].nodeValue === ' Value';
35
+ })();
36
+
37
+ // Constructor that supports either Metamorph('foo') or new
38
+ // Metamorph('foo');
39
+ //
40
+ // Takes a string of HTML as the argument.
41
+
42
+ var Metamorph = function(html) {
43
+ var self;
44
+
45
+ if (this instanceof Metamorph) {
46
+ self = this;
47
+ } else {
48
+ self = new K();
49
+ }
50
+
51
+ self.innerHTML = html;
52
+ var myGuid = 'metamorph-'+(guid++);
53
+ self.start = myGuid + '-start';
54
+ self.end = myGuid + '-end';
55
+
56
+ return self;
57
+ };
58
+
59
+ K.prototype = Metamorph.prototype;
60
+
61
+ var rangeFor, htmlFunc, removeFunc, outerHTMLFunc, appendToFunc, afterFunc, prependFunc, startTagFunc, endTagFunc;
62
+
63
+ outerHTMLFunc = function() {
64
+ return this.startTag() + this.innerHTML + this.endTag();
65
+ };
66
+
67
+ startTagFunc = function() {
68
+ /*
69
+ * We replace chevron by its hex code in order to prevent escaping problems.
70
+ * Check this thread for more explaination:
71
+ * http://stackoverflow.com/questions/8231048/why-use-x3c-instead-of-when-generating-html-from-javascript
72
+ */
73
+ return "<script id='" + this.start + "' type='text/x-placeholder'>\x3C/script>";
74
+ };
75
+
76
+ endTagFunc = function() {
77
+ /*
78
+ * We replace chevron by its hex code in order to prevent escaping problems.
79
+ * Check this thread for more explaination:
80
+ * http://stackoverflow.com/questions/8231048/why-use-x3c-instead-of-when-generating-html-from-javascript
81
+ */
82
+ return "<script id='" + this.end + "' type='text/x-placeholder'>\x3C/script>";
83
+ };
84
+
85
+ // If we have the W3C range API, this process is relatively straight forward.
86
+ if (supportsRange) {
87
+
88
+ // Get a range for the current morph. Optionally include the starting and
89
+ // ending placeholders.
90
+ rangeFor = function(morph, outerToo) {
91
+ var range = document.createRange();
92
+ var before = document.getElementById(morph.start);
93
+ var after = document.getElementById(morph.end);
94
+
95
+ if (outerToo) {
96
+ range.setStartBefore(before);
97
+ range.setEndAfter(after);
98
+ } else {
99
+ range.setStartAfter(before);
100
+ range.setEndBefore(after);
101
+ }
102
+
103
+ return range;
104
+ };
105
+
106
+ htmlFunc = function(html, outerToo) {
107
+ // get a range for the current metamorph object
108
+ var range = rangeFor(this, outerToo);
109
+
110
+ // delete the contents of the range, which will be the
111
+ // nodes between the starting and ending placeholder.
112
+ range.deleteContents();
113
+
114
+ // create a new document fragment for the HTML
115
+ var fragment = range.createContextualFragment(html);
116
+
117
+ // insert the fragment into the range
118
+ range.insertNode(fragment);
119
+ };
120
+
121
+ removeFunc = function() {
122
+ // get a range for the current metamorph object including
123
+ // the starting and ending placeholders.
124
+ var range = rangeFor(this, true);
125
+
126
+ // delete the entire range.
127
+ range.deleteContents();
128
+ };
129
+
130
+ appendToFunc = function(node) {
131
+ var range = document.createRange();
132
+ range.setStart(node);
133
+ range.collapse(false);
134
+ var frag = range.createContextualFragment(this.outerHTML());
135
+ node.appendChild(frag);
136
+ };
137
+
138
+ afterFunc = function(html) {
139
+ var range = document.createRange();
140
+ var after = document.getElementById(this.end);
141
+
142
+ range.setStartAfter(after);
143
+ range.setEndAfter(after);
144
+
145
+ var fragment = range.createContextualFragment(html);
146
+ range.insertNode(fragment);
147
+ };
148
+
149
+ prependFunc = function(html) {
150
+ var range = document.createRange();
151
+ var start = document.getElementById(this.start);
152
+
153
+ range.setStartAfter(start);
154
+ range.setEndAfter(start);
155
+
156
+ var fragment = range.createContextualFragment(html);
157
+ range.insertNode(fragment);
158
+ };
159
+
160
+ } else {
161
+ /**
162
+ * This code is mostly taken from jQuery, with one exception. In jQuery's case, we
163
+ * have some HTML and we need to figure out how to convert it into some nodes.
164
+ *
165
+ * In this case, jQuery needs to scan the HTML looking for an opening tag and use
166
+ * that as the key for the wrap map. In our case, we know the parent node, and
167
+ * can use its type as the key for the wrap map.
168
+ **/
169
+ var wrapMap = {
170
+ select: [ 1, "<select multiple='multiple'>", "</select>" ],
171
+ fieldset: [ 1, "<fieldset>", "</fieldset>" ],
172
+ table: [ 1, "<table>", "</table>" ],
173
+ tbody: [ 2, "<table><tbody>", "</tbody></table>" ],
174
+ tr: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
175
+ colgroup: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
176
+ map: [ 1, "<map>", "</map>" ],
177
+ _default: [ 0, "", "" ]
178
+ };
179
+
180
+ var findChildById = function(element, id) {
181
+ if (element.getAttribute('id') === id) { return element; }
182
+
183
+ var len = element.childNodes.length, idx, node, found;
184
+ for (idx=0; idx<len; idx++) {
185
+ node = element.childNodes[idx];
186
+ found = node.nodeType === 1 && findChildById(node, id);
187
+ if (found) { return found; }
188
+ }
189
+ };
190
+
191
+ var setInnerHTML = function(element, html) {
192
+ var matches = [];
193
+ if (movesWhitespace) {
194
+ // Right now we only check for script tags with ids with the
195
+ // goal of targeting morphs.
196
+ html = html.replace(/(\s+)(<script id='([^']+)')/g, function(match, spaces, tag, id) {
197
+ matches.push([id, spaces]);
198
+ return tag;
199
+ });
200
+ }
201
+
202
+ element.innerHTML = html;
203
+
204
+ // If we have to do any whitespace adjustments do them now
205
+ if (matches.length > 0) {
206
+ var len = matches.length, idx;
207
+ for (idx=0; idx<len; idx++) {
208
+ var script = findChildById(element, matches[idx][0]),
209
+ node = document.createTextNode(matches[idx][1]);
210
+ script.parentNode.insertBefore(node, script);
211
+ }
212
+ }
213
+ };
214
+
215
+ /**
216
+ * Given a parent node and some HTML, generate a set of nodes. Return the first
217
+ * node, which will allow us to traverse the rest using nextSibling.
218
+ *
219
+ * We need to do this because innerHTML in IE does not really parse the nodes.
220
+ **/
221
+ var firstNodeFor = function(parentNode, html) {
222
+ var arr = wrapMap[parentNode.tagName.toLowerCase()] || wrapMap._default;
223
+ var depth = arr[0], start = arr[1], end = arr[2];
224
+
225
+ if (needsShy) { html = '&shy;'+html; }
226
+
227
+ var element = document.createElement('div');
228
+
229
+ setInnerHTML(element, start + html + end);
230
+
231
+ for (var i=0; i<=depth; i++) {
232
+ element = element.firstChild;
233
+ }
234
+
235
+ // Look for &shy; to remove it.
236
+ if (needsShy) {
237
+ var shyElement = element;
238
+
239
+ // Sometimes we get nameless elements with the shy inside
240
+ while (shyElement.nodeType === 1 && !shyElement.nodeName) {
241
+ shyElement = shyElement.firstChild;
242
+ }
243
+
244
+ // At this point it's the actual unicode character.
245
+ if (shyElement.nodeType === 3 && shyElement.nodeValue.charAt(0) === "\u00AD") {
246
+ shyElement.nodeValue = shyElement.nodeValue.slice(1);
247
+ }
248
+ }
249
+
250
+ return element;
251
+ };
252
+
253
+ /**
254
+ * In some cases, Internet Explorer can create an anonymous node in
255
+ * the hierarchy with no tagName. You can create this scenario via:
256
+ *
257
+ * div = document.createElement("div");
258
+ * div.innerHTML = "<table>&shy<script></script><tr><td>hi</td></tr></table>";
259
+ * div.firstChild.firstChild.tagName //=> ""
260
+ *
261
+ * If our script markers are inside such a node, we need to find that
262
+ * node and use *it* as the marker.
263
+ **/
264
+ var realNode = function(start) {
265
+ while (start.parentNode.tagName === "") {
266
+ start = start.parentNode;
267
+ }
268
+
269
+ return start;
270
+ };
271
+
272
+ /**
273
+ * When automatically adding a tbody, Internet Explorer inserts the
274
+ * tbody immediately before the first <tr>. Other browsers create it
275
+ * before the first node, no matter what.
276
+ *
277
+ * This means the the following code:
278
+ *
279
+ * div = document.createElement("div");
280
+ * div.innerHTML = "<table><script id='first'></script><tr><td>hi</td></tr><script id='last'></script></table>
281
+ *
282
+ * Generates the following DOM in IE:
283
+ *
284
+ * + div
285
+ * + table
286
+ * - script id='first'
287
+ * + tbody
288
+ * + tr
289
+ * + td
290
+ * - "hi"
291
+ * - script id='last'
292
+ *
293
+ * Which means that the two script tags, even though they were
294
+ * inserted at the same point in the hierarchy in the original
295
+ * HTML, now have different parents.
296
+ *
297
+ * This code reparents the first script tag by making it the tbody's
298
+ * first child.
299
+ **/
300
+ var fixParentage = function(start, end) {
301
+ if (start.parentNode !== end.parentNode) {
302
+ end.parentNode.insertBefore(start, end.parentNode.firstChild);
303
+ }
304
+ };
305
+
306
+ htmlFunc = function(html, outerToo) {
307
+ // get the real starting node. see realNode for details.
308
+ var start = realNode(document.getElementById(this.start));
309
+ var end = document.getElementById(this.end);
310
+ var parentNode = end.parentNode;
311
+ var node, nextSibling, last;
312
+
313
+ // make sure that the start and end nodes share the same
314
+ // parent. If not, fix it.
315
+ fixParentage(start, end);
316
+
317
+ // remove all of the nodes after the starting placeholder and
318
+ // before the ending placeholder.
319
+ node = start.nextSibling;
320
+ while (node) {
321
+ nextSibling = node.nextSibling;
322
+ last = node === end;
323
+
324
+ // if this is the last node, and we want to remove it as well,
325
+ // set the `end` node to the next sibling. This is because
326
+ // for the rest of the function, we insert the new nodes
327
+ // before the end (note that insertBefore(node, null) is
328
+ // the same as appendChild(node)).
329
+ //
330
+ // if we do not want to remove it, just break.
331
+ if (last) {
332
+ if (outerToo) { end = node.nextSibling; } else { break; }
333
+ }
334
+
335
+ node.parentNode.removeChild(node);
336
+
337
+ // if this is the last node and we didn't break before
338
+ // (because we wanted to remove the outer nodes), break
339
+ // now.
340
+ if (last) { break; }
341
+
342
+ node = nextSibling;
343
+ }
344
+
345
+ // get the first node for the HTML string, even in cases like
346
+ // tables and lists where a simple innerHTML on a div would
347
+ // swallow some of the content.
348
+ node = firstNodeFor(start.parentNode, html);
349
+
350
+ // copy the nodes for the HTML between the starting and ending
351
+ // placeholder.
352
+ while (node) {
353
+ nextSibling = node.nextSibling;
354
+ parentNode.insertBefore(node, end);
355
+ node = nextSibling;
356
+ }
357
+ };
358
+
359
+ // remove the nodes in the DOM representing this metamorph.
360
+ //
361
+ // this includes the starting and ending placeholders.
362
+ removeFunc = function() {
363
+ var start = realNode(document.getElementById(this.start));
364
+ var end = document.getElementById(this.end);
365
+
366
+ this.html('');
367
+ start.parentNode.removeChild(start);
368
+ end.parentNode.removeChild(end);
369
+ };
370
+
371
+ appendToFunc = function(parentNode) {
372
+ var node = firstNodeFor(parentNode, this.outerHTML());
373
+ var nextSibling;
374
+
375
+ while (node) {
376
+ nextSibling = node.nextSibling;
377
+ parentNode.appendChild(node);
378
+ node = nextSibling;
379
+ }
380
+ };
381
+
382
+ afterFunc = function(html) {
383
+ // get the real starting node. see realNode for details.
384
+ var end = document.getElementById(this.end);
385
+ var insertBefore = end.nextSibling;
386
+ var parentNode = end.parentNode;
387
+ var nextSibling;
388
+ var node;
389
+
390
+ // get the first node for the HTML string, even in cases like
391
+ // tables and lists where a simple innerHTML on a div would
392
+ // swallow some of the content.
393
+ node = firstNodeFor(parentNode, html);
394
+
395
+ // copy the nodes for the HTML between the starting and ending
396
+ // placeholder.
397
+ while (node) {
398
+ nextSibling = node.nextSibling;
399
+ parentNode.insertBefore(node, insertBefore);
400
+ node = nextSibling;
401
+ }
402
+ };
403
+
404
+ prependFunc = function(html) {
405
+ var start = document.getElementById(this.start);
406
+ var parentNode = start.parentNode;
407
+ var nextSibling;
408
+ var node;
409
+
410
+ node = firstNodeFor(parentNode, html);
411
+ var insertBefore = start.nextSibling;
412
+
413
+ while (node) {
414
+ nextSibling = node.nextSibling;
415
+ parentNode.insertBefore(node, insertBefore);
416
+ node = nextSibling;
417
+ }
418
+ };
419
+ }
420
+
421
+ Metamorph.prototype.html = function(html) {
422
+ this.checkRemoved();
423
+ if (html === undefined) { return this.innerHTML; }
424
+
425
+ htmlFunc.call(this, html);
426
+
427
+ this.innerHTML = html;
428
+ };
429
+
430
+ Metamorph.prototype.replaceWith = function(html) {
431
+ this.checkRemoved();
432
+ htmlFunc.call(this, html, true);
433
+ };
434
+
435
+ Metamorph.prototype.remove = removeFunc;
436
+ Metamorph.prototype.outerHTML = outerHTMLFunc;
437
+ Metamorph.prototype.appendTo = appendToFunc;
438
+ Metamorph.prototype.after = afterFunc;
439
+ Metamorph.prototype.prepend = prependFunc;
440
+ Metamorph.prototype.startTag = startTagFunc;
441
+ Metamorph.prototype.endTag = endTagFunc;
442
+
443
+ Metamorph.prototype.isRemoved = function() {
444
+ var before = document.getElementById(this.start);
445
+ var after = document.getElementById(this.end);
446
+
447
+ return !before || !after;
448
+ };
449
+
450
+ Metamorph.prototype.checkRemoved = function() {
451
+ if (this.isRemoved()) {
452
+ throw new Error("Cannot perform operations on a Metamorph that is not in the DOM.");
453
+ }
454
+ };
455
+
456
+ window.Metamorph = Metamorph;
457
+ })(this);
@@ -2,7 +2,7 @@ beforeEach ->
2
2
  @addMatchers
3
3
 
4
4
  #
5
- # Checks whether listed array of callbacks was
5
+ # Checks whether listed array of callbacks was
6
6
  # called in exact order one by one
7
7
  #
8
8
  # @example
@@ -10,7 +10,7 @@ beforeEach ->
10
10
  #
11
11
  toBeSequenced: ->
12
12
  # Are we working with array?
13
- if !Object.isArray(@actual) || @actual.length == 0
13
+ if !Array.isArray(@actual) || @actual.length == 0
14
14
  @message = -> 'Not array or empty array given'
15
15
  return false
16
16
 
@@ -22,7 +22,7 @@ beforeEach ->
22
22
 
23
23
  # Were they called in a proper order?
24
24
  if @actual.length > 1
25
- for spy, i in @actual.from(1)
25
+ for spy, i in @actual.slice(1)
26
26
  unless spy.calledAfter @actual[i]
27
27
  @message = -> "Spy ##{i+1} wasn't called after spy ##{i}"
28
28
  return false
@@ -69,4 +69,4 @@ beforeEach ->
69
69
  else
70
70
  flag &&= tag.attr(name) == val
71
71
 
72
- flag
72
+ flag
@@ -109,7 +109,7 @@ describe "Joosy.Application", ->
109
109
 
110
110
  it "sequences paint hooks", ->
111
111
  spies = []
112
- 11.times -> spies.push sinon.spy()
112
+ spies.push sinon.spy() for i in [1..11]
113
113
 
114
114
  class Layout extends Joosy.Layout
115
115
  @beforePaint (complete) -> spies[0](); complete()
@@ -8,7 +8,7 @@ describe "Joosy.Helpers.View", ->
8
8
  expect(tag).toEqual '<div id="id">content</div>'
9
9
 
10
10
  it "renders tag with lambda content", ->
11
- tag = h.contentTag 'div', {id: 'id'}, ->
11
+ tag = h.contentTag 'div', {id: 'id'}, ->
12
12
  h.contentTag 'div', 'content', {id: 'id2'}
13
13
 
14
- expect(tag).toEqual '<div id="id"><div id="id2">content</div></div>'
14
+ expect(tag).toEqual '<div id="id"><div id="id2">content</div></div>'
@@ -1,15 +1,19 @@
1
1
  describe "Joosy", ->
2
2
 
3
+ unique = (array) ->
4
+ array.filter (item, index, array) ->
5
+ array.indexOf(item) == index
6
+
3
7
  it "generates proper UUIDs", ->
4
8
  uuids = []
5
- 2.times -> uuids.push Joosy.uuid()
6
- expect(uuids.unique().length).toEqual(2)
9
+ uuids.push Joosy.uuid() for i in [1..2]
10
+ expect(unique(uuids).length).toEqual(2)
7
11
  expect(uuids[0]).toMatch /[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}/
8
12
 
9
13
  it "generates proper UIDs", ->
10
14
  uids = []
11
- 5.times -> uids.push Joosy.uid()
12
- expect(uids.unique().length).toEqual(5)
15
+ uids.push Joosy.uid() for i in [1..5]
16
+ expect(unique(uids).length).toEqual(5)
13
17
 
14
18
  it "builds proper URLs", ->
15
19
  expect(Joosy.buildUrl 'http://www.org').toEqual('http://www.org')
@@ -36,9 +36,9 @@ describe "Joosy.Modules.DOM", ->
36
36
  first: 'overrided'
37
37
  third: 'third'
38
38
 
39
- expect((new B).__elements).toEqual Object.extended
39
+ expect((new B).__elements).toEqual
40
40
  posts: '.post'
41
- content:
41
+ content:
42
42
  post1: '#post1'
43
43
  post2: '#post2'
44
44
  first: 'overrided'
@@ -46,10 +46,10 @@ describe "Joosy.Modules.DOM", ->
46
46
  third: 'third'
47
47
  footer: '.footer'
48
48
 
49
- expect((new @DOM).__elements).toEqual Object.extended
49
+ expect((new @DOM).__elements).toEqual
50
50
  posts: '.post'
51
51
  footer: '.footer'
52
- content:
52
+ content:
53
53
  post1: '#post1'
54
54
  post2: '#post2'
55
55
 
@@ -102,17 +102,17 @@ describe "Joosy.Modules.DOM", ->
102
102
  'test $footer': 'onFooterTest'
103
103
  'custom' : 'overrided'
104
104
 
105
- expect((new B).__events).toEqual Object.extended
105
+ expect((new B).__events).toEqual
106
106
  'test': 'onDOMTest'
107
107
  'test .post': 'callback2'
108
108
  'test $footer': 'onFooterTest'
109
109
  'custom' : 'overrided'
110
110
 
111
- expect((new @DOM).__events).toEqual Object.extended
111
+ expect((new @DOM).__events).toEqual
112
112
  'test': 'onDOMTest'
113
113
 
114
114
  it "delegates", ->
115
- callbacks = 1.upto(3).map -> sinon.spy()
115
+ callbacks = [1..3].map -> sinon.spy()
116
116
 
117
117
  @DOM.mapEvents
118
118
  'test .post': callbacks[2]
@@ -88,8 +88,8 @@ describe "Joosy.Modules.Events", ->
88
88
  expect(@callback.callCount).toEqual 1
89
89
 
90
90
  it "allows simultaneous usage", ->
91
- 3.times (i) => @eventer.bind "event#{i}", @callback
92
- 3.times (i) => @eventer.wait "event#{i}", @callback
91
+ @eventer.bind "event#{i}", @callback for i in [1..3]
92
+ @eventer.wait "event#{i}", @callback for i in [1..3]
93
93
 
94
94
  @eventer.trigger 'event2'
95
95
 
@@ -36,7 +36,7 @@ describe "Joosy.Modules.Filters", ->
36
36
  expect(target.__afterUnloads).toBeUndefined()
37
37
 
38
38
  it "runs callbacks", ->
39
- callbacks = 0.upto(2).map -> sinon.spy()
39
+ callbacks = [0..2].map -> sinon.spy()
40
40
  @Filters.beforeLoad callbacks[0]
41
41
  @Filters.afterLoad callbacks[1]
42
42
  @Filters.afterUnload callbacks[2]
@@ -45,14 +45,14 @@ describe "Joosy.Modules.Filters", ->
45
45
  @filters.__runAfterLoads 1, 2
46
46
  @filters.__runAfterUnloads 1, 2
47
47
 
48
- for i in 0.upto(2)
48
+ for i in [0..2]
49
49
  expect(callbacks[i].callCount).toEqual 1
50
50
  expect(callbacks[i].alwaysCalledWithExactly 1, 2).toBeTruthy()
51
51
 
52
52
  describe "chaining", ->
53
53
 
54
54
  it "evaluates", ->
55
- callbacks = 0.upto(1).map =>
55
+ callbacks = [0..1].map =>
56
56
  callback = sinon.stub()
57
57
  @Filters.beforeLoad callback
58
58
  callback
@@ -66,7 +66,7 @@ describe "Joosy.Modules.Filters", ->
66
66
  expect(callbacks[1].callCount).toEqual 1
67
67
 
68
68
  it "breaks on false", ->
69
- callbacks = 0.upto(2).map =>
69
+ callbacks = [0..2].map =>
70
70
  callback = sinon.stub()
71
71
  @Filters.beforeLoad callback
72
72
  callback
@@ -81,7 +81,7 @@ describe "Joosy.Modules.Filters", ->
81
81
  expect(callbacks[2].callCount).toEqual 0
82
82
 
83
83
  it "accepts method names as callbacks", ->
84
- @filters['callback' + i] = sinon.spy() for i in 0.upto(2)
84
+ @filters['callback' + i] = sinon.spy() for i in [0..2]
85
85
 
86
86
  @Filters.beforeLoad 'callback0'
87
87
  @Filters.afterLoad 'callback1'
@@ -91,8 +91,7 @@ describe "Joosy.Modules.Filters", ->
91
91
  @filters.__runAfterLoads()
92
92
  @filters.__runAfterUnloads()
93
93
 
94
- expect(@filters['callback' + i].callCount).toEqual 1 for i in 0.upto(2)
95
-
94
+ expect(@filters['callback' + i].callCount).toEqual 1 for i in [0..2]
96
95
  describe 'sequenced', ->
97
96
 
98
97
  beforeEach ->
@@ -165,7 +164,7 @@ describe "Joosy.Modules.Filters", ->
165
164
  expect(spy.args[2][1]).toEqual 'test2'
166
165
 
167
166
  it "runs multiple callbacks", ->
168
- spies = 0.upto(2).map -> sinon.spy()
167
+ spies = [0..2].map -> sinon.spy()
169
168
  context = @filters
170
169
 
171
170
  @Filters.beforeLoad (argument, complete) ->
@@ -9,9 +9,9 @@ describe "Joosy.Module", ->
9
9
  for a in [A, B, C, D]
10
10
  for b in [A, B, C, D]
11
11
  if (a == b) ||
12
- ((a == B) && (b == A)) ||
13
- ((a == C) && (b != D))
14
- expect(Joosy.Module.hasAncestor a, b).toBeTruthy()
12
+ ((a == B) && (b == A)) ||
13
+ ((a == C) && (b != D))
14
+ expect(Joosy.Module.hasAncestor a, b).toBeTruthy()
15
15
  else
16
16
  expect(Joosy.Module.hasAncestor a, b).toBeFalsy()
17
17
 
@@ -19,8 +19,8 @@ describe "Joosy.Module", ->
19
19
  it "has minimal set of properties", ->
20
20
  class Klass extends Joosy.Module
21
21
 
22
- expect(Object.extended(Klass).keys()).toEqual ['__namespace__', '__className', 'hasAncestor', 'aliasMethodChain', 'aliasStaticMethodChain', 'merge', 'include', 'extend', '__super__']
23
- expect(Object.extended(Klass.prototype).keys()).toEqual ['constructor']
22
+ expect(Object.keys Klass).toEqual ['__namespace__', '__className', 'hasAncestor', 'aliasMethodChain', 'aliasStaticMethodChain', 'merge', 'include', 'extend', '__super__']
23
+ expect(Object.keys Klass.prototype).toEqual ['constructor']
24
24
 
25
25
  it "includes", ->
26
26
  Module =