cornerstone-source 0.1.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 (51) hide show
  1. data/.gitignore +22 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE +22 -0
  4. data/README.md +20 -0
  5. data/Rakefile +8 -0
  6. data/config.rb +79 -0
  7. data/config.ru +4 -0
  8. data/cornerstone.gemspec +22 -0
  9. data/doc_scraper.rb +51 -0
  10. data/game.js +4293 -0
  11. data/lib/assets/javascripts/cornerstone.js +4719 -0
  12. data/lib/cornerstone.rb +11 -0
  13. data/lib/cornerstone/rails.rb +5 -0
  14. data/lib/cornerstone/sprockets.rb +2 -0
  15. data/lib/cornerstone/version.rb +3 -0
  16. data/manifest.json +15 -0
  17. data/pixie.json +12 -0
  18. data/source/javascripts/_cornerstone/_object_extensions.js.coffee +108 -0
  19. data/source/javascripts/_cornerstone/array_extensions.js.coffee +570 -0
  20. data/source/javascripts/_cornerstone/bindable.js.coffee +125 -0
  21. data/source/javascripts/_cornerstone/command_stack.js.coffee +36 -0
  22. data/source/javascripts/_cornerstone/core_object.js.coffee +183 -0
  23. data/source/javascripts/_cornerstone/function_extensions.js.coffee +60 -0
  24. data/source/javascripts/_cornerstone/logging.js.coffee +19 -0
  25. data/source/javascripts/_cornerstone/matrix.js.coffee +337 -0
  26. data/source/javascripts/_cornerstone/number_extensions.js.coffee +491 -0
  27. data/source/javascripts/_cornerstone/point.js.coffee +641 -0
  28. data/source/javascripts/_cornerstone/random.js.coffee +86 -0
  29. data/source/javascripts/_cornerstone/rectangle.js.coffee +35 -0
  30. data/source/javascripts/_cornerstone/string_extensions.js.coffee +232 -0
  31. data/source/javascripts/_cornerstone/stubs.js.coffee +1042 -0
  32. data/source/javascripts/_cornerstone/uuid.js +96 -0
  33. data/source/javascripts/_test/array_extensions.coffee +173 -0
  34. data/source/javascripts/_test/bindable.coffee +68 -0
  35. data/source/javascripts/_test/command_stack.coffee +99 -0
  36. data/source/javascripts/_test/core_object.coffee +95 -0
  37. data/source/javascripts/_test/function_extensions.coffee +50 -0
  38. data/source/javascripts/_test/logging.coffee +7 -0
  39. data/source/javascripts/_test/matrix.coffee +174 -0
  40. data/source/javascripts/_test/number_extensions.coffee +138 -0
  41. data/source/javascripts/_test/object_extensions.coffee +53 -0
  42. data/source/javascripts/_test/point.coffee +196 -0
  43. data/source/javascripts/_test/random.coffee +22 -0
  44. data/source/javascripts/_test/rectangle.coffee +70 -0
  45. data/source/javascripts/_test/string_extensions.coffee +59 -0
  46. data/source/javascripts/cornerstone.js.coffee +1 -0
  47. data/source/javascripts/cornerstone_tests.js.coffee +2 -0
  48. data/source/test.html.haml +13 -0
  49. data/vendor/javascripts/qunit.js +1275 -0
  50. data/vendor/stylesheets/qunit.css.sass +115 -0
  51. metadata +141 -0
@@ -0,0 +1,11 @@
1
+ require "cornerstone/version"
2
+
3
+ # Sneaky require for Rails engine environment
4
+ if defined? ::Rails::Engine
5
+ require "cornerstone/rails"
6
+ elsif defined? ::Sprockets
7
+ require "cornerstone/sprockets"
8
+ end
9
+
10
+ module Cornerstone
11
+ end
@@ -0,0 +1,5 @@
1
+ module Cornerstone
2
+ class Rails < Rails::Engine
3
+ # auto wire assets
4
+ end
5
+ end
@@ -0,0 +1,2 @@
1
+ root_dir = File.expand_path(File.dirname(File.dirname(File.dirname(__FILE__))))
2
+ Sprockets.paths << File.join(root_dir, "lib", "assets")
@@ -0,0 +1,3 @@
1
+ module Cornerstone
2
+ VERSION = "0.1.1"
3
+ end
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "corelib",
3
+ "description": "Extending JavaScript in all the right ways.",
4
+ "app": {
5
+ "launch": {
6
+ "local_path": "webstore/main.html"
7
+ }
8
+ },
9
+ "version": "0.0.1",
10
+ "icons": {
11
+ "128": "webstore/images/icon_128.png",
12
+ "96": "webstore/images/icon_96.png",
13
+ "16": "webstore/images/icon_16.png"
14
+ }
15
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "author": "PixieEngine",
3
+ "main": null,
4
+ "name": "Cornerstone",
5
+ "library": true,
6
+ "directories": {
7
+ "lib": "vendor/assets/javascripts",
8
+ "source": "_cornerstone",
9
+ "test": "_test"
10
+ },
11
+ "autosave": true
12
+ }
@@ -0,0 +1,108 @@
1
+ ###*
2
+ Checks whether an object is an array.
3
+
4
+ Object.isArray([1, 2, 4])
5
+ # => true
6
+
7
+ Object.isArray({key: "value"})
8
+ # => false
9
+
10
+ @name isArray
11
+ @methodOf Object
12
+ @param {Object} object The object to check for array-ness.
13
+ @returns {Boolean} A boolean expressing whether the object is an instance of Array
14
+ ###
15
+ Object.isArray = (object) ->
16
+ Object::toString.call(object) == "[object Array]"
17
+
18
+ ###*
19
+ Checks whether an object is a string.
20
+
21
+ Object.isString("a string")
22
+ # => true
23
+
24
+ Object.isString([1, 2, 4])
25
+ # => false
26
+
27
+ Object.isString({key: "value"})
28
+ # => false
29
+
30
+ @name isString
31
+ @methodOf Object
32
+ @param {Object} object The object to check for string-ness.
33
+ @returns {Boolean} A boolean expressing whether the object is an instance of String
34
+ ###
35
+ Object.isString = (object) ->
36
+ Object::toString.call(object) == "[object String]"
37
+
38
+ ###*
39
+ Merges properties from objects into target without overiding.
40
+ First come, first served.
41
+
42
+ I =
43
+ a: 1
44
+ b: 2
45
+ c: 3
46
+
47
+ Object.reverseMerge I,
48
+ c: 6
49
+ d: 4
50
+
51
+ I # => {a: 1, b:2, c:3, d: 4}
52
+
53
+ @name reverseMerge
54
+ @methodOf Object
55
+ @param {Object} target The object to merge the properties into.
56
+ @returns {Object} target
57
+ ###
58
+ Object.reverseMerge = (target, objects...) ->
59
+ for object in objects
60
+ for name of object
61
+ unless target.hasOwnProperty(name)
62
+ target[name] = object[name]
63
+
64
+ return target
65
+
66
+ ###*
67
+ Merges properties from sources into target with overiding.
68
+ Last in covers earlier properties.
69
+
70
+ I =
71
+ a: 1
72
+ b: 2
73
+ c: 3
74
+
75
+ Object.extend I,
76
+ c: 6
77
+ d: 4
78
+
79
+ I # => {a: 1, b:2, c:6, d: 4}
80
+
81
+ @name extend
82
+ @methodOf Object
83
+ @param {Object} target The object to merge the properties into.
84
+ @returns {Object} target
85
+ ###
86
+ Object.extend = (target, sources...) ->
87
+ for source in sources
88
+ for name of source
89
+ target[name] = source[name]
90
+
91
+ return target
92
+
93
+ ###*
94
+ Helper method that tells you if something is an object.
95
+
96
+ object = {a: 1}
97
+
98
+ Object.isObject(object)
99
+ # => true
100
+
101
+ @name isObject
102
+ @methodOf Object
103
+ @param {Object} object Maybe this guy is an object.
104
+ @returns {Boolean} true if this guy is an object.
105
+ ###
106
+ Object.isObject = (object) ->
107
+ Object.prototype.toString.call(object) == '[object Object]'
108
+
@@ -0,0 +1,570 @@
1
+ ###*
2
+ Calculate the average value of an array. Returns undefined if some elements
3
+ are not numbers.
4
+
5
+ [1, 3, 5, 7].average()
6
+ # => 4
7
+
8
+ @name average
9
+ @methodOf Array#
10
+ @returns {Number} The average (arithmetic mean) of the list of numbers.
11
+ ###
12
+ Array::average = ->
13
+ @sum()/@length
14
+
15
+ ###*
16
+ Returns a copy of the array without null and undefined values.
17
+
18
+ [null, undefined, 3, 3, undefined, 5].compact()
19
+ # => [3, 3, 5]
20
+
21
+ @name compact
22
+ @methodOf Array#
23
+ @returns {Array} A new array that contains only the non-null values.
24
+ ###
25
+ Array::compact = ->
26
+ this.select (element) ->
27
+ element?
28
+
29
+ ###*
30
+ Creates and returns a copy of the array. The copy contains
31
+ the same objects.
32
+
33
+ a = ["a", "b", "c"]
34
+ b = a.copy()
35
+
36
+ # their elements are equal
37
+ a[0] == b[0] && a[1] == b[1] && a[2] == b[2]
38
+ # => true
39
+
40
+ # but they aren't the same object in memory
41
+ a === b
42
+ # => false
43
+
44
+ @name copy
45
+ @methodOf Array#
46
+ @returns {Array} A new array that is a copy of the array
47
+ ###
48
+ Array::copy = ->
49
+ this.concat()
50
+
51
+ ###*
52
+ Empties the array of its contents. It is modified in place.
53
+
54
+ fullArray = [1, 2, 3]
55
+ fullArray.clear()
56
+ fullArray
57
+ # => []
58
+
59
+ @name clear
60
+ @methodOf Array#
61
+ @returns {Array} this, now emptied.
62
+ ###
63
+ Array::clear = ->
64
+ this.length = 0
65
+
66
+ return this
67
+
68
+ ###*
69
+ Flatten out an array of arrays into a single array of elements.
70
+
71
+ [[1, 2], [3, 4], 5].flatten()
72
+ # => [1, 2, 3, 4, 5]
73
+
74
+ # won't flatten twice nested arrays. call
75
+ # flatten twice if that is what you want
76
+ [[1, 2], [3, [4, 5]], 6].flatten()
77
+ # => [1, 2, 3, [4, 5], 6]
78
+
79
+ @name flatten
80
+ @methodOf Array#
81
+ @returns {Array} A new array with all the sub-arrays flattened to the top.
82
+ ###
83
+ Array::flatten = ->
84
+ this.inject [], (a, b) ->
85
+ a.concat b
86
+
87
+ ###*
88
+ Invoke the named method on each element in the array
89
+ and return a new array containing the results of the invocation.
90
+
91
+ [1.1, 2.2, 3.3, 4.4].invoke("floor")
92
+ # => [1, 2, 3, 4]
93
+
94
+ ['hello', 'world', 'cool!'].invoke('substring', 0, 3)
95
+ # => ['hel', 'wor', 'coo']
96
+
97
+ @param {String} method The name of the method to invoke.
98
+ @param [arg...] Optional arguments to pass to the method being invoked.
99
+ @name invoke
100
+ @methodOf Array#
101
+ @returns {Array} A new array containing the results of invoking the named method on each element.
102
+ ###
103
+ Array::invoke = (method, args...) ->
104
+ this.map (element) ->
105
+ element[method].apply(element, args)
106
+
107
+ ###*
108
+ Randomly select an element from the array.
109
+
110
+ [1, 2, 3].rand()
111
+ # => 2
112
+
113
+ @name rand
114
+ @methodOf Array#
115
+ @returns {Object} A random element from an array
116
+ ###
117
+ Array::rand = ->
118
+ this[rand(this.length)]
119
+
120
+ ###*
121
+ Remove the first occurrence of the given object from the array if it is
122
+ present. The array is modified in place.
123
+
124
+ a = [1, 1, "a", "b"]
125
+ a.remove(1)
126
+ # => 1
127
+
128
+ a
129
+ # => [1, "a", "b"]
130
+
131
+ @name remove
132
+ @methodOf Array#
133
+ @param {Object} object The object to remove from the array if present.
134
+ @returns {Object} The removed object if present otherwise undefined.
135
+ ###
136
+ Array::remove = (object) ->
137
+ index = this.indexOf(object)
138
+
139
+ if index >= 0
140
+ this.splice(index, 1)[0]
141
+ else
142
+ undefined
143
+
144
+ ###*
145
+ Returns true if the element is present in the array.
146
+
147
+ ["a", "b", "c"].include("c")
148
+ # => true
149
+
150
+ [40, "a"].include(700)
151
+ # => false
152
+
153
+ @name include
154
+ @methodOf Array#
155
+ @param {Object} element The element to check if present.
156
+ @returns {Boolean} true if the element is in the array, false otherwise.
157
+ ###
158
+ Array::include = (element) ->
159
+ this.indexOf(element) != -1
160
+
161
+ ###*
162
+ Call the given iterator once for each element in the array,
163
+ passing in the element as the first argument, the index of
164
+ the element as the second argument, and <code>this</code> array as the
165
+ third argument.
166
+
167
+ word = ""
168
+ indices = []
169
+ ["r", "a", "d"].each (letter, index) ->
170
+ word += letter
171
+ indices.push(index)
172
+
173
+ # => ["r", "a", "d"]
174
+
175
+ word
176
+ # => "rad"
177
+
178
+ indices
179
+ # => [0, 1, 2]
180
+
181
+ @name each
182
+ @methodOf Array#
183
+ @param {Function} iterator Function to be called once for each element in the array.
184
+ @param {Object} [context] Optional context parameter to be used as `this` when calling the iterator function.
185
+ @returns {Array} this to enable method chaining.
186
+ ###
187
+ Array::each = (iterator, context) ->
188
+ if this.forEach
189
+ this.forEach iterator, context
190
+ else
191
+ for element, i in this
192
+ iterator.call context, element, i, this
193
+
194
+ return this
195
+
196
+ ###*
197
+ Call the given iterator once for each element in the array,
198
+ passing in the element as the first argument, the index of
199
+ the element as the second argument, and `this` array as the
200
+ third argument.
201
+
202
+ [1, 2, 3].map (number) ->
203
+ number * number
204
+ # => [1, 4, 9]
205
+
206
+ @name map
207
+ @methodOf Array#
208
+ @param {Function} iterator Function to be called once for each element in the array.
209
+ @param {Object} [context] Optional context parameter to be used as `this` when calling the iterator function.
210
+ @returns {Array} An array of the results of the iterator function being called on the original array elements.
211
+ ###
212
+ Array::map ||= (iterator, context) ->
213
+ results = []
214
+
215
+ for element, i in this
216
+ results.push iterator.call(context, element, i, this)
217
+
218
+ results
219
+
220
+ ###*
221
+ Call the given iterator once for each pair of objects in the array.
222
+
223
+ [1, 2, 3, 4].eachPair (a, b) ->
224
+ # 1, 2
225
+ # 1, 3
226
+ # 1, 4
227
+ # 2, 3
228
+ # 2, 4
229
+ # 3, 4
230
+
231
+ @name eachPair
232
+ @methodOf Array#
233
+ @param {Function} iterator Function to be called once for each pair of elements in the array.
234
+ @param {Object} [context] Optional context parameter to be used as `this` when calling the iterator function.
235
+ ###
236
+ Array::eachPair = (iterator, context) ->
237
+ length = this.length
238
+ i = 0
239
+ while i < length
240
+ a = this[i]
241
+ j = i + 1
242
+ i += 1
243
+
244
+ while j < length
245
+ b = this[j]
246
+ j += 1
247
+
248
+ iterator.call context, a, b
249
+
250
+ ###*
251
+ Call the given iterator once for each element in the array,
252
+ passing in the element as the first argument and the given object
253
+ as the second argument. Additional arguments are passed similar to
254
+ <code>each</code>.
255
+
256
+ @see Array#each
257
+ @name eachWithObject
258
+ @methodOf Array#
259
+ @param {Object} object The object to pass to the iterator on each visit.
260
+ @param {Function} iterator Function to be called once for each element in the array.
261
+ @param {Object} [context] Optional context parameter to be used as `this` when calling the iterator function.
262
+ @returns {Array} this
263
+ ###
264
+ Array::eachWithObject = (object, iterator, context) ->
265
+ this.each (element, i, self) ->
266
+ iterator.call context, element, object, i, self
267
+
268
+ return object
269
+
270
+ ###*
271
+ Call the given iterator once for each group of elements in the array,
272
+ passing in the elements in groups of n. Additional argumens are
273
+ passed as in each.
274
+
275
+ results = []
276
+ [1, 2, 3, 4].eachSlice 2, (slice) ->
277
+ results.push(slice)
278
+ # => [1, 2, 3, 4]
279
+
280
+ results
281
+ # => [[1, 2], [3, 4]]
282
+
283
+ @see Array#each
284
+ @name eachSlice
285
+ @methodOf Array#
286
+ @param {Number} n The number of elements in each group.
287
+ @param {Function} iterator Function to be called once for each group of elements in the array.
288
+ @param {Object} [context] Optional context parameter to be used as `this` when calling the iterator function.
289
+ @returns {Array} this
290
+ ###
291
+ Array::eachSlice = (n, iterator, context) ->
292
+ if n > 0
293
+ len = (this.length / n).floor()
294
+ i = -1
295
+
296
+ while ++i < len
297
+ iterator.call(context, this.slice(i*n, (i+1)*n), i*n, this)
298
+
299
+ return this
300
+
301
+ ###*
302
+ Pipe the input through each function in the array in turn. For example, if you have a
303
+ list of objects you can perform a series of selection, sorting, and other processing
304
+ methods and then receive the processed list. This array must contain functions that
305
+ accept a single input and return the processed input. The output of the first function
306
+ is fed to the input of the second and so on until the final processed output is returned.
307
+
308
+ @name pipeline
309
+ @methodOf Array#
310
+
311
+ @param {Object} input The initial input to pass to the first function in the pipeline.
312
+ @returns {Object} The result of processing the input by each function in the array.
313
+ ###
314
+ Array::pipeline = (input) ->
315
+ for fn in this
316
+ input = fn(input)
317
+
318
+ return input
319
+
320
+ ###*
321
+ Returns a new array with the elements all shuffled up.
322
+
323
+ a = [1, 2, 3]
324
+
325
+ a.shuffle()
326
+ # => [2, 3, 1]
327
+
328
+ a # => [1, 2, 3]
329
+
330
+ @name shuffle
331
+ @methodOf Array#
332
+ @returns {Array} A new array that is randomly shuffled.
333
+ ###
334
+ Array::shuffle = ->
335
+ shuffledArray = []
336
+
337
+ this.each (element) ->
338
+ shuffledArray.splice(rand(shuffledArray.length + 1), 0, element)
339
+
340
+ return shuffledArray
341
+
342
+ ###*
343
+ Returns the first element of the array, undefined if the array is empty.
344
+
345
+ ["first", "second", "third"].first()
346
+ # => "first"
347
+
348
+ @name first
349
+ @methodOf Array#
350
+ @returns {Object} The first element, or undefined if the array is empty.
351
+ ###
352
+ Array::first = ->
353
+ this[0]
354
+
355
+ ###*
356
+ Returns the last element of the array, undefined if the array is empty.
357
+
358
+ ["first", "second", "third"].last()
359
+ # => "third"
360
+
361
+ @name last
362
+ @methodOf Array#
363
+ @returns {Object} The last element, or undefined if the array is empty.
364
+ ###
365
+ Array::last = ->
366
+ this[this.length - 1]
367
+
368
+ ###*
369
+ Returns an object containing the extremes of this array.
370
+
371
+ [-1, 3, 0].extremes()
372
+ # => {min: -1, max: 3}
373
+
374
+ @name extremes
375
+ @methodOf Array#
376
+ @param {Function} [fn] An optional funtion used to evaluate each element to calculate its value for determining extremes.
377
+ @returns {Object} {min: minElement, max: maxElement}
378
+ ###
379
+ Array::extremes = (fn) ->
380
+ fn ||= (n) -> n
381
+
382
+ min = max = undefined
383
+ minResult = maxResult = undefined
384
+
385
+ this.each (object) ->
386
+ result = fn(object)
387
+
388
+ if min?
389
+ if result < minResult
390
+ min = object
391
+ minResult = result
392
+ else
393
+ min = object
394
+ minResult = result
395
+
396
+ if max?
397
+ if result > maxResult
398
+ max = object
399
+ maxResult = result
400
+ else
401
+ max = object
402
+ maxResult = result
403
+
404
+ min: min
405
+ max: max
406
+
407
+ ###*
408
+ Pretend the array is a circle and grab a new array containing length elements.
409
+ If length is not given return the element at start, again assuming the array
410
+ is a circle.
411
+
412
+ [1, 2, 3].wrap(-1)
413
+ # => 3
414
+
415
+ [1, 2, 3].wrap(6)
416
+ # => 1
417
+
418
+ ["l", "o", "o", "p"].wrap(0, 16)
419
+ # => ["l", "o", "o", "p", "l", "o", "o", "p", "l", "o", "o", "p", "l", "o", "o", "p"]
420
+
421
+ @name wrap
422
+ @methodOf Array#
423
+ @param {Number} start The index to start wrapping at, or the index of the sole element to return if no length is given.
424
+ @param {Number} [length] Optional length determines how long result array should be.
425
+ @returns {Object} or {Array} The element at start mod array.length, or an array of length elements, starting from start and wrapping.
426
+ ###
427
+ Array::wrap = (start, length) ->
428
+ if length?
429
+ end = start + length
430
+ i = start
431
+ result = []
432
+
433
+ result.push(this[i.mod(this.length)]) while i++ < end
434
+
435
+ return result
436
+ else
437
+ return this[start.mod(this.length)]
438
+
439
+ ###*
440
+ Partitions the elements into two groups: those for which the iterator returns
441
+ true, and those for which it returns false.
442
+
443
+ [evens, odds] = [1, 2, 3, 4].partition (n) ->
444
+ n.even()
445
+
446
+ evens
447
+ # => [2, 4]
448
+
449
+ odds
450
+ # => [1, 3]
451
+
452
+ @name partition
453
+ @methodOf Array#
454
+ @param {Function} iterator
455
+ @param {Object} [context] Optional context parameter to be used as `this` when calling the iterator function.
456
+ @returns {Array} An array in the form of [trueCollection, falseCollection]
457
+ ###
458
+ Array::partition = (iterator, context) ->
459
+ trueCollection = []
460
+ falseCollection = []
461
+
462
+ this.each (element) ->
463
+ if iterator.call(context, element)
464
+ trueCollection.push element
465
+ else
466
+ falseCollection.push element
467
+
468
+ return [trueCollection, falseCollection]
469
+
470
+ ###*
471
+ Return the group of elements for which the return value of the iterator is true.
472
+
473
+ @name select
474
+ @methodOf Array#
475
+ @param {Function} iterator The iterator receives each element in turn as the first agument.
476
+ @param {Object} [context] Optional context parameter to be used as `this` when calling the iterator function.
477
+ @returns {Array} An array containing the elements for which the iterator returned true.
478
+ ###
479
+ Array::select = (iterator, context) ->
480
+ return this.partition(iterator, context)[0]
481
+
482
+ ###*
483
+ Return the group of elements that are not in the passed in set.
484
+
485
+ [1, 2, 3, 4].without ([2, 3])
486
+ # => [1, 4]
487
+
488
+ @name without
489
+ @methodOf Array#
490
+ @param {Array} values List of elements to exclude.
491
+ @returns {Array} An array containing the elements that are not passed in.
492
+ ###
493
+ Array::without = (values) ->
494
+ this.reject (element) ->
495
+ values.include(element)
496
+
497
+ ###*
498
+ Return the group of elements for which the return value of the iterator is false.
499
+
500
+ @name reject
501
+ @methodOf Array#
502
+ @param {Function} iterator The iterator receives each element in turn as the first agument.
503
+ @param {Object} [context] Optional context parameter to be used as `this` when calling the iterator function.
504
+ @returns {Array} An array containing the elements for which the iterator returned false.
505
+ ###
506
+ Array::reject = (iterator, context) ->
507
+ this.partition(iterator, context)[1]
508
+
509
+ ###*
510
+ Combines all elements of the array by applying a binary operation.
511
+ for each element in the arra the iterator is passed an accumulator
512
+ value (memo) and the element.
513
+
514
+ @name inject
515
+ @methodOf Array#
516
+ @returns {Object} The result of a
517
+ ###
518
+ Array::inject = (initial, iterator) ->
519
+ this.each (element) ->
520
+ initial = iterator(initial, element)
521
+
522
+ return initial
523
+
524
+ ###*
525
+ Add all the elements in the array.
526
+
527
+ [1, 2, 3, 4].sum()
528
+ # => 10
529
+
530
+ @name sum
531
+ @methodOf Array#
532
+ @returns {Number} The sum of the elements in the array.
533
+ ###
534
+ Array::sum = ->
535
+ this.inject 0, (sum, n) ->
536
+ sum + n
537
+
538
+ ###*
539
+ Multiply all the elements in the array.
540
+
541
+ [1, 2, 3, 4].product()
542
+ # => 24
543
+
544
+ @name product
545
+ @methodOf Array#
546
+ @returns {Number} The product of the elements in the array.
547
+ ###
548
+ Array::product = ->
549
+ this.inject 1, (product, n) ->
550
+ product * n
551
+
552
+ ###*
553
+ Merges together the values of each of the arrays with the values at the corresponding position.
554
+
555
+ ['a', 'b', 'c'].zip([1, 2, 3])
556
+ # => [['a', 1], ['b', 2], ['c', 3]]
557
+
558
+ @name zip
559
+ @methodOf Array#
560
+ @returns {Array} Array groupings whose values are arranged by their positions in the original input arrays.
561
+ ###
562
+ Array::zip = (args...) ->
563
+ this.map (element, index) ->
564
+ output = args.map (arr) ->
565
+ arr[index]
566
+
567
+ output.unshift(element)
568
+
569
+ return output
570
+