agt 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.md +7 -0
  3. data/README.md +5 -0
  4. data/app/assets/javascripts/agt/config.coffee +9 -0
  5. data/app/assets/javascripts/agt/dom.coffee +12 -0
  6. data/app/assets/javascripts/agt/function.coffee +317 -0
  7. data/app/assets/javascripts/agt/geom/circle.coffee +338 -0
  8. data/app/assets/javascripts/agt/geom/cubic_bezier.coffee +37 -0
  9. data/app/assets/javascripts/agt/geom/diamond.coffee +241 -0
  10. data/app/assets/javascripts/agt/geom/ellipsis.coffee +141 -0
  11. data/app/assets/javascripts/agt/geom/linear_spline.coffee +56 -0
  12. data/app/assets/javascripts/agt/geom/matrix.coffee +240 -0
  13. data/app/assets/javascripts/agt/geom/mixins/geometry.coffee +171 -0
  14. data/app/assets/javascripts/agt/geom/mixins/intersections.coffee +150 -0
  15. data/app/assets/javascripts/agt/geom/mixins/path.coffee +145 -0
  16. data/app/assets/javascripts/agt/geom/mixins/proxyable.coffee +9 -0
  17. data/app/assets/javascripts/agt/geom/mixins/spline.coffee +329 -0
  18. data/app/assets/javascripts/agt/geom/mixins/surface.coffee +55 -0
  19. data/app/assets/javascripts/agt/geom/mixins/triangulable.coffee +112 -0
  20. data/app/assets/javascripts/agt/geom/point.coffee +454 -0
  21. data/app/assets/javascripts/agt/geom/polygon.coffee +119 -0
  22. data/app/assets/javascripts/agt/geom/quad_bezier.coffee +43 -0
  23. data/app/assets/javascripts/agt/geom/quint_bezier.coffee +42 -0
  24. data/app/assets/javascripts/agt/geom/rectangle.coffee +599 -0
  25. data/app/assets/javascripts/agt/geom/spiral.coffee +90 -0
  26. data/app/assets/javascripts/agt/geom/transformation_proxy.coffee +43 -0
  27. data/app/assets/javascripts/agt/geom/triangle.coffee +442 -0
  28. data/app/assets/javascripts/agt/impulse.coffee +105 -0
  29. data/app/assets/javascripts/agt/index.coffee +56 -0
  30. data/app/assets/javascripts/agt/inflector/inflection.coffee +21 -0
  31. data/app/assets/javascripts/agt/inflector/inflections.coffee +75 -0
  32. data/app/assets/javascripts/agt/inflector/inflector.coffee +235 -0
  33. data/app/assets/javascripts/agt/inheritance.coffee +132 -0
  34. data/app/assets/javascripts/agt/math.coffee +45 -0
  35. data/app/assets/javascripts/agt/mixins/activable.coffee +31 -0
  36. data/app/assets/javascripts/agt/mixins/aliasable.coffee +25 -0
  37. data/app/assets/javascripts/agt/mixins/alternate_case.coffee +72 -0
  38. data/app/assets/javascripts/agt/mixins/cloneable.coffee +71 -0
  39. data/app/assets/javascripts/agt/mixins/delegation.coffee +90 -0
  40. data/app/assets/javascripts/agt/mixins/disposable.coffee +7 -0
  41. data/app/assets/javascripts/agt/mixins/equatable.coffee +37 -0
  42. data/app/assets/javascripts/agt/mixins/formattable.coffee +52 -0
  43. data/app/assets/javascripts/agt/mixins/globalizable.coffee +175 -0
  44. data/app/assets/javascripts/agt/mixins/has_ancestors.coffee +47 -0
  45. data/app/assets/javascripts/agt/mixins/has_collection.coffee +107 -0
  46. data/app/assets/javascripts/agt/mixins/has_nested_collection.coffee +51 -0
  47. data/app/assets/javascripts/agt/mixins/memoizable.coffee +64 -0
  48. data/app/assets/javascripts/agt/mixins/parameterizable.coffee +101 -0
  49. data/app/assets/javascripts/agt/mixins/poolable.coffee +62 -0
  50. data/app/assets/javascripts/agt/mixins/sourcable.coffee +45 -0
  51. data/app/assets/javascripts/agt/mixins/state_machine.coffee +47 -0
  52. data/app/assets/javascripts/agt/net/router.coffee +165 -0
  53. data/app/assets/javascripts/agt/object.coffee +9 -0
  54. data/app/assets/javascripts/agt/particles/actions/base_action.coffee +7 -0
  55. data/app/assets/javascripts/agt/particles/actions/die_on_surface.coffee +14 -0
  56. data/app/assets/javascripts/agt/particles/actions/force.coffee +11 -0
  57. data/app/assets/javascripts/agt/particles/actions/friction.coffee +14 -0
  58. data/app/assets/javascripts/agt/particles/actions/live.coffee +9 -0
  59. data/app/assets/javascripts/agt/particles/actions/macro_action.coffee +13 -0
  60. data/app/assets/javascripts/agt/particles/actions/move.coffee +11 -0
  61. data/app/assets/javascripts/agt/particles/actions/null_action.coffee +9 -0
  62. data/app/assets/javascripts/agt/particles/counters/by_rate.coffee +17 -0
  63. data/app/assets/javascripts/agt/particles/counters/fixed.coffee +9 -0
  64. data/app/assets/javascripts/agt/particles/counters/null_counter.coffee +9 -0
  65. data/app/assets/javascripts/agt/particles/emission.coffee +35 -0
  66. data/app/assets/javascripts/agt/particles/emitters/null_emitter.coffee +7 -0
  67. data/app/assets/javascripts/agt/particles/emitters/path.coffee +10 -0
  68. data/app/assets/javascripts/agt/particles/emitters/ponctual.coffee +9 -0
  69. data/app/assets/javascripts/agt/particles/emitters/surface.coffee +10 -0
  70. data/app/assets/javascripts/agt/particles/initializers/explosion.coffee +19 -0
  71. data/app/assets/javascripts/agt/particles/initializers/life.coffee +16 -0
  72. data/app/assets/javascripts/agt/particles/initializers/macro_initializer.coffee +10 -0
  73. data/app/assets/javascripts/agt/particles/initializers/null_initializer.coffee +7 -0
  74. data/app/assets/javascripts/agt/particles/initializers/particle_sub_system.coffee +12 -0
  75. data/app/assets/javascripts/agt/particles/initializers/stream.coffee +20 -0
  76. data/app/assets/javascripts/agt/particles/mixins/randomizable.coffee +10 -0
  77. data/app/assets/javascripts/agt/particles/particle.coffee +32 -0
  78. data/app/assets/javascripts/agt/particles/sub_system.coffee +11 -0
  79. data/app/assets/javascripts/agt/particles/system.coffee +103 -0
  80. data/app/assets/javascripts/agt/particles/timers/instant.coffee +11 -0
  81. data/app/assets/javascripts/agt/particles/timers/limited.coffee +19 -0
  82. data/app/assets/javascripts/agt/particles/timers/null_timer.coffee +11 -0
  83. data/app/assets/javascripts/agt/particles/timers/unlimited.coffee +9 -0
  84. data/app/assets/javascripts/agt/particles/timers/until_death.coffee +11 -0
  85. data/app/assets/javascripts/agt/promise.coffee +214 -0
  86. data/app/assets/javascripts/agt/random/random.coffee +100 -0
  87. data/app/assets/javascripts/agt/random/seeds/lagged_fibonnacci.coffee +53 -0
  88. data/app/assets/javascripts/agt/random/seeds/linear.coffee +16 -0
  89. data/app/assets/javascripts/agt/random/seeds/linear_congruential.coffee +23 -0
  90. data/app/assets/javascripts/agt/random/seeds/math_random.coffee +9 -0
  91. data/app/assets/javascripts/agt/random/seeds/mersenne_twister.coffee +42 -0
  92. data/app/assets/javascripts/agt/random/seeds/no_random.coffee +12 -0
  93. data/app/assets/javascripts/agt/random/seeds/paul_houle.coffee +19 -0
  94. data/app/assets/javascripts/agt/signal.coffee +272 -0
  95. data/app/assets/javascripts/agt/sprites/animation.coffee +13 -0
  96. data/app/assets/javascripts/agt/sprites/sprite.coffee +30 -0
  97. data/app/assets/javascripts/agt/widgets/hash.coffee +36 -0
  98. data/app/assets/javascripts/agt/widgets/widgets.coffee +194 -0
  99. data/app/assets/javascripts/agt/widgets/widgets/checked_input.coffee +7 -0
  100. data/app/assets/javascripts/agt/widgets/widgets/focus_bubbling.coffee +15 -0
  101. data/lib/agt.rb +8 -0
  102. data/lib/agt/version.rb +5 -0
  103. metadata +173 -0
@@ -0,0 +1,132 @@
1
+
2
+ # Internal: For a given function on an object it will find the property
3
+ # name and its kind (value/getter/setter).
4
+ findCaller = (caller, proto) ->
5
+ keys = Object.keys proto
6
+
7
+ for k in keys
8
+ descriptor = Object.getPropertyDescriptor proto, k
9
+
10
+ if descriptor?
11
+ return {key: k, descriptor, kind: 'value'} if descriptor.value is caller
12
+ return {key: k, descriptor, kind: 'get'} if descriptor.get is caller
13
+ return {key: k, descriptor, kind: 'set'} if descriptor.set is caller
14
+ else
15
+ return {key: k} if proto[k] is caller
16
+
17
+ {}
18
+
19
+ unless Object::super?
20
+ # Public: Gives access to the super method of any
21
+ Object.defineProperty Object.prototype, 'super', {
22
+ enumerable: false
23
+ configurable: true
24
+ value: (args...) ->
25
+ # To define which function to use as super when
26
+ # calling the `this.super` method we need to know which
27
+ # function is the caller.
28
+ caller = arguments.caller ? @super.caller
29
+ if caller?
30
+ # When the caller has a `__super__` property, we face
31
+ # a mixin method, we can access the `__super__` property
32
+ # to retrieve its super property.
33
+ if caller.__super__?
34
+ value = caller.__super__[caller.__included__.indexOf @constructor]
35
+
36
+ # The `this.super` method can be called only if the super
37
+ # is a function.
38
+ if value?
39
+ if typeof value is 'function'
40
+ value.apply(this, args)
41
+ else
42
+ throw new Error "The super for #{caller._name} isn't a function"
43
+ else
44
+ throw new Error "No super method for #{caller._name}"
45
+
46
+ # Without the `__super__` property we face a method declared
47
+ # in the including class and that may redefine a method from
48
+ # a mixin or a parent.
49
+ else
50
+ # The name of the property that stores the caller is retrieved.
51
+ # The `kind` variable is either `'value'`, `'get'`, `'set'`
52
+ # or `'null'`. It will be needed to find the correspondant
53
+ # super method in the property descriptor.
54
+ {key, kind} = findCaller caller, @constructor.prototype
55
+
56
+ # If the key is present we'll try to get a descriptor on the
57
+ # `__super__` class property.
58
+ if key?
59
+ desc = Object.getPropertyDescriptor @constructor.__super__, key
60
+
61
+ # And if a descriptor is available we get the function
62
+ # corresponding to the `kind` and call it with the arguments.
63
+ if desc?
64
+ value = desc[kind].apply(this, args)
65
+
66
+ # Otherwise, the value of the property is simply called.
67
+ else
68
+ value = @constructor.__super__[key].apply(this, args)
69
+
70
+ return value
71
+
72
+ # And in other cases an error is raised.
73
+ else
74
+ throw new Error "No super method for #{caller.name || caller._name}"
75
+ else
76
+ throw new Error "Super called with a caller"
77
+
78
+ }
79
+
80
+ # Public:
81
+ Object.defineProperty Function.prototype, 'super', {
82
+ enumerable: false
83
+ configurable: true
84
+ value: (args...) ->
85
+ caller = arguments.caller or @super.caller
86
+ if caller?
87
+ if caller.__super__?
88
+ value = caller.__super__[caller.__included__.indexOf this]
89
+
90
+ if value?
91
+ if typeof value is 'function'
92
+ value.apply(this, args)
93
+ else
94
+ throw new Error "The super for #{caller._name} isn't a function"
95
+ else
96
+ throw new Error "No super method for #{caller._name}"
97
+
98
+ else
99
+ # super method in the property descriptor.
100
+ {key, kind} = findCaller caller, this
101
+
102
+ reverseMixins = []
103
+ reverseMixins.unshift m for m in @__mixins__
104
+
105
+ # If the key is present we'll try to get a descriptor on the
106
+ # `__super__` class property.
107
+ if key?
108
+ for m in reverseMixins
109
+ if m[key]?
110
+ mixin = m
111
+ break
112
+
113
+ desc = Object.getPropertyDescriptor mixin, key
114
+
115
+ # And if a descriptor is available we get the function
116
+ # corresponding to the `kind` and call it with the arguments.
117
+ if desc?
118
+ value = desc[kind].apply(this, args)
119
+
120
+ # Otherwise, the value of the property is simply called.
121
+ else
122
+ value = mixin[key].apply(this, args)
123
+
124
+ return value
125
+
126
+ # And in other cases an error is raised.
127
+ else
128
+ throw new Error "No super class method for #{caller.name || caller._name}"
129
+ else
130
+ throw new Error "super called without a caller"
131
+
132
+ }
@@ -0,0 +1,45 @@
1
+
2
+ Math.PI2 = Math.PI * 2
3
+ Math.PI_2 = Math.PI / 2
4
+ Math.PI_4 = Math.PI / 4
5
+ Math.PI_8 = Math.PI / 8
6
+
7
+ ### Public ###
8
+
9
+ Math.degToRad = (n) -> n * Math.PI / 180
10
+
11
+ Math.radToDeg = (n) -> n * 180 / Math.PI
12
+
13
+ Math.normalize = (value, minimum, maximum) ->
14
+ (value - minimum) / (maximum - minimum)
15
+
16
+ Math.interpolate = (normValue, minimum, maximum) ->
17
+ minimum + (maximum - minimum) * normValue
18
+
19
+ Math.deltaBelowRatio = (a, b, ratio=10000000000) -> Math.abs(a - b) < 1 / ratio
20
+
21
+ Math.map = (value, min1, max1, min2, max2) ->
22
+ Math.interpolate Math.normalize(value, min1, max1), min2, max2
23
+
24
+ # Returns true if the passed-in argument can be casted to a number.
25
+ #
26
+ # Math.isFloat 0.245 # true
27
+ # Math.isFloat '12' # true
28
+ # Math.isFloat 'foo' # false
29
+ Math.isFloat = (floats...) ->
30
+ return false for float in floats when isNaN parseFloat float
31
+ true
32
+
33
+ Math.isInt = (ints...) ->
34
+ return false for int in ints when isNaN parseInt int
35
+ true
36
+
37
+ # Returns the passed-in arguments casted into floats.
38
+ Math.asFloat = (floats...) ->
39
+ floats[i] = parseFloat n for n,i in floats
40
+ floats
41
+
42
+ # Returns the passed-in arguments casted into floats.
43
+ Math.asInt = (ints...) ->
44
+ ints[i] = parseInt n for n,i in ints
45
+ ints
@@ -0,0 +1,31 @@
1
+ namespace('agt.mixins')
2
+ # Public: The `Activable` mixin provides the basic interface for an activable
3
+ # widget. You can hook your own activation/deactivation routines by overriding
4
+ # the `activated` and `deactivated` methods.
5
+ #
6
+ # ```coffeescript
7
+ # class Dummy
8
+ # @include agt.mixins.Activable
9
+ #
10
+ # activated: ->
11
+ # # ...
12
+ #
13
+ # deactivated: ->
14
+ # # ...
15
+ # ```
16
+ #
17
+ # `Activable` instances are deactivated at creation.
18
+ class agt.mixins.Activable
19
+ active: false
20
+
21
+ # Public: Activates the instance.
22
+ activate: ->
23
+ return if @active
24
+ @active = true
25
+ @activated?()
26
+
27
+ # Public: Deactivates the instance.
28
+ deactivate: ->
29
+ return unless @active
30
+ @active = false
31
+ @deactivated?()
@@ -0,0 +1,25 @@
1
+ namespace('agt.mixins')
2
+ # Public: Provides class methods to deal with aliased methods and properties.
3
+ #
4
+ # ```coffeescript
5
+ # class Dummy
6
+ # @extend agt.mixins.Aliasable
7
+ #
8
+ # someMethod: ->
9
+ # @alias 'someMethod', 'someMethodAlias'
10
+ # ```
11
+ class agt.mixins.Aliasable
12
+
13
+ # Public: Creates aliases for the given `source` property of tthe current
14
+ # class prototype. Any number of alias can be passed at once.
15
+ #
16
+ # source - The {String} name of the aliased property
17
+ # aliases - A list of {String}s to use as aliases.
18
+ @alias: (source, aliases...) ->
19
+ desc = Object.getPropertyDescriptor @prototype, source
20
+
21
+ if desc?
22
+ Object.defineProperty @prototype, alias, desc for alias in aliases
23
+ else
24
+ if @prototype[ source ]?
25
+ @prototype[ alias ] = @prototype[ source ] for alias in aliases
@@ -0,0 +1,72 @@
1
+ namespace('agt.mixins')
2
+ # Public: The `AlternateCase` mixin add methods to convert the properties
3
+ # of a class instance to camelCase or snake_case.
4
+ #
5
+ # The methods are available on the class itself and should be called
6
+ # after having declared all the class members.
7
+ #
8
+ # For instance, given the class below:
9
+ #
10
+ # ```coffeescript
11
+ # class Dummy
12
+ # @extend agt.mixins.AlternateCase
13
+ #
14
+ # someProperty: 'foo'
15
+ # someMethod: ->
16
+ #
17
+ # @snakify()
18
+ # ```
19
+ #
20
+ # An instance will have both `someProperty` and `someMethod` as defined
21
+ # by the class, but also `some_property` and `some_method`.
22
+ #
23
+ # The alternative is also possible. Given a class that uses snake_case
24
+ # to declare its member, the `camelize` method will provides the camelCase
25
+ # alternative to the class.
26
+ class agt.mixins.AlternateCase
27
+
28
+ # Public: Converts all the prototype properties to snake_case.
29
+ @snakify: -> @convert 'toSnakeCase'
30
+
31
+ # Public: Converts all the prototype properties to camelCase.
32
+ @camelize: -> @convert 'toCamelCase'
33
+
34
+ # Public: Adds the specified alternatives of each properties on the
35
+ # current prototype. The passed-in argument is the name of the class
36
+ # method to call to convert the key string.
37
+ #
38
+ # alternateCase - The {String} name of the class method to use
39
+ # to convert.
40
+ @convert: (alternateCase) ->
41
+ for key,value of @prototype
42
+ alternate = @[alternateCase] key
43
+
44
+ descriptor = Object.getPropertyDescriptor @prototype, key
45
+
46
+ if descriptor?
47
+ Object.defineProperty @prototype, alternate, descriptor
48
+ else
49
+ @prototype[alternate] = value
50
+
51
+ # Public: Converts a string to `snake_case`.
52
+ #
53
+ # str - The {String} to convert.
54
+ #
55
+ # Returns a {String} in `snake_case` .
56
+ @toSnakeCase: (str) ->
57
+ str.
58
+ replace(/([a-z])([A-Z])/g, "$1_$2")
59
+ .split(/_+/g)
60
+ .join('_')
61
+ .toLowerCase()
62
+
63
+ # Public: Converts a string to `camelCase`.
64
+ #
65
+ # str - The {String} to convert.
66
+ #
67
+ # Returns a {String} in `camelCase`.
68
+ @toCamelCase: (str) ->
69
+ a = str.toLowerCase().split(/[_\s-]/)
70
+ s = a.shift()
71
+ s = "#{ s }#{w.replace /^./, (s) -> s.toUpperCase()}" for w in a
72
+ s
@@ -0,0 +1,71 @@
1
+ namespace('agt.mixins')
2
+ # Internal: Contains all the function that will instanciate a class
3
+ # with a specific number of arguments. These functions are all generated
4
+ # at runtime with the `Function` constructor.
5
+ build = (klass, args) ->
6
+ BUILDS = (
7
+ new Function( "return new arguments[0](#{
8
+ ("arguments[1][#{ j-1 }]" for j in [ 0..i ] when j isnt 0).join ","
9
+ });") for i in [ 0..24 ]
10
+ )
11
+
12
+ f = BUILDS[ if args? then args.length else 0 ]
13
+ f klass, args
14
+
15
+ # Public: A `Cloneable` object can return a copy of itself through its `clone`
16
+ # method.
17
+ #
18
+ # The `Cloneable` generator function produces a different mixin when called
19
+ # with or without arguments.
20
+ #
21
+ # When called without argument, the returned mixin creates a clone using
22
+ # a copy constructor (a constructor that initialize the current object
23
+ # with an object).
24
+ #
25
+ # ```coffeescript
26
+ # class Dummy
27
+ # @include agt.mixins.Cloneable()
28
+ #
29
+ # constructor: (options={}) ->
30
+ # @property = options.property or 'foo'
31
+ # @otherProperty = options.otherProperty or 'bar'
32
+ #
33
+ # instance = new Dummy
34
+ # otherInstance = instance.clone()
35
+ # # otherInstance = {property: 'foo', otherProperty: 'bar'}
36
+ # ```
37
+ #
38
+ # When called with arguments, the `clone` method will call the class
39
+ # constructor with the values extracted from the given properties.
40
+ #
41
+ # ```coffeescript
42
+ # class Dummy
43
+ # @include agt.mixins.Cloneable('property', 'otherProperty')
44
+ #
45
+ # constructor: (@property='foo', @otherProperty='bar') ->
46
+ #
47
+ # instance = new Dummy
48
+ # otherInstance = instance.clone()
49
+ # # otherInstance = {property: 'foo', otherProperty: 'bar'}
50
+ # ```
51
+ #
52
+ # properties - A list of {String} of the properties to pass in the constructor.
53
+ #
54
+ # Returns a {ConcreteCloneable} mixin configured with the passed-in arguments.
55
+ agt.mixins.Cloneable = (properties...) ->
56
+
57
+ # Public: The concrete cloneable mixin as created by the
58
+ # [Cloneable](../files/mixins/cloneable.coffee.html) generator.
59
+ class ConcreteCloneable
60
+
61
+ # Public: Returns a copy of this instance.
62
+ #
63
+ # When the mixin is configurated without any `properties` the cloned
64
+ # instance is passed directly as argument at the creation of the new
65
+ # instance.
66
+ #
67
+ # Returns an {Object}.
68
+ clone: -> new @constructor this
69
+
70
+ if properties.length > 0
71
+ ConcreteCloneable::clone = -> build @constructor, properties.map (p) => @[ p ]
@@ -0,0 +1,90 @@
1
+ namespace('agt.mixins')
2
+ # Public: The `Delegation` mixin allow to define properties on an object that
3
+ # proxy another property of an object stored in one of its property.
4
+ #
5
+ # ```coffeescript
6
+ # class Dummy
7
+ # @extend agt.mixins.Delegation
8
+ #
9
+ # @delegate 'someProperty', to: 'someObject'
10
+ #
11
+ # constructor: ->
12
+ # @someObject = someProperty: 'some value'
13
+ #
14
+ # instance = new Dummy
15
+ # instance.someProperty
16
+ # # 'some value'
17
+ # ```
18
+ class agt.mixins.Delegation
19
+
20
+ # Public: The `delegate` class method generates a property on the current
21
+ # prototype that proxy the property of the given object.
22
+ #
23
+ # The `to` option specify the property of the object accessed by
24
+ # the delegated property.
25
+ #
26
+ # The delegated property name can be prefixed with the name of the
27
+ # accessed property
28
+ #
29
+ # ```coffeescript
30
+ # class Dummy
31
+ # @extend agt.mixins.Delegation
32
+ #
33
+ # @delegate 'someProperty', to: 'someObject', prefix: true
34
+ # # delegated property is named `someObjectSomeProperty`
35
+ # ```
36
+ #
37
+ # By default, using a prefix generates a camelCase property name.
38
+ # You can use the `case` option to change that to a snake_case property
39
+ # name.
40
+ #
41
+ # ```coffeescript
42
+ # class Dummy
43
+ # @extend agt.mixins.Delegation
44
+ #
45
+ # @delegate 'some_property', to: 'some_object', prefix: true, case: 'snake'
46
+ # # delegated property is named `some_object_some_property`
47
+ # ```
48
+ #
49
+ # The `delegate` method accept any number of properties to delegate
50
+ # with the same options.
51
+ #
52
+ # ```coffeescript
53
+ # class Dummy
54
+ # @extend agt.mixins.Delegation
55
+ #
56
+ # @delegate 'someProperty', 'someOtherProperty', to: 'someObject'
57
+ # ```
58
+ #
59
+ # properties - A list of {String} of the properties to delegate.
60
+ # options - The delegation options {Object}:
61
+ # :to - The {String} name of the target property.
62
+ # :prefix - A {Boolean} indicating whether to prefix the created
63
+ # delegated property name with the target property name.
64
+ # :case - An optional {String} to define the case to use to generate
65
+ # a prefixed delegated property.
66
+ @delegate: (properties..., options={}) ->
67
+ delegated = options.to
68
+ prefixed = options.prefix
69
+ _case = options.case or agt.CAMEL_CASE
70
+
71
+ properties.forEach (property) =>
72
+ localAlias = property
73
+
74
+ # Currently, only `camel`, and `snake` cases are supported.
75
+ if prefixed
76
+ switch _case
77
+ when agt.SNAKE_CASE
78
+ localAlias = delegated + '_' + property
79
+ when agt.CAMEL_CASE
80
+ localAlias = delegated + property.replace /^./, (m) ->
81
+ m.toUpperCase()
82
+
83
+ # The `Delegation` mixin rely on `Object.property` and thus can't
84
+ # be used on IE8.
85
+ Object.defineProperty @prototype, localAlias, {
86
+ enumerable: true
87
+ configurable: true
88
+ get: -> @[ delegated ][ property ]
89
+ set: (value) -> @[ delegated ][ property ] = value
90
+ }