luca 0.9.8 → 0.9.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +49 -0
- data/Gemfile +8 -1
- data/Gemfile.lock +97 -53
- data/Guardfile +3 -25
- data/README.md +5 -16
- data/ROADMAP +15 -9
- data/Rakefile +24 -75
- data/app.rb +10 -42
- data/app/assets/javascripts/luca/basic.coffee +1 -1
- data/app/assets/javascripts/luca/components/application.coffee +187 -104
- data/app/assets/javascripts/luca/components/collection_view.coffee +115 -51
- data/app/assets/javascripts/luca/components/controller.coffee +87 -10
- data/app/assets/javascripts/luca/components/fields/base.coffee +74 -13
- data/app/assets/javascripts/luca/components/fields/button_field.coffee +60 -13
- data/app/assets/javascripts/luca/components/fields/checkbox_array.coffee +12 -7
- data/app/assets/javascripts/luca/components/fields/select_field.coffee +82 -23
- data/app/assets/javascripts/luca/components/fields/text_area_field.coffee +25 -10
- data/app/assets/javascripts/luca/components/fields/text_field.coffee +9 -3
- data/app/assets/javascripts/luca/components/form_view.coffee +105 -33
- data/app/assets/javascripts/luca/components/grid_layout_view.coffee +42 -0
- data/app/assets/javascripts/luca/components/index.coffee +6 -0
- data/app/assets/javascripts/luca/components/nav_bar.coffee +60 -6
- data/app/assets/javascripts/luca/components/page.coffee +70 -0
- data/app/assets/javascripts/luca/components/simple_collection_view.coffee +10 -0
- data/app/assets/javascripts/luca/components/table_view.coffee +7 -3
- data/app/assets/javascripts/luca/components/table_view_scrollable.coffee +23 -0
- data/app/assets/javascripts/luca/concerns/collection_event_bindings.coffee +4 -1
- data/app/assets/javascripts/luca/concerns/development_tool_helpers.coffee +23 -14
- data/app/assets/javascripts/luca/concerns/dom_helpers.coffee +2 -2
- data/app/assets/javascripts/luca/concerns/filterable.coffee +8 -11
- data/app/assets/javascripts/luca/concerns/form_model_bindings.coffee +20 -0
- data/app/assets/javascripts/luca/concerns/modal_view.coffee +40 -15
- data/app/assets/javascripts/luca/concerns/query_collection_bindings.coffee +7 -1
- data/app/assets/javascripts/luca/concerns/state_model.coffee +40 -26
- data/app/assets/javascripts/luca/concerns/templating.coffee +3 -1
- data/app/assets/javascripts/luca/config.coffee +5 -0
- data/app/assets/javascripts/luca/containers/card_view.coffee +87 -52
- data/app/assets/javascripts/luca/containers/container.coffee +305 -108
- data/app/assets/javascripts/luca/containers/modal_view.coffee +9 -9
- data/app/assets/javascripts/luca/containers/page_controller.coffee +25 -0
- data/app/assets/javascripts/luca/containers/panel_toolbar.coffee +5 -6
- data/app/assets/javascripts/luca/containers/tab_view.coffee +19 -10
- data/app/assets/javascripts/luca/containers/viewport.coffee +12 -16
- data/app/assets/javascripts/luca/core/collection.coffee +19 -5
- data/app/assets/javascripts/luca/core/events.coffee +5 -5
- data/app/assets/javascripts/luca/core/model.coffee +1 -1
- data/app/assets/javascripts/luca/core/panel.coffee +18 -6
- data/app/assets/javascripts/luca/core/registry/component_definition.coffee +2 -1
- data/app/assets/javascripts/luca/core/registry/meta_data.coffee +2 -0
- data/app/assets/javascripts/luca/core/registry/registry.coffee +14 -11
- data/app/assets/javascripts/luca/core/templates.coffee +5 -1
- data/app/assets/javascripts/luca/core/view.coffee +200 -47
- data/app/assets/javascripts/luca/dependencies.coffee +2 -0
- data/app/assets/javascripts/luca/development/code_sync_manager.coffee +173 -0
- data/app/assets/javascripts/luca/development/component.coffee +76 -0
- data/app/assets/javascripts/luca/development/components.coffee +57 -0
- data/app/assets/javascripts/luca/development/console.coffee +1 -1
- data/app/assets/javascripts/luca/development/index.coffee +4 -1
- data/app/assets/javascripts/luca/framework.coffee +7 -3
- data/app/assets/javascripts/luca/index.coffee +2 -1
- data/app/assets/javascripts/luca/managers/collection_manager.coffee +2 -3
- data/app/assets/javascripts/luca/managers/index.coffee +1 -1
- data/app/assets/javascripts/luca/managers/socket_manager.coffee +31 -8
- data/app/assets/javascripts/luca/templates/components/nav_bar.jst.ejs +16 -1
- data/app/assets/javascripts/luca/templates/containers/tab_view.jst.ejs +1 -1
- data/app/assets/javascripts/luca/util/index.coffee +1 -0
- data/app/assets/javascripts/luca/util/keybindings.coffee +24 -0
- data/app/assets/javascripts/luca/util/logging.coffee +15 -0
- data/app/assets/javascripts/luca/util/luca.coffee +9 -1
- data/app/assets/stylesheets/luca/components/table_view.scss +85 -0
- data/app/assets/stylesheets/luca/components/viewport.scss +0 -4
- data/app/assets/stylesheets/luca/containers/container.scss +8 -0
- data/app/assets/stylesheets/luca/index.css +2 -2
- data/bin/luca +14 -0
- data/config.ru +1 -2
- data/docs/framework.json +1 -0
- data/docs/luca-framework-documentation.js +1 -0
- data/docs/{application.md → old/application.md} +0 -0
- data/docs/{collection.md → old/collection.md} +0 -0
- data/docs/{collection_manager.md → old/collection_manager.md} +0 -0
- data/docs/{container_philosophy.md → old/container_philosophy.md} +0 -0
- data/docs/{event_binding_helpers.md → old/event_binding_helpers.md} +0 -0
- data/docs/{method_caching_and_computed_properties.md → old/method_caching_and_computed_properties.md} +0 -0
- data/docs/{view.md → old/view.md} +0 -0
- data/lib/generators/luca/application/templates/javascripts/dependencies.coffee +2 -5
- data/lib/guard/luca.rb +84 -0
- data/lib/luca.rb +25 -1
- data/lib/luca/asset_compiler.rb +117 -0
- data/lib/luca/cli.rb +68 -0
- data/lib/luca/cli/generate.rb +37 -0
- data/lib/luca/cli/server.rb +20 -0
- data/lib/luca/cli/sync.rb +40 -0
- data/lib/luca/cli/watch.rb +16 -0
- data/lib/luca/collection.rb +64 -0
- data/lib/luca/collection/endpoint.rb +38 -0
- data/lib/luca/collection/file_backend.rb +121 -0
- data/lib/luca/collection/redis_backend.rb +153 -0
- data/lib/luca/compiled_asset.rb +61 -0
- data/lib/luca/component_definition.rb +356 -0
- data/lib/luca/luca_application.rb +258 -0
- data/lib/luca/project.rb +73 -0
- data/lib/luca/project_harness.rb +96 -0
- data/lib/luca/rails.rb +5 -3
- data/lib/luca/rails/engine.rb +8 -0
- data/lib/luca/rails/version.rb +1 -2
- data/lib/luca/server.rb +7 -0
- data/lib/luca/stylesheet.rb +35 -0
- data/lib/luca/template.rb +2 -0
- data/lib/luca/template_asset.rb +64 -0
- data/lib/luca/version.rb +3 -0
- data/lib/luca/watcher.rb +72 -0
- data/lib/railties/luca/tasks.rake +7 -0
- data/site/.bundle/config +2 -0
- data/site/.gitignore +5 -0
- data/site/.rvmrc +1 -0
- data/site/CHANGELOG.md +41 -0
- data/site/DOCS.md +41 -0
- data/site/Gemfile +8 -0
- data/site/Gemfile.lock +134 -0
- data/site/LICENSE.md +19 -0
- data/site/config.rb +84 -0
- data/site/helpers/site_helpers.rb +20 -0
- data/site/html5bp-docs/README.md +38 -0
- data/site/html5bp-docs/contribute.md +104 -0
- data/site/html5bp-docs/crossdomain.md +21 -0
- data/site/html5bp-docs/css.md +135 -0
- data/site/html5bp-docs/extend.md +507 -0
- data/site/html5bp-docs/faq.md +77 -0
- data/site/html5bp-docs/htaccess.md +323 -0
- data/site/html5bp-docs/html.md +170 -0
- data/site/html5bp-docs/js.md +31 -0
- data/site/html5bp-docs/misc.md +25 -0
- data/site/html5bp-docs/usage.md +109 -0
- data/site/readme.md +47 -0
- data/site/source/.htaccess +540 -0
- data/site/source/404.html +157 -0
- data/site/source/app/assets/javascripts/dependencies.js.coffee +6 -0
- data/site/source/app/assets/javascripts/docs-docs.js +1 -0
- data/site/source/app/assets/javascripts/docs/application.coffee +64 -0
- data/site/source/app/assets/javascripts/docs/collections/docs_documentation.coffee +17 -0
- data/site/source/app/assets/javascripts/docs/collections/github_repositories.coffee +7 -0
- data/site/source/app/assets/javascripts/docs/collections/index.coffee +1 -0
- data/site/source/app/assets/javascripts/docs/collections/luca_documentation.coffee +17 -0
- data/site/source/app/assets/javascripts/docs/collections/public_gists.coffee +4 -0
- data/site/source/app/assets/javascripts/docs/config.coffee +5 -0
- data/site/source/app/assets/javascripts/docs/index.coffee +12 -0
- data/site/source/app/assets/javascripts/docs/lib/router.coffee +3 -0
- data/{spec/components/application_spec.coffee → site/source/app/assets/javascripts/docs/lib/util.coffee} +0 -0
- data/site/source/app/assets/javascripts/docs/models/component.coffee +99 -0
- data/site/source/app/assets/javascripts/docs/models/github_repository.coffee +3 -0
- data/site/source/app/assets/javascripts/docs/models/index.coffee +1 -0
- data/site/source/app/assets/javascripts/docs/templates/component_documentation.jst.ejs +55 -0
- data/site/source/app/assets/javascripts/docs/templates/examples_browser/overview.jst.ejs +4 -0
- data/site/source/app/assets/javascripts/docs/templates/examples_browser/selector.jst.ejs +11 -0
- data/site/source/app/assets/javascripts/docs/templates/github_repository.jst.ejs +4 -0
- data/site/source/app/assets/javascripts/docs/templates/layouts/main.jst.ejs +4 -0
- data/site/source/app/assets/javascripts/docs/templates/left_navigation.jst.ejs +5 -0
- data/site/source/app/assets/javascripts/docs/templates/pages/getting_started.jst.ejs +78 -0
- data/site/source/app/assets/javascripts/docs/templates/pages/home.jst.ejs +57 -0
- data/site/source/app/assets/javascripts/docs/views/components/code_editor.coffee +45 -0
- data/{spec/components/collection_loader_view_spec.coffee → site/source/app/assets/javascripts/docs/views/components/code_editor/index.coffee} +0 -0
- data/site/source/app/assets/javascripts/docs/views/components/component_documentation.coffee +72 -0
- data/site/source/app/assets/javascripts/docs/views/index.coffee +3 -0
- data/site/source/app/assets/javascripts/docs/views/pages/browse_source.coffee +46 -0
- data/site/source/app/assets/javascripts/docs/views/pages/browse_source/details.coffee +37 -0
- data/site/source/app/assets/javascripts/docs/views/pages/browse_source/list.coffee +31 -0
- data/site/source/app/assets/javascripts/docs/views/pages/component_editor.coffee +10 -0
- data/site/source/app/assets/javascripts/docs/views/pages/examples_browser.coffee +102 -0
- data/site/source/app/assets/javascripts/docs/views/pages/examples_browser/docs.coffee +12 -0
- data/site/source/app/assets/javascripts/docs/views/pages/examples_browser/source.coffee +13 -0
- data/site/source/app/assets/javascripts/docs/views/pages/home.coffee +10 -0
- data/site/source/app/assets/javascripts/docs/views/views/api_browser/index.coffee +43 -0
- data/site/source/app/assets/javascripts/docs/views/views/collection_view_examples/grid_layout_view_example.coffee +14 -0
- data/site/source/app/assets/javascripts/docs/views/views/collection_view_examples/table_view_example.coffee +39 -0
- data/site/source/app/assets/javascripts/docs/views/views/form_view_examples/basic_example.coffee +38 -0
- data/site/source/app/assets/javascripts/docs/views/views/form_view_examples/complex_layout.coffee +110 -0
- data/site/source/app/assets/javascripts/docs/views/views/top_navigation.coffee +6 -0
- data/site/source/app/assets/javascripts/luca-docs.js +1 -0
- data/site/source/app/assets/javascripts/luca-framework-documentation.js +1 -0
- data/site/source/app/assets/javascripts/site.js.coffee +4 -0
- data/site/source/app/assets/javascripts/vendor/codemirror.js +4786 -0
- data/site/source/app/assets/javascripts/vendor/coffeescript.js +346 -0
- data/site/source/app/assets/javascripts/vendor/css.js +465 -0
- data/site/source/app/assets/javascripts/vendor/htmlmixed.js +84 -0
- data/site/source/app/assets/javascripts/vendor/javascript.js +422 -0
- data/site/source/app/assets/javascripts/vendor/js-beautify.js +1353 -0
- data/site/source/app/assets/javascripts/vendor/modernizr-2.6.1.min.js +4 -0
- data/site/source/app/assets/javascripts/vendor/vim.js +2511 -0
- data/site/source/app/assets/stylesheets/docs/api-browser.css.scss +5 -0
- data/site/source/app/assets/stylesheets/docs/application.css.scss +35 -0
- data/site/source/app/assets/stylesheets/docs/browse-source.css.scss +5 -0
- data/site/source/app/assets/stylesheets/docs/scrollable-table.css.scss +5 -0
- data/site/source/app/assets/stylesheets/site.css.scss +2 -0
- data/site/source/app/assets/stylesheets/vendor/codemirror.css +240 -0
- data/site/source/app/assets/stylesheets/vendor/prettify-tomorrow-night-bright.css +160 -0
- data/site/source/app/assets/stylesheets/vendor/twilight.css +26 -0
- data/site/source/crossdomain.xml +15 -0
- data/site/source/documentation.html.haml +1 -0
- data/site/source/favicon_base.png +0 -0
- data/site/source/humans.txt +15 -0
- data/site/source/images/background.png +0 -0
- data/site/source/images/middleman.png +0 -0
- data/site/source/index.html.haml +1 -0
- data/site/source/layouts/layout.haml +55 -0
- data/site/source/readme.md +63 -0
- data/site/source/robots.txt +3 -0
- data/spec/{components/grid_view_spec.coffee → javascripts/components/application_spec.coffee} +0 -0
- data/spec/{components/pagination_control_spec.coffee → javascripts/components/collection_loader_view_spec.coffee} +0 -0
- data/spec/{components → javascripts/components}/collection_view_spec.coffee +1 -1
- data/spec/{components → javascripts/components}/controller_spec.coffee +0 -0
- data/spec/{components → javascripts/components}/fields/checkbox_array_spec.coffee +0 -0
- data/spec/javascripts/components/form_view_spec.coffee +162 -0
- data/spec/{components/record_manager_spec.coffee → javascripts/components/grid_view_spec.coffee} +0 -0
- data/spec/{components → javascripts/components}/multi_collection_view_spec.coffee +0 -0
- data/spec/{components/template_spec.coffee → javascripts/components/pagination_control_spec.coffee} +0 -0
- data/spec/{concerns/paginatable_spec.coffee → javascripts/components/record_manager_spec.coffee} +0 -0
- data/spec/{components → javascripts/components}/table_view_spec.coffee +0 -0
- data/spec/{containers/modal_view_spec.coffee → javascripts/components/template_spec.coffee} +0 -0
- data/spec/{concerns → javascripts/concerns}/collection_event_bindings_spec.coffee +0 -0
- data/spec/{concerns → javascripts/concerns}/dom_helpers_spec.coffee +0 -0
- data/spec/{concerns → javascripts/concerns}/filterable_spec.coffee +0 -0
- data/spec/{concerns → javascripts/concerns}/model_presenter_spec.coffee +0 -0
- data/spec/{containers/panel_view_spec.coffee → javascripts/concerns/paginatable_spec.coffee} +0 -0
- data/spec/{concerns → javascripts/concerns}/state_model_spec.coffee +5 -0
- data/spec/javascripts/containers/card_view_spec.coffee +108 -0
- data/spec/{containers/tab_view_spec.coffee → javascripts/containers/modal_view_spec.coffee} +0 -0
- data/spec/{containers/viewport_spec.coffee → javascripts/containers/panel_view_spec.coffee} +0 -0
- data/spec/{core/observer_spec.coffee → javascripts/containers/tab_view_spec.coffee} +0 -0
- data/spec/{managers/socket_manager_spec.coffee → javascripts/containers/viewport_spec.coffee} +0 -0
- data/spec/{core → javascripts/core}/collection_spec.coffee +1 -1
- data/spec/{core → javascripts/core}/concerns_spec.coffee +0 -0
- data/spec/{core → javascripts/core}/container_spec.coffee +0 -0
- data/spec/{core → javascripts/core}/define_spec.coffee +0 -0
- data/spec/{core → javascripts/core}/events_spec.coffee +0 -0
- data/spec/{core → javascripts/core}/field_spec.coffee +0 -0
- data/spec/{core → javascripts/core}/framework_spec.coffee +0 -0
- data/spec/{core → javascripts/core}/model_spec.coffee +0 -0
- data/spec/javascripts/core/observer_spec.coffee +0 -0
- data/spec/{core → javascripts/core}/util_spec.coffee +0 -0
- data/spec/{core → javascripts/core}/view_spec.coffee +51 -39
- data/spec/{dependencies → javascripts/dependencies}/index.coffee +0 -0
- data/spec/{dependencies → javascripts/dependencies}/jasmine-html.js +0 -0
- data/spec/{dependencies → javascripts/dependencies}/jasmine.js +0 -0
- data/spec/{dependencies → javascripts/dependencies}/sinon.js +0 -0
- data/spec/{helper.coffee → javascripts/helper.coffee} +0 -0
- data/spec/{managers → javascripts/managers}/collection_manager_spec.coffee +0 -0
- data/spec/javascripts/managers/socket_manager_spec.coffee +0 -0
- data/spec/lib/component_definition_spec.rb +63 -0
- data/spec/lib/input_compiler_spec.rb +9 -0
- data/spec/lib/luca_application_spec.rb +30 -0
- data/spec/support/fixtures/application.coffee +45 -0
- data/spec/support/fixtures/component.coffee +34 -0
- data/tutorials/component-definitions.md +0 -0
- data/tutorials/component-definitions/01_intro.md +0 -0
- data/tutorials/component-driven-design.md +140 -0
- data/tutorials/structure-of-a-project.md +63 -0
- data/vendor/assets/javascripts/backbone-min.js +37 -33
- data/vendor/assets/javascripts/backbone-query.min.js +1 -1
- data/vendor/assets/javascripts/hogan.js +707 -0
- data/vendor/assets/javascripts/jquery.js +5 -4
- data/vendor/assets/javascripts/keymaster.min.js +4 -0
- data/vendor/assets/javascripts/luca-dependencies.min.js +8 -0
- data/vendor/assets/javascripts/luca-development.min.js +1 -0
- data/vendor/assets/javascripts/luca-spec.js +6 -6
- data/vendor/assets/javascripts/luca-ui.js +7386 -0
- data/vendor/assets/javascripts/luca-ui.min.js +5 -0
- data/vendor/assets/javascripts/luca.full.min.js +12 -0
- data/vendor/assets/javascripts/luca.min.js +5 -0
- data/vendor/assets/javascripts/underscore-min.js +1 -5
- data/vendor/assets/javascripts/underscore-string.min.js +1 -1
- data/vendor/assets/stylesheets/luca-components.css +202 -0
- data/vendor/assets/stylesheets/luca-development.css +23 -0
- data/vendor/assets/stylesheets/luca-ui.css +198 -0
- metadata +324 -94
- data/app/assets/javascripts/luca/components/base_toolbar.coffee +0 -17
- data/app/assets/javascripts/luca/components/form_button_toolbar.coffee +0 -28
- data/app/assets/javascripts/luca/components/grid_view.coffee +0 -269
- data/app/assets/javascripts/luca/components/page_controller.coffee +0 -7
- data/app/assets/javascripts/luca/components/template.coffee +0 -5
- data/app/assets/javascripts/luca/components/toolbar_dialog.coffee +0 -25
- data/lib/luca/code_browser.rb +0 -55
- data/lib/luca/command_line.rb +0 -69
- data/lib/luca/component_documentation.rb +0 -72
- data/site/assets/bootstrap.min.js +0 -7
- data/site/assets/dependencies.js +0 -94
- data/site/assets/glyphicons-halflings-white.png +0 -0
- data/site/assets/glyphicons-halflings.png +0 -0
- data/site/assets/luca-ui-bootstrap.css +0 -1331
- data/site/assets/luca-ui-bootstrap.js +0 -9
- data/site/assets/luca-ui-development-tools.css +0 -234
- data/site/assets/luca-ui-development-tools.js +0 -18561
- data/site/assets/luca-ui-development-tools.min.js +0 -15
- data/site/assets/luca-ui-full.min.js +0 -8
- data/site/assets/luca-ui.min.js +0 -4
- data/site/assets/sandbox.css +0 -62
- data/site/assets/sandbox.js +0 -469
- data/site/docs/application.html +0 -41
- data/site/docs/caching.html +0 -43
- data/site/docs/collection.html +0 -75
- data/site/docs/collection_manager.html +0 -71
- data/site/docs/containers.html +0 -118
- data/site/docs/events.html +0 -153
- data/site/docs/view.html +0 -128
- data/site/img/glyphicons-halflings-white.png +0 -0
- data/site/img/glyphicons-halflings.png +0 -0
- data/site/index.html +0 -20
- data/site/source-map.js +0 -1
- data/spec/components/form_view_spec.coffee +0 -84
- data/spec/containers/card_view_spec.coffee +0 -50
- data/spec/luca-spec.coffee +0 -9
@@ -21,6 +21,12 @@ Luca.concerns.QueryCollectionBindings =
|
|
21
21
|
|
22
22
|
Luca.util.readAll(query)
|
23
23
|
|
24
|
+
getRemoteQuery: (options = {}) ->
|
25
|
+
@getQuery(options)
|
26
|
+
|
27
|
+
getLocalQuery: (options = {}) ->
|
28
|
+
@getQuery(options)
|
29
|
+
|
24
30
|
# Private: returns the query that is applied to the underlying collection.
|
25
31
|
# accepts the same options as Luca.Collection.query's initial query option.
|
26
32
|
getQueryOptions: (options={})->
|
@@ -34,7 +40,7 @@ Luca.concerns.QueryCollectionBindings =
|
|
34
40
|
# responds to @query() then it will use that interface.
|
35
41
|
getModels: (query,options)->
|
36
42
|
if @collection?.query
|
37
|
-
query ||= @
|
43
|
+
query ||= @getLocalQuery()
|
38
44
|
options ||= @getQueryOptions()
|
39
45
|
options.prepare ||= @prepareQuery
|
40
46
|
|
@@ -1,44 +1,58 @@
|
|
1
|
+
|
2
|
+
stateModel = Luca.register("Luca.ViewState").extends("Luca.Model")
|
3
|
+
|
1
4
|
Luca.concerns.StateModel =
|
5
|
+
__onModelChange: (args...)->
|
6
|
+
statefulView = @
|
7
|
+
state = statefulView.state
|
8
|
+
|
9
|
+
@trigger.call(statefulView, "state:change", args... )
|
10
|
+
|
11
|
+
for changed, value of state.changedAttributes()
|
12
|
+
@trigger.call statefulView, "state:change:#{ changed }", state, value, state.previous(changed)
|
13
|
+
|
2
14
|
__initializer: ()->
|
3
15
|
@stateful = @stateAttributes if @stateAttributes?
|
4
16
|
|
5
17
|
return unless @stateful?
|
6
|
-
return if @state?
|
7
18
|
|
19
|
+
statefulView = @
|
20
|
+
|
8
21
|
if _.isObject(@stateful) and not @defaultState?
|
9
22
|
@defaultState = @stateful
|
10
23
|
|
11
|
-
@state
|
12
|
-
|
13
|
-
|
24
|
+
@state ||= new Luca.ViewState(@defaultState || {})
|
25
|
+
|
26
|
+
view = @
|
27
|
+
|
28
|
+
@get = ()->
|
29
|
+
view.state.get.apply(view.state, arguments)
|
30
|
+
|
31
|
+
@set = ()->
|
32
|
+
view.state.set.apply(view.state, arguments)
|
14
33
|
|
15
34
|
for key, value of @state.toJSON()
|
16
35
|
hook = "on" + _.str.capitalize(key) + "Change"
|
17
36
|
getter = "get" + _.str.capitalize(key)
|
18
37
|
unless _.isFunction(@[getter])
|
19
38
|
1
|
20
|
-
#console.log("State Change Getter", getter)
|
21
|
-
# @[getter] = ()=> @state.get(key)
|
22
|
-
# WE COULD CREATE AUTO GETTERS HERE
|
23
|
-
|
24
39
|
if _.isFunction(@[hook])
|
25
40
|
1
|
26
|
-
#console.log("State Change Hook", hook)
|
27
|
-
# @stateChangeEvents[ key ] = hook
|
28
|
-
# WE COULD AUTO BIND TO STATE CHANGE EVENTS HERE
|
29
|
-
|
30
|
-
unless _.isEmpty(@stateChangeEvents)
|
31
|
-
for attribute, handler of @stateChangeEvents
|
32
|
-
fn = if _.isString(handler) then @[handler] else handler
|
33
|
-
|
34
|
-
if attribute is "*"
|
35
|
-
@on "state:change", fn, @
|
36
|
-
else
|
37
|
-
@on "state:change:#{ attribute }", fn, @
|
38
|
-
|
39
|
-
@state.on "change", (state)=>
|
40
|
-
@trigger "state:change", state
|
41
|
-
|
42
|
-
for changed, value of state.changedAttributes()
|
43
|
-
@trigger "state:change:#{ changed }", state, value, state.previous(changed)
|
44
41
|
|
42
|
+
Luca.concerns.StateModel.__setupModelBindings.call(@, "on")
|
43
|
+
|
44
|
+
__setupModelBindings: (direction="on")->
|
45
|
+
statefulView = @
|
46
|
+
for attribute, handler of @stateChangeEvents
|
47
|
+
fn = if _.isString(handler) then statefulView[handler] else handler
|
48
|
+
|
49
|
+
if attribute is "*"
|
50
|
+
statefulView[direction]("state:change", fn, statefulView)
|
51
|
+
else
|
52
|
+
statefulView[direction]("state:change:#{ attribute }", fn, statefulView)
|
53
|
+
|
54
|
+
# Any time there is a model change event on the internal state machine
|
55
|
+
# we will trigger a general state:change event on the component as well
|
56
|
+
# as individual state:change:attribute events
|
57
|
+
state = statefulView.state
|
58
|
+
statefulView.state[direction]("change", Luca.concerns.StateModel.__onModelChange, statefulView)
|
@@ -4,8 +4,10 @@ Luca.concerns.Templating =
|
|
4
4
|
|
5
5
|
if template = @bodyTemplate
|
6
6
|
@$el.empty()
|
7
|
+
|
7
8
|
try
|
8
9
|
templateContent = Luca.template(template, templateVars)
|
9
10
|
catch e
|
10
|
-
console.log "Error Rendering #{
|
11
|
+
console.log "Error Rendering #{ template} in View: #{ @identifier?() || @name || @cid }"
|
12
|
+
|
11
13
|
Luca.View::$html.call(@, templateContent)
|
@@ -25,9 +25,12 @@ Luca.enableGlobalObserver = Luca.config.enableGlobalObserver = false
|
|
25
25
|
# for what it is best at, and not try to solve this
|
26
26
|
# problem on our own!
|
27
27
|
Luca.config.enableBoostrap = Luca.config.enableBootstrap = true
|
28
|
+
Luca.config.fluidWrapperClass = "container-fluid"
|
29
|
+
Luca.config.wrapperClass = "container"
|
28
30
|
|
29
31
|
Luca.config.enhancedViewProperties = true
|
30
32
|
|
33
|
+
# Need to replace this with something like keymaster.js
|
31
34
|
Luca.keys = Luca.config.keys =
|
32
35
|
ENTER: 13
|
33
36
|
ESCAPE: 27
|
@@ -37,6 +40,7 @@ Luca.keys = Luca.config.keys =
|
|
37
40
|
KEYDOWN: 40
|
38
41
|
SPACEBAR: 32
|
39
42
|
FORWARDSLASH: 191
|
43
|
+
TAB: 9
|
40
44
|
|
41
45
|
Luca.config.toolbarContainerClass = "toolbar-container"
|
42
46
|
|
@@ -47,3 +51,4 @@ Luca.keyMap = Luca.config.keyMap = _( Luca.keys ).inject (memo, value, symbol)->
|
|
47
51
|
, {}
|
48
52
|
|
49
53
|
Luca.config.showWarnings = true
|
54
|
+
Luca.config.default_socket_port = 9292
|
@@ -1,8 +1,3 @@
|
|
1
|
-
component = Luca.define "Luca.containers.CardView"
|
2
|
-
component.extends "Luca.Container"
|
3
|
-
|
4
|
-
component.aliases "Luca.PageView"
|
5
|
-
#
|
6
1
|
# The CardView is a type of Container which has many sub-views
|
7
2
|
# which are only going to be visible one at a time. A CardView
|
8
3
|
# allows you to @activate() its cards, navigate through them using
|
@@ -23,75 +18,70 @@ component.aliases "Luca.PageView"
|
|
23
18
|
# cardView.activeComponent().name # => "one"
|
24
19
|
# cardView.activate('two')
|
25
20
|
# cardView.activeComponent().name # => "two"
|
26
|
-
|
27
|
-
component.
|
28
|
-
|
29
|
-
className: 'luca-ui-card-view-wrapper'
|
21
|
+
component = Luca.register "Luca.containers.CardView"
|
22
|
+
component.extends "Luca.Container"
|
30
23
|
|
24
|
+
component.publicConfiguration
|
31
25
|
activeCard: 0
|
32
|
-
|
33
26
|
components: []
|
34
27
|
|
28
|
+
component.classInterface
|
29
|
+
# When the activate method is called and passed a callback
|
30
|
+
# what context should we run that callback in? Default is
|
31
|
+
# to call the callback in the context of the component that
|
32
|
+
# is currently being activated
|
33
|
+
activationContext: "current"
|
34
|
+
|
35
|
+
component.privateConfiguration
|
36
|
+
# Will automatically call beforeCardSwitch and afterCardSwitch
|
37
|
+
# methods if they exist on this view. These events will be triggered
|
38
|
+
# in response to a call to @activate()
|
35
39
|
hooks:[
|
36
40
|
'before:card:switch',
|
37
41
|
'after:card:switch'
|
38
42
|
]
|
39
43
|
|
44
|
+
# Which css class should we apply to each of the cards
|
40
45
|
componentClass: 'luca-ui-card'
|
41
|
-
generateComponentElements: true
|
42
|
-
|
43
|
-
initialize: (@options)->
|
44
|
-
@components ||= @pages ||= @cards
|
45
|
-
Luca.Container::initialize.apply @,arguments
|
46
|
-
@setupHooks(@hooks)
|
47
|
-
|
48
|
-
@defer( @simulateActivationEvent, @ ).until("after:render")
|
49
|
-
|
50
|
-
simulateActivationEvent: ()->
|
51
|
-
c = @activeComponent()
|
52
46
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
prepareComponents: ()->
|
57
|
-
Luca.Container::prepareComponents?.apply(@, arguments)
|
58
|
-
@componentElements().hide()
|
59
|
-
@activeComponentElement().show()
|
60
|
-
|
61
|
-
activeComponentElement: ()->
|
62
|
-
@componentElements().eq( @activeCard )
|
63
|
-
|
64
|
-
activeComponent: ()->
|
65
|
-
@getComponent( @activeCard )
|
66
|
-
|
67
|
-
customizeContainerEl: (containerEl, panel, panelIndex)->
|
68
|
-
containerEl.style += if panelIndex is @activeCard then "display:block;" else "display:none;"
|
69
|
-
|
70
|
-
containerEl
|
47
|
+
# Should we generate elements to append each component?
|
48
|
+
generateComponentElements: true
|
71
49
|
|
50
|
+
component.publicMethods
|
51
|
+
# Returns true if at the first
|
72
52
|
atFirst: ()->
|
73
53
|
@activeCard is 0
|
74
54
|
|
55
|
+
# Returns true if we're at the last card
|
75
56
|
atLast: ()->
|
76
57
|
@activeCard is @components.length - 1
|
77
58
|
|
59
|
+
# Activate the next component. If at the last, do nothing.
|
78
60
|
next: ()->
|
79
61
|
return if @atLast()
|
80
62
|
@activate( @activeCard + 1)
|
81
63
|
|
64
|
+
# Activate the previous component. If at the first, do nothing.
|
82
65
|
previous: ()->
|
83
66
|
return if @atFirst()
|
84
67
|
@activate( @activeCard - 1)
|
85
68
|
|
69
|
+
# Activates the next component after the current one.
|
70
|
+
# If at the last component, it will activate the first.
|
86
71
|
cycle: ()->
|
87
72
|
nextIndex = if @atLast() then 0 else @activeCard + 1
|
88
73
|
@activate( nextIndex )
|
89
74
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
75
|
+
# Find a direct component on this card by its name.
|
76
|
+
find: (name)->
|
77
|
+
_( @components ).detect (c)->
|
78
|
+
c.name is name
|
94
79
|
|
80
|
+
# Activates the component at the specified index. You may optionally specify
|
81
|
+
# the name of the component you wish to activate. You can pass false as your second
|
82
|
+
# argument, to disable the event handling that occurs when you activate a card on this container.
|
83
|
+
# If you pass a callback function to the activate method, that callback will be executed within
|
84
|
+
# the context of the activated component.
|
95
85
|
activate: (index, silent=false, callback)->
|
96
86
|
if _.isFunction(silent)
|
97
87
|
silent = false
|
@@ -100,14 +90,12 @@ component.defaults
|
|
100
90
|
return if index is @activeCard
|
101
91
|
|
102
92
|
previous = @activeComponent()
|
103
|
-
current = @getComponent(index)
|
104
93
|
|
105
|
-
|
106
|
-
index = @indexOf(index)
|
107
|
-
current = @getComponent( index )
|
94
|
+
current = @getComponent(index)
|
108
95
|
|
109
|
-
|
110
|
-
|
96
|
+
if !current?
|
97
|
+
index = @indexOf(index)
|
98
|
+
return unless current = @getComponent(index)
|
111
99
|
|
112
100
|
unless silent is true
|
113
101
|
@trigger "before:card:switch", previous, current
|
@@ -120,10 +108,15 @@ component.defaults
|
|
120
108
|
@componentElements().hide()
|
121
109
|
|
122
110
|
unless current.previously_activated is true
|
123
|
-
current.
|
111
|
+
if current.rendered is true
|
112
|
+
current.trigger "first:activation"
|
113
|
+
else
|
114
|
+
current.once "after:render", ()->
|
115
|
+
current.rendered = true
|
116
|
+
current.trigger("first:activation")
|
124
117
|
current.previously_activated = true
|
125
118
|
|
126
|
-
@activeCard = index
|
119
|
+
@activeCard = index
|
127
120
|
@activeComponentElement().show()
|
128
121
|
|
129
122
|
unless silent is true
|
@@ -139,5 +132,47 @@ component.defaults
|
|
139
132
|
if _.isFunction(callback)
|
140
133
|
callback.apply activationContext, [@,previous,current]
|
141
134
|
|
135
|
+
component.privateMethods
|
136
|
+
initialize: (@options)->
|
137
|
+
@components ||= @pages ||= @cards
|
138
|
+
Luca.Container::initialize.apply @,arguments
|
139
|
+
@setupHooks(@hooks)
|
140
|
+
@defer( @simulateActivationEvent, @ ).until("after:render")
|
141
|
+
|
142
|
+
# Simulates the activation event being triggered on the
|
143
|
+
# active component that gets rendered inside of this card view.
|
144
|
+
simulateActivationEvent: ()->
|
145
|
+
c = @activeComponent()
|
146
|
+
|
147
|
+
if c? and (@visible || @$el.is(":visible"))
|
148
|
+
c?.trigger "activation", @, c, c
|
149
|
+
if !c.previously_activated
|
150
|
+
c.trigger "first:activation"
|
151
|
+
c.previously_activated = true
|
152
|
+
|
153
|
+
prepareComponents: ()->
|
154
|
+
Luca.Container::prepareComponents?.apply(@, arguments)
|
155
|
+
@componentElements().hide()
|
156
|
+
@activeComponentElement().show()
|
157
|
+
|
158
|
+
activeComponentElement: ()->
|
159
|
+
@componentElements().eq( @activeCard )
|
160
|
+
|
161
|
+
activeComponent: ()->
|
162
|
+
@getComponent( @activeCard )
|
163
|
+
|
164
|
+
customizeContainerEl: (containerEl, panel, panelIndex)->
|
165
|
+
containerEl.style += if panelIndex is @activeCard then "display:block;" else "display:none;"
|
166
|
+
|
167
|
+
containerEl
|
168
|
+
|
169
|
+
|
170
|
+
|
171
|
+
# The first time activate event is triggered on this component
|
172
|
+
# the @firstActivation hook is responsible for relaying that event
|
173
|
+
# to our @activeComponent() so that it knows it has been activated.
|
174
|
+
firstActivation: ()->
|
175
|
+
if activeComponent = @activeComponent()
|
176
|
+
activeComponent.trigger "first:activation", @, @activeComponent()
|
142
177
|
|
143
|
-
|
178
|
+
component.register()
|
@@ -1,3 +1,148 @@
|
|
1
|
+
# The Luca.Container is the heart and soul of the Luca framework
|
2
|
+
# and the component driven design philosophy. The central idea
|
3
|
+
# is that every component should be designed as an isolated unit
|
4
|
+
# which completely encapsulates its features. It should not know about
|
5
|
+
# other components outside of it.
|
6
|
+
#
|
7
|
+
# It is the responsibility of a `Luca.Container` to define its
|
8
|
+
# child `@components`, render them, and broker communication between them
|
9
|
+
# in response to events which occur in the user interface.
|
10
|
+
#
|
11
|
+
# A common use case for this would be a page which has a filter form, and
|
12
|
+
# a grid of search results. The fields in the filter form are used to
|
13
|
+
# filter the table. Neither the form or the table know about each other,
|
14
|
+
# since both can be used in other contexts. A `Luca.Container` would be used
|
15
|
+
# to relay events from the form to the table, and in doing so create a higher
|
16
|
+
# level component which can be extended and re-used.
|
17
|
+
#
|
18
|
+
# #### Using a container to combine a Filter View and Results Table
|
19
|
+
#
|
20
|
+
# form = Luca.register "App.views.FilterForm"
|
21
|
+
# form.extends "Luca.components.FormView"
|
22
|
+
#
|
23
|
+
# form.contains
|
24
|
+
# type: "text"
|
25
|
+
# label: "Filter by"
|
26
|
+
# name: "filter_text"
|
27
|
+
# ,
|
28
|
+
# type: "button"
|
29
|
+
# className: "filter"
|
30
|
+
# value: "Filter"
|
31
|
+
#
|
32
|
+
#
|
33
|
+
# form.defines
|
34
|
+
# toolbar: false
|
35
|
+
#
|
36
|
+
# Elsewhere, we have a table that lists records in a collection:
|
37
|
+
#
|
38
|
+
# table = Luca.register "App.views.ResultsTable"
|
39
|
+
# table.extends "Luca.components.TableView"
|
40
|
+
# table.defines
|
41
|
+
# striped: true
|
42
|
+
# collection: "components"
|
43
|
+
# columns:[
|
44
|
+
# header: "Component Class"
|
45
|
+
# reader: "class_name"
|
46
|
+
# ,
|
47
|
+
# header: "Component Type Alias"
|
48
|
+
# reader: "type_alias"
|
49
|
+
# ]
|
50
|
+
#
|
51
|
+
# We can join these two components together by declaring their relationship
|
52
|
+
# in a `Luca.Container`. Remember the components we defined above are just
|
53
|
+
# prototypes. We can override specific instance configuration and properties
|
54
|
+
# in our container.
|
55
|
+
#
|
56
|
+
# #### Container Example
|
57
|
+
#
|
58
|
+
# container = Luca.register "App.views.ComponentFinder"
|
59
|
+
# container.extends "Luca.Container"
|
60
|
+
#
|
61
|
+
# # This is the same as defining a components property on the component.
|
62
|
+
# # The type alias is derived from the name of the component. It is
|
63
|
+
# # a short hand way of referencing a component you might reuse a lot.
|
64
|
+
# container.contains
|
65
|
+
# type: "filter_form"
|
66
|
+
# role: "filter"
|
67
|
+
# ,
|
68
|
+
# type: "results_table"
|
69
|
+
# # change the prototype's default
|
70
|
+
# striped: false
|
71
|
+
# role: "results"
|
72
|
+
# filterable: true
|
73
|
+
#
|
74
|
+
# # A Container will generally define some component event bindings
|
75
|
+
# # and handler methods to handle the communication between its sub
|
76
|
+
# # components. By default a container is able to access events
|
77
|
+
# # from all of its descendants in the hierarchy.
|
78
|
+
# container.defines
|
79
|
+
# # These will be applied to each of our components.
|
80
|
+
# defaults:
|
81
|
+
# attributes:
|
82
|
+
# "data-attribute": "whatever"
|
83
|
+
#
|
84
|
+
# componentEvents:
|
85
|
+
# # Any time any of our child components emit
|
86
|
+
# # the on:change event, pass it to the filterTable method
|
87
|
+
# "* on:change" : "filterTable"
|
88
|
+
#
|
89
|
+
# # Communicates between the filter and the table's
|
90
|
+
# # underlying collection. NOtice the use of the @role
|
91
|
+
# # property. It automatically creates getter helpers for us.
|
92
|
+
# filterTable: ()->
|
93
|
+
# filter = @getFilter()
|
94
|
+
# results = @getResults()
|
95
|
+
# # filter.getValues() is a hash of each field and its value
|
96
|
+
# results.applyFilter( filter.getValues() )
|
97
|
+
#
|
98
|
+
# ### DOM Layout Configuration
|
99
|
+
#
|
100
|
+
# Another responsibility of the container is to structurally layout its
|
101
|
+
# child components in the DOM. There are a number of different
|
102
|
+
# options available depending on how you need to do this. By default,
|
103
|
+
# a `Luca.Container` will simply append the @$el of all of its views
|
104
|
+
# to its own.
|
105
|
+
#
|
106
|
+
# The `Luca.components.Controller` is a container which hides every page
|
107
|
+
# but the active page. Similarly, there is the `Luca.containers.TabView`
|
108
|
+
# which does the same thing, but renders a tab selector menu for you. You
|
109
|
+
# can create any type of interface you want using containers.
|
110
|
+
#
|
111
|
+
# To make this easy for you, you can do a few different things:
|
112
|
+
#
|
113
|
+
# #### Use the Twitter Bootstrap Fluid Grid
|
114
|
+
#
|
115
|
+
# container = Luca.register "App.views.ColumnLayout"
|
116
|
+
# container.extends "App.views.ComponentFinder"
|
117
|
+
#
|
118
|
+
# container.contains
|
119
|
+
# span: 4
|
120
|
+
# type: "filter_form"
|
121
|
+
# role: "filter"
|
122
|
+
# ,
|
123
|
+
# span: 8
|
124
|
+
# type: "results_table"
|
125
|
+
# role: "results"
|
126
|
+
#
|
127
|
+
# container.defines
|
128
|
+
# rowFluid: true
|
129
|
+
#
|
130
|
+
# #### Using a layout template with CSS Selectors
|
131
|
+
# If you find yourself needing a container view with a complicated
|
132
|
+
# visual layout, you can provide your own DOM template as a `@bodyTemplate`
|
133
|
+
# and assign each child view in `@components` to its own specific CSS selector.
|
134
|
+
#
|
135
|
+
# ...
|
136
|
+
# container.contains
|
137
|
+
# role: "filter"
|
138
|
+
# container: "#filter-wrapper-dom-selector"
|
139
|
+
# ,
|
140
|
+
# role: "results"
|
141
|
+
# container: "#results-wrapper-dom-selector"
|
142
|
+
# ...
|
143
|
+
# container.defines
|
144
|
+
# # assumes the template will provide the CSS selectors used above
|
145
|
+
# bodyTemplate: "layouts/custom_template"
|
1
146
|
container = Luca.register "Luca.Container"
|
2
147
|
|
3
148
|
container.extends "Luca.Panel"
|
@@ -11,36 +156,95 @@ container.triggers "before:components",
|
|
11
156
|
|
12
157
|
container.replaces "Luca.Container"
|
13
158
|
|
14
|
-
container.
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
159
|
+
container.publicConfiguration
|
160
|
+
# @components should contain a list of object configurations for child view(s)
|
161
|
+
# of this container. The values specified in the configuration object will override the
|
162
|
+
# values defined as properties and methods on your view prototypes.
|
163
|
+
#
|
164
|
+
# There are special properties you can define in your components configuration items
|
165
|
+
# that will effect the container:
|
166
|
+
#
|
167
|
+
# - role: will create a camelized getter for you on the container. e.g. when role is `my_custom_role`,
|
168
|
+
# the container will have a method `getMyCustomRole()` that returns that child view.
|
169
|
+
#
|
170
|
+
# - name: a name for the child view. this allows you to access the component by name using
|
171
|
+
# the find() method on the container.
|
172
|
+
#
|
173
|
+
# - type: a type alias from the component registry. type alias are underscore'd strings
|
174
|
+
# matching the component class name. e.g. App.views.MyCustomView type alias is `my_custom_view`
|
175
|
+
#
|
176
|
+
# - component: a convenience property for setting type, role, and name to be equal.
|
177
|
+
components:[]
|
22
178
|
|
23
|
-
|
179
|
+
# The `@defaults` property is an object of configuration parameters which will be set
|
180
|
+
# on each child component. Values explicitly defines in the components config will
|
181
|
+
# take precedence over the default.
|
182
|
+
defaults: {}
|
24
183
|
|
25
|
-
|
184
|
+
# The `@extensions` property is useful when you are subclassing a container view
|
185
|
+
# which already defines an array of components, and you want to specifically override
|
186
|
+
# properties and settings on the children. The `@extensions` property expects either:
|
187
|
+
#
|
188
|
+
# An object whose keys match the names of the `@role` property defined on the child components.
|
189
|
+
# The value should be an object which will override any values defined on the parent class.
|
190
|
+
#
|
191
|
+
# or:
|
192
|
+
#
|
193
|
+
# An array of objects in the same array position / index as the target child view you wish to extend.
|
194
|
+
extensions: {}
|
26
195
|
|
27
196
|
# @componentEvents provides declarative syntax for responding to events on
|
28
197
|
# the components in this container. the format of the syntax is very similar
|
29
198
|
# to the other event binding helpers:
|
30
199
|
#
|
31
|
-
#
|
32
|
-
#
|
33
|
-
# where component_accessor is either the name of the role, or a method on the container
|
34
|
-
# which will find the component in question.
|
35
|
-
#
|
36
|
-
# myContainer = new Luca.Container
|
37
|
-
# componentEvents:
|
38
|
-
# "name component:trigger" : "handler"
|
39
|
-
# "role component:trigger" : "handler"
|
40
|
-
# "getter component:trigger" : "handler"
|
200
|
+
# `component_accessor component:trigger`
|
41
201
|
#
|
202
|
+
# where component_accessor is either the name of the component, or a the role
|
203
|
+
# property on the component, component:trigger is the event that component fires.
|
204
|
+
# handler is a method on the container which will respond to the child component event.
|
205
|
+
# <pre>
|
206
|
+
# myContainer = new Luca.Container
|
207
|
+
# componentEvents:
|
208
|
+
# "name component:trigger" : "handler"
|
209
|
+
# "role component:trigger" : "handler"
|
210
|
+
# "getter component:trigger" : "handler"
|
211
|
+
# components:[
|
212
|
+
# name: "name"
|
213
|
+
# ]
|
214
|
+
# </pre>
|
42
215
|
componentEvents: {}
|
43
216
|
|
217
|
+
container.privateConfiguration
|
218
|
+
className: 'luca-ui-container'
|
219
|
+
|
220
|
+
# This is a convenience attribute for identifying
|
221
|
+
# views which are luca containers
|
222
|
+
isContainer: true
|
223
|
+
|
224
|
+
# if set to true, we will generate DOM elements
|
225
|
+
# to wrap each of our components in. This should
|
226
|
+
# generally be avoided IMO as it pollutes the DOM,
|
227
|
+
# but is currently necessary for some container implementations
|
228
|
+
generateComponentElements: false
|
229
|
+
|
230
|
+
# if set to true, the DOM elements which wrap
|
231
|
+
# our components will be emptied prior to rendering
|
232
|
+
# the component inside this container.
|
233
|
+
emptyContainerElements: false
|
234
|
+
|
235
|
+
# if @generateComponentElements is true, which tag should this
|
236
|
+
# container wrap our components in?
|
237
|
+
componentTag: 'div'
|
238
|
+
|
239
|
+
# if @generateComponentElements is true, which class should we
|
240
|
+
# apply to the container elements which wrap our components?
|
241
|
+
componentClass: 'luca-ui-panel'
|
242
|
+
|
243
|
+
rendered: false
|
244
|
+
|
245
|
+
|
246
|
+
|
247
|
+
container.privateMethods
|
44
248
|
initialize: (@options={})->
|
45
249
|
_.extend @, @options
|
46
250
|
|
@@ -60,52 +264,12 @@ container.defines
|
|
60
264
|
|
61
265
|
Luca.View::initialize.apply @, arguments
|
62
266
|
|
63
|
-
#
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
# element by specifying a @container property on the component.
|
70
|
-
#
|
71
|
-
# Each component is instantiated by looking up its @ctype propery
|
72
|
-
# in the Luca Component Registry. Then the components are rendered
|
73
|
-
# by having their @render() method called on them.
|
74
|
-
#
|
75
|
-
# Any class which extends Luca.View will have its defined render method
|
76
|
-
# wrapped in a method which triggers "before:render", and "after:render"
|
77
|
-
# before and after the defined render method.
|
78
|
-
#
|
79
|
-
# so you can expect the following, for any container or nested container
|
80
|
-
#
|
81
|
-
# DOM Element Manipulation:
|
82
|
-
#
|
83
|
-
# beforeRender()
|
84
|
-
# beforeLayout()
|
85
|
-
# prepareLayout()
|
86
|
-
# afterLayout()
|
87
|
-
#
|
88
|
-
# Luca / Backbone Component Manipulation
|
89
|
-
#
|
90
|
-
# beforeComponents()
|
91
|
-
# prepareComponents()
|
92
|
-
# createComponents()
|
93
|
-
# beforeRenderComponents()
|
94
|
-
# renderComponents() ->
|
95
|
-
# calls render() on each component, starting this whole cycle
|
96
|
-
#
|
97
|
-
# afterComponents()
|
98
|
-
#
|
99
|
-
# DOM Injection
|
100
|
-
#
|
101
|
-
# render()
|
102
|
-
# afterRender()
|
103
|
-
#
|
104
|
-
# For Components which are originally hidden
|
105
|
-
# ( card view, tab view, etc )
|
106
|
-
#
|
107
|
-
# firstActivation()
|
108
|
-
#
|
267
|
+
# Removing a container will call remove on all of the nested components as well.
|
268
|
+
remove: ()->
|
269
|
+
Luca.View::remove.apply(@, arguments)
|
270
|
+
@eachComponent (component)->
|
271
|
+
component.remove?()
|
272
|
+
|
109
273
|
beforeRender: ()->
|
110
274
|
doLayout.call(@)
|
111
275
|
doComponents.call(@)
|
@@ -144,7 +308,6 @@ container.defines
|
|
144
308
|
prepareComponents: ()->
|
145
309
|
container = @
|
146
310
|
|
147
|
-
|
148
311
|
_( @components ).each (component, index)=>
|
149
312
|
ce = componentContainerElement = @componentContainers?[index]
|
150
313
|
|
@@ -205,8 +368,17 @@ container.defines
|
|
205
368
|
component = if Luca.isComponent( object )
|
206
369
|
object
|
207
370
|
else
|
371
|
+
# if a component is tagged with a @component property
|
372
|
+
# we assume this is the kind of singleton component
|
373
|
+
# and set the type, role and name to the same value (if they're blank)
|
374
|
+
if object.component? and not (object.type || object.ctype)
|
375
|
+
object.type = object.component
|
376
|
+
object.name ||= object.component
|
377
|
+
object.role ||= object.component
|
378
|
+
|
208
379
|
object.type ||= object.ctype
|
209
380
|
|
381
|
+
# guess the type based on the properties
|
210
382
|
if !object.type?
|
211
383
|
# TODO
|
212
384
|
# Add support for all of the various components property aliases
|
@@ -238,8 +410,7 @@ container.defines
|
|
238
410
|
|
239
411
|
map
|
240
412
|
|
241
|
-
# Trigger the Rendering Pipeline process on all of the nested
|
242
|
-
# components
|
413
|
+
# Trigger the Rendering Pipeline process on all of the nested components
|
243
414
|
renderComponents: (@debugMode="")->
|
244
415
|
@debug "container render components"
|
245
416
|
|
@@ -260,10 +431,14 @@ container.defines
|
|
260
431
|
# so look into wtf is going on and which components are problematic
|
261
432
|
containerElement = @$( component.container ).eq(0) if containerElement.length is 0
|
262
433
|
|
434
|
+
if @emptyContainerElements is true
|
435
|
+
containerElement.empty()
|
436
|
+
|
263
437
|
containerElement.append( component.el )
|
264
438
|
|
265
439
|
component.trigger "after:attach"
|
266
440
|
component.render()
|
441
|
+
component.rendered = true
|
267
442
|
catch e
|
268
443
|
console.log "Error Rendering Component #{ component.name || component.cid }", component
|
269
444
|
|
@@ -273,8 +448,6 @@ container.defines
|
|
273
448
|
|
274
449
|
throw e unless Luca.silenceRenderErrors? is true
|
275
450
|
|
276
|
-
#### Container Activation
|
277
|
-
#
|
278
451
|
# When a container is first activated is a good time to perform
|
279
452
|
# operations which are not needed unless that component becomes
|
280
453
|
# visible. This first activation event should be relayed to all
|
@@ -291,28 +464,7 @@ container.defines
|
|
291
464
|
component?.trigger?.call component, "first:activation", component, activator
|
292
465
|
component.previously_activated = true
|
293
466
|
|
294
|
-
|
295
|
-
_: ()-> _( @components )
|
296
|
-
|
297
|
-
pluck: (attribute)->
|
298
|
-
@_().pluck(attribute)
|
299
|
-
|
300
|
-
invoke: (method)->
|
301
|
-
@_().invoke(method)
|
302
|
-
|
303
|
-
select: (fn)->
|
304
|
-
@_().select(fn)
|
305
|
-
|
306
|
-
detect: (fn)->
|
307
|
-
@_().detect(attribute)
|
308
|
-
|
309
|
-
reject: (fn)->
|
310
|
-
@_().reject(fn)
|
311
|
-
|
312
|
-
map: (fn)->
|
313
|
-
@_().map(fn)
|
314
|
-
|
315
|
-
registerComponentEvents: (eventList)->
|
467
|
+
registerComponentEvents: (eventList, direction="on")->
|
316
468
|
container = @
|
317
469
|
|
318
470
|
for listener, handler of (eventList || @componentEvents||{})
|
@@ -331,31 +483,71 @@ container.defines
|
|
331
483
|
console.log "Error registering component event", listener, componentNameOrRole, eventId
|
332
484
|
throw "Invalid component event definition: #{ componentNameOrRole }"
|
333
485
|
|
334
|
-
component
|
486
|
+
component[direction](eventId, @[handler], container)
|
487
|
+
|
488
|
+
container.publicMethods
|
489
|
+
# Returns an underscore.js object that wraps the components array
|
490
|
+
_: ()-> _( @components )
|
491
|
+
|
492
|
+
# Return the value of attribute of each component
|
493
|
+
pluck: (attribute)->
|
494
|
+
@_().pluck(attribute)
|
495
|
+
|
496
|
+
# Invoke the passed method name on each component
|
497
|
+
invoke: (method)->
|
498
|
+
@_().invoke(method)
|
499
|
+
|
500
|
+
# Select any component for which the passed iterator returns true
|
501
|
+
select: (iterator)->
|
502
|
+
@_().select(iterator)
|
335
503
|
|
504
|
+
# Find the first matching component for which the passed iterator returns true
|
505
|
+
detect: (iterator)->
|
506
|
+
@_().detect(iterator)
|
336
507
|
|
508
|
+
# Return a list of components without the components for which the passed iterator returns true
|
509
|
+
reject: (iterator)->
|
510
|
+
@_().reject(iterator)
|
511
|
+
|
512
|
+
# Run the passed iterator over each component and return the result in an array
|
513
|
+
map: (fn)->
|
514
|
+
@_().map(fn)
|
515
|
+
|
516
|
+
# Returns a list of nested components which are also containers
|
337
517
|
subContainers: ()->
|
338
518
|
@select (component)->
|
339
519
|
component.isContainer is true
|
340
520
|
|
341
521
|
roles: ()->
|
342
|
-
_( @allChildren() ).pluck('role')
|
522
|
+
_( @allChildren() ).chain().pluck('role').compact().value()
|
343
523
|
|
344
524
|
allChildren: ()->
|
345
525
|
children = @components
|
346
|
-
|
526
|
+
|
527
|
+
grandchildren = _( @subContainers() ).map (component)->
|
528
|
+
component?.allChildren?()
|
529
|
+
|
347
530
|
_([children,grandchildren]).chain().compact().flatten().value()
|
348
531
|
|
532
|
+
# Find a direct component on this card by its name.
|
533
|
+
find: (name)->
|
534
|
+
_( @components ).detect (c)->
|
535
|
+
c.name is name
|
536
|
+
|
349
537
|
findComponentForEventBinding: (nameRoleOrGetter, deep=true)->
|
350
538
|
@findComponentByName(nameRoleOrGetter, deep) || @findComponentByGetter( nameRoleOrGetter, deep ) || @findComponentByRole( nameRoleOrGetter, deep )
|
351
539
|
|
352
540
|
findComponentByGetter: (getter, deep=false)->
|
353
541
|
_( @allChildren() ).detect (component)->
|
354
|
-
component
|
542
|
+
component?.getter is getter
|
355
543
|
|
356
544
|
findComponentByRole: (role,deep=false)->
|
357
545
|
_( @allChildren() ).detect (component)->
|
358
|
-
component
|
546
|
+
component?.role is role or component?.type is role or component?.ctype is role
|
547
|
+
|
548
|
+
findComponentByType: (desired,deep=false)->
|
549
|
+
_( @allChildren() ).detect (component)->
|
550
|
+
desired is (component.type || component.ctype)
|
359
551
|
|
360
552
|
findComponentByName: (name, deep=false)->
|
361
553
|
_( @allChildren() ).detect (component)->
|
@@ -389,10 +581,17 @@ container.defines
|
|
389
581
|
fn.call component, component, index
|
390
582
|
component?.eachComponent?.apply component, [fn,deep] if deep
|
391
583
|
|
392
|
-
|
584
|
+
indexOfComponentName: (name)->
|
393
585
|
names = _( @components ).pluck('name')
|
394
586
|
_( names ).indexOf(name)
|
395
587
|
|
588
|
+
indexOf: (nameOrComponent)->
|
589
|
+
if _.isString(nameOrComponent)
|
590
|
+
return @indexOfComponentName(nameOrComponent)
|
591
|
+
|
592
|
+
if _.isObject(nameOrComponent)
|
593
|
+
_( @components ).indexOf( nameOrComponent )
|
594
|
+
|
396
595
|
activeComponent: ()->
|
397
596
|
return @ unless @activeItem
|
398
597
|
return @components[ @activeItem ]
|
@@ -425,6 +624,8 @@ container.defines
|
|
425
624
|
_.flatten( components )
|
426
625
|
|
427
626
|
|
627
|
+
container.register()
|
628
|
+
|
428
629
|
# This is the method by which a container injects the rendered child views
|
429
630
|
# into the DOM. It will get passed the container object, and the component
|
430
631
|
# that is being rendered.
|
@@ -464,22 +665,21 @@ createGetterMethods = ()->
|
|
464
665
|
container = @
|
465
666
|
|
466
667
|
childrenWithGetter = _( @allChildren() ).select (component)->
|
467
|
-
component
|
668
|
+
component?.getter?
|
468
669
|
|
469
670
|
_( childrenWithGetter ).each (component)->
|
470
|
-
container[ component.getter ] ||= ()->
|
471
|
-
component
|
671
|
+
container[ component.getter ] ||= ()-> component
|
472
672
|
|
473
673
|
createMethodsToGetComponentsByRole = ()->
|
474
674
|
container = @
|
475
675
|
|
476
676
|
childrenWithRole = _( @allChildren() ).select (component)->
|
477
|
-
component
|
677
|
+
component?.role?
|
478
678
|
|
479
679
|
_( childrenWithRole ).each (component)->
|
480
680
|
getter = _.str.camelize( "get_" + component.role )
|
481
|
-
|
482
|
-
|
681
|
+
getterFn = ()-> component
|
682
|
+
container[ getter ] ||= _.bind(getterFn, container)
|
483
683
|
|
484
684
|
doComponents = ()->
|
485
685
|
@trigger "before:components", @, @components
|
@@ -499,9 +699,6 @@ doComponents = ()->
|
|
499
699
|
validateContainerConfiguration = ()->
|
500
700
|
true
|
501
701
|
|
502
|
-
|
503
|
-
# Private Helpers
|
504
|
-
#
|
505
702
|
# indexComponent( component ).at( index ).in( componentsInternalIndexMap )
|
506
703
|
indexComponent = (component)->
|
507
704
|
at: (index)->
|