luca 0.9.6 → 0.9.7
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +37 -14
- data/lib/luca/rails/version.rb +1 -1
- data/spec/components/collection_view_spec.coffee +24 -2
- data/spec/components/pagination_control_spec.coffee +0 -0
- data/spec/concerns/dom_helpers_spec.coffee +16 -0
- data/spec/concerns/filterable_spec.coffee +25 -0
- data/spec/concerns/model_presenter_spec.coffee +31 -0
- data/spec/concerns/paginatable_spec.coffee +0 -0
- data/spec/concerns/state_model_spec.coffee +0 -0
- data/spec/concerns_spec.coffee +88 -0
- data/spec/core/container_spec.coffee +74 -12
- data/spec/core/model_spec.coffee +6 -1
- data/spec/define_spec.coffee +0 -6
- data/spec/util_spec.coffee +24 -0
- data/src/components/application.coffee +32 -30
- data/src/components/base_toolbar.coffee +6 -4
- data/src/components/collection_loader_view.coffee +3 -1
- data/src/components/collection_view.coffee +42 -21
- data/src/components/controller.coffee +3 -1
- data/src/components/fields/button_field.coffee +19 -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_field.coffee +3 -1
- 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 +49 -44
- data/src/components/grid_view.coffee +1 -1
- data/src/components/multi_collection_view.coffee +49 -22
- data/src/components/pagination_control.coffee +17 -13
- 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/concerns/filterable.coffee +82 -0
- 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/concerns/paginatable.coffee +87 -0
- data/src/{modules → concerns}/state_model.coffee +1 -1
- data/src/{modules → concerns}/templating.coffee +1 -1
- data/src/concerns.coffee +70 -0
- data/src/containers/tab_view.coffee +7 -10
- data/src/core/collection.coffee +17 -1
- data/src/core/container.coffee +56 -31
- data/src/core/field.coffee +39 -38
- data/src/core/meta_data.coffee +37 -0
- data/src/core/model.coffee +18 -1
- data/src/core/view.coffee +25 -29
- data/src/define.coffee +54 -66
- data/src/framework.coffee +23 -18
- data/src/index.coffee +3 -1
- 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/tools/console.coffee +5 -5
- data/src/util.coffee +47 -0
- data/vendor/assets/javascripts/luca-ui-development-tools.js +5 -5
- data/vendor/assets/javascripts/luca-ui-development-tools.min.js +1 -1
- data/vendor/assets/javascripts/luca-ui-full.js +905 -416
- data/vendor/assets/javascripts/luca-ui-full.min.js +5 -5
- data/vendor/assets/javascripts/luca-ui.js +905 -416
- data/vendor/assets/javascripts/luca-ui.min.js +5 -4
- data/vendor/assets/stylesheets/luca-ui.css +15 -15
- metadata +27 -17
- data/spec/mixin_spec.coffee +0 -49
- data/src/modules/filterable.coffee +0 -60
- data/src/modules/paginatable.coffee +0 -79
data/src/concerns.coffee
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
Luca.concern = (mixinName)->
|
2
|
+
namespace = _( Luca.concern.namespaces ).detect (space)->
|
3
|
+
Luca.util.resolve(space)?[ mixinName ]?
|
4
|
+
|
5
|
+
namespace ||= "Luca.concerns"
|
6
|
+
|
7
|
+
resolved = Luca.util.resolve(namespace)[ mixinName ]
|
8
|
+
|
9
|
+
console.log "Could not find #{ mixinName } in ", Luca.concern.namespaces unless resolved?
|
10
|
+
|
11
|
+
resolved
|
12
|
+
|
13
|
+
Luca.concern.namespaces = [
|
14
|
+
"Luca.concerns"
|
15
|
+
]
|
16
|
+
|
17
|
+
Luca.concern.namespace = (namespace)->
|
18
|
+
Luca.concern.namespaces.push(namespace)
|
19
|
+
Luca.concern.namespaces = _( Luca.concern.namespaces ).uniq()
|
20
|
+
|
21
|
+
Luca.concern.setup = ()->
|
22
|
+
if @concerns?.length > 0
|
23
|
+
for module in @concerns
|
24
|
+
Luca.concern(module)?.__initializer?.call(@, @, module)
|
25
|
+
|
26
|
+
# Luca.decorate('Luca.View').with('Luca.concerns.MyCustomMixin')
|
27
|
+
Luca.decorate = (target)->
|
28
|
+
try
|
29
|
+
if _.isString(target)
|
30
|
+
componentName = target
|
31
|
+
componentClass = Luca.util.resolve(componentName)
|
32
|
+
|
33
|
+
componentClass = target if _.isFunction(target)
|
34
|
+
componentPrototype = componentClass.prototype
|
35
|
+
componentName = componentName || componentClass.displayName
|
36
|
+
componentName ||= componentPrototype.displayName
|
37
|
+
catch e
|
38
|
+
console.log e.message
|
39
|
+
console.log e.stack
|
40
|
+
console.log "Error calling Luca.decorate on ", componentClass, componentPrototype, componentName
|
41
|
+
|
42
|
+
throw(e)
|
43
|
+
|
44
|
+
return with: (mixinName)->
|
45
|
+
mixinDefinition = Luca.concern(mixinName)
|
46
|
+
mixinDefinition.__displayName ||= mixinName
|
47
|
+
|
48
|
+
mixinPrivates = _( mixinDefinition ).chain().keys().select (key)->
|
49
|
+
"#{ key }".match(/^__/) or key is "classMethods"
|
50
|
+
|
51
|
+
sanitized = _( mixinDefinition ).omit( mixinPrivates.value() )
|
52
|
+
|
53
|
+
_.extend(componentPrototype, sanitized)
|
54
|
+
|
55
|
+
if mixinDefinition.classMethods?
|
56
|
+
for method, fn of mixinDefinition.classMethods
|
57
|
+
componentClass[ method ] = _.bind(fn, componentClass)
|
58
|
+
|
59
|
+
# When a mixin is included, we may want to do things
|
60
|
+
mixinDefinition?.__included?(componentName, componentClass, mixinDefinition)
|
61
|
+
|
62
|
+
superclassMixins = componentPrototype._superClass()::concerns
|
63
|
+
|
64
|
+
componentPrototype.concerns ||= []
|
65
|
+
componentPrototype.concerns.push( mixinName )
|
66
|
+
componentPrototype.concerns = componentPrototype.concerns.concat( superclassMixins )
|
67
|
+
|
68
|
+
componentPrototype.concerns = _( componentPrototype.concerns ).chain().uniq().compact().value()
|
69
|
+
|
70
|
+
componentPrototype
|
@@ -1,23 +1,20 @@
|
|
1
1
|
_.def('Luca.containers.TabView').extends('Luca.containers.CardView').with
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
]
|
7
|
-
|
8
|
-
componentType: 'tab_view'
|
9
|
-
|
10
|
-
className: 'luca-ui-tab-view tabbable'
|
3
|
+
tabView = Luca.register "Luca.containers.TabView"
|
4
|
+
tabView.triggers "before:select",
|
5
|
+
"after:select"
|
11
6
|
|
7
|
+
tabView.publicConfiguration
|
12
8
|
tab_position: 'top'
|
13
|
-
|
14
9
|
tabVerticalOffset: '50px'
|
15
10
|
|
11
|
+
tabView.privateConfiguration
|
12
|
+
additionalClassNames: 'tabbable'
|
16
13
|
navClass: "nav-tabs"
|
17
|
-
|
18
14
|
bodyTemplate: "containers/tab_view"
|
19
15
|
bodyEl: "div.tab-content"
|
20
16
|
|
17
|
+
tabView.defines
|
21
18
|
initialize: (@options={})->
|
22
19
|
@navClass = "nav-list"if @navStyle is "list"
|
23
20
|
|
data/src/core/collection.coffee
CHANGED
@@ -91,6 +91,8 @@ collection.defines
|
|
91
91
|
if models
|
92
92
|
@reset models, silent: true, parse: options?.parse
|
93
93
|
|
94
|
+
Luca.concern.setup.call(@)
|
95
|
+
|
94
96
|
@trigger "after:initialize"
|
95
97
|
|
96
98
|
# Luca.Collections will append a query string to the URL
|
@@ -211,7 +213,7 @@ collection.defines
|
|
211
213
|
# fetch will try to pull from the bootstrap if it is setup to do so
|
212
214
|
# you can actually make the roundtrip to the server anyway if you pass
|
213
215
|
# refresh = true in the options hash
|
214
|
-
return @bootstrap() if @cached_models().length and not options.refresh
|
216
|
+
return @bootstrap() if @cached_models().length and not (options.refresh is true or options.remote is true)
|
215
217
|
|
216
218
|
url = if _.isFunction(@url) then @url() else @url
|
217
219
|
|
@@ -350,6 +352,20 @@ _.extend Luca.Collection.prototype,
|
|
350
352
|
|
351
353
|
Backbone.View.prototype.trigger.apply @, arguments
|
352
354
|
|
355
|
+
Luca.Collection._originalExtend = Backbone.Collection.extend
|
356
|
+
|
357
|
+
Luca.Collection.extend = (definition={})->
|
358
|
+
# for backward compatibility
|
359
|
+
definition.concerns ||= definition.concerns if definition.concerns?
|
360
|
+
|
361
|
+
componentClass = Luca.Collection._originalExtend.call(@, definition)
|
362
|
+
|
363
|
+
if definition.concerns? and _.isArray( definition.concerns )
|
364
|
+
for module in definition.concerns
|
365
|
+
Luca.decorate( componentClass ).with( module )
|
366
|
+
|
367
|
+
componentClass
|
368
|
+
|
353
369
|
# Always include these parameters in every request to your REST API.
|
354
370
|
#
|
355
371
|
# either specify a function which returns a hash, or just a normal hash
|
data/src/core/container.coffee
CHANGED
@@ -9,7 +9,7 @@ container.triggers "before:components",
|
|
9
9
|
"after:layout",
|
10
10
|
"first:activation"
|
11
11
|
|
12
|
-
container.defines
|
12
|
+
container.defines
|
13
13
|
className: 'luca-ui-container'
|
14
14
|
|
15
15
|
componentTag: 'div'
|
@@ -25,7 +25,7 @@ container.defines
|
|
25
25
|
# @componentEvents provides declarative syntax for responding to events on
|
26
26
|
# the components in this container. the format of the syntax is very similar
|
27
27
|
# to the other event binding helpers:
|
28
|
-
#
|
28
|
+
#
|
29
29
|
# component_accessor component:trigger
|
30
30
|
#
|
31
31
|
# where component_accessor is either the name of the role, or a method on the container
|
@@ -115,6 +115,8 @@ container.defines
|
|
115
115
|
applyDOMConfig.call(container, component, index)
|
116
116
|
|
117
117
|
prepareComponents: ()->
|
118
|
+
container = @
|
119
|
+
|
118
120
|
# accept components as an array of strings representing
|
119
121
|
# the luca component type
|
120
122
|
for component in @components when _.isString(component)
|
@@ -130,6 +132,26 @@ container.defines
|
|
130
132
|
panel = @make(@componentTag, componentContainerElement, '')
|
131
133
|
@$append( panel )
|
132
134
|
|
135
|
+
# if the container defines a @defaults property
|
136
|
+
# then we should make sure our child components inherit
|
137
|
+
# these values unless specifically defined
|
138
|
+
if container.defaults?
|
139
|
+
component = _.defaults(component, (container.defaults || {}))
|
140
|
+
|
141
|
+
# if the container defines an @extensions property as an array of
|
142
|
+
# configuration objects, then we will extend the component config with
|
143
|
+
# the object in the matching position of the @extensions array.
|
144
|
+
if _.isArray(container.extensions) and _.isObject(container.extensions?[ index ])
|
145
|
+
componentExtension = container.extensions[index]
|
146
|
+
component = _.extend(component, componentExtension)
|
147
|
+
|
148
|
+
# if the container defines an @extensions property as an object of nested hashes,
|
149
|
+
# then extensions is a key/value pair whose key represents the role of the component
|
150
|
+
# that we wish to extend / customize
|
151
|
+
if component.role? and _.isObject(container.extensions) and _.isObject(container.extensions[component.role])
|
152
|
+
componentExtension = container.extensions[component.role]
|
153
|
+
component = _.extend(component, componentExtension)
|
154
|
+
|
133
155
|
unless component.container?
|
134
156
|
component.container = "##{ componentContainerElement.id }" if @generateComponentElements
|
135
157
|
component.container ||= @$bodyEl()
|
@@ -157,30 +179,31 @@ container.defines
|
|
157
179
|
# adding the views @$el to the appropriate @container.
|
158
180
|
|
159
181
|
# you can also just pass a string representing the component_type
|
160
|
-
component = if Luca.
|
182
|
+
component = if Luca.isComponent( object )
|
161
183
|
object
|
162
184
|
else
|
163
185
|
object.type ||= object.ctype
|
164
186
|
|
165
187
|
if !object.type?
|
188
|
+
# TODO
|
189
|
+
# Add support for all of the various components property aliases
|
166
190
|
if object.components?
|
167
191
|
object.type = object.ctype = 'container'
|
168
192
|
else
|
169
193
|
object.type = object.ctype = Luca.defaultComponentType
|
170
194
|
|
171
|
-
# if the container defines a @defaults property
|
172
|
-
# then we should make sure our child components inherit
|
173
|
-
# these values unless specifically defined
|
174
|
-
object = _.defaults(object, (container.defaults || {}))
|
175
|
-
|
176
195
|
created = Luca.util.lazyComponent( object )
|
177
196
|
|
178
197
|
# if we're using base backbone views, then they don't extend themselves
|
179
198
|
# with their passed options, so this is a workaround to get them to
|
180
199
|
# pick up the container config property
|
181
|
-
if !component.container and component.options
|
200
|
+
if !component.container and component.options?.container
|
182
201
|
component.container = component.options.container
|
183
202
|
|
203
|
+
if not component.container?
|
204
|
+
console.log component,index,@
|
205
|
+
console.error "could not assign container property to component on container #{ @name || @cid }"
|
206
|
+
|
184
207
|
indexComponent( component ).at(index).in( @componentIndex )
|
185
208
|
|
186
209
|
component
|
@@ -194,14 +217,14 @@ container.defines
|
|
194
217
|
renderComponents: (@debugMode="")->
|
195
218
|
@debug "container render components"
|
196
219
|
|
197
|
-
container = @
|
220
|
+
container = @
|
198
221
|
_(@components).each (component)->
|
199
|
-
component.getParent = ()->
|
200
|
-
container
|
222
|
+
component.getParent = ()->
|
223
|
+
container
|
201
224
|
|
202
225
|
try
|
203
|
-
|
204
|
-
component.render()
|
226
|
+
@$( component.container ).eq(0).append( component.el )
|
227
|
+
component.render()
|
205
228
|
catch e
|
206
229
|
console.log "Error Rendering Component #{ component.name || component.cid }", component
|
207
230
|
|
@@ -232,7 +255,7 @@ container.defines
|
|
232
255
|
#### Underscore Methods For Working with Components
|
233
256
|
_: ()-> _( @components )
|
234
257
|
|
235
|
-
pluck: (attribute)->
|
258
|
+
pluck: (attribute)->
|
236
259
|
@_().pluck(attribute)
|
237
260
|
|
238
261
|
invoke: (method)->
|
@@ -243,17 +266,17 @@ container.defines
|
|
243
266
|
|
244
267
|
detect: (fn)->
|
245
268
|
@_().detect(attribute)
|
246
|
-
|
269
|
+
|
247
270
|
reject: (fn)->
|
248
271
|
@_().reject(fn)
|
249
272
|
|
250
273
|
map: (fn)->
|
251
274
|
@_().map(fn)
|
252
275
|
|
253
|
-
registerComponentEvents: ()->
|
276
|
+
registerComponentEvents: (eventList)->
|
254
277
|
container = @
|
255
278
|
|
256
|
-
for listener, handler of (@componentEvents||{})
|
279
|
+
for listener, handler of (eventList || @componentEvents||{})
|
257
280
|
[componentNameOrRole,eventId] = listener.split(' ')
|
258
281
|
|
259
282
|
unless _.isFunction( @[handler] )
|
@@ -262,7 +285,7 @@ container.defines
|
|
262
285
|
|
263
286
|
if componentNameOrRole is "*"
|
264
287
|
@eachComponent (component)=> component.on(eventId, @[handler], container)
|
265
|
-
else
|
288
|
+
else
|
266
289
|
component = @findComponentForEventBinding( componentNameOrRole )
|
267
290
|
|
268
291
|
unless component? and Luca.isComponent(component)
|
@@ -273,18 +296,18 @@ container.defines
|
|
273
296
|
|
274
297
|
|
275
298
|
subContainers: ()->
|
276
|
-
@select (component)->
|
299
|
+
@select (component)->
|
277
300
|
component.isContainer is true
|
278
301
|
|
279
302
|
roles: ()->
|
280
303
|
_( @allChildren() ).pluck('role')
|
281
|
-
|
304
|
+
|
282
305
|
allChildren: ()->
|
283
306
|
children = @components
|
284
307
|
grandchildren = _( @subContainers() ).invoke('allChildren')
|
285
|
-
|
308
|
+
_([children,grandchildren]).chain().compact().flatten().value()
|
286
309
|
|
287
|
-
findComponentForEventBinding: (nameRoleOrGetter, deep=
|
310
|
+
findComponentForEventBinding: (nameRoleOrGetter, deep=true)->
|
288
311
|
@findComponentByName(nameRoleOrGetter, deep) || @findComponentByGetter( nameRoleOrGetter, deep ) || @findComponentByRole( nameRoleOrGetter, deep )
|
289
312
|
|
290
313
|
findComponentByGetter: (getter, deep=false)->
|
@@ -293,7 +316,7 @@ container.defines
|
|
293
316
|
|
294
317
|
findComponentByRole: (role,deep=false)->
|
295
318
|
_( @allChildren() ).detect (component)->
|
296
|
-
component.role is role
|
319
|
+
component.role is role or component.type is role or component.ctype is role
|
297
320
|
|
298
321
|
findComponentByName: (name, deep=false)->
|
299
322
|
_( @allChildren() ).detect (component)->
|
@@ -311,7 +334,7 @@ container.defines
|
|
311
334
|
return component if component
|
312
335
|
|
313
336
|
if deep is true
|
314
|
-
sub_container = _( @components ).detect (component)->
|
337
|
+
sub_container = _( @components ).detect (component)->
|
315
338
|
component?.findComponent?(needle, haystack, true)
|
316
339
|
|
317
340
|
sub_container?.findComponent?(needle, haystack, true)
|
@@ -346,7 +369,7 @@ container.defines
|
|
346
369
|
|
347
370
|
getRootComponent: ()->
|
348
371
|
if @isRootComponent() then @ else @getParent().getRootComponent()
|
349
|
-
|
372
|
+
|
350
373
|
|
351
374
|
selectByAttribute: (attribute, value=undefined, deep=false)->
|
352
375
|
components = _( @components ).map (component)->
|
@@ -365,7 +388,7 @@ container.defines
|
|
365
388
|
|
366
389
|
# This is the method by which a container injects the rendered child views
|
367
390
|
# into the DOM. It will get passed the container object, and the component
|
368
|
-
# that is being rendered.
|
391
|
+
# that is being rendered.
|
369
392
|
Luca.core.Container.componentRenderer = (container, component)->
|
370
393
|
attachMethod = $( component.container )[ component.attachWith || "append" ]
|
371
394
|
attachMethod( component.render().el )
|
@@ -406,7 +429,6 @@ createGetterMethods = ()->
|
|
406
429
|
|
407
430
|
_( childrenWithGetter ).each (component)->
|
408
431
|
container[ component.getter ] ||= ()->
|
409
|
-
console.log "getter is being deprecated in favor of role"
|
410
432
|
console.log component.getter, component, container
|
411
433
|
component
|
412
434
|
|
@@ -428,8 +450,11 @@ doComponents = ()->
|
|
428
450
|
@trigger "before:render:components", @, @components
|
429
451
|
@renderComponents()
|
430
452
|
@trigger "after:components", @, @components
|
431
|
-
|
432
|
-
|
453
|
+
|
454
|
+
unless @skipGetterMethods is true
|
455
|
+
createGetterMethods.call(@)
|
456
|
+
createMethodsToGetComponentsByRole.call(@)
|
457
|
+
|
433
458
|
@registerComponentEvents()
|
434
459
|
|
435
460
|
validateContainerConfiguration = ()->
|
@@ -447,4 +472,4 @@ indexComponent = (component)->
|
|
447
472
|
if component.role?
|
448
473
|
map.role_index[ component.role ] = index
|
449
474
|
if component.name?
|
450
|
-
map.name_index[ component.name ] = index
|
475
|
+
map.name_index[ component.name ] = index
|
data/src/core/field.coffee
CHANGED
@@ -1,26 +1,51 @@
|
|
1
|
-
|
1
|
+
field = Luca.register "Luca.core.Field"
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
isField: true
|
3
|
+
field.extends "Luca.View"
|
6
4
|
|
7
|
-
|
5
|
+
field.triggers "before:validation",
|
6
|
+
"after:validation",
|
7
|
+
"on:change"
|
8
8
|
|
9
|
+
field.publicConfiguration
|
9
10
|
labelAlign: 'top'
|
10
|
-
|
11
|
-
hooks:[
|
12
|
-
"before:validation",
|
13
|
-
"after:validation",
|
14
|
-
"on:change"
|
15
|
-
]
|
16
|
-
|
17
|
-
# see: http://twitter.github.com/bootstrap/base-css.html
|
11
|
+
className: 'luca-ui-text-field luca-ui-field'
|
18
12
|
statuses: [
|
19
13
|
"warning"
|
20
14
|
"error"
|
21
15
|
"success"
|
22
16
|
]
|
23
17
|
|
18
|
+
field.publicInterface
|
19
|
+
disable: ()->
|
20
|
+
@getInputElement().attr('disabled', true)
|
21
|
+
|
22
|
+
enable: ()->
|
23
|
+
@getInputElement().attr('disabled', false)
|
24
|
+
|
25
|
+
getValue: ()->
|
26
|
+
raw = @getInputElement()?.attr('value')
|
27
|
+
|
28
|
+
return raw if _.str.isBlank( raw )
|
29
|
+
|
30
|
+
switch @valueType
|
31
|
+
when "integer" then parseInt(raw)
|
32
|
+
when "string" then "#{ raw }"
|
33
|
+
when "float" then parseFloat(raw)
|
34
|
+
else raw
|
35
|
+
|
36
|
+
setValue: (value)->
|
37
|
+
@getInputElement()?.attr('value', value)
|
38
|
+
|
39
|
+
updateState: (state)->
|
40
|
+
_( @statuses ).each (cls)=>
|
41
|
+
@$el.removeClass(cls)
|
42
|
+
@$el.addClass(state)
|
43
|
+
|
44
|
+
field.privateConfiguration
|
45
|
+
isField: true
|
46
|
+
template: 'fields/text_field'
|
47
|
+
|
48
|
+
field.defines
|
24
49
|
initialize: (@options={})->
|
25
50
|
_.extend @, @options
|
26
51
|
|
@@ -29,6 +54,7 @@ _.def('Luca.core.Field').extends('Luca.View').with
|
|
29
54
|
@input_class ||= ""
|
30
55
|
@input_type ||= ""
|
31
56
|
@helperText ||= ""
|
57
|
+
@label = @name if not @label? or @label.length is 0
|
32
58
|
@label ||= "*#{ @label }" if @required and not @label?.match(/^\*/)
|
33
59
|
@inputStyles ||= ""
|
34
60
|
@input_value ||= @value || ""
|
@@ -53,30 +79,5 @@ _.def('Luca.core.Field').extends('Luca.View').with
|
|
53
79
|
change_handler: (e)->
|
54
80
|
@trigger "on:change", @, e
|
55
81
|
|
56
|
-
disable: ()->
|
57
|
-
@getInputElement().attr('disabled', true)
|
58
|
-
|
59
|
-
enable: ()->
|
60
|
-
@getInputElement().attr('disabled', false)
|
61
|
-
|
62
|
-
getValue: ()->
|
63
|
-
raw = @getInputElement()?.attr('value')
|
64
|
-
|
65
|
-
return raw if _.str.isBlank( raw )
|
66
|
-
|
67
|
-
switch @valueType
|
68
|
-
when "integer" then parseInt(raw)
|
69
|
-
when "string" then "#{ raw }"
|
70
|
-
when "float" then parseFloat(raw)
|
71
|
-
else raw
|
72
|
-
|
73
|
-
setValue: (value)->
|
74
|
-
@getInputElement()?.attr('value', value)
|
75
|
-
|
76
82
|
getInputElement: ()->
|
77
83
|
@input ||= @$('input').eq(0)
|
78
|
-
|
79
|
-
updateState: (state)->
|
80
|
-
_( @statuses ).each (cls)=>
|
81
|
-
@$el.removeClass(cls)
|
82
|
-
@$el.addClass(state)
|
@@ -0,0 +1,37 @@
|
|
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
|
+
|
12
|
+
class MetaDataProxy
|
13
|
+
constructor: (@meta={})->
|
14
|
+
@
|
15
|
+
|
16
|
+
superClass: ()->
|
17
|
+
Luca.util.resolve(@meta["super class name"])
|
18
|
+
|
19
|
+
componentDefinition: ()->
|
20
|
+
Luca.util.resolve(@meta["display name"])
|
21
|
+
|
22
|
+
styleHierarchy: ()->
|
23
|
+
list = _( @classHierarchy() ).map (cls)->
|
24
|
+
Luca.util.toCssClass(cls, 'views', 'components', 'core','fields','containers')
|
25
|
+
|
26
|
+
_( list ).without('backbone-view','luca-view')
|
27
|
+
|
28
|
+
classHierarchy: ()->
|
29
|
+
list = [ @meta["display name"], @meta["super class name"]]
|
30
|
+
|
31
|
+
proxy = @superClass()?.prototype?.componentMetaData?()
|
32
|
+
|
33
|
+
until not proxy
|
34
|
+
list = list.concat( proxy?.classHierarchy() )
|
35
|
+
proxy = proxy.superClass()?.prototype?.componentMetaData?()
|
36
|
+
|
37
|
+
_( 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/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,12 +48,10 @@ view.defines
|
|
48
48
|
|
49
49
|
@setupHooks _( Luca.View::hooks.concat( @hooks ) ).uniq()
|
50
50
|
|
51
|
-
|
52
|
-
for module in @mixins
|
53
|
-
Luca.mixin(module)?.__initializer?.call(@, @, module)
|
51
|
+
Luca.concern.setup.call(@)
|
54
52
|
|
55
53
|
@delegateEvents()
|
56
|
-
|
54
|
+
|
57
55
|
@trigger "after:initialize", @
|
58
56
|
|
59
57
|
#### Hooks or Auto Event Binding
|
@@ -69,18 +67,7 @@ view.defines
|
|
69
67
|
# after:render : afterRender()
|
70
68
|
# after:initialize : afterInitialize()
|
71
69
|
# first:activation : firstActivation()
|
72
|
-
setupHooks:
|
73
|
-
set ||= @hooks
|
74
|
-
|
75
|
-
_(set).each (eventId)=>
|
76
|
-
fn = Luca.util.hook( eventId )
|
77
|
-
|
78
|
-
callback = ()->
|
79
|
-
@[fn]?.apply @, arguments
|
80
|
-
|
81
|
-
callback = _.once(callback) if eventId?.match(/once:/)
|
82
|
-
|
83
|
-
@on eventId, callback, @
|
70
|
+
setupHooks: Luca.util.setupHooks
|
84
71
|
|
85
72
|
registerEvent: (selector, handler)->
|
86
73
|
@events ||= {}
|
@@ -90,13 +77,18 @@ view.defines
|
|
90
77
|
definitionClass: ()->
|
91
78
|
Luca.util.resolve(@displayName, window)?.prototype
|
92
79
|
|
93
|
-
collections: ()->
|
94
|
-
|
95
|
-
views: ()-> Luca.util.selectProperties( Luca.isBackboneView, @ )
|
80
|
+
collections: ()->
|
81
|
+
Luca.util.selectProperties( Luca.isBackboneCollection, @ )
|
96
82
|
|
97
|
-
|
83
|
+
models: ()->
|
84
|
+
Luca.util.selectProperties( Luca.isBackboneModel, @ )
|
85
|
+
|
86
|
+
views: ()->
|
87
|
+
Luca.util.selectProperties( Luca.isBackboneView, @ )
|
88
|
+
|
89
|
+
debug: (args...)->
|
98
90
|
return unless @debugMode or window.LucaDebugMode?
|
99
|
-
console.log [(@name || @cid),
|
91
|
+
console.log [(@name || @cid), args...]
|
100
92
|
|
101
93
|
trigger: ()->
|
102
94
|
if Luca.enableGlobalObserver
|
@@ -163,14 +155,18 @@ bindEventHandlers = (events={})->
|
|
163
155
|
if _.isString(handler)
|
164
156
|
_.bindAll @, handler
|
165
157
|
|
166
|
-
Luca.View.
|
158
|
+
Luca.View.deferrableEvent = "reset"
|
159
|
+
|
160
|
+
Luca.View.extend = (definition={})->
|
167
161
|
definition = Luca.View.renderWrapper( definition )
|
162
|
+
# for backward compatibility
|
163
|
+
definition.concerns ||= definition.concerns if definition.concerns?
|
168
164
|
|
169
|
-
|
170
|
-
for module in definition.mixins
|
171
|
-
Luca.decorate( definition ).with( module )
|
165
|
+
componentClass = Luca.View._originalExtend.call(@, definition)
|
172
166
|
|
173
|
-
|
167
|
+
if definition.concerns? and _.isArray( definition.concerns )
|
168
|
+
for module in definition.concerns
|
169
|
+
Luca.decorate( componentClass ).with( module )
|
174
170
|
|
171
|
+
componentClass
|
175
172
|
|
176
|
-
Luca.View.deferrableEvent = "reset"
|