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.
Files changed (233) hide show
  1. data/.gitignore +5 -0
  2. data/Gemfile +17 -0
  3. data/Gemfile.lock +77 -0
  4. data/Guardfile +22 -0
  5. data/README.md +291 -0
  6. data/Rakefile +28 -0
  7. data/app.rb +46 -0
  8. data/assets/images/glyphicons-halflings-white.png +0 -0
  9. data/assets/images/glyphicons-halflings.png +0 -0
  10. data/assets/javascripts/dependencies/backbone-min.js +37 -0
  11. data/assets/javascripts/dependencies/backbone-query.min.js +1 -0
  12. data/assets/javascripts/dependencies/bootstrap.min.js +1 -0
  13. data/assets/javascripts/dependencies/jasmine-html.js +190 -0
  14. data/assets/javascripts/dependencies/jasmine.js +2476 -0
  15. data/assets/javascripts/dependencies/jquery.js +4 -0
  16. data/assets/javascripts/dependencies/modal.js +698 -0
  17. data/assets/javascripts/dependencies/modernizr.min.js +30 -0
  18. data/assets/javascripts/dependencies/prettify.js +28 -0
  19. data/assets/javascripts/dependencies/sinon.js +3469 -0
  20. data/assets/javascripts/dependencies/spin-min.js +2 -0
  21. data/assets/javascripts/dependencies/underscore-min.js +31 -0
  22. data/assets/javascripts/dependencies/underscore-string.min.js +14 -0
  23. data/assets/javascripts/dependencies.coffee +7 -0
  24. data/assets/javascripts/luca-ui-base.coffee +12 -0
  25. data/assets/javascripts/luca-ui-spec.coffee +2 -0
  26. data/assets/javascripts/luca-ui.coffee +3 -0
  27. data/assets/javascripts/sandbox/collections/sample.coffee +0 -0
  28. data/assets/javascripts/sandbox/config.coffee +7 -0
  29. data/assets/javascripts/sandbox/sandbox.coffee +16 -0
  30. data/assets/javascripts/sandbox/templates/features/collection_helpers.luca +33 -0
  31. data/assets/javascripts/sandbox/templates/features/form_demo_code.luca +48 -0
  32. data/assets/javascripts/sandbox/templates/features/grid_demo_code.luca +24 -0
  33. data/assets/javascripts/sandbox/templates/features/introduction.luca +11 -0
  34. data/assets/javascripts/sandbox/templates/features/view_helpers.luca +43 -0
  35. data/assets/javascripts/sandbox/templates/navigation.luca +8 -0
  36. data/assets/javascripts/sandbox/views/form_demo.coffee +47 -0
  37. data/assets/javascripts/sandbox/views/grid_demo.coffee +23 -0
  38. data/assets/javascripts/sandbox/views/pages/collection_events_sample.coffee +1 -0
  39. data/assets/javascripts/sandbox/views/pages/pages_controller.coffee +28 -0
  40. data/assets/javascripts/sandbox.coffee +4 -0
  41. data/assets/javascripts/spec-dependencies.coffee +4 -0
  42. data/assets/stylesheets/bootstrap-responsive.min.css +3 -0
  43. data/assets/stylesheets/bootstrap.min.css +610 -0
  44. data/assets/stylesheets/jasmine.css +166 -0
  45. data/assets/stylesheets/luca-ui-bootstrap.css +5 -0
  46. data/assets/stylesheets/luca-ui-spec.css +3 -0
  47. data/assets/stylesheets/luca-ui.css +3 -0
  48. data/assets/stylesheets/prettify.css +40 -0
  49. data/assets/stylesheets/sandbox/sandbox.scss +4 -0
  50. data/assets/stylesheets/sandbox.css +3 -0
  51. data/config.ru +11 -0
  52. data/lib/luca/command_line.rb +69 -0
  53. data/lib/luca/rails/engine.rb +12 -0
  54. data/lib/luca/rails/version.rb +6 -0
  55. data/lib/luca/rails.rb +9 -0
  56. data/lib/luca/template.rb +51 -0
  57. data/lib/luca/test_harness.rb +106 -0
  58. data/lib/luca.rb +1 -0
  59. data/lib/sprockets/luca_template.rb +49 -0
  60. data/lib/templates/spec_manifest_javascripts.erb +7 -0
  61. data/lib/templates/spec_manifest_stylesheets.erb +11 -0
  62. data/luca.gemspec +26 -0
  63. data/public/jasmine/index.html +26 -0
  64. data/public/sandbox/api.js +1 -0
  65. data/spec/components/application_spec.coffee +0 -0
  66. data/spec/components/collection_loader_view_spec.coffee +0 -0
  67. data/spec/components/controller_spec.coffee +0 -0
  68. data/spec/components/form_view_spec.coffee +13 -0
  69. data/spec/components/grid_view_spec.coffee +0 -0
  70. data/spec/components/record_manager_spec.coffee +0 -0
  71. data/spec/components/template_spec.coffee +0 -0
  72. data/spec/containers/card_view_spec.coffee +1 -0
  73. data/spec/containers/column_view_spec.coffee +0 -0
  74. data/spec/containers/modal_view_spec.coffee +0 -0
  75. data/spec/containers/panel_view_spec.coffee +0 -0
  76. data/spec/containers/split_view_spec.coffee +0 -0
  77. data/spec/containers/tab_view_spec.coffee +0 -0
  78. data/spec/containers/viewport_spec.coffee +0 -0
  79. data/spec/core/collection_spec.coffee +215 -0
  80. data/spec/core/container_spec.coffee +0 -0
  81. data/spec/core/field_spec.coffee +0 -0
  82. data/spec/core/observer_spec.coffee +0 -0
  83. data/spec/core/view_spec.coffee +87 -0
  84. data/spec/framework_spec.coffee +48 -0
  85. data/spec/helper.coffee +120 -0
  86. data/spec/managers/collection_manager_spec.coffee +95 -0
  87. data/spec/managers/socket_manager_spec.coffee +0 -0
  88. data/src/components/application.coffee +83 -0
  89. data/src/components/base_toolbar.coffee +16 -0
  90. data/src/components/collection_loader_view.coffee +37 -0
  91. data/src/components/controller.coffee +41 -0
  92. data/src/components/fields/button_field.coffee +40 -0
  93. data/src/components/fields/checkbox_field.coffee +41 -0
  94. data/src/components/fields/file_upload_field.coffee +15 -0
  95. data/src/components/fields/hidden_field.coffee +18 -0
  96. data/src/components/fields/select_field.coffee +100 -0
  97. data/src/components/fields/text_area_field.coffee +43 -0
  98. data/src/components/fields/text_field.coffee +42 -0
  99. data/src/components/fields/type_ahead_field.coffee +10 -0
  100. data/src/components/form_button_toolbar.coffee +26 -0
  101. data/src/components/form_view.coffee +205 -0
  102. data/src/components/grid_view.coffee +208 -0
  103. data/src/components/record_manager.coffee +215 -0
  104. data/src/components/router.coffee +34 -0
  105. data/src/components/template.coffee +19 -0
  106. data/src/containers/card_view.coffee +89 -0
  107. data/src/containers/column_view.coffee +48 -0
  108. data/src/containers/modal_view.coffee +85 -0
  109. data/src/containers/panel_view.coffee +24 -0
  110. data/src/containers/split_view.coffee +12 -0
  111. data/src/containers/tab_view.coffee +77 -0
  112. data/src/containers/viewport.coffee +16 -0
  113. data/src/core/collection.coffee +319 -0
  114. data/src/core/container.coffee +256 -0
  115. data/src/core/field.coffee +68 -0
  116. data/src/core/observer.coffee +17 -0
  117. data/src/core/view.coffee +190 -0
  118. data/src/framework.coffee +110 -0
  119. data/src/index.coffee +255 -0
  120. data/src/managers/collection_manager.coffee +168 -0
  121. data/src/managers/socket_manager.coffee +54 -0
  122. data/src/modules/deferrable.coffee +18 -0
  123. data/src/modules/local_storage.coffee +50 -0
  124. data/src/stylesheets/base.scss +78 -0
  125. data/src/stylesheets/components/form_view.scss +54 -0
  126. data/src/stylesheets/components/grid_view.scss +111 -0
  127. data/src/stylesheets/components/toolbar.scss +15 -0
  128. data/src/stylesheets/containers/container.scss +7 -0
  129. data/src/stylesheets/containers/modal_view.scss +0 -0
  130. data/src/stylesheets/containers/tab_view.scss +33 -0
  131. data/src/stylesheets/normalize.scss +430 -0
  132. data/src/templates/components/bootstrap_form_controls.luca +7 -0
  133. data/src/templates/components/collection_loader_view.luca +5 -0
  134. data/src/templates/components/form_view.luca +15 -0
  135. data/src/templates/components/grid_view.luca +9 -0
  136. data/src/templates/components/grid_view_empty_text.luca +3 -0
  137. data/src/templates/containers/basic.luca +1 -0
  138. data/src/templates/containers/tab_selector_container.luca +8 -0
  139. data/src/templates/containers/tab_view.luca +1 -0
  140. data/src/templates/containers/toolbar_wrapper.luca +1 -0
  141. data/src/templates/fields/button_field.luca +2 -0
  142. data/src/templates/fields/button_field_link.luca +5 -0
  143. data/src/templates/fields/checkbox_field.luca +9 -0
  144. data/src/templates/fields/file_upload_field.luca +8 -0
  145. data/src/templates/fields/hidden_field.luca +1 -0
  146. data/src/templates/fields/select_field.luca +7 -0
  147. data/src/templates/fields/text_area_field.luca +8 -0
  148. data/src/templates/fields/text_field.luca +13 -0
  149. data/src/templates/sample/contents.luca +1 -0
  150. data/src/templates/sample/welcome.luca +1 -0
  151. data/vendor/assets/images/glyphicons-halflings-white.png +0 -0
  152. data/vendor/assets/images/glyphicons-halflings.png +0 -0
  153. data/vendor/assets/javascripts/luca-spec-dependencies.js +6135 -0
  154. data/vendor/assets/javascripts/luca-ui-base.js +1527 -0
  155. data/vendor/assets/javascripts/luca-ui-spec.js +3654 -0
  156. data/vendor/assets/javascripts/luca-ui.js +2763 -0
  157. data/vendor/assets/luca-ui/base.css +85 -0
  158. data/vendor/assets/luca-ui/components/application.js +91 -0
  159. data/vendor/assets/luca-ui/components/base_toolbar.js +23 -0
  160. data/vendor/assets/luca-ui/components/controller.js +38 -0
  161. data/vendor/assets/luca-ui/components/fields/button_field.js +45 -0
  162. data/vendor/assets/luca-ui/components/fields/checkbox_field.js +43 -0
  163. data/vendor/assets/luca-ui/components/fields/file_upload_field.js +20 -0
  164. data/vendor/assets/luca-ui/components/fields/hidden_field.js +20 -0
  165. data/vendor/assets/luca-ui/components/fields/select_field.js +97 -0
  166. data/vendor/assets/luca-ui/components/fields/text_area_field.js +48 -0
  167. data/vendor/assets/luca-ui/components/fields/text_field.js +46 -0
  168. data/vendor/assets/luca-ui/components/fields/type_ahead_field.js +13 -0
  169. data/vendor/assets/luca-ui/components/form_button_toolbar.js +32 -0
  170. data/vendor/assets/luca-ui/components/form_view.css +32 -0
  171. data/vendor/assets/luca-ui/components/form_view.js +207 -0
  172. data/vendor/assets/luca-ui/components/grid_view.css +76 -0
  173. data/vendor/assets/luca-ui/components/grid_view.js +202 -0
  174. data/vendor/assets/luca-ui/components/record_manager.js +207 -0
  175. data/vendor/assets/luca-ui/components/router.js +36 -0
  176. data/vendor/assets/luca-ui/components/template.js +26 -0
  177. data/vendor/assets/luca-ui/components/toolbar.css +11 -0
  178. data/vendor/assets/luca-ui/containers/card_view.js +98 -0
  179. data/vendor/assets/luca-ui/containers/column_view.js +52 -0
  180. data/vendor/assets/luca-ui/containers/container.css +3 -0
  181. data/vendor/assets/luca-ui/containers/modal_view.css +0 -0
  182. data/vendor/assets/luca-ui/containers/modal_view.js +87 -0
  183. data/vendor/assets/luca-ui/containers/panel_view.js +34 -0
  184. data/vendor/assets/luca-ui/containers/split_view.js +13 -0
  185. data/vendor/assets/luca-ui/containers/tab_view.css +16 -0
  186. data/vendor/assets/luca-ui/containers/tab_view.js +80 -0
  187. data/vendor/assets/luca-ui/containers/viewport.js +18 -0
  188. data/vendor/assets/luca-ui/core/collection.js +221 -0
  189. data/vendor/assets/luca-ui/core/container.js +205 -0
  190. data/vendor/assets/luca-ui/core/field.js +59 -0
  191. data/vendor/assets/luca-ui/core/observer.js +42 -0
  192. data/vendor/assets/luca-ui/core/view.js +127 -0
  193. data/vendor/assets/luca-ui/framework.js +110 -0
  194. data/vendor/assets/luca-ui/index.js +5 -0
  195. data/vendor/assets/luca-ui/managers/collection_manager.js +98 -0
  196. data/vendor/assets/luca-ui/managers/socket_manager.js +52 -0
  197. data/vendor/assets/luca-ui/modules/deferrable.js +21 -0
  198. data/vendor/assets/luca-ui/modules/local_storage.js +81 -0
  199. data/vendor/assets/luca-ui/normalize.css +359 -0
  200. data/vendor/assets/luca-ui/stylesheets/base.css +85 -0
  201. data/vendor/assets/luca-ui/stylesheets/components/form_view.css +32 -0
  202. data/vendor/assets/luca-ui/stylesheets/components/grid_view.css +76 -0
  203. data/vendor/assets/luca-ui/stylesheets/components/toolbar.css +11 -0
  204. data/vendor/assets/luca-ui/stylesheets/containers/container.css +3 -0
  205. data/vendor/assets/luca-ui/stylesheets/containers/modal_view.css +0 -0
  206. data/vendor/assets/luca-ui/stylesheets/containers/tab_view.css +16 -0
  207. data/vendor/assets/luca-ui/stylesheets/normalize.css +359 -0
  208. data/vendor/assets/luca-ui/templates/components/bootstrap_form_controls.js +4 -0
  209. data/vendor/assets/luca-ui/templates/components/form_view.js +4 -0
  210. data/vendor/assets/luca-ui/templates/components/grid_view.js +4 -0
  211. data/vendor/assets/luca-ui/templates/components/grid_view_empty_text.js +4 -0
  212. data/vendor/assets/luca-ui/templates/containers/basic.js +4 -0
  213. data/vendor/assets/luca-ui/templates/containers/tab_selector_container.js +4 -0
  214. data/vendor/assets/luca-ui/templates/containers/tab_view.js +4 -0
  215. data/vendor/assets/luca-ui/templates/containers/toolbar_wrapper.js +4 -0
  216. data/vendor/assets/luca-ui/templates/fields/button_field.js +4 -0
  217. data/vendor/assets/luca-ui/templates/fields/button_field_link.js +4 -0
  218. data/vendor/assets/luca-ui/templates/fields/checkbox_field.js +4 -0
  219. data/vendor/assets/luca-ui/templates/fields/file_upload_field.js +4 -0
  220. data/vendor/assets/luca-ui/templates/fields/hidden_field.js +4 -0
  221. data/vendor/assets/luca-ui/templates/fields/select_field.js +4 -0
  222. data/vendor/assets/luca-ui/templates/fields/text_area_field.js +4 -0
  223. data/vendor/assets/luca-ui/templates/fields/text_field.js +4 -0
  224. data/vendor/assets/luca-ui/templates/sample/contents.js +4 -0
  225. data/vendor/assets/luca-ui/templates/sample/welcome.js +4 -0
  226. data/vendor/assets/stylesheets/luca-spec-dependencies.css +166 -0
  227. data/vendor/assets/stylesheets/luca-ui-bootstrap.css +1201 -0
  228. data/vendor/assets/stylesheets/luca-ui-spec.css +586 -0
  229. data/vendor/assets/stylesheets/luca-ui.css +586 -0
  230. data/views/index.erb +20 -0
  231. data/views/jasmine.erb +22 -0
  232. data/views/spec_harness.erb +29 -0
  233. 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
+