luca 0.6.6
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/.gitignore +5 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +77 -0
- data/Guardfile +22 -0
- data/README.md +291 -0
- data/Rakefile +28 -0
- data/app.rb +46 -0
- data/assets/images/glyphicons-halflings-white.png +0 -0
- data/assets/images/glyphicons-halflings.png +0 -0
- data/assets/javascripts/dependencies/backbone-min.js +37 -0
- data/assets/javascripts/dependencies/backbone-query.min.js +1 -0
- data/assets/javascripts/dependencies/bootstrap.min.js +1 -0
- data/assets/javascripts/dependencies/jasmine-html.js +190 -0
- data/assets/javascripts/dependencies/jasmine.js +2476 -0
- data/assets/javascripts/dependencies/jquery.js +4 -0
- data/assets/javascripts/dependencies/modal.js +698 -0
- data/assets/javascripts/dependencies/modernizr.min.js +30 -0
- data/assets/javascripts/dependencies/prettify.js +28 -0
- data/assets/javascripts/dependencies/sinon.js +3469 -0
- data/assets/javascripts/dependencies/spin-min.js +2 -0
- data/assets/javascripts/dependencies/underscore-min.js +31 -0
- data/assets/javascripts/dependencies/underscore-string.min.js +14 -0
- data/assets/javascripts/dependencies.coffee +7 -0
- data/assets/javascripts/luca-ui-base.coffee +12 -0
- data/assets/javascripts/luca-ui-spec.coffee +2 -0
- data/assets/javascripts/luca-ui.coffee +3 -0
- data/assets/javascripts/sandbox/collections/sample.coffee +0 -0
- data/assets/javascripts/sandbox/config.coffee +7 -0
- data/assets/javascripts/sandbox/sandbox.coffee +16 -0
- data/assets/javascripts/sandbox/templates/features/collection_helpers.luca +33 -0
- data/assets/javascripts/sandbox/templates/features/form_demo_code.luca +48 -0
- data/assets/javascripts/sandbox/templates/features/grid_demo_code.luca +24 -0
- data/assets/javascripts/sandbox/templates/features/introduction.luca +11 -0
- data/assets/javascripts/sandbox/templates/features/view_helpers.luca +43 -0
- data/assets/javascripts/sandbox/templates/navigation.luca +8 -0
- data/assets/javascripts/sandbox/views/form_demo.coffee +47 -0
- data/assets/javascripts/sandbox/views/grid_demo.coffee +23 -0
- data/assets/javascripts/sandbox/views/pages/collection_events_sample.coffee +1 -0
- data/assets/javascripts/sandbox/views/pages/pages_controller.coffee +28 -0
- data/assets/javascripts/sandbox.coffee +4 -0
- data/assets/javascripts/spec-dependencies.coffee +4 -0
- data/assets/stylesheets/bootstrap-responsive.min.css +3 -0
- data/assets/stylesheets/bootstrap.min.css +610 -0
- data/assets/stylesheets/jasmine.css +166 -0
- data/assets/stylesheets/luca-ui-bootstrap.css +5 -0
- data/assets/stylesheets/luca-ui-spec.css +3 -0
- data/assets/stylesheets/luca-ui.css +3 -0
- data/assets/stylesheets/prettify.css +40 -0
- data/assets/stylesheets/sandbox/sandbox.scss +4 -0
- data/assets/stylesheets/sandbox.css +3 -0
- data/config.ru +11 -0
- data/lib/luca/command_line.rb +69 -0
- data/lib/luca/rails/engine.rb +12 -0
- data/lib/luca/rails/version.rb +6 -0
- data/lib/luca/rails.rb +9 -0
- data/lib/luca/template.rb +51 -0
- data/lib/luca/test_harness.rb +106 -0
- data/lib/luca.rb +1 -0
- data/lib/sprockets/luca_template.rb +49 -0
- data/lib/templates/spec_manifest_javascripts.erb +7 -0
- data/lib/templates/spec_manifest_stylesheets.erb +11 -0
- data/luca.gemspec +26 -0
- data/public/jasmine/index.html +26 -0
- data/public/sandbox/api.js +1 -0
- data/spec/components/application_spec.coffee +0 -0
- data/spec/components/collection_loader_view_spec.coffee +0 -0
- data/spec/components/controller_spec.coffee +0 -0
- data/spec/components/form_view_spec.coffee +13 -0
- data/spec/components/grid_view_spec.coffee +0 -0
- data/spec/components/record_manager_spec.coffee +0 -0
- data/spec/components/template_spec.coffee +0 -0
- data/spec/containers/card_view_spec.coffee +1 -0
- data/spec/containers/column_view_spec.coffee +0 -0
- data/spec/containers/modal_view_spec.coffee +0 -0
- data/spec/containers/panel_view_spec.coffee +0 -0
- data/spec/containers/split_view_spec.coffee +0 -0
- data/spec/containers/tab_view_spec.coffee +0 -0
- data/spec/containers/viewport_spec.coffee +0 -0
- data/spec/core/collection_spec.coffee +215 -0
- data/spec/core/container_spec.coffee +0 -0
- data/spec/core/field_spec.coffee +0 -0
- data/spec/core/observer_spec.coffee +0 -0
- data/spec/core/view_spec.coffee +87 -0
- data/spec/framework_spec.coffee +48 -0
- data/spec/helper.coffee +120 -0
- data/spec/managers/collection_manager_spec.coffee +95 -0
- data/spec/managers/socket_manager_spec.coffee +0 -0
- data/src/components/application.coffee +83 -0
- data/src/components/base_toolbar.coffee +16 -0
- data/src/components/collection_loader_view.coffee +37 -0
- data/src/components/controller.coffee +41 -0
- data/src/components/fields/button_field.coffee +40 -0
- data/src/components/fields/checkbox_field.coffee +41 -0
- data/src/components/fields/file_upload_field.coffee +15 -0
- data/src/components/fields/hidden_field.coffee +18 -0
- data/src/components/fields/select_field.coffee +100 -0
- data/src/components/fields/text_area_field.coffee +43 -0
- data/src/components/fields/text_field.coffee +42 -0
- data/src/components/fields/type_ahead_field.coffee +10 -0
- data/src/components/form_button_toolbar.coffee +26 -0
- data/src/components/form_view.coffee +205 -0
- data/src/components/grid_view.coffee +208 -0
- data/src/components/record_manager.coffee +215 -0
- data/src/components/router.coffee +34 -0
- data/src/components/template.coffee +19 -0
- data/src/containers/card_view.coffee +89 -0
- data/src/containers/column_view.coffee +48 -0
- data/src/containers/modal_view.coffee +85 -0
- data/src/containers/panel_view.coffee +24 -0
- data/src/containers/split_view.coffee +12 -0
- data/src/containers/tab_view.coffee +77 -0
- data/src/containers/viewport.coffee +16 -0
- data/src/core/collection.coffee +319 -0
- data/src/core/container.coffee +256 -0
- data/src/core/field.coffee +68 -0
- data/src/core/observer.coffee +17 -0
- data/src/core/view.coffee +190 -0
- data/src/framework.coffee +110 -0
- data/src/index.coffee +255 -0
- data/src/managers/collection_manager.coffee +168 -0
- data/src/managers/socket_manager.coffee +54 -0
- data/src/modules/deferrable.coffee +18 -0
- data/src/modules/local_storage.coffee +50 -0
- data/src/stylesheets/base.scss +78 -0
- data/src/stylesheets/components/form_view.scss +54 -0
- data/src/stylesheets/components/grid_view.scss +111 -0
- data/src/stylesheets/components/toolbar.scss +15 -0
- data/src/stylesheets/containers/container.scss +7 -0
- data/src/stylesheets/containers/modal_view.scss +0 -0
- data/src/stylesheets/containers/tab_view.scss +33 -0
- data/src/stylesheets/normalize.scss +430 -0
- data/src/templates/components/bootstrap_form_controls.luca +7 -0
- data/src/templates/components/collection_loader_view.luca +5 -0
- data/src/templates/components/form_view.luca +15 -0
- data/src/templates/components/grid_view.luca +9 -0
- data/src/templates/components/grid_view_empty_text.luca +3 -0
- data/src/templates/containers/basic.luca +1 -0
- data/src/templates/containers/tab_selector_container.luca +8 -0
- data/src/templates/containers/tab_view.luca +1 -0
- data/src/templates/containers/toolbar_wrapper.luca +1 -0
- data/src/templates/fields/button_field.luca +2 -0
- data/src/templates/fields/button_field_link.luca +5 -0
- data/src/templates/fields/checkbox_field.luca +9 -0
- data/src/templates/fields/file_upload_field.luca +8 -0
- data/src/templates/fields/hidden_field.luca +1 -0
- data/src/templates/fields/select_field.luca +7 -0
- data/src/templates/fields/text_area_field.luca +8 -0
- data/src/templates/fields/text_field.luca +13 -0
- data/src/templates/sample/contents.luca +1 -0
- data/src/templates/sample/welcome.luca +1 -0
- data/vendor/assets/images/glyphicons-halflings-white.png +0 -0
- data/vendor/assets/images/glyphicons-halflings.png +0 -0
- data/vendor/assets/javascripts/luca-spec-dependencies.js +6135 -0
- data/vendor/assets/javascripts/luca-ui-base.js +1527 -0
- data/vendor/assets/javascripts/luca-ui-spec.js +3654 -0
- data/vendor/assets/javascripts/luca-ui.js +2763 -0
- data/vendor/assets/luca-ui/base.css +85 -0
- data/vendor/assets/luca-ui/components/application.js +91 -0
- data/vendor/assets/luca-ui/components/base_toolbar.js +23 -0
- data/vendor/assets/luca-ui/components/controller.js +38 -0
- data/vendor/assets/luca-ui/components/fields/button_field.js +45 -0
- data/vendor/assets/luca-ui/components/fields/checkbox_field.js +43 -0
- data/vendor/assets/luca-ui/components/fields/file_upload_field.js +20 -0
- data/vendor/assets/luca-ui/components/fields/hidden_field.js +20 -0
- data/vendor/assets/luca-ui/components/fields/select_field.js +97 -0
- data/vendor/assets/luca-ui/components/fields/text_area_field.js +48 -0
- data/vendor/assets/luca-ui/components/fields/text_field.js +46 -0
- data/vendor/assets/luca-ui/components/fields/type_ahead_field.js +13 -0
- data/vendor/assets/luca-ui/components/form_button_toolbar.js +32 -0
- data/vendor/assets/luca-ui/components/form_view.css +32 -0
- data/vendor/assets/luca-ui/components/form_view.js +207 -0
- data/vendor/assets/luca-ui/components/grid_view.css +76 -0
- data/vendor/assets/luca-ui/components/grid_view.js +202 -0
- data/vendor/assets/luca-ui/components/record_manager.js +207 -0
- data/vendor/assets/luca-ui/components/router.js +36 -0
- data/vendor/assets/luca-ui/components/template.js +26 -0
- data/vendor/assets/luca-ui/components/toolbar.css +11 -0
- data/vendor/assets/luca-ui/containers/card_view.js +98 -0
- data/vendor/assets/luca-ui/containers/column_view.js +52 -0
- data/vendor/assets/luca-ui/containers/container.css +3 -0
- data/vendor/assets/luca-ui/containers/modal_view.css +0 -0
- data/vendor/assets/luca-ui/containers/modal_view.js +87 -0
- data/vendor/assets/luca-ui/containers/panel_view.js +34 -0
- data/vendor/assets/luca-ui/containers/split_view.js +13 -0
- data/vendor/assets/luca-ui/containers/tab_view.css +16 -0
- data/vendor/assets/luca-ui/containers/tab_view.js +80 -0
- data/vendor/assets/luca-ui/containers/viewport.js +18 -0
- data/vendor/assets/luca-ui/core/collection.js +221 -0
- data/vendor/assets/luca-ui/core/container.js +205 -0
- data/vendor/assets/luca-ui/core/field.js +59 -0
- data/vendor/assets/luca-ui/core/observer.js +42 -0
- data/vendor/assets/luca-ui/core/view.js +127 -0
- data/vendor/assets/luca-ui/framework.js +110 -0
- data/vendor/assets/luca-ui/index.js +5 -0
- data/vendor/assets/luca-ui/managers/collection_manager.js +98 -0
- data/vendor/assets/luca-ui/managers/socket_manager.js +52 -0
- data/vendor/assets/luca-ui/modules/deferrable.js +21 -0
- data/vendor/assets/luca-ui/modules/local_storage.js +81 -0
- data/vendor/assets/luca-ui/normalize.css +359 -0
- data/vendor/assets/luca-ui/stylesheets/base.css +85 -0
- data/vendor/assets/luca-ui/stylesheets/components/form_view.css +32 -0
- data/vendor/assets/luca-ui/stylesheets/components/grid_view.css +76 -0
- data/vendor/assets/luca-ui/stylesheets/components/toolbar.css +11 -0
- data/vendor/assets/luca-ui/stylesheets/containers/container.css +3 -0
- data/vendor/assets/luca-ui/stylesheets/containers/modal_view.css +0 -0
- data/vendor/assets/luca-ui/stylesheets/containers/tab_view.css +16 -0
- data/vendor/assets/luca-ui/stylesheets/normalize.css +359 -0
- data/vendor/assets/luca-ui/templates/components/bootstrap_form_controls.js +4 -0
- data/vendor/assets/luca-ui/templates/components/form_view.js +4 -0
- data/vendor/assets/luca-ui/templates/components/grid_view.js +4 -0
- data/vendor/assets/luca-ui/templates/components/grid_view_empty_text.js +4 -0
- data/vendor/assets/luca-ui/templates/containers/basic.js +4 -0
- data/vendor/assets/luca-ui/templates/containers/tab_selector_container.js +4 -0
- data/vendor/assets/luca-ui/templates/containers/tab_view.js +4 -0
- data/vendor/assets/luca-ui/templates/containers/toolbar_wrapper.js +4 -0
- data/vendor/assets/luca-ui/templates/fields/button_field.js +4 -0
- data/vendor/assets/luca-ui/templates/fields/button_field_link.js +4 -0
- data/vendor/assets/luca-ui/templates/fields/checkbox_field.js +4 -0
- data/vendor/assets/luca-ui/templates/fields/file_upload_field.js +4 -0
- data/vendor/assets/luca-ui/templates/fields/hidden_field.js +4 -0
- data/vendor/assets/luca-ui/templates/fields/select_field.js +4 -0
- data/vendor/assets/luca-ui/templates/fields/text_area_field.js +4 -0
- data/vendor/assets/luca-ui/templates/fields/text_field.js +4 -0
- data/vendor/assets/luca-ui/templates/sample/contents.js +4 -0
- data/vendor/assets/luca-ui/templates/sample/welcome.js +4 -0
- data/vendor/assets/stylesheets/luca-spec-dependencies.css +166 -0
- data/vendor/assets/stylesheets/luca-ui-bootstrap.css +1201 -0
- data/vendor/assets/stylesheets/luca-ui-spec.css +586 -0
- data/vendor/assets/stylesheets/luca-ui.css +586 -0
- data/views/index.erb +20 -0
- data/views/jasmine.erb +22 -0
- data/views/spec_harness.erb +29 -0
- metadata +361 -0
data/src/index.coffee
ADDED
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
# #### Luca.js
|
|
2
|
+
# #
|
|
3
|
+
# # Luca is a Backbone Helper and Container View Library
|
|
4
|
+
# # which is packed with about a year worth of Backbone.js
|
|
5
|
+
# # experience and best practices accumulated while I developed
|
|
6
|
+
# # several large Backbone applications. By using it, you are
|
|
7
|
+
# # to a degree accepting my way of doing things. But, I can
|
|
8
|
+
# # assure you that by accepting my way of doing things you can
|
|
9
|
+
# # focus a lot more on developing your UI and features and less
|
|
10
|
+
# # on the boilerplate code required to get things to work properly.
|
|
11
|
+
# #
|
|
12
|
+
# # Luca components and stock Backbone components are completely
|
|
13
|
+
# # compatible and you can ( and should ) use both in your application
|
|
14
|
+
# # wherever it makes the most sense to do so
|
|
15
|
+
|
|
16
|
+
# #### ExtJS Component Style
|
|
17
|
+
|
|
18
|
+
# # Luca is inspired by the ExtJS style of laying out applications
|
|
19
|
+
# # as composite views with components nested within components, and
|
|
20
|
+
# # where the outer views or components handle communication between
|
|
21
|
+
# # their children. By properly abstracting your views it becomes
|
|
22
|
+
# # possible to build large applications simply with a bunch of JSON
|
|
23
|
+
# # configuration parameters
|
|
24
|
+
|
|
25
|
+
# MyApplication = Luca.containers.Viewport.extend
|
|
26
|
+
# components:[
|
|
27
|
+
# ctype: 'column_view'
|
|
28
|
+
# layout: '50/50'
|
|
29
|
+
# components: [
|
|
30
|
+
# ctype: 'card_view'
|
|
31
|
+
# name: 'view1'
|
|
32
|
+
# components:[
|
|
33
|
+
# ctype: 'custom_view'
|
|
34
|
+
# name: 'custom_view_1'
|
|
35
|
+
# ,
|
|
36
|
+
# ctype: 'custom_view'
|
|
37
|
+
# name: 'custom_view_2'
|
|
38
|
+
# ]
|
|
39
|
+
# ,
|
|
40
|
+
# ctype : 'custom_view'
|
|
41
|
+
# name: 'custom_view_3'
|
|
42
|
+
# ]
|
|
43
|
+
# ]
|
|
44
|
+
|
|
45
|
+
# #### View Registry
|
|
46
|
+
# #
|
|
47
|
+
# # if You define your views in namespaces, like you should be
|
|
48
|
+
# App.views.CustomView = Luca.View.extend()
|
|
49
|
+
# App.views.OtherView = Luca.View.extend()
|
|
50
|
+
|
|
51
|
+
# # Then you can call Luca.registry.addNamespace 'App.views'
|
|
52
|
+
# # and then have views like CustomView be accessible by
|
|
53
|
+
# # a @ctype property with the value 'custom_view'
|
|
54
|
+
# # in the various container views provided by luca. This style of
|
|
55
|
+
# # lazy instantiation adopted from ExtJS makes it possible to define
|
|
56
|
+
# # a view and its relationships but not necessarily create it until
|
|
57
|
+
# # you need it. Or at the very least, to have the containers render
|
|
58
|
+
# # these components for you and inject them into their proper place
|
|
59
|
+
# # in the DOM structure
|
|
60
|
+
|
|
61
|
+
# Luca.registry.addNamespace 'App.views'
|
|
62
|
+
|
|
63
|
+
# #### View Helpers
|
|
64
|
+
# #
|
|
65
|
+
# # Luca.View is an extension of Backbone.View and provides some common
|
|
66
|
+
# # patterns that I have found useful in the most generic cases when developing
|
|
67
|
+
# # all different kinds of features in various kinds of apps.
|
|
68
|
+
|
|
69
|
+
# #### Auto Event Binding
|
|
70
|
+
# #
|
|
71
|
+
# # views can define a hooks attribute which prevent you from having to
|
|
72
|
+
# # bind to certain named triggers. Hooks methods are automatically called
|
|
73
|
+
# # within the context of the view itself
|
|
74
|
+
# Luca.View = Backbone.View.extend
|
|
75
|
+
# ...
|
|
76
|
+
# hooks:[
|
|
77
|
+
# "before:render"
|
|
78
|
+
# "after:render"
|
|
79
|
+
# ]
|
|
80
|
+
|
|
81
|
+
# SubClass = Luca.View.extend
|
|
82
|
+
# beforeRender: ()->
|
|
83
|
+
# @doSomething()
|
|
84
|
+
# afterRender: ()->
|
|
85
|
+
# @doSomething()
|
|
86
|
+
|
|
87
|
+
# # this is accomplished by the setupHooks method
|
|
88
|
+
# # which is automatically called on every Luca.View
|
|
89
|
+
# # subclass. This allows you to just define which
|
|
90
|
+
# # methods on your view should be called any time an
|
|
91
|
+
# # event gets triggered
|
|
92
|
+
# setupHooks: (set)->
|
|
93
|
+
# set ||= @hooks
|
|
94
|
+
|
|
95
|
+
# _(set).each (event)=>
|
|
96
|
+
# parts = event.split(':')
|
|
97
|
+
# prefix = parts.shift()
|
|
98
|
+
|
|
99
|
+
# parts = _( parts ).map (p)-> _.capitalize(p)
|
|
100
|
+
# fn = prefix + parts.join('')
|
|
101
|
+
|
|
102
|
+
# @bind event, ()=> @[fn].apply @, arguments if @[fn]
|
|
103
|
+
|
|
104
|
+
# #### Collection Helpers
|
|
105
|
+
# #
|
|
106
|
+
# # Luca.Collection is an extenstion of Backbone.Collection which provides
|
|
107
|
+
# # a bunch of commonly used patterns for doing things like:
|
|
108
|
+
# #
|
|
109
|
+
|
|
110
|
+
# # - setting base parameters used on every request to your REST API
|
|
111
|
+
# Luca.Collection.baseParams = (obj)->
|
|
112
|
+
# return Luca.Collection._baseParams = obj if obj
|
|
113
|
+
|
|
114
|
+
# if _.isFunction( Luca.Collection._baseParams )
|
|
115
|
+
# return Luca.Collection._baseParams.call()
|
|
116
|
+
|
|
117
|
+
# if _.isObject( Luca.Collection._baseParams )
|
|
118
|
+
# Luca.Collection._baseParams
|
|
119
|
+
|
|
120
|
+
# #
|
|
121
|
+
# # - filtering with query string parameters against your API
|
|
122
|
+
# #
|
|
123
|
+
# # - automatic interaction with your Luca.CollectionManager class
|
|
124
|
+
|
|
125
|
+
# register: (collectionManager="", key="", collection)->
|
|
126
|
+
# ...
|
|
127
|
+
# collection ||= this
|
|
128
|
+
# ...
|
|
129
|
+
# if _.isString( collectionManager )
|
|
130
|
+
# collectionManager = Luca.util.nestedValue( collectionManager, window )
|
|
131
|
+
|
|
132
|
+
# if _.isFunction( collectionManager.add )
|
|
133
|
+
# return collectionManager.add(key, collection)
|
|
134
|
+
|
|
135
|
+
# if _.isObject( collect)
|
|
136
|
+
# collectionManager[ key ] = collection
|
|
137
|
+
|
|
138
|
+
# # - make it easier to parse Rails style responses which include the root
|
|
139
|
+
# # by specifying a @root parameter
|
|
140
|
+
# #
|
|
141
|
+
# # - use backbone-query if available
|
|
142
|
+
# #
|
|
143
|
+
# # - onceLoaded: run a callback once if there are models present, otherwise wait until
|
|
144
|
+
# # the collection fetches
|
|
145
|
+
# onceLoaded: (fn)->
|
|
146
|
+
# ...
|
|
147
|
+
# wrapped = ()=> fn.apply @,[@]
|
|
148
|
+
|
|
149
|
+
# @bind "reset", ()=>
|
|
150
|
+
# wrapped()
|
|
151
|
+
# @unbind "reset", wrapped
|
|
152
|
+
# ...
|
|
153
|
+
# # - ifLoaded: run a callback any time the model gets reset, or if there are already models
|
|
154
|
+
# ifLoaded: (fn, scope=@)->
|
|
155
|
+
# ...
|
|
156
|
+
# @bind "reset", (collection)=>
|
|
157
|
+
# fn.apply scope, [collection]
|
|
158
|
+
# ...
|
|
159
|
+
# unless @fetching
|
|
160
|
+
# @fetch()
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
# # - bootstrapping a collection of objects which are
|
|
164
|
+
# # rendered in your markup on page load
|
|
165
|
+
|
|
166
|
+
# #### Collections with Bootstrapped Models
|
|
167
|
+
# #
|
|
168
|
+
# # In order to make our Backbone Apps super fast it is a good practice
|
|
169
|
+
# # to pre-populate your collections by what is referred to as bootstrapping
|
|
170
|
+
# #
|
|
171
|
+
# # Luca.Collections make it easier for you to do this cleanly and automatically
|
|
172
|
+
# #
|
|
173
|
+
# # by specifying a @cached property or method in your collection definition
|
|
174
|
+
# # Luca.Collections will automatically look in this space to find models
|
|
175
|
+
# # and avoid a roundtrip to your API unless explicitly told to.
|
|
176
|
+
# Luca.Collection._bootstrapped_models = {}
|
|
177
|
+
|
|
178
|
+
# Luca.Collection.bootstrap = (obj)->
|
|
179
|
+
# _.extend Luca.Collection._bootstrapped_models, obj
|
|
180
|
+
|
|
181
|
+
# Luca.Collection.cache = (key, models)->
|
|
182
|
+
# return Luca.Collection._bootstrapped_models[ key ] = models if models
|
|
183
|
+
# Luca.Collection._bootstrapped_models[ key ] || []
|
|
184
|
+
|
|
185
|
+
# Luca.Collection = Backbone.Collection.extend
|
|
186
|
+
# ...
|
|
187
|
+
# fetch: (options={})->
|
|
188
|
+
# @trigger "before:fetch", @
|
|
189
|
+
|
|
190
|
+
# return @reset(@data) if @memoryCollection is true
|
|
191
|
+
|
|
192
|
+
# # fetch will try to pull from the bootstrap if it is setup to do so
|
|
193
|
+
# # you can actually make the roundtrip to the server anyway if you pass
|
|
194
|
+
# # refresh = true in the options hash
|
|
195
|
+
# return @bootstrap() if @cached_models().length and not options.refresh
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
# #### Collection Manager
|
|
199
|
+
# #
|
|
200
|
+
# # The purpose of the collection manager is to provide an interface
|
|
201
|
+
# # for tracking the creation of collections, so that you only create
|
|
202
|
+
# # one instance of a given collection class per instance of some scope.
|
|
203
|
+
|
|
204
|
+
# class Luca.CollectionManager
|
|
205
|
+
# ...
|
|
206
|
+
# getOrCreate: (key,collectionOptions={},initialModels=[])->
|
|
207
|
+
# @get(key) || @create(key,collectionOptions,initialModels)
|
|
208
|
+
|
|
209
|
+
# # If you use a underscored version of your collection class name
|
|
210
|
+
# # as the key for your collection ( defined via @registerAs ) then
|
|
211
|
+
# # it will automatically be able to guess which collection you are
|
|
212
|
+
# # referring to and create it for you
|
|
213
|
+
# guessCollectionClass: (key)->
|
|
214
|
+
# classified = _( key ).chain().capitalize().camelize().value()
|
|
215
|
+
# guess = (@collectionPrefix || window)[ classified ]
|
|
216
|
+
|
|
217
|
+
# # You would generally create the collection manager once as part of
|
|
218
|
+
# # your global application object which, in my opinion should be a
|
|
219
|
+
# # Luca Viewport container
|
|
220
|
+
|
|
221
|
+
# LucaApp = Luca.containers.Viewport.extend
|
|
222
|
+
# initialize: (@options={})->
|
|
223
|
+
# @collectionManager = new Luca.CollectionManager
|
|
224
|
+
# getScope: ()=> @someParentValue()
|
|
225
|
+
|
|
226
|
+
# collection: (key,options={},models=[])->
|
|
227
|
+
# @collectionManager.getOrCreate(key,options,models)
|
|
228
|
+
|
|
229
|
+
# someParentValue: ()-> @usedToScopeTheCollections
|
|
230
|
+
|
|
231
|
+
# # Now in the single global instance of LucaApp you have
|
|
232
|
+
# # one central place to access a collection of models, one
|
|
233
|
+
# # interface to listen to for add, remove, reset, change events
|
|
234
|
+
|
|
235
|
+
# #### Collection and View Integration
|
|
236
|
+
|
|
237
|
+
# # One really cool feature of Luca is the enhanced API for binding
|
|
238
|
+
# # collections to views. Using an API very similar to the
|
|
239
|
+
# # DOM @events property on Backbone views. If you are using Luca.Collection
|
|
240
|
+
# # classes and a Luca.CollectionManager to track them, you can use the
|
|
241
|
+
# # @collectionEvents property on your views as a cleaner interface for
|
|
242
|
+
# # setting up your event bindings
|
|
243
|
+
|
|
244
|
+
# App.Manager = new Luca.CollectionManager()
|
|
245
|
+
|
|
246
|
+
# App.SampleCollection = new Luca.SampleCollection
|
|
247
|
+
# registerWith: "App.Manager"
|
|
248
|
+
# registerAs: "sample_collection"
|
|
249
|
+
|
|
250
|
+
# App.View = Luca.View.extend
|
|
251
|
+
# collectionEvents:
|
|
252
|
+
# "sample_collection add" : "onCollectionAdd"
|
|
253
|
+
|
|
254
|
+
# onCollectionAdd: (model,collection)->
|
|
255
|
+
# @doSomethingRighteous()
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
#### Collection Manager
|
|
2
|
+
#
|
|
3
|
+
# The purpose of the collection manager is to provide an interface
|
|
4
|
+
# for tracking the creation of collections, so that you only create
|
|
5
|
+
# one instance of a given collection class per instance of some scope
|
|
6
|
+
#
|
|
7
|
+
# For example:
|
|
8
|
+
|
|
9
|
+
# LucaApp = Luca.containers.Viewport.extend
|
|
10
|
+
# initialize: (@options={})->
|
|
11
|
+
# @collectionManager = new Luca.CollectionManager
|
|
12
|
+
# getScope: ()-> @someParentValue
|
|
13
|
+
# collection: (key,options={},models=[])->
|
|
14
|
+
# @collectionManager.getOrCreate(key,options,models)
|
|
15
|
+
#
|
|
16
|
+
# Now in the single global instance of LucaApp you have
|
|
17
|
+
# one central place to access a collection of models, one
|
|
18
|
+
# interface to listen to for add, remove, reset, change events
|
|
19
|
+
#
|
|
20
|
+
# If you don't want this, you can either do it the old fashioned way
|
|
21
|
+
# or just use the private option to get an unregistered instance.
|
|
22
|
+
#
|
|
23
|
+
|
|
24
|
+
#### View Event Binding Interface
|
|
25
|
+
#
|
|
26
|
+
# Luca.Views can specify a @collectionEvents property very similar to
|
|
27
|
+
# the DOM @events property in Backbone.Views and this provides a very
|
|
28
|
+
# clean API for binding to events on the collection manager and doing
|
|
29
|
+
# the necessary things on the view. This does assume that by default
|
|
30
|
+
# there is only one instance of the collection manager running, otherwise
|
|
31
|
+
# a configuration directive is provided at a view level to know which
|
|
32
|
+
# collection manager to pull from.
|
|
33
|
+
#
|
|
34
|
+
# Special Thanks to @tjbladez for this wonderful initialModelsa
|
|
35
|
+
#
|
|
36
|
+
|
|
37
|
+
instances = []
|
|
38
|
+
|
|
39
|
+
class Luca.CollectionManager
|
|
40
|
+
__collections: {}
|
|
41
|
+
|
|
42
|
+
constructor: (@options={})->
|
|
43
|
+
_.extend @, @options
|
|
44
|
+
_.extend @, Backbone.Events
|
|
45
|
+
|
|
46
|
+
# if you are going to use more than one collection
|
|
47
|
+
# manager, then you will have to specify which
|
|
48
|
+
# collection manager your views need to interact
|
|
49
|
+
# with for their collectionEvents configuration handling
|
|
50
|
+
instances.push(@)
|
|
51
|
+
|
|
52
|
+
# model to maintain state of the collection manager
|
|
53
|
+
@state = new Backbone.Model
|
|
54
|
+
|
|
55
|
+
if @collectionNames
|
|
56
|
+
|
|
57
|
+
@state.set({loaded_collections_count: 0, collections_count: @collectionNames.length })
|
|
58
|
+
@state.bind "change:loaded_collections_count", @collectionCountDidChange
|
|
59
|
+
|
|
60
|
+
if @useProgressLoader
|
|
61
|
+
@loader = new Luca.components.CollectionLoaderView(manager: @,name:"collection_loader_view")
|
|
62
|
+
|
|
63
|
+
@loadInitialCollections()
|
|
64
|
+
|
|
65
|
+
@
|
|
66
|
+
|
|
67
|
+
add: (key, collection)->
|
|
68
|
+
@currentScope()[ key ] ||= collection
|
|
69
|
+
|
|
70
|
+
allCollections: ()->
|
|
71
|
+
_( @currentScope() ).values()
|
|
72
|
+
|
|
73
|
+
# create a collection from just a key.
|
|
74
|
+
# if you pass the private option, it will
|
|
75
|
+
# skip registering this collection
|
|
76
|
+
create: (key, collectionOptions={}, initialModels=[])->
|
|
77
|
+
CollectionClass = collectionOptions.base
|
|
78
|
+
CollectionClass ||= @guessCollectionClass(key)
|
|
79
|
+
collectionOptions.name = "" if collectionOptions.private
|
|
80
|
+
|
|
81
|
+
collection = new CollectionClass(initialModels,collectionOptions)
|
|
82
|
+
|
|
83
|
+
@add(key, collection)
|
|
84
|
+
|
|
85
|
+
return collection
|
|
86
|
+
|
|
87
|
+
#### Collection Prefix
|
|
88
|
+
#
|
|
89
|
+
# If you are doing things right, you are namespacing all of your collection
|
|
90
|
+
# definitions, for example
|
|
91
|
+
#
|
|
92
|
+
# LucaApp.collections.SomeCollection = Luca.Collection.extend
|
|
93
|
+
# registerAs: "some_collection"
|
|
94
|
+
# registerWith: ""
|
|
95
|
+
#
|
|
96
|
+
# You should override this attribute when you create or define your collection manager
|
|
97
|
+
#
|
|
98
|
+
#
|
|
99
|
+
collectionNamespace: Luca.Collection.namespace
|
|
100
|
+
|
|
101
|
+
#### Collection Scopes
|
|
102
|
+
|
|
103
|
+
# any time you create a collection, or use getOrCreate, the key
|
|
104
|
+
# value ( @registerAs ) for your collection will be used to retrieve it
|
|
105
|
+
#
|
|
106
|
+
# if you plan to have multiple instances per key, but with some sort of
|
|
107
|
+
# scope based on a parent attribute, you should define a
|
|
108
|
+
currentScope: ()->
|
|
109
|
+
if current_scope = @getScope()
|
|
110
|
+
@__collections[ current_scope ] ||= {}
|
|
111
|
+
else
|
|
112
|
+
@__collections
|
|
113
|
+
|
|
114
|
+
# do something to each collection in the scope
|
|
115
|
+
each: (fn)->
|
|
116
|
+
_( @all() ).each(fn)
|
|
117
|
+
|
|
118
|
+
get:(key)->
|
|
119
|
+
@currentScope()[key]
|
|
120
|
+
|
|
121
|
+
# by default, we won't use a scope, but if you wish to use one
|
|
122
|
+
# you should define this method on your collection manager
|
|
123
|
+
getScope: ()-> undefined
|
|
124
|
+
|
|
125
|
+
getOrCreate: (key,collectionOptions={},initialModels=[])->
|
|
126
|
+
@get(key) || @create(key,collectionOptions,initialModels,false)
|
|
127
|
+
|
|
128
|
+
guessCollectionClass: (key)->
|
|
129
|
+
classified = _( key ).chain().capitalize().camelize().value()
|
|
130
|
+
guess = (@collectionNamespace || (window || global) )[ classified ]
|
|
131
|
+
guess ||= (@collectionNamespace || (window || global) )[ "#{classified}Collection" ]
|
|
132
|
+
guess
|
|
133
|
+
|
|
134
|
+
# load collection, iterates over each name you have passed for the
|
|
135
|
+
# your collections in the currentScope, makes sure they exist and
|
|
136
|
+
# fetched
|
|
137
|
+
loadInitialCollections: ()->
|
|
138
|
+
collectionDidLoad = (collection) =>
|
|
139
|
+
collection.unbind "reset"
|
|
140
|
+
@trigger "collection_loaded", collection.name
|
|
141
|
+
|
|
142
|
+
_(@collectionNames).each (name) =>
|
|
143
|
+
collection = @getOrCreate(name)
|
|
144
|
+
collection.bind "reset", ()->
|
|
145
|
+
collectionDidLoad(collection)
|
|
146
|
+
collection.fetch()
|
|
147
|
+
|
|
148
|
+
collectionCountDidChange: ()->
|
|
149
|
+
@trigger "all_collections_loaded" if @totalCollectionsCount() == @loadedCollectionsCount()
|
|
150
|
+
|
|
151
|
+
totalCollectionsCount: ()->
|
|
152
|
+
@state.get("collections_count")
|
|
153
|
+
|
|
154
|
+
loadedCollectionsCount: ()->
|
|
155
|
+
@state.get("loaded_collections_count")
|
|
156
|
+
# in most cases, the collections we use can be used only once
|
|
157
|
+
# and any reset events should be respected, bound to, etc. however
|
|
158
|
+
# if this ever isn't the case, you can create an instance
|
|
159
|
+
# of a collection which is "private" in that once it is
|
|
160
|
+
# returned from the collection manager, it isn't tracked so
|
|
161
|
+
# you can make sure any add / reset / remove / filter events
|
|
162
|
+
# don't effect other views
|
|
163
|
+
private: (key, collectionOptions={}, initialModels=[])->
|
|
164
|
+
@create(key,collectionOptions,initialModels,true)
|
|
165
|
+
|
|
166
|
+
Luca.CollectionManager.destroyAll = ()-> instances = []
|
|
167
|
+
Luca.CollectionManager.instances = ()-> instances
|
|
168
|
+
Luca.CollectionManager.get = ()-> _( instances ).last()
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Luca.SocketManager is an abstraction
|
|
2
|
+
# around various websocket services such as
|
|
3
|
+
# faye.js, socket.io, now.js, etc.
|
|
4
|
+
#
|
|
5
|
+
# It provides a common interface for adding
|
|
6
|
+
# push / async functionality to Collections,
|
|
7
|
+
# Models, and the like, regardless of the
|
|
8
|
+
# transport mechanism used.
|
|
9
|
+
#
|
|
10
|
+
# Simply bind to it, and any message that comes
|
|
11
|
+
# across the channel you subscribe to, will be
|
|
12
|
+
# bubbled up as a Backbone.Event with the message
|
|
13
|
+
# contents as your argument
|
|
14
|
+
class Luca.SocketManager
|
|
15
|
+
constructor: (@options={})->
|
|
16
|
+
_.extend Backbone.Events
|
|
17
|
+
|
|
18
|
+
@loadTransport()
|
|
19
|
+
|
|
20
|
+
connect: ()->
|
|
21
|
+
switch @options.provider
|
|
22
|
+
when "socket.io"
|
|
23
|
+
@socket = io.connect( @options.socket_host )
|
|
24
|
+
when "faye.js"
|
|
25
|
+
@socket = new Faye.Client( @options.socket_host )
|
|
26
|
+
|
|
27
|
+
#### Transport Loading and Configuration
|
|
28
|
+
#
|
|
29
|
+
# Luca wraps several popular client side socket abstractions
|
|
30
|
+
# such as socket.io or faye.js ( more coming soon )
|
|
31
|
+
#
|
|
32
|
+
# it provides a common interface on top of these and just
|
|
33
|
+
# treats them as Backbone.Events which you bind to like you
|
|
34
|
+
# would on any other Backbone class
|
|
35
|
+
|
|
36
|
+
transportLoaded: ()-> @connect()
|
|
37
|
+
|
|
38
|
+
transport_script: ()->
|
|
39
|
+
switch @options.provider
|
|
40
|
+
when "socket.io" then "#{ @options.transport_host }/socket.io/socket.io.js"
|
|
41
|
+
when "faye.js" then "#{ @options.transport_host }/faye.js"
|
|
42
|
+
|
|
43
|
+
loadTransport: ()->
|
|
44
|
+
script = document.createElement 'script'
|
|
45
|
+
script.setAttribute "type", "text/javascript"
|
|
46
|
+
script.setAttribute "src", @transport_script()
|
|
47
|
+
script.onload = @transportLoaded
|
|
48
|
+
|
|
49
|
+
if Luca.util.isIE()
|
|
50
|
+
script.onreadystatechange = ()=>
|
|
51
|
+
if script.readyState is "loaded"
|
|
52
|
+
@transportLoaded()
|
|
53
|
+
|
|
54
|
+
document.getElementsByTagName('head')[0].appendChild script
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# TODO THis module is going to be deprecated as it has been gradually gut over time
|
|
2
|
+
Luca.modules.Deferrable =
|
|
3
|
+
configure_collection: (setAsDeferrable=true)->
|
|
4
|
+
return unless @collection
|
|
5
|
+
|
|
6
|
+
if _.isString( @collection ) and collectionManager = Luca.CollectionManager?.get()
|
|
7
|
+
@collection = collectionManager.getOrCreate(@collection)
|
|
8
|
+
|
|
9
|
+
# if there is already an instantiated backbone collection don't do anything
|
|
10
|
+
unless @collection and _.isFunction( @collection.fetch ) and _.isFunction( @collection.reset )
|
|
11
|
+
@collection = new Luca.Collection( @collection.initial_set, @collection )
|
|
12
|
+
|
|
13
|
+
if @collection?.deferrable_trigger
|
|
14
|
+
@deferrable_trigger = @collection.deferrable_trigger
|
|
15
|
+
|
|
16
|
+
if setAsDeferrable
|
|
17
|
+
@deferrable = @collection
|
|
18
|
+
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
class Luca.LocalStore
|
|
2
|
+
|
|
3
|
+
# think of name the way you would a table in a mysql db
|
|
4
|
+
constructor: (@name)->
|
|
5
|
+
store = localStorage.getItem(@name)
|
|
6
|
+
@data = ( store && JSON.parse(store) ) || {}
|
|
7
|
+
|
|
8
|
+
guid: ()->
|
|
9
|
+
S4 = ()-> (((1+Math.random())*0x10000)|0).toString(16).substring(1)
|
|
10
|
+
(S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4())
|
|
11
|
+
|
|
12
|
+
# serialize the store into JSON and put it in the localStorage
|
|
13
|
+
save: ()->
|
|
14
|
+
localStorage.setItem(@name, JSON.stringify(@data) )
|
|
15
|
+
|
|
16
|
+
create: (model)->
|
|
17
|
+
model.id = model.attribtues.id = @guid() unless model.id
|
|
18
|
+
@data[ model.id ] = model
|
|
19
|
+
@save()
|
|
20
|
+
model
|
|
21
|
+
|
|
22
|
+
update: (model)->
|
|
23
|
+
@data[model.id] = model
|
|
24
|
+
@save()
|
|
25
|
+
model
|
|
26
|
+
|
|
27
|
+
find: (model)-> @data[ model.id ]
|
|
28
|
+
|
|
29
|
+
findAll: ()->
|
|
30
|
+
_.values( @data )
|
|
31
|
+
|
|
32
|
+
destroy: (model)->
|
|
33
|
+
delete @data[ model.id ]
|
|
34
|
+
@save()
|
|
35
|
+
model
|
|
36
|
+
|
|
37
|
+
Backbone.LocalSync = (method, model, options)->
|
|
38
|
+
store = model.localStorage || model.collection.localStorage
|
|
39
|
+
|
|
40
|
+
resp = switch method
|
|
41
|
+
when "read" then (if model.id then store.find(model) else store.findAll())
|
|
42
|
+
when "create" then store.create(model)
|
|
43
|
+
when "update" then store.update(model)
|
|
44
|
+
when "delete" then store.destroy(model)
|
|
45
|
+
|
|
46
|
+
if resp
|
|
47
|
+
options.success(resp)
|
|
48
|
+
else
|
|
49
|
+
options.error("Record not found")
|
|
50
|
+
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
html.luca-ui-fullscreen {
|
|
2
|
+
height: 100%;
|
|
3
|
+
|
|
4
|
+
body {
|
|
5
|
+
height: 100%;
|
|
6
|
+
padding: 0;
|
|
7
|
+
margin: 0;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.luca-ui-viewport {
|
|
11
|
+
height: 100%;
|
|
12
|
+
padding: 0;
|
|
13
|
+
margin: 0;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.luca-ui-viewport {
|
|
18
|
+
li {
|
|
19
|
+
list-style-type: none;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
li.nav {
|
|
23
|
+
cursor: pointer;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/*http://csswizardry.com/fluid-grids/#generated-grids*/
|
|
30
|
+
.wrapper{
|
|
31
|
+
max-width:1208px;
|
|
32
|
+
/* max-width:894px;*/
|
|
33
|
+
padding:0 15px;
|
|
34
|
+
margin:0 auto;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/*
|
|
38
|
+
Column container
|
|
39
|
+
*/
|
|
40
|
+
.grids{
|
|
41
|
+
width:auto;
|
|
42
|
+
max-width:924px;
|
|
43
|
+
clear:both;
|
|
44
|
+
margin:0 0 0 -3.247%;
|
|
45
|
+
list-style:none; /* So we can make grids out of lists. */
|
|
46
|
+
overflow:hidden; /* Clear the floats */
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
[class*="grid-"]{
|
|
50
|
+
float:left;
|
|
51
|
+
margin:0 3.247% 0 0;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.grid-margin {
|
|
55
|
+
margin:0 3.247% 0 0;
|
|
56
|
+
}
|
|
57
|
+
.grids {
|
|
58
|
+
.grid-margin {
|
|
59
|
+
margin:0 0 0 3.247%;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.grids [class*="grid-"]{
|
|
64
|
+
margin:0 0 0 3.247%;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.grid-1{ width:5.087% }
|
|
68
|
+
.grid-2{ width:13.42% }
|
|
69
|
+
.grid-3{ width:21.753% }
|
|
70
|
+
.grid-4{ width:30.087% }
|
|
71
|
+
.grid-5{ width:38.42% }
|
|
72
|
+
.grid-6{ width:46.753% }
|
|
73
|
+
.grid-7{ width:55.087% }
|
|
74
|
+
.grid-8{ width:63.42% }
|
|
75
|
+
.grid-9{ width:71.753% }
|
|
76
|
+
.grid-10{ width:80.087% }
|
|
77
|
+
.grid-11{ width:88.42% }
|
|
78
|
+
.grid-12{ width:96.753%; margin:0; }
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
.luca-ui-form-view-wrapper {
|
|
2
|
+
width: 100%;
|
|
3
|
+
float: left;
|
|
4
|
+
display: block;
|
|
5
|
+
clear: both;
|
|
6
|
+
margin: 10px 0px;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
.luca-ui-form-view {
|
|
11
|
+
.luca-ui-field {
|
|
12
|
+
margin: 5px;
|
|
13
|
+
padding: 5px;
|
|
14
|
+
|
|
15
|
+
.helper-text {
|
|
16
|
+
font-size: 0.75em;
|
|
17
|
+
font-color: #ccc;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.luca-ui-form-view.label-align-top {
|
|
23
|
+
.luca-ui-field {
|
|
24
|
+
label, input, select, textarea {
|
|
25
|
+
margin: 5px 0px;
|
|
26
|
+
display: block;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.luca-ui-form-view.column-layout {
|
|
32
|
+
.luca-ui-field {
|
|
33
|
+
float: left;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.form-view-footer {
|
|
38
|
+
.toolbar-container {
|
|
39
|
+
float: left;
|
|
40
|
+
width: 100%;
|
|
41
|
+
clear: both;
|
|
42
|
+
display: block;
|
|
43
|
+
.luca-ui-form-toolbar, .luca-ui-toolbar {
|
|
44
|
+
width: 50%;
|
|
45
|
+
display: block;
|
|
46
|
+
margin: 0px auto;
|
|
47
|
+
.luca-ui-field {
|
|
48
|
+
float: left;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
|