luca 0.9.65 → 0.9.76

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 (86) hide show
  1. data/CHANGELOG +30 -0
  2. data/Gemfile +1 -0
  3. data/Gemfile.lock +27 -0
  4. data/lib/luca/rails/version.rb +1 -1
  5. data/spec/components/controller_spec.coffee +58 -0
  6. data/spec/components/form_view_spec.coffee +4 -0
  7. data/spec/concerns/dom_helpers_spec.coffee +16 -0
  8. data/spec/{modules → concerns}/filterable_spec.coffee +0 -0
  9. data/spec/concerns/model_presenter_spec.coffee +31 -0
  10. data/spec/{modules → concerns}/paginatable_spec.coffee +0 -0
  11. data/spec/{modules → concerns}/state_model_spec.coffee +0 -0
  12. data/spec/concerns_spec.coffee +88 -0
  13. data/spec/core/container_spec.coffee +103 -6
  14. data/spec/core/field_spec.coffee +4 -0
  15. data/spec/core/model_spec.coffee +6 -1
  16. data/spec/define_spec.coffee +104 -7
  17. data/spec/framework_spec.coffee +30 -1
  18. data/spec/util_spec.coffee +24 -0
  19. data/src/components/application.coffee +62 -25
  20. data/src/components/base_toolbar.coffee +6 -4
  21. data/src/components/collection_loader_view.coffee +3 -1
  22. data/src/components/collection_view.coffee +36 -73
  23. data/src/components/controller.coffee +73 -35
  24. data/src/components/fields/button_field.coffee +20 -12
  25. data/src/components/fields/checkbox_array.coffee +8 -2
  26. data/src/components/fields/checkbox_field.coffee +18 -9
  27. data/src/components/fields/file_upload_field.coffee +5 -1
  28. data/src/components/fields/hidden_field.coffee +3 -1
  29. data/src/components/fields/label_field.coffee +4 -3
  30. data/src/components/fields/select_field.coffee +7 -8
  31. data/src/components/fields/text_area_field.coffee +3 -2
  32. data/src/components/fields/text_field.coffee +5 -4
  33. data/src/components/fields/type_ahead_field.coffee +4 -2
  34. data/src/components/form_button_toolbar.coffee +4 -1
  35. data/src/components/form_view.coffee +26 -24
  36. data/src/components/grid_view.coffee +3 -3
  37. data/src/components/multi_collection_view.coffee +6 -35
  38. data/src/components/pagination_control.coffee +1 -3
  39. data/src/components/router.coffee +2 -0
  40. data/src/components/table_view.coffee +7 -0
  41. data/src/concerns.coffee +70 -0
  42. data/src/{modules → concerns}/application_event_bindings.coffee +1 -1
  43. data/src/{modules → concerns}/collection_event_bindings.coffee +1 -1
  44. data/src/{modules → concerns}/deferrable.coffee +1 -1
  45. data/src/{modules → concerns}/dom_helpers.coffee +11 -2
  46. data/src/{modules → concerns}/enhanced_properties.coffee +1 -1
  47. data/src/{modules → concerns}/filterable.coffee +11 -11
  48. data/src/{modules → concerns}/grid_layout.coffee +1 -1
  49. data/src/{modules → concerns}/loadmaskable.coffee +1 -1
  50. data/src/{modules → concerns}/local_storage.coffee +0 -0
  51. data/src/{modules → concerns}/modal_view.coffee +1 -1
  52. data/src/concerns/model_presenter.coffee +23 -0
  53. data/src/{modules → concerns}/paginatable.coffee +9 -3
  54. data/src/concerns/query_collection_bindings.coffee +44 -0
  55. data/src/{modules → concerns}/state_model.coffee +1 -1
  56. data/src/{modules → concerns}/templating.coffee +1 -1
  57. data/src/containers/card_view.coffee +16 -9
  58. data/src/containers/tab_view.coffee +8 -11
  59. data/src/containers/viewport.coffee +3 -3
  60. data/src/core/collection.coffee +39 -28
  61. data/src/core/container.coffee +37 -15
  62. data/src/core/field.coffee +40 -39
  63. data/src/core/meta_data.coffee +93 -0
  64. data/src/core/model.coffee +18 -1
  65. data/src/core/registry.coffee +4 -3
  66. data/src/core/view.coffee +24 -30
  67. data/src/define.coffee +165 -79
  68. data/src/framework.coffee +97 -21
  69. data/src/index.coffee +4 -2
  70. data/src/managers/collection_manager.coffee +7 -3
  71. data/src/stylesheets/components/checkbox_array.scss +1 -1
  72. data/src/stylesheets/components/form_view.scss +5 -5
  73. data/src/stylesheets/components/viewport.scss +2 -1
  74. data/src/stylesheets/containers/container.scss +0 -5
  75. data/src/stylesheets/containers/tab_view.scss +5 -5
  76. data/src/templates/fields/text_area_field.jst.ejs +1 -1
  77. data/src/templates/fields/text_field.jst.ejs +1 -1
  78. data/src/util.coffee +47 -0
  79. data/vendor/assets/javascripts/luca-ui-full.js +1279 -494
  80. data/vendor/assets/javascripts/luca-ui-full.min.js +5 -5
  81. data/vendor/assets/javascripts/luca-ui-templates.js +2 -2
  82. data/vendor/assets/javascripts/luca-ui.js +1279 -494
  83. data/vendor/assets/javascripts/luca-ui.min.js +5 -4
  84. data/vendor/assets/stylesheets/luca-ui.css +15 -15
  85. metadata +27 -20
  86. data/spec/mixin_spec.coffee +0 -49
@@ -0,0 +1,93 @@
1
+ Luca.registry.componentMetaData = {}
2
+
3
+ Luca.registry.getMetaDataFor = (componentName)->
4
+ new MetaDataProxy(Luca.registry.componentMetaData[ componentName ])
5
+
6
+ Luca.registry.addMetaData = (componentName, key, value)->
7
+ data = Luca.registry.componentMetaData[ componentName ] ||= {}
8
+ data[ key ] = _(value).clone()
9
+ data
10
+
11
+ class MetaDataProxy
12
+ constructor: (@meta={})->
13
+ _.defaults @meta,
14
+ "super class name" : ""
15
+ "display name" : ""
16
+ "public interface" : []
17
+ "public configuration" : []
18
+ "private interface" : []
19
+ "private configuration" : []
20
+ "class configuration" : []
21
+ "class interface" : []
22
+
23
+ superClass: ()->
24
+ Luca.util.resolve(@meta["super class name"])
25
+
26
+ componentDefinition: ()->
27
+ Luca.registry.find @meta["display name"]
28
+
29
+ componentPrototype: ()->
30
+ @componentDefinition()?.prototype
31
+
32
+ prototypeFunctions: ()->
33
+ _.functions( @componentPrototype() )
34
+
35
+ classAttributes: ()->
36
+ _.uniq @classInterface().concat( @classConfiguration() )
37
+
38
+ publicAttributes: ()->
39
+ _.uniq @publicInterface().concat( @publicConfiguration() )
40
+
41
+ privateAttributes: ()->
42
+ _.uniq @privateInterface().concat( @privateConfiguration() )
43
+
44
+ classMethods: ()->
45
+ list = _.functions( @componentDefinition() )
46
+ _( list ).intersection( @classAttributes() )
47
+
48
+ publicMethods: ()->
49
+ _( @prototypeFunctions() ).intersection( @publicAttributes() )
50
+
51
+ privateMethods: ()->
52
+ _( @prototypeFunctions() ).intersection( @privateAttributes() )
53
+
54
+ classConfiguration: ()->
55
+ @meta["class configuration"]
56
+
57
+ publicConfiguration: ()->
58
+ @meta["public configuration"]
59
+
60
+ privateConfiguration: ()->
61
+ @meta["private configuration"]
62
+
63
+ classInterface: ()->
64
+ @meta["class interface"]
65
+
66
+ publicInterface: ()->
67
+ @meta["public interface"]
68
+
69
+ privateInterface: ()->
70
+ @meta["private interface"]
71
+
72
+ triggers: ()->
73
+ @meta["hooks"]
74
+
75
+ hooks: ()->
76
+ @meta["hooks"]
77
+
78
+ styleHierarchy: ()->
79
+ list = _( @classHierarchy() ).map (cls)->
80
+ Luca.util.toCssClass(cls, 'views', 'components', 'core','fields','containers')
81
+
82
+ _( list ).without('backbone-view','luca-view')
83
+
84
+ classHierarchy: ()->
85
+ list = [ @meta["display name"], @meta["super class name"]]
86
+
87
+ proxy = @superClass()?.prototype?.componentMetaData?()
88
+
89
+ until not proxy
90
+ list = list.concat( proxy?.classHierarchy() )
91
+ proxy = proxy.superClass()?.prototype?.componentMetaData?()
92
+
93
+ _( list ).uniq()
@@ -8,12 +8,13 @@ model.defines
8
8
  initialize: ()->
9
9
  Backbone.Model::initialize(@, arguments)
10
10
  setupComputedProperties.call(@)
11
+ Luca.concern.setup.call(@)
11
12
 
12
13
  read: (attr)->
13
14
  if _.isFunction(@[attr])
14
15
  @[attr].call(@)
15
16
  else
16
- @get(attr)
17
+ @get(attr) || @[attr]
17
18
 
18
19
  get: (attr)->
19
20
  if @computed?.hasOwnProperty(attr)
@@ -37,3 +38,19 @@ setupComputedProperties = ()->
37
38
  @trigger "change:#{attr}"
38
39
 
39
40
  @trigger "change:#{attr}" if @has(dep)
41
+
42
+
43
+ Luca.Model._originalExtend = Backbone.Model.extend
44
+
45
+ Luca.Model.extend = (definition={})->
46
+ # for backward compatibility
47
+ definition.concerns ||= definition.concerns if definition.concerns?
48
+
49
+ componentClass = Luca.Model._originalExtend.call(@, definition)
50
+
51
+ if definition.concerns? and _.isArray( definition.concerns )
52
+ for module in definition.concerns
53
+ Luca.decorate( componentClass ).with( module )
54
+
55
+ componentClass
56
+
@@ -76,10 +76,8 @@ Luca.registry.namespaces = (resolve=true)->
76
76
  _( registry.namespaces ).map (namespace)->
77
77
  if resolve then Luca.util.resolve( namespace ) else namespace
78
78
 
79
-
80
-
81
79
  # Lookup a component in the Luca component registry
82
- # by it's ctype identifier. If it doesn't exist,
80
+ # by it's type identifier. If it doesn't exist,
83
81
  # check any other registered namespace
84
82
  Luca.registry.lookup = (ctype)->
85
83
  if alias = Luca.registry.aliases[ ctype ]
@@ -119,6 +117,9 @@ Luca.registry.classes = (toString=false)->
119
117
  className: className
120
118
  ctype: ctype
121
119
 
120
+ Luca.registry.find = (search)->
121
+ Luca.util.resolve(search) || Luca.define.findDefinition(search)
122
+
122
123
  Luca.cache = Luca.cacheInstance = (cacheKey, object)->
123
124
  return unless cacheKey?
124
125
  return object if object?.doNotCache is true
data/src/core/view.coffee CHANGED
@@ -4,9 +4,9 @@ view.extends "Backbone.View"
4
4
 
5
5
  # includes are extensions to the prototype, and have no special behavior
6
6
  view.includes "Luca.Events",
7
- "Luca.modules.DomHelpers"
7
+ "Luca.concerns.DomHelpers"
8
8
 
9
- # mixins are includes with special property / method conventions
9
+ # concerns are includes with special property / method conventions
10
10
  # which customize the components through the use of __initializer and
11
11
  # __included method names. These will be called every time an instance
12
12
  # is created, and the first time the mixin is used to enhance a component.
@@ -48,16 +48,12 @@ view.defines
48
48
 
49
49
  @setupHooks _( Luca.View::hooks.concat( @hooks ) ).uniq()
50
50
 
51
- @setupMixins()
52
- @delegateEvents()
51
+ Luca.concern.setup.call(@)
53
52
 
53
+ @delegateEvents()
54
+
54
55
  @trigger "after:initialize", @
55
56
 
56
- setupMixins: ()->
57
- if @mixins?.length > 0
58
- for module in @mixins
59
- Luca.mixin(module)?.__initializer?.call(@, @, module)
60
-
61
57
  #### Hooks or Auto Event Binding
62
58
  #
63
59
  # views which inherit from Luca.View can define hooks
@@ -71,18 +67,7 @@ view.defines
71
67
  # after:render : afterRender()
72
68
  # after:initialize : afterInitialize()
73
69
  # first:activation : firstActivation()
74
- setupHooks: (set)->
75
- set ||= @hooks
76
-
77
- _(set).each (eventId)=>
78
- fn = Luca.util.hook( eventId )
79
-
80
- callback = ()->
81
- @[fn]?.apply @, arguments
82
-
83
- callback = _.once(callback) if eventId?.match(/once:/)
84
-
85
- @on eventId, callback, @
70
+ setupHooks: Luca.util.setupHooks
86
71
 
87
72
  registerEvent: (selector, handler)->
88
73
  @events ||= {}
@@ -92,9 +77,14 @@ view.defines
92
77
  definitionClass: ()->
93
78
  Luca.util.resolve(@displayName, window)?.prototype
94
79
 
95
- collections: ()-> Luca.util.selectProperties( Luca.isBackboneCollection, @ )
96
- models: ()-> Luca.util.selectProperties( Luca.isBackboneModel, @ )
97
- views: ()-> Luca.util.selectProperties( Luca.isBackboneView, @ )
80
+ collections: ()->
81
+ Luca.util.selectProperties( Luca.isBackboneCollection, @ )
82
+
83
+ models: ()->
84
+ Luca.util.selectProperties( Luca.isBackboneModel, @ )
85
+
86
+ views: ()->
87
+ Luca.util.selectProperties( Luca.isBackboneView, @ )
98
88
 
99
89
  debug: (args...)->
100
90
  return unless @debugMode or window.LucaDebugMode?
@@ -165,14 +155,18 @@ bindEventHandlers = (events={})->
165
155
  if _.isString(handler)
166
156
  _.bindAll @, handler
167
157
 
168
- Luca.View.extend = (definition)->
158
+ Luca.View.deferrableEvent = "reset"
159
+
160
+ Luca.View.extend = (definition={})->
169
161
  definition = Luca.View.renderWrapper( definition )
162
+ # for backward compatibility
163
+ definition.concerns ||= definition.concerns if definition.concerns?
170
164
 
171
- if definition.mixins? and _.isArray( definition.mixins )
172
- for module in definition.mixins
173
- Luca.decorate( definition ).with( module )
165
+ componentClass = Luca.View._originalExtend.call(@, definition)
174
166
 
175
- Luca.View._originalExtend.call(@, definition)
167
+ if definition.concerns? and _.isArray( definition.concerns )
168
+ for module in definition.concerns
169
+ Luca.decorate( componentClass ).with( module )
176
170
 
171
+ componentClass
177
172
 
178
- Luca.View.deferrableEvent = "reset"
data/src/define.coffee CHANGED
@@ -1,25 +1,39 @@
1
1
  # Component Definition Helpers
2
2
  #
3
- #
4
3
  # We have customized the core Backbone.extend process to use a slightly
5
4
  # different syntax, which allows us to intercept the component definition at
6
5
  # various points, and maintain information about classes being defined, and
7
6
  # the relationships between inherited classes, etc.
7
+ #
8
+ # Under the hood it isn't much more than Backbone.View.extend(@proto)
9
+ #
10
+ # Luca provides a self-documenting component generation language which
11
+ # allows you to build the @proto property in a way which captures the intent
12
+ # of the interface being described.
13
+ #
14
+ # Example:
15
+ # myForm = MyApp.register 'MyForm'
16
+ #
17
+ # myForm.extends 'Luca.components.FormView'
18
+ #
19
+ # myForm.triggers 'some:custom:hook'
20
+ #
21
+ # myForm.publicMethods
22
+ # publicMethod: ()-> ...
23
+ #
24
+ # myForm.classMethods
25
+ # classMethod: ()-> ...
26
+ #
27
+ # This gives us the ability to inspect our component registry at run time,
28
+ # auto-generate nice documentation, build development tools, etc.
8
29
 
9
- # _.def, or Luca.define returns a chainable object which allows you to define
10
- # your components with a readable syntax. For example:
11
-
12
- # _.def("Luca.View").extends("Backbone.View").with the_good:"shit"
13
- # _.def("MyView").extends("Luca.View").with the_custom:"shit"
14
- _.mixin
15
- def: Luca.component = Luca.define = Luca.register = (componentName)-> new DefineProxy(componentName)
16
-
17
- # The define proxy chain sets up a call to Luca.extend, which is a wrapper around Luca and Backbone component class' extend function.
18
- class DefineProxy
19
- constructor:(componentName)->
30
+ class ComponentDefinition
31
+ constructor:(componentName, @autoRegister=true)->
20
32
  @namespace = Luca.util.namespace()
21
33
  @componentId = @componentName = componentName
22
34
  @superClassName = 'Luca.View'
35
+ @properties ||= {}
36
+ @_classProperties ||= {}
23
37
 
24
38
  if componentName.match(/\./)
25
39
  @namespaced = true
@@ -30,6 +44,31 @@ class DefineProxy
30
44
  # automatically add the namespace to the namespace registry
31
45
  Luca.registry.addNamespace( parts.join('.') )
32
46
 
47
+ Luca.define.__definitions.push(@)
48
+
49
+ @create: (componentName, autoRegister=Luca.config.autoRegister)->
50
+ new ComponentDefinition(componentName, autoRegister)
51
+
52
+ isValid: ()->
53
+ return false unless _.isObject(@properties)
54
+ return false unless Luca.util.resolve(@superClassName)?
55
+ return false unless @componentName?
56
+ true
57
+
58
+ isDefined: ()->
59
+ @defined is true
60
+
61
+ isOpen: ()->
62
+ !!(@isValid() and not @isDefined())
63
+
64
+ meta: (key, value)->
65
+ metaKey = @namespace + '.' + @componentId
66
+ metaKey = metaKey.replace(/^\./,'')
67
+ data = Luca.registry.addMetaData(metaKey, key, value)
68
+
69
+ @properties.componentMetaData = ()->
70
+ Luca.registry.getMetaDataFor(metaKey)
71
+
33
72
  # allow for specifying the namespace
34
73
  in: (@namespace)-> @
35
74
 
@@ -43,6 +82,7 @@ class DefineProxy
43
82
  for hook in hooks
44
83
  @properties.hooks.push(hook)
45
84
  @properties.hooks = _.uniq(@properties.hooks)
85
+ @meta("hooks", @properties.hooks)
46
86
  @
47
87
 
48
88
  includes: (includes...)->
@@ -50,16 +90,69 @@ class DefineProxy
50
90
  for include in includes
51
91
  @properties.include.push(include)
52
92
  @properties.include = _.uniq(@properties.include)
93
+ @meta("includes", @properties.include)
94
+ @
95
+
96
+ mixesIn: (concerns...)->
97
+ _.defaults(@properties ||= {}, concerns: [])
98
+ for concern in concerns
99
+ @properties.concerns.push(concern)
100
+ @properties.concerns = _.uniq(@properties.concerns)
101
+
102
+ @meta("concerns", @properties.concerns)
103
+ @
104
+
105
+ contains: (components...)->
106
+ _.defaults(@properties, components: [])
107
+ @properties.components = components
108
+ @
109
+
110
+ validatesConfigurationWith:(validationConfiguration={})->
111
+ @meta "configuration validations", validationConfiguration
112
+ @properties.validatable = true
113
+ @
114
+
115
+ beforeDefinition: (callback)->
116
+ @_classProperties.beforeDefinition = callback
117
+ @
118
+
119
+ afterDefinition: (callback)->
120
+ @_classProperties.afterDefinition = callback
121
+ @
122
+
123
+ classConfiguration: (properties={})->
124
+ @meta("class configuration", _.keys(properties))
125
+ _.defaults((@_classProperties||={}), properties)
126
+ @
127
+
128
+ publicConfiguration: (properties={})->
129
+ @meta("public configuration", _.keys(properties) )
130
+ _.defaults((@properties||={}), properties)
131
+ @
132
+
133
+ privateConfiguration: (properties={})->
134
+ @meta("private configuration", _.keys(properties) )
135
+ _.defaults((@properties||={}), properties)
136
+ @
137
+
138
+ classInterface: (properties={})->
139
+ @meta("class interface", _.keys(properties))
140
+ _.defaults((@_classProperties||={}), properties)
53
141
  @
54
142
 
55
- mixesIn: (mixins...)->
56
- _.defaults(@properties ||= {}, mixins: [])
57
- for mixin in mixins
58
- @properties.mixins.push(mixin)
59
- @properties.mixins = _.uniq(@properties.mixins)
143
+ publicInterface: (properties={})->
144
+ @meta("public interface", _.keys(properties) )
145
+ _.defaults((@properties||={}), properties)
60
146
  @
61
147
 
62
- defaultProperties: (properties={})->
148
+ privateInterface: (properties={})->
149
+ @meta("private interface", _.keys(properties) )
150
+ _.defaults((@properties||={}), properties)
151
+ @
152
+
153
+ # This is the end of the chain. It MUST be called
154
+ # in order for the component definition to be complete.
155
+ definePrototype: (properties={})->
63
156
  _.defaults((@properties||={}), properties)
64
157
 
65
158
  at = if @namespaced
@@ -72,31 +165,74 @@ class DefineProxy
72
165
  eval("(window||global).#{ @namespace } = {}")
73
166
  at = Luca.util.resolve(@namespace,(window || global))
74
167
 
75
- at[@componentId] = Luca.extend(@superClassName,@componentName, @properties)
168
+ @meta("super class name", @superClassName )
169
+ @meta("display name", @componentName)
170
+
171
+ @properties.displayName = @componentName
172
+
173
+ @properties.componentMetaData = ()->
174
+ Luca.registry.getMetaDataFor(@displayName)
175
+
176
+ @_classProperties?.beforeDefinition?(@)
177
+
178
+ definition = at[@componentId] = Luca.extend(@superClassName,@componentName, @properties)
76
179
 
77
- if Luca.autoRegister is true
78
- componentType = "view" if Luca.isViewPrototype( at[@componentId] )
180
+ if @autoRegister is true
181
+ componentType = "view" if Luca.isViewPrototype( definition )
79
182
 
80
- if Luca.isCollectionPrototype( at[@componentId] )
183
+ if Luca.isCollectionPrototype( definition )
81
184
  Luca.Collection.namespaces ||= []
82
185
  Luca.Collection.namespaces.push( @namespace )
83
186
  componentType = "collection"
84
187
 
85
- componentType = "model" if Luca.isModelPrototype( at[@componentId] )
188
+ componentType = "model" if Luca.isModelPrototype( definition )
86
189
 
87
190
  # automatically register this with the component registry
88
191
  Luca.registerComponent( _.string.underscored(@componentId), @componentName, componentType)
89
192
 
90
- at[@componentId]
193
+ @defined = true
194
+
195
+ unless _.isEmpty(@_classProperties)
196
+ _.extend(definition, @_classProperties)
197
+
198
+ definition?.afterDefinition?.call(definition, @)
199
+
200
+ definition
201
+
91
202
 
92
203
  # Aliases for the mixin definition
93
- DefineProxy::behavesAs = DefineProxy::uses = DefineProxy::mixesIn
204
+ cd = ComponentDefinition::
205
+
206
+ cd.concerns = cd.behavesAs = cd.uses = cd.mixesIn
94
207
 
95
208
  # Aliases for the final call on the define proxy
96
- DefineProxy::defines = DefineProxy::defaults = DefineProxy::exports = DefineProxy::defaultProperties
97
- DefineProxy::defaultsTo = DefineProxy::enhance = DefineProxy::with = DefineProxy::defaultProperties
209
+ cd.register = cd.defines = cd.defaults = cd.exports = cd.defaultProperties = cd.definePrototype
210
+
211
+ cd.defaultsTo = cd.enhance = cd.with = cd.definePrototype
212
+
213
+ cd.publicMethods = cd.publicInterface
214
+ cd.privateMethods = cd.privateInterface
215
+ cd.classMethods = cd.classInterface
98
216
 
99
- # The last method of the DefineProxy chain is always going to result in
217
+ _.extend (Luca.define = ComponentDefinition.create),
218
+ __definitions: []
219
+ incomplete: ()->
220
+ _( Luca.define.__definitions ).select (definition)->
221
+ definition.isOpen()
222
+ close: ()->
223
+ for open in Luca.define.incomplete()
224
+ open.register() if open.isValid()
225
+ Luca.define.__definitions.length = 0
226
+ findDefinition: (componentName)->
227
+ _( Luca.define.__definitions ).detect (definition)->
228
+ definition.componentName is componentName
229
+
230
+ Luca.register = (componentName)->
231
+ new ComponentDefinition(componentName, true)
232
+
233
+ _.mixin def: Luca.define
234
+
235
+ # The last method of the ComponentDefinition chain is always going to result in
100
236
  # a call to Luca.extend. Luca.extend wraps the call to Luca.View.extend,
101
237
  # or Backbone.Collection.extend, and accepts the names of the extending,
102
238
  # and extended classes as strings. This allows us to maintain information
@@ -105,8 +241,6 @@ DefineProxy::defaultsTo = DefineProxy::enhance = DefineProxy::with = DefineProxy
105
241
  Luca.extend = (superClassName, childName, properties={})->
106
242
  superClass = Luca.util.resolve( superClassName, (window || global) )
107
243
 
108
- superClass.__initializers ||= []
109
-
110
244
  unless _.isFunction(superClass?.extend)
111
245
  throw "Error defining #{ childName }. #{ superClassName } is not a valid component to extend from"
112
246
 
@@ -117,9 +251,8 @@ Luca.extend = (superClassName, childName, properties={})->
117
251
  superClass
118
252
 
119
253
  properties._super = (method, context=@, args=[])->
120
- # protect against a stack too deep error in weird cases
121
254
  # TODO: debug this better
122
-
255
+ # protect against a stack too deep error in weird cases
123
256
  @_superClass().prototype[method]?.apply(context, args)
124
257
 
125
258
  definition = superClass.extend(properties)
@@ -133,50 +266,3 @@ Luca.extend = (superClassName, childName, properties={})->
133
266
 
134
267
  definition
135
268
 
136
-
137
- Luca.mixin = (mixinName)->
138
- namespace = _( Luca.mixin.namespaces ).detect (space)->
139
- Luca.util.resolve(space)?[ mixinName ]?
140
-
141
- namespace ||= "Luca.modules"
142
-
143
- resolved = Luca.util.resolve(namespace)[ mixinName ]
144
-
145
- console.log "Could not find #{ mixinName } in ", Luca.mixin.namespaces unless resolved?
146
-
147
- resolved
148
-
149
- Luca.mixin.namespaces = [
150
- "Luca.modules"
151
- ]
152
-
153
- Luca.mixin.namespace = (namespace)->
154
- Luca.mixin.namespaces.push(namespace)
155
- Luca.mixin.namespaces = _( Luca.mixin.namespaces ).uniq()
156
-
157
- # Luca.decorate('Luca.View').with('Luca.modules.MyCustomMixin')
158
- Luca.decorate = (componentPrototype)->
159
- componentPrototype = Luca.util.resolve(componentPrototype).prototype if _.isString(componentPrototype)
160
-
161
- return with: (mixin)->
162
- mixinDefinition = Luca.mixin(mixin)
163
-
164
- mixinPrivates = _( mixinDefinition ).chain().keys().select (key)->
165
- "#{ key }".match(/^__/)
166
-
167
- sanitized = _( mixinDefinition ).omit( mixinPrivates.value() )
168
-
169
- _.extend(componentPrototype, sanitized)
170
-
171
- # When a mixin is included, we may want to do things
172
- mixinDefinition?.__included?.call(mixinDefinition, mixin)
173
-
174
- superclassMixins = componentPrototype._superClass()::mixins
175
-
176
- componentPrototype.mixins ||= []
177
- componentPrototype.mixins.push( mixin )
178
- componentPrototype.mixins = componentPrototype.mixins.concat( superclassMixins )
179
-
180
- componentPrototype.mixins = _( componentPrototype.mixins ).chain().uniq().compact().value()
181
-
182
- componentPrototype