luca 0.9.8 → 0.9.9

Sign up to get free protection for your applications and to get access to all the features.
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
data/site/docs/view.html DELETED
@@ -1,128 +0,0 @@
1
- <h1>Luca.View</h1>
2
- <p>The <code>Luca.View</code> class is the base class for Luca components. A number of patterns and optimizations that are helpful in your view classes have been extracted into the base class.
3
-
4
- </p>
5
- <h2>Hooks</h2>
6
- <p>The concept of hooks in Luca is that components can trigger events, and we can bind to them as normally, and that this is good. However, where it is more useful or cleaner to just define methods that represent some part of the component lifecycle, we provide a configuration API for doing that.
7
-
8
- </p>
9
- <pre><code class="lang-coffeescript"> _.def("Luca.View").extends("Backbone.View").with
10
- hooks:[
11
- "after:initialize" # =&gt; @afterInitialize
12
- "before:render" # =&gt; @beforeRender
13
- "after:render" # =&gt; @afterRender
14
- "first:activation" # =&gt; @firstActivation
15
- "activation" # =&gt; @activation
16
- "deactivation" # =&gt; @deactivation
17
- ]</code></pre>
18
- <p>Any Luca.View which defines an <code>@afterInitialize</code> method, or a <code>@beforeRender</code> method, will automatically call that method when the corresponding event is triggered.
19
-
20
- </p>
21
- <p><strong>Note on extending hook methods</strong>
22
-
23
- </p>
24
- <p>If you want to maintain the functionality of the component you are extending from, you will have to remember to call the prototype method like such:
25
-
26
- </p>
27
- <pre><code class="lang-coffeescript"> _.def("MyView").extends("Luca.View").with
28
- beforeRender: ()-&gt;
29
- @_super("beforeRender", @, arguments)
30
-
31
- # or, if you prefer
32
- Luca.View::beforeRender?.apply(@, arguments)</code></pre>
33
- <h2>The @render() method</h2>
34
- <p>The default implementation of @render() simply appends the view's <code>@$el</code> to the DOM element represented by the <code>$(@container)</code> property on the view.
35
-
36
- </p>
37
- <p>Whatever method you choose to implement for your <code>@render()</code> call should behave similar to how the Backbone.View::render() expects, in that it should return an instance of the view.
38
-
39
- </p>
40
- <p>Additionally, the call to <code>@render()</code> will trigger <code>before:render</code> and <code>after:render</code> as which, on a Luca.View is configured as a hook. So any <code>@beforeRender()</code> and <code>@afterRender()</code> method will get called as well, if they exist.
41
-
42
- </p>
43
- <h2>Before Render</h2>
44
- <p>Since in Luca, the actual render method just attaches the view to its container, setup related methods for building your view's content are best put in the <code>beforeRender()</code> method. In addition to this, there are other options available for filling the content of the view, like <code>@bodyTemplate</code>.
45
-
46
- </p>
47
- <h2>Luca.template helper</h2>
48
- <p><code>Luca.template()</code> is a util function which allows you reference your client side template system. It accepts a name of a template ( which, if not found, it will attempt to match one for you ) and an object of interpolations to pass to the template function
49
-
50
- </p>
51
- <p><code>Luca.available_templates()</code> is a util function, useful for debugging, to see which templates are available to you.
52
-
53
- </p>
54
- <h2>Configuration Options</h2>
55
- <ul>
56
- <li><p><code>@additionalClassNames</code> - an array of CSS classes to apply to the view's <code>@$el</code>. This is helpful for inheritance of views.</p>
57
- </li>
58
- <li><p><code>@name</code> - Setting a name property on your view, will allow you to reference the instance of that view later.</p>
59
- </li>
60
- </ul>
61
- <pre><code class="lang-coffeescript"> view = new Luca.View(name:"my_view")
62
-
63
- Luca("my_view") is view # =&gt; true</code></pre>
64
- <ul>
65
- <li><p><code>@wrapperClass</code> - automatically wraps the view with a div with this as the CSS class.</p>
66
- </li>
67
- <li><p><code>@bodyTemplate</code> - will apply the content of the template to your view </p>
68
- </li>
69
- <li><p><code>@bindAllEvents</code> - true or false automatically bind all event handler methods to the context of your view's instance</p>
70
- </li>
71
- <li><p><code>@applicationEvents</code> - configuration similar to the DOM <code>@events</code> configuration on Backbone.View. Used to bind to events triggered by the <code>Luca.Application.get()</code> object. You can customize which application you use by setting <code>@app</code> to either reference the app, or to the name of a given application.</p>
72
- </li>
73
- <li><p><code>@collectionEvents</code> - configuration similar to the DOM <code>@events</code> configuration on Backbone.View. Used to bind to events triggered by the <code>Luca.CollectionManager.get()</code> object. </p>
74
- </li>
75
- </ul>
76
- <h2>Luca.View::$bodyEl()</h2>
77
- <p>In your <code>Luca.View</code> definitions, If you set the <code>@bodyTemplate</code> property to one of the available templates, then on <code>initialize</code> the view will set the HTML of its DOM element to the contents of the template.
78
-
79
- </p>
80
- <p>This is useful in cases where there is a fair amount of structural, or otherwise static DOM content in your view, and one of the standard <code>Luca.core.Container</code> components is not suited for what you want to do. The <code>Luca.components.Panel</code> view is basically just a <code>Luca.View</code> which has additional DOM containers for footers and headers. It accomplishes this through the use of the <code>@bodyClassName</code> and <code>@bodyTagName</code> properties.
81
-
82
- </p>
83
- <p><code>@bodyClassName</code> and <code>@bodyTagName</code> work the same way the <code>@className</code> and <code>@tagName</code> properties work on standard Backbone views. They are used to create a DOM element via <code>Backbone.View.prototype.make(@bodyTagName,class:@bodyClassName,id:@bodyId</code>
84
-
85
- </p>
86
- <p>If you use <code>view.$bodyEl()</code> instead of the standard <code>view.$el()</code> that ships with Backbone, all of the standard DOM manipulation methods available will be scoped to the CSS selector that corresponds to the actual body element of your view.
87
-
88
- </p>
89
- <h2>Deferrable Rendering</h2>
90
- <p>The jury is still out as to whether or not deferrable rendering is a useful pattern, or whether it is too complex. The use case it was trying to optimize is for views which can only be rendered in response to an event being fired on another object. Such as <code>Backbone.Collection::fetch</code>.
91
-
92
- </p>
93
- <p>If this is what you are doing, then this feature is for you.
94
-
95
- </p>
96
- <p>The options available for views which use the <code>@deferrable</code> property are as follows:
97
-
98
- </p>
99
- <ul>
100
- <li><code>@deferrable</code> - if you set a reference to an object, such as a collection, on the @deferrable property, then the call to <code>view.render()</code> will actually just set up an event binding to the <code>reset</code> event of your collection, and it will automatically call <code>fetch</code> for you on that collection. </li>
101
- </ul>
102
- <p>If you set <code>@deferrable</code> to true then the view will expect a <code>@collection</code> property.
103
-
104
- </p>
105
- <ul>
106
- <li><p><code>@deferrable_method</code> - a call to <code>@render()</code> on a <code>@deferrable</code> view will automatically call this method on the <code>@deferrable</code> object.</p>
107
- </li>
108
- <li><p><code>@deferrable_trigger</code> - if you use the deferrable system , by default, it will automatically call the <code>@deferrable_method</code> on your <code>@deferrable</code> object when you call <code>@render()</code>. However, if you want to defer this method being fired even later, just set the <code>@deferrable_trigger</code> property to whatever trigger your view will listen for.</p>
109
- </li>
110
- </ul>
111
- <p>A useful example would be for views which get rendered hidden, and activated if and only if the user does a specific action. ( For example, a TabView activating a secondary tab ). If that action triggers an event, and you want to delay the render process if and only if that event is triggered.
112
-
113
- </p>
114
- <h2>Helpers</h2>
115
- <ul>
116
- <li><p><code>view.$template</code> calls <code>view.$.html()</code> on your view, with whatever is returned from the template. Delegates to <code>Luca.template(templateName, customizationHash)</code></p>
117
- </li>
118
- <li><p><code>view.$wrap</code> the same as <code>view.$el.wrap()</code> -- accepts a CSS class name string, or a DOM element</p>
119
- </li>
120
- <li><p><code>view.$append</code> the same as <code>view.$el.append()</code></p>
121
- </li>
122
- <li><p><code>view.$container</code> - references <code>$( view.container )</code>. Note: the @container property is set on a view when it belongs to the <code>@components</code> property of a <code>Luca.core.Container</code> instance. It is just a standard CSS selector.</p>
123
- </li>
124
- <li><p><code>view.registerEvent()</code> manipulates your <code>@events</code> configuration on your Backbone.View and then calls <code>@delegateEvents</code> to make sure they are live.</p>
125
- </li>
126
- </ul>
127
- <h2>Backbone Component Helpers</h2>
128
- <p>Views which have properties on them referencing other views, models, or collections, can access those objects by calling <code>view.models()</code> or <code>view.views()</code> or <code>view.collections()</code>. This is mainly useful for introspection, debugging, or what not.</p>
Binary file
data/site/index.html DELETED
@@ -1,20 +0,0 @@
1
- <!doctype html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="utf-8">
5
- <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
6
- <title>Luca. Container Framework For Backbone Views</title>
7
- <meta name="viewport" content="width=device-width,initial-scale=1">
8
- <link rel="stylesheet" href="assets/luca-ui-bootstrap.css">
9
- <link rel="stylesheet" href="assets/luca-ui-development-tools.css">
10
- <link rel="stylesheet" href="assets/sandbox.css">
11
- </head>
12
- <body>
13
- <div id="viewport"></div>
14
- <script src="assets/dependencies.js"></script>
15
- <script src="assets/bootstrap.min.js"></script>
16
- <script src="assets/luca-ui.min.js"></script>
17
- <script src="assets/luca-ui-development-tools.min.js"></script>
18
- <script src="assets/sandbox.js"></script>
19
- </body>
20
- </html>
data/site/source-map.js DELETED
@@ -1 +0,0 @@
1
- [{"className":"Luca.Application","file":"src/components/application.coffee","source":"# Luca.Application \n#\n# The Application class is the global state tracking mechanism\n# for your single page application, as well as the entry point.\n#\n# By default it contains a main controller which is a Luca.components.Controller instance. \n#\n# In a typical Luca application, the router will use the applications @navigate_to() method to switch\n# from page to page on the main controller, or any other controllers nested inside of it.\n#\n# You would control flow when the controller fires activation events on the nested view components inside of it.\n#\n# Decoupling application control flow from the URL Fragment from Backbone.History and preventing\n# your components from directly caring about the URL Fragment, allows you to build applications as\n# isolated components which can run separately or nested inside of other applications. \n\nstartHistory = ()-> Backbone.history.start()\n\n_.def('Luca.Application').extends('Luca.containers.Viewport').with\n name: \"MyApp\"\n\n # The Application uses a Backbone.Model as a state machine, which\n # allows you to get / set attributes, persist them somewhere, and\n # most importantly to bind to change events of certain attributes.\n #\n # the @defaultState property will be the default attributes\n defaultState: {}\n\n # if autoBoot is set to true, the application will \n # attempt to boot on document ready.\n autoBoot: false\n\n # automatically starts the @router if it exists, \n # once the components for the application have \n # been created. Pass the event name you want to\n # listen for on this component before you start history\n autoStartHistory: \"before:render\"\n\n # we will create a collection manager singleton\n # by default unless otherwise specified. \n useCollectionManager: true\n\n # to pass options to the collection manager, set the @collectionManager\n # hash which will get passed once the collection manager is created\n collectionManager: {}\n\n # by default we will use the standard collection manager which ships with\n # Luca. If you would like to use your own extension of the collection manager\n # just pass a reference to the class you would like to use. \n collectionManagerClass: \"Luca.CollectionManager\"\n\n # Luca plugin apps are apps which mount onto existing\n # luca apps, and will not have the behavior of a main\n # app which acts as a singleton\n plugin: false\n\n # by default, the application will use a controller\n # component, which is a card view container which shows\n # one view at a time. this is useful for having an application\n # with several 'pages' so to speak\n useController: true\n\n # Key Handler\n # \n # One responsibility of the application, since it is a viewport which monopolizes the entire screen\n # is to relay keypress events from the document, to whatever views are interested in responding to them.\n #\n # This functionality is disabled by default.\n useKeyHandler: false\n\n # You can configure key events by specifying them by their name, as it exists in Luca.keyMap. For example:\n #\n # keyEvents\n # keyup: keyUpHandler\n # enter: enterHandler\n # meta:\n # up: metaUpHandler\n # control:\n # forwardslash: controlSlashHandler\n # keyup: controlUpHandler\n # control_meta:\n # keydown: metaControlKeyDownHandler\n #\n keyEvents: {} \n\n # applications have one component, the controller.\n # any components defined on the application class directly\n # will get wrapped by the main controller unless you\n # set useController = false\n components:[\n ctype: 'template'\n name: 'welcome'\n template: 'sample/welcome'\n templateContainer: \"Luca.templates\"\n ]\n\n initialize: (@options={})->\n app = @\n appName = @name\n alreadyRunning = Luca.getApplication?()\n\n Luca.Application.instances ||= {}\n Luca.Application.instances[ appName ] = app\n \n Luca.containers.Viewport::initialize.apply @, arguments\n\n @state = new Luca.Model( @defaultState )\n\n # The Controller is the piece of the application that handles showing\n # and hiding 'pages' of the app. The Application has a navigate_to\n # method which delegates to the controller, and allows you to navigate\n # to a given page, or component, by its name. The controller integrates\n # with the state machine of the application\n @setupMainController()\n\n # The Collection Manager is responsible \n @setupCollectionManager()\n\n # we will render when all of the various components\n # which handle our data dependencies determine that\n # we are ready\n @defer(()-> app.render()).until(@, \"ready\")\n\n # Set up the Backbone Router\n @setupRouter()\n\n # the keyHandler allows us to specify\n # keyEvents on our application with an API very similar\n # to the DOM events API for Backbone.View\n #\n # Example:\n #\n # keyEvents:\n # meta:\n # forwardslash: \"altSlashHandler\"\n console.log \"The useKeyRouter property is being deprecated. switch to useKeyHandler instead\"\n \n @setupKeyHandler() if (@useKeyHandler is true or @useKeyRouter is true) and @keyEvents?\n\n # if the application is a plugin designed to modify the behavior\n # of another app, then don't claim ownership. otherwise the most common\n # use-case is that there will be one application instance\n unless @plugin is true or alreadyRunning\n Luca.getApplication = (name)=> \n return app unless name?\n Luca.Application.instances[ name ] \n\n if @autoBoot\n if Luca.util.resolve(@name)\n throw \"Attempting to override window.#{ @name } when it already exists\"\n\n $ ->\n window[ appName ] = app \n app.boot()\n\n # @activeView() returns a reference to the instance of the view\n # which is currently monopolizing the viewport.\n #\n # this will be whicever component is active on the controllers\n # nested within the main controller, if there are any, or the view\n # itself which is active on the main controller. \n activeView: ()->\n if active = @activeSubSection()\n @view( active )\n else\n @view( @activeSection() )\n\n # Returns the name of the active component on the main controller \n activeSection: ()->\n @get(\"active_section\")\n\n # Returns the name of the active component on the nested controllers\n # on the main controller, if there is one. These get set on the\n # state machine in response to card switch events on the controller component\n activeSubSection: ()->\n @get(\"active_sub_section\")\n\n activePages: ()->\n @$('.luca-ui-controller').map (index,element)=> $(element).data('active-section')\n\n # boot should trigger the ready event, which will call the initial call\n # to render() your application, which will have a cascading effect on every\n # subcomponent in the view, recursively rendering everything which is set\n # to automatically render (i.e. any non-deferrable components ).\n #\n # you should use boot to fire up any dependent collections, manager, any\n # sort of data processing, whatever your application requires to run outside\n # of the views\n boot: ()->\n @trigger \"ready\"\n\n # delegate to the collection manager's get or create function.\n # use App.collection() to create or access existing collections\n collection: ()->\n @collectionManager.getOrCreate.apply(@collectionManager, arguments)\n\n get: (attribute)->\n @state.get(attribute)\n\n set: (attribute, value, options)->\n @state.set.apply(@state, arguments)\n\n view: (name)->\n Luca.cache(name)\n\n #### Navigation Hooks\n #\n # delegate to the main controller so that we can switch the active section\n navigate_to: (component_name, callback)->\n @getMainController().navigate_to(component_name, callback)\n\n getMainController: ()->\n return @components[0] if @useController is true\n Luca.cache('main_controller')\n\n # \n keyHandler: (e)->\n return unless e and @keyEvents\n\n isInputEvent = $(e.target).is('input') || $(e.target).is('textarea')\n\n return if isInputEvent\n\n keyname = Luca.keyMap[ e.keyCode ]\n\n return unless keyname\n\n meta = e?.metaKey is true\n control = e?.ctrlKey is true\n\n source = @keyEvents\n source = if meta then @keyEvents.meta else source\n source = if control then @keyEvents.control else source\n source = if meta and control then @keyEvents.meta_control else source\n\n if keyEvent = source?[keyname]\n if @[keyEvent]?\n @[keyEvent]?.call(@)\n else\n @trigger(keyEvent)\n\n setupControllerBindings: ()->\n # any time the main controller card switches we should track\n # the active card on the global state chart\n @getMainController()?.bind \"after:card:switch\", (previous,current)=>\n @state.set(active_section:current.name)\n\n # any time the card switches on one of the sub controllers\n # then we should track the active sub section on the global state chart\n @getMainController()?.each (component)=>\n if component.ctype.match(/controller$/)\n component.bind \"after:card:switch\", (previous,current)=>\n @state.set(active_sub_section:current.name) \n\n setupMainController: ()->\n if @useController is true\n definedComponents = @components || []\n\n @components = [\n ctype: 'controller'\n name: \"main_controller\"\n components: definedComponents\n ]\n\n @defer( @setupControllerBindings, false ).until(\"after:components\")\n\n setupCollectionManager: ()->\n if @useCollectionManager is true\n @collectionManagerClass = Luca.util.resolve( @collectionManagerClass ) if _.isString( @collectionManagerClass )\n\n collectionManagerOptions = @collectionManagerOptions\n\n if _.isObject(@collectionManager) and not _.isFunction( @collectionManager?.get )\n collectionManagerOptions = @collectionManager\n @collectionManager = undefined\n\n if _.isString(@collectionManager)\n collectionManagerOptions = \n name: @collectionManager\n\n @collectionManager = Luca.CollectionManager.get?( collectionManagerOptions.name )\n\n unless _.isFunction(@collectionManager?.get)\n @collectionManager = new @collectionManagerClass( collectionManagerOptions ) \n\n setupRouter: ()->\n app = @\n\n if _.isString( @router )\n routerClass = Luca.util.resolve(@router)\n @router = new routerClass({app})\n\n # if this application has a router associated with it\n # then we need to start backbone history on a certain event.\n # you can control which by setting the @startHistoryOn property\n if @router and @autoStartHistory\n @autoStartHistory = \"before:render\" if @autoStartHistory is true\n @defer(startHistory, false).until(@, @autoStartHistory) \n\n setupKeyHandler: ()->\n return unless @keyEvents\n\n @keyEvents.control_meta ||= {}\n\n # allow for both meta_control, control_meta for the combo\n _.extend(@keyEvents.control_meta, @keyEvents.meta_control) if @keyEvents.meta_control\n\n handler = _.bind(@keyHandler, @)\n\n $( document ).keydown( handler )\n\n"},{"className":"Luca.components.Toolbar","file":"src/components/base_toolbar.coffee","source":"_.def('Luca.components.Toolbar').extends('Luca.core.Container').with\n\n className: 'luca-ui-toolbar'\n\n position: 'bottom'\n\n initialize: (@options={})->\n Luca.core.Container::initialize.apply @, arguments\n\n prepareComponents: ()->\n _( @components ).each (component)=>\n component.container = @$el\n\n render: ()->\n $(@container).append(@el)"},{"className":"Luca.components.CollectionLoaderView","file":"src/components/collection_loader_view.coffee","source":"# Collection Loader View is a simple modal view\n# You can provide your own template for the collection loader modal\n# if you want to. Default implementation uses twitter bootstrap modal and\n# progress bar (http://twitter.github.com/bootstrap/). You template\n# should contain `progress`, `bar` and `message` classes\n_.def('Luca.components.CollectionLoaderView').extends('Luca.components.Template').with\n\n className: 'luca-ui-collection-loader-view'\n\n template: \"components/collection_loader_view\"\n\n initialize: (@options={})->\n Luca.components.Template::initialize.apply @,arguments\n\n @container ||= $('body')\n @manager ||= Luca.CollectionManager.get()\n\n @setupBindings()\n\n modalContainer: ()->\n $(\"#progress-modal\", @el)\n\n setupBindings: ()->\n @manager.bind \"collection_loaded\", (name)=>\n loaded = @manager.loadedCollectionsCount()\n total = @manager.totalCollectionsCount()\n progress = parseInt((loaded / total) * 100)\n collectionName = _.string.titleize( _.string.humanize( name ) )\n\n @modalContainer().find('.progress .bar').attr(\"style\", \"width: #{progress}%;\")\n @modalContainer().find('.message').html(\"Loaded #{ collectionName }...\")\n\n @manager.bind \"all_collections_loaded\", ()=>\n @modalContainer().find('.message').html(\"All done!\")\n _.delay ()=>\n @modalContainer().modal('hide')\n , 400"},{"className":"Luca.components.CollectionView","file":"src/components/collection_view.coffee","source":"make = Luca.View::make\n\n_.def(\"Luca.components.CollectionView\").extends(\"Luca.components.Panel\").with\n tagName: \"div\"\n\n className: \"luca-ui-collection-view\"\n\n bodyClassName: \"collection-ui-panel\"\n\n # A collection view can pass a model through to a template\n itemTemplate: undefined\n\n # A collection view can pass a model through a function which should return a string\n itemRenderer: undefined\n\n itemTagName: 'li'\n\n itemClassName: 'collection-item'\n\n initialize: (@options={})->\n _.extend(@, @options)\n\n _.bindAll @, \"refresh\"\n\n unless @collection? or @options.collection\n throw \"Collection Views must specify a collection\"\n\n unless @itemTemplate? || @itemRenderer? || @itemProperty?\n throw \"Collection Views must specify an item template or item renderer function\"\n\n Luca.components.Panel::initialize.apply(@, arguments)\n\n if _.isString(@collection) and Luca.CollectionManager.get()\n @collection = Luca.CollectionManager.get().get(@collection)\n\n if Luca.isBackboneCollection(@collection)\n @collection.bind \"reset\", @refresh\n @collection.bind \"add\", @refresh\n @collection.bind \"remove\", @refresh\n\n attributesForItem: (item)->\n _.extend {}, class: @itemClassName, \"data-index\": item.index\n\n contentForItem: (item={})->\n if @itemTemplate? and templateFn = Luca.template(@itemTemplate)\n content = templateFn.call(@, item)\n\n if @itemRenderer? and _.isFunction( @itemRenderer )\n content = @itemRenderer.call(@, item, item.model, item.index)\n\n if @itemProperty\n content = item.model.get(@itemProperty) || item.model[ @itemProperty ]\n content = content() if _.isFunction(content)\n\n content\n\n makeItem: (model, index)->\n item = if @prepareItem? then @prepareItem.call(@, model, index) else (model:model, index: index)\n\n make(@itemTagName, @attributesForItem(item), @contentForItem(item))\n\n getModels: ()->\n if @collection?.query and (@filter || @filterOptions)\n @collection.query(@filter, @filterOptions)\n else\n @collection.models\n\n refresh: ()->\n panel = @\n\n @$bodyEl().empty()\n\n _( @getModels() ).each (model, index)->\n panel.$append( panel.makeItem(model, index) )\n\n registerEvent: (domEvent, selector, handler)->\n if !handler? and _.isFunction(selector)\n handler = selector\n selector = undefined\n\n eventTrigger = _([domEvent,\"#{ @itemTagName }.#{ @itemClassName }\", selector]).compact().join(\" \")\n Luca.View::registerEvent(eventTrigger,handler)\n\n render: ()->\n @refresh()\n @$attach() if @$el.parent().length > 0 and @container?"},{"className":"Luca.components.Controller","file":"src/components/controller.coffee","source":"_.def('Luca.components.Controller').extends('Luca.containers.CardView').with\n\n additionalClassNames:['luca-ui-controller']\n\n activeAttribute: \"active-section\"\n\n initialize: (@options)->\n Luca.containers.CardView::initialize.apply @, arguments\n\n @defaultCard ||= @components[0]?.name\n\n throw \"Controllers must specify a defaultCard property and/or the first component must have a name\" unless @defaultCard\n\n @state = new Backbone.Model \n active_section: @defaultCard\n\n each: (fn)->\n _( @components ).each (component)=>\n fn.apply @, [component]\n\n activeSection: ()->\n @get(\"activeSection\")\n\n controllers:(deep=false)->\n @select 'ctype', 'controller', deep\n\n availableSections: ()->\n base = {}\n base[ @name ] = @sectionNames()\n\n _( @controllers() ).reduce (memo,controller)=>\n memo[ controller.name ] = controller.sectionNames() \n memo\n , base \n\n sectionNames: (deep=false)->\n @pluck('name')\n\n default: (callback)->\n @navigate_to(@defaultCard, callback)\n\n # switch the active card of this controller\n # optionally passing an onActivation callback\n # will fire this callback in the context of\n # the currently active card\n navigate_to: (section, callback)->\n section ||= @defaultCard\n\n # activate is a method on Luca.containers.CardView which\n # selects a component and makes it visible, hiding any\n # other component which may be monopolizing the view at that time.\n\n # after activation it triggers a after:card:switch event\n # and if it is the first time that view is being activated,\n # it triggers a first:activation event which gets relayed to all\n # child components in that view\n @activate section, false, (activator, previous,current)=>\n @state.set(active_section: current.name )\n if _.isFunction( callback )\n callback.apply(current)\n\n # return the section we are navigating to\n @find(section)\n"},{"className":"Luca.fields.ButtonField","file":"src/components/fields/button_field.coffee","source":"_.def('Luca.fields.ButtonField').extends('Luca.core.Field').with\n\n readOnly: true\n\n events:\n \"click input\" : \"click_handler\"\n\n hooks:[\n \"button:click\"\n ]\n\n className: 'luca-ui-field luca-ui-button-field'\n\n template: 'fields/button_field'\n\n click_handler: (e)->\n me = my = $( e.currentTarget )\n @trigger \"button:click\"\n\n initialize: (@options={})->\n _.extend @options\n _.bindAll @, \"click_handler\"\n\n Luca.core.Field::initialize.apply @, arguments\n\n @template = \"fields/button_field_link\" if @icon_class?.length\n\n afterInitialize: ()->\n @input_id ||= _.uniqueId('button')\n @input_name ||= @name ||= @input_id\n @input_value ||= @label ||= @text\n @input_type ||= \"button\"\n @input_class ||= @class\n @icon_class ||= \"\"\n @icon_class = \"icon-#{ @icon_class }\" if @icon_class.length and !@icon_class.match(/^icon-/)\n @icon_class += \" icon-white\" if @white\n\n setValue: ()-> true"},{"className":"Luca.fields.CheckboxArray","file":"src/components/fields/checkbox_array.coffee","source":"make = Luca.View::make\n\n_.def('Luca.fields.CheckboxArray').extends('Luca.core.Field').with\n version: 2\n\n template: \"fields/checkbox_array\"\n\n className: \"luca-ui-checkbox-array\"\n\n events:\n \"click input\" : \"clickHandler\"\n\n selectedItems: []\n\n initialize: (@options={})->\n _.extend @, @options\n _.extend @, Luca.modules.Deferrable\n _.bindAll @, \"renderCheckboxes\", \"clickHandler\", \"checkSelected\"\n\n Luca.core.Field::initialize.apply @, arguments\n\n @input_id ||= _.uniqueId('field')\n @input_name ||= @name\n @label ||= @name\n @valueField ||= \"id\"\n @displayField ||= \"name\"\n\n afterInitialize: (@options={})->\n try\n @configure_collection()\n catch e\n console.log \"Error Configuring Collection\", @, e.message\n\n cbArray = @\n\n if @collection.length > 0\n @renderCheckboxes()\n else\n @defer(\"renderCheckboxes\").until(@collection,\"reset\")\n\n clickHandler: (event)->\n checkbox = $(event.target)\n\n if checkbox.prop('checked')\n @selectedItems.push( checkbox.val() )\n else\n if _( @selectedItems ).include( checkbox.val() )\n @selectedItems = _( @selectedItems ).without( checkbox.val() )\n\n controls: ()->\n @$('.controls')\n\n renderCheckboxes: ()->\n @controls().empty()\n @selectedItems = []\n\n @collection.each (model)=>\n value = model.get(@valueField)\n label = model.get(@displayField)\n input_id = _.uniqueId(\"#{ @cid }_checkbox\")\n\n inputElement = make(\"input\",type:\"checkbox\",class:\"array-checkbox\",name:@input_name,value:value,id: input_id)\n element = make(\"label\", {for:input_id}, inputElement)\n\n $( element ).append(\" #{ label }\")\n @controls().append( element )\n\n @trigger(\"checkboxes:rendered\", @checkboxesRendered = true)\n @\n\n uncheckAll: ()->\n @allFields().prop('checked', false)\n\n allFields: ()->\n @controls().find(\"input[type='checkbox']\")\n\n checkSelected: (items)->\n @selectedItems = items if items?\n\n @uncheckAll()\n\n for value in @selectedItems\n checkbox = @controls().find(\"input[value='#{ value }']\")\n checkbox.prop('checked', true)\n\n @selectedItems\n\n getValue: ()->\n @$(field).val() for field in @allFields() when @$(field).prop('checked')\n\n setValue: (items)->\n @selectedItems = items\n\n if @checkboxesRendered is true\n @checkSelected(items)\n else\n cbArray = @\n @defer ()->\n cbArray.checkSelected(items)\n .until(\"checkboxes:rendered\")\n\n getValues: ()->\n @getValue()\n\n setValues: (items)->\n @setValue(items)"},{"className":"Luca.fields.CheckboxField","file":"src/components/fields/checkbox_field.coffee","source":"_.def('Luca.fields.CheckboxField').extends('Luca.core.Field').with\n\n events:\n \"change input\" : \"change_handler\"\n\n change_handler: (e)->\n me = my = $(e.currentTarget)\n\n @trigger \"on:change\", @, e\n\n if me.checked is true\n @trigger \"checked\"\n else\n @trigger \"unchecked\"\n\n className: 'luca-ui-checkbox-field luca-ui-field'\n\n template: 'fields/checkbox_field'\n\n hooks: [\"checked\",\"unchecked\"]\n\n send_blanks: true\n\n initialize: (@options={})->\n _.extend @, @options\n _.bindAll @, \"change_handler\"\n\n Luca.core.Field::initialize.apply @, arguments\n\n afterInitialize: ()->\n @input_id ||= _.uniqueId('field')\n @input_name ||= @name\n @input_value ||= 1\n @label ||= @name\n\n setValue: (checked)->\n @input.attr('checked', checked)\n\n getValue:()->\n @input.attr('checked') is true"},{"className":"Luca.fields.FileUploadField","file":"src/components/fields/file_upload_field.coffee","source":"_.def('Luca.fields.FileUploadField').extends('Luca.core.Field').with\n\n template: 'fields/file_upload_field'\n\n initialize: (@options={})->\n Luca.core.Field::initialize.apply @, arguments\n\n afterInitialize: ()->\n @input_id ||= _.uniqueId('field')\n @input_name ||= @name\n @label ||= @name\n @helperText ||= \"\"\n"},{"className":"Luca.fields.HiddenField","file":"src/components/fields/hidden_field.coffee","source":"_.def('Luca.fields.HiddenField').extends('Luca.core.Field').with\n\n template: 'fields/hidden_field'\n\n initialize: (@options={})->\n Luca.core.Field::initialize.apply @, arguments\n\n afterInitialize: ()->\n @input_id ||= _.uniqueId('field')\n @input_name ||= @name\n @input_value ||= @value\n @label ||= @name"},{"className":"Luca.fields.SelectField","file":"src/components/fields/select_field.coffee","source":"_.def('Luca.fields.SelectField').extends('Luca.core.Field').with\n\n events:\n \"change select\" : \"change_handler\"\n\n hooks:[\n \"after:select\"\n ]\n\n className: 'luca-ui-select-field luca-ui-field'\n\n template: \"fields/select_field\"\n\n includeBlank: true\n\n blankValue: ''\n\n blankText: 'Select One'\n\n initialize: (@options={})->\n _.extend @, @options\n _.extend @, Luca.modules.Deferrable\n _.bindAll @, \"change_handler\", \"populateOptions\", \"beforeFetch\"\n\n Luca.core.Field::initialize.apply @, arguments\n\n @input_id ||= _.uniqueId('field')\n @input_name ||= @name\n @label ||= @name\n @retainValue = true if _.isUndefined @retainValue\n\n afterInitialize: ()->\n if @collection?.data\n @valueField ||= \"id\"\n @displayField ||= \"name\"\n @parseData()\n\n try\n @configure_collection()\n catch e\n console.log \"Error Configuring Collection\", @, e.message\n\n @collection.bind \"before:fetch\", @beforeFetch\n @collection.bind \"reset\", @populateOptions\n\n # if the select field is configured with a data property\n # then parse that data into the proper format. either\n # an array of objects with the valueField and displayField\n # properties, or an array of arrays with [valueField, displayField]\n parseData: ()->\n @collection.data = _( @collection.data ).map (record)=>\n return record if not _.isArray( record )\n hash = {}\n hash[ @valueField ] = record[0]\n hash[ @displayField ] = record[1]\n\n hash\n\n\n afterRender: ()->\n @input = $('select', @el)\n\n if @collection?.models?.length > 0\n @populateOptions()\n else\n @collection.trigger(\"reset\")\n\n setValue: (value)->\n @currentValue = value\n Luca.core.Field::setValue.apply @, arguments\n\n beforeFetch: ()->\n @resetOptions()\n\n change_handler: (e)->\n @trigger \"on:change\", @, e\n\n resetOptions: ()->\n @input.html('')\n\n if @includeBlank\n @input.append(\"<option value='#{ @blankValue }'>#{ @blankText }</option>\")\n\n\n populateOptions: ()->\n @resetOptions()\n\n if @collection?.each?\n @collection.each (model) =>\n value = model.get( @valueField )\n display = model.get( @displayField )\n selected = \"selected\" if @selected and value is @selected\n option = \"<option #{ selected } value='#{ value }'>#{ display }</option>\"\n @input.append( option )\n\n @trigger \"after:populate:options\", @\n @setValue( @currentValue )"},{"className":"Luca.fields.TextAreaField","file":"src/components/fields/text_area_field.coffee","source":"_.def('Luca.fields.TextAreaField').extends('Luca.core.Field').with\n\n events:\n \"keydown input\" : \"keydown_handler\"\n \"blur input\" : \"blur_handler\"\n \"focus input\" : \"focus_handler\"\n\n template: 'fields/text_area_field'\n\n height: \"200px\"\n width: \"90%\"\n\n initialize: (@options={})->\n _.bindAll @, \"keydown_handler\"\n\n Luca.core.Field::initialize.apply @, arguments\n\n @input_id ||= _.uniqueId('field')\n @input_name ||= @name\n @label ||= @name\n @input_class ||= @class\n @inputStyles ||= \"height:#{ @height };width:#{ @width }\"\n\n setValue: (value)->\n $( @field() ).val(value)\n\n getValue: ()->\n $( @field() ).val()\n\n field: ()->\n @input = $(\"textarea##{ @input_id }\", @el)\n\n keydown_handler: (e)->\n me = my = $( e.currentTarget )\n\n blur_handler: (e)->\n me = my = $( e.currentTarget )\n\n focus_handler: (e)->\n me = my = $( e.currentTarget )"},{"className":"Luca.fields.TextField","file":"src/components/fields/text_field.coffee","source":"change_handler = (e)-> @trigger \"on:change\", @, e\n\n_.def('Luca.fields.TextField').extends('Luca.core.Field').with\n events:\n \"blur input\" : \"blur_handler\"\n \"focus input\" : \"focus_handler\"\n \"change input\" : \"change_handler\"\n\n template: 'fields/text_field'\n\n autoBindEventHandlers: true\n\n send_blanks: true\n\n initialize: (@options={})->\n Luca.core.Field::initialize.apply @, arguments\n\n @input_id ||= _.uniqueId('field')\n @input_name ||= @name\n @label ||= @name\n @input_class ||= @class\n\n if @prepend\n @$el.addClass('input-prepend')\n @addOn = @prepend\n\n if @append\n @$el.addClass('input-append')\n @addOn = @append\n\n @registerEvent(\"keydown input\",\"keydown_handler\") if @enableKeyEvents\n\n blur_handler: (e)->\n me = my = $( e.currentTarget )\n\n focus_handler: (e)->\n me = my = $( e.currentTarget )\n\n change_handler: change_handler\n keydown_handler: _.throttle ((e)-> change_handler.apply @, arguments), 300\n"},{"className":"Luca.fields.TypeAheadField","file":"src/components/fields/type_ahead_field.coffee","source":"_.def('Luca.fields.TypeAheadField').extends('Luca.fields.TextField').with\n className: 'luca-ui-field'\n\n getSource: ()->\n @source || []\n\n matcher: (item)->\n # IMPLEMENT\n # return true where item matches @query\n true\n\n beforeRender: ()->\n @_super(\"beforeRender\", @, arguments)\n @$('input').attr('data-provide','typeahead')\n\n afterRender: ()->\n @_super(\"afterRender\", @, arguments)\n\n @$('input').typeahead\n matcher: @matcher\n source: @getSource()"},{"className":"Luca.components.FormButtonToolbar","file":"src/components/form_button_toolbar.coffee","source":"_.def('Luca.components.FormButtonToolbar').extends('Luca.components.Toolbar').with\n\n className: 'luca-ui-form-toolbar form-actions'\n\n position: 'bottom'\n\n includeReset: false\n\n render: ()->\n $(@container).append(@el)\n\n initialize: (@options={})->\n Luca.components.Toolbar.prototype.initialize.apply @, arguments\n\n @components = [\n ctype: 'button_field'\n label: 'Submit'\n class: 'btn submit-button'\n ]\n\n if @includeReset\n @components.push\n ctype: 'button_field'\n label: 'Reset'\n class: 'btn reset-button'\n"},{"className":"Luca.components.FormView","file":"src/components/form_view.coffee","source":"defaultToolbar =\n buttons:[\n icon:\"remove-sign\"\n label: \"Reset\"\n eventId: \"click:reset\"\n className:\"reset-button\"\n align: 'right'\n ,\n icon:\"ok-sign\"\n white: true\n label: \"Save Changes\"\n eventId: \"click:submit\"\n color: \"success\"\n className: 'submit-button'\n align: 'right'\n ]\n\n_.def(\"Luca.components.FormView\").extends('Luca.core.Container').with\n\n tagName: 'form'\n\n className: 'luca-ui-form-view'\n\n hooks:[\n \"before:submit\"\n \"before:reset\"\n \"before:load\"\n \"before:load:new\"\n \"before:load:existing\"\n \"after:submit\"\n \"after:reset\"\n \"after:load\"\n \"after:load:new\"\n \"after:load:existing\"\n \"after:submit:success\"\n \"after:submit:fatal_error\"\n \"after:submit:error\"\n ]\n\n events:\n \"click .submit-button\" : \"submitHandler\"\n \"click .reset-button\" : \"resetHandler\"\n\n toolbar: true\n\n legend: \"\"\n\n bodyClassName: \"form-view-body\"\n\n initialize: (@options={})->\n @loadMask = Luca.enableBootstrap unless @loadMask?\n\n Luca.core.Container::initialize.apply @, arguments\n\n _.bindAll @, \"submitHandler\", \"resetHandler\", \"renderToolbars\", \"applyLoadMask\"\n\n @state ||= new Backbone.Model\n\n @setupHooks( @hooks )\n\n @applyStyleClasses()\n\n if @toolbar isnt false and (not @topToolbar and not @bottomToolbar)\n @topToolbar = @getDefaultToolbar() if @toolbar is \"both\" or @toolbar is \"top\"\n @bottomToolbar = @getDefaultToolbar() unless @toolbar is \"top\"\n\n getDefaultToolbar: ()->\n defaultToolbar\n\n applyStyleClasses: ()->\n if Luca.enableBootstrap\n @applyBootstrapStyleClasses()\n\n @$el.addClass( \"label-align-#{ @labelAlign }\") if @labelAlign\n @$el.addClass( @fieldLayoutClass ) if @fieldLayoutClass\n\n applyBootstrapStyleClasses: ()->\n @inlineForm = true if @labelAlign is \"left\"\n\n @$el.addClass('well') if @well\n @$el.addClass('form-search') if @searchForm\n @$el.addClass('form-horizontal') if @horizontalForm\n @$el.addClass('form-inline') if @inlineForm\n\n resetHandler: (e)->\n me = my = $( e?.target )\n @trigger \"before:reset\", @\n @reset()\n @trigger \"after:reset\", @\n\n submitHandler: (e)->\n me = my = $( e?.target )\n @trigger \"before:submit\", @\n @trigger \"enable:loadmask\", @ if @loadMask is true\n @submit() if @hasModel()\n\n afterComponents: ()->\n Luca.core.Container::afterComponents?.apply(@, arguments)\n\n @eachField (field)=>\n field.getForm = ()=> @\n field.getModel = ()=> @currentModel()\n\n eachField: (iterator)->\n _( @getFields() ).map( iterator )\n\n getField: (name)->\n _( @getFields('name', name) ).first()\n\n getFields: (attr,value)->\n # do a deep search of all of the nested components\n # to find the fields\n fields = @select(\"isField\", true, true)\n\n return fields unless attr and value\n # if an optional attribute and value pair is passed\n # then you can limit the array of fields even further\n _(fields).select (field)->\n property = field[ attr ]\n property? and value is (if _.isFunction(property) then property() else property)\n\n fields\n\n loadModel: (@current_model)->\n form = @\n fields = @getFields()\n\n @trigger \"before:load\", @, @current_model\n\n if @current_model\n @current_model.beforeFormLoad?.apply(@current_model, @)\n\n event = \"before:load:#{ (if @current_model.isNew() then \"new\" else \"existing\")}\"\n @trigger event, @, @current_model\n\n @setValues(@current_model)\n\n @trigger \"after:load\", @, @current_model\n\n if @current_model\n @trigger \"after:load:#{ (if @current_model.isNew() then \"new\" else \"existing\")}\", @, @current_model\n\n reset: ()->\n @loadModel( @current_model ) if @current_model?\n\n clear: ()->\n @current_model = if @defaultModel? then @defaultModel() else undefined\n\n _( @getFields() ).each (field)=>\n try\n field.setValue('')\n catch e\n console.log \"Error Clearing\", @, field\n\n # set the values on the form\n # without syncing\n setValues: (source, options={})->\n source ||= @currentModel()\n fields = @getFields()\n\n _( fields ).each (field) =>\n field_name = field.input_name || field.name\n\n if value = source[field_name]\n if _.isFunction(value)\n value = value.apply(@)\n\n if !value and Luca.isBackboneModel(source)\n value = source.get(field_name)\n\n field?.setValue( value ) unless field.readOnly is true\n\n @syncFormWithModel() unless options.silent? is true\n\n getValues: (options={})->\n options.reject_blank = true unless options.reject_blank?\n options.skip_buttons = true unless options.skip_buttons?\n\n _( @getFields() ).inject (memo,field)->\n value = field.getValue()\n key = field.input_name || field.name\n\n skip = false\n\n # don't include the values of buttons in our values hash\n skip = true if options.skip_buttons and field.ctype is \"button_field\"\n\n # if the value is blank and we are passed reject_blank in the options\n # then we should not include this field in our hash. however, if the\n # field is setup to send blanks, then we will send this value anyway\n if _.string.isBlank( value )\n skip = true if options.reject_blank and !field.send_blanks\n skip = true if field.input_name is \"id\"\n\n memo[ key ] = value unless skip is true\n\n memo\n , {}\n\n submit_success_handler: (model, response, xhr)->\n @trigger \"after:submit\", @, model, response\n @trigger \"disable:loadmask\", @ if @loadMask is true\n\n if response and response?.success is true\n @trigger \"after:submit:success\", @, model, response\n else\n @trigger \"after:submit:error\", @, model, response\n\n submit_fatal_error_handler: (model, response, xhr)->\n @trigger \"after:submit\", @, model, response\n @trigger \"after:submit:fatal_error\", @, model, response\n\n submit: (save=true, saveOptions={})->\n _.bindAll @, \"submit_success_handler\", \"submit_fatal_error_handler\"\n\n saveOptions.success ||= @submit_success_handler\n saveOptions.error ||= @submit_fatal_error_handler\n\n @syncFormWithModel()\n return unless save\n @current_model.save( @current_model.toJSON(), saveOptions )\n\n hasModel: ()->\n @current_model?\n\n currentModel: (options={})->\n if options is true or options?.refresh is true\n @syncFormWithModel()\n\n @current_model\n\n syncFormWithModel: ()->\n @current_model?.set( @getValues() )\n\n setLegend: (@legend)->\n $('fieldset legend', @el).first().html(@legend)\n\n flash: (message)->\n if @$('.toolbar-container.top').length > 0\n @$('.toolbar-container.top').after(message)\n else\n @$bodyEl().prepend(message)\n\n successFlashDelay: 1500\n\n successMessage: (message)->\n @$('.alert.alert-success').remove()\n @flash Luca.template(\"components/form_alert\", className:\"alert alert-success\", message: message)\n _.delay ()=>\n @$('.alert.alert-success').fadeOut()\n , @successFlashDelay || 0\n\n errorMessage: (message)->\n @$('.alert.alert-error').remove()\n @flash Luca.template(\"components/form_alert\", className:\"alert alert-error\", message: message)\n\n"},{"className":"Luca.components.GridView","file":"src/components/grid_view.coffee","source":"_.def('Luca.components.GridView').extend('Luca.components.Panel').with\n\n bodyTemplate: \"components/grid_view\"\n\n autoBindEventHandlers: true\n\n events:\n \"dblclick table tbody tr\" : \"double_click_handler\"\n \"click table tbody tr\": \"click_handler\"\n\n className: 'luca-ui-g-view'\n\n rowClass: \"luca-ui-g-row\"\n\n wrapperClass: \"luca-ui-g-view-wrapper\"\n\n # add whatever additional container classes you want\n # to be applied to the wrapper here\n additionalWrapperClasses: []\n\n # add additional style declarations to the wrapper if you like\n # these will be added by jquery.css and accept the same syntax\n wrapperStyles: {}\n\n scrollable: true\n\n emptyText: 'No Results To display.'\n\n # available options are striped, condensed, bordered\n # or any combination of these, split up by space\n tableStyle: 'striped'\n\n # we have to specify height to make the scrollable table portion work\n defaultHeight: 285\n\n # unless we specify the width ourselves\n # the width of the grid will automatically be set to the width of the container\n # and if it can't be determined, then it will be set to the default\n defaultWidth: 756\n\n # the grid should never outgrow its container\n maxWidth: undefined\n\n # hooks is configuration sugar\n # the before:grid:render trigger\n # will automatically fire the\n # beforeGridRender function\n hooks:[\n \"before:grid:render\"\n \"before:render:header\"\n \"before:render:row\"\n \"after:grid:render\"\n \"row:double:click\"\n \"row:click\"\n \"after:collection:load\"\n ]\n\n initialize: (@options={})->\n _.extend @, @options\n _.extend @, Luca.modules.Deferrable\n\n @loadMask = Luca.enableBootstrap unless @loadMask?\n @loadMaskEl ||= \".luca-ui-g-view-body\" if @loadMask is true\n\n Luca.components.Panel::initialize.apply(@, arguments)\n\n @configure_collection(true)\n\n @collection.bind \"before:fetch\", ()=>\n @trigger \"enable:loadmask\" if @loadMask is true\n\n @collection.bind \"reset\", (collection) =>\n @refresh()\n @trigger \"disable:loadmask\" if @loadMask is true\n @trigger \"after:collection:load\", collection\n\n # if a model changes, then we will update the row's contents\n # by rerendering that row's cells\n @collection.bind \"change\", (model)=>\n return unless @rendered is true\n\n try\n rowEl = @getRowEl( model.id || model.get('id') || model.cid )\n cells = @render_row(model, @collection.indexOf(model), cellsOnly: true )\n $( rowEl ).html( cells.join(\" \") )\n catch error\n console.log \"Error in change handler for GridView.collection\", error, @, model\n\n beforeRender: ()->\n Luca.components.Panel::beforeRender?.apply(@, arguments)\n\n @trigger \"before:grid:render\", @\n\n @table = @$ 'table.luca-ui-g-view'\n @header = @$ \"thead\"\n @body = @$ \"tbody\"\n @footer = @$ \"tfoot\"\n @wrapper = @$ \".#{ @wrapperClass }\"\n\n @applyCssClasses()\n\n @setDimensions() if @scrollable\n\n @renderHeader()\n\n @emptyMessage()\n\n $(@container).append @$el\n\n afterRender: ()->\n Luca.components.Panel::afterRender?.apply(@, arguments)\n\n @rendered = true\n @refresh()\n @trigger \"after:grid:render\", @\n\n applyCssClasses: ()->\n @$el.addClass 'scrollable-g-view' if @scrollable\n\n _( @additionalWrapperClasses ).each (containerClass)=>\n @wrapper?.addClass( containerClass )\n\n if Luca.enableBootstrap\n @table.addClass('table')\n\n _( @tableStyle?.split(\" \") ).each (style)=>\n @table.addClass(\"table-#{ style }\")\n\n setDimensions: (offset)->\n @height ||= @defaultHeight\n\n @$('.luca-ui-g-view-body').height( @height )\n @$('tbody.scrollable').height( @height - 23 )\n\n @container_width = do => $(@container).width()\n\n @width ||= if @container_width > 0 then @container_width else @defaultWidth\n\n # don't let the grid outgrow its maxWidth\n @width = _([@width, (@maxWidth || @width)]).max()\n\n @$('.luca-ui-g-view-body').width @width\n @$('.luca-ui-g-view-body table').width @width\n\n @setDefaultColumnWidths()\n\n resize: (newWidth)->\n difference = newWidth - @width\n @width = newWidth\n\n @$('.luca-ui-g-view-body').width( @width )\n @$('.luca-ui-g-view-body table').width( @width )\n\n if @columns.length > 0\n distribution = difference / @columns.length\n\n _(@columns).each (col,index)=>\n column = $(\".column-#{ index }\", @el )\n column.width( col.width = col.width + distribution )\n\n padLastColumn: ()->\n configured_column_widths = _(@columns).inject (sum, column)->\n sum = (column.width) + sum\n , 0\n\n unused_width = @width - configured_column_widths\n\n if unused_width > 0\n @lastColumn().width += unused_width\n\n setDefaultColumnWidths: ()->\n default_column_width = if @columns.length > 0 then @width / @columns.length else 200\n\n _( @columns ).each (column)->\n parseInt(column.width ||= default_column_width)\n\n @padLastColumn()\n\n lastColumn: ()->\n @columns[ @columns.length - 1 ]\n\n\n\n emptyMessage: (text=\"\")->\n text ||= @emptyText\n @body.html('')\n @body.append Luca.templates[\"components/grid_view_empty_text\"](colspan:@columns.length,text:text)\n\n refresh: ()->\n @body.html('')\n @collection.each (model,index)=>\n @render_row.apply(@, [model,index])\n\n if @collection.models.length == 0\n @emptyMessage()\n\n ifLoaded: (fn, scope)->\n scope ||= @\n fn ||= ()-> true\n\n @collection.ifLoaded(fn,scope)\n\n applyFilter: (values, options={auto:true,refresh:true})->\n @collection.applyFilter(values, options)\n\n renderHeader: ()->\n @trigger \"before:render:header\"\n\n headers = _(@columns).map (column,column_index) =>\n # temporary hack for scrollable grid dimensions.\n style = if column.width then \"width:#{ column.width }px;\" else \"\"\n\n \"<th style='#{ style }' class='column-#{ column_index }'>#{ column.header}</th>\"\n\n @header.append(\"<tr>#{ headers }</tr>\")\n\n getRowEl: (id)->\n @$ \"[data-record-id=#{ id }]\", 'table'\n\n render_row: (row,row_index, options={})->\n rowClass = @rowClass\n\n model_id = if row?.get and row?.attributes then row.get('id') else ''\n\n @trigger \"before:render:row\", row, row_index\n\n cells = _( @columns ).map (column,col_index) =>\n value = @cell_renderer(row, column, col_index)\n style = if column.width then \"width:#{ column.width }px;\" else \"\"\n\n display = if _.isUndefined(value) then \"\" else value\n\n \"<td style='#{ style }' class='column-#{ col_index }'>#{ display }</td>\"\n\n return cells if options.cellsOnly\n\n altClass = ''\n if @alternateRowClasses\n altClass = if row_index % 2 is 0 then \"even\" else \"odd\"\n\n content = \"<tr data-record-id='#{ model_id }' data-row-index='#{ row_index }' class='#{ rowClass } #{ altClass }' id='row-#{ row_index }'>#{ cells }</tr>\"\n\n return content if options.contentOnly is true\n\n @body?.append(content)\n\n cell_renderer: (row, column, columnIndex )->\n if _.isFunction column.renderer\n return column.renderer.apply @, [row,column,columnIndex]\n else if column.data.match(/\\w+\\.\\w+/)\n source = row.attributes || row\n return Luca.util.nestedValue( column.data, source )\n else\n return row.get?( column.data ) || row[ column.data ]\n\n double_click_handler: (e)->\n me = my = $( e.currentTarget )\n rowIndex = my.data('row-index')\n record = @collection.at( rowIndex )\n @trigger \"row:double:click\", @, record, rowIndex\n\n click_handler: (e)->\n me = my = $( e.currentTarget )\n rowIndex = my.data('row-index')\n record = @collection.at( rowIndex )\n @trigger \"row:click\", @, record, rowIndex\n\n $(\".#{ @rowClass }\", @body ).removeClass('selected-row')\n me.addClass('selected-row')"},{"className":"Luca.components.LoadMask","file":"src/components/load_mask.coffee","source":"_.def(\"Luca.components.LoadMask\").extends(\"Luca.View\").with\n className: \"luca-ui-load-mask\"\n bodyTemplate:\"components/load_mask\""},{"className":"Luca.components.NavBar","file":"src/components/nav_bar.coffee","source":"_.def(\"Luca.components.NavBar\").extends(\"Luca.View\").with\n fixed: true\n position: 'top'\n className: 'navbar'\n brand: \"Luca.js\"\n bodyTemplate: 'nav_bar'\n bodyClassName: 'luca-ui-navbar-body'\n\n beforeRender: ()->\n @$el.addClass \"navbar-fixed-#{ @position }\" if @fixed\n\n if @brand?\n @content().append(\"<a class='brand' href='#'>#{ @brand }</a>\")\n\n if @template\n @content().append Luca.template(@template, @)\n\n render: ()->\n @\n\n content: ()->\n @$('.container').eq(0)\n"},{"className":"Luca.components.RecordManager","file":"src/components/record_manager.coffee","source":"# The RecordManager is a high level component which incorporates\n# a filterable grid, and an editor form responsible for editing\n# the records in that grid.\n#\n# it provides convenience methods for accesing those components.\n#\n# this represents a clean pattern for having multiple components\n# which work together. inter-component communication should be handled\n# by parent containers, and not individual components, which should\n# usually not be aware of other components.\n_.def('Luca.components.RecordManager').extends('Luca.containers.CardView').with\n events:\n \"click .record-manager-grid .edit-link\" : \"edit_handler\"\n \"click .record-manager-filter .filter-button\" : \"filter_handler\"\n \"click .record-manager-filter .reset-button\" : \"reset_filter_handler\"\n \"click .add-button\" : \"add_handler\"\n \"click .refresh-button\" : \"filter_handler\"\n \"click .back-to-search-button\" : \"back_to_search_handler\"\n\n record_manager: true\n\n initialize: (@options={})->\n Luca.containers.CardView::initialize.apply @, arguments\n\n throw \"Record Managers must specify a name\" unless @name\n\n _.bindAll @, \"add_handler\", \"edit_handler\", \"filter_handler\", \"reset_filter_handler\"\n\n _.extend @components[0][0], @filterConfig if @filterConfig\n _.extend @components[0][1], @gridConfig if @gridConfig\n _.extend @components[1][0], @editorConfig if @editorConfig\n\n @bind \"after:card:switch\", () =>\n @trigger(\"activation:search\", @) if @activeCard is 0\n @trigger(\"activation:editor\", @) if @activeCard is 1\n\n components:[\n ctype: 'split_view',\n relayFirstActivation: true\n components:[\n ctype: 'form_view'\n ,\n ctype: 'grid_view'\n ]\n ,\n ctype: 'form_view'\n ]\n\n getSearch: (activate=false, reset=true)->\n @activate(0) if activate is true\n @getEditor().clear() if reset is true\n\n _.first(@components)\n\n getFilter: ()->\n _.first @getSearch().components\n\n getGrid: ()->\n _.last @getSearch().components\n\n getCollection: ()->\n @getGrid().collection\n\n getEditor: (activate=false,reset=false)->\n if activate is true\n @activate 1, (activator,previous,current)=>\n current.reset()\n\n _.last(@components)\n\n beforeRender: ()->\n @$el.addClass(\"#{ @resource }-manager\")\n Luca.containers.CardView::beforeRender?.apply @, arguments\n\n @$el.addClass(\"#{ @resource } record-manager\")\n @$el.data('resource', @resource)\n\n $(@getGrid().el).addClass(\"#{ @resource } record-manager-grid\")\n $(@getFilter().el).addClass(\"#{ @resource } record-manager-filter\")\n $(@getEditor().el).addClass(\"#{ @resource } record-manager-editor\")\n\n # This is an example of a best practice from ExtJS\n # that we incorporate in Luca, which is that container\n # components are responsible for component communication.\n #\n # child components should not be aware of other components\n # in the layout. Their parents should be responsible for\n # controlling how they interact. listening to events on one,\n # changing state, inducing effects in the others\n afterRender: ()->\n Luca.containers.CardView::afterRender?.apply @, arguments\n\n manager = @\n grid = @getGrid()\n filter = @getFilter()\n editor = @getEditor()\n collection = @getCollection()\n\n # when a row is double clicked on the grid\n # then we edit that row\n grid.bind \"row:double:click\", (grid,model,index)->\n manager.getEditor(true)\n editor.loadModel( model )\n\n editor.bind \"before:submit\", ()=>\n $('.form-view-flash-container', @el).html('')\n $('.form-view-body', @el).spin(\"large\")\n\n editor.bind \"after:submit\", ()=>\n $('.form-view-body', @el).spin(false)\n\n editor.bind \"after:submit:fatal_error\", ()=>\n $('.form-view-flash-container', @el ).append \"<li class='error'>There was an internal server error saving this record. Please contact developers@benchprep.com to report this error.</li>\"\n $('.form-view-body', @el).spin(false)\n\n editor.bind \"after:submit:error\", (form, model, response)=>\n _( response.errors ).each (error)=>\n $('.form-view-flash-container', @el ).append \"<li class='error'>#{ error }</li>\"\n\n editor.bind \"after:submit:success\", (form, model, response)=>\n $('.form-view-flash-container', @el).append \"<li class='success'>Successfully Saved Record</li>\"\n\n model.set( response.result )\n form.loadModel( model )\n\n grid.refresh()\n\n _.delay ()=>\n $('.form-view-flash-container li.success', @el).fadeOut(1000)\n $('.form-view-flash-container', @el).html('')\n , 4000\n\n filter.eachComponent (component)=>\n try\n component.bind \"on:change\", @filter_handler\n catch e\n undefined\n\n firstActivation: ()->\n @getGrid().trigger \"first:activation\", @, @getGrid()\n @getFilter().trigger \"first:activation\", @, @getGrid()\n\n reload: ()->\n manager = @\n\n grid = @getGrid()\n filter = @getFilter()\n editor = @getEditor()\n\n # refresh the select fields in the filter\n filter.clear()\n\n grid.applyFilter()\n\n manageRecord: (record_id)->\n model = @getCollection().get(record_id)\n return @loadModel(model) if model\n\n console.log \"Could Not Find Model, building and fetching\"\n\n model = @buildModel()\n model.set({id:record_id},{silent:true})\n\n model.fetch\n success: (model,response)=>\n @loadModel(model)\n\n loadModel: (@current_model)->\n @getEditor(true).loadModel( @current_model )\n @trigger \"model:loaded\", @current_model\n\n currentModel: ()->\n @getEditor(false).currentModel()\n\n buildModel: ()->\n editor = @getEditor(false)\n collection = @getCollection()\n\n collection.add([{}], silent:true, at: 0)\n\n model = collection.at(0)\n\n createModel: ()->\n @loadModel(@buildModel())\n\n ##### DOM Event Handlers\n reset_filter_handler: (e)->\n @getFilter().clear()\n @getGrid().applyFilter( @getFilter().getValues() )\n\n filter_handler: (e)->\n @getGrid().applyFilter( @getFilter().getValues() )\n\n edit_handler: (e)->\n me = my = $( e.currentTarget )\n record_id = my.parents('tr').data('record-id')\n\n if record_id\n model = @getGrid().collection.get( record_id )\n\n model ||= @getGrid().collection.at( row_index )\n\n\n add_handler: (e)->\n me = my = $( e.currentTarget )\n resource = my.parents('.record-manager').eq(0).data('resource')\n\n destroy_handler: (e)->\n #destroy handler\n\n back_to_search_handler: ()->\n # search handler"},{"className":"Luca.Router","file":"src/components/router.coffee","source":"_.def(\"Luca.Router\").extends(\"Backbone.Router\").with\n routes:\n \"\" : \"default\"\n\n initialize: (@options)->\n _.extend @, @options\n\n @routeHandlers = _( @routes ).values()\n\n # when a route handler is fired, the route:route_name event is triggered by the router\n # unfortunately this doesn't apply to calls to @navigate() so we override Backbone.Router.navigate\n # and trigger an event separately.\n _( @routeHandlers ).each (route_id) =>\n @bind \"route:#{ route_id }\", ()=>\n @trigger.apply @, [\"change:navigation\", route_id ].concat( _( arguments ).flatten() )\n\n #### Router Functions\n\n # Intercept calls to Backbone.Router.navigate so that we can at least\n # build a path from the route, even if we don't trigger the route handler\n navigate: (route, triggerRoute=false)->\n Backbone.Router.prototype.navigate.apply @, arguments\n @buildPathFrom( Backbone.history.getFragment() )\n\n # given a url fragment, construct an argument chain similar to what would be\n # emitted from a normal route:#{ name } event that gets triggered\n # when a route is actually fired. This is used to trap route changes that happen\n # through calls to @navigate()\n buildPathFrom: (matchedRoute)->\n _(@routes).each (route_id, route)=>\n regex = @_routeToRegExp(route)\n if regex.test(matchedRoute)\n args = @_extractParameters(regex, matchedRoute)\n @trigger.apply @, [\"change:navigation\", route_id].concat( args )\n"},{"className":"Luca.components.Template","file":"src/components/template.coffee","source":"_.def('Luca.components.Template').extends('Luca.View').with\n initialize: (@options={})->\n console.log \"The Use of Luca.components.Template directly is being DEPRECATED\"\n\n Luca.View::initialize.apply @, arguments\n"},{"className":"Luca.components.ToolbarDialog","file":"src/components/toolbar_dialog.coffee","source":"_.def(\"Luca.components.ToolbarDialog\").extends(\"Luca.View\").with\n className:\"luca-ui-toolbar-dialog span well\"\n\n styles:\n \"position\" : \"absolute\"\n \"z-Index\" : \"3000\"\n \"float\" : \"left\"\n\n initialize: (@options={})->\n @_super(\"initialize\", @, arguments)\n\n createWrapper: ()->\n @make \"div\",\n class: \"component-picker span4 well\"\n style:\n \"position: absolute; z-index:12000\"\n\n show: ()->\n @$el.parent().show()\n\n hide: ()->\n @$el.parent().hide()\n\n toggle: ()->\n @$el.parent().toggle()\n"},{"className":"Luca.containers.CardView","file":"src/containers/card_view.coffee","source":"_.def(\"Luca.containers.CardView\").extends(\"Luca.core.Container\").with\n componentType: 'card_view'\n\n className: 'luca-ui-card-view-wrapper'\n\n activeCard: 0\n\n components: []\n\n hooks:[\n 'before:card:switch',\n 'after:card:switch'\n ]\n\n componentClass: 'luca-ui-card'\n appendContainers: true\n\n initialize: (@options)->\n Luca.core.Container::initialize.apply @,arguments\n @setupHooks(@hooks)\n\n prepareComponents: ()->\n Luca.core.Container::prepareComponents?.apply(@, arguments)\n\n _( @components ).each (component,index)=>\n if index is @activeCard\n $( component.container ).show()\n else\n $( component.container ).hide()\n\n activeComponentElement: ()->\n @componentElements().eq( @activeCard )\n\n activeComponent: ()->\n @getComponent( @activeCard )\n\n customizeContainerEl: (containerEl, panel, panelIndex)->\n containerEl.style += if panelIndex is @activeCard then \"display:block;\" else \"display:none;\"\n\n containerEl\n\n cycle: ()->\n nextIndex = if @activeCard < @components.length - 1 then @activeCard + 1 else 0\n @activate( nextIndex )\n\n find: (name)->\n @findComponentByName(name,true)\n\n firstActivation: ()->\n @activeComponent().trigger \"first:activation\", @, @activeComponent()\n\n activate: (index, silent=false, callback)->\n if _.isFunction(silent)\n silent = false\n callback = silent\n\n return if index is @activeCard\n\n previous = @activeComponent()\n current = @getComponent(index)\n\n if !current\n index = @indexOf(index)\n current = @getComponent( index )\n\n unless current\n return\n\n unless silent\n @trigger \"before:card:switch\", previous, current\n previous?.trigger?.apply(previous,[\"before:deactivation\", @, previous, current])\n current?.trigger?.apply(previous,[\"before:activation\", @, previous, current])\n\n _.defer ()=>\n @$el.data( @activeAttribute || \"active-card\", current.name)\n\n @componentElements().hide()\n\n unless current.previously_activated\n current.trigger \"first:activation\"\n current.previously_activated = true\n\n @activeCard = index\n @activeComponentElement().show()\n\n unless silent\n @trigger \"after:card:switch\", previous, current\n previous.trigger?.apply(previous, [\"deactivation\", @, previous, current])\n current.trigger?.apply(current, [\"activation\", @, previous, current])\n\n\n if _.isFunction(callback)\n callback.apply @, [@,previous,current]"},{"className":"Luca.containers.ColumnView","file":"src/containers/column_view.coffee","source":"_.def('Luca.containers.ColumnView').extends('Luca.core.Container').with\n componentType: 'column_view'\n\n className: 'luca-ui-column-view'\n\n components: []\n\n initialize: (@options={})->\n Luca.core.Container::initialize.apply @, arguments\n @setColumnWidths()\n\n componentClass: 'luca-ui-column'\n\n containerTemplate: \"containers/basic\"\n\n appendContainers: true\n\n autoColumnWidths: ()->\n widths = []\n\n _( @components.length ).times ()=>\n widths.push( parseInt( 100 / @components.length ) )\n\n widths\n\n setColumnWidths: ()->\n @columnWidths = if @layout?\n _( @layout.split('/') ).map((v)-> parseInt(v) )\n else\n @autoColumnWidths()\n\n @columnWidths = _( @columnWidths ).map (val)-> \"#{ val }%\"\n\n beforeLayout: ()->\n @debug \"column_view before layout\"\n\n _(@columnWidths).each (width,index) =>\n @components[index].float = \"left\"\n @components[index].width = width\n\n Luca.core.Container::beforeLayout?.apply @, arguments"},{"className":"Luca.ModalView","file":"src/containers/modal_view.coffee","source":"_.def(\"Luca.ModalView\").extends(\"Luca.View\").with\n\n closeOnEscape: true\n\n showOnInitialize: false\n\n backdrop: false\n\n container: ()->\n $('body')\n\n toggle: ()->\n @$el.modal('toggle')\n\n show: ()->\n @$el.modal('show')\n\n hide: ()->\n @$el.modal('hide')\n\n render: ()->\n @$el.addClass 'modal'\n @$el.addClass 'fade' if @fade is true\n\n $('body').append( @$el )\n\n @$el.modal\n backdrop: @backdrop is true\n keyboard: @closeOnEscape is true\n show: @showOnInitialize is true\n\n_.def(\"Luca.containers.ModalView\").extends(\"Luca.ModalView\").with()"},{"className":"Luca.containers.ModalView","file":"src/containers/modal_view.coffee","source":"_.def(\"Luca.ModalView\").extends(\"Luca.View\").with\n\n closeOnEscape: true\n\n showOnInitialize: false\n\n backdrop: false\n\n container: ()->\n $('body')\n\n toggle: ()->\n @$el.modal('toggle')\n\n show: ()->\n @$el.modal('show')\n\n hide: ()->\n @$el.modal('hide')\n\n render: ()->\n @$el.addClass 'modal'\n @$el.addClass 'fade' if @fade is true\n\n $('body').append( @$el )\n\n @$el.modal\n backdrop: @backdrop is true\n keyboard: @closeOnEscape is true\n show: @showOnInitialize is true\n\n_.def(\"Luca.containers.ModalView\").extends(\"Luca.ModalView\").with()"},{"className":"Luca.containers.PanelToolbar","file":"src/containers/panel_toolbar.coffee","source":"\n# button config accepts the following paramters:\n#\n# label what should the button say\n# eventId what event should the button trigger\n# dropdown an array of arrays: [eventId, label]\n# group an array of button configs\n# wrapper a css class, in addition to btn-group\n# icon which icon do you want to use on this button?\n# white true or false: is it a white colored text?\n# color options are primary, info, success, warning, danger, inverse\n\nmake = Backbone.View::make\n\nbuildButton = (config, wrap=true)->\n if config.ctype?\n config.className ||= \"\"\n config.className += 'toolbar-component'\n\n object = Luca(config).render()\n if Luca.isBackboneView(object)\n console.log \"Adding toolbar component\", object\n return object.el\n\n if config.spacer\n return make \"div\", class: \"spacer #{ config.spacer }\"\n\n if config.text\n return make \"div\", {class: \"toolbar-text\"}, config.text\n\n wrapper = 'btn-group'\n wrapper += \" #{ config.wrapper }\" if config.wrapper?\n wrapper += \" align-#{ config.align }\" if config.align?\n\n # if we're passed a group, then we need to just\n # wrap the contents of the buttons property in that group\n # skipping the btn-group wrapping that takes place for\n # individual buttons\n if config.group? and config.buttons?\n buttons = prepareButtons( config.buttons, false )\n return make \"div\", class: wrapper, buttons\n\n # if it is a normal button, and not a button group\n else\n label = config.label ||= \"\"\n\n config.eventId ||= _.string.dasherize( config.label.toLowerCase() )\n\n if config.icon\n label = \" \" if _.string.isBlank( label )\n white = \"icon-white\" if config.white\n label = \"<i class='#{ white || \"\" } icon-#{ config.icon }' /> #{ label }\"\n\n buttonAttributes =\n class: _.compact([\"btn\",config.classes,config.className]).join(\" \")\n \"data-eventId\" : config.eventId\n title: config.title || config.description\n\n buttonAttributes[\"class\"] += \" btn-#{ config.color }\" if config.color?\n\n if config.dropdown\n label = \"#{ label } <span class='caret'></span>\"\n buttonAttributes[\"class\"] += \" dropdown-toggle\"\n buttonAttributes[\"data-toggle\"] = \"dropdown\"\n\n dropdownItems = _(config.dropdown).map (dropdownItem)=>\n link = make \"a\", {}, dropdownItem[1]\n make \"li\", {\"data-eventId\": dropdownItem[0]}, link\n\n dropdownEl = make \"ul\", {class:\"dropdown-menu\"}, dropdownItems\n\n buttonEl = make \"a\", buttonAttributes, label\n\n # needs to be wrapped for proper rendering, but not\n # if it already is part of a group\n autoWrapClass = \"btn-group\"\n autoWrapClass += \" align-#{ config.align }\" if config.align?\n\n if wrap is true\n return make \"div\", {class: autoWrapClass}, [buttonEl,dropdownEl]\n else\n # for buttons which are already part f a group\n buttonEl\n\nprepareButtons = (buttons, wrap=true)->\n _( buttons ).map (button)->\n buildButton(button, wrap)\n\n\n#### Panel Toolbar Component\n#\n# The Panel Toolbar is a collection of buttons and / or dropdowns\n# which are automatically created by BasicPanel classes, or can be\n# added to any other view component.\n_.def(\"Luca.containers.PanelToolbar\").extends(\"Luca.View\").with\n\n className: \"luca-ui-toolbar btn-toolbar\"\n\n # @buttons is an array of button config objects\n\n\n buttons:[]\n\n well: true\n\n orientation: 'top'\n\n autoBindEventHandlers: true\n\n events:\n \"click a.btn, click .dropdown-menu li\" : \"clickHandler\"\n\n #autoBindEventHandlers: true\n\n # The Toolbar behaves by triggering events on the components which they\n # belong to. Combined with Luca.View::setupHooks it is a clean way\n # to organize actions\n clickHandler: (e)->\n me = my = $( e.target )\n\n if me.is('i')\n me = my = $( e.target ).parent()\n\n eventId = my.data('eventid')\n\n return unless eventId?\n\n hook = Luca.util.hook( eventId )\n\n source = @parent || @\n if _.isFunction( source[hook] )\n source[ hook ].call(@, me, e)\n else\n source.trigger(eventId, me, e)\n\n beforeRender:()->\n @_super(\"beforeRender\", @, arguments)\n\n if @well is true\n @$el.addClass 'well'\n\n @$el.addClass \"toolbar-#{ @orientation }\"\n\n @applyStyles( @styles ) if @styles?\n\n render: ()->\n @$el.empty()\n\n elements = prepareButtons(@buttons)\n _( elements ).each (element)=>\n @$el.append( element )\n"},{"className":"Luca.containers.PanelView","file":"src/containers/panel_view.coffee","source":"_.def('Luca.containers.PanelView').extends('Luca.core.Container').with\n className: 'luca-ui-panel'\n\n initialize: (@options={})->\n Luca.core.Container::initialize.apply @, arguments\n\n afterLayout: ()->\n if @template\n contents = ( Luca.templates || JST )[ @template ]( @ )\n @$el.html(contents)\n\n render: ()->\n $(@container).append @$el\n\n afterRender: ()->\n Luca.core.Container::afterRender?.apply @, arguments\n if @css\n _( @css ).each (value,property)=>\n @$el.css(property,value)\n\n\n\n\n"},{"className":"Luca.containers.SplitView","file":"src/containers/split_view.coffee","source":"_.def('Luca.containers.SplitView').extends('Luca.core.Container').with\n componentType: 'split_view'\n\n containerTemplate: 'containers/basic'\n\n className: 'luca-ui-split-view'\n\n componentClass: 'luca-ui-panel'"},{"className":"Luca.containers.TabView","file":"src/containers/tab_view.coffee","source":"_.def('Luca.containers.TabView').extends('Luca.containers.CardView').with\n\n hooks:[\n \"before:select\"\n \"after:select\"\n ]\n\n componentType: 'tab_view'\n\n className: 'luca-ui-tab-view tabbable'\n\n tab_position: 'top'\n\n tabVerticalOffset: '50px'\n\n navClass: \"nav-tabs\"\n\n bodyTemplate: \"containers/tab_view\"\n bodyEl: \"div.tab-content\"\n\n initialize: (@options={})->\n @navClass = \"nav-list\"if @navStyle is \"list\"\n\n Luca.containers.CardView::initialize.apply @, arguments\n\n _.bindAll @, \"select\", \"highlightSelectedTab\"\n\n @setupHooks( @hooks )\n\n @bind \"after:card:switch\", @highlightSelectedTab\n\n activeTabSelector: ()->\n @tabSelectors().eq( @activeCard || @activeTab || @activeItem )\n\n beforeLayout: ()->\n @$el.addClass(\"tabs-#{ @tab_position }\")\n @activeTabSelector().addClass 'active'\n\n @createTabSelectors()\n\n Luca.containers.CardView::beforeLayout?.apply @, arguments\n\n afterRender: ()->\n Luca.containers.CardView::afterRender?.apply @, arguments\n @registerEvent(\"click ##{ @cid }-tabs-selector li a\", \"select\")\n\n if Luca.enableBootstrap and (@tab_position is \"left\" or @tab_position is \"right\")\n @tabContainerWrapper().addClass(\"span2\")\n @tabContentWrapper().addClass(\"span9\")\n\n\n createTabSelectors: ()->\n tabView = @\n @each (component,index)->\n icon = \"<i class='icon-#{ component.tabIcon }\" if component.tabIcon\n link = \"<a href='#'>#{ icon || ''} #{ component.title }</a>\"\n selector = tabView.make(\"li\",{class:\"tab-selector\",\"data-target\":index}, link)\n tabView.tabContainer().append(selector)\n\n if component.navHeading? and not tabView.navHeadings?[ component.navHeading ]\n $( selector ).before( tabView.make('li',{class:\"nav-header\"}, component.navHeading))\n tabView.navHeadings ||= {}\n tabView.navHeadings[ component.navHeading ] = true\n\n highlightSelectedTab: ()->\n @tabSelectors().removeClass('active')\n @activeTabSelector().addClass('active')\n\n select: (e)->\n e.preventDefault()\n\n me = my = $( e.target )\n\n @trigger \"before:select\", @\n @activate my.parent().data('target')\n @trigger \"after:select\", @\n\n componentElements: ()->\n @$(\">.tab-content >.#{ @componentClass }\")\n\n tabContentWrapper: ()->\n $(\"##{ @cid }-tab-view-content\")\n\n tabContainerWrapper: ()->\n $(\"##{ @cid }-tabs-selector\")\n\n tabContainer: ()->\n @$(\"ul.#{ @navClass }\", @tabContainerWrapper() )\n\n tabSelectors: ()->\n @$( 'li.tab-selector', @tabContainer() )"},{"className":"Luca.containers.Viewport","file":"src/containers/viewport.coffee","source":"_.def('Luca.containers.Viewport').extend('Luca.containers.CardView').with\n\n activeItem: 0\n\n additionalClassNames: 'luca-ui-viewport'\n\n fullscreen: true\n\n fluid: false\n\n wrapperClass: 'row'\n\n initialize: (@options={})->\n _.extend @, @options\n\n if Luca.enableBootstrap is true\n @wrapperClass = \"row-fluid fluid-viewport-wrapper\" if @fluid is true\n\n Luca.core.Container::initialize.apply(@, arguments)\n\n $('html,body').addClass('luca-ui-fullscreen') if @fullscreen\n\n beforeRender: ()->\n Luca.containers.CardView::beforeRender?.apply(@, arguments)\n\n #if Luca.enableBootstrap and @topNav and @fullscreen\n # $('body').css('padding','40px')\n\n @renderTopNavigation() if @topNav?\n @renderBottomNavigation() if @bottomNav?\n\n afterRender: ()->\n Luca.containers.CardView::after?.apply(@, arguments)\n\n if Luca.enableBootstrap is true and @containerClassName\n @$el.children().wrap('<div class=\"#{ containerClassName }\" />')\n\n renderTopNavigation: ()->\n return unless @topNav?\n\n if _.isString( @topNav )\n @topNav = Luca.util.lazyComponent(@topNav)\n\n if _.isObject( @topNav )\n @topNav.ctype ||= @topNav.type || \"nav_bar\"\n unless Luca.isBackboneView(@topNav)\n @topNav = Luca.util.lazyComponent( @topNav )\n\n @topNav.app = @\n\n $('body').prepend( @topNav.render().el )\n\n renderBottomNavigation: ()->\n # IMPLEMENT\n\n"},{"className":"Luca.Collection","file":"src/core/collection.coffee","source":"source = 'Backbone.Collection'\nsource = 'Backbone.QueryCollection' if Backbone.QueryCollection?\n\n_.def(\"Luca.Collection\").extends( source ).with\n # cachedMethods refers to a list of methods on the collection\n # whose value gets cached once it is ran. the collection then\n # binds to change, add, remove, and reset events and then expires\n # the cached value once these events are fired.\n\n # cachedMethods expects an array of strings representing the method name\n # or objects containing @method and @resetEvents properties. by default\n # @resetEvents are 'add','remove',reset' and 'change'.\n cachedMethods: []\n\n # if filtering a collection should handle via a call to a REST API\n # and return the filtered results that way, then leave this true\n remoteFilter: false\n\n initialize: (models=[], @options)->\n _.extend @, @options\n @setupMethodCaching()\n @_reset()\n\n # By specifying a @cache_key property or method, you can instruct\n # Luca.Collection instances where to pull an array of model attributes\n # usually done with the bootstrap functionality provided.\n\n # DEPRECATION NOTICE\n if @cached\n console.log 'The @cached property of Luca.Collection is being deprecated. Please change to cache_key'\n\n if @cache_key ||= @cached\n @bootstrap_cache_key = if _.isFunction( @cache_key ) then @cache_key() else @cache_key\n\n if @registerAs or @registerWith\n console.log \"This configuration API is deprecated. use @name and @manager properties instead\"\n\n # support the older configuration API\n @name ||= @registerAs\n @manager ||= @registerWith\n\n @manager = if _.isFunction(@manager) then @manager() else @manager\n\n # if they specify a\n if @name and not @manager\n @manager = Luca.CollectionManager.get()\n\n # If we are going to be registering this collection with the CollectionManager\n # class, then we need to specify a key to register ourselves under. @registerAs can be\n # as simple as something as \"books\", or if you are using collections which need\n # to be scoped with some sort of unique id, as say some sort of belongsTo relationship\n # then you can specify @registerAs as a method()\n if @manager\n @name ||= @cache_key()\n @name = if _.isFunction( @name ) then @name() else @name\n\n unless @private or @anonymous\n @bind \"after:initialize\", ()=>\n @register( @manager, @name, @)\n\n # by passing useLocalStorage = true to your collection definition\n # you will bypass the RESTful persistence layer and just persist everything\n # locally in localStorage\n if @useLocalStorage is true and window.localStorage?\n table = @bootstrap_cache_key || @name\n throw \"Must specify either a cached or registerAs property to use localStorage\"\n @localStorage = new Luca.LocalStore( table )\n\n # Populating a collection with local data\n #\n # by specifying a @data property which is an array\n # then you can set the collection to be a @memoryCollection\n # which never interacts with a persistence layer at all.\n #\n # this is mainly used by the Luca.fields.SelectField class for\n # generating simple select fields with static data\n if _.isArray(@data) and @data.length > 0\n @memoryCollection = true\n\n @__wrapUrl() unless @useNormalUrl is true\n\n Backbone.Collection::initialize.apply @, [models, @options]\n\n if models\n @reset models, silent: true, parse: options?.parse\n\n @trigger \"after:initialize\"\n\n # Luca.Collections will append a query string to the URL\n # and will automatically do this for you without you having\n # to write a special url handler. If you want to use a normal\n # url without this feature, just set @useNormalUrl = true\n __wrapUrl: ()->\n if _.isFunction(@url)\n @url = _.wrap @url, (fn)=>\n val = fn.apply @\n parts = val.split('?')\n\n existing_params = _.last(parts) if parts.length > 1\n\n queryString = @queryString()\n\n if existing_params and val.match(existing_params)\n queryString = queryString.replace( existing_params, '')\n\n new_val = \"#{ val }?#{ queryString }\"\n new_val = new_val.replace(/\\?$/,'') if new_val.match(/\\?$/)\n\n new_val\n else\n url = @url\n params = @queryString()\n\n @url = _([url,params]).compact().join(\"?\")\n\n queryString: ()->\n parts = _( @base_params ||= Luca.Collection.baseParams() ).inject (memo, value, key)=>\n str = \"#{ key }=#{ value }\"\n memo.push(str)\n memo\n , []\n\n _.uniq(parts).join(\"&\")\n\n resetFilter: ()->\n @base_params = _( Luca.Collection.baseParams() ).clone()\n @\n\n applyFilter: (filter={}, options={})->\n if options.remote? is true or @remoteFilter is true\n @applyParams(filter)\n @fetch _.extend(options,refresh:true)\n else\n @reset @query filter\n\n # You can apply params to a collection, so that any upcoming requests\n # made to the REST API are made with the key values specified\n applyParams: (params)->\n @base_params = _( Luca.Collection.baseParams() ).clone()\n _.extend @base_params, params\n\n @\n\n # If this collection is to be registered with some global collection\n # tracker such as new Luca.CollectionManager() then we will register\n # ourselves automatically\n #\n # To automatically register a collection with the registry, instantiate\n # it with the registerWith property, which can either be a reference to\n # the manager itself, or a string in case the manager isn't available\n # at compile time\n register: (collectionManager=Luca.CollectionManager.get(), key=\"\", collection)->\n throw \"Can not register with a collection manager without a key\" unless key.length >= 1\n throw \"Can not register with a collection manager without a valid collection manager\" unless collectionManager?\n\n # by passing a string instead of a reference to an object, we can look up\n # that object only when necessary. this prevents us from having to create\n # the manager instance before we can define our collections\n if _.isString( collectionManager )\n collectionManager = Luca.util.nestedValue( collectionManager, (window || global) )\n\n throw \"Could not register with collection manager\" unless collectionManager\n\n if _.isFunction( collectionManager.add )\n return collectionManager.add(key, collection)\n\n if _.isObject( collectionManager )\n collectionManager[ key ] = collection\n\n # A Luca.Collection will load models from the in memory model store\n # returned from Luca.Collection.cache, where the key returned from\n # the @cache_keyattribute or method matches the key of the model cache\n loadFromBootstrap: ()->\n return unless @bootstrap_cache_key\n @reset @cached_models()\n @trigger \"bootstrapped\", @\n\n # an alias for loadFromBootstrap which is a bit more descriptive\n bootstrap: ()->\n @loadFromBootstrap()\n\n # cached_models is a reference to the Luca.Collection.cache object\n # key'd on whatever this collection's bootstrap_cache_key is set to be\n # via the @cache_key() interface\n cached_models: ()->\n Luca.Collection.cache( @bootstrap_cache_key )\n\n # Luca.Collection overrides the default Backbone.Collection.fetch method\n # and triggers an event \"before:fetch\" which gives you additional control\n # over the process\n #\n # in addition, it loads models directly from the bootstrap cache instead\n # of going directly to the API\n fetch: (options={})->\n @trigger \"before:fetch\", @\n\n return @reset(@data) if @memoryCollection is true\n\n # fetch will try to pull from the bootstrap if it is setup to do so\n # you can actually make the roundtrip to the server anyway if you pass\n # refresh = true in the options hash\n return @bootstrap() if @cached_models().length and not options.refresh\n\n url = if _.isFunction(@url) then @url() else @url\n\n return true unless ((url and url.length > 1) or @localStorage)\n\n @fetching = true\n\n try\n Backbone.Collection.prototype.fetch.apply @, arguments\n catch e\n console.log \"Error in Collection.fetch\", e\n\n throw e\n\n # onceLoaded is equivalent to binding to the\n # reset trigger with a function wrapped in _.once\n # so that it only gets run...ahem...once.\n #\n # that being said, if the collection already has models\n # it won't even bother fetching it it will just run\n # as if reset was already triggered\n onceLoaded: (fn, options={autoFetch:true})->\n if @length > 0 and not @fetching\n fn.apply @, [@]\n return\n\n wrapped = ()=> fn.apply @,[@]\n\n @bind \"reset\", ()->\n wrapped()\n @unbind \"reset\", @\n\n unless @fetching or not options.autoFetch\n @fetch()\n\n # ifLoaded is equivalent to binding to the reset trigger with\n # a function, if the collection already has models it will just\n # run automatically. similar to onceLoaded except the binding\n # stays in place\n ifLoaded: (fn, options={scope:@,autoFetch:true})->\n scope = options.scope || @\n\n if @length > 0 and not @fetching\n fn.apply scope, [@]\n\n @bind \"reset\", (collection)=> fn.call(scope,collection)\n\n unless @fetching is true or !options.autoFetch or @length > 0\n @fetch()\n\n # parse is very close to the stock Backbone.Collection parse, which\n # just returns the response. However, it also triggers a callback\n # after:response, and automatically parses responses which contain\n # a JSON root like you would see in rails, if you specify the @root\n # property.\n #\n # it will also update the Luca.Collection.cache with the models from\n # the response, so that any subsequent calls to fetch() on a bootstrapped\n # collection, will have updated models from the server. Really only\n # useful if you call fetch(refresh:true) manually on any bootstrapped\n # collection\n parse: (response)->\n @fetching = false\n @trigger \"after:response\", response\n models = if @root? then response[ @root ] else response\n\n if @bootstrap_cache_key\n Luca.Collection.cache( @bootstrap_cache_key, models)\n\n models\n\n # Method Caching\n #\n # Method Caching is a way of saving the output of a method on your collection.\n # And then expiring that value if any changes are detected to the models in\n # the collection\n restoreMethodCache: ()->\n for name, config of @_methodCache\n if config.original?\n config.args = undefined\n @[ name ] = config.original\n\n clearMethodCache: (method)->\n @_methodCache[method].value = undefined\n\n clearAllMethodsCache: ()->\n for name, config of @_methodCache\n @clearMethodCache(name)\n\n setupMethodCaching: ()->\n collection = @\n membershipEvents = [\"reset\",\"add\",\"remove\"]\n cache = @_methodCache = {}\n\n _( @cachedMethods ).each (method)->\n # store a reference to the unwrapped version of the method\n # and a placeholder for the cached value\n cache[ method ] =\n name: method\n original: collection[method]\n value: undefined\n\n # wrap the collection method with a basic memoize operation\n collection[ method ] = ()->\n cache[method].value ||= cache[method].original.apply collection, arguments\n\n # bind to events on the collection, which once triggered, will\n # invalidate the cached value. causing us to have to restore it\n for membershipEvent in membershipEvents\n collection.bind membershipEvent, ()->\n collection.clearAllMethodsCache()\n\n dependencies = method.split(':')[1]\n\n if dependencies\n for dependency in dependencies.split(\",\")\n collection.bind \"change:#{dependency}\", ()->\n collection.clearMethodCache(method: method)\n\n # make sure the querying interface from backbone.query is present\n # in the case backbone-query isn't loaded. without it, it will\n # just return the models\n query: (filter={},options={})->\n if Backbone.QueryCollection?\n return Backbone.QueryCollection::query.apply(@, arguments)\n else\n @models\n\n# Global Collection Observer\n_.extend Luca.Collection.prototype,\n trigger: ()->\n if Luca.enableGlobalObserver\n Luca.CollectionObserver ||= new Luca.Observer(type:\"collection\")\n Luca.CollectionObserver.relay(@, arguments)\n\n Backbone.View.prototype.trigger.apply @, arguments\n\n# Always include these parameters in every request to your REST API.\n#\n# either specify a function which returns a hash, or just a normal hash\nLuca.Collection.baseParams = (obj)->\n return Luca.Collection._baseParams = obj if obj\n\n if _.isFunction( Luca.Collection._baseParams )\n return Luca.Collection._baseParams()\n\n if _.isObject( Luca.Collection._baseParams )\n Luca.Collection._baseParams\n\n# In order to make our Backbone Apps super fast it is a good practice\n# to pre-populate your collections by what is referred to as bootstrapping\n#\n# Luca.Collections make it easier for you to do this cleanly and automatically\n#\n# by specifying a @cache_keyproperty or method in your collection definition\n# Luca.Collections will automatically look in this space to find models\n# and avoid a roundtrip to your API unless explicitly told to.\nLuca.Collection._bootstrapped_models = {}\n\n# In order to do this, just load an object whose keys\nLuca.Collection.bootstrap = (obj)->\n _.extend Luca.Collection._bootstrapped_models, obj\n\n# Lookup cached() or bootstrappable models. This is used by the\n# augmented version of Backbone.Collection.fetch() in order to avoid\n# roundtrips to the API\nLuca.Collection.cache = (key, models)->\n return Luca.Collection._bootstrapped_models[ key ] = models if models\n Luca.Collection._bootstrapped_models[ key ] || []\n"},{"className":"Luca.core.Container","file":"src/core/container.coffee","source":"# The Component Container\n#\n# The Component Container is a nestable component\n# which are responsible for handling communication between multiple\n# nested views.\n#\n# One: Layout\n#\n# a container is responsible for laying out the nested views\n# and rendering them in a special DOM element\ndoLayout = ()->\n @trigger \"before:layout\", @\n @prepareLayout()\n @trigger \"after:layout\", @\n\n# and displaying those elements in a way that is\n# optimal for the desired user experience of that view\n# ( i.e seeing only one of them at a time, seeing them side by side )\napplyDOMConfig = (panel, panelIndex)->\n style_declarations = []\n\n style_declarations.push \"height: #{ (if _.isNumber(panel.height) then panel.height + 'px' else panel.height ) }\" if panel.height?\n style_declarations.push \"width: #{ (if _.isNumber(panel.width) then panel.width + 'px' else panel.width ) }\" if panel.width?\n style_declarations.push \"float: #{ panel.float }\" if panel.float\n\n config =\n class: panel?.classes || @componentClass\n id: \"#{ @cid }-#{ panelIndex }\"\n style: style_declarations.join(';')\n \"data-luca-owner\" : @name || @cid\n\n if @customizeContainerEl?\n config = @customizeContainerEl( config, panel, panelIndex )\n\n config\n\n# Two: Component Creation\n#\n# A container is responsible for creating and storing references to the nested\n# views that are required for its functioning.\ndoComponents = ()->\n\n @trigger \"before:components\", @, @components\n @prepareComponents()\n @createComponents()\n @trigger \"before:render:components\", @, @components\n @renderComponents()\n @trigger \"after:components\", @, @components\n\n\n# Containers are central to Luca. They are what make it easy to structure\n# your application in a logical way and to specify much of the behavior of\n# complex / composite views at define time using JSON syntax combined with\n# the meta data contained in the Luca component registry.\n_.def('Luca.core.Container').extends('Luca.components.Panel').with\n\n className: 'luca-ui-container'\n\n componentTag: 'div'\n componentClass: 'luca-ui-panel'\n\n isContainer: true\n\n hooks:[\n \"before:components\"\n \"before:render:components\"\n \"before:layout\"\n \"after:components\"\n \"after:layout\"\n \"first:activation\"\n ]\n\n rendered: false\n\n components: []\n\n initialize: (@options={})->\n _.extend @, @options\n\n @setupHooks [\n \"before:components\"\n \"before:render:components\"\n \"before:layout\"\n \"after:components\"\n \"after:layout\"\n \"first:activation\"\n ]\n\n Luca.View::initialize.apply @, arguments\n\n # Rendering Pipeline\n #\n # A container has nested components. these components\n # are automatically rendered inside their own DOM element\n # and then CSS configuration is generally applied to these\n # DOM elements. Each component is assigned to this DOM\n # element by specifying a @container property on the component.\n #\n # Each component is instantiated by looking up its @ctype propery\n # in the Luca Component Registry. Then the components are rendered\n # by having their @render() method called on them.\n #\n # Any class which extends Luca.View will have its defined render method\n # wrapped in a method which triggers \"before:render\", and \"after:render\"\n # before and after the defined render method.\n #\n # so you can expect the following, for any container or nested container\n #\n # DOM Element Manipulation:\n #\n # beforeRender()\n # beforeLayout()\n # prepareLayout()\n # afterLayout()\n #\n # Luca / Backbone Component Manipulation\n #\n # beforeComponents()\n # prepareComponents()\n # createComponents()\n # beforeRenderComponents()\n # renderComponents() ->\n # calls render() on each component, starting this whole cycle\n #\n # afterComponents()\n #\n # DOM Injection\n #\n # render()\n # afterRender()\n #\n # For Components which are originally hidden\n # ( card view, tab view, etc )\n #\n # firstActivation()\n #\n beforeRender: ()->\n doLayout.call(@)\n doComponents.call(@)\n Luca.components.Panel::beforeRender?.apply(@, arguments)\n\n # Components which inherit from Luca.core.Container can implement\n # their own versions of this method, if they need to apply any sort\n # of additional styling / configuration for the DOM elements that\n # are created to wrap each container.\n customizeContainerEl: (containerEl, panel, panelIndex)->\n containerEl\n\n prepareLayout: ()->\n container = @\n @componentContainers = _( @components ).map (component, index)->\n applyDOMConfig.call(container, component, index)\n\n # prepare components is where each component gets assigned\n # a container to be rendered into. if @appendContainers is\n # set to true, then the view will automatically $append()\n # elements created via Backbone.View::make() to the body element of the view\n prepareComponents: ()->\n # accept components as an array of strings representing\n # the luca component type\n for component in @components when _.isString(component)\n component = (type: component)\n\n _( @components ).each (component, index)=>\n container = @componentContainers?[index]\n\n # support a variety of the bad naming conventions\n container.class = container.class || container.className || container.classes\n\n if @appendContainers\n panel = @make(@componentTag, container, '')\n @$append( panel )\n\n unless component.container?\n component.container = \"##{ container.id }\" if @appendContainers\n component.container ||= @$bodyEl()\n\n # create components is responsible for turning the JSON syntax of the\n # container's definition into live objects against a given Luca Component\n # type.\n #\n # In addition to this, a container builds an index of the components\n # which belong to it, so that they can easily be looked up by name\n createComponents: ()->\n return if @componentsCreated is true\n\n map = @componentIndex =\n name_index: {}\n cid_index: {}\n\n @components = _( @components ).map (object, index)=>\n\n # you can include normal backbone views as components\n # you will want to make sure your render method handles\n # adding the views @$el to the appropriate @container.\n\n # you can also just pass a string representing the component_type\n component = if Luca.isBackboneView( object )\n object\n else\n object.type ||= object.ctype\n\n if !object.type?\n if object.components?\n object.type = object.ctype = 'container'\n else\n object.type = object.ctype = Luca.defaultComponentType\n\n Luca.util.lazyComponent( object )\n\n # if we're using base backbone views, then they don't extend themselves\n # with their passed options, so this is a workaround to get them to\n # pick up the container config property\n if !component.container and component.options.container\n component.container = component.options.container\n\n if map and component.cid?\n map.cid_index[ component.cid ] = index\n\n if map and component.name?\n map.name_index[ component.name ] = index\n\n component\n\n @componentsCreated = true\n\n @registerComponentEvents() unless _.isEmpty(@componentEvents)\n\n map\n\n # Trigger the Rendering Pipeline process on all of the nested\n # components\n renderComponents: (@debugMode=\"\")->\n @debug \"container render components\"\n _(@components).each (component)=>\n component.getParent = ()=> @\n $( component.container ).append $(component.el)\n\n try\n component.render()\n catch e\n console.log \"Error Rendering Component #{ component.name || component.cid }\", component\n\n if _.isObject(e)\n console.log e.message\n console.log e.stack\n\n throw e unless Luca.silenceRenderErrors? is true\n\n #### Container Activation\n #\n # When a container is first activated is a good time to perform\n # operations which are not needed unless that component becomes\n # visible. This first activation event should be relayed to all\n # of the nested components. Components which hide / display\n # other components, such as a CardView or TabContainer\n # will trigger first:activation on the components as they become\n # displayed.\n firstActivation: ()->\n activator = @\n @each (component, index)->\n # apply the first:activation trigger on the component, in the context of the component\n # passing as arguments the component itself, and the component doing the activation\n unless component?.previously_activated is true\n component?.trigger?.call component, \"first:activation\", component, activator\n component.previously_activated = true\n\n #### Underscore Methods For Working with Components\n pluck: (attribute)-> \n _( @components ).pluck attribute\n\n invoke: (method)->\n _( @components ).invoke method\n\n select: (attribute, value, deep=false)->\n components = _( @components ).map (component)->\n matches = []\n test = component[ attribute ]\n\n matches.push( component ) if test is value\n\n # recursively traverse our components\n matches.push component.select?(attribute, value, true) if deep is true\n\n _.compact matches\n\n _.flatten( components )\n\n # event binding sugar for nested components\n #\n # you can define events like:\n\n # _.def(\"MyContainer\").extends(\"Luca.View\").with\n # componentEvents:\n # \"component_name before:load\" : \"mySpecialHandler\"\n #\n componentEvents: {}\n\n registerComponentEvents: ()->\n for listener, handler of @componentEvents\n [componentName,trigger] = listener.split(' ')\n component = @findComponentByName(componentName)\n component?.bind trigger, @[handler]\n\n findComponentByName: (name, deep=false)->\n @findComponent(name, \"name_index\", deep)\n\n findComponentById: (id, deep=false)->\n @findComponent(id, \"cid_index\", deep)\n\n findComponent: (needle, haystack=\"name\", deep=false)->\n @createComponents() unless @componentsCreated is true\n\n\n position = @componentIndex?[ haystack ][ needle ]\n component = @components?[ position ]\n\n return component if component\n\n if deep is true\n sub_container = _( @components ).detect (component)-> component?.findComponent?(needle, haystack, true)\n sub_container?.findComponent?(needle, haystack, true)\n\n each: (fn)->\n @eachComponent(fn, false)\n\n # run a function for each component in this container\n # and any nested containers in those components, recursively\n # pass false as the second argument to skip the deep recursion\n eachComponent: (fn, deep=true)->\n _( @components ).each (component, index)=>\n fn.call component, component, index\n component?.eachComponent?.apply component, [fn,deep] if deep\n\n indexOf: (name)->\n names = _( @components ).pluck('name')\n _( names ).indexOf(name)\n\n activeComponent: ()->\n return @ unless @activeItem\n return @components[ @activeItem ]\n\n componentElements: ()->\n $(\">.#{ @componentClass }\", @el)\n\n getComponent: (needle)->\n @components[ needle ]\n\n rootComponent: ()->\n !@getParent?\n\n getRootComponent: ()->\n if @rootComponent() then @ else @getParent().getRootComponent()"},{"className":"MyContainer","file":"src/core/container.coffee","source":"# The Component Container\n#\n# The Component Container is a nestable component\n# which are responsible for handling communication between multiple\n# nested views.\n#\n# One: Layout\n#\n# a container is responsible for laying out the nested views\n# and rendering them in a special DOM element\ndoLayout = ()->\n @trigger \"before:layout\", @\n @prepareLayout()\n @trigger \"after:layout\", @\n\n# and displaying those elements in a way that is\n# optimal for the desired user experience of that view\n# ( i.e seeing only one of them at a time, seeing them side by side )\napplyDOMConfig = (panel, panelIndex)->\n style_declarations = []\n\n style_declarations.push \"height: #{ (if _.isNumber(panel.height) then panel.height + 'px' else panel.height ) }\" if panel.height?\n style_declarations.push \"width: #{ (if _.isNumber(panel.width) then panel.width + 'px' else panel.width ) }\" if panel.width?\n style_declarations.push \"float: #{ panel.float }\" if panel.float\n\n config =\n class: panel?.classes || @componentClass\n id: \"#{ @cid }-#{ panelIndex }\"\n style: style_declarations.join(';')\n \"data-luca-owner\" : @name || @cid\n\n if @customizeContainerEl?\n config = @customizeContainerEl( config, panel, panelIndex )\n\n config\n\n# Two: Component Creation\n#\n# A container is responsible for creating and storing references to the nested\n# views that are required for its functioning.\ndoComponents = ()->\n\n @trigger \"before:components\", @, @components\n @prepareComponents()\n @createComponents()\n @trigger \"before:render:components\", @, @components\n @renderComponents()\n @trigger \"after:components\", @, @components\n\n\n# Containers are central to Luca. They are what make it easy to structure\n# your application in a logical way and to specify much of the behavior of\n# complex / composite views at define time using JSON syntax combined with\n# the meta data contained in the Luca component registry.\n_.def('Luca.core.Container').extends('Luca.components.Panel').with\n\n className: 'luca-ui-container'\n\n componentTag: 'div'\n componentClass: 'luca-ui-panel'\n\n isContainer: true\n\n hooks:[\n \"before:components\"\n \"before:render:components\"\n \"before:layout\"\n \"after:components\"\n \"after:layout\"\n \"first:activation\"\n ]\n\n rendered: false\n\n components: []\n\n initialize: (@options={})->\n _.extend @, @options\n\n @setupHooks [\n \"before:components\"\n \"before:render:components\"\n \"before:layout\"\n \"after:components\"\n \"after:layout\"\n \"first:activation\"\n ]\n\n Luca.View::initialize.apply @, arguments\n\n # Rendering Pipeline\n #\n # A container has nested components. these components\n # are automatically rendered inside their own DOM element\n # and then CSS configuration is generally applied to these\n # DOM elements. Each component is assigned to this DOM\n # element by specifying a @container property on the component.\n #\n # Each component is instantiated by looking up its @ctype propery\n # in the Luca Component Registry. Then the components are rendered\n # by having their @render() method called on them.\n #\n # Any class which extends Luca.View will have its defined render method\n # wrapped in a method which triggers \"before:render\", and \"after:render\"\n # before and after the defined render method.\n #\n # so you can expect the following, for any container or nested container\n #\n # DOM Element Manipulation:\n #\n # beforeRender()\n # beforeLayout()\n # prepareLayout()\n # afterLayout()\n #\n # Luca / Backbone Component Manipulation\n #\n # beforeComponents()\n # prepareComponents()\n # createComponents()\n # beforeRenderComponents()\n # renderComponents() ->\n # calls render() on each component, starting this whole cycle\n #\n # afterComponents()\n #\n # DOM Injection\n #\n # render()\n # afterRender()\n #\n # For Components which are originally hidden\n # ( card view, tab view, etc )\n #\n # firstActivation()\n #\n beforeRender: ()->\n doLayout.call(@)\n doComponents.call(@)\n Luca.components.Panel::beforeRender?.apply(@, arguments)\n\n # Components which inherit from Luca.core.Container can implement\n # their own versions of this method, if they need to apply any sort\n # of additional styling / configuration for the DOM elements that\n # are created to wrap each container.\n customizeContainerEl: (containerEl, panel, panelIndex)->\n containerEl\n\n prepareLayout: ()->\n container = @\n @componentContainers = _( @components ).map (component, index)->\n applyDOMConfig.call(container, component, index)\n\n # prepare components is where each component gets assigned\n # a container to be rendered into. if @appendContainers is\n # set to true, then the view will automatically $append()\n # elements created via Backbone.View::make() to the body element of the view\n prepareComponents: ()->\n # accept components as an array of strings representing\n # the luca component type\n for component in @components when _.isString(component)\n component = (type: component)\n\n _( @components ).each (component, index)=>\n container = @componentContainers?[index]\n\n # support a variety of the bad naming conventions\n container.class = container.class || container.className || container.classes\n\n if @appendContainers\n panel = @make(@componentTag, container, '')\n @$append( panel )\n\n unless component.container?\n component.container = \"##{ container.id }\" if @appendContainers\n component.container ||= @$bodyEl()\n\n # create components is responsible for turning the JSON syntax of the\n # container's definition into live objects against a given Luca Component\n # type.\n #\n # In addition to this, a container builds an index of the components\n # which belong to it, so that they can easily be looked up by name\n createComponents: ()->\n return if @componentsCreated is true\n\n map = @componentIndex =\n name_index: {}\n cid_index: {}\n\n @components = _( @components ).map (object, index)=>\n\n # you can include normal backbone views as components\n # you will want to make sure your render method handles\n # adding the views @$el to the appropriate @container.\n\n # you can also just pass a string representing the component_type\n component = if Luca.isBackboneView( object )\n object\n else\n object.type ||= object.ctype\n\n if !object.type?\n if object.components?\n object.type = object.ctype = 'container'\n else\n object.type = object.ctype = Luca.defaultComponentType\n\n Luca.util.lazyComponent( object )\n\n # if we're using base backbone views, then they don't extend themselves\n # with their passed options, so this is a workaround to get them to\n # pick up the container config property\n if !component.container and component.options.container\n component.container = component.options.container\n\n if map and component.cid?\n map.cid_index[ component.cid ] = index\n\n if map and component.name?\n map.name_index[ component.name ] = index\n\n component\n\n @componentsCreated = true\n\n @registerComponentEvents() unless _.isEmpty(@componentEvents)\n\n map\n\n # Trigger the Rendering Pipeline process on all of the nested\n # components\n renderComponents: (@debugMode=\"\")->\n @debug \"container render components\"\n _(@components).each (component)=>\n component.getParent = ()=> @\n $( component.container ).append $(component.el)\n\n try\n component.render()\n catch e\n console.log \"Error Rendering Component #{ component.name || component.cid }\", component\n\n if _.isObject(e)\n console.log e.message\n console.log e.stack\n\n throw e unless Luca.silenceRenderErrors? is true\n\n #### Container Activation\n #\n # When a container is first activated is a good time to perform\n # operations which are not needed unless that component becomes\n # visible. This first activation event should be relayed to all\n # of the nested components. Components which hide / display\n # other components, such as a CardView or TabContainer\n # will trigger first:activation on the components as they become\n # displayed.\n firstActivation: ()->\n activator = @\n @each (component, index)->\n # apply the first:activation trigger on the component, in the context of the component\n # passing as arguments the component itself, and the component doing the activation\n unless component?.previously_activated is true\n component?.trigger?.call component, \"first:activation\", component, activator\n component.previously_activated = true\n\n #### Underscore Methods For Working with Components\n pluck: (attribute)-> \n _( @components ).pluck attribute\n\n invoke: (method)->\n _( @components ).invoke method\n\n select: (attribute, value, deep=false)->\n components = _( @components ).map (component)->\n matches = []\n test = component[ attribute ]\n\n matches.push( component ) if test is value\n\n # recursively traverse our components\n matches.push component.select?(attribute, value, true) if deep is true\n\n _.compact matches\n\n _.flatten( components )\n\n # event binding sugar for nested components\n #\n # you can define events like:\n\n # _.def(\"MyContainer\").extends(\"Luca.View\").with\n # componentEvents:\n # \"component_name before:load\" : \"mySpecialHandler\"\n #\n componentEvents: {}\n\n registerComponentEvents: ()->\n for listener, handler of @componentEvents\n [componentName,trigger] = listener.split(' ')\n component = @findComponentByName(componentName)\n component?.bind trigger, @[handler]\n\n findComponentByName: (name, deep=false)->\n @findComponent(name, \"name_index\", deep)\n\n findComponentById: (id, deep=false)->\n @findComponent(id, \"cid_index\", deep)\n\n findComponent: (needle, haystack=\"name\", deep=false)->\n @createComponents() unless @componentsCreated is true\n\n\n position = @componentIndex?[ haystack ][ needle ]\n component = @components?[ position ]\n\n return component if component\n\n if deep is true\n sub_container = _( @components ).detect (component)-> component?.findComponent?(needle, haystack, true)\n sub_container?.findComponent?(needle, haystack, true)\n\n each: (fn)->\n @eachComponent(fn, false)\n\n # run a function for each component in this container\n # and any nested containers in those components, recursively\n # pass false as the second argument to skip the deep recursion\n eachComponent: (fn, deep=true)->\n _( @components ).each (component, index)=>\n fn.call component, component, index\n component?.eachComponent?.apply component, [fn,deep] if deep\n\n indexOf: (name)->\n names = _( @components ).pluck('name')\n _( names ).indexOf(name)\n\n activeComponent: ()->\n return @ unless @activeItem\n return @components[ @activeItem ]\n\n componentElements: ()->\n $(\">.#{ @componentClass }\", @el)\n\n getComponent: (needle)->\n @components[ needle ]\n\n rootComponent: ()->\n !@getParent?\n\n getRootComponent: ()->\n if @rootComponent() then @ else @getParent().getRootComponent()"},{"className":"Luca.View","file":"src/core/view.coffee","source":"_.def(\"Luca.View\").extends(\"Backbone.View\").with\n\n additionalClassNames:[]\n\n debug: ()->\n return unless @debugMode or window.LucaDebugMode?\n console.log [(@name || @cid),message] for message in arguments\n\n trigger: ()->\n if Luca.enableGlobalObserver\n if Luca.developmentMode is true or @observeEvents is true\n Luca.ViewObserver ||= new Luca.Observer(type:\"view\")\n Luca.ViewObserver.relay @, arguments\n\n Backbone.View.prototype.trigger.apply @, arguments\n\n hooks:[\n \"after:initialize\"\n \"before:render\"\n \"after:render\"\n \"first:activation\"\n \"activation\"\n \"deactivation\"\n ]\n\n initialize: (@options={})->\n\n _.extend @, @options\n\n @cid = _.uniqueId(@name) if @name?\n\n if template = @bodyTemplate\n @$el.empty()\n Luca.View::$html.call(@, Luca.template(template, @) )\n\n Luca.cache( @cid, @ )\n\n unique = _( Luca.View.prototype.hooks.concat( @hooks ) ).uniq()\n\n @setupHooks( unique )\n\n if @autoBindEventHandlers is true\n @bindAllEventHandlers()\n\n if @additionalClassNames\n @additionalClassNames = @additionalClassNames.split(\" \") if _.isString(@additionalClassNames)\n @$el.addClass( additional ) for additional in @additionalClassNames\n\n @$wrap(@wrapperClass) if @wrapperClass?\n\n @trigger \"after:initialize\", @\n\n @registerCollectionEvents()\n\n @delegateEvents()\n\n #### JQuery / DOM Selector Helpers\n $wrap: (wrapper)->\n if _.isString(wrapper) and not wrapper.match(/[<>]/)\n wrapper = @make(\"div\",class:wrapper)\n\n @$el.wrap( wrapper )\n\n $template: (template, variables={})->\n @$el.html( Luca.template(template,variables) )\n\n $html: (content)->\n @$el.html( content )\n\n $append: (content)->\n @$el.append( content )\n\n #### Containers\n #\n # Luca is heavily reliant on the concept of Container views. Views which\n # contain other views and handle inter-component communication between the\n # component views. The default render() operation consists of building the\n # view's content, and then attaching that view to its container.\n #\n # 99% of the time this would happen automatically\n $attach: ()->\n @$container().append( @el )\n\n $container: ()->\n $(@container)\n\n #### Hooks or Auto Event Binding\n #\n # views which inherit from Luca.View can define hooks\n # or events which can be emitted from them. Automatically,\n # any functions on the view which are named according to the\n # convention will automatically get run.\n #\n # by default, all Luca.View classes come with the following:\n #\n # before:render : beforeRender()\n # after:render : afterRender()\n # after:initialize : afterInitialize()\n # first:activation : firstActivation()\n setupHooks: (set)->\n set ||= @hooks\n\n _(set).each (eventId)=>\n fn = Luca.util.hook( eventId )\n\n callback = ()=>\n @[fn]?.apply @, arguments\n\n callback = _.once(callback) if eventId?.match(/once:/)\n\n @bind eventId, callback\n\n\n #### Luca.Collection and Luca.CollectionManager integration\n\n # under the hood, this will find your collection manager using\n # Luca.CollectionManager.get, which is a function that returns\n # the first instance of the CollectionManager class ever created.\n #\n # if you want to use more than one collection manager, over ride this\n # function in your views with your own logic\n getCollectionManager: ()->\n @collectionManager || Luca.CollectionManager.get?()\n\n ##### Collection Events\n #\n # By defining a hash of collectionEvents in the form of\n #\n # \"books add\" : \"onBookAdd\"\n #\n # the Luca.View will bind to the collection found in the\n # collectionManager with that key, and bind to that event.\n # a property of @booksCollection will be created on the view,\n # and the \"add\" event will trigger \"onBookAdd\"\n #\n # you may also specify a function directly. this\n #\n registerCollectionEvents: ()->\n manager = @getCollectionManager()\n\n _( @collectionEvents ).each (handler, signature)=>\n [key,event] = signature.split(\" \")\n\n collection = @[\"#{ key }Collection\"] = manager.getOrCreate( key )\n\n if !collection\n throw \"Could not find collection specified by #{ key }\"\n\n if _.isString(handler)\n handler = @[handler]\n\n unless _.isFunction(handler)\n throw \"invalid collectionEvents configuration\"\n\n try\n collection.bind(event, handler)\n catch e\n console.log \"Error Binding To Collection in registerCollectionEvents\", @\n throw e\n\n registerEvent: (selector, handler)->\n @events ||= {}\n @events[ selector ] = handler\n @delegateEvents()\n\n bindAllEventHandlers: ()->\n _( @events ).each (handler,event)=>\n if _.isString(handler)\n _.bindAll @, handler\n\n definitionClass: ()->\n Luca.util.resolve(@displayName, window)?.prototype\n\n # refreshCode happens whenever the Luca.Framework extension\n # system is run after there are running instances of a given component\n\n # in the context of views, what this means is that each eventHandler which\n # is bound to a specific object via _.bind or _.bindAll, or autoBindEventHandlers\n # is refreshed with the prototype method of the component that it inherits from,\n # and then delegateEvents is called to refresh any of the updated event handlers\n\n # in addition to this, all properties of the instance of a given view which are\n # also backbone views will have the same process run against them\n refreshCode: ()->\n view = @\n\n _( @eventHandlerProperties() ).each (prop)->\n view[ prop ] = view.definitionClass()[prop]\n\n if @autoBindEventHandlers is true\n @bindAllEventHandlers()\n\n @delegateEvents()\n\n eventHandlerProperties: ()->\n handlerIds = _( @events ).values()\n _( handlerIds ).select (v)->\n _.isString(v)\n\n eventHandlerFunctions: ()->\n handlerIds = _( @events ).values()\n _( handlerIds ).map (handlerId)=>\n if _.isFunction(handlerId) then handlerId else @[handlerId]\n\n collections: ()-> Luca.util.selectProperties( Luca.isBackboneCollection, @ )\n models: ()-> Luca.util.selectProperties( Luca.isBackboneModel, @ )\n views: ()-> Luca.util.selectProperties( Luca.isBackboneView, @ )\n\n\noriginalExtend = Backbone.View.extend\n\ncustomizeRender = (definition)->\n #### Rendering\n #\n # Our base view class wraps the defined render() method\n # of the views which inherit from it, and does things like\n # trigger the before and after render events automatically.\n # In addition, if the view has a deferrable property on it\n # then it will make sure that the render method doesn't get called\n # until.\n\n _base = definition.render\n\n _base ||= Luca.View::$attach\n\n\n definition.render = ()->\n view = @\n # if a view has a deferrable property set\n\n if @deferrable\n target = @deferrable_target\n\n unless Luca.isBackboneCollection(@deferrable)\n @deferrable = @collection\n\n target ||= @deferrable\n trigger = if @deferrable_event then @deferrable_event else \"reset\"\n\n deferred = ()->\n _base.call(view)\n view.trigger(\"after:render\", view)\n\n view.defer(deferred).until(target, trigger)\n\n view.trigger \"before:render\", @\n\n autoTrigger = @deferrable_trigger || @deferUntil\n\n if !autoTrigger?\n target[ (@deferrable_method||\"fetch\") ].call(target)\n else\n fn = _.once ()=> @deferrable[ (@deferrable_method||\"fetch\") ]?()\n (@deferrable_target || @ ).bind(@deferrable_trigger, fn)\n\n return @\n\n else\n @trigger \"before:render\", @\n _base.apply(@, arguments)\n @trigger \"after:render\", @\n\n return @\n\n definition\n\n# By overriding Backbone.View.extend we are able to intercept\n# some method definitions and add special behavior around them\n# mostly related to render()\nLuca.View.extend = (definition)->\n definition = customizeRender( definition )\n originalExtend.call(@, definition)\n\n"},{"className":"MyView","file":"src/core/core.coffee","source":"# Component Definition Helpers\n#\n#\n# We have customized the core Backbone.extend process to use a slightly\n# different syntax, which allows us to intercept the component definition at\n# various points, and maintain information about classes being defined, and\n# the relationships between inherited classes, etc.\n\n# _.def, or Luca.define returns a chainable object which allows you to define\n# your components with a readable syntax. For example:\n\n# _.def(\"Luca.View\").extends(\"Backbone.View\").with the_good:\"shit\"\n# _.def(\"MyView\").extends(\"Luca.View\").with the_custom:\"shit\"\n\nLuca.define = (componentName)->\n new DefineProxy(componentName)\n\nLuca.component = Luca.define\n\n# The define proxy chain sets up a call to Luca.extend, which is a wrapper around Luca and Backbone component class' extend function.\nclass DefineProxy\n constructor:(componentName)->\n @namespace = Luca.util.namespace()\n @componentId = @componentName = componentName\n\n if componentName.match(/\\./)\n @namespaced = true\n parts = componentName.split('.')\n @componentId = parts.pop()\n @namespace = parts.join('.')\n\n # automatically add the namespace to the namespace registry\n Luca.registry.addNamespace( parts.join('.') )\n\n # allow for specifying the namespace\n in: (@namespace)-> @\n\n # allow for multiple ways of saying the same thing for readability purposes\n from: (@superClassName)-> @\n extends: (@superClassName)-> @\n extend: (@superClassName)-> @\n\n # an alias for with, or a readability helper in multi-line definitions\n enhance: (properties)->\n return @with(properties) if properties?\n @\n\n # which properties, methods, etc will you be extending the base class with?\n with: (properties)->\n at = if @namespaced\n Luca.util.resolve(@namespace, (window || global))\n else\n (window||global)\n\n # automatically create the namespace\n if @namespaced and not at?\n eval(\"(window||global).#{ @namespace } = {}\")\n at = Luca.util.resolve(@namespace,(window || global))\n\n at[@componentId] = Luca.extend(@superClassName,@componentName, properties)\n\n if Luca.autoRegister is true \n componentType = \"view\" if Luca.isViewPrototype( at[@componentId] )\n\n if Luca.isCollectionPrototype( at[@componentId] )\n Luca.Collection.namespaces ||= []\n Luca.Collection.namespaces.push( @namespace )\n componentType = \"collection\" \n\n componentType = \"model\" if Luca.isModelPrototype( at[@componentId] )\n\n # automatically register this with the component registry\n Luca.register( _.string.underscored(@componentId), @componentName, componentType)\n\n at[@componentId]\n\n# The last method of the DefineProxy chain is always going to result in\n# a call to Luca.extend. Luca.extend wraps the call to Luca.View.extend,\n# or Backbone.Collection.extend, and accepts the names of the extending,\n# and extended classes as strings. This allows us to maintain information\n# and references to the classes and their prototypes, mainly for the purposes\n# of introspection and development tools\nLuca.extend = (superClassName, childName, properties={})->\n superClass = Luca.util.resolve( superClassName, (window || global) )\n\n unless _.isFunction(superClass?.extend)\n throw \"#{ superClassName } is not a valid component to extend from\"\n\n properties.displayName = childName\n\n properties._superClass = ()->\n superClass.displayName ||= superClassName\n superClass\n\n properties._super = (method, context, args)->\n @_superClass().prototype[method]?.apply(context, args)\n\n superClass.extend(properties)\n\n_.mixin\n def: Luca.define\n\n\n# Luca.Events\n#\n# These helpers will get mixed into Luca.Collection, Luca.View, and Luca.Model.\n#\n# They allow for syntactic sugar like:\n#\n# view.defer(\"someMethodOnTheView\").until(\"collection\",\"fetch\")\n#\n# or\n#\n# view.defer( myCallback ).until(\"triggered:event\")\nclass DeferredBindingProxy\n constructor: (@object, operation, wrapWithUnderscore=true)->\n if _.isFunction(operation)\n fn = operation\n\n else if _.isString(operation) and _.isFunction(@object[operation])\n fn = @object[operation]\n\n unless _.isFunction(fn)\n throw \"Must pass a function or a string representing one\"\n\n if wrapWithUnderscore is true\n @fn = ()=>\n _.defer(fn)\n else\n @fn = fn\n\n @\n\n # until accepts an object to bind to, and a trigger to bind with\n # if you just pass a trigger, the object getting bound to\n # will implicitly be @object\n until: (watch, trigger)->\n if watch? and not trigger?\n trigger = watch\n watch = @object\n\n watch.once(trigger, @fn)\n\n @object\n\nLuca.Events =\n defer: (operation, wrapWithUnderscore=true)->\n new DeferredBindingProxy(@, operation, wrapWithUnderscore)\n\n once: (trigger, callback, context)->\n context ||= @\n\n onceFn = ()->\n callback.apply(context, arguments)\n @unbind(trigger, onceFn)\n\n @bind trigger, onceFn\n\nclass Luca.ScriptLoader\n @loaded: {}\n\n constructor: (options={})->\n _.extend(@, Backbone.Events, Luca.Events)\n @autoStart = options.autoStart is true\n @scripts = options.scripts\n\n ready = ()-> @trigger(\"ready\")\n\n @ready = _.after( @scripts.length, ready)\n\n _.bindAll @, \"load\", \"ready\"\n\n @defer(\"load\").until(@, \"start\")\n\n if @autoStart is true\n @trigger(\"start\")\n\n @bind \"ready\", @onReady\n\n applyPrefix: (script)->\n script\n\n onReady: ()->\n console.log \"All dependencies loaded\"\n\n start: ()->\n @trigger(\"start\")\n\n load: ()->\n Luca.util.loadScript( @applyPrefix(script), @ready ) for script in @scripts\n\n"},{"className":"Luca.core.Field","file":"src/core/field.coffee","source":"_.def('Luca.core.Field').extends('Luca.View').with\n\n className: 'luca-ui-text-field luca-ui-field'\n\n isField: true\n\n template: 'fields/text_field'\n\n labelAlign: 'top'\n\n hooks:[\n \"before:validation\",\n \"after:validation\",\n \"on:change\"\n ]\n\n # see: http://twitter.github.com/bootstrap/base-css.html\n statuses: [\n \"warning\"\n \"error\"\n \"success\"\n ]\n\n initialize: (@options={})->\n _.extend @, @options\n\n @input_id ||= _.uniqueId('field')\n @input_name ||= @name\n @input_class ||= \"\"\n @helperText ||= \"\"\n @label ||= \"*#{ @label }\" if @required and not @label?.match(/^\\*/)\n @inputStyles ||= \"\"\n\n @disable() if @disabled\n\n @updateState( @state )\n @placeHolder ||= \"\"\n\n Luca.View::initialize.apply(@, arguments)\n\n beforeRender: ()->\n if Luca.enableBootstrap\n @$el.addClass('control-group')\n\n @$el.addClass('required') if @required\n\n @$el.html Luca.templates[ @template ]( @ )\n @input = $('input', @el)\n\n change_handler: (e)->\n @trigger \"on:change\", @, e\n\n disable: ()->\n $(\"input\",@el).attr('disabled', true)\n\n enable: ()->\n $(\"input\", @el).attr('disabled', false)\n\n getValue: ()->\n @input.attr('value')\n\n render: ()->\n $( @container ).append( @$el )\n\n setValue: (value)->\n @input.attr('value', value)\n\n updateState: (state)->\n _( @statuses ).each (cls)=>\n @$el.removeClass(cls)\n @$el.addClass(state)"},{"className":"Luca.Model","file":"src/core/model.coffee","source":"# Luca.Model\n#\n# Luca.Model is an extenstion of Backbone.Model which provides\n# few useful patterns:\n#\n# - computed properties support\n_.def('Luca.Model').extends('Backbone.Model').with\n initialize: ()->\n Backbone.Model::initialize @, arguments\n\n return if _.isUndefined(@computed)\n\n @_computed = {}\n\n for attr, dependencies of @computed\n @on \"change:#{attr}\", ()=>\n @_computed[attr] = @[attr].call @\n\n _(dependencies).each (dep)=>\n @on \"change:#{dep}\", ()=>\n @trigger \"change:#{attr}\"\n @trigger \"change:#{attr}\" if @has(dep)\n\n get: (attr)->\n if @computed?.hasOwnProperty(attr)\n @_computed[attr]\n else\n Backbone.Model::get.call @, attr\n"},{"className":"Luca.components.Panel","file":"src/core/panel.coffee","source":"# This is a helper for creating the DOM element that go along with\n# a given component, if it is configured to use one via the topToolbar\n# and bottomToolbar properties\nattachToolbar = (config={}, targetEl)->\n config.orientation ||= \"top\"\n config.ctype ||= @toolbarType || \"panel_toolbar\"\n\n id = \"#{ @cid }-tbc-#{ config.orientation }\"\n\n toolbar = Luca.util.lazyComponent( config )\n\n container = @make \"div\",\n class:\"toolbar-container #{ config.orientation }\",\n id: id\n ,\n toolbar.render().el\n\n hasBody = @bodyClassName or @bodyTagName\n\n # there will be a body panel inside of the views $el\n # so just place the toolbar before, or after the body\n action = switch config.orientation\n when \"top\", \"left\"\n if hasBody then \"before\" else \"prepend\"\n when \"bottom\", \"right\"\n if hasBody then \"after\" else \"append\"\n\n (targetEl || @$bodyEl() )[action]( container )\n\n# A Panel is a basic Luca.View but with Toolbar extensions\n#\n# In general other components should inherit from the panel class.\n\n_.def(\"Luca.components.Panel\").extends(\"Luca.View\").with\n\n topToolbar: undefined\n\n bottomToolbar: undefined\n\n # Load Mask will apply a transparent overlay over the form\n # upon submission, with a moving progress bar which will be\n # hidden upon successful response\n loadMask: false\n loadMaskTemplate: [\"components/load_mask\"]\n loadMaskTimeout: 3000\n\n initialize: (@options={})->\n Luca.View::initialize.apply(@, arguments)\n\n _.bindAll @, \"applyLoadMask\", \"disableLoadMask\"\n\n if @loadMask is true\n @defer ()=>\n @$el.addClass('with-mask')\n\n if @$('.load-mask').length is 0\n @loadMaskTarget().prepend Luca.template(@loadMaskTemplate, @)\n @$('.load-mask').hide()\n .until(\"after:render\")\n\n @on \"enable:loadmask\", @applyLoadMask\n @on \"disable:loadmask\", @applyLoadMask\n\n loadMaskTarget: ()->\n if @loadMaskEl? then @$(@loadMaskEl) else @$bodyEl()\n\n disableLoadMask: ()->\n @$('.load-mask .bar').css(\"width\",\"100%\")\n @$('.load-mask').hide()\n clearInterval(@loadMaskInterval)\n\n enableLoadMask: ()->\n @$('.load-mask').show().find('.bar').css(\"width\",\"0%\")\n maxWidth = @$('.load-mask .progress').width()\n if maxWidth < 20 and (maxWidth = @$el.width()) < 20\n maxWidth = @$el.parent().width()\n\n @loadMaskInterval = setInterval ()=>\n currentWidth = @$('.load-mask .bar').width()\n newWidth = currentWidth + 12\n @$('.load-mask .bar').css('width', newWidth)\n , 200\n\n return unless @loadMaskTimeout?\n\n _.delay ()=>\n @disableLoadMask()\n , @loadMaskTimeout\n\n applyLoadMask: ()->\n if @$('.load-mask').is(\":visible\")\n @disableLoadMask()\n else\n @enableLoadMask()\n\n applyStyles: (styles={},body=false)->\n\n target = if body then @$bodyEl() else @$el\n\n for setting, value of styles\n target.css(setting,value)\n\n @\n\n beforeRender: ()->\n Luca.View::beforeRender?.apply(@, arguments)\n @applyStyles( @styles ) if @styles?\n @applyStyles( @bodyStyles, true ) if @bodyStyles?\n @renderToolbars?()\n\n $bodyEl: ()->\n element = @bodyTagName || \"div\"\n className = @bodyClassName || \"view-body\"\n\n @bodyEl ||= \"#{ element }.#{ className }\"\n\n bodyEl = @$(@bodyEl)\n\n return bodyEl if bodyEl.length > 0\n\n # if we've been configured to have one, and it doesn't exist\n # then we should append it to ourselves\n if bodyEl.length is 0 and (@bodyClassName? || @bodyTagName?)\n newElement = @make(element,class:className,\"data-auto-appended\":true)\n $(@el).append( newElement )\n return @$(@bodyEl)\n\n\n $(@el)\n\n $wrap: (wrapper)->\n if _.isString(wrapper) and not wrapper.match(/[<>]/)\n wrapper = @make(\"div\",class:wrapper)\n\n @$el.wrap( wrapper )\n\n $template: (template, variables={})->\n @$html( Luca.template(template,variables) )\n\n $html: (content)->\n @$bodyEl().html( content )\n\n $append: (content)->\n @$bodyEl().append(content)\n\n # Luca containers can have toolbars,\n # these will get injected before or after the bodyEl, or at the top\n # or bottom of the $el\n renderToolbars: ()->\n _( [\"top\",\"left\",\"right\",\"bottom\"] ).each (orientation)=>\n if config = @[\"#{ orientation }Toolbar\"]\n @renderToolbar( orientation, config)\n\n renderToolbar: (orientation=\"top\", config={})->\n config.parent = @\n config.orientation = orientation\n\n attachToolbar.call(@, config, config.targetEl )"},{"className":"App.collections.MyCollection","file":"src/samples/definition.coffee","source":"# Component Definition\n\n# In Luca, we define components like such:\n\n_.def(\"App.collections.MyCollection\").extends(\"Luca.Collection\").with\n cache_key: \"my_collection\"\n storageEngine: \"localStorage\"\n\n_.def(\"App.views.MyView\").extends(\"Luca.core.Container\").with\n name: \"default_name_of_the_view\"\n components:[\n ctype: \"form_view\"\n ,\n ctype: \"grid_view\"\n collection: \"my_collection\"\n ]\n initialize: (@options)->\n @_super(\"initialize\", @, arguments)\n @customMethod()\n\n# This achieves a few things:\n#\n# 0. More pleasant to read\n#\n# 1. All instances of App.views.MyView have a displayName property set\n# so we know upon inspection which class they inherit from\n#\n# 2. All instances of App.views.MyView know that they extend Luca.components.FormView,\n# which allows us to use @_super() when overriding important framework methods, and\n# saves us from having to type Luca.core.Container.prototype.initialize.apply(@, arguments)\n# every time, on every method that it is needed\n#\n# 3. App.views.MyView gets assigned a ctype: \"my_view\" so that we can use a declarative\n# JSON syntax for building complex components made up of smaller views, models, collections\n# simply by referencing their 'ctype'. This allows Luca.Containers to create the nested components\n# for you\n#\n# 4. Luca.registry knows about all of the components defined against it, as well as all instances of\n# the components, so with our in browser development tool we can modify the prototype of a view and\n# automatically refresh all running instances of the comoponent with updated code\n#\n# 5. We don't actually have to create App.views.MyView right away, we could develop an intermediate layer\n# which stores the name of the defined view, who it extends from, and what customizations are being made to it\n# in some temporary buffer, and build our own dependency management layer which handles loading dependencies on demand\n\n# Problem\n#\n# What is the best way to integrate a solution like requirejs, airdrop, stitch, or similar\n# with the above style of component definition?"},{"className":"App.views.MyView","file":"src/samples/definition.coffee","source":"# Component Definition\n\n# In Luca, we define components like such:\n\n_.def(\"App.collections.MyCollection\").extends(\"Luca.Collection\").with\n cache_key: \"my_collection\"\n storageEngine: \"localStorage\"\n\n_.def(\"App.views.MyView\").extends(\"Luca.core.Container\").with\n name: \"default_name_of_the_view\"\n components:[\n ctype: \"form_view\"\n ,\n ctype: \"grid_view\"\n collection: \"my_collection\"\n ]\n initialize: (@options)->\n @_super(\"initialize\", @, arguments)\n @customMethod()\n\n# This achieves a few things:\n#\n# 0. More pleasant to read\n#\n# 1. All instances of App.views.MyView have a displayName property set\n# so we know upon inspection which class they inherit from\n#\n# 2. All instances of App.views.MyView know that they extend Luca.components.FormView,\n# which allows us to use @_super() when overriding important framework methods, and\n# saves us from having to type Luca.core.Container.prototype.initialize.apply(@, arguments)\n# every time, on every method that it is needed\n#\n# 3. App.views.MyView gets assigned a ctype: \"my_view\" so that we can use a declarative\n# JSON syntax for building complex components made up of smaller views, models, collections\n# simply by referencing their 'ctype'. This allows Luca.Containers to create the nested components\n# for you\n#\n# 4. Luca.registry knows about all of the components defined against it, as well as all instances of\n# the components, so with our in browser development tool we can modify the prototype of a view and\n# automatically refresh all running instances of the comoponent with updated code\n#\n# 5. We don't actually have to create App.views.MyView right away, we could develop an intermediate layer\n# which stores the name of the defined view, who it extends from, and what customizations are being made to it\n# in some temporary buffer, and build our own dependency management layer which handles loading dependencies on demand\n\n# Problem\n#\n# What is the best way to integrate a solution like requirejs, airdrop, stitch, or similar\n# with the above style of component definition?"},{"className":"Luca.tools.CodeEditor","file":"src/tools/code_editor.coffee","source":"BuffersModel = Luca.Model.extend\n defaults:\n _current: \"default\"\n _namespace: \"default\"\n _compiled: []\n\n initialize: (@attributes={})->\n Luca.Model::initialize.apply(@, arguments)\n @fetch(silent:true)\n\n requireCompilation: ()->\n @get(\"_compiled\")\n\n bufferKeys: ()->\n return @bufferNames if @bufferNames?\n\n for key, value of @attributes when !key.match(/_/)\n key\n\n namespacedBuffer: (key)->\n \"#{ @get('_namespace') }:#{ key }\"\n\n bufferValues: ()->\n _( @attributes ).pick( @bufferKeys() )\n\n fetch: (options={})->\n options.silent ||= true\n\n _( @bufferKeys() ).each (key)=>\n value = localStorage?.getItem( @namespacedBuffer(key) )\n @set(key, value, silent: options.silent is true) if value?\n\n @\n\n persist: ()->\n _( @bufferKeys() ).each (key)=>\n value = @get(key)\n localStorage?.setItem( @namespacedBuffer(key), value)\n\n @\n\n currentContent: ()->\n current = @get(\"_current\")\n @get(current)\n\ncompilers =\n coffeescript: (code)->\n CoffeeScript.compile code, bare: true\n default: (code)->\n code\n\n_.def(\"Luca.tools.CodeEditor\").extends(\"Luca.components.Panel\").with\n name: \"code_editor\"\n\n id: \"editor_container\"\n\n autoBindEventHandlers: true\n\n bodyClassName: \"codemirror-wrapper\"\n\n defaultValue: ''\n\n compilationEnabled: false\n\n bufferNamespace: \"luca:code\"\n\n namespace: (set, options={})->\n if set?\n @bufferNamespace = set\n @buffers?.set(\"_namespace\", set, silent: (options.silent is true) )\n\n @bufferNamespace\n\n initialize: (@options)->\n @_super(\"initialize\", @, arguments)\n\n _.bindAll @, \"onCompiledCodeChange\", \"onBufferChange\", \"onEditorChange\", \"stripTabs\"\n\n @mode ||= \"coffeescript\"\n @theme ||= \"monokai\"\n @keyMap ||= \"vim\"\n @lineWrapping ||= true\n\n @compiler = compilers[@mode] || compilers.default\n\n @setupBuffers()\n\n setWrap: (@lineWrapping)->\n @editor.setOption(\"lineWrapping\", @lineWrapping)\n\n setMode: (@mode)->\n @editor.setOption(\"mode\", @mode)\n @\n\n setKeyMap: (@keyMap)->\n @editor.setOption(\"keyMap\", @keyMap)\n @\n\n setTheme: (@theme)->\n @editor.setOption(\"theme\",@theme)\n @\n\n setupBuffers: ()->\n attributes = _.extend(@currentBuffers || {},_compiled:@compiledBuffers,_namespace:@namespace())\n @buffers = new BuffersModel(attributes)\n\n editor = @\n\n _( @buffers.bufferKeys() ).each (key)=>\n @buffers.bind \"change:#{ key }\", ()=>\n @onBufferChange.apply(@, arguments)\n\n _( @buffers.requireCompilation() ).each (key)=>\n @buffers.bind \"change:compiled_#{ key }\", @onCompiledCodeChange\n\n # handle switching of the buffers. when the editor\n # is told to switch buffers, we will get the current content\n # in that buffer, and update the code mirror instance\n @buffers.bind \"change:_current\", (model,value)=>\n editor.trigger \"buffer:change\"\n editor.editor.setValue( @buffers.currentContent() || \"\" )\n\n @monitorChanges = true\n\n currentBuffer: ()->\n @buffers.get(\"_current\")\n\n loadBuffer: (bufferName, autoSave=true)->\n @saveBuffer() if autoSave\n @buffers.set(\"_current\", bufferName)\n\n saveBuffer: ()->\n localStorage.setItem( @buffers.namespacedBuffer( @currentBuffer() ), @editor.getValue())\n @buffers.set( @currentBuffer(), @editor.getValue() )\n\n getBuffer: (buffer, compiled=false)->\n buffer ||= @currentBuffer()\n code = @buffers.get( buffer )\n\n return code unless compiled is true\n\n compiledCode = @buffers.get(\"compiled_#{ buffer }\")\n\n if _.string.isBlank(compiledCode)\n compiledCode = @compileCode(code, buffer)\n\n return compiledCode\n\n editorOptions: ()->\n mode: @mode\n theme: @theme\n keyMap: @keyMap\n lineNumbers: true\n gutter: true\n autofocus: true\n onChange: @onEditorChange\n onKeyEvent: @stripTabs\n passDelay: 50\n autoClearEmptyLines: true\n smartIndent: false\n tabSize: 2\n electricChars: false\n\n\n beforeRender: ()->\n Luca.components.Panel::beforeRender?.apply(@, arguments)\n\n styles =\n \"min-height\": @minHeight\n background:'#272822'\n color:'#f8f8f2'\n\n @$bodyEl().css(styles)\n\n @$html \"<textarea></textarea>\"\n\n afterRender: ()->\n _.defer ()=>\n @editor = window.CodeMirror.fromTextArea( @$('textarea')[0], @editorOptions())\n @restore()\n @enableTabStripping = true\n\n save: ()->\n @saveBuffer()\n\n restore: ()->\n @editor.setValue(\"\")\n @editor.refresh()\n\n replaceTabWithSpace: ()->\n\n stripTabs: (editor, keyEvent)->\n if keyEvent?.keyCode is 9\n coords = @editor.cursorCoords()\n cleansed = @getValue().replace(/\\t/g,' ')\n @setValue(cleansed)\n @editor.setCursor( coords )\n\n false\n\n onEditorChange: ()->\n if @monitorChanges\n @save()\n\n onBufferChange: (model, newValue, changes)->\n previous = model.previousAttributes()\n\n _( @buffers.bufferKeys() ).each (key)=>\n if previous[key] isnt @buffers.get(key)\n\n if _( @buffers.requireCompilation() ).include(key)\n result = @compileCode( @buffers.get(key), key )\n if result.success is true\n @buffers.persist(key)\n @buffers.set(\"compiled_#{ key }\", result.compiled, silent: true)\n else\n @trigger \"code:change:#{ key }\", @buffers.get(key)\n @buffers.persist(key)\n\n @buffers.change()\n\n onCompiledCodeChange: (model, newValue, changes)->\n changedBuffers = _( model.changedAttributes() ).keys()\n @trigger \"code:change\", changedBuffers\n for changed in changedBuffers\n @trigger \"code:change:#{ changed }\", changed\n\n compileCode: (code, buffer)->\n buffer ||= @currentBuffer()\n code ||= @getBuffer(buffer, false)\n\n compiled = \"\"\n\n result =\n success: true\n compiled: \"\"\n\n try\n compiled = @compiler.call(@, code)\n @trigger \"compile:success\", code, compiled\n result.compiled = compiled\n catch error\n @trigger \"compile:error\", error, code\n result.success = false\n result.compiled = @buffers.get(\"compiled_#{ buffer }\")\n\n result\n\n getCompiledCode: (buffer)->\n buffer = @getBuffer(buffer)\n _.string.strip( @compileCode(buffer) )\n\n getValue: ()->\n @editor.getValue()\n\n setValue: (value)->\n value = value.replace(/\\t/g, ' ')\n @editor.setValue( value )"},{"className":"Luca.tools.CoffeeEditor","file":"src/tools/coffee_script_editor.coffee","source":"_.def(\"Luca.tools.CoffeeEditor\").extends(\"Luca.tools.CodeMirrorField\").with\n name : \"coffeescript_editor\"\n\n autoCompile: true\n\n compileOptions:\n bare: true\n\n hooks:[\n \"editor:change\"\n ]\n\n initialize: (@options)->\n Luca.tools.CodeMirrorField::initialize.apply(@, arguments)\n\n _.bindAll(@, \"editorChange\", \"toggleSource\")\n\n editor = @\n\n @state = new Luca.Model\n currentMode: \"coffeescript\"\n coffeescript:\"\"\n javascript:\"\"\n\n @state.bind \"change:coffeescript\", (model)->\n editor.trigger(\"change:coffeescript\")\n code = model.get(\"coffeescript\")\n\n editor.compile code, (compiled)->\n model.set('javascript',compiled)\n\n @state.bind \"change:javascript\", (model)->\n editor.onJavascriptChange?.call(editor, model.get('javascript') )\n\n @state.bind \"change:currentMode\", (model)->\n if model.get('currentMode') is \"javascript\"\n editor.setValue model.get('javascript')\n else \n editor.setValue model.get('coffeescript')\n\n compile: (code, callback)->\n response = {}\n code ||= @getValue()\n\n try\n compiled = CoffeeScript.compile(code, @compileOptions)\n callback?.call(@, compiled)\n response =\n success: true\n compiled: compiled\n catch error\n @trigger(\"compile:error\", error, code)\n\n response =\n success: false\n compiled: ''\n message: error.message\n\n toggleMode: ()->\n if @currentMode() is \"coffeescript\"\n @state.set('currentMode', 'javascript')\n else if @currentMode() is \"javascript\"\n @state.set('currentMode', 'coffeescript')\n\n currentMode: ()->\n @state.get(\"currentMode\")\n\n getCoffeescript: ()->\n @state.get(\"coffeescript\")\n \n getJavascript: (recompile=false)->\n js = @state.get(\"javascript\")\n\n if recompile is true or js?.length is 0\n results = @compile( @getCoffeescript() ) \n js = results?.compiled\n\n js\n\n editorChange: ()->\n if @autoCompile is true\n @state.set( @currentMode(), @getValue() )\n"},{"className":"Luca.tools.CollectionInspector","file":"src/tools/collection_inspector.coffee","source":"_.def(\"Luca.tools.CollectionInspector\").extends(\"Luca.View\").with\n name: \"collection_inspector\"\n\n className: \"collection-inspector\"\n"},{"className":"Luca.collections.Components","file":"src/tools/collections/components.coffee","source":"_.def('Luca.collections.Components').extends('Luca.Collection').with\n\n cachedMethods: [\n \"namespaces\"\n \"classes\"\n \"roots\"\n \"views\"\n \"collections\"\n \"models\"\n ]\n\n cache_key: \"luca_components\"\n\n name: \"components\"\n\n initialize: ()->\n @model = Luca.models.Component\n Luca.Collection::initialize.apply(@, arguments)\n \n url: ()->\n \"/source-map.js\"\n\n collections: ()->\n @select (component)-> Luca.isCollectionPrototype( component.definition() )\n\n modelClasses: ()->\n @select (component)-> Luca.isModelPrototype( component.definition() )\n\n views: ()->\n @select (component)-> Luca.isViewPrototype( component.definition() )\n\n classes: ()->\n _.uniq( @pluck \"className\" )\n\n roots: ()->\n _.uniq( @invoke(\"root\") )\n\n namespaces: ()->\n _.uniq( @invoke(\"namespace\") )\n\n asTree: ()->\n classes = @classes()\n namespaces = @namespaces()\n roots = @roots()\n\n tree = _( roots ).inject (memo,root)->\n memo[ root ] ||= {}\n regexp = new RegExp(\"^#{ root }\")\n memo[root] = _( namespaces ).select (namespace)->\n regexp.exec(namespace) and _( namespaces ).include(namespace) and namespace.split('.').length is 2\n memo\n , {}\n\n _( tree ).inject (memo, namespaces, root)->\n memo[root] = {}\n _( namespaces ).each (namespace)->\n memo[root][namespace] = {}\n memo\n , {}"},{"className":"MyComponent","file":"src/tools/component_tester.coffee","source":"# TODO\n#\n# Developed this component for use with the component tester.\n#\n# The editor which compiles coffeescript code should be extracted into a separate component\n# and all of the buffers / specifics etc should be moved into a more specific component for\n# this purpose\n\ndefaults = {}\n\ndefaults.setup = \"\"\"\n# the setup tab contains code which is run every time\n# prior to the 'implementation' run\n\"\"\"\n\ndefaults.component = \"\"\"\n# the component tab is where you handle the definition of the component\n# that you are trying to test. it will render its output into the\n# output panel of the code tester\n#\n# example definition:\n#\n# _.def('MyComponent').extends('Luca.View').with\n# bodyTemplate: 'sample/welcome'\n\"\"\"\n\ndefaults.teardown = \"\"\"\n# the teardown tab is where you undo / cleanup any of the operations\n# from setup / implementation\n\"\"\"\n\ndefaults.implementation = \"\"\"\n# the implementation tab is where you specify options for your component.\n#\n# NOTE: the component tester uses whatever is returned from evalulating\n# the code in this tab. if it responds to render(), it will append\n# render().el to the output panel. if it is an object, then we will attempt\n# to create an instance of the component you defined with the object as\n\"\"\"\n\ndefaults.style = \"\"\"\n/*\n * customize the styles that effect this component\n * note, all styles here will be scoped to only effect\n * the output panel :)\n*/\n\"\"\"\n\ndefaults.html = \"\"\n\nbufferNames = [\"setup\",\"implementation\",\"component\",\"style\",\"html\"]\ncompiledBuffers = [\"setup\",\"implementation\",\"component\"]\n\nComponentPicker = Luca.fields.TypeAheadField.extend\n name: \"component_picker\"\n\n label: \"Choose a component to edit\"\n\n initialize: ()->\n @collection = new Luca.collections.Components()\n @collection.fetch()\n\n @_super(\"initialize\", @, arguments)\n\n getSource: ()->\n @collection.classes()\n\n change_handler: ()->\n componentDefinition = @getValue()\n\n component = @collection.find (model)->\n model.get(\"className\") is componentDefinition\n\n component.fetch success: (model, response)=>\n if response?.source.length > 0\n @trigger \"component:fetched\", response.source, response.className\n\n @hide()\n\n createWrapper: ()->\n @make \"div\",\n class: \"component-picker span4 well\"\n style:\n \"position: absolute; z-index:12000\"\n\n show: ()->\n @$el.parent().show()\n\n hide: ()->\n @$el.parent().hide()\n\n toggle: ()->\n @$el.parent().toggle()\n\n\n\n_.def(\"Luca.tools.ComponentTester\").extends(\"Luca.core.Container\").with\n id: \"component_tester\"\n name: \"component_tester\"\n\n autoEvaluateCode: true\n\n currentSize: 1\n\n sizes:[\n icon: \"resize-full\"\n value: ()-> $(window).height() * 0.3\n ,\n icon: \"resize-small\"\n value: ()-> $(window).height() * 0.6\n ]\n \n components:[\n ctype: 'card_view'\n name: \"component_detail\"\n activeCard: 0\n components:[\n ctype: 'panel'\n name: \"component_tester_output\"\n bodyTemplate: \"component_tester/help\"\n ]\n ,\n ctype: \"code_editor\"\n name: \"ctester_edit\"\n className: 'font-large fixed-height'\n minHeight:'350px'\n\n currentBuffers: defaults\n\n compiledBuffers:[\"component\",\"setup\",\"implementation\"]\n\n topToolbar:\n buttons:[\n icon: \"resize-full\"\n align: \"right\"\n description: \"change the size of the component tester editor\"\n eventId: \"toggle:size\"\n ,\n icon: \"pause\"\n align: \"right\"\n description: \"Toggle auto-evaluation of test script on code change\"\n eventId: \"click:autoeval\"\n ,\n icon: \"plus\"\n description: \"add a new component to test\"\n eventId: \"click:add\"\n ,\n icon: \"folder-open\"\n description: \"open an existing component's definition\"\n eventId: \"click:open\"\n ]\n\n bottomToolbar:\n buttons:[\n group: true\n wrapper: \"span4\"\n buttons:[\n label: \"View Javascript\"\n description: \"Switch between compiled JS and Coffeescript\"\n eventId: \"toggle:mode\"\n ]\n ,\n group: true\n wrapper: \"span6 offset4\"\n buttons:[\n label: \"Component\"\n eventId: \"edit:component\"\n description: \"Edit the component itself\"\n ,\n label: \"Setup\"\n eventId: \"edit:setup\"\n description: \"Edit the setup for your component test\"\n ,\n label: \"Implementation\"\n eventId: \"edit:implementation\"\n description: \"Implement your component\"\n ,\n label: \"Markup\",\n eventId: \"edit:markup\"\n description: \"Edit the HTML produced by the component\"\n ,\n label: \"CSS\"\n eventId: \"edit:style\"\n description: \"Edit CSS\"\n ]\n ,\n group: true\n align: \"right\"\n buttons:[\n icon:\"question-sign\"\n align: \"right\"\n eventId: \"click:help\"\n description: \"Help\"\n ,\n icon: \"cog\"\n align: 'right'\n eventId: \"click:settings\"\n description : \"component tester settings\"\n ,\n icon: \"eye-close\"\n align: \"right\"\n eventId: \"click:hide\"\n description: \"hide the tester controls\"\n ,\n icon: \"heart\"\n eventId: \"click:console\"\n description: \"Coffeescript Console\"\n align: \"right\"\n ]\n ]\n ]\n\n debugMode: true\n\n componentEvents:\n \"ctester_edit click:autoeval\" : \"toggleAutoeval\"\n \"ctester_edit click:refresh\" : \"refreshCode\"\n \"ctester_edit click:hide\" : \"toggleControls\"\n \"ctester_edit click:settings\" : \"toggleSettings\"\n \"ctester_edit click:add\" : \"addComponent\"\n \"ctester_edit click:open\" : \"openComponent\"\n \"ctester_edit click:help\" : \"showHelp\"\n \"ctester_edit click:console\" : \"toggleConsole\"\n \"ctester_edit eval:error\" : \"onError\"\n \"ctester_edit eval:success\" : \"onSuccess\"\n \"ctester_edit edit:setup\" : \"editSetup\"\n \"ctester_edit edit:teardown\" : \"editTeardown\"\n \"ctester_edit edit:component\" : \"editComponent\"\n \"ctester_edit edit:style\" : \"editStyle\"\n \"ctester_edit edit:markup\" : \"editMarkup\"\n \"ctester_edit edit:implementation\" : \"editImplementation\"\n \"ctester_edit toggle:keymap\" : \"toggleKeymap\"\n \"ctester_edit toggle:mode\" : \"toggleMode\"\n \"ctester_edit code:change:html\" : \"onMarkupChange\"\n \"ctester_edit code:change:style\" : \"onStyleChange\"\n \"ctester_edit toggle:size\" : \"toggleSize\"\n\n\n initialize: ()->\n Luca.core.Container::initialize.apply(@, arguments)\n\n for key, value of @componentEvents\n @[ value ] = _.bind(@[value], @)\n\n @defer(\"editComponent\").until(\"after:render\")\n\n afterRender: ()->\n changeHandler = _.idleMedium ()=>\n if @autoEvaluateCode is true\n @applyTestRun()\n , 500\n\n @getEditor().bind \"code:change\", changeHandler\n\n getEditor: ()->\n Luca(\"ctester_edit\")\n\n getDetail: ()->\n Luca(\"component_detail\")\n\n getOutput: ()->\n @getDetail().findComponentByName(\"component_tester_output\")\n\n onError: (error, bufferId)->\n console.log \"Error in #{ bufferId }\", error, error.message, error.stack\n\n onSuccess: (result, bufferId)->\n if bufferId is \"component\"\n @componentDefinition = result\n\n if bufferId is \"implementation\"\n if Luca.isBackboneView(result)\n object = result\n else if _.isObject(result) and result.ctype?\n object = Luca(result)\n else if _.isObject(result) and _.isFunction(@componentDefinition)\n object = ( new @componentDefinition(result) )\n\n if Luca.isBackboneView(object)\n @getOutput().$html( object.render().el )\n\n applyTestRun: ()->\n @getOutput().$html('')\n\n for bufferId, code of @getTestRun()\n @evaluateCode(code, bufferId)\n\n toggleConsole: (button)->\n @developmentConsole = Luca \"coffeescript-console\", ()-> new Luca.tools.DevelopmentConsole(name:\"coffeescript-console\")\n\n unless @consoleContainerAppended\n container = @make(\"div\",{id:\"devtools-console-wrapper\",class:\"devtools-console-container modal\",style:\"width:900px;height:650px;\"}, @developmentConsole.el)\n $('body').append( container )\n @consoleContainerAppended = true\n @developmentConsole.render()\n\n $('#devtools-console-wrapper').modal(backdrop:false,show:true)\n\n toggleAutoeval: (button)->\n @autoEvaluateCode = !(@autoEvaluateCode is true)\n\n if not @started and @autoEvaluateCode is true\n @started = true\n @applyTestRun()\n\n iconHolder = button.children('i').eq(0)\n buttonClass = if @autoEvaluateCode then \"icon-pause\" else \"icon-play\"\n iconHolder.removeClass()\n iconHolder.addClass(buttonClass)\n\n @\n\n showEditor: (options)->\n @getEditor().$('.toolbar-container.top').toggle(options)\n @getEditor().$('.codemirror-wrapper').toggle(options)\n @trigger \"controls:toggled\"\n\n toggleKeymap: (button)->\n newMode = if @getEditor().keyMap is \"vim\" then \"basic\" else \"vim\"\n @getEditor().setKeyMap(newMode)\n button.html( _.string.capitalize(newMode) )\n\n toggleMode: (button)->\n newMode = if @getEditor().mode is \"coffeescript\" then \"javascript\" else \"coffeescript\"\n @getEditor().setMode(newMode)\n button.html _.string.capitalize((if newMode is \"coffeescript\" then \"View Javascript\" else \"View Coffeescript\"))\n @editBuffer @currentBufferName, (newMode is \"javascript\")\n\n\n\n\n toggleSize: (button)->\n index = @currentSize++ % @sizes.length\n newSize = @sizes[ index ].value()\n newIcon = @sizes[ index ].icon\n\n if button?\n iconHolder = button.children('i').eq(0)\n iconHolder.removeClass().addClass(\"icon-#{ newIcon }\")\n\n @$('.codemirror-wrapper').css('height', \"#{ parseInt(newSize) }px\")\n @getEditor().refresh()\n\n toggleControls: (button)->\n @bind \"controls:toggled\", ()=>\n iconHolder = button.children('i').eq(0)\n iconHolder.removeClass()\n\n buttonClass = if @getEditor().$('.toolbar-container.top').is(\":visible\") then \"icon-eye-close\" else \"icon-eye-open\"\n iconHolder.addClass(buttonClass)\n\n @showEditor()\n\n @\n\n toggleSettings: ()->\n @\n\n setValue: (value, buffer=\"component\")->\n compiled = @getEditor().editor.getOption('mode') is \"javascript\"\n @editBuffer(buffer, compiled, false).getEditor().setValue( value )\n\n editBuffer: (@currentBufferName, compiled=false, autoSave=true)->\n @showEditor(true)\n @highlight(@currentBufferName)\n\n buffer = if compiled then \"compiled_#{ @currentBufferName }\" else @currentBufferName\n @getEditor().loadBuffer(buffer,autoSave)\n @\n\n editMarkup: ()->\n @getEditor().setMode('htmlmixed')\n @getEditor().setWrap(true)\n @editBuffer(\"html\").setValue(@getOutput().$html(), 'html')\n\n editStyle: ()->\n @getEditor().setMode('css')\n @editBuffer(\"style\")\n\n editComponent: ()->\n @getEditor().setMode('coffeescript')\n @editBuffer(\"component\")\n\n editTeardown: ()->\n @getEditor().setMode('coffeescript')\n @editBuffer(\"teardown\")\n\n editSetup: ()->\n @getEditor().setMode('coffeescript')\n @editBuffer(\"setup\")\n\n editImplementation: ()->\n @getEditor().setMode('coffeescript')\n @editBuffer(\"implementation\")\n\n getTestRun: ()->\n editor = @getEditor()\n\n testRun = {}\n\n for buffer in [\"component\",\"setup\",\"implementation\"]\n testRun[buffer] = editor.getBuffer(buffer, true)\n\n testRun\n\n getContext: ()->\n Luca.util.resolve(@context||=\"window\")\n\n evaluateCode: (code, bufferId, compile=false)->\n code ||= @getEditor().getValue()\n compiled = if compile is true then @getEditor().compileCode(code) else code\n\n evaluator = ()-> eval( compiled )\n\n try\n result = evaluator.call( @getContext() )\n @onSuccess(result, bufferId, code)\n catch error\n @onError( error, bufferId, code)\n\n onMarkupChange: ()->\n if @autoEvaluateCode is true\n @getOutput().$html @getEditor().getValue()\n\n onStyleChange: ()->\n if @autoEvaluateCode is true\n $('#component-tester-stylesheet').remove()\n\n style = @getEditor()?.getValue()\n\n if style\n styleTag = @make \"style\", type:\"text/css\", id: \"component-tester-stylesheet\"\n $('head').append( styleTag )\n $(styleTag).append(style)\n\n showHelp: ()->\n @getOutput().$html( Luca.template(\"component_tester/help\",@) )\n\n addComponent: (button)->\n\n openComponent: (button)->\n @componentPicker ||= new ComponentPicker()\n\n @componentPicker.bind \"component:fetched\", (source, component)=>\n @setEditorNamespace(component).setValue( source, \"component\")\n\n if !@getEditor().$('.component-picker').length > 0\n @getEditor().$('.codemirror-wrapper').before(@componentPicker.createWrapper())\n @getEditor().$('.component-picker').html( @componentPicker.render().el )\n @componentPicker.show()\n return\n\n @componentPicker.toggle()\n\n highlight: (section)->\n @$(\"a.btn[data-eventid='edit:#{ section }']\").siblings().css('font-weight','normal')\n @$(\"a.btn[data-eventid='edit:#{ section }']\").css('font-weight','bold')\n\n setEditorNamespace: (namespace)->\n @getEditor().namespace( namespace )\n @getEditor().buffers.fetch()\n @"},{"className":"Luca.tools.ComponentTester","file":"src/tools/component_tester.coffee","source":"# TODO\n#\n# Developed this component for use with the component tester.\n#\n# The editor which compiles coffeescript code should be extracted into a separate component\n# and all of the buffers / specifics etc should be moved into a more specific component for\n# this purpose\n\ndefaults = {}\n\ndefaults.setup = \"\"\"\n# the setup tab contains code which is run every time\n# prior to the 'implementation' run\n\"\"\"\n\ndefaults.component = \"\"\"\n# the component tab is where you handle the definition of the component\n# that you are trying to test. it will render its output into the\n# output panel of the code tester\n#\n# example definition:\n#\n# _.def('MyComponent').extends('Luca.View').with\n# bodyTemplate: 'sample/welcome'\n\"\"\"\n\ndefaults.teardown = \"\"\"\n# the teardown tab is where you undo / cleanup any of the operations\n# from setup / implementation\n\"\"\"\n\ndefaults.implementation = \"\"\"\n# the implementation tab is where you specify options for your component.\n#\n# NOTE: the component tester uses whatever is returned from evalulating\n# the code in this tab. if it responds to render(), it will append\n# render().el to the output panel. if it is an object, then we will attempt\n# to create an instance of the component you defined with the object as\n\"\"\"\n\ndefaults.style = \"\"\"\n/*\n * customize the styles that effect this component\n * note, all styles here will be scoped to only effect\n * the output panel :)\n*/\n\"\"\"\n\ndefaults.html = \"\"\n\nbufferNames = [\"setup\",\"implementation\",\"component\",\"style\",\"html\"]\ncompiledBuffers = [\"setup\",\"implementation\",\"component\"]\n\nComponentPicker = Luca.fields.TypeAheadField.extend\n name: \"component_picker\"\n\n label: \"Choose a component to edit\"\n\n initialize: ()->\n @collection = new Luca.collections.Components()\n @collection.fetch()\n\n @_super(\"initialize\", @, arguments)\n\n getSource: ()->\n @collection.classes()\n\n change_handler: ()->\n componentDefinition = @getValue()\n\n component = @collection.find (model)->\n model.get(\"className\") is componentDefinition\n\n component.fetch success: (model, response)=>\n if response?.source.length > 0\n @trigger \"component:fetched\", response.source, response.className\n\n @hide()\n\n createWrapper: ()->\n @make \"div\",\n class: \"component-picker span4 well\"\n style:\n \"position: absolute; z-index:12000\"\n\n show: ()->\n @$el.parent().show()\n\n hide: ()->\n @$el.parent().hide()\n\n toggle: ()->\n @$el.parent().toggle()\n\n\n\n_.def(\"Luca.tools.ComponentTester\").extends(\"Luca.core.Container\").with\n id: \"component_tester\"\n name: \"component_tester\"\n\n autoEvaluateCode: true\n\n currentSize: 1\n\n sizes:[\n icon: \"resize-full\"\n value: ()-> $(window).height() * 0.3\n ,\n icon: \"resize-small\"\n value: ()-> $(window).height() * 0.6\n ]\n \n components:[\n ctype: 'card_view'\n name: \"component_detail\"\n activeCard: 0\n components:[\n ctype: 'panel'\n name: \"component_tester_output\"\n bodyTemplate: \"component_tester/help\"\n ]\n ,\n ctype: \"code_editor\"\n name: \"ctester_edit\"\n className: 'font-large fixed-height'\n minHeight:'350px'\n\n currentBuffers: defaults\n\n compiledBuffers:[\"component\",\"setup\",\"implementation\"]\n\n topToolbar:\n buttons:[\n icon: \"resize-full\"\n align: \"right\"\n description: \"change the size of the component tester editor\"\n eventId: \"toggle:size\"\n ,\n icon: \"pause\"\n align: \"right\"\n description: \"Toggle auto-evaluation of test script on code change\"\n eventId: \"click:autoeval\"\n ,\n icon: \"plus\"\n description: \"add a new component to test\"\n eventId: \"click:add\"\n ,\n icon: \"folder-open\"\n description: \"open an existing component's definition\"\n eventId: \"click:open\"\n ]\n\n bottomToolbar:\n buttons:[\n group: true\n wrapper: \"span4\"\n buttons:[\n label: \"View Javascript\"\n description: \"Switch between compiled JS and Coffeescript\"\n eventId: \"toggle:mode\"\n ]\n ,\n group: true\n wrapper: \"span6 offset4\"\n buttons:[\n label: \"Component\"\n eventId: \"edit:component\"\n description: \"Edit the component itself\"\n ,\n label: \"Setup\"\n eventId: \"edit:setup\"\n description: \"Edit the setup for your component test\"\n ,\n label: \"Implementation\"\n eventId: \"edit:implementation\"\n description: \"Implement your component\"\n ,\n label: \"Markup\",\n eventId: \"edit:markup\"\n description: \"Edit the HTML produced by the component\"\n ,\n label: \"CSS\"\n eventId: \"edit:style\"\n description: \"Edit CSS\"\n ]\n ,\n group: true\n align: \"right\"\n buttons:[\n icon:\"question-sign\"\n align: \"right\"\n eventId: \"click:help\"\n description: \"Help\"\n ,\n icon: \"cog\"\n align: 'right'\n eventId: \"click:settings\"\n description : \"component tester settings\"\n ,\n icon: \"eye-close\"\n align: \"right\"\n eventId: \"click:hide\"\n description: \"hide the tester controls\"\n ,\n icon: \"heart\"\n eventId: \"click:console\"\n description: \"Coffeescript Console\"\n align: \"right\"\n ]\n ]\n ]\n\n debugMode: true\n\n componentEvents:\n \"ctester_edit click:autoeval\" : \"toggleAutoeval\"\n \"ctester_edit click:refresh\" : \"refreshCode\"\n \"ctester_edit click:hide\" : \"toggleControls\"\n \"ctester_edit click:settings\" : \"toggleSettings\"\n \"ctester_edit click:add\" : \"addComponent\"\n \"ctester_edit click:open\" : \"openComponent\"\n \"ctester_edit click:help\" : \"showHelp\"\n \"ctester_edit click:console\" : \"toggleConsole\"\n \"ctester_edit eval:error\" : \"onError\"\n \"ctester_edit eval:success\" : \"onSuccess\"\n \"ctester_edit edit:setup\" : \"editSetup\"\n \"ctester_edit edit:teardown\" : \"editTeardown\"\n \"ctester_edit edit:component\" : \"editComponent\"\n \"ctester_edit edit:style\" : \"editStyle\"\n \"ctester_edit edit:markup\" : \"editMarkup\"\n \"ctester_edit edit:implementation\" : \"editImplementation\"\n \"ctester_edit toggle:keymap\" : \"toggleKeymap\"\n \"ctester_edit toggle:mode\" : \"toggleMode\"\n \"ctester_edit code:change:html\" : \"onMarkupChange\"\n \"ctester_edit code:change:style\" : \"onStyleChange\"\n \"ctester_edit toggle:size\" : \"toggleSize\"\n\n\n initialize: ()->\n Luca.core.Container::initialize.apply(@, arguments)\n\n for key, value of @componentEvents\n @[ value ] = _.bind(@[value], @)\n\n @defer(\"editComponent\").until(\"after:render\")\n\n afterRender: ()->\n changeHandler = _.idleMedium ()=>\n if @autoEvaluateCode is true\n @applyTestRun()\n , 500\n\n @getEditor().bind \"code:change\", changeHandler\n\n getEditor: ()->\n Luca(\"ctester_edit\")\n\n getDetail: ()->\n Luca(\"component_detail\")\n\n getOutput: ()->\n @getDetail().findComponentByName(\"component_tester_output\")\n\n onError: (error, bufferId)->\n console.log \"Error in #{ bufferId }\", error, error.message, error.stack\n\n onSuccess: (result, bufferId)->\n if bufferId is \"component\"\n @componentDefinition = result\n\n if bufferId is \"implementation\"\n if Luca.isBackboneView(result)\n object = result\n else if _.isObject(result) and result.ctype?\n object = Luca(result)\n else if _.isObject(result) and _.isFunction(@componentDefinition)\n object = ( new @componentDefinition(result) )\n\n if Luca.isBackboneView(object)\n @getOutput().$html( object.render().el )\n\n applyTestRun: ()->\n @getOutput().$html('')\n\n for bufferId, code of @getTestRun()\n @evaluateCode(code, bufferId)\n\n toggleConsole: (button)->\n @developmentConsole = Luca \"coffeescript-console\", ()-> new Luca.tools.DevelopmentConsole(name:\"coffeescript-console\")\n\n unless @consoleContainerAppended\n container = @make(\"div\",{id:\"devtools-console-wrapper\",class:\"devtools-console-container modal\",style:\"width:900px;height:650px;\"}, @developmentConsole.el)\n $('body').append( container )\n @consoleContainerAppended = true\n @developmentConsole.render()\n\n $('#devtools-console-wrapper').modal(backdrop:false,show:true)\n\n toggleAutoeval: (button)->\n @autoEvaluateCode = !(@autoEvaluateCode is true)\n\n if not @started and @autoEvaluateCode is true\n @started = true\n @applyTestRun()\n\n iconHolder = button.children('i').eq(0)\n buttonClass = if @autoEvaluateCode then \"icon-pause\" else \"icon-play\"\n iconHolder.removeClass()\n iconHolder.addClass(buttonClass)\n\n @\n\n showEditor: (options)->\n @getEditor().$('.toolbar-container.top').toggle(options)\n @getEditor().$('.codemirror-wrapper').toggle(options)\n @trigger \"controls:toggled\"\n\n toggleKeymap: (button)->\n newMode = if @getEditor().keyMap is \"vim\" then \"basic\" else \"vim\"\n @getEditor().setKeyMap(newMode)\n button.html( _.string.capitalize(newMode) )\n\n toggleMode: (button)->\n newMode = if @getEditor().mode is \"coffeescript\" then \"javascript\" else \"coffeescript\"\n @getEditor().setMode(newMode)\n button.html _.string.capitalize((if newMode is \"coffeescript\" then \"View Javascript\" else \"View Coffeescript\"))\n @editBuffer @currentBufferName, (newMode is \"javascript\")\n\n\n\n\n toggleSize: (button)->\n index = @currentSize++ % @sizes.length\n newSize = @sizes[ index ].value()\n newIcon = @sizes[ index ].icon\n\n if button?\n iconHolder = button.children('i').eq(0)\n iconHolder.removeClass().addClass(\"icon-#{ newIcon }\")\n\n @$('.codemirror-wrapper').css('height', \"#{ parseInt(newSize) }px\")\n @getEditor().refresh()\n\n toggleControls: (button)->\n @bind \"controls:toggled\", ()=>\n iconHolder = button.children('i').eq(0)\n iconHolder.removeClass()\n\n buttonClass = if @getEditor().$('.toolbar-container.top').is(\":visible\") then \"icon-eye-close\" else \"icon-eye-open\"\n iconHolder.addClass(buttonClass)\n\n @showEditor()\n\n @\n\n toggleSettings: ()->\n @\n\n setValue: (value, buffer=\"component\")->\n compiled = @getEditor().editor.getOption('mode') is \"javascript\"\n @editBuffer(buffer, compiled, false).getEditor().setValue( value )\n\n editBuffer: (@currentBufferName, compiled=false, autoSave=true)->\n @showEditor(true)\n @highlight(@currentBufferName)\n\n buffer = if compiled then \"compiled_#{ @currentBufferName }\" else @currentBufferName\n @getEditor().loadBuffer(buffer,autoSave)\n @\n\n editMarkup: ()->\n @getEditor().setMode('htmlmixed')\n @getEditor().setWrap(true)\n @editBuffer(\"html\").setValue(@getOutput().$html(), 'html')\n\n editStyle: ()->\n @getEditor().setMode('css')\n @editBuffer(\"style\")\n\n editComponent: ()->\n @getEditor().setMode('coffeescript')\n @editBuffer(\"component\")\n\n editTeardown: ()->\n @getEditor().setMode('coffeescript')\n @editBuffer(\"teardown\")\n\n editSetup: ()->\n @getEditor().setMode('coffeescript')\n @editBuffer(\"setup\")\n\n editImplementation: ()->\n @getEditor().setMode('coffeescript')\n @editBuffer(\"implementation\")\n\n getTestRun: ()->\n editor = @getEditor()\n\n testRun = {}\n\n for buffer in [\"component\",\"setup\",\"implementation\"]\n testRun[buffer] = editor.getBuffer(buffer, true)\n\n testRun\n\n getContext: ()->\n Luca.util.resolve(@context||=\"window\")\n\n evaluateCode: (code, bufferId, compile=false)->\n code ||= @getEditor().getValue()\n compiled = if compile is true then @getEditor().compileCode(code) else code\n\n evaluator = ()-> eval( compiled )\n\n try\n result = evaluator.call( @getContext() )\n @onSuccess(result, bufferId, code)\n catch error\n @onError( error, bufferId, code)\n\n onMarkupChange: ()->\n if @autoEvaluateCode is true\n @getOutput().$html @getEditor().getValue()\n\n onStyleChange: ()->\n if @autoEvaluateCode is true\n $('#component-tester-stylesheet').remove()\n\n style = @getEditor()?.getValue()\n\n if style\n styleTag = @make \"style\", type:\"text/css\", id: \"component-tester-stylesheet\"\n $('head').append( styleTag )\n $(styleTag).append(style)\n\n showHelp: ()->\n @getOutput().$html( Luca.template(\"component_tester/help\",@) )\n\n addComponent: (button)->\n\n openComponent: (button)->\n @componentPicker ||= new ComponentPicker()\n\n @componentPicker.bind \"component:fetched\", (source, component)=>\n @setEditorNamespace(component).setValue( source, \"component\")\n\n if !@getEditor().$('.component-picker').length > 0\n @getEditor().$('.codemirror-wrapper').before(@componentPicker.createWrapper())\n @getEditor().$('.component-picker').html( @componentPicker.render().el )\n @componentPicker.show()\n return\n\n @componentPicker.toggle()\n\n highlight: (section)->\n @$(\"a.btn[data-eventid='edit:#{ section }']\").siblings().css('font-weight','normal')\n @$(\"a.btn[data-eventid='edit:#{ section }']\").css('font-weight','bold')\n\n setEditorNamespace: (namespace)->\n @getEditor().namespace( namespace )\n @getEditor().buffers.fetch()\n @"},{"className":"Luca.models.Component","file":"src/tools/models/components.coffee","source":"_.def(\"Luca.models.Component\").extends(\"Luca.Model\").with\n root: ()->\n @get(\"className\").split('.')[0]\n\n className: ()->\n @get(\"className\")\n\n instances: ()->\n Luca.registry.findInstancesByClassName @className()\n\n definitionPrototype: ()->\n @definition()?.prototype \n\n parentClasses: ()->\n Luca.parentClasses( @className() ) \n\n definition: ()->\n Luca.util.resolve @className()\n\n namespace: ()->\n return \"\" unless @get(\"className\")?\n\n parts = @get(\"className\").split('.')\n parts.pop()\n parts.join \".\"\n"},{"className":"Sandbox.Application","file":"assets/javascripts/sandbox/application.coffee","source":"_.def('Sandbox.Application').extends('Luca.Application').with\n\n autoBoot: true\n\n name: 'SandboxApp'\n\n router: \"Sandbox.Router\"\n\n el: '#viewport'\n\n fluid: true\n\n topNav:'top_navigation'\n\n useKeyHandler: true\n\n keyEvents:\n meta:\n forwardslash: \"developmentConsole\"\n\n collectionManager:\n initialCollections: [\"components\"]\n\n components:[\n ctype: 'controller'\n name: 'pages'\n components:[\n name: \"main\"\n className:\"marketing-content\"\n bodyTemplate: 'main'\n ,\n name: \"intro\"\n className:\"marketing-content\"\n bodyTemplate: \"readme\"\n ,\n name: \"build\"\n ctype: \"builder\"\n ]\n ]\n\n developmentConsole: ()->\n @developmentConsole = Luca \"coffeescript-console\", ()->\n new Luca.tools.DevelopmentConsole(name:\"coffeescript-console\")\n\n unless @consoleContainerAppended\n container = @make(\"div\",{id:\"devtools-console-wrapper\",class:\"devtools-console-container modal\",style:\"width:1000px\"}, @developmentConsole.el)\n $('body').append( container )\n @consoleContainerAppended = true\n @developmentConsole.render()\n\n $('#devtools-console-wrapper').modal(backdrop:false,show:true)\n\n$ -> \n new Sandbox.Application()"},{"className":"Sandbox.views.BuilderCanvas","file":"assets/javascripts/sandbox/views/builder/builder_canvas.coffee","source":"_.def(\"Sandbox.views.BuilderCanvas\").extends(\"Luca.View\").with\n name: \"builder_canvas\"\n bodyTemplate: \"builder\""},{"className":"Sandbox.views.BuilderEditor","file":"assets/javascripts/sandbox/views/builder/builder_editor.coffee","source":"_.def(\"Sandbox.views.BuilderEditor\").extends(\"Luca.tools.CoffeeEditor\").with\n name: \"builder_editor\"\n\n bottomToolbar:\n buttons:[\n eventId:\"toggle:source\"\n label:\"mode: coffeescript\"\n ]\n\n toggleSource:()->\n @_super(\"toggleMode\", @, arguments)\n @updateToggleSourceButton()\n\n updateToggleSourceButton: ()->\n @$('[data-eventid=\"toggle:source\"]').html(\"mode: #{ @currentMode() }\")\n"},{"className":"Sandbox.views.ComponentList","file":"assets/javascripts/sandbox/views/builder/component_list.coffee","source":"_.def(\"Sandbox.views.ComponentList\").extends(\"Luca.components.CollectionView\").with\n name: \"component_list\"\n id: \"component_list\"\n className:\"span3\"\n collection:\"components\"\n itemTagName:\"div\"\n itemRenderer: (item, model, index)->\n Luca.util.make(\"a\",{\"data-index\":index}, model.className() )\n\n autoBindEventHandlers: true\n\n events:\n \"click div.collection-item a\" : \"clickHandler\"\n\n clickHandler: (e)->\n e.preventDefault()\n me = my = $( e.target )\n component = @collection.at( my.data('index') )\n @trigger \"selected\", component"},{"className":"Sandbox.views.Builder","file":"assets/javascripts/sandbox/views/builder.coffee","source":"_.def(\"Sandbox.views.Builder\").extends(\"Luca.core.Container\").with\n name: \"builder\"\n id: \"builder\"\n components:[\n ctype: \"builder_canvas\"\n className: \"builder-canvas\"\n ,\n ctype: \"container\"\n name:\"editor_container\"\n bodyClassName:\"row-fluid\" \n\n topToolbar:\n buttons:[\n align:\"left\"\n label:\"View\"\n dropdown:[\n [\"toggle:all\",\"All\"]\n [\"toggle:collections\",\"Collections\"]\n [\"toggle:models\",\"Models\"]\n [\"toggle:views\",\"Views\"],\n ]\n ]\n\n componentEvents:\n \"component_list selected\" : \"onComponentSelection\"\n\n components:[\n ctype:\"component_list\"\n name: \"component_list\"\n className:\"span3\"\n beforeRender: ()->\n @collection.fetch()\n ,\n ctype: \"builder_editor\" \n className:\"span9 builder-editor-container\"\n styles:\n \"margin-left\":\"0px\"\n \"width\":\"76%\"\n ]\n\n onComponentSelection: (component)->\n Luca(\"builder_editor\").setValue( component.get('source') )\n Luca(\"builder_editor\").state.set('currentMode','coffeescript')\n Luca(\"builder_editor\").updateToggleSourceButton()\n ]\n\n\n initialize: (@options={})->\n Luca.core.Container::initialize.apply(@, arguments)\n\n @state = new Backbone.Model\n canvasLayout: \"horizontal-split\" \n\n @state.bind \"change:canvasLayout\", ()=>\n @$el.removeClass().addClass @state.get(\"canvasLayout\")\n\n canvas: ()-> Luca(\"builder_canvas\")\n editor: ()-> Luca(\"builder_editor\")\n componentList: ()-> Luca(\"component_list\")\n\n fitToScreen: ()->\n viewportHeight = $(window).height()\n half = viewportHeight * 0.5\n toolbarHeight = 0\n toolbarHeight += @$('.toolbar-container.top').height() * @$('.toolbar-container.top').length\n\n @canvas().$el.height( half - toolbarHeight - 40 )\n\n @componentList().$el.height( half )\n @editor().$el.height( half )\n @editor().setHeight( half - 50 )\n\n activation: ()->\n @fitToScreen()\n\n deactivation: ()->\n\n beforeRender: ()->\n Luca.core.Container::beforeRender?.apply(@, arguments)\n @$el.removeClass().addClass @state.get(\"canvasLayout\")\n\n"},{"className":"Sandbox.views.TopNavigation","file":"assets/javascripts/sandbox/views/top_navigation.coffee","source":"_.def(\"Sandbox.views.TopNavigation\").extends(\"Luca.components.NavBar\").with\n brand: \"Luca\"\n name: \"top_navigation\"\n template: \"sandbox/navigation\""}]
@@ -1,84 +0,0 @@
1
- describe 'The Form View', ->
2
- beforeEach ->
3
- FormView = Luca.components.FormView.extend
4
- components:[
5
- ctype: 'hidden_field'
6
- name: 'id'
7
- ,
8
-
9
- ctype: "text_field",
10
- label: "Field Two"
11
- name: "field2"
12
- ,
13
- ctype: "text_field",
14
- label: "Field One"
15
- name: "field1"
16
- ,
17
- ctype: "checkbox_field"
18
- label: "Field Three"
19
- name: "field3"
20
- ,
21
- name: "field4"
22
- label: "Field Four"
23
- ctype: "text_area_field"
24
- ,
25
- name: "field5"
26
- ctype: "button_field"
27
- label: "Click Me"
28
- ]
29
-
30
- Model = Backbone.Model.extend
31
- schema:
32
- field0: "hidden"
33
- field2: "text"
34
- field1: "text"
35
- field3: "boolean"
36
- field4: "blob"
37
- field5:
38
- collection: "sample"
39
-
40
- @form = new FormView()
41
- @model = new Model(field0:1,field1:"jonathan",field3:true,field4:"what up player?")
42
-
43
- afterEach ->
44
- @form = undefined
45
- @model = undefined
46
-
47
- it "should create a form", ->
48
- expect( @form ).toBeDefined()
49
-
50
- it "should have access to all of the fields", ->
51
- @form.render()
52
- expect( @form.getFields().length ).toEqual 6
53
-
54
- it "should load the model", ->
55
- @form.loadModel(@model)
56
- expect( @form.currentModel() ).toEqual @model
57
-
58
- it "should set the field values from the model when loaded", ->
59
- @form.render()
60
- @form.loadModel(@model)
61
- values = @form.getValues()
62
- expect( values.field1 ).toEqual "jonathan"
63
-
64
- it "should render the components within the body element", ->
65
- @form.render()
66
- expect( @form.$bodyEl().is('.form-view-body') ).toEqual true
67
-
68
- it "should assign the components to render inside of the body", ->
69
- @form.render()
70
- expect( @form.$bodyEl().html() ).toContain "Field Four"
71
-
72
- it "should allow me to set the values of the form fields with a hash", ->
73
- @form.render()
74
- @form.setValues(field1:"yes",field2:"no")
75
- values = @form.getValues()
76
-
77
- expect( values.field1 ).toEqual "yes"
78
- expect( values.field2 ).toEqual "no"
79
-
80
- it "should sync the model with the form field values", ->
81
- @form.render()
82
- @form.loadModel(@model)
83
- @form.setValues(field1:"yes")
84
- expect( @form.getValues().field1 ).toEqual "yes"
@@ -1,50 +0,0 @@
1
- describe "The Card View", ->
2
- beforeEach ->
3
- @cardView = new Luca.containers.CardView
4
- activeItem: 0
5
- components:[
6
- markup: "component one"
7
- name: "one"
8
- one: true
9
- ,
10
- markup: "component two"
11
- name: "two"
12
- two: true
13
- firstActivation: sinon.spy()
14
- ,
15
- markup: "component three"
16
- name: "three"
17
- three: true
18
- ]
19
-
20
- @cardView.render()
21
-
22
- it "should create three card elements", ->
23
- expect( @cardView.componentElements().length ).toEqual 3
24
-
25
- it "should hide all but one of the card elements", ->
26
- display = _( @cardView.$('.luca-ui-card') ).map (el)-> $(el).css('display')
27
- expect( display ).toEqual(['block','none','none'])
28
-
29
- it "should be able to find the cards by name", ->
30
- expect( @cardView.find("one") ).toBeDefined()
31
- expect( @cardView.find("one").one ).toEqual true
32
-
33
- it "should start with the first component active", ->
34
- expect( @cardView.activeComponent()?.name ).toEqual "one"
35
-
36
- it "should be able to activate components by name", ->
37
- @cardView.activate("two")
38
- expect( @cardView.activeComponent()?.name ).toEqual "two"
39
-
40
- it "shouldn't fire first activation on a component", ->
41
- expect( @cardView.find("two")?.firstActivation ).not.toHaveBeenCalled()
42
-
43
- it "should fire firstActivation on a component", ->
44
- @cardView.activate("two")
45
- expect( @cardView.find("two")?.firstActivation ).toHaveBeenCalled()
46
-
47
- it "should fire deactivation on a component", ->
48
- @cardView.find("one").spiedEvents = {}
49
- @cardView.activate("two")
50
- expect( @cardView.find("one") ).toHaveTriggered("deactivation")
@@ -1,9 +0,0 @@
1
- #= require_self
2
- #= require_tree ./dependencies
3
- #= require_tree ./core
4
- #= require_tree ./concerns
5
- #= require_tree ./components
6
- #= require_tree ./containers
7
- #= require_tree ./managers
8
-
9
- Luca.define.close()