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.
- data/CHANGELOG +30 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +27 -0
- data/lib/luca/rails/version.rb +1 -1
- data/spec/components/controller_spec.coffee +58 -0
- data/spec/components/form_view_spec.coffee +4 -0
- data/spec/concerns/dom_helpers_spec.coffee +16 -0
- data/spec/{modules → concerns}/filterable_spec.coffee +0 -0
- data/spec/concerns/model_presenter_spec.coffee +31 -0
- data/spec/{modules → concerns}/paginatable_spec.coffee +0 -0
- data/spec/{modules → concerns}/state_model_spec.coffee +0 -0
- data/spec/concerns_spec.coffee +88 -0
- data/spec/core/container_spec.coffee +103 -6
- data/spec/core/field_spec.coffee +4 -0
- data/spec/core/model_spec.coffee +6 -1
- data/spec/define_spec.coffee +104 -7
- data/spec/framework_spec.coffee +30 -1
- data/spec/util_spec.coffee +24 -0
- data/src/components/application.coffee +62 -25
- data/src/components/base_toolbar.coffee +6 -4
- data/src/components/collection_loader_view.coffee +3 -1
- data/src/components/collection_view.coffee +36 -73
- data/src/components/controller.coffee +73 -35
- data/src/components/fields/button_field.coffee +20 -12
- data/src/components/fields/checkbox_array.coffee +8 -2
- data/src/components/fields/checkbox_field.coffee +18 -9
- data/src/components/fields/file_upload_field.coffee +5 -1
- data/src/components/fields/hidden_field.coffee +3 -1
- data/src/components/fields/label_field.coffee +4 -3
- data/src/components/fields/select_field.coffee +7 -8
- data/src/components/fields/text_area_field.coffee +3 -2
- data/src/components/fields/text_field.coffee +5 -4
- data/src/components/fields/type_ahead_field.coffee +4 -2
- data/src/components/form_button_toolbar.coffee +4 -1
- data/src/components/form_view.coffee +26 -24
- data/src/components/grid_view.coffee +3 -3
- data/src/components/multi_collection_view.coffee +6 -35
- data/src/components/pagination_control.coffee +1 -3
- data/src/components/router.coffee +2 -0
- data/src/components/table_view.coffee +7 -0
- data/src/concerns.coffee +70 -0
- data/src/{modules → concerns}/application_event_bindings.coffee +1 -1
- data/src/{modules → concerns}/collection_event_bindings.coffee +1 -1
- data/src/{modules → concerns}/deferrable.coffee +1 -1
- data/src/{modules → concerns}/dom_helpers.coffee +11 -2
- data/src/{modules → concerns}/enhanced_properties.coffee +1 -1
- data/src/{modules → concerns}/filterable.coffee +11 -11
- data/src/{modules → concerns}/grid_layout.coffee +1 -1
- data/src/{modules → concerns}/loadmaskable.coffee +1 -1
- data/src/{modules → concerns}/local_storage.coffee +0 -0
- data/src/{modules → concerns}/modal_view.coffee +1 -1
- data/src/concerns/model_presenter.coffee +23 -0
- data/src/{modules → concerns}/paginatable.coffee +9 -3
- data/src/concerns/query_collection_bindings.coffee +44 -0
- data/src/{modules → concerns}/state_model.coffee +1 -1
- data/src/{modules → concerns}/templating.coffee +1 -1
- data/src/containers/card_view.coffee +16 -9
- data/src/containers/tab_view.coffee +8 -11
- data/src/containers/viewport.coffee +3 -3
- data/src/core/collection.coffee +39 -28
- data/src/core/container.coffee +37 -15
- data/src/core/field.coffee +40 -39
- data/src/core/meta_data.coffee +93 -0
- data/src/core/model.coffee +18 -1
- data/src/core/registry.coffee +4 -3
- data/src/core/view.coffee +24 -30
- data/src/define.coffee +165 -79
- data/src/framework.coffee +97 -21
- data/src/index.coffee +4 -2
- data/src/managers/collection_manager.coffee +7 -3
- data/src/stylesheets/components/checkbox_array.scss +1 -1
- data/src/stylesheets/components/form_view.scss +5 -5
- data/src/stylesheets/components/viewport.scss +2 -1
- data/src/stylesheets/containers/container.scss +0 -5
- data/src/stylesheets/containers/tab_view.scss +5 -5
- data/src/templates/fields/text_area_field.jst.ejs +1 -1
- data/src/templates/fields/text_field.jst.ejs +1 -1
- data/src/util.coffee +47 -0
- data/vendor/assets/javascripts/luca-ui-full.js +1279 -494
- data/vendor/assets/javascripts/luca-ui-full.min.js +5 -5
- data/vendor/assets/javascripts/luca-ui-templates.js +2 -2
- data/vendor/assets/javascripts/luca-ui.js +1279 -494
- data/vendor/assets/javascripts/luca-ui.min.js +5 -4
- data/vendor/assets/stylesheets/luca-ui.css +15 -15
- metadata +27 -20
- 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()
|
data/src/core/model.coffee
CHANGED
@@ -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
|
+
|
data/src/core/registry.coffee
CHANGED
@@ -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
|
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.
|
7
|
+
"Luca.concerns.DomHelpers"
|
8
8
|
|
9
|
-
#
|
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
|
-
@
|
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:
|
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: ()->
|
96
|
-
|
97
|
-
|
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.
|
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
|
-
|
172
|
-
for module in definition.mixins
|
173
|
-
Luca.decorate( definition ).with( module )
|
165
|
+
componentClass = Luca.View._originalExtend.call(@, definition)
|
174
166
|
|
175
|
-
|
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
|
-
|
10
|
-
|
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
|
-
|
56
|
-
_.
|
57
|
-
|
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
|
-
|
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
|
-
|
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
|
78
|
-
componentType = "view" if Luca.isViewPrototype(
|
180
|
+
if @autoRegister is true
|
181
|
+
componentType = "view" if Luca.isViewPrototype( definition )
|
79
182
|
|
80
|
-
if Luca.isCollectionPrototype(
|
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(
|
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
|
-
|
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
|
-
|
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
|
-
|
97
|
-
|
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
|
-
|
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
|