luca 0.9.8 → 0.9.9

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 (310) hide show
  1. data/CHANGELOG +49 -0
  2. data/Gemfile +8 -1
  3. data/Gemfile.lock +97 -53
  4. data/Guardfile +3 -25
  5. data/README.md +5 -16
  6. data/ROADMAP +15 -9
  7. data/Rakefile +24 -75
  8. data/app.rb +10 -42
  9. data/app/assets/javascripts/luca/basic.coffee +1 -1
  10. data/app/assets/javascripts/luca/components/application.coffee +187 -104
  11. data/app/assets/javascripts/luca/components/collection_view.coffee +115 -51
  12. data/app/assets/javascripts/luca/components/controller.coffee +87 -10
  13. data/app/assets/javascripts/luca/components/fields/base.coffee +74 -13
  14. data/app/assets/javascripts/luca/components/fields/button_field.coffee +60 -13
  15. data/app/assets/javascripts/luca/components/fields/checkbox_array.coffee +12 -7
  16. data/app/assets/javascripts/luca/components/fields/select_field.coffee +82 -23
  17. data/app/assets/javascripts/luca/components/fields/text_area_field.coffee +25 -10
  18. data/app/assets/javascripts/luca/components/fields/text_field.coffee +9 -3
  19. data/app/assets/javascripts/luca/components/form_view.coffee +105 -33
  20. data/app/assets/javascripts/luca/components/grid_layout_view.coffee +42 -0
  21. data/app/assets/javascripts/luca/components/index.coffee +6 -0
  22. data/app/assets/javascripts/luca/components/nav_bar.coffee +60 -6
  23. data/app/assets/javascripts/luca/components/page.coffee +70 -0
  24. data/app/assets/javascripts/luca/components/simple_collection_view.coffee +10 -0
  25. data/app/assets/javascripts/luca/components/table_view.coffee +7 -3
  26. data/app/assets/javascripts/luca/components/table_view_scrollable.coffee +23 -0
  27. data/app/assets/javascripts/luca/concerns/collection_event_bindings.coffee +4 -1
  28. data/app/assets/javascripts/luca/concerns/development_tool_helpers.coffee +23 -14
  29. data/app/assets/javascripts/luca/concerns/dom_helpers.coffee +2 -2
  30. data/app/assets/javascripts/luca/concerns/filterable.coffee +8 -11
  31. data/app/assets/javascripts/luca/concerns/form_model_bindings.coffee +20 -0
  32. data/app/assets/javascripts/luca/concerns/modal_view.coffee +40 -15
  33. data/app/assets/javascripts/luca/concerns/query_collection_bindings.coffee +7 -1
  34. data/app/assets/javascripts/luca/concerns/state_model.coffee +40 -26
  35. data/app/assets/javascripts/luca/concerns/templating.coffee +3 -1
  36. data/app/assets/javascripts/luca/config.coffee +5 -0
  37. data/app/assets/javascripts/luca/containers/card_view.coffee +87 -52
  38. data/app/assets/javascripts/luca/containers/container.coffee +305 -108
  39. data/app/assets/javascripts/luca/containers/modal_view.coffee +9 -9
  40. data/app/assets/javascripts/luca/containers/page_controller.coffee +25 -0
  41. data/app/assets/javascripts/luca/containers/panel_toolbar.coffee +5 -6
  42. data/app/assets/javascripts/luca/containers/tab_view.coffee +19 -10
  43. data/app/assets/javascripts/luca/containers/viewport.coffee +12 -16
  44. data/app/assets/javascripts/luca/core/collection.coffee +19 -5
  45. data/app/assets/javascripts/luca/core/events.coffee +5 -5
  46. data/app/assets/javascripts/luca/core/model.coffee +1 -1
  47. data/app/assets/javascripts/luca/core/panel.coffee +18 -6
  48. data/app/assets/javascripts/luca/core/registry/component_definition.coffee +2 -1
  49. data/app/assets/javascripts/luca/core/registry/meta_data.coffee +2 -0
  50. data/app/assets/javascripts/luca/core/registry/registry.coffee +14 -11
  51. data/app/assets/javascripts/luca/core/templates.coffee +5 -1
  52. data/app/assets/javascripts/luca/core/view.coffee +200 -47
  53. data/app/assets/javascripts/luca/dependencies.coffee +2 -0
  54. data/app/assets/javascripts/luca/development/code_sync_manager.coffee +173 -0
  55. data/app/assets/javascripts/luca/development/component.coffee +76 -0
  56. data/app/assets/javascripts/luca/development/components.coffee +57 -0
  57. data/app/assets/javascripts/luca/development/console.coffee +1 -1
  58. data/app/assets/javascripts/luca/development/index.coffee +4 -1
  59. data/app/assets/javascripts/luca/framework.coffee +7 -3
  60. data/app/assets/javascripts/luca/index.coffee +2 -1
  61. data/app/assets/javascripts/luca/managers/collection_manager.coffee +2 -3
  62. data/app/assets/javascripts/luca/managers/index.coffee +1 -1
  63. data/app/assets/javascripts/luca/managers/socket_manager.coffee +31 -8
  64. data/app/assets/javascripts/luca/templates/components/nav_bar.jst.ejs +16 -1
  65. data/app/assets/javascripts/luca/templates/containers/tab_view.jst.ejs +1 -1
  66. data/app/assets/javascripts/luca/util/index.coffee +1 -0
  67. data/app/assets/javascripts/luca/util/keybindings.coffee +24 -0
  68. data/app/assets/javascripts/luca/util/logging.coffee +15 -0
  69. data/app/assets/javascripts/luca/util/luca.coffee +9 -1
  70. data/app/assets/stylesheets/luca/components/table_view.scss +85 -0
  71. data/app/assets/stylesheets/luca/components/viewport.scss +0 -4
  72. data/app/assets/stylesheets/luca/containers/container.scss +8 -0
  73. data/app/assets/stylesheets/luca/index.css +2 -2
  74. data/bin/luca +14 -0
  75. data/config.ru +1 -2
  76. data/docs/framework.json +1 -0
  77. data/docs/luca-framework-documentation.js +1 -0
  78. data/docs/{application.md → old/application.md} +0 -0
  79. data/docs/{collection.md → old/collection.md} +0 -0
  80. data/docs/{collection_manager.md → old/collection_manager.md} +0 -0
  81. data/docs/{container_philosophy.md → old/container_philosophy.md} +0 -0
  82. data/docs/{event_binding_helpers.md → old/event_binding_helpers.md} +0 -0
  83. data/docs/{method_caching_and_computed_properties.md → old/method_caching_and_computed_properties.md} +0 -0
  84. data/docs/{view.md → old/view.md} +0 -0
  85. data/lib/generators/luca/application/templates/javascripts/dependencies.coffee +2 -5
  86. data/lib/guard/luca.rb +84 -0
  87. data/lib/luca.rb +25 -1
  88. data/lib/luca/asset_compiler.rb +117 -0
  89. data/lib/luca/cli.rb +68 -0
  90. data/lib/luca/cli/generate.rb +37 -0
  91. data/lib/luca/cli/server.rb +20 -0
  92. data/lib/luca/cli/sync.rb +40 -0
  93. data/lib/luca/cli/watch.rb +16 -0
  94. data/lib/luca/collection.rb +64 -0
  95. data/lib/luca/collection/endpoint.rb +38 -0
  96. data/lib/luca/collection/file_backend.rb +121 -0
  97. data/lib/luca/collection/redis_backend.rb +153 -0
  98. data/lib/luca/compiled_asset.rb +61 -0
  99. data/lib/luca/component_definition.rb +356 -0
  100. data/lib/luca/luca_application.rb +258 -0
  101. data/lib/luca/project.rb +73 -0
  102. data/lib/luca/project_harness.rb +96 -0
  103. data/lib/luca/rails.rb +5 -3
  104. data/lib/luca/rails/engine.rb +8 -0
  105. data/lib/luca/rails/version.rb +1 -2
  106. data/lib/luca/server.rb +7 -0
  107. data/lib/luca/stylesheet.rb +35 -0
  108. data/lib/luca/template.rb +2 -0
  109. data/lib/luca/template_asset.rb +64 -0
  110. data/lib/luca/version.rb +3 -0
  111. data/lib/luca/watcher.rb +72 -0
  112. data/lib/railties/luca/tasks.rake +7 -0
  113. data/site/.bundle/config +2 -0
  114. data/site/.gitignore +5 -0
  115. data/site/.rvmrc +1 -0
  116. data/site/CHANGELOG.md +41 -0
  117. data/site/DOCS.md +41 -0
  118. data/site/Gemfile +8 -0
  119. data/site/Gemfile.lock +134 -0
  120. data/site/LICENSE.md +19 -0
  121. data/site/config.rb +84 -0
  122. data/site/helpers/site_helpers.rb +20 -0
  123. data/site/html5bp-docs/README.md +38 -0
  124. data/site/html5bp-docs/contribute.md +104 -0
  125. data/site/html5bp-docs/crossdomain.md +21 -0
  126. data/site/html5bp-docs/css.md +135 -0
  127. data/site/html5bp-docs/extend.md +507 -0
  128. data/site/html5bp-docs/faq.md +77 -0
  129. data/site/html5bp-docs/htaccess.md +323 -0
  130. data/site/html5bp-docs/html.md +170 -0
  131. data/site/html5bp-docs/js.md +31 -0
  132. data/site/html5bp-docs/misc.md +25 -0
  133. data/site/html5bp-docs/usage.md +109 -0
  134. data/site/readme.md +47 -0
  135. data/site/source/.htaccess +540 -0
  136. data/site/source/404.html +157 -0
  137. data/site/source/app/assets/javascripts/dependencies.js.coffee +6 -0
  138. data/site/source/app/assets/javascripts/docs-docs.js +1 -0
  139. data/site/source/app/assets/javascripts/docs/application.coffee +64 -0
  140. data/site/source/app/assets/javascripts/docs/collections/docs_documentation.coffee +17 -0
  141. data/site/source/app/assets/javascripts/docs/collections/github_repositories.coffee +7 -0
  142. data/site/source/app/assets/javascripts/docs/collections/index.coffee +1 -0
  143. data/site/source/app/assets/javascripts/docs/collections/luca_documentation.coffee +17 -0
  144. data/site/source/app/assets/javascripts/docs/collections/public_gists.coffee +4 -0
  145. data/site/source/app/assets/javascripts/docs/config.coffee +5 -0
  146. data/site/source/app/assets/javascripts/docs/index.coffee +12 -0
  147. data/site/source/app/assets/javascripts/docs/lib/router.coffee +3 -0
  148. data/{spec/components/application_spec.coffee → site/source/app/assets/javascripts/docs/lib/util.coffee} +0 -0
  149. data/site/source/app/assets/javascripts/docs/models/component.coffee +99 -0
  150. data/site/source/app/assets/javascripts/docs/models/github_repository.coffee +3 -0
  151. data/site/source/app/assets/javascripts/docs/models/index.coffee +1 -0
  152. data/site/source/app/assets/javascripts/docs/templates/component_documentation.jst.ejs +55 -0
  153. data/site/source/app/assets/javascripts/docs/templates/examples_browser/overview.jst.ejs +4 -0
  154. data/site/source/app/assets/javascripts/docs/templates/examples_browser/selector.jst.ejs +11 -0
  155. data/site/source/app/assets/javascripts/docs/templates/github_repository.jst.ejs +4 -0
  156. data/site/source/app/assets/javascripts/docs/templates/layouts/main.jst.ejs +4 -0
  157. data/site/source/app/assets/javascripts/docs/templates/left_navigation.jst.ejs +5 -0
  158. data/site/source/app/assets/javascripts/docs/templates/pages/getting_started.jst.ejs +78 -0
  159. data/site/source/app/assets/javascripts/docs/templates/pages/home.jst.ejs +57 -0
  160. data/site/source/app/assets/javascripts/docs/views/components/code_editor.coffee +45 -0
  161. data/{spec/components/collection_loader_view_spec.coffee → site/source/app/assets/javascripts/docs/views/components/code_editor/index.coffee} +0 -0
  162. data/site/source/app/assets/javascripts/docs/views/components/component_documentation.coffee +72 -0
  163. data/site/source/app/assets/javascripts/docs/views/index.coffee +3 -0
  164. data/site/source/app/assets/javascripts/docs/views/pages/browse_source.coffee +46 -0
  165. data/site/source/app/assets/javascripts/docs/views/pages/browse_source/details.coffee +37 -0
  166. data/site/source/app/assets/javascripts/docs/views/pages/browse_source/list.coffee +31 -0
  167. data/site/source/app/assets/javascripts/docs/views/pages/component_editor.coffee +10 -0
  168. data/site/source/app/assets/javascripts/docs/views/pages/examples_browser.coffee +102 -0
  169. data/site/source/app/assets/javascripts/docs/views/pages/examples_browser/docs.coffee +12 -0
  170. data/site/source/app/assets/javascripts/docs/views/pages/examples_browser/source.coffee +13 -0
  171. data/site/source/app/assets/javascripts/docs/views/pages/home.coffee +10 -0
  172. data/site/source/app/assets/javascripts/docs/views/views/api_browser/index.coffee +43 -0
  173. data/site/source/app/assets/javascripts/docs/views/views/collection_view_examples/grid_layout_view_example.coffee +14 -0
  174. data/site/source/app/assets/javascripts/docs/views/views/collection_view_examples/table_view_example.coffee +39 -0
  175. data/site/source/app/assets/javascripts/docs/views/views/form_view_examples/basic_example.coffee +38 -0
  176. data/site/source/app/assets/javascripts/docs/views/views/form_view_examples/complex_layout.coffee +110 -0
  177. data/site/source/app/assets/javascripts/docs/views/views/top_navigation.coffee +6 -0
  178. data/site/source/app/assets/javascripts/luca-docs.js +1 -0
  179. data/site/source/app/assets/javascripts/luca-framework-documentation.js +1 -0
  180. data/site/source/app/assets/javascripts/site.js.coffee +4 -0
  181. data/site/source/app/assets/javascripts/vendor/codemirror.js +4786 -0
  182. data/site/source/app/assets/javascripts/vendor/coffeescript.js +346 -0
  183. data/site/source/app/assets/javascripts/vendor/css.js +465 -0
  184. data/site/source/app/assets/javascripts/vendor/htmlmixed.js +84 -0
  185. data/site/source/app/assets/javascripts/vendor/javascript.js +422 -0
  186. data/site/source/app/assets/javascripts/vendor/js-beautify.js +1353 -0
  187. data/site/source/app/assets/javascripts/vendor/modernizr-2.6.1.min.js +4 -0
  188. data/site/source/app/assets/javascripts/vendor/vim.js +2511 -0
  189. data/site/source/app/assets/stylesheets/docs/api-browser.css.scss +5 -0
  190. data/site/source/app/assets/stylesheets/docs/application.css.scss +35 -0
  191. data/site/source/app/assets/stylesheets/docs/browse-source.css.scss +5 -0
  192. data/site/source/app/assets/stylesheets/docs/scrollable-table.css.scss +5 -0
  193. data/site/source/app/assets/stylesheets/site.css.scss +2 -0
  194. data/site/source/app/assets/stylesheets/vendor/codemirror.css +240 -0
  195. data/site/source/app/assets/stylesheets/vendor/prettify-tomorrow-night-bright.css +160 -0
  196. data/site/source/app/assets/stylesheets/vendor/twilight.css +26 -0
  197. data/site/source/crossdomain.xml +15 -0
  198. data/site/source/documentation.html.haml +1 -0
  199. data/site/source/favicon_base.png +0 -0
  200. data/site/source/humans.txt +15 -0
  201. data/site/source/images/background.png +0 -0
  202. data/site/source/images/middleman.png +0 -0
  203. data/site/source/index.html.haml +1 -0
  204. data/site/source/layouts/layout.haml +55 -0
  205. data/site/source/readme.md +63 -0
  206. data/site/source/robots.txt +3 -0
  207. data/spec/{components/grid_view_spec.coffee → javascripts/components/application_spec.coffee} +0 -0
  208. data/spec/{components/pagination_control_spec.coffee → javascripts/components/collection_loader_view_spec.coffee} +0 -0
  209. data/spec/{components → javascripts/components}/collection_view_spec.coffee +1 -1
  210. data/spec/{components → javascripts/components}/controller_spec.coffee +0 -0
  211. data/spec/{components → javascripts/components}/fields/checkbox_array_spec.coffee +0 -0
  212. data/spec/javascripts/components/form_view_spec.coffee +162 -0
  213. data/spec/{components/record_manager_spec.coffee → javascripts/components/grid_view_spec.coffee} +0 -0
  214. data/spec/{components → javascripts/components}/multi_collection_view_spec.coffee +0 -0
  215. data/spec/{components/template_spec.coffee → javascripts/components/pagination_control_spec.coffee} +0 -0
  216. data/spec/{concerns/paginatable_spec.coffee → javascripts/components/record_manager_spec.coffee} +0 -0
  217. data/spec/{components → javascripts/components}/table_view_spec.coffee +0 -0
  218. data/spec/{containers/modal_view_spec.coffee → javascripts/components/template_spec.coffee} +0 -0
  219. data/spec/{concerns → javascripts/concerns}/collection_event_bindings_spec.coffee +0 -0
  220. data/spec/{concerns → javascripts/concerns}/dom_helpers_spec.coffee +0 -0
  221. data/spec/{concerns → javascripts/concerns}/filterable_spec.coffee +0 -0
  222. data/spec/{concerns → javascripts/concerns}/model_presenter_spec.coffee +0 -0
  223. data/spec/{containers/panel_view_spec.coffee → javascripts/concerns/paginatable_spec.coffee} +0 -0
  224. data/spec/{concerns → javascripts/concerns}/state_model_spec.coffee +5 -0
  225. data/spec/javascripts/containers/card_view_spec.coffee +108 -0
  226. data/spec/{containers/tab_view_spec.coffee → javascripts/containers/modal_view_spec.coffee} +0 -0
  227. data/spec/{containers/viewport_spec.coffee → javascripts/containers/panel_view_spec.coffee} +0 -0
  228. data/spec/{core/observer_spec.coffee → javascripts/containers/tab_view_spec.coffee} +0 -0
  229. data/spec/{managers/socket_manager_spec.coffee → javascripts/containers/viewport_spec.coffee} +0 -0
  230. data/spec/{core → javascripts/core}/collection_spec.coffee +1 -1
  231. data/spec/{core → javascripts/core}/concerns_spec.coffee +0 -0
  232. data/spec/{core → javascripts/core}/container_spec.coffee +0 -0
  233. data/spec/{core → javascripts/core}/define_spec.coffee +0 -0
  234. data/spec/{core → javascripts/core}/events_spec.coffee +0 -0
  235. data/spec/{core → javascripts/core}/field_spec.coffee +0 -0
  236. data/spec/{core → javascripts/core}/framework_spec.coffee +0 -0
  237. data/spec/{core → javascripts/core}/model_spec.coffee +0 -0
  238. data/spec/javascripts/core/observer_spec.coffee +0 -0
  239. data/spec/{core → javascripts/core}/util_spec.coffee +0 -0
  240. data/spec/{core → javascripts/core}/view_spec.coffee +51 -39
  241. data/spec/{dependencies → javascripts/dependencies}/index.coffee +0 -0
  242. data/spec/{dependencies → javascripts/dependencies}/jasmine-html.js +0 -0
  243. data/spec/{dependencies → javascripts/dependencies}/jasmine.js +0 -0
  244. data/spec/{dependencies → javascripts/dependencies}/sinon.js +0 -0
  245. data/spec/{helper.coffee → javascripts/helper.coffee} +0 -0
  246. data/spec/{managers → javascripts/managers}/collection_manager_spec.coffee +0 -0
  247. data/spec/javascripts/managers/socket_manager_spec.coffee +0 -0
  248. data/spec/lib/component_definition_spec.rb +63 -0
  249. data/spec/lib/input_compiler_spec.rb +9 -0
  250. data/spec/lib/luca_application_spec.rb +30 -0
  251. data/spec/support/fixtures/application.coffee +45 -0
  252. data/spec/support/fixtures/component.coffee +34 -0
  253. data/tutorials/component-definitions.md +0 -0
  254. data/tutorials/component-definitions/01_intro.md +0 -0
  255. data/tutorials/component-driven-design.md +140 -0
  256. data/tutorials/structure-of-a-project.md +63 -0
  257. data/vendor/assets/javascripts/backbone-min.js +37 -33
  258. data/vendor/assets/javascripts/backbone-query.min.js +1 -1
  259. data/vendor/assets/javascripts/hogan.js +707 -0
  260. data/vendor/assets/javascripts/jquery.js +5 -4
  261. data/vendor/assets/javascripts/keymaster.min.js +4 -0
  262. data/vendor/assets/javascripts/luca-dependencies.min.js +8 -0
  263. data/vendor/assets/javascripts/luca-development.min.js +1 -0
  264. data/vendor/assets/javascripts/luca-spec.js +6 -6
  265. data/vendor/assets/javascripts/luca-ui.js +7386 -0
  266. data/vendor/assets/javascripts/luca-ui.min.js +5 -0
  267. data/vendor/assets/javascripts/luca.full.min.js +12 -0
  268. data/vendor/assets/javascripts/luca.min.js +5 -0
  269. data/vendor/assets/javascripts/underscore-min.js +1 -5
  270. data/vendor/assets/javascripts/underscore-string.min.js +1 -1
  271. data/vendor/assets/stylesheets/luca-components.css +202 -0
  272. data/vendor/assets/stylesheets/luca-development.css +23 -0
  273. data/vendor/assets/stylesheets/luca-ui.css +198 -0
  274. metadata +324 -94
  275. data/app/assets/javascripts/luca/components/base_toolbar.coffee +0 -17
  276. data/app/assets/javascripts/luca/components/form_button_toolbar.coffee +0 -28
  277. data/app/assets/javascripts/luca/components/grid_view.coffee +0 -269
  278. data/app/assets/javascripts/luca/components/page_controller.coffee +0 -7
  279. data/app/assets/javascripts/luca/components/template.coffee +0 -5
  280. data/app/assets/javascripts/luca/components/toolbar_dialog.coffee +0 -25
  281. data/lib/luca/code_browser.rb +0 -55
  282. data/lib/luca/command_line.rb +0 -69
  283. data/lib/luca/component_documentation.rb +0 -72
  284. data/site/assets/bootstrap.min.js +0 -7
  285. data/site/assets/dependencies.js +0 -94
  286. data/site/assets/glyphicons-halflings-white.png +0 -0
  287. data/site/assets/glyphicons-halflings.png +0 -0
  288. data/site/assets/luca-ui-bootstrap.css +0 -1331
  289. data/site/assets/luca-ui-bootstrap.js +0 -9
  290. data/site/assets/luca-ui-development-tools.css +0 -234
  291. data/site/assets/luca-ui-development-tools.js +0 -18561
  292. data/site/assets/luca-ui-development-tools.min.js +0 -15
  293. data/site/assets/luca-ui-full.min.js +0 -8
  294. data/site/assets/luca-ui.min.js +0 -4
  295. data/site/assets/sandbox.css +0 -62
  296. data/site/assets/sandbox.js +0 -469
  297. data/site/docs/application.html +0 -41
  298. data/site/docs/caching.html +0 -43
  299. data/site/docs/collection.html +0 -75
  300. data/site/docs/collection_manager.html +0 -71
  301. data/site/docs/containers.html +0 -118
  302. data/site/docs/events.html +0 -153
  303. data/site/docs/view.html +0 -128
  304. data/site/img/glyphicons-halflings-white.png +0 -0
  305. data/site/img/glyphicons-halflings.png +0 -0
  306. data/site/index.html +0 -20
  307. data/site/source-map.js +0 -1
  308. data/spec/components/form_view_spec.coffee +0 -84
  309. data/spec/containers/card_view_spec.coffee +0 -50
  310. data/spec/luca-spec.coffee +0 -9
@@ -1,9 +1,51 @@
1
- # The CollectionView handles rendering a set of models from a
2
- # collection
3
- collectionView = Luca.register "Luca.components.CollectionView"
1
+ # The `Luca.CollectionView` renders models from a `Luca.Collection` into multiple
2
+ # elements, and provides methods for filtering, paginating, sorting the underlying
3
+ # collection and re-rendering the contents of its `@el` accordingly.
4
+ #
5
+ # #### Basic Example
6
+ # collectionView = Luca.register "App.views.Books"
7
+ # collectionView.extends "Luca.CollectionView"
8
+ #
9
+ # collectionView.defines
10
+ # itemProperty: "author"
11
+ # collection: new Luca.Collection([
12
+ # author: "George Orwell"
13
+ # title: "Animal Farm"
14
+ # ,
15
+ # author: "Noam Chomsky"
16
+ # title: "Manufacturing Consent"
17
+ # ])
18
+ #
19
+ # view = new App.views.Books()
20
+ # #### Extending it to make it Filterable and Paginatable
21
+ # filterable = Luca.register "App.views.FilterableBooks"
22
+ # filterable.extends "App.views.Books"
23
+ # filterable.defines
24
+ # collection: "books"
25
+ # paginatable: 12
26
+ # filterable:
27
+ # query:
28
+ # author: "George Orwell"
29
+ #
30
+ # view = new App.views.FilterableBooks()
31
+ # #### Filterable Collections
32
+ #
33
+ # The `Luca.CollectionView` will attempt to perform a local query against its
34
+ # collection which behaves like a `Backbone.QueryCollection`. It will do this
35
+ # by default without making a remote request to the API.
36
+ #
37
+ # If you do not want this behavior, you can configure the `Luca.CollectionView` to
38
+ # behave as if the filtering was happen remotely in your REST API.
39
+ #
40
+ # filterable:
41
+ # options:
42
+ # remote: true
43
+ collectionView = Luca.register "Luca.CollectionView"
4
44
 
5
45
  collectionView.extends "Luca.Panel"
6
46
 
47
+ collectionView.replaces "Luca.components.CollectionView"
48
+
7
49
  collectionView.mixesIn "QueryCollectionBindings",
8
50
  "LoadMaskable",
9
51
  "Filterable",
@@ -15,36 +57,46 @@ collectionView.triggers "before:refresh",
15
57
  "refresh",
16
58
  "empty:results"
17
59
 
18
- # IDEA:
19
- #
20
- # For validation of component configuration,
21
- # we could define a convention like:
22
- #
23
- # collectionView.validatesConfigurationWith
24
- # requiresValidCollectionAt: "collection"
25
- # requiresPresenceOf:
26
- # either: ["itemTemplate", "itemRenderer", "itemProperty"]
27
- #
28
- #
29
60
  collectionView.publicConfiguration
61
+ # Specify which collection will be used to supply the models to be rendered.
62
+ # Accepts either a string alias for the Collection class, or an instance of
63
+ # any class which inherits from Backbone.Collection
64
+ collection: undefined
65
+
66
+ # By default the CollectionView will be rendered inside of an OL tag.
30
67
  tagName: "ol"
68
+
69
+ # The CollectionView behaves as a Luca.Panel which means it has an area for
70
+ # top and bottom toolbars. The actual content that gets rendered from the
71
+ # collection will be rendered inside an element with the specified class.
31
72
  bodyClassName: "collection-ui-panel"
73
+
74
+ # Each item from the collection will be rendered inside of an element specified by @itemTagName
32
75
  itemTagName: 'li'
76
+
77
+ # Each item element will be assigned a CSS class specified by @itemClassName
33
78
  itemClassName: 'collection-item'
79
+
80
+ # Specify which template should be used to render each item in the collection.
81
+ # Accepts a string which will be passed to Luca.template(@itemTemplate). Your template
82
+ # can expect to be passed an object with the `model` and `index` properties on it.
34
83
  itemTemplate: undefined
84
+
85
+ # Accepts a reference to a function, which will be called with an object with the `model` and `index`
86
+ # properties on it. This function should return a String which will be injected into the item DOM element.
35
87
  itemRenderer: undefined
88
+
89
+ # Plucks the specified property from the model and inserts it into the item DOM element.
36
90
  itemProperty: undefined
37
91
 
38
- collectionView.defines
92
+ # If @observeChanges is set to true, any change in an underlying model will automatically be re-rendered.
93
+ observeChanges: false
94
+
95
+ collectionView.publicMethods
39
96
  initialize: (@options={})->
40
97
  _.extend(@, @options)
41
98
  _.bindAll @, "refresh"
42
99
 
43
- # IDEA:
44
- #
45
- # This type of code could be moved into a re-usable concern
46
- # which higher order components can mixin to make it easier
47
- # to extend them, instantiate them, etc.
48
100
  unless @collection? or @options.collection
49
101
  console.log "Error on initialize of collection view", @
50
102
  throw "Collection Views must specify a collection"
@@ -62,9 +114,10 @@ collectionView.defines
62
114
  console.log "Missing Collection on #{ @name || @cid }", @, @collection
63
115
  throw "Collection Views must have a valid backbone collection"
64
116
 
117
+ # INVESTIGATE THIS BEING DOUBLE WORK
65
118
  @on "data:refresh", @refresh, @
66
-
67
119
  @on "collection:reset", @refresh, @
120
+
68
121
  @on "collection:remove", @refresh, @
69
122
  @on "collection:add", @refresh, @
70
123
  @on "collection:change", @refreshModel, @ if @observeChanges is true
@@ -77,10 +130,46 @@ collectionView.defines
77
130
  view.refresh()
78
131
  view.unbind "after:render", @
79
132
 
133
+ # Given the id of a model, find the underlying DOM element which was rendered by this collection.
134
+ # Assumes that the data-model-id attribute is set, which it is by default by @attributesForItem.
135
+ locateItemElement: (id)->
136
+ @$(".#{ @itemClassName }[data-model-id='#{ id }']")
137
+
138
+ # Refresh is responsible for applying any filtering, pagination, or sorting options that may be set
139
+ # from the various Luca.concerns mixed in by `Luca.CollectionView` and making a query to the underlying
140
+ # collection. It will then take the set of models returned by `@getModels` and pass them through the
141
+ # item rendering pipeline.
142
+ refresh: ()->
143
+ query = @getLocalQuery()
144
+ options = @getQueryOptions()
145
+ models = @getModels(query, options)
146
+
147
+ @$bodyEl().empty()
148
+
149
+ @trigger("before:refresh", models, query, options)
150
+
151
+ if models.length is 0
152
+ @trigger("empty:results", query, options)
153
+
154
+ @renderModels(models, query, options)
155
+
156
+ @trigger("after:refresh", models, query, options)
157
+
158
+ @
159
+
80
160
 
161
+ collectionView.privateMethods
162
+ renderModels: (models, query, options)->
163
+ index = 0
164
+ for model in models
165
+ @$append @makeItem(model, index++)
166
+
167
+ # Determines which attributes should be set on the item DOM element.
81
168
  attributesForItem: (item, model)->
82
169
  _.extend {}, class: @itemClassName, "data-index": item.index, "data-model-id": item.model.get('id')
83
170
 
171
+ # Determines the content for the item DOM element. Will use the appropriate options
172
+ # specified by `@itemTemplate`, `@itemRenderer`, or `@itemProperty`
84
173
  contentForItem: (item={})->
85
174
  if @itemTemplate? and templateFn = Luca.template(@itemTemplate)
86
175
  return content = templateFn.call(@, item)
@@ -93,45 +182,23 @@ collectionView.defines
93
182
 
94
183
  ""
95
184
 
185
+ # Uses the various options passed to the `CollectionView` to assemble a call to `Luca.View::make`.
96
186
  makeItem: (model, index)->
97
187
  item = if @prepareItem? then @prepareItem.call(@, model, index) else (model:model, index: index)
98
188
  attributes = @attributesForItem(item, model)
99
189
  content = @contentForItem(item)
100
- # TEMP
101
- # Figure out why calls to make are failing with an unexpected string error
190
+
102
191
  try
103
- make(@itemTagName, attributes, content)
192
+ Luca.View::make(@itemTagName, attributes, content)
104
193
  catch e
105
194
  console.log "Error generating DOM element for CollectionView", @, model, index
106
- #no op
107
-
108
- locateItemElement: (id)->
109
- @$(".#{ @itemClassName }[data-model-id='#{ id }']")
110
195
 
196
+ # Given a model, attempt to re-render the contents of its item in this view's DOM contents.
111
197
  refreshModel: (model)->
112
198
  index = @collection.indexOf( model )
113
199
  @locateItemElement(model.get('id')).empty().append( @contentForItem({model,index}, model) )
114
200
  @trigger("model:refreshed", index, model)
115
201
 
116
- refresh: (query,options,models)->
117
- query ||= @getQuery()
118
- options ||= @getQueryOptions()
119
- models ||= @getModels(query, options)
120
-
121
- @$bodyEl().empty()
122
-
123
- @trigger("before:refresh", models, query, options)
124
-
125
- if models.length is 0
126
- @trigger("empty:results")
127
-
128
- index = 0
129
- for model in models
130
- @$append @makeItem(model, index++)
131
-
132
- @trigger("after:refresh", models, query, options)
133
-
134
- @
135
202
 
136
203
  registerEvent: (domEvent, selector, handler)->
137
204
  if !handler? and _.isFunction(selector)
@@ -141,7 +208,4 @@ collectionView.defines
141
208
  eventTrigger = _([domEvent,"#{ @itemTagName }.#{ @itemClassName }", selector]).compact().join(" ")
142
209
  Luca.View::registerEvent(eventTrigger,handler)
143
210
 
144
- # Private Helpers
145
-
146
-
147
- make = Luca.View::make
211
+ collectionView.register()
@@ -1,30 +1,108 @@
1
+ # The Controller is a special type of CardView that is used to provide structure to a Luca.Application. Each
2
+ # component in the controller is expected to have a unique `@name` property. The Application's router configuration
3
+ # will map URL / Hashbangs to the `@name`s of components that belong to the Application controller.
4
+ #
5
+ # Applications which structure their 'pages' in controllers, or sections, will have the names of which
6
+ # section or page is active inside of its state model. One example / common application structure we see:
7
+ #
8
+ # application:
9
+ # main_controller:
10
+ # controller / section_one:
11
+ # page_one
12
+ # page_two
13
+ # page_three
14
+ # controller / section_two
15
+ # page_alpha
16
+ # page_bravo
17
+ #
18
+ # In the above example, the Application would attempt to route to page_one, and the state
19
+ # of the application may look like:
20
+ #
21
+ # application.activeSection() #=> 'section_one'
22
+ # application.activeSubSection() # => 'page_one'
23
+ # application.activePage() # => page_one
24
+ #
1
25
  controller = Luca.register "Luca.components.Controller"
2
26
  controller.extends "Luca.containers.CardView"
3
27
 
4
- controller.publicInterface
28
+ controller.publicConfiguration
29
+ # If there is an active application, we will attempt to
30
+ # set the name of our currently activated page on the application's
31
+ # state machine. The attribute we will set can be configured by setting this value.
32
+ tracker: "page"
33
+
34
+ # We will set the name of the active page / section on our DOM element
35
+ # The attribute we will set can be configured by setting this.
36
+ activeAttribute: "active-section"
37
+ stateful: true
38
+ defaultPage: undefined
39
+ defaultCard: 0
40
+
41
+ controller.publicMethods
42
+ # Navigate to the default ( or first ) component on this controller.
43
+ # This will automatically get called upon rendering, so that it sets up
44
+ # the proper state tracking, event binding, etc.
5
45
  default: (callback)->
6
46
  @navigate_to(@defaultPage || @defaultCard, callback)
7
47
 
48
+ # Returns the name of the component which is currently active
49
+ # on this controller.
8
50
  activePage: ()->
9
51
  @activeSection()
10
52
 
11
- navigate_to: (section, callback)->
12
- section ||= @defaultCard
53
+ # Navigate to a page on this controller by name. If passed an optional
54
+ # callback, the callback will be called within the context of the activated page.
55
+ navigate_to: (page, callback)->
56
+ page ||= @defaultCard
13
57
 
14
- @activate section, false, (activator, previous,current)=>
15
- unless current.activatedByController is true
58
+ @activate page, false, (activator, previous,current)=>
59
+ if current.activatedByController is true
60
+ current.trigger("on:controller:reactivation")
61
+ else
16
62
  current.trigger("on:controller:activation")
17
63
  current.activatedByController = true
18
64
 
19
65
  @state.set(active_section: current.name )
20
66
 
67
+ if @tracker? and app = @app || Luca.getApplication?()
68
+ app.state.set(@tracker, current.name)
69
+
70
+ Luca.key?.setScope( current.name )
71
+
21
72
  if _.isFunction( callback )
22
73
  callback.call(current)
23
74
 
24
- # return the section we are navigating to
25
- @find(section)
75
+ # return the component we are navigating to
76
+ @find(page)
26
77
 
27
78
  controller.classMethods
79
+ # For each component we control, if there is a keyEvents property defined
80
+ # then we will define a keymaster scope for that component's name, and setup
81
+ # bindings as directed. This is important because each time a controller
82
+ # activates a component, that component will attempt to change the scope of
83
+ # the keymaster so that components becomes responsible for handling detected key events.
84
+ setupComponentKeyEvents: ()->
85
+ @_().each (component)->
86
+ if _.isObject(component.keyEvents) and component.name?
87
+ Luca.util.setupKeymaster(component.keyEvents, component.name).on(component)
88
+
89
+ # The Controller Path is an array of the names of the controllers
90
+ # a given component belongs to. This method will get patched on to each
91
+ # component that belongs to a controller. It will always be bound to the instance
92
+ # of the component itself. Example:
93
+ #
94
+ # application.contains
95
+ # name: "main_controller"
96
+ # components: [
97
+ # name: "sub_controller"
98
+ # components:[
99
+ # name: "page"
100
+ # ]
101
+ # ]
102
+ #
103
+ # The @controllerPath() method for the component named page would be ['sub_controller','page'].
104
+ # This will be used internally by the Application route builder, so that each of page's parent
105
+ # controllers are activated in the proper order needed to make page visible.
28
106
  controllerPath: ()->
29
107
  component = @
30
108
 
@@ -42,9 +120,6 @@ controller.afterDefinition ()->
42
120
  Luca.View::hooks.push "on:controller:activation"
43
121
 
44
122
  controller.defines
45
- additionalClassNames: 'luca-ui-controller'
46
- activeAttribute: "active-section"
47
- stateful: true
48
123
 
49
124
  initialize: (@options)->
50
125
  # let's phase out the 'card' terminology
@@ -63,6 +138,7 @@ controller.defines
63
138
  component.controllerPath = Luca.components.Controller.controllerPath
64
139
 
65
140
  @on "after:render", @default, @
141
+ @on "before:render", Luca.components.Controller.setupComponentKeyEvents, @
66
142
 
67
143
  each: (fn)->
68
144
  _( @components ).each (component)=> fn.call(@,component)
@@ -82,6 +158,7 @@ controller.defines
82
158
  @availableSections.apply(@, arguments)
83
159
 
84
160
  availableSections: ()->
161
+ console.log "The availableSections()/availablePages() method will be removed in 1.0"
85
162
  base = {}
86
163
  base[ @name ] = @sectionNames()
87
164
 
@@ -1,3 +1,9 @@
1
+ # The `Luca.core.Field` is an abstract base class for field components
2
+ # which are used in the `Luca.components.FormView`. They provide common
3
+ # functionality like getValue, setValue, change and validation event bindings.
4
+ #
5
+ # Additionally, the field component provides common Twitter Bootstrap styling
6
+ # hooks, such as error, warning, and success status flagging.
1
7
  field = Luca.register "Luca.core.Field"
2
8
 
3
9
  field.extends "Luca.View"
@@ -6,25 +12,85 @@ field.triggers "before:validation",
6
12
  "after:validation",
7
13
  "on:change"
8
14
 
9
- field.publicConfiguration
15
+ field.publicConfiguration
16
+ className: 'luca-ui-field'
17
+
18
+ # Controls whether or not this field is rendered in a disabled state
19
+ disabled: undefined
20
+
21
+ # Controls the bootstrap helperText value for this field control
22
+ helperText: undefined
23
+
24
+ # Text value for the label element that goes along with this field control
25
+ label: undefined
26
+
27
+ # Controls the positioning of the label element. Valid options are
28
+ # 'top', 'left'. For any other custom display you can control this
29
+ # on your own by specifying a template
10
30
  labelAlign: 'top'
11
- className: 'luca-ui-text-field luca-ui-field'
31
+
32
+ # Controls the value displayed in this field when it is in an untouched state
33
+ # by the user. Uses the html5 placeholder attribute
34
+ placeHolder: undefined
35
+
36
+ # Controls whether or not we want to display visual indicator
37
+ # that this field is required.
38
+ required: undefined
39
+
40
+ # Which statuses can be applied to this field? Valid options are taken
41
+ # from bootstrap state styling.
12
42
  statuses: [
13
43
  "warning"
14
44
  "error"
15
45
  "success"
16
46
  ]
17
47
 
18
- field.publicInterface
48
+ # What is the type of value that this field
49
+ # should have? You can use this to coerce the `getValue()` type
50
+ # into an integer, string, or float.
51
+ valueType: "string"
52
+
53
+
54
+
55
+ field.publicMethods
56
+ # Disable this field
19
57
  disable: ()->
20
58
  @getInputElement().attr('disabled', true)
21
59
 
60
+ # Enable this field
22
61
  enable: ()->
23
62
  @getInputElement().attr('disabled', false)
24
63
 
64
+ # Gets the value from the input element in this field control
25
65
  getValue: ()->
26
- raw = @getInputElement()?.attr('value')
66
+ raw = @getInputElement()?.val()
67
+ @getParsedValue(raw)
68
+
69
+ # Sets the value on the input element inside this field control
70
+ setValue: (value)->
71
+ @getInputElement()?.val(value)
72
+
73
+ # Update the state of this field. Valid options are defined on
74
+ # this fields `@statuses` property
75
+ updateState: (state)->
76
+ for cssClass in @statuses
77
+ @$el.removeClass(cssClass)
78
+
79
+ @$el.addClass(state)
80
+
81
+ # Remove any visual error indications from this field control
82
+ clearErrors: ()->
83
+ @$el.removeClass('error')
84
+
85
+ # Display a visual error state on this field
86
+ displayErrors: (errors)->
87
+ @updateState('error')
27
88
 
89
+ field.privateMethods
90
+ # Runs the value from the underlying input element
91
+ # through a type conversion process configured by
92
+ # the `@valueType` field
93
+ getParsedValue: (raw)->
28
94
  return raw if _.str.isBlank( raw )
29
95
 
30
96
  switch @valueType
@@ -33,19 +99,12 @@ field.publicInterface
33
99
  when "float" then parseFloat(raw)
34
100
  else raw
35
101
 
36
- setValue: (value)->
37
- @getInputElement()?.attr('value', value)
38
-
39
- updateState: (state)->
40
- _( @statuses ).each (cls)=>
41
- @$el.removeClass(cls)
42
- @$el.addClass(state)
43
-
44
102
  field.privateConfiguration
103
+ # A convenience method for identifying field components
45
104
  isField: true
46
105
  template: 'fields/text_field'
47
106
 
48
- field.defines
107
+ field.privateMethods
49
108
  initialize: (@options={})->
50
109
  _.extend @, @options
51
110
 
@@ -81,3 +140,5 @@ field.defines
81
140
 
82
141
  getInputElement: ()->
83
142
  @input ||= @$('input').eq(0)
143
+
144
+ field.register()