luca 0.8.599 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/.rvmrc +1 -0
- data/CHANGELOG +51 -2
- data/README.md +10 -247
- data/ROADMAP +6 -2
- data/app.rb +16 -2
- data/assets/javascripts/dependencies/bootstrap.min.js +7 -1
- data/assets/javascripts/dependencies/codemirror-coffeescript.js +347 -0
- data/assets/javascripts/dependencies/codemirror-css.js +124 -0
- data/assets/javascripts/dependencies/codemirror-html.js +410 -0
- data/assets/javascripts/dependencies/codemirror-javascript.js +361 -0
- data/assets/javascripts/dependencies/codemirror-less.js +232 -0
- data/assets/javascripts/dependencies/codemirror-vim.js +500 -0
- data/assets/javascripts/dependencies/codemirror.js +3076 -0
- data/assets/javascripts/dependencies.coffee +0 -1
- data/assets/javascripts/luca-ui-base.coffee +10 -3
- data/assets/javascripts/luca-ui-bootstrap.js +1 -0
- data/assets/javascripts/luca-ui-development-tools.coffee +9 -0
- data/assets/javascripts/luca-ui.coffee +6 -1
- data/assets/javascripts/sandbox/application.coffee +51 -0
- data/assets/javascripts/sandbox/router.coffee +14 -0
- data/assets/javascripts/sandbox/templates/main.luca +33 -0
- data/assets/javascripts/sandbox/templates/sandbox/navigation.luca +1 -0
- data/assets/javascripts/sandbox/templates/sandbox.luca +1 -0
- data/assets/javascripts/sandbox/views/top_navigation.coffee +4 -0
- data/assets/javascripts/sandbox.coffee +2 -2
- data/assets/stylesheets/bootstrap.min.css +395 -297
- data/assets/stylesheets/codemirror-blackboard.css +25 -0
- data/assets/stylesheets/codemirror-monokai.css +33 -0
- data/assets/stylesheets/codemirror.css +126 -0
- data/assets/stylesheets/luca-ui-bootstrap.css +0 -1
- data/assets/stylesheets/luca-ui-development-tools.css +5 -0
- data/assets/stylesheets/sandbox/sandbox.scss +1 -3
- data/assets/stylesheets/themes/amelia-bootstrap.css +826 -0
- data/assets/stylesheets/themes/slate-bootstrap.css +797 -0
- data/assets/stylesheets/themes/superhero-bootstrap.css +830 -0
- data/lib/luca/code_browser.rb +55 -0
- data/lib/luca/rails/version.rb +1 -1
- data/lib/luca/rails.rb +1 -0
- data/spec/components/fields/checkbox_array_spec.coffee +46 -0
- data/spec/components/form_view_spec.coffee +10 -4
- data/spec/containers/card_view_spec.coffee +7 -0
- data/spec/core/collection_spec.coffee +58 -4
- data/spec/core/container_spec.coffee +6 -6
- data/spec/core/view_spec.coffee +93 -7
- data/spec/framework_spec.coffee +15 -12
- data/src/components/application.coffee +126 -18
- data/src/components/base_toolbar.coffee +2 -2
- data/src/components/collection_loader_view.coffee +1 -2
- data/src/components/collection_view.coffee +77 -0
- data/src/components/controller.coffee +1 -4
- data/src/components/fields/button_field.coffee +1 -1
- data/src/components/fields/checkbox_array.coffee +2 -2
- data/src/components/fields/checkbox_field.coffee +3 -1
- data/src/components/fields/file_upload_field.coffee +1 -1
- data/src/components/fields/hidden_field.coffee +1 -1
- data/src/components/fields/select_field.coffee +1 -1
- data/src/components/fields/text_area_field.coffee +1 -1
- data/src/components/fields/text_field.coffee +10 -6
- data/src/components/fields/type_ahead_field.coffee +18 -5
- data/src/components/form_button_toolbar.coffee +1 -2
- data/src/components/form_view.coffee +44 -62
- data/src/components/grid_view.coffee +27 -20
- data/src/components/load_mask.coffee +3 -0
- data/src/components/nav_bar.coffee +26 -0
- data/src/components/record_manager.coffee +1 -3
- data/src/components/router.coffee +1 -1
- data/src/components/template.coffee +3 -15
- data/src/components/toolbar_dialog.coffee +25 -0
- data/src/containers/card_view.coffee +22 -23
- data/src/containers/column_view.coffee +1 -6
- data/src/containers/modal_view.coffee +20 -71
- data/src/containers/panel_toolbar.coffee +156 -0
- data/src/containers/panel_view.coffee +1 -1
- data/src/containers/split_view.coffee +1 -3
- data/src/containers/tab_view.coffee +29 -29
- data/src/containers/viewport.coffee +38 -3
- data/src/core/collection.coffee +80 -48
- data/src/core/container.coffee +153 -72
- data/src/core/core.coffee +181 -0
- data/src/core/field.coffee +4 -2
- data/src/core/model.coffee +1 -1
- data/src/core/observer.coffee +3 -3
- data/src/core/panel.coffee +143 -0
- data/src/core/registry.coffee +104 -0
- data/src/core/util.coffee +82 -0
- data/src/core/view.coffee +158 -85
- data/src/framework.coffee +112 -178
- data/src/index.coffee +0 -255
- data/src/managers/collection_manager.coffee +1 -0
- data/src/samples/definition.coffee +49 -0
- data/src/stylesheets/base.scss +0 -78
- data/src/stylesheets/components/form_view.scss +8 -3
- data/src/stylesheets/components/grid_view.scss +3 -7
- data/src/stylesheets/components/load_mask.scss +14 -0
- data/src/stylesheets/components/toolbar.scss +0 -15
- data/src/stylesheets/containers/container.scss +14 -2
- data/src/stylesheets/containers/panels.scss +23 -0
- data/src/stylesheets/tools/class_browser.scss +32 -0
- data/src/stylesheets/tools/code_editor.scss +24 -0
- data/src/stylesheets/tools/component_tester.scss +8 -0
- data/src/stylesheets/tools/console.scss +26 -0
- data/src/templates/components/collection_loader_view.luca +1 -1
- data/src/templates/components/form_view.luca +2 -13
- data/src/templates/components/grid_view.luca +0 -2
- data/src/templates/components/load_mask.luca +3 -0
- data/src/templates/components/nav_bar.luca +2 -0
- data/src/templates/containers/tab_view.luca +1 -0
- data/src/templates/fields/text_field.luca +4 -1
- data/src/tools/class_browser.coffee +39 -0
- data/src/tools/code_editor.coffee +258 -0
- data/src/tools/code_mirror_field.coffee +57 -0
- data/src/tools/coffee_script_editor.coffee +60 -0
- data/src/tools/collection_inspector.coffee +4 -0
- data/src/tools/component_tester.coffee +472 -0
- data/src/tools/components/class_browser_detail.coffee +10 -0
- data/src/tools/components/class_browser_list.coffee +74 -0
- data/src/tools/console.coffee +147 -0
- data/src/tools/development_console.coffee +147 -0
- data/src/tools/models/components.coffee +63 -0
- data/src/tools/templates/component_tester/help.luca +14 -0
- data/vendor/assets/javascripts/luca-ui-base.js +1389 -611
- data/vendor/assets/javascripts/luca-ui-bootstrap.js +9 -0
- data/vendor/assets/javascripts/luca-ui-development-tools.js +18719 -0
- data/vendor/assets/javascripts/luca-ui-spec.js +2065 -878
- data/vendor/assets/javascripts/luca-ui.js +1759 -852
- data/vendor/assets/javascripts/luca-ui.min.js +3 -3
- data/vendor/assets/stylesheets/luca-ui-bootstrap.css +494 -440
- data/vendor/assets/stylesheets/luca-ui-development-tools.css +224 -0
- data/vendor/assets/stylesheets/luca-ui-spec.css +99 -140
- data/vendor/assets/stylesheets/luca-ui.css +99 -140
- data/views/index.erb +6 -3
- metadata +60 -18
- data/assets/javascripts/dependencies/jquery-console.js +0 -649
- data/assets/javascripts/development-console.coffee +0 -2
- data/assets/javascripts/sandbox/sandbox.coffee +0 -16
- data/assets/javascripts/sandbox/templates/features/collection_helpers.luca +0 -33
- data/assets/javascripts/sandbox/templates/features/form_demo_code.luca +0 -48
- data/assets/javascripts/sandbox/templates/features/grid_demo_code.luca +0 -24
- data/assets/javascripts/sandbox/templates/features/introduction.luca +0 -11
- data/assets/javascripts/sandbox/templates/features/view_helpers.luca +0 -43
- data/assets/javascripts/sandbox/templates/navigation.luca +0 -8
- data/assets/javascripts/sandbox/views/form_demo.coffee +0 -47
- data/assets/javascripts/sandbox/views/grid_demo.coffee +0 -23
- data/assets/javascripts/sandbox/views/pages/collection_events_sample.coffee +0 -1
- data/assets/javascripts/sandbox/views/pages/pages_controller.coffee +0 -38
- data/src/components/collection_inspector.coffee +0 -2
- data/src/components/development_console.coffee +0 -59
- data/src/stylesheets/components/development_console.scss +0 -47
data/src/core/collection.coffee
CHANGED
@@ -1,39 +1,77 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
1
|
+
source = 'Backbone.Collection'
|
2
|
+
source = 'Backbone.QueryCollection' if Backbone.QueryCollection?
|
3
|
+
|
4
|
+
_.def("Luca.Collection").extends( source ).with
|
5
|
+
# cachedMethods refers to a list of methods on the collection
|
6
|
+
# whose value gets cached once it is ran. the collection then
|
7
|
+
# binds to change, add, remove, and reset events and then expires
|
8
|
+
# the cached value once these events are fired.
|
9
|
+
|
10
|
+
# cachedMethods expects an array of strings representing the method name
|
11
|
+
# or objects containing @method and @resetEvents properties. by default
|
12
|
+
# @resetEvents are 'add','remove',reset' and 'change'.
|
13
|
+
cachedMethods: []
|
14
|
+
|
15
|
+
restoreMethodCache: ()->
|
16
|
+
for name, config of @_methodCache
|
17
|
+
if config.original?
|
18
|
+
config.args = undefined
|
19
|
+
@[ name ] = config.original
|
20
|
+
|
21
|
+
clearMethodCache: (method)->
|
22
|
+
@_methodCache[method].value = undefined
|
23
|
+
|
24
|
+
clearAllMethodsCache: ()->
|
25
|
+
for name, config of @_methodCache
|
26
|
+
@clearMethodCache(name)
|
27
|
+
|
28
|
+
setupMethodCaching: ()->
|
29
|
+
collection = @
|
30
|
+
membershipEvents = ["reset","add","remove"]
|
31
|
+
cache = @_methodCache = {}
|
32
|
+
|
33
|
+
_( @cachedMethods ).each (method)->
|
34
|
+
# store a reference to the unwrapped version of the method
|
35
|
+
# and a placeholder for the cached value
|
36
|
+
cache[ method ] =
|
37
|
+
name: method
|
38
|
+
original: collection[method]
|
39
|
+
value: undefined
|
40
|
+
|
41
|
+
# wrap the collection method with a basic memoize operation
|
42
|
+
collection[ method ] = ()->
|
43
|
+
cache[method].value ||= cache[method].original.apply collection, arguments
|
44
|
+
|
45
|
+
# bind to events on the collection, which once triggered, will
|
46
|
+
# invalidate the cached value. causing us to have to restore it
|
47
|
+
for membershipEvent in membershipEvents
|
48
|
+
collection.bind membershipEvent, ()->
|
49
|
+
collection.clearAllMethodsCache()
|
50
|
+
|
51
|
+
dependencies = method.split(':')[1]
|
52
|
+
|
53
|
+
if dependencies
|
54
|
+
for dependency in dependencies.split(",")
|
55
|
+
collection.bind "change:#{dependency}", ()->
|
56
|
+
collection.clearMethodCache(method: method)
|
26
57
|
|
27
58
|
initialize: (models=[], @options)->
|
28
59
|
_.extend @, @options
|
29
60
|
|
61
|
+
@setupMethodCaching()
|
62
|
+
|
30
63
|
@_reset()
|
31
64
|
|
32
|
-
# By specifying a @
|
65
|
+
# By specifying a @cache_key property or method, you can instruct
|
33
66
|
# Luca.Collection instances where to pull an array of model attributes
|
34
67
|
# usually done with the bootstrap functionality provided.
|
68
|
+
|
69
|
+
# DEPRECATION NOTICE
|
35
70
|
if @cached
|
36
|
-
@
|
71
|
+
console.log 'The @cached property of Luca.Collection is being deprecated. Please change to cache_key'
|
72
|
+
|
73
|
+
if @cache_key ||= @cached
|
74
|
+
@bootstrap_cache_key = if _.isFunction( @cache_key ) then @cache_key() else @cache_key
|
37
75
|
|
38
76
|
if @registerAs or @registerWith
|
39
77
|
console.log "This configuration API is deprecated. use @name and @manager properties instead"
|
@@ -42,7 +80,6 @@ Luca.Collection = (Backbone.QueryCollection || Backbone.Collection).extend
|
|
42
80
|
@name ||= @registerAs
|
43
81
|
@manager ||= @registerWith
|
44
82
|
|
45
|
-
|
46
83
|
# if they specify a
|
47
84
|
if @name and not @manager
|
48
85
|
@manager = Luca.CollectionManager.get()
|
@@ -53,7 +90,7 @@ Luca.Collection = (Backbone.QueryCollection || Backbone.Collection).extend
|
|
53
90
|
# to be scoped with some sort of unique id, as say some sort of belongsTo relationship
|
54
91
|
# then you can specify @registerAs as a method()
|
55
92
|
if @manager
|
56
|
-
@name ||= @
|
93
|
+
@name ||= @cache_key()
|
57
94
|
@name = if _.isFunction( @name ) then @name() else @name
|
58
95
|
|
59
96
|
unless @private or @anonymous
|
@@ -81,15 +118,13 @@ Luca.Collection = (Backbone.QueryCollection || Backbone.Collection).extend
|
|
81
118
|
|
82
119
|
@__wrapUrl() unless @useNormalUrl is true
|
83
120
|
|
84
|
-
Backbone.Collection
|
121
|
+
Backbone.Collection::initialize.apply @, [models, @options]
|
85
122
|
|
86
123
|
if models
|
87
124
|
@reset models, silent: true, parse: options?.parse
|
88
125
|
|
89
126
|
@trigger "after:initialize"
|
90
127
|
|
91
|
-
#### Automatic Query String Generation
|
92
|
-
#
|
93
128
|
# Luca.Collections will append a query string to the URL
|
94
129
|
# and will automatically do this for you without you having
|
95
130
|
# to write a special url handler. If you want to use a normal
|
@@ -130,13 +165,16 @@ Luca.Collection = (Backbone.QueryCollection || Backbone.Collection).extend
|
|
130
165
|
@base_params = Luca.Collection.baseParams()
|
131
166
|
@
|
132
167
|
|
133
|
-
#
|
134
|
-
# the
|
135
|
-
|
136
|
-
|
168
|
+
# if filtering a collection should handle via a call to a REST API
|
169
|
+
# and return the filtered results that way, then leave this true
|
170
|
+
remoteFilter: true
|
171
|
+
|
137
172
|
applyFilter: (filter={}, options={})->
|
138
|
-
|
139
|
-
|
173
|
+
if options.remote? is true
|
174
|
+
@applyParams(filter)
|
175
|
+
@fetch _.extend(options,refresh:true)
|
176
|
+
else
|
177
|
+
@reset @query filter
|
140
178
|
|
141
179
|
# You can apply params to a collection, so that any upcoming requests
|
142
180
|
# made to the REST API are made with the key values specified
|
@@ -144,8 +182,6 @@ Luca.Collection = (Backbone.QueryCollection || Backbone.Collection).extend
|
|
144
182
|
@base_params ||= _( Luca.Collection.baseParams() ).clone()
|
145
183
|
_.extend @base_params, params
|
146
184
|
|
147
|
-
# Collection Manager Registry
|
148
|
-
#
|
149
185
|
# If this collection is to be registered with some global collection
|
150
186
|
# tracker such as new Luca.CollectionManager() then we will register
|
151
187
|
# ourselves automatically
|
@@ -174,7 +210,7 @@ Luca.Collection = (Backbone.QueryCollection || Backbone.Collection).extend
|
|
174
210
|
|
175
211
|
# A Luca.Collection will load models from the in memory model store
|
176
212
|
# returned from Luca.Collection.cache, where the key returned from
|
177
|
-
# the @
|
213
|
+
# the @cache_keyattribute or method matches the key of the model cache
|
178
214
|
loadFromBootstrap: ()->
|
179
215
|
return unless @bootstrap_cache_key
|
180
216
|
@reset @cached_models()
|
@@ -186,7 +222,7 @@ Luca.Collection = (Backbone.QueryCollection || Backbone.Collection).extend
|
|
186
222
|
|
187
223
|
# cached_models is a reference to the Luca.Collection.cache object
|
188
224
|
# key'd on whatever this collection's bootstrap_cache_key is set to be
|
189
|
-
# via the @
|
225
|
+
# via the @cache_key() interface
|
190
226
|
cached_models: ()->
|
191
227
|
Luca.Collection.cache( @bootstrap_cache_key )
|
192
228
|
|
@@ -286,8 +322,6 @@ _.extend Luca.Collection.prototype,
|
|
286
322
|
|
287
323
|
Backbone.View.prototype.trigger.apply @, arguments
|
288
324
|
|
289
|
-
#### Base Parameters
|
290
|
-
#
|
291
325
|
# Always include these parameters in every request to your REST API.
|
292
326
|
#
|
293
327
|
# either specify a function which returns a hash, or just a normal hash
|
@@ -300,14 +334,12 @@ Luca.Collection.baseParams = (obj)->
|
|
300
334
|
if _.isObject( Luca.Collection._baseParams )
|
301
335
|
Luca.Collection._baseParams
|
302
336
|
|
303
|
-
#### Bootstrapped Models ( stuff loaded on page load )
|
304
|
-
#
|
305
337
|
# In order to make our Backbone Apps super fast it is a good practice
|
306
338
|
# to pre-populate your collections by what is referred to as bootstrapping
|
307
339
|
#
|
308
340
|
# Luca.Collections make it easier for you to do this cleanly and automatically
|
309
341
|
#
|
310
|
-
# by specifying a @
|
342
|
+
# by specifying a @cache_keyproperty or method in your collection definition
|
311
343
|
# Luca.Collections will automatically look in this space to find models
|
312
344
|
# and avoid a roundtrip to your API unless explicitly told to.
|
313
345
|
Luca.Collection._bootstrapped_models = {}
|
@@ -321,4 +353,4 @@ Luca.Collection.bootstrap = (obj)->
|
|
321
353
|
# roundtrips to the API
|
322
354
|
Luca.Collection.cache = (key, models)->
|
323
355
|
return Luca.Collection._bootstrapped_models[ key ] = models if models
|
324
|
-
Luca.Collection._bootstrapped_models[ key ] || []
|
356
|
+
Luca.Collection._bootstrapped_models[ key ] || []
|
data/src/core/container.coffee
CHANGED
@@ -1,14 +1,62 @@
|
|
1
|
-
|
1
|
+
# The Component Container
|
2
2
|
#
|
3
3
|
# The Component Container is a nestable component
|
4
|
-
# which
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
|
4
|
+
# which are responsible for handling communication between multiple
|
5
|
+
# nested views.
|
6
|
+
#
|
7
|
+
# One: Layout
|
8
|
+
#
|
9
|
+
# a container is responsible for laying out the nested views
|
10
|
+
# and rendering them in a special DOM element
|
11
|
+
doLayout = ()->
|
12
|
+
@trigger "before:layout", @
|
13
|
+
@prepareLayout()
|
14
|
+
@trigger "after:layout", @
|
15
|
+
|
16
|
+
# and displaying those elements in a way that is
|
17
|
+
# optimal for the desired user experience of that view
|
18
|
+
# ( i.e seeing only one of them at a time, seeing them side by side )
|
19
|
+
applyDOMConfig = (panel, panelIndex)->
|
20
|
+
style_declarations = []
|
21
|
+
|
22
|
+
style_declarations.push "height: #{ (if _.isNumber(panel.height) then panel.height + 'px' else panel.height ) }" if panel.height?
|
23
|
+
style_declarations.push "width: #{ (if _.isNumber(panel.width) then panel.width + 'px' else panel.width ) }" if panel.width?
|
24
|
+
style_declarations.push "float: #{ panel.float }" if panel.float
|
25
|
+
|
26
|
+
config =
|
27
|
+
class: panel?.classes || @componentClass
|
28
|
+
id: "#{ @cid }-#{ panelIndex }"
|
29
|
+
style: style_declarations.join(';')
|
30
|
+
"data-luca-owner" : @name || @cid
|
31
|
+
|
32
|
+
if @customizeContainerEl?
|
33
|
+
config = @customizeContainerEl( config, panel, panelIndex )
|
34
|
+
|
35
|
+
config
|
36
|
+
|
37
|
+
# Two: Component Creation
|
38
|
+
#
|
39
|
+
# A container is responsible for creating and storing references to the nested
|
40
|
+
# views that are required for its functioning.
|
41
|
+
doComponents = ()->
|
42
|
+
|
43
|
+
@trigger "before:components", @, @components
|
44
|
+
@prepareComponents()
|
45
|
+
@createComponents()
|
46
|
+
@trigger "before:render:components", @, @components
|
47
|
+
@renderComponents()
|
48
|
+
@trigger "after:components", @, @components
|
49
|
+
|
50
|
+
|
51
|
+
# Containers are central to Luca. They are what make it easy to structure
|
52
|
+
# your application in a logical way and to specify much of the behavior of
|
53
|
+
# complex / composite views at define time using JSON syntax combined with
|
54
|
+
# the meta data contained in the Luca component registry.
|
55
|
+
_.def('Luca.core.Container').extends('Luca.components.Panel').with
|
9
56
|
|
10
57
|
className: 'luca-ui-container'
|
11
58
|
|
59
|
+
componentTag: 'div'
|
12
60
|
componentClass: 'luca-ui-panel'
|
13
61
|
|
14
62
|
isContainer: true
|
@@ -29,11 +77,18 @@ _.component('Luca.core.Container').extends('Luca.View').with
|
|
29
77
|
initialize: (@options={})->
|
30
78
|
_.extend @, @options
|
31
79
|
|
32
|
-
@setupHooks
|
80
|
+
@setupHooks [
|
81
|
+
"before:components"
|
82
|
+
"before:render:components"
|
83
|
+
"before:layout"
|
84
|
+
"after:components"
|
85
|
+
"after:layout"
|
86
|
+
"first:activation"
|
87
|
+
]
|
33
88
|
|
34
89
|
Luca.View::initialize.apply @, arguments
|
35
90
|
|
36
|
-
|
91
|
+
# Rendering Pipeline
|
37
92
|
#
|
38
93
|
# A container has nested components. these components
|
39
94
|
# are automatically rendered inside their own DOM element
|
@@ -80,62 +135,52 @@ _.component('Luca.core.Container').extends('Luca.View').with
|
|
80
135
|
# firstActivation()
|
81
136
|
#
|
82
137
|
beforeRender: ()->
|
83
|
-
@
|
84
|
-
@
|
85
|
-
|
86
|
-
|
87
|
-
doLayout: ()->
|
88
|
-
@debug "container do layout"
|
89
|
-
@trigger "before:layout", @
|
90
|
-
@prepareLayout()
|
91
|
-
@trigger "after:layout", @
|
92
|
-
|
93
|
-
doComponents: ()->
|
94
|
-
@debug "container do components"
|
95
|
-
|
96
|
-
@trigger "before:components", @, @components
|
97
|
-
@prepareComponents()
|
98
|
-
@createComponents()
|
99
|
-
@trigger "before:render:components", @, @components
|
100
|
-
@renderComponents()
|
101
|
-
@trigger "after:components", @, @components
|
102
|
-
|
103
|
-
applyPanelConfig: (panel, panelIndex)->
|
104
|
-
style_declarations = []
|
105
|
-
|
106
|
-
style_declarations.push "height: #{ (if _.isNumber(panel.height) then panel.height + 'px' else panel.height ) }" if panel.height
|
107
|
-
style_declarations.push "width: #{ (if _.isNumber(panel.width) then panel.width + 'px' else panel.width ) }" if panel.width
|
108
|
-
style_declarations.push "float: #{ panel.float }" if panel.float
|
109
|
-
|
110
|
-
config =
|
111
|
-
classes: panel?.classes || @componentClass
|
112
|
-
id: "#{ @cid }-#{ panelIndex }"
|
113
|
-
style: style_declarations.join(';')
|
114
|
-
|
115
|
-
# prepare layout is where you would perform the DOM element
|
116
|
-
# creation / manipulation for how your container lays out
|
117
|
-
# its components. Minimally you will want to set the
|
118
|
-
# container property on each component.
|
119
|
-
prepareLayout: ()->
|
120
|
-
@debug "container prepare layout"
|
121
|
-
@componentContainers = _( @components ).map (component, index) =>
|
122
|
-
@applyPanelConfig.apply @, [ component, index ]
|
138
|
+
doLayout.call(@)
|
139
|
+
doComponents.call(@)
|
140
|
+
Luca.components.Panel::beforeRender?.apply(@, arguments)
|
123
141
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
142
|
+
# Components which inherit from Luca.core.Container can implement
|
143
|
+
# their own versions of this method, if they need to apply any sort
|
144
|
+
# of additional styling / configuration for the DOM elements that
|
145
|
+
# are created to wrap each container.
|
146
|
+
customizeContainerEl: (containerEl, panel, panelIndex)->
|
147
|
+
containerEl
|
128
148
|
|
129
|
-
|
130
|
-
|
149
|
+
prepareLayout: ()->
|
150
|
+
container = @
|
151
|
+
@componentContainers = _( @components ).map (component, index)->
|
152
|
+
applyDOMConfig.call(container, component, index)
|
153
|
+
|
154
|
+
# prepare components is where each component gets assigned
|
155
|
+
# a container to be rendered into. if @appendContainers is
|
156
|
+
# set to true, then the view will automatically $append()
|
157
|
+
# elements created via Backbone.View::make() to the body element of the view
|
131
158
|
prepareComponents: ()->
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
159
|
+
# accept components as an array of strings representing
|
160
|
+
# the luca component type
|
161
|
+
for component in @components when _.isString(component)
|
162
|
+
component = (type: component)
|
163
|
+
|
164
|
+
_( @components ).each (component, index)=>
|
165
|
+
container = @componentContainers?[index]
|
166
|
+
|
167
|
+
# support a variety of the bad naming conventions
|
168
|
+
container.class = container.class || container.className || container.classes
|
169
|
+
|
170
|
+
if @appendContainers
|
171
|
+
panel = @make(@componentTag, container, '')
|
172
|
+
@$append( panel )
|
136
173
|
|
137
|
-
|
174
|
+
unless component.container?
|
175
|
+
component.container = "##{ container.id }" if @appendContainers
|
176
|
+
component.container ||= @$bodyEl()
|
138
177
|
|
178
|
+
# create components is responsible for turning the JSON syntax of the
|
179
|
+
# container's definition into live objects against a given Luca Component
|
180
|
+
# type.
|
181
|
+
#
|
182
|
+
# In addition to this, a container builds an index of the components
|
183
|
+
# which belong to it, so that they can easily be looked up by name
|
139
184
|
createComponents: ()->
|
140
185
|
return if @componentsCreated is true
|
141
186
|
|
@@ -144,17 +189,28 @@ _.component('Luca.core.Container').extends('Luca.View').with
|
|
144
189
|
cid_index: {}
|
145
190
|
|
146
191
|
@components = _( @components ).map (object, index)=>
|
192
|
+
|
147
193
|
# you can include normal backbone views as components
|
148
194
|
# you will want to make sure your render method handles
|
149
|
-
# adding the views @$el to the appropriate @container
|
150
|
-
|
195
|
+
# adding the views @$el to the appropriate @container.
|
196
|
+
|
197
|
+
# you can also just pass a string representing the component_type
|
198
|
+
component = if Luca.isBackboneView( object )
|
151
199
|
object
|
152
200
|
else
|
153
|
-
object.
|
201
|
+
object.type ||= object.ctype
|
202
|
+
|
203
|
+
if !object.type?
|
204
|
+
if object.components?
|
205
|
+
object.type = object.ctype = 'container'
|
206
|
+
else
|
207
|
+
object.type = object.ctype = Luca.defaultComponentType
|
208
|
+
|
154
209
|
Luca.util.lazyComponent( object )
|
155
210
|
|
156
211
|
# if we're using base backbone views, then they don't extend themselves
|
157
|
-
# with their passed options, so this is a workaround
|
212
|
+
# with their passed options, so this is a workaround to get them to
|
213
|
+
# pick up the container config property
|
158
214
|
if !component.container and component.options.container
|
159
215
|
component.container = component.options.container
|
160
216
|
|
@@ -167,6 +223,9 @@ _.component('Luca.core.Container').extends('Luca.View').with
|
|
167
223
|
component
|
168
224
|
|
169
225
|
@componentsCreated = true
|
226
|
+
|
227
|
+
@registerComponentEvents() unless _.isEmpty(@componentEvents)
|
228
|
+
|
170
229
|
map
|
171
230
|
|
172
231
|
# Trigger the Rendering Pipeline process on all of the nested
|
@@ -181,8 +240,11 @@ _.component('Luca.core.Container').extends('Luca.View').with
|
|
181
240
|
component.render()
|
182
241
|
catch e
|
183
242
|
console.log "Error Rendering Component #{ component.name || component.cid }", component
|
184
|
-
|
185
|
-
|
243
|
+
|
244
|
+
if _.isObject(e)
|
245
|
+
console.log e.message
|
246
|
+
console.log e.stack
|
247
|
+
|
186
248
|
throw e unless Luca.silenceRenderErrors? is true
|
187
249
|
|
188
250
|
#### Container Activation
|
@@ -195,13 +257,12 @@ _.component('Luca.core.Container').extends('Luca.View').with
|
|
195
257
|
# will trigger first:activation on the components as they become
|
196
258
|
# displayed.
|
197
259
|
firstActivation: ()->
|
198
|
-
|
199
|
-
|
200
|
-
|
260
|
+
activator = @
|
261
|
+
@each (component, index)->
|
201
262
|
# apply the first:activation trigger on the component, in the context of the component
|
202
263
|
# passing as arguments the component itself, and the component doing the activation
|
203
264
|
unless component?.previously_activated is true
|
204
|
-
component?.trigger?.
|
265
|
+
component?.trigger?.call component, "first:activation", component, activator
|
205
266
|
component.previously_activated = true
|
206
267
|
|
207
268
|
#### Component Finder Methods
|
@@ -219,6 +280,22 @@ _.component('Luca.core.Container').extends('Luca.View').with
|
|
219
280
|
|
220
281
|
_.flatten( components )
|
221
282
|
|
283
|
+
# event binding sugar for nested components
|
284
|
+
#
|
285
|
+
# you can define events like:
|
286
|
+
|
287
|
+
# _.def("MyContainer").extends("Luca.View").with
|
288
|
+
# componentEvents:
|
289
|
+
# "component_name before:load" : "mySpecialHandler"
|
290
|
+
#
|
291
|
+
componentEvents: {}
|
292
|
+
|
293
|
+
registerComponentEvents: ()->
|
294
|
+
for listener, handler of @componentEvents
|
295
|
+
[componentName,trigger] = listener.split(' ')
|
296
|
+
component = @findComponentByName(componentName)
|
297
|
+
component?.bind trigger, @[handler]
|
298
|
+
|
222
299
|
findComponentByName: (name, deep=false)->
|
223
300
|
@findComponent(name, "name_index", deep)
|
224
301
|
|
@@ -238,12 +315,15 @@ _.component('Luca.core.Container').extends('Luca.View').with
|
|
238
315
|
sub_container = _( @components ).detect (component)-> component?.findComponent?(needle, haystack, true)
|
239
316
|
sub_container?.findComponent?(needle, haystack, true)
|
240
317
|
|
318
|
+
each: (fn)->
|
319
|
+
@eachComponent(fn, false)
|
320
|
+
|
241
321
|
# run a function for each component in this container
|
242
322
|
# and any nested containers in those components, recursively
|
243
323
|
# pass false as the second argument to skip the deep recursion
|
244
324
|
eachComponent: (fn, deep=true)->
|
245
|
-
_( @components ).each (component)=>
|
246
|
-
fn.
|
325
|
+
_( @components ).each (component, index)=>
|
326
|
+
fn.call component, component, index
|
247
327
|
component?.eachComponent?.apply component, [fn,deep] if deep
|
248
328
|
|
249
329
|
indexOf: (name)->
|
@@ -254,7 +334,8 @@ _.component('Luca.core.Container').extends('Luca.View').with
|
|
254
334
|
return @ unless @activeItem
|
255
335
|
return @components[ @activeItem ]
|
256
336
|
|
257
|
-
componentElements: ()->
|
337
|
+
componentElements: ()->
|
338
|
+
$(">.#{ @componentClass }", @el)
|
258
339
|
|
259
340
|
getComponent: (needle)->
|
260
341
|
@components[ needle ]
|