sproutit-sproutcore 1.0.0.20090407205609 → 1.0.0.20090408130025
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/frameworks/sproutcore/Buildfile +63 -0
- data/frameworks/sproutcore/HISTORY +682 -0
- data/frameworks/sproutcore/README +22 -0
- data/frameworks/sproutcore/apps/sc_jsdoc/controllers/docs.js +149 -0
- data/frameworks/sproutcore/apps/sc_jsdoc/core.js +16 -0
- data/frameworks/sproutcore/apps/sc_jsdoc/english.lproj/body.css +17 -0
- data/frameworks/sproutcore/apps/sc_jsdoc/english.lproj/body.js +99 -0
- data/frameworks/sproutcore/apps/sc_jsdoc/english.lproj/images/sproutcore-logo.png +0 -0
- data/frameworks/sproutcore/apps/sc_jsdoc/english.lproj/strings.js +15 -0
- data/frameworks/sproutcore/apps/sc_jsdoc/main.js +27 -0
- data/frameworks/sproutcore/apps/sc_jsdoc/models/doc.js +21 -0
- data/frameworks/sproutcore/apps/sc_qunit/controllers/runner.js +209 -0
- data/frameworks/sproutcore/apps/sc_qunit/core.js +16 -0
- data/frameworks/sproutcore/apps/sc_qunit/english.lproj/body.css +17 -0
- data/frameworks/sproutcore/apps/sc_qunit/english.lproj/body.js +107 -0
- data/frameworks/sproutcore/apps/sc_qunit/english.lproj/images/sproutcore-logo.png +0 -0
- data/frameworks/sproutcore/apps/sc_qunit/english.lproj/strings.js +15 -0
- data/frameworks/sproutcore/apps/sc_qunit/main.js +18 -0
- data/frameworks/sproutcore/apps/sc_qunit/models/test.js +24 -0
- data/frameworks/sproutcore/apps/sc_qunit/views/test_iframe.js +52 -0
- data/frameworks/sproutcore/apps/tests/controllers/targets.js +47 -0
- data/frameworks/sproutcore/apps/tests/controllers/test.js +20 -0
- data/frameworks/sproutcore/apps/tests/controllers/tests.js +38 -0
- data/frameworks/sproutcore/apps/tests/core.js +35 -0
- data/frameworks/sproutcore/apps/tests/english.lproj/loading.rhtml +9 -0
- data/frameworks/sproutcore/apps/tests/english.lproj/main_page.css +19 -0
- data/frameworks/sproutcore/apps/tests/english.lproj/main_page.js +86 -0
- data/frameworks/sproutcore/apps/tests/english.lproj/strings.js +17 -0
- data/frameworks/sproutcore/apps/tests/fixtures/target.js +43 -0
- data/frameworks/sproutcore/apps/tests/fixtures/test.js +43 -0
- data/frameworks/sproutcore/apps/tests/main.js +39 -0
- data/frameworks/sproutcore/apps/tests/models/target.js +49 -0
- data/frameworks/sproutcore/apps/tests/models/test.js +20 -0
- data/frameworks/sproutcore/apps/tests/tests/controllers/targets.js +15 -0
- data/frameworks/sproutcore/apps/tests/tests/controllers/test.js +15 -0
- data/frameworks/sproutcore/apps/tests/tests/controllers/tests.js +15 -0
- data/frameworks/sproutcore/apps/tests/tests/models/target.js +15 -0
- data/frameworks/sproutcore/apps/tests/tests/models/test.js +15 -0
- data/frameworks/sproutcore/apps/welcome/core.js +23 -0
- data/frameworks/sproutcore/apps/welcome/english.lproj/loading.rhtml +8 -0
- data/frameworks/sproutcore/apps/welcome/english.lproj/main_page.js +43 -0
- data/frameworks/sproutcore/apps/welcome/english.lproj/strings.js +15 -0
- data/frameworks/sproutcore/apps/welcome/main.js +36 -0
- data/frameworks/sproutcore/design/Design Charts.graffle +15819 -0
- data/frameworks/sproutcore/design/Record State Table.numbers +0 -0
- data/frameworks/sproutcore/frameworks/datastore/core.js +14 -0
- data/frameworks/sproutcore/frameworks/datastore/data_sources/cascade.js +113 -0
- data/frameworks/sproutcore/frameworks/datastore/data_sources/data_source.js +256 -0
- data/frameworks/sproutcore/frameworks/datastore/data_sources/fixtures.js +196 -0
- data/frameworks/sproutcore/frameworks/datastore/debug/json.js +71 -0
- data/frameworks/sproutcore/frameworks/datastore/debug/standard_setup.js +96 -0
- data/frameworks/sproutcore/frameworks/datastore/fixtures/author_fixtures.js +2503 -0
- data/frameworks/sproutcore/frameworks/datastore/fixtures/sample.js +17 -0
- data/frameworks/sproutcore/frameworks/datastore/models/fetched_attribute.js +92 -0
- data/frameworks/sproutcore/frameworks/datastore/models/many_attribute.js +38 -0
- data/frameworks/sproutcore/frameworks/datastore/models/record.js +430 -0
- data/frameworks/sproutcore/frameworks/datastore/models/record_attribute.js +361 -0
- data/frameworks/sproutcore/frameworks/datastore/system/nested_store.js +305 -0
- data/frameworks/sproutcore/frameworks/datastore/system/query.js +128 -0
- data/frameworks/sproutcore/frameworks/datastore/system/record_array.js +149 -0
- data/frameworks/sproutcore/frameworks/datastore/system/store.js +1689 -0
- data/frameworks/sproutcore/frameworks/datastore/tests/data_sources/fixtures.js +86 -0
- data/frameworks/sproutcore/frameworks/datastore/tests/integration/contact_model.js +114 -0
- data/frameworks/sproutcore/frameworks/datastore/tests/integration/mail_model.js +91 -0
- data/frameworks/sproutcore/frameworks/datastore/tests/integration/test_runner_model.js +56 -0
- data/frameworks/sproutcore/frameworks/datastore/tests/models/record/destroy.js +73 -0
- data/frameworks/sproutcore/frameworks/datastore/tests/models/record/readAttribute.js +48 -0
- data/frameworks/sproutcore/frameworks/datastore/tests/models/record/refresh.js +42 -0
- data/frameworks/sproutcore/frameworks/datastore/tests/models/record/storeDidChangeProperties.js +138 -0
- data/frameworks/sproutcore/frameworks/datastore/tests/models/record/unknownProperty.js +46 -0
- data/frameworks/sproutcore/frameworks/datastore/tests/models/record/writeAttribute.js +71 -0
- data/frameworks/sproutcore/frameworks/datastore/tests/models/record_attribute.js +115 -0
- data/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/chain.js +40 -0
- data/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/commitChanges.js +116 -0
- data/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/commitChangesFromNestedStore.js +135 -0
- data/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/dataHashDidChange.js +110 -0
- data/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/discardChanges.js +99 -0
- data/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/readDataHash.js +180 -0
- data/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/readEditableDataHash.js +126 -0
- data/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/removeDataHash.js +163 -0
- data/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/writeDataHash.js +166 -0
- data/frameworks/sproutcore/frameworks/datastore/tests/system/record_array/core_methods.js +175 -0
- data/frameworks/sproutcore/frameworks/datastore/tests/system/store/cancelRecord.js +54 -0
- data/frameworks/sproutcore/frameworks/datastore/tests/system/store/commitChangesFromNestedStore.js +126 -0
- data/frameworks/sproutcore/frameworks/datastore/tests/system/store/commitRecord.js +127 -0
- data/frameworks/sproutcore/frameworks/datastore/tests/system/store/createRecord.js +57 -0
- data/frameworks/sproutcore/frameworks/datastore/tests/system/store/dataHashDidChange.js +78 -0
- data/frameworks/sproutcore/frameworks/datastore/tests/system/store/dataSourceCallbacks.js +247 -0
- data/frameworks/sproutcore/frameworks/datastore/tests/system/store/destroyRecord.js +106 -0
- data/frameworks/sproutcore/frameworks/datastore/tests/system/store/init.js +21 -0
- data/frameworks/sproutcore/frameworks/datastore/tests/system/store/pushChanges.js +61 -0
- data/frameworks/sproutcore/frameworks/datastore/tests/system/store/readDataHash.js +74 -0
- data/frameworks/sproutcore/frameworks/datastore/tests/system/store/readEditableDataHash.js +74 -0
- data/frameworks/sproutcore/frameworks/datastore/tests/system/store/recordDidChange.js +74 -0
- data/frameworks/sproutcore/frameworks/datastore/tests/system/store/removeDataHash.js +144 -0
- data/frameworks/sproutcore/frameworks/datastore/tests/system/store/retrieveRecord.js +137 -0
- data/frameworks/sproutcore/frameworks/datastore/tests/system/store/writeDataHash.js +130 -0
- data/frameworks/sproutcore/frameworks/debug/core.js +1 -0
- data/frameworks/sproutcore/frameworks/deprecated/core.js +61 -0
- data/frameworks/sproutcore/frameworks/deprecated/lib/button_views.rb +330 -0
- data/frameworks/sproutcore/frameworks/deprecated/lib/collection_view.rb +83 -0
- data/frameworks/sproutcore/frameworks/deprecated/lib/core_views.rb +326 -0
- data/frameworks/sproutcore/frameworks/deprecated/lib/form_views.rb +253 -0
- data/frameworks/sproutcore/frameworks/deprecated/lib/index.rhtml +75 -0
- data/frameworks/sproutcore/frameworks/deprecated/lib/menu_views.rb +93 -0
- data/frameworks/sproutcore/frameworks/deprecated/server/rails_server.js +80 -0
- data/frameworks/sproutcore/frameworks/deprecated/server/rest_server.js +178 -0
- data/frameworks/sproutcore/frameworks/deprecated/server/server.js +674 -0
- data/frameworks/sproutcore/frameworks/deprecated/system/animator.js +679 -0
- data/frameworks/sproutcore/frameworks/deprecated/system/binding.js +36 -0
- data/frameworks/sproutcore/frameworks/deprecated/system/browser.js +77 -0
- data/frameworks/sproutcore/frameworks/deprecated/system/classic_responder.js +314 -0
- data/frameworks/sproutcore/frameworks/deprecated/system/event.js +60 -0
- data/frameworks/sproutcore/frameworks/deprecated/system/globals.js +20 -0
- data/frameworks/sproutcore/frameworks/deprecated/system/misc.js +60 -0
- data/frameworks/sproutcore/frameworks/deprecated/system/node_descriptor.js +72 -0
- data/frameworks/sproutcore/frameworks/deprecated/system/object.js +124 -0
- data/frameworks/sproutcore/frameworks/deprecated/system/path_module.js +433 -0
- data/frameworks/sproutcore/frameworks/deprecated/system/string.js +109 -0
- data/frameworks/sproutcore/frameworks/deprecated/tests/application/application.rhtml +125 -0
- data/frameworks/sproutcore/frameworks/deprecated/tests/views/classic_view/clippingFrame.rhtml +401 -0
- data/frameworks/sproutcore/frameworks/deprecated/tests/views/classic_view/frame.rhtml +357 -0
- data/frameworks/sproutcore/frameworks/deprecated/tests/views/classic_view/isVisibleInWindow.rhtml +147 -0
- data/frameworks/sproutcore/frameworks/deprecated/tests/views/collection/base.rhtml +298 -0
- data/frameworks/sproutcore/frameworks/deprecated/tests/views/collection/incremental_rendering.rhtml +260 -0
- data/frameworks/sproutcore/frameworks/deprecated/tests/views/collection/source_list_rendering.rhtml +143 -0
- data/frameworks/sproutcore/frameworks/deprecated/tests/views/popup_button.rhtml +128 -0
- data/frameworks/sproutcore/frameworks/deprecated/tests/views/text_field.rhtml +37 -0
- data/frameworks/sproutcore/frameworks/deprecated/views/collection.js +24 -0
- data/frameworks/sproutcore/frameworks/designer/coders/design.js +30 -0
- data/frameworks/sproutcore/frameworks/designer/coders/localization.js +28 -0
- data/frameworks/sproutcore/frameworks/designer/coders/object.js +347 -0
- data/frameworks/sproutcore/frameworks/designer/controllers/page_design.js +102 -0
- data/frameworks/sproutcore/frameworks/designer/css/css_rule.js +22 -0
- data/frameworks/sproutcore/frameworks/designer/css/css_style.js +29 -0
- data/frameworks/sproutcore/frameworks/designer/css/css_style_sheet.js +201 -0
- data/frameworks/sproutcore/frameworks/designer/ext/page.js +88 -0
- data/frameworks/sproutcore/frameworks/designer/ext/view.js +40 -0
- data/frameworks/sproutcore/frameworks/designer/views/controls/button.js +18 -0
- data/frameworks/sproutcore/frameworks/designer/views/designer.js +553 -0
- data/frameworks/sproutcore/frameworks/designer/views/label.js +17 -0
- data/frameworks/sproutcore/frameworks/designer/views/mixins/button.js +13 -0
- data/frameworks/sproutcore/frameworks/designer/views/tab.js +17 -0
- data/frameworks/sproutcore/frameworks/desktop/core.js +6 -0
- data/frameworks/sproutcore/frameworks/desktop/debug/drag.js +41 -0
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/alert.css +56 -0
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/debug/a_sample_image.jpg +0 -0
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/debug/apple-logo1.jpeg +0 -0
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/debug/iframe.html +23 -0
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/disclosure.css +71 -0
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/icons.css +943 -0
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/images/blank.gif +0 -0
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/images/icons/mini_222222.png +0 -0
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/images/icons/mini_454545.png +0 -0
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/images/icons/mini_888888.png +0 -0
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/images/icons/mini_ffffff.png +0 -0
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/images/icons/shared.png +0 -0
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/images/indicator.gif +0 -0
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/images/panels/sprite-x.png +0 -0
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/images/panels/sprite-y.png +0 -0
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/images/sc-theme-sprite.png +0 -0
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/images/standard_fade/000000.png +0 -0
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/images/standard_fade/ffffff.png +0 -0
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/images/sticky-note.png +0 -0
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/list_item.css +156 -0
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/menu.css +83 -0
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/menu_item_view.css +99 -0
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/palette.css +3 -0
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/panel.css +94 -0
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/picker.css +39 -0
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/progress.css +31 -0
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/radio.css +10 -0
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/scroller.css +26 -0
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/segmented.css +141 -0
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/separator.css +19 -0
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/slider.css +57 -0
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/split.css +70 -0
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/split_divider.css +8 -0
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/strings.js +14 -0
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/tab.css +12 -0
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/text_field.css +29 -0
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/toolbar.css +6 -0
- data/frameworks/sproutcore/frameworks/desktop/mixins/border.js +53 -0
- data/frameworks/sproutcore/frameworks/desktop/mixins/collection_group.js +22 -0
- data/frameworks/sproutcore/frameworks/desktop/mixins/collection_item.js +22 -0
- data/frameworks/sproutcore/frameworks/desktop/mixins/collection_view_delegate.js +226 -0
- data/frameworks/sproutcore/frameworks/desktop/mixins/scrollable.js +247 -0
- data/frameworks/sproutcore/frameworks/desktop/panes/alert.js +377 -0
- data/frameworks/sproutcore/frameworks/desktop/panes/menu.js +504 -0
- data/frameworks/sproutcore/frameworks/desktop/panes/modal.js +68 -0
- data/frameworks/sproutcore/frameworks/desktop/panes/palette.js +63 -0
- data/frameworks/sproutcore/frameworks/desktop/panes/panel.js +184 -0
- data/frameworks/sproutcore/frameworks/desktop/panes/picker.js +402 -0
- data/frameworks/sproutcore/frameworks/desktop/panes/sheet.js +46 -0
- data/frameworks/sproutcore/frameworks/desktop/protocols/drag_data_source.js +39 -0
- data/frameworks/sproutcore/frameworks/desktop/protocols/drag_source.js +81 -0
- data/frameworks/sproutcore/frameworks/desktop/protocols/drop_target.js +175 -0
- data/frameworks/sproutcore/frameworks/desktop/protocols/responder.js +280 -0
- data/frameworks/sproutcore/frameworks/desktop/system/drag.js +721 -0
- data/frameworks/sproutcore/frameworks/desktop/system/key_bindings.js +40 -0
- data/frameworks/sproutcore/frameworks/desktop/system/root_responder.js +641 -0
- data/frameworks/sproutcore/frameworks/desktop/system/undo_manager.js +187 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/integration/dialog.js +43 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/panes/alert/methods.js +10 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/panes/alert/ui.js +152 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/panes/menu/methods.js +10 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/panes/menu/ui.js +57 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/panes/palette/methods.js +10 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/panes/palette/ui.js +36 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/panes/panel/methods.js +10 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/panes/panel/ui.js +40 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/panes/picker/methods.js +10 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/panes/picker/ui.js +80 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/panes/sheet/methods.js +10 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/panes/sheet/ui.js +38 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/views/button/methods.js +45 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/views/button/ui.js +140 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/views/checkbox/methods.js +145 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/views/checkbox/ui.js +99 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/views/collection/methods.js +10 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/views/collection/selectPreviousItem.js +39 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/views/disclosure/methods.js +10 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/views/disclosure/ui.js +64 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/views/grid/methods.js +10 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/views/grid/ui.js +10 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/views/list/methods.js +10 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/views/list/ui.js +110 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/views/list_item.js +255 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/views/menu_item/methods.js +10 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/views/menu_item/ui.js +44 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/views/progress/methods.js +128 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/views/progress/ui.js +240 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/views/radio/methods.js +113 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/views/radio/ui.js +202 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/views/scroll/methods.js +139 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/views/scroll/ui.js +111 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/views/scroller/methods.js +63 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/views/scroller/ui.js +70 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/views/segmented/methods.js +94 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/views/segmented/ui.js +206 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/views/select_field/methods.js +81 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/views/select_field/ui.js +85 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/views/separator.js +37 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/views/source_list/methods.js +10 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/views/source_list/ui.js +10 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/views/split/methods.js +50 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/views/split/ui.js +52 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/views/tab/methods.js +54 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/views/tab/ui.js +88 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/views/text_field/methods.js +76 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/views/text_field/ui.js +198 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/views/web/methods.js +10 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/views/web/ui.js +110 -0
- data/frameworks/sproutcore/frameworks/desktop/views/button.js +320 -0
- data/frameworks/sproutcore/frameworks/desktop/views/checkbox.js +98 -0
- data/frameworks/sproutcore/frameworks/desktop/views/collection.js +2141 -0
- data/frameworks/sproutcore/frameworks/desktop/views/disclosure.js +44 -0
- data/frameworks/sproutcore/frameworks/desktop/views/form.js +595 -0
- data/frameworks/sproutcore/frameworks/desktop/views/grid.js +199 -0
- data/frameworks/sproutcore/frameworks/desktop/views/list.js +706 -0
- data/frameworks/sproutcore/frameworks/desktop/views/list_item.js +523 -0
- data/frameworks/sproutcore/frameworks/desktop/views/menu_item.js +437 -0
- data/frameworks/sproutcore/frameworks/desktop/views/popup_button.js +62 -0
- data/frameworks/sproutcore/frameworks/desktop/views/progress.js +207 -0
- data/frameworks/sproutcore/frameworks/desktop/views/radio.js +332 -0
- data/frameworks/sproutcore/frameworks/desktop/views/scene.js +56 -0
- data/frameworks/sproutcore/frameworks/desktop/views/scroll.js +648 -0
- data/frameworks/sproutcore/frameworks/desktop/views/scroller.js +203 -0
- data/frameworks/sproutcore/frameworks/desktop/views/segmented.js +509 -0
- data/frameworks/sproutcore/frameworks/desktop/views/select_field.js +292 -0
- data/frameworks/sproutcore/frameworks/desktop/views/separator.js +37 -0
- data/frameworks/sproutcore/frameworks/desktop/views/slider.js +178 -0
- data/frameworks/sproutcore/frameworks/desktop/views/source_list.js +1117 -0
- data/frameworks/sproutcore/frameworks/desktop/views/source_list_group.js +169 -0
- data/frameworks/sproutcore/frameworks/desktop/views/split.js +651 -0
- data/frameworks/sproutcore/frameworks/desktop/views/split_divider.js +55 -0
- data/frameworks/sproutcore/frameworks/desktop/views/tab.js +190 -0
- data/frameworks/sproutcore/frameworks/desktop/views/text_field.js +233 -0
- data/frameworks/sproutcore/frameworks/desktop/views/thumb.js +49 -0
- data/frameworks/sproutcore/frameworks/desktop/views/toolbar.js +49 -0
- data/frameworks/sproutcore/frameworks/desktop/views/web.js +86 -0
- data/frameworks/sproutcore/frameworks/foundation/TESTING +46 -0
- data/frameworks/sproutcore/frameworks/foundation/controllers/array.js +490 -0
- data/frameworks/sproutcore/frameworks/foundation/controllers/controller.js +317 -0
- data/frameworks/sproutcore/frameworks/foundation/controllers/object.js +421 -0
- data/frameworks/sproutcore/frameworks/foundation/core.js +111 -0
- data/frameworks/sproutcore/frameworks/foundation/debug/control_test_pane.js +172 -0
- data/frameworks/sproutcore/frameworks/foundation/english.lproj/blank.gif +0 -0
- data/frameworks/sproutcore/frameworks/foundation/english.lproj/bootstrap.rhtml +53 -0
- data/frameworks/sproutcore/frameworks/foundation/english.lproj/button_view.css +55 -0
- data/frameworks/sproutcore/frameworks/foundation/english.lproj/core.css +5 -0
- data/frameworks/sproutcore/frameworks/foundation/english.lproj/debug/control-test-pane.css +8 -0
- data/frameworks/sproutcore/frameworks/foundation/english.lproj/images/sproutcore-logo.png +0 -0
- data/frameworks/sproutcore/frameworks/foundation/english.lproj/static_layout.css +5 -0
- data/frameworks/sproutcore/frameworks/foundation/english.lproj/view.css +40 -0
- data/frameworks/sproutcore/frameworks/foundation/ext/object.js +81 -0
- data/frameworks/sproutcore/frameworks/foundation/ext/run_loop.js +158 -0
- data/frameworks/sproutcore/frameworks/foundation/fixtures/file_exists.json +1 -0
- data/frameworks/sproutcore/frameworks/foundation/mixins/button.js +291 -0
- data/frameworks/sproutcore/frameworks/foundation/mixins/content_display.js +88 -0
- data/frameworks/sproutcore/frameworks/foundation/mixins/control.js +352 -0
- data/frameworks/sproutcore/frameworks/foundation/mixins/editable.js +146 -0
- data/frameworks/sproutcore/frameworks/foundation/mixins/responder.js +156 -0
- data/frameworks/sproutcore/frameworks/foundation/mixins/selection_support.js +154 -0
- data/frameworks/sproutcore/frameworks/foundation/mixins/static_layout.js +101 -0
- data/frameworks/sproutcore/frameworks/foundation/mixins/string.js +237 -0
- data/frameworks/sproutcore/frameworks/foundation/mixins/validatable.js +176 -0
- data/frameworks/sproutcore/frameworks/foundation/panes/main.js +47 -0
- data/frameworks/sproutcore/frameworks/foundation/panes/pane.js +555 -0
- data/frameworks/sproutcore/frameworks/foundation/protocols/inline_editor_delegate.js +84 -0
- data/frameworks/sproutcore/frameworks/foundation/system/benchmark.js +244 -0
- data/frameworks/sproutcore/frameworks/foundation/system/browser.js +64 -0
- data/frameworks/sproutcore/frameworks/foundation/system/builder.js +210 -0
- data/frameworks/sproutcore/frameworks/foundation/system/core_query.js +2015 -0
- data/frameworks/sproutcore/frameworks/foundation/system/cursor.js +129 -0
- data/frameworks/sproutcore/frameworks/foundation/system/error.js +93 -0
- data/frameworks/sproutcore/frameworks/foundation/system/event.js +817 -0
- data/frameworks/sproutcore/frameworks/foundation/system/image_cache.js +433 -0
- data/frameworks/sproutcore/frameworks/foundation/system/json.js +440 -0
- data/frameworks/sproutcore/frameworks/foundation/system/locale.js +288 -0
- data/frameworks/sproutcore/frameworks/foundation/system/page.js +106 -0
- data/frameworks/sproutcore/frameworks/foundation/system/ready.js +189 -0
- data/frameworks/sproutcore/frameworks/foundation/system/render_context.js +865 -0
- data/frameworks/sproutcore/frameworks/foundation/system/request.js +255 -0
- data/frameworks/sproutcore/frameworks/foundation/system/root_responder.js +368 -0
- data/frameworks/sproutcore/frameworks/foundation/system/routes.js +446 -0
- data/frameworks/sproutcore/frameworks/foundation/system/time.js +478 -0
- data/frameworks/sproutcore/frameworks/foundation/system/timer.js +549 -0
- data/frameworks/sproutcore/frameworks/foundation/system/user_defaults.js +158 -0
- data/frameworks/sproutcore/frameworks/foundation/system/utils.js +330 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/controllers/array.js +118 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/controllers/controller.js +268 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/controllers/object.js +433 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/debug/control_test_pane/methods.js +10 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/debug/control_test_pane/ui.js +113 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/integration/creating_views.js +113 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/mixins/button/content.js +195 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/mixins/button/displayProperties.js +89 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/mixins/control/content.js +168 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/mixins/control/displayProperties.js +89 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/system/builder.js +42 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/system/core_query/jquery_core.js +1323 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/system/core_query/jquery_dimensions.js +387 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/system/core_query/jquery_selector.js +405 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/system/core_query/setClass.js +49 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/system/core_query/within.js +66 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/system/error.js +41 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/system/json.js +14 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/system/locale.js +128 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/system/render_context/begin.js +47 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/system/render_context/element.js +44 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/system/render_context/end.js +119 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/system/render_context/get.js +51 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/system/render_context/helpers_attr.js +50 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/system/render_context/helpers_basic.js +28 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/system/render_context/helpers_className.js +179 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/system/render_context/helpers_style.js +100 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/system/render_context/init.js +55 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/system/render_context/join.js +28 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/system/render_context/push_text.js +74 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/system/render_context/tag.js +45 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/system/render_context/update.js +205 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/system/request.js +89 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/system/root_responder/makeKeyPane.js +124 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/system/root_responder/makeMainPane.js +68 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/system/root_responder/root_responder.js +97 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/system/root_responder/targetForAction.js +238 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/system/routes.js +33 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/system/timer/invalidate.js +38 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/system/timer/invokeLater.js +201 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/system/timer/isPaused.js +71 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/system/timer/performAction.js +67 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/system/timer/schedule.js +170 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/system/user_defaults.js +27 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/system/utils/normalizeURL.js +18 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/system/utils/range.js +62 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/validators/credit_card.js +35 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/validators/date.js +21 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/validators/number.js +47 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/validators/password.js +13 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/views/container/methods.js +10 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/views/container/ui.js +83 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/views/image/ui.js +39 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/views/main_pane.js +31 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/views/pane/append_remove.js +89 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/views/pane/firstResponder.js +148 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/views/pane/keyPane.js +133 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/views/pane/sendEvent.js +165 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/views/view/clippingFrame.js +132 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/views/view/convertFrames.js +246 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/views/view/createChildViews.js +87 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/views/view/createLayer.js +97 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/views/view/destroyLayer.js +85 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/views/view/findLayerInParentLayer.js +52 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/views/view/init.js +50 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/views/view/insertBefore.js +200 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/views/view/isVisibleInWindow.js +102 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/views/view/layer.js +150 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/views/view/layoutChildViews.js +162 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/views/view/layoutDidChange.js +127 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/views/view/layoutStyle.js +248 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/views/view/parentViewDidChange.js +67 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/views/view/prepareContext.js +166 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/views/view/removeChild.js +189 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/views/view/render.js +83 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/views/view/replaceChild.js +29 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/views/view/updateLayer.js +142 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/views/view/updateLayerLocation.js +194 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/views/view/viewDidResize.js +185 -0
- data/frameworks/sproutcore/frameworks/foundation/validators/credit_card.js +125 -0
- data/frameworks/sproutcore/frameworks/foundation/validators/date.js +52 -0
- data/frameworks/sproutcore/frameworks/foundation/validators/email.js +45 -0
- data/frameworks/sproutcore/frameworks/foundation/validators/not_empty.js +33 -0
- data/frameworks/sproutcore/frameworks/foundation/validators/number.js +82 -0
- data/frameworks/sproutcore/frameworks/foundation/validators/password.js +86 -0
- data/frameworks/sproutcore/frameworks/foundation/validators/validator.js +311 -0
- data/frameworks/sproutcore/frameworks/foundation/views/container.js +136 -0
- data/frameworks/sproutcore/frameworks/foundation/views/field.js +276 -0
- data/frameworks/sproutcore/frameworks/foundation/views/image.js +158 -0
- data/frameworks/sproutcore/frameworks/foundation/views/label.js +261 -0
- data/frameworks/sproutcore/frameworks/foundation/views/view.js +2160 -0
- data/frameworks/sproutcore/frameworks/mobile/english.lproj/core.css +12 -0
- data/frameworks/sproutcore/frameworks/mobile/lib/index.rhtml +126 -0
- data/frameworks/sproutcore/frameworks/mobile/system/root_responder.js +109 -0
- data/frameworks/sproutcore/frameworks/mobile/tests/views/button/ui.js +9 -0
- data/frameworks/sproutcore/frameworks/mobile/views/button.js +190 -0
- data/frameworks/sproutcore/frameworks/runtime/README +11 -0
- data/frameworks/sproutcore/frameworks/runtime/core.js +777 -0
- data/frameworks/sproutcore/frameworks/runtime/license.js +28 -0
- data/frameworks/sproutcore/frameworks/runtime/mixins/array.js +403 -0
- data/frameworks/sproutcore/frameworks/runtime/mixins/delegate_support.js +70 -0
- data/frameworks/sproutcore/frameworks/runtime/mixins/enumerable.js +1193 -0
- data/frameworks/sproutcore/frameworks/runtime/mixins/observable.js +1149 -0
- data/frameworks/sproutcore/frameworks/runtime/private/chain_observer.js +135 -0
- data/frameworks/sproutcore/frameworks/runtime/private/observer_queue.js +108 -0
- data/frameworks/sproutcore/frameworks/runtime/private/observer_set.js +128 -0
- data/frameworks/sproutcore/frameworks/runtime/protocols/sparse_array_delegate.js +131 -0
- data/frameworks/sproutcore/frameworks/runtime/system/binding.js +891 -0
- data/frameworks/sproutcore/frameworks/runtime/system/enumerator.js +107 -0
- data/frameworks/sproutcore/frameworks/runtime/system/object.js +783 -0
- data/frameworks/sproutcore/frameworks/runtime/system/range_observer.js +99 -0
- data/frameworks/sproutcore/frameworks/runtime/system/run_loop.js +214 -0
- data/frameworks/sproutcore/frameworks/runtime/system/set.js +246 -0
- data/frameworks/sproutcore/frameworks/runtime/system/sparse_array.js +286 -0
- data/frameworks/sproutcore/frameworks/runtime/tests/core/IsEqual.js +56 -0
- data/frameworks/sproutcore/frameworks/runtime/tests/core/beget.js +23 -0
- data/frameworks/sproutcore/frameworks/runtime/tests/core/clone.js +66 -0
- data/frameworks/sproutcore/frameworks/runtime/tests/core/guidFor.js +147 -0
- data/frameworks/sproutcore/frameworks/runtime/tests/core/inspect.js +27 -0
- data/frameworks/sproutcore/frameworks/runtime/tests/core/isArray.js +25 -0
- data/frameworks/sproutcore/frameworks/runtime/tests/core/itemType.js +38 -0
- data/frameworks/sproutcore/frameworks/runtime/tests/core/keys.js +20 -0
- data/frameworks/sproutcore/frameworks/runtime/tests/core/makeArray.js +30 -0
- data/frameworks/sproutcore/frameworks/runtime/tests/core/objectForPropertyPath.js +19 -0
- data/frameworks/sproutcore/frameworks/runtime/tests/core/tupleForPropertyPath.js +37 -0
- data/frameworks/sproutcore/frameworks/runtime/tests/mixins/enumerable.js +592 -0
- data/frameworks/sproutcore/frameworks/runtime/tests/mixins/observable/observable.js +467 -0
- data/frameworks/sproutcore/frameworks/runtime/tests/mixins/observable/propertyChanges.js +123 -0
- data/frameworks/sproutcore/frameworks/runtime/tests/mixins/observable/registerDependentKeys.js +79 -0
- data/frameworks/sproutcore/frameworks/runtime/tests/mixins/propertyChanges.js +80 -0
- data/frameworks/sproutcore/frameworks/runtime/tests/system/array.js +263 -0
- data/frameworks/sproutcore/frameworks/runtime/tests/system/binding.js +190 -0
- data/frameworks/sproutcore/frameworks/runtime/tests/system/object/base.js +135 -0
- data/frameworks/sproutcore/frameworks/runtime/tests/system/object/bindings.js +339 -0
- data/frameworks/sproutcore/frameworks/runtime/tests/system/run_loop.js +120 -0
- data/frameworks/sproutcore/frameworks/runtime/tests/system/set.js +313 -0
- data/frameworks/sproutcore/frameworks/runtime/tests/system/sparse_array.js +84 -0
- data/frameworks/sproutcore/frameworks/testing/core.js +13 -0
- data/frameworks/sproutcore/frameworks/testing/english.lproj/additions.css +8 -0
- data/frameworks/sproutcore/frameworks/testing/english.lproj/testsuite.css +131 -0
- data/frameworks/sproutcore/frameworks/testing/extras.js +43 -0
- data/frameworks/sproutcore/frameworks/testing/jquery.js +3559 -0
- data/frameworks/sproutcore/frameworks/testing/qunit.js +819 -0
- data/frameworks/sproutcore/frameworks/testing/tests/debug/qunit.js +25 -0
- data/frameworks/sproutcore/frameworks/testing/utils.js +55 -0
- data/frameworks/sproutcore/lib/index.rhtml +118 -0
- data/frameworks/sproutcore/license.js +28 -0
- data/frameworks/sproutcore/themes/empty_theme/tests/mini_icons.rhtml +69 -0
- data/frameworks/sproutcore/themes/iphone_theme/english.lproj/button.css +41 -0
- data/frameworks/sproutcore/themes/iphone_theme/english.lproj/core.css +8 -0
- data/frameworks/sproutcore/themes/iphone_theme/english.lproj/images/backButton.png +0 -0
- data/frameworks/sproutcore/themes/iphone_theme/english.lproj/images/blueButton.png +0 -0
- data/frameworks/sproutcore/themes/iphone_theme/english.lproj/images/cancel.png +0 -0
- data/frameworks/sproutcore/themes/iphone_theme/english.lproj/images/grayButton.png +0 -0
- data/frameworks/sproutcore/themes/iphone_theme/english.lproj/images/leftButton.png +0 -0
- data/frameworks/sproutcore/themes/iphone_theme/english.lproj/images/listArrow.png +0 -0
- data/frameworks/sproutcore/themes/iphone_theme/english.lproj/images/listArrowSel.png +0 -0
- data/frameworks/sproutcore/themes/iphone_theme/english.lproj/images/listGroup.png +0 -0
- data/frameworks/sproutcore/themes/iphone_theme/english.lproj/images/loading.gif +0 -0
- data/frameworks/sproutcore/themes/iphone_theme/english.lproj/images/pinstripes.png +0 -0
- data/frameworks/sproutcore/themes/iphone_theme/english.lproj/images/rightButton.png +0 -0
- data/frameworks/sproutcore/themes/iphone_theme/english.lproj/images/selection.png +0 -0
- data/frameworks/sproutcore/themes/iphone_theme/english.lproj/images/thumb.png +0 -0
- data/frameworks/sproutcore/themes/iphone_theme/english.lproj/images/toggle.png +0 -0
- data/frameworks/sproutcore/themes/iphone_theme/english.lproj/images/toggleOn.png +0 -0
- data/frameworks/sproutcore/themes/iphone_theme/english.lproj/images/toolButton.png +0 -0
- data/frameworks/sproutcore/themes/iphone_theme/english.lproj/images/toolbar.png +0 -0
- data/frameworks/sproutcore/themes/iphone_theme/english.lproj/images/whiteButton.png +0 -0
- data/frameworks/sproutcore/themes/iphone_theme/english.lproj/strings.js +15 -0
- data/frameworks/sproutcore/themes/standard_theme/Source/Panel.drawit/Data +0 -0
- data/frameworks/sproutcore/themes/standard_theme/Source/Panel.drawit/QuickLook/Preview.jpg +0 -0
- data/frameworks/sproutcore/themes/standard_theme/Source/Panel.drawit/QuickLook/Thumbnail.jpg +0 -0
- data/frameworks/sproutcore/themes/standard_theme/Source/ToolbarView Pattern.drawit/Data +0 -0
- data/frameworks/sproutcore/themes/standard_theme/Source/ToolbarView Pattern.drawit/QuickLook/Preview.jpg +0 -0
- data/frameworks/sproutcore/themes/standard_theme/Source/ToolbarView Pattern.drawit/QuickLook/Thumbnail.jpg +0 -0
- data/frameworks/sproutcore/themes/standard_theme/Source/panel-sprite-x.drawit/Data +0 -0
- data/frameworks/sproutcore/themes/standard_theme/Source/panel-sprite-x.drawit/QuickLook/Preview.jpg +0 -0
- data/frameworks/sproutcore/themes/standard_theme/Source/panel-sprite-x.drawit/QuickLook/Thumbnail.jpg +0 -0
- data/frameworks/sproutcore/themes/standard_theme/Source/panel-sprite-y.drawit/Data +0 -0
- data/frameworks/sproutcore/themes/standard_theme/Source/panel-sprite-y.drawit/QuickLook/Preview.jpg +0 -0
- data/frameworks/sproutcore/themes/standard_theme/Source/panel-sprite-y.drawit/QuickLook/Thumbnail.jpg +0 -0
- data/frameworks/sproutcore/themes/standard_theme/english.lproj/button.css +333 -0
- data/frameworks/sproutcore/themes/standard_theme/english.lproj/checkbox.css +90 -0
- data/frameworks/sproutcore/themes/standard_theme/english.lproj/collection.css +53 -0
- data/frameworks/sproutcore/themes/standard_theme/english.lproj/core.css +47 -0
- data/frameworks/sproutcore/themes/standard_theme/english.lproj/disclosure.css +55 -0
- data/frameworks/sproutcore/themes/standard_theme/english.lproj/images/sc-theme-sprite.png +0 -0
- data/frameworks/sproutcore/themes/standard_theme/english.lproj/images/sc-theme-ysprite.png +0 -0
- data/frameworks/sproutcore/themes/standard_theme/english.lproj/images/sc-toolbar-view.png +0 -0
- data/frameworks/sproutcore/themes/standard_theme/english.lproj/label.css +37 -0
- data/frameworks/sproutcore/themes/standard_theme/english.lproj/pane.css +8 -0
- data/frameworks/sproutcore/themes/standard_theme/english.lproj/panels/background-fat.jpg +0 -0
- data/frameworks/sproutcore/themes/standard_theme/english.lproj/panels/background-thin.jpg +0 -0
- data/frameworks/sproutcore/themes/standard_theme/english.lproj/panels/bottom-edge.png +0 -0
- data/frameworks/sproutcore/themes/standard_theme/english.lproj/panels/bottom-left-corner.png +0 -0
- data/frameworks/sproutcore/themes/standard_theme/english.lproj/panels/bottom-right-corner.png +0 -0
- data/frameworks/sproutcore/themes/standard_theme/english.lproj/panels/left-edge.png +0 -0
- data/frameworks/sproutcore/themes/standard_theme/english.lproj/panels/overlay.png +0 -0
- data/frameworks/sproutcore/themes/standard_theme/english.lproj/panels/right-edge.png +0 -0
- data/frameworks/sproutcore/themes/standard_theme/english.lproj/panels/top-edge.png +0 -0
- data/frameworks/sproutcore/themes/standard_theme/english.lproj/panels/top-left-corner.png +0 -0
- data/frameworks/sproutcore/themes/standard_theme/english.lproj/panels/top-right-corner.png +0 -0
- data/frameworks/sproutcore/themes/standard_theme/english.lproj/progress.css +23 -0
- data/frameworks/sproutcore/themes/standard_theme/english.lproj/radio.css +113 -0
- data/frameworks/sproutcore/themes/standard_theme/english.lproj/segmented.css +141 -0
- data/frameworks/sproutcore/themes/standard_theme/english.lproj/slider.css +62 -0
- data/frameworks/sproutcore/themes/standard_theme/english.lproj/split_view.css +27 -0
- data/frameworks/sproutcore/themes/standard_theme/english.lproj/tab.css +12 -0
- data/frameworks/sproutcore/themes/standard_theme/english.lproj/text_field.css +13 -0
- data/frameworks/sproutcore/themes/standard_theme/english.lproj/toolbar.css +4 -0
- data/lib/thor/.autotest +7 -0
- data/lib/thor/CHANGELOG.rdoc +52 -0
- data/lib/thor/LICENSE +20 -0
- data/lib/thor/README.markdown +76 -0
- data/lib/thor/Rakefile +6 -0
- data/lib/thor/Thorfile +45 -0
- data/lib/thor/bin/rake2thor +83 -0
- data/lib/thor/bin/thor +7 -0
- data/lib/thor/lib/thor/error.rb +3 -0
- data/lib/thor/lib/thor/options.rb +267 -0
- data/lib/thor/lib/thor/ordered_hash.rb +64 -0
- data/lib/thor/lib/thor/runner.rb +305 -0
- data/lib/thor/lib/thor/task.rb +83 -0
- data/lib/thor/lib/thor/task_hash.rb +22 -0
- data/lib/thor/lib/thor/tasks/package.rb +18 -0
- data/lib/thor/lib/thor/tasks.rb +77 -0
- data/lib/thor/lib/thor/util.rb +75 -0
- data/lib/thor/lib/thor.rb +170 -0
- data/lib/thor/script/destroy +14 -0
- data/lib/thor/script/generate +14 -0
- data/lib/thor/spec/fixtures/task.thor +10 -0
- data/lib/thor/spec/options_spec.rb +271 -0
- data/lib/thor/spec/ordered_hash_spec.rb +84 -0
- data/lib/thor/spec/spec.opts +1 -0
- data/lib/thor/spec/spec_helper.rb +30 -0
- data/lib/thor/spec/task_spec.rb +11 -0
- data/lib/thor/spec/tasks_spec.rb +28 -0
- data/lib/thor/spec/thor_runner_spec.rb +194 -0
- data/lib/thor/spec/thor_spec.rb +206 -0
- data/lib/thor/spec/util_spec.rb +99 -0
- data/lib/thor/task.thor +15 -0
- data/lib/thor/thor.gemspec +29 -0
- metadata +3 -4
- data/sproutcore.gemspec +0 -47
@@ -0,0 +1,2160 @@
|
|
1
|
+
// ==========================================================================
|
2
|
+
// Project: SproutCore - JavaScript Application Framework
|
3
|
+
// Copyright: ©2006-2009 Sprout Systems, Inc. and contributors.
|
4
|
+
// Portions ©2008-2009 Apple, Inc. All rights reserved.
|
5
|
+
// License: Licened under MIT license (see license.js)
|
6
|
+
// ==========================================================================
|
7
|
+
|
8
|
+
require('system/browser');
|
9
|
+
require('system/event');
|
10
|
+
require('system/cursor');
|
11
|
+
|
12
|
+
require('mixins/responder') ;
|
13
|
+
require('mixins/string') ;
|
14
|
+
|
15
|
+
SC.viewKey = SC.guidKey + "_view" ;
|
16
|
+
|
17
|
+
/** Select a horizontal layout for various views.*/
|
18
|
+
SC.LAYOUT_HORIZONTAL = 'sc-layout-horizontal';
|
19
|
+
|
20
|
+
/** Select a vertical layout for various views.*/
|
21
|
+
SC.LAYOUT_VERTICAL = 'sc-layout-vertical';
|
22
|
+
|
23
|
+
/** @private */
|
24
|
+
SC._VIEW_DEFAULT_DIMS = 'marginTop marginLeft'.w();
|
25
|
+
|
26
|
+
/**
|
27
|
+
Layout properties needed to anchor a view to the top.
|
28
|
+
*/
|
29
|
+
SC.ANCHOR_TOP = { top: 0 };
|
30
|
+
|
31
|
+
/**
|
32
|
+
Layout properties needed to anchor a view to the left.
|
33
|
+
*/
|
34
|
+
SC.ANCHOR_LEFT = { left: 0 };
|
35
|
+
|
36
|
+
/*
|
37
|
+
Layout properties to anchor a view to the top left
|
38
|
+
*/
|
39
|
+
SC.ANCHOR_TOP_LEFT = { top: 0, left: 0 };
|
40
|
+
|
41
|
+
/**
|
42
|
+
Layout properties to anchoe view to the bottom.
|
43
|
+
*/
|
44
|
+
SC.ANCHOR_BOTTOM = { bottom: 0 };
|
45
|
+
|
46
|
+
/**
|
47
|
+
Layout properties to anchor a view to the right.
|
48
|
+
*/
|
49
|
+
SC.ANCHOR_RIGHT = { right: 0 } ;
|
50
|
+
|
51
|
+
/**
|
52
|
+
Layout properties to anchor a view to the bottom right.
|
53
|
+
*/
|
54
|
+
SC.ANCHOR_BOTTOM_RIGHT = { bottom: 0, right: 0 };
|
55
|
+
|
56
|
+
/**
|
57
|
+
Layout properties to take up the full width of a parent view.
|
58
|
+
*/
|
59
|
+
SC.FULL_WIDTH = { left: 0, right: 0 };
|
60
|
+
|
61
|
+
/**
|
62
|
+
Layout properties to take up the full height of a parent view.
|
63
|
+
*/
|
64
|
+
SC.FULL_HEIGHT = { top: 0, bottom: 0 };
|
65
|
+
|
66
|
+
/**
|
67
|
+
Layout properties to center. Note that you must also specify a width and
|
68
|
+
height for this to work.
|
69
|
+
*/
|
70
|
+
SC.ANCHOR_CENTER = { centerX: 0, centerY: 0 };
|
71
|
+
|
72
|
+
/** @private - custom array used for child views */
|
73
|
+
SC.EMPTY_CHILD_VIEWS_ARRAY = [];
|
74
|
+
SC.EMPTY_CHILD_VIEWS_ARRAY.needsClone = YES;
|
75
|
+
|
76
|
+
/**
|
77
|
+
@class
|
78
|
+
|
79
|
+
Base class for managing a view. View's provide two functions:
|
80
|
+
|
81
|
+
1. They translate state and events into drawing instructions for the
|
82
|
+
web browser and
|
83
|
+
|
84
|
+
2. They act as first responders for incoming keyboard, mouse, and
|
85
|
+
touch events.
|
86
|
+
|
87
|
+
h2. View Initialization
|
88
|
+
|
89
|
+
When a view is setup, there are several methods you can override that
|
90
|
+
will be called at different times depending on how your view is created.
|
91
|
+
Here is a guide to which method you want to override and when:
|
92
|
+
|
93
|
+
- *init:* override this method for any general object setup (such as
|
94
|
+
observers, starting timers and animations, etc) that you need to happen
|
95
|
+
everytime the view is created, regardless of whether or not its layer
|
96
|
+
exists yet.
|
97
|
+
|
98
|
+
- *render:* override this method to generate or update your HTML to reflect
|
99
|
+
the current state of your view. This method is called both when your view
|
100
|
+
is first created and later anytime it needs to be updated.
|
101
|
+
|
102
|
+
- *didCreateLayer:* the render() method is used to generate new HTML.
|
103
|
+
Override this method to perform any additional setup on the DOM you might
|
104
|
+
need to do after creating the view. For example, if you need to listen
|
105
|
+
for events.
|
106
|
+
|
107
|
+
- *willDestroyLayer:* if you implement didCreateLayer() to setup event
|
108
|
+
listeners, you should implement this method as well to remove the same
|
109
|
+
just before the DOM for your view is destroyed.
|
110
|
+
|
111
|
+
- *updateLayer:* Normally, when a view needs to update its content, it will
|
112
|
+
re-render the view using the render() method. If you would like to
|
113
|
+
override this behavior with your own custom updating code, you can
|
114
|
+
replace updateLayer() with your own implementation instead.
|
115
|
+
|
116
|
+
@extends SC.Object
|
117
|
+
@extends SC.Responder
|
118
|
+
@extends SC.DelegateSupport
|
119
|
+
@since SproutCore 1.0
|
120
|
+
*/
|
121
|
+
SC.View = SC.Object.extend(SC.Responder, SC.DelegateSupport,
|
122
|
+
/** @scope SC.View.prototype */ {
|
123
|
+
|
124
|
+
concatenatedProperties: 'outlets displayProperties layoutProperties classNames renderMixin didCreateLayerMixin willDestroyLayerMixin'.w(),
|
125
|
+
|
126
|
+
/**
|
127
|
+
The current pane.
|
128
|
+
@property {SC.Pane}
|
129
|
+
*/
|
130
|
+
pane: function() {
|
131
|
+
var view = this ;
|
132
|
+
while (view && !view.isPane) view = view.get('parentView') ;
|
133
|
+
return view ;
|
134
|
+
}.property('parentView').cacheable(),
|
135
|
+
|
136
|
+
/**
|
137
|
+
The page this view was instantiated from. This is set by the page object
|
138
|
+
during instantiation.
|
139
|
+
|
140
|
+
@property {SC.Page}
|
141
|
+
*/
|
142
|
+
page: null,
|
143
|
+
|
144
|
+
/**
|
145
|
+
The current split view this view is embedded in (may be null).
|
146
|
+
@property {SC.SplitView}
|
147
|
+
*/
|
148
|
+
splitView: function() {
|
149
|
+
var view = this ;
|
150
|
+
while (view && !view.isSplitView) view = view.get('parentView') ;
|
151
|
+
return view ;
|
152
|
+
}.property('parentView').cacheable(),
|
153
|
+
|
154
|
+
/**
|
155
|
+
If the view is currently inserted into the DOM of a parent view, this
|
156
|
+
property will point to the parent of the view.
|
157
|
+
*/
|
158
|
+
parentView: null,
|
159
|
+
|
160
|
+
/**
|
161
|
+
Optional background color. Will be applied to the view's element if
|
162
|
+
set. This property is intended for one-off views that need a background
|
163
|
+
element. If you plan to create many view instances it is probably better
|
164
|
+
to use CSS.
|
165
|
+
|
166
|
+
@property {String}
|
167
|
+
*/
|
168
|
+
backgroundColor: null,
|
169
|
+
|
170
|
+
// ..........................................................
|
171
|
+
// IS ENABLED SUPPORT
|
172
|
+
//
|
173
|
+
|
174
|
+
/**
|
175
|
+
Set to true when the item is enabled. Note that changing this value
|
176
|
+
will also alter the isVisibleInWindow property for this view and any
|
177
|
+
child views.
|
178
|
+
|
179
|
+
Note that if you apply the SC.Control mixin, changing this property will
|
180
|
+
also automatically add or remove a 'disabled' CSS class name as well.
|
181
|
+
|
182
|
+
This property is observable and bindable.
|
183
|
+
|
184
|
+
@property {Boolean}
|
185
|
+
*/
|
186
|
+
isEnabled: YES,
|
187
|
+
isEnabledBindingDefault: SC.Binding.oneWay().bool(),
|
188
|
+
|
189
|
+
/**
|
190
|
+
Computed property returns YES if the view and all of its parent views
|
191
|
+
are enabled in the pane. You should use this property when deciding
|
192
|
+
whether to respond to an incoming event or not.
|
193
|
+
|
194
|
+
This property is not observable.
|
195
|
+
|
196
|
+
@property {Boolean}
|
197
|
+
*/
|
198
|
+
isEnabledInPane: function() {
|
199
|
+
var ret = this.get('isEnabled'), pv ;
|
200
|
+
if (ret && (pv = this.get('parentView'))) ret = pv.get('isEnabledInPane');
|
201
|
+
return ret ;
|
202
|
+
}.property('parentView', 'isEnabled'),
|
203
|
+
|
204
|
+
// ..........................................................
|
205
|
+
// IS VISIBLE IN WINDOW SUPPORT
|
206
|
+
//
|
207
|
+
|
208
|
+
/**
|
209
|
+
The isVisible property determines if the view is shown in the view
|
210
|
+
hierarchy it is a part of. A view can have isVisible == YES and still have
|
211
|
+
isVisibleInWindow == NO. This occurs, for instance, when a parent view has
|
212
|
+
isVisible == NO. Default is YES.
|
213
|
+
|
214
|
+
The isVisible property is considered part of the layout and so changing it
|
215
|
+
will trigger a layout update.
|
216
|
+
|
217
|
+
@property {Boolean}
|
218
|
+
*/
|
219
|
+
isVisible: YES,
|
220
|
+
|
221
|
+
/**
|
222
|
+
YES only if the view and all of its parent views are currently visible
|
223
|
+
in the window. This property is used to optimize certain behaviors in
|
224
|
+
the view. For example, updates to the view layer are not performed
|
225
|
+
if the view until the view becomes visible in the window.
|
226
|
+
*/
|
227
|
+
isVisibleInWindow: NO,
|
228
|
+
|
229
|
+
/**
|
230
|
+
Recomputes the isVisibleInWindow property based on the visibility of the
|
231
|
+
view and its parent. If the recomputed value differs from the current
|
232
|
+
isVisibleInWindow state, this method will also call
|
233
|
+
recomputIsVisibleInWindow() on its child views as well. As an optional
|
234
|
+
optimization, you can pass the isVisibleInWindow state of the parentView
|
235
|
+
if you already know it.
|
236
|
+
|
237
|
+
You will not generally need to call or override this method yourself. It
|
238
|
+
is used by the SC.View hierarchy to relay window visibility changes up
|
239
|
+
and down the chain.
|
240
|
+
|
241
|
+
@property {Boolean} parentViewIsVisible
|
242
|
+
@returns {SC.View} receiver
|
243
|
+
*/
|
244
|
+
recomputeIsVisibleInWindow: function(parentViewIsVisible) {
|
245
|
+
var last = this.get('isVisibleInWindow') ;
|
246
|
+
var cur = this.get('isVisible'), parentView ;
|
247
|
+
|
248
|
+
// isVisibleInWindow = isVisible && parentView.isVisibleInWindow
|
249
|
+
// this approach only goes up to the parentView if necessary.
|
250
|
+
if (cur) {
|
251
|
+
cur = (parentViewIsVisible === undefined) ?
|
252
|
+
((parentView=this.get('parentView')) ?
|
253
|
+
parentView.get('isVisibleInWindow') : NO) : parentViewIsVisible ;
|
254
|
+
}
|
255
|
+
|
256
|
+
// if the state has changed, update it and notify children
|
257
|
+
if (last !== cur) {
|
258
|
+
this.set('isVisibleInWindow', cur) ;
|
259
|
+
|
260
|
+
var childViews = this.get('childViews'), len = childViews.length, idx;
|
261
|
+
for(idx=0;idx<len;idx++) {
|
262
|
+
childViews[idx].recomputeIsVisibleInWindow(cur);
|
263
|
+
}
|
264
|
+
|
265
|
+
// if we just became visible, update layer + layout if needed...
|
266
|
+
if (cur && this.parentViewDidResize) this.parentViewDidResize();
|
267
|
+
|
268
|
+
// if we were firstResponder, resign firstResponder also if no longer
|
269
|
+
// visible.
|
270
|
+
if (!cur && this.get('isFirstResponder')) this.resignFirstResponder();
|
271
|
+
|
272
|
+
}
|
273
|
+
|
274
|
+
return this ;
|
275
|
+
},
|
276
|
+
|
277
|
+
// ..........................................................
|
278
|
+
// CHILD VIEW SUPPORT
|
279
|
+
//
|
280
|
+
|
281
|
+
/**
|
282
|
+
Array of child views. You should never edit this array directly unless
|
283
|
+
you are implementing createChildViews(). Most of the time, you should
|
284
|
+
use the accessor methods such as appendChild(), insertBefore() and
|
285
|
+
removeChild().
|
286
|
+
|
287
|
+
@property {Array}
|
288
|
+
*/
|
289
|
+
childViews: SC.EMPTY_CHILD_VIEWS_ARRAY,
|
290
|
+
|
291
|
+
/**
|
292
|
+
Insert the view into the the receiver's childNodes array.
|
293
|
+
|
294
|
+
The view will be added to the childNodes array before the beforeView. If
|
295
|
+
beforeView is null, then the view will be added to the end of the array.
|
296
|
+
This will also add the view's rootElement DOM node to the receivers
|
297
|
+
containerElement DOM node as a child.
|
298
|
+
|
299
|
+
If the specified view already belongs to another parent, it will be
|
300
|
+
removed from that view first.
|
301
|
+
|
302
|
+
@param {SC.View} view
|
303
|
+
@param {SC.View} beforeView
|
304
|
+
@returns {SC.View} the receiver
|
305
|
+
*/
|
306
|
+
insertBefore: function(view, beforeView) {
|
307
|
+
|
308
|
+
view.beginPropertyChanges(); // limit notifications
|
309
|
+
|
310
|
+
// remove view from old parent if needed. Also notify views.
|
311
|
+
if (view.get('parentView')) view.removeFromParent() ;
|
312
|
+
if (this.willAddChild) this.willAddChild(view, beforeView) ;
|
313
|
+
if (view.willAddToParent) view.willAddToParent(this, beforeView) ;
|
314
|
+
|
315
|
+
// set parentView of child
|
316
|
+
view.set('parentView', this);
|
317
|
+
|
318
|
+
// add to childView's array.
|
319
|
+
var idx, childViews = this.get('childViews') ;
|
320
|
+
if (childViews.needsClone) this.set(childViews = []);
|
321
|
+
idx = (beforeView) ? childViews.indexOf(beforeView) : childViews.length;
|
322
|
+
if (idx<0) idx = childViews.length ;
|
323
|
+
childViews.insertAt(idx, view) ;
|
324
|
+
|
325
|
+
// The DOM will need some fixing up, note this on the view.
|
326
|
+
view.parentViewDidChange() ;
|
327
|
+
view.layoutDidChange() ;
|
328
|
+
|
329
|
+
// notify views
|
330
|
+
if (this.didAddChild) this.didAddChild(view, beforeView) ;
|
331
|
+
if (view.didAddToParent) view.didAddToParent(this, beforeView) ;
|
332
|
+
|
333
|
+
view.endPropertyChanges();
|
334
|
+
|
335
|
+
return this ;
|
336
|
+
},
|
337
|
+
|
338
|
+
/**
|
339
|
+
Removes the child view from the parent view.
|
340
|
+
|
341
|
+
@param {SC.View} view
|
342
|
+
@returns {SC.View} receiver
|
343
|
+
*/
|
344
|
+
removeChild: function(view) {
|
345
|
+
if (!view) return this; // nothing to do
|
346
|
+
if (view.parentView !== this) {
|
347
|
+
throw "%@.removeChild(%@) must belong to parent".fmt(this,view);
|
348
|
+
}
|
349
|
+
|
350
|
+
// notify views
|
351
|
+
if (view.willRemoveFromParent) view.willRemoveFromParent() ;
|
352
|
+
if (this.willRemoveChild) this.willRemoveChild(view) ;
|
353
|
+
|
354
|
+
// update parent node
|
355
|
+
view.set('parentView', null) ;
|
356
|
+
|
357
|
+
// remove view from childViews array.
|
358
|
+
var childViews = this.get('childViews') ;
|
359
|
+
var idx = childViews.indexOf(view) ;
|
360
|
+
if (idx>=0) childViews.removeAt(idx);
|
361
|
+
|
362
|
+
// The DOM will need some fixing up, note this on the view.
|
363
|
+
view.parentViewDidChange() ;
|
364
|
+
|
365
|
+
// notify views
|
366
|
+
if (this.didRemoveChild) this.didRemoveChild(view);
|
367
|
+
if (view.didRemoveFromParent) view.didRemoveFromParent(this) ;
|
368
|
+
|
369
|
+
return this ;
|
370
|
+
},
|
371
|
+
|
372
|
+
/**
|
373
|
+
Removes all children from the parentView.
|
374
|
+
|
375
|
+
@returns {SC.View} receiver
|
376
|
+
*/
|
377
|
+
removeAllChildren: function() {
|
378
|
+
var childViews = this.get('childViews'), view ;
|
379
|
+
while (view = childViews.objectAt(childViews.get('length')-1)) {
|
380
|
+
this.removeChild(view) ;
|
381
|
+
}
|
382
|
+
return this ;
|
383
|
+
},
|
384
|
+
|
385
|
+
/**
|
386
|
+
Removes the view from its parentView, if one is found. Otherwise
|
387
|
+
does nothing.
|
388
|
+
|
389
|
+
@returns {SC.View} receiver
|
390
|
+
*/
|
391
|
+
removeFromParent: function() {
|
392
|
+
var parent = this.get('parentView') ;
|
393
|
+
if (parent) parent.removeChild(this) ;
|
394
|
+
return this ;
|
395
|
+
},
|
396
|
+
|
397
|
+
/**
|
398
|
+
Replace the oldView with the specified view in the receivers childNodes
|
399
|
+
array. This will also replace the DOM node of the oldView with the DOM
|
400
|
+
node of the new view in the receivers DOM.
|
401
|
+
|
402
|
+
If the specified view already belongs to another parent, it will be
|
403
|
+
removed from that view first.
|
404
|
+
|
405
|
+
@param view {SC.View} the view to insert in the DOM
|
406
|
+
@param view {SC.View} the view to remove from the DOM.
|
407
|
+
@returns {SC.View} the receiver
|
408
|
+
*/
|
409
|
+
replaceChild: function(view, oldView) {
|
410
|
+
|
411
|
+
// suspend notifications
|
412
|
+
view.beginPropertyChanges();
|
413
|
+
oldView.beginPropertyChanges();
|
414
|
+
this.beginPropertyChanges();
|
415
|
+
|
416
|
+
this.insertBefore(view,oldView).removeChild(oldView) ;
|
417
|
+
|
418
|
+
// resume notifications
|
419
|
+
this.endPropertyChanges();
|
420
|
+
oldView.endPropertyChanges();
|
421
|
+
view.endPropertyChanges();
|
422
|
+
|
423
|
+
return this;
|
424
|
+
},
|
425
|
+
|
426
|
+
/**
|
427
|
+
Appends the specified view to the end of the receivers childViews array.
|
428
|
+
This is equivalent to calling insertBefore(view, null);
|
429
|
+
|
430
|
+
@param view {SC.View} the view to insert
|
431
|
+
@returns {SC.View} the receiver
|
432
|
+
*/
|
433
|
+
appendChild: function(view) {
|
434
|
+
return this.insertBefore(view, null);
|
435
|
+
},
|
436
|
+
|
437
|
+
/**
|
438
|
+
This method is called whenever the receiver's parentView has changed.
|
439
|
+
The default implementation of this method marks the view's display
|
440
|
+
location as dirty so that it will update at the end of the run loop.
|
441
|
+
|
442
|
+
You will not usually need to override or call this method yourself, though
|
443
|
+
if you manually patch the parentView hierarchy for some reason, you should
|
444
|
+
call this method to notify the view that it's parentView has changed.
|
445
|
+
|
446
|
+
@returns {SC.View} receiver
|
447
|
+
*/
|
448
|
+
parentViewDidChange: function() {
|
449
|
+
this.recomputeIsVisibleInWindow() ;
|
450
|
+
|
451
|
+
this.set('layerLocationNeedsUpdate', YES) ;
|
452
|
+
this.invokeOnce(this.updateLayerLocationIfNeeded) ;
|
453
|
+
|
454
|
+
return this ;
|
455
|
+
}.observes('isVisible'),
|
456
|
+
|
457
|
+
// ..........................................................
|
458
|
+
// LAYER SUPPORT
|
459
|
+
//
|
460
|
+
|
461
|
+
/**
|
462
|
+
Returns the current layer for the view. The layer for a view is only
|
463
|
+
generated when the view first becomes visible in the window and even
|
464
|
+
then it will not be computed until you request this layer property.
|
465
|
+
|
466
|
+
If the layer is not actually set on the view itself, then the layer will
|
467
|
+
be found by calling this.findLayerInParentLayer().
|
468
|
+
|
469
|
+
You can also set the layer by calling set on this property.
|
470
|
+
|
471
|
+
@property {DOMElement} the layer
|
472
|
+
*/
|
473
|
+
layer: function(key, value) {
|
474
|
+
if (value !== undefined) {
|
475
|
+
this._view_layer = value ;
|
476
|
+
|
477
|
+
// no layer...attempt to discover it...
|
478
|
+
} else {
|
479
|
+
value = this._view_layer;
|
480
|
+
if (!value) {
|
481
|
+
var parent = this.get('parentView');
|
482
|
+
if (parent) parent = parent.get('layer');
|
483
|
+
if (parent) {
|
484
|
+
this._view_layer = value = this.findLayerInParentLayer(parent);
|
485
|
+
}
|
486
|
+
parent = null ; // avoid memory leak
|
487
|
+
}
|
488
|
+
}
|
489
|
+
return value ;
|
490
|
+
}.property('isVisibleInWindow').cacheable(),
|
491
|
+
|
492
|
+
/**
|
493
|
+
Get a CoreQuery object for this view's layer, or pass in a selector string
|
494
|
+
to get a CoreQuery object for a DOM node nested within this layer.
|
495
|
+
|
496
|
+
@param {String} sel a CoreQuery-compatible selector string
|
497
|
+
@returns {SC.CoreQuery} the CoreQuery object for the DOM node
|
498
|
+
*/
|
499
|
+
$: function(sel) {
|
500
|
+
var ret, layer = this.get('layer') ;
|
501
|
+
// note: SC.$([]) returns an empty CoreQuery object. SC.$() would
|
502
|
+
// return an object selecting hte document.
|
503
|
+
ret = !layer ? SC.$([]) : (sel === undefined) ? SC.$(layer) : SC.$(sel, layer) ;
|
504
|
+
layer = null ; // avoid memory leak
|
505
|
+
return ret ;
|
506
|
+
},
|
507
|
+
|
508
|
+
/**
|
509
|
+
Returns the DOM element that should be used to hold child views when they
|
510
|
+
are added/remove via DOM manipulation. The default implementation simply
|
511
|
+
returns the layer itself. You can override this to return a DOM element
|
512
|
+
within the layer.
|
513
|
+
|
514
|
+
@property {DOMElement} the container layer
|
515
|
+
*/
|
516
|
+
containerLayer: function() {
|
517
|
+
return this.get('layer') ;
|
518
|
+
}.property('layer').cacheable(),
|
519
|
+
|
520
|
+
/**
|
521
|
+
The ID to use when trying to locate the layer in the DOM. If you do not
|
522
|
+
set the layerId explicitly, then the view's GUID will be used instead.
|
523
|
+
This ID must be set at the time the view is created.
|
524
|
+
|
525
|
+
@property {String}
|
526
|
+
@readOnly
|
527
|
+
*/
|
528
|
+
layerId: function() {
|
529
|
+
return SC.guidFor(this) ;
|
530
|
+
}.property().cacheable(),
|
531
|
+
|
532
|
+
/**
|
533
|
+
Attempts to discover the layer in the parent layer. The default
|
534
|
+
implementation looks for an element with an ID of layerId (or the view's
|
535
|
+
guid if layerId is null). You can override this method to provide your
|
536
|
+
own form of lookup. For example, if you want to discover your layer using
|
537
|
+
a CSS class name instead of an ID.
|
538
|
+
|
539
|
+
@param {DOMElement} parentLayer the parent's DOM layer
|
540
|
+
@returns {DOMElement} the discovered layer
|
541
|
+
*/
|
542
|
+
findLayerInParentLayer: function(parentLayer) {
|
543
|
+
var layerId = this.get('layerId') ;
|
544
|
+
|
545
|
+
// first, let's try the fast path...
|
546
|
+
var elem = document.getElementById(layerId) ;
|
547
|
+
|
548
|
+
// TODO: use code generation to only really do this check on IE
|
549
|
+
if (SC.browser.msie && elem && elem.id !== layerId) elem = null ;
|
550
|
+
|
551
|
+
// if browser supports querySelector use that.
|
552
|
+
if (!elem && parentLayer.querySelector) {
|
553
|
+
// TODO: make querySelector work on all platforms...
|
554
|
+
// elem = parentLayer.querySelector('#' + layerId)[0];
|
555
|
+
}
|
556
|
+
|
557
|
+
// if no element was found the fast way, search down the parentLayer for
|
558
|
+
// the element. This code should not be invoked very often. Usually a
|
559
|
+
// DOM element will be discovered by the first method above.
|
560
|
+
if (!elem) {
|
561
|
+
elem = parentLayer.firstChild ;
|
562
|
+
while (elem && (elem.id !== layerId)) {
|
563
|
+
// try to get first child or next sibling if no children
|
564
|
+
var next = elem.firstChild || elem.nextSibling ;
|
565
|
+
|
566
|
+
// if no next sibling, then get next sibling of parent. Walk up
|
567
|
+
// until we find parent with next sibling or find ourselves back at
|
568
|
+
// the beginning.
|
569
|
+
while (!next && elem && ((elem = elem.parentNode) !== parentLayer)) {
|
570
|
+
next = elem.nextSibling ;
|
571
|
+
}
|
572
|
+
|
573
|
+
elem = next ;
|
574
|
+
}
|
575
|
+
}
|
576
|
+
|
577
|
+
return elem;
|
578
|
+
},
|
579
|
+
|
580
|
+
/**
|
581
|
+
This method is invoked whenever a display property changes. It will set
|
582
|
+
the layerNeedsUpdate method to YES.
|
583
|
+
*/
|
584
|
+
displayDidChange: function() {
|
585
|
+
this.set('layerNeedsUpdate', YES) ;
|
586
|
+
},
|
587
|
+
|
588
|
+
/**
|
589
|
+
Setting this property to YES will cause the updateLayerIfNeeded method to
|
590
|
+
be invoked at the end of the runloop. You can also force a view to update
|
591
|
+
sooner by calling updateLayerIfNeeded() directly. The method will update
|
592
|
+
the layer only if this property is YES.
|
593
|
+
|
594
|
+
@property {Boolean}
|
595
|
+
@test in updateLayer
|
596
|
+
*/
|
597
|
+
layerNeedsUpdate: NO,
|
598
|
+
|
599
|
+
/** @private
|
600
|
+
Schedules the updateLayerIfNeeded method to run at the end of the runloop
|
601
|
+
if layerNeedsUpdate is set to YES.
|
602
|
+
*/
|
603
|
+
_view_layerNeedsUpdateDidChange: function() {
|
604
|
+
if (this.get('layerNeedsUpdate')) {
|
605
|
+
this.invokeOnce(this.updateLayerIfNeeded) ;
|
606
|
+
}
|
607
|
+
}.observes('layerNeedsUpdate'),
|
608
|
+
|
609
|
+
/**
|
610
|
+
Updates the layer only if the view is visible onscreen and if
|
611
|
+
layerNeedsUpdate is set to YES. Normally you will not invoke this method
|
612
|
+
directly. Instead you set the layerNeedsUpdate property to YES and this
|
613
|
+
method will be called once at the end of the runloop.
|
614
|
+
|
615
|
+
If you need to update view's layer sooner than the end of the runloop, you
|
616
|
+
can call this method directly. If your view is not visible in the window
|
617
|
+
but you want it to update anyway, then call this method, passing YES for
|
618
|
+
the 'force' parameter.
|
619
|
+
|
620
|
+
You should not override this method. Instead override updateLayer() or
|
621
|
+
render().
|
622
|
+
|
623
|
+
@param {Boolean} isVisible if true assume view is visible even if it is not.
|
624
|
+
@returns {SC.View} receiver
|
625
|
+
@test in updateLayer
|
626
|
+
*/
|
627
|
+
updateLayerIfNeeded: function(isVisible) {
|
628
|
+
if (!isVisible) isVisible = this.get('isVisibleInWindow') ;
|
629
|
+
if (isVisible && this.get('layerNeedsUpdate')) {
|
630
|
+
this.beginPropertyChanges() ;
|
631
|
+
this.set('layerNeedsUpdate', NO) ;
|
632
|
+
this.updateLayer() ;
|
633
|
+
this.endPropertyChanges() ;
|
634
|
+
}
|
635
|
+
return this ;
|
636
|
+
},
|
637
|
+
|
638
|
+
/**
|
639
|
+
This is the core method invoked to update a view layer whenever it has
|
640
|
+
changed. This method simply creates a render context focused on the
|
641
|
+
layer element and then calls your render() method.
|
642
|
+
|
643
|
+
You will not usually call or override this method directly. Instead you
|
644
|
+
should set the layerNeedsUpdate property to YES to cause this method to
|
645
|
+
run at the end of the run loop, or you can call updateLayerIfNeeded()
|
646
|
+
to force the layer to update immediately.
|
647
|
+
|
648
|
+
Instead of overriding this method, consider overidding the render() method
|
649
|
+
instead, which is called both when creating and updating a layer. If you
|
650
|
+
do not want your render() method called when updating a layer, then you
|
651
|
+
should override this method instead.
|
652
|
+
|
653
|
+
@returns {SC.View} receiver
|
654
|
+
*/
|
655
|
+
updateLayer: function() {
|
656
|
+
var context = this.renderContext(this.get('layer')) ;
|
657
|
+
this.prepareContext(context, NO) ;
|
658
|
+
context.update() ;
|
659
|
+
return this ;
|
660
|
+
},
|
661
|
+
|
662
|
+
/**
|
663
|
+
Creates a new renderContext with the passed tagName or element. You
|
664
|
+
can override this method to provide further customization to the context
|
665
|
+
if needed. Normally you will not need to call or override this method.
|
666
|
+
|
667
|
+
@returns {SC.RenderContext}
|
668
|
+
*/
|
669
|
+
renderContext: function(tagNameOrElement) {
|
670
|
+
return SC.RenderContext(tagNameOrElement) ;
|
671
|
+
},
|
672
|
+
|
673
|
+
/**
|
674
|
+
Creates the layer by creating a renderContext and invoking the view's
|
675
|
+
render() method. This will only create the layer if the layer does not
|
676
|
+
already exist.
|
677
|
+
|
678
|
+
When you create a layer, it is expected that your render() method will
|
679
|
+
also render the HTML for all child views as well. This method will
|
680
|
+
notify the view along with any of its childViews that its layer has been
|
681
|
+
created.
|
682
|
+
|
683
|
+
@returns {SC.View} receiver
|
684
|
+
*/
|
685
|
+
createLayer: function() {
|
686
|
+
if (this.get('layer')) return this ; // nothing to do
|
687
|
+
|
688
|
+
var context = this.renderContext(this.get('tagName')) ;
|
689
|
+
|
690
|
+
// now prepare the contet like normal.
|
691
|
+
this.prepareContext(context, YES) ;
|
692
|
+
this.set('layer', context.element()) ;
|
693
|
+
|
694
|
+
// now notify the view and its child views..
|
695
|
+
this._notifyDidCreateLayer() ;
|
696
|
+
|
697
|
+
return this ;
|
698
|
+
},
|
699
|
+
|
700
|
+
/** @private -
|
701
|
+
Invokes the receivers didCreateLayer() method if it exists and then
|
702
|
+
invokes the same on all child views.
|
703
|
+
*/
|
704
|
+
_notifyDidCreateLayer: function() {
|
705
|
+
if (this.didCreateLayer) this.didCreateLayer() ;
|
706
|
+
var mixins = this.didCreateLayerMixin, len, idx ;
|
707
|
+
if (mixins) {
|
708
|
+
len = mixins.length ;
|
709
|
+
for (idx=0; idx<len; ++idx) mixins[idx].call(this) ;
|
710
|
+
}
|
711
|
+
|
712
|
+
var childViews = this.get('childViews') ;
|
713
|
+
len = childViews.length ;
|
714
|
+
for (idx=0; idx<len; ++idx) childViews[idx]._notifyDidCreateLayer() ;
|
715
|
+
},
|
716
|
+
|
717
|
+
/**
|
718
|
+
Destroys any existing layer along with the layer for any child views as
|
719
|
+
well. If the view does not currently have a layer, then this method will
|
720
|
+
do nothing.
|
721
|
+
|
722
|
+
If you implement willDestroyLayer() on your view or if any mixins
|
723
|
+
implement willDestroLayerMixin(), then this method will be invoked on your
|
724
|
+
view before your layer is destroyed to give you a chance to clean up any
|
725
|
+
event handlers, etc.
|
726
|
+
|
727
|
+
If you write a willDestroyLayer() handler, you can assume that your
|
728
|
+
didCreateLayer() handler was called earlier for the same layer.
|
729
|
+
|
730
|
+
Normally you will not call or override this method yourself, but you may
|
731
|
+
want to implement the above callbacks when it is run.
|
732
|
+
|
733
|
+
@returns {SC.View} receiver
|
734
|
+
*/
|
735
|
+
destroyLayer: function() {
|
736
|
+
var layer = this.get('layer') ;
|
737
|
+
if (layer) {
|
738
|
+
// Now notify the view and its child views. It will also set the
|
739
|
+
// layer property to null.
|
740
|
+
this._notifyWillDestroyLayer() ;
|
741
|
+
|
742
|
+
// do final cleanup
|
743
|
+
if (layer.parentNode) layer.parentNode.removeChild(layer) ;
|
744
|
+
layer = null ;
|
745
|
+
}
|
746
|
+
return this ;
|
747
|
+
},
|
748
|
+
|
749
|
+
/** @private -
|
750
|
+
Invokes willDestroyLayer() on view and child views. Then sets layer to
|
751
|
+
null for receiver.
|
752
|
+
*/
|
753
|
+
_notifyWillDestroyLayer: function() {
|
754
|
+
if (this.willDestroyLayer) this.willDestroyLayer() ;
|
755
|
+
var mixins = this.willDestroyLayerMixin, len, idx ;
|
756
|
+
if (mixins) {
|
757
|
+
len = mixins.length ;
|
758
|
+
for (idx=0; idx<len; ++idx) mixins[idx].call(this) ;
|
759
|
+
}
|
760
|
+
|
761
|
+
var childViews = this.get('childViews') ;
|
762
|
+
len = childViews.length ;
|
763
|
+
for (idx=0; idx<len; ++idx) childViews[idx]._notifyWillDestroyLayer() ;
|
764
|
+
|
765
|
+
this.set('layer', null) ;
|
766
|
+
},
|
767
|
+
|
768
|
+
/**
|
769
|
+
Invoked by createLayer() and updateLayer() to actually render a context.
|
770
|
+
This method calls the render() method on your view along with any
|
771
|
+
renderMixin() methods supplied by mixins you might have added.
|
772
|
+
|
773
|
+
You should not override this method directly. However, you might call
|
774
|
+
this method if you choose to override updateLayer() or createLayer().
|
775
|
+
|
776
|
+
@param {SC.RenderContext} context the render context
|
777
|
+
@param {Boolean} firstTime YES if this is creating a layer
|
778
|
+
@returns {void}
|
779
|
+
*/
|
780
|
+
prepareContext: function(context, firstTime) {
|
781
|
+
var mixins, len, idx, layerId, bgcolor, cursor ;
|
782
|
+
|
783
|
+
// do some initial setup only needed at create time.
|
784
|
+
if (firstTime) {
|
785
|
+
// TODO: seems like things will break later if SC.guidFor(this) is used
|
786
|
+
layerId = this.layerId ? this.get('layerId') : SC.guidFor(this) ;
|
787
|
+
context.id(layerId).classNames(this.get('classNames'), YES) ;
|
788
|
+
this.renderLayout(context, firstTime) ;
|
789
|
+
}
|
790
|
+
|
791
|
+
// do some standard setup...
|
792
|
+
if (this.get('isTextSelectable')) context.addClass('allow-select') ;
|
793
|
+
if (!this.get('isEnabled')) context.addClass('disabled') ;
|
794
|
+
if (!this.get('isVisible')) context.addClass('hidden') ;
|
795
|
+
|
796
|
+
bgcolor = this.get('backgroundColor');
|
797
|
+
if (bgcolor) context.addStyle('backgroundColor', bgcolor);
|
798
|
+
|
799
|
+
cursor = this.get('cursor') ;
|
800
|
+
if (cursor) context.addClass(cursor.get('className')) ;
|
801
|
+
|
802
|
+
this.render(context, firstTime) ;
|
803
|
+
if (mixins = this.renderMixin) {
|
804
|
+
len = mixins.length;
|
805
|
+
for(idx=0; idx<len; ++idx) mixins[idx].call(this, context, firstTime) ;
|
806
|
+
}
|
807
|
+
},
|
808
|
+
|
809
|
+
/**
|
810
|
+
Your render method should invoke this method to render any child views,
|
811
|
+
especially if this is the first time the view will be rendered. This will
|
812
|
+
walk down the childView chain, rendering all of the children in a nested
|
813
|
+
way.
|
814
|
+
|
815
|
+
@param {SC.RenderContext} context the context
|
816
|
+
@param {Boolean} firstName true if the layer is being created
|
817
|
+
@returns {SC.RenderContext} the render context
|
818
|
+
@test in render
|
819
|
+
*/
|
820
|
+
renderChildViews: function(context, firstTime) {
|
821
|
+
var cv = this.get('childViews'), len = cv.length, idx, view ;
|
822
|
+
for (idx=0; idx<len; ++idx) {
|
823
|
+
view = cv[idx] ;
|
824
|
+
context = context.begin(view.get('tagName')) ;
|
825
|
+
view.prepareContext(context, firstTime) ;
|
826
|
+
context = context.end() ;
|
827
|
+
}
|
828
|
+
return context ;
|
829
|
+
},
|
830
|
+
|
831
|
+
/**
|
832
|
+
Invoked whenever your view needs to be rendered, including when the view's
|
833
|
+
layer is first created and any time in the future when it needs to be
|
834
|
+
updated.
|
835
|
+
|
836
|
+
You will normally override this method in your subclassed views to
|
837
|
+
provide whatever drawing functionality you will need in order to
|
838
|
+
render your content.
|
839
|
+
|
840
|
+
You can use the passed firstTime property to determine whether or not
|
841
|
+
you need to completely re-render the view or only update the surrounding
|
842
|
+
HTML.
|
843
|
+
|
844
|
+
The default implementation of this method simply calls renderChildViews()
|
845
|
+
if this is the first time you are rendering, or null otherwise.
|
846
|
+
|
847
|
+
@param {SC.RenderContext} context the render context
|
848
|
+
@param {Boolean} firstTime YES if this is creating a layer
|
849
|
+
@returns {void}
|
850
|
+
*/
|
851
|
+
render: function(context, firstTime) {
|
852
|
+
if (firstTime) this.renderChildViews(context, firstTime) ;
|
853
|
+
},
|
854
|
+
|
855
|
+
// ..........................................................
|
856
|
+
// STANDARD RENDER PROPERTIES
|
857
|
+
//
|
858
|
+
|
859
|
+
/**
|
860
|
+
Tag name for the view's outer element. The tag name is only used when
|
861
|
+
a layer is first created. If you change the tagName for an element, you
|
862
|
+
must destroy and recreate the view layer.
|
863
|
+
|
864
|
+
@property {String}
|
865
|
+
*/
|
866
|
+
tagName: 'div',
|
867
|
+
|
868
|
+
/**
|
869
|
+
Standard CSS class names to apply to the view's outer element. This
|
870
|
+
property automatically inherits any class names defined by the view's
|
871
|
+
superclasses as well.
|
872
|
+
|
873
|
+
@property {Array}
|
874
|
+
*/
|
875
|
+
classNames: ['sc-view'],
|
876
|
+
|
877
|
+
/**
|
878
|
+
Determines if the user can select text within the view. Normally this is
|
879
|
+
set to NO to disable text selection. You should set this to YES if you
|
880
|
+
are creating a view that includes editable text. Otherwise, settings this
|
881
|
+
to YES will probably make your controls harder to use and it is not
|
882
|
+
recommended.
|
883
|
+
|
884
|
+
@property {Boolean}
|
885
|
+
@readOnly
|
886
|
+
*/
|
887
|
+
isTextSelectable: NO,
|
888
|
+
|
889
|
+
/**
|
890
|
+
You can set this array to include any properties that should immediately
|
891
|
+
invalidate the display. The display will be automatically invalidated
|
892
|
+
when one of these properties change.
|
893
|
+
|
894
|
+
@property {Array}
|
895
|
+
@readOnly
|
896
|
+
*/
|
897
|
+
displayProperties: [],
|
898
|
+
|
899
|
+
/**
|
900
|
+
You can set this to an SC.Cursor instance; it's className will
|
901
|
+
automatically be added to the layer's classNames. The cursor is only used
|
902
|
+
when a layer is first created. If you change the cursor for an element,
|
903
|
+
you must destroy and recreate the view layer.
|
904
|
+
|
905
|
+
@property {SC.Cursor}
|
906
|
+
*/
|
907
|
+
cursor: null,
|
908
|
+
|
909
|
+
// ..........................................................
|
910
|
+
// LAYER LOCATION
|
911
|
+
//
|
912
|
+
|
913
|
+
/**
|
914
|
+
Set to YES when the view's layer location is dirty. You can call
|
915
|
+
updateLayerLocationIfNeeded() to clear this flag if it is set.
|
916
|
+
|
917
|
+
@property {Boolean}
|
918
|
+
*/
|
919
|
+
layerLocationNeedsUpdate: NO,
|
920
|
+
|
921
|
+
/**
|
922
|
+
Calls updateLayerLocation(), but only if the view's layer location
|
923
|
+
currently needs to be updated. This method is called automatically at
|
924
|
+
the end of a run loop if you have called parentViewDidChange() at some
|
925
|
+
point.
|
926
|
+
|
927
|
+
@property {Boolean} force This property is ignored.
|
928
|
+
@returns {SC.View} receiver
|
929
|
+
@test in updateLayerLocation
|
930
|
+
*/
|
931
|
+
updateLayerLocationIfNeeded: function(force) {
|
932
|
+
if (this.get('layerLocationNeedsUpdate')) {
|
933
|
+
this.set('layerLocationNeedsUpdate', NO) ;
|
934
|
+
this.updateLayerLocation() ;
|
935
|
+
}
|
936
|
+
return this ;
|
937
|
+
},
|
938
|
+
|
939
|
+
/**
|
940
|
+
This method is called when a view changes its location in the view
|
941
|
+
hierarchy. This method will update the underlying DOM-location of the
|
942
|
+
layer so that it reflects the new location.
|
943
|
+
|
944
|
+
@returns {SC.View} receiver
|
945
|
+
*/
|
946
|
+
updateLayerLocation: function() {
|
947
|
+
// collect some useful value
|
948
|
+
// if there is no node for some reason, just exit
|
949
|
+
var node = this.get('layer') ;
|
950
|
+
var parentView = this.get('parentView') ;
|
951
|
+
var parentNode = parentView ? parentView.get('containerLayer') : null ;
|
952
|
+
|
953
|
+
// remove node from current parentNode if the node does not match the new
|
954
|
+
// parent node.
|
955
|
+
if (node && node.parentNode && node.parentNode !== parentNode) {
|
956
|
+
node.parentNode.removeChild(node);
|
957
|
+
}
|
958
|
+
|
959
|
+
// CASE 1: no new parentView. just remove from parent (above).
|
960
|
+
if (!parentView) {
|
961
|
+
if (node && node.parentNode) node.parentNode.removeChild(node);
|
962
|
+
|
963
|
+
// CASE 2: parentView has no layer, view has layer. destroy layer
|
964
|
+
// CASE 3: parentView has no layer, view has no layer, nothing to do
|
965
|
+
} else if (!parentNode) {
|
966
|
+
if (node) {
|
967
|
+
if (node.parentNode) node.parentNode.removeChild(node);
|
968
|
+
this.destroyLayer();
|
969
|
+
}
|
970
|
+
|
971
|
+
// CASE 4: parentView has layer, view has no layer. create layer & add
|
972
|
+
// CASE 5: parentView has layer, view has layer. move layer
|
973
|
+
} else {
|
974
|
+
if (!node) {
|
975
|
+
this.createLayer() ;
|
976
|
+
node = this.get('layer') ;
|
977
|
+
}
|
978
|
+
|
979
|
+
var siblings = parentView.get('childViews') ;
|
980
|
+
var nextView = siblings.objectAt(siblings.indexOf(this)+1) ;
|
981
|
+
var nextNode = (nextView) ? nextView.get('layer') : null ;
|
982
|
+
|
983
|
+
// before we add to parent node, make sure that the nextNode exists...
|
984
|
+
if (nextView && !nextNode) {
|
985
|
+
nextView.updateLayerLocationIfNeeded() ;
|
986
|
+
nextNode = nextView.get('layer') ;
|
987
|
+
}
|
988
|
+
|
989
|
+
// add to parentNode if needed. If we do add, then also notify view
|
990
|
+
// that its parentView has resized since joining a parentView has the
|
991
|
+
// same effect.
|
992
|
+
if ((node.parentNode!==parentNode) || (node.nextSibling!==nextNode)) {
|
993
|
+
parentNode.insertBefore(node, nextNode) ;
|
994
|
+
if (this.parentViewDidResize) this.parentViewDidResize() ;
|
995
|
+
}
|
996
|
+
}
|
997
|
+
|
998
|
+
parentNode = parentView = node = null ; // avoid memory leaks
|
999
|
+
return this ;
|
1000
|
+
},
|
1001
|
+
|
1002
|
+
// .......................................................
|
1003
|
+
// SC.RESPONDER SUPPORT
|
1004
|
+
//
|
1005
|
+
|
1006
|
+
/** @property
|
1007
|
+
The nextResponder is usually the parentView.
|
1008
|
+
*/
|
1009
|
+
nextResponder: function() {
|
1010
|
+
return this.get('parentView');
|
1011
|
+
}.property('parentView').cacheable(),
|
1012
|
+
|
1013
|
+
/**
|
1014
|
+
Recursively travels down the view hierarchy looking for a view that
|
1015
|
+
implements the key equivalent (returning to YES to indicate it handled
|
1016
|
+
the event). You can override this method to handle specific key
|
1017
|
+
equivalents yourself.
|
1018
|
+
|
1019
|
+
The keystring is a string description of the key combination pressed.
|
1020
|
+
The evt is the event itself. If you handle the equivalent, return YES.
|
1021
|
+
Otherwise, you should just return sc_super.
|
1022
|
+
|
1023
|
+
@param {String} keystring
|
1024
|
+
@param {SC.Event} evt
|
1025
|
+
@returns {Boolean}
|
1026
|
+
*/
|
1027
|
+
performKeyEquivalent: function(keystring, evt) {
|
1028
|
+
var ret = null, childViews = this.get('childViews'), len = childViews.length, idx=-1;
|
1029
|
+
while(!ret && (++idx<len)) {
|
1030
|
+
ret = childViews[idx].performKeyEquivalent(keystring, evt);
|
1031
|
+
}
|
1032
|
+
return ret ;
|
1033
|
+
},
|
1034
|
+
|
1035
|
+
// .......................................................
|
1036
|
+
// CORE DISPLAY METHODS
|
1037
|
+
//
|
1038
|
+
|
1039
|
+
/** @private
|
1040
|
+
Setup a view, but do not finish waking it up.
|
1041
|
+
- configure childViews
|
1042
|
+
- generate DOM + plug in outlets/childViews unless rootElement is defined
|
1043
|
+
- register the view with the global views hash, which is used for mgmt
|
1044
|
+
*/
|
1045
|
+
init: function() {
|
1046
|
+
var parentView, path, root, idx, len, lp, dp ;
|
1047
|
+
|
1048
|
+
sc_super() ;
|
1049
|
+
|
1050
|
+
// register for event handling now if we're not a materialized view
|
1051
|
+
// (materialized views register themselves as needed)
|
1052
|
+
if (!this.get('isMaterialized')) {
|
1053
|
+
SC.View.views[this.get('layerId')] = this ;
|
1054
|
+
}
|
1055
|
+
|
1056
|
+
// setup child views. be sure to clone the child views array first
|
1057
|
+
this.childViews = this.childViews ? this.childViews.slice() : [] ;
|
1058
|
+
this.createChildViews() ; // setup child Views
|
1059
|
+
|
1060
|
+
// register display property observers ..
|
1061
|
+
// TODO: Optimize into class setup
|
1062
|
+
dp = this.get('displayProperties') ;
|
1063
|
+
idx = dp.length ;
|
1064
|
+
while(--idx >= 0) {
|
1065
|
+
this.addObserver(dp[idx], this, this.displayDidChange) ;
|
1066
|
+
}
|
1067
|
+
|
1068
|
+
// register for drags
|
1069
|
+
if (this.get('isDropTarget')) SC.Drag.addDropTarget(this) ;
|
1070
|
+
|
1071
|
+
// register scroll views for autoscroll during drags
|
1072
|
+
if (this.get('isScrollable')) SC.Drag.addScrollableView(this) ;
|
1073
|
+
},
|
1074
|
+
|
1075
|
+
/**
|
1076
|
+
Wakes up the view. The default implementation immediately syncs any
|
1077
|
+
bindings, which may cause the view to need its display updated. You
|
1078
|
+
can override this method to perform any additional setup. Be sure to
|
1079
|
+
call sc_super to setup bindings and to call awake on childViews.
|
1080
|
+
|
1081
|
+
It is best to awake a view before you add it to the DOM. This way when
|
1082
|
+
the DOM is generated, it will have the correct initial values and will
|
1083
|
+
not require any additional setup.
|
1084
|
+
|
1085
|
+
@returns {void}
|
1086
|
+
*/
|
1087
|
+
awake: function() {
|
1088
|
+
sc_super();
|
1089
|
+
var childViews = this.get('childViews'), len = childViews.length, idx ;
|
1090
|
+
for (idx=0; idx<len; ++idx) childViews[idx].awake() ;
|
1091
|
+
},
|
1092
|
+
|
1093
|
+
/**
|
1094
|
+
You must call this method on a view to destroy the view (and all of its
|
1095
|
+
child views). This will remove the view from any parent node, then make
|
1096
|
+
sure that the DOM element managed by the view can be released by the
|
1097
|
+
memory manager.
|
1098
|
+
*/
|
1099
|
+
destroy: function() {
|
1100
|
+
if (this.get('isDestroyed')) return this; // nothing to do
|
1101
|
+
|
1102
|
+
sc_super();
|
1103
|
+
|
1104
|
+
// remove from parent if found
|
1105
|
+
this.removeFromParent() ;
|
1106
|
+
this._destroy(); // core destroy method
|
1107
|
+
|
1108
|
+
// unregister for drags
|
1109
|
+
if (this.get('isDropTarget')) SC.Drag.removeDropTarget(this) ;
|
1110
|
+
|
1111
|
+
// unregister for autoscroll during drags
|
1112
|
+
if (this.get('isScrollable')) SC.Drag.removeScrollableView(this) ;
|
1113
|
+
return this; // done with cleanup
|
1114
|
+
},
|
1115
|
+
|
1116
|
+
_destroy: function() {
|
1117
|
+
if (this.get('isDestroyed')) return this ; // nothing to do
|
1118
|
+
|
1119
|
+
// destroy the layer -- this will avoid each child view destroying
|
1120
|
+
// the layer over and over again...
|
1121
|
+
this.destroyLayer() ;
|
1122
|
+
|
1123
|
+
// first destroy any children.
|
1124
|
+
var childViews = this.get('childViews'), len = childViews.length, idx ;
|
1125
|
+
if (len) {
|
1126
|
+
childViews = childViews.slice() ;
|
1127
|
+
for (idx=0; idx<len; ++idx) childViews[idx]._destroy() ;
|
1128
|
+
}
|
1129
|
+
|
1130
|
+
// next remove view from global hash
|
1131
|
+
delete SC.View.views[this.get('layerId')] ;
|
1132
|
+
delete this._CQ ;
|
1133
|
+
delete this.page ;
|
1134
|
+
|
1135
|
+
// mark as destroyed so we don't do this again
|
1136
|
+
this.set('isDestroyed', YES) ;
|
1137
|
+
return this ;
|
1138
|
+
},
|
1139
|
+
|
1140
|
+
/**
|
1141
|
+
This method is called when your view is first created to setup any child
|
1142
|
+
views that are already defined on your class. If any are found, it will
|
1143
|
+
instantiate them for you.
|
1144
|
+
|
1145
|
+
The default implementation of this method simply steps through your
|
1146
|
+
childViews array, which is expects to either be empty or to contain View
|
1147
|
+
designs that can be instantiated
|
1148
|
+
|
1149
|
+
Alternatively, you can implement this method yourself in your own
|
1150
|
+
subclasses to look for views defined on specific properties and then build
|
1151
|
+
a childViews array yourself.
|
1152
|
+
|
1153
|
+
Note that when you implement this method yourself, you should never
|
1154
|
+
instantiate views directly. Instead, you should use
|
1155
|
+
this.createChildView() method instead. This method can be much faster in
|
1156
|
+
a production environment than creating views yourself.
|
1157
|
+
|
1158
|
+
@returns {SC.View} receiver
|
1159
|
+
*/
|
1160
|
+
createChildViews: function() {
|
1161
|
+
var childViews = this.get('childViews'),
|
1162
|
+
len = childViews.length,
|
1163
|
+
idx, key, views, view ;
|
1164
|
+
|
1165
|
+
this.beginPropertyChanges() ;
|
1166
|
+
|
1167
|
+
// swap the array
|
1168
|
+
for (idx=0; idx<len; ++idx) {
|
1169
|
+
if (key = (view = childViews[idx])) {
|
1170
|
+
|
1171
|
+
// is this is a key name, lookup view class
|
1172
|
+
if (typeof key === SC.T_STRING) {
|
1173
|
+
view = this[key];
|
1174
|
+
} else key = null ;
|
1175
|
+
|
1176
|
+
if (view.isClass) {
|
1177
|
+
view = this.createChildView(view) ; // instantiate if needed
|
1178
|
+
if (key) this[key] = view ; // save on key name if passed
|
1179
|
+
}
|
1180
|
+
}
|
1181
|
+
childViews[idx] = view;
|
1182
|
+
}
|
1183
|
+
|
1184
|
+
this.endPropertyChanges() ;
|
1185
|
+
return this ;
|
1186
|
+
},
|
1187
|
+
|
1188
|
+
/**
|
1189
|
+
Instantiates a view to be added to the childViews array during view
|
1190
|
+
initialization. You generally will not call this method directly unless
|
1191
|
+
you are overriding createChildViews(). Note that this method will
|
1192
|
+
automatically configure the correct settings on the new view instance to
|
1193
|
+
act as a child of the parent.
|
1194
|
+
|
1195
|
+
@param {Class} viewClass
|
1196
|
+
@param {Hash} attrs optional attributes to add
|
1197
|
+
@returns {SC.View} new instance
|
1198
|
+
@test in createChildViews
|
1199
|
+
*/
|
1200
|
+
createChildView: function(view, attrs) {
|
1201
|
+
// attrs should always exist...
|
1202
|
+
if (!attrs) attrs = {} ;
|
1203
|
+
attrs.owner = attrs.parentView = this ;
|
1204
|
+
if (!attrs.page) attrs.page = this.page ;
|
1205
|
+
|
1206
|
+
// Now add this to the attributes and create.
|
1207
|
+
view = view.create(attrs) ;
|
1208
|
+
return view ;
|
1209
|
+
},
|
1210
|
+
|
1211
|
+
// ...........................................
|
1212
|
+
// LAYOUT
|
1213
|
+
//
|
1214
|
+
|
1215
|
+
/**
|
1216
|
+
This convenience method will take the current layout, apply any changes
|
1217
|
+
you pass and set it again. It is more convenient than having to do this
|
1218
|
+
yourself sometimes.
|
1219
|
+
|
1220
|
+
You can pass just a key/value pair or a hash with several pairs. You can
|
1221
|
+
also pass a null value to delete a property.
|
1222
|
+
|
1223
|
+
This method will avoid actually setting the layout if the value you pass
|
1224
|
+
does not edit the layout.
|
1225
|
+
|
1226
|
+
@param {String|Hash} key
|
1227
|
+
@param {Object} value
|
1228
|
+
@returns {SC.View} receiver
|
1229
|
+
*/
|
1230
|
+
adjust: function(key, value) {
|
1231
|
+
var layout = SC.clone(this.get('layout')), didChange = NO, cur ;
|
1232
|
+
|
1233
|
+
if (key === undefined) return this ; // nothing to do.
|
1234
|
+
|
1235
|
+
// handle string case
|
1236
|
+
if (SC.typeOf(key) === SC.T_STRING) {
|
1237
|
+
cur = layout[key] ;
|
1238
|
+
if (SC.none(value)) {
|
1239
|
+
if (cur !== undefined) didChange = YES ;
|
1240
|
+
delete layout[key] ;
|
1241
|
+
} else {
|
1242
|
+
if (cur !== value) didChange = YES ;
|
1243
|
+
layout[key] = value ;
|
1244
|
+
}
|
1245
|
+
|
1246
|
+
// handle hash -- do it this way to avoid creating memory unless needed
|
1247
|
+
} else {
|
1248
|
+
var hash = key;
|
1249
|
+
for(key in hash) {
|
1250
|
+
if (!hash.hasOwnProperty(key)) continue;
|
1251
|
+
value = hash[key] ;
|
1252
|
+
cur = layout[key] ;
|
1253
|
+
|
1254
|
+
if (value === null) {
|
1255
|
+
if (cur !== undefined) didChange = YES ;
|
1256
|
+
delete layout[key] ;
|
1257
|
+
} else if (value !== undefined) {
|
1258
|
+
if (cur !== value) didChange = YES ;
|
1259
|
+
layout[key] = value ;
|
1260
|
+
}
|
1261
|
+
}
|
1262
|
+
}
|
1263
|
+
|
1264
|
+
// if (didChange) {
|
1265
|
+
// console.log('did change layout') ;
|
1266
|
+
// console.log(layout) ;
|
1267
|
+
// }
|
1268
|
+
|
1269
|
+
// now set adjusted layout
|
1270
|
+
if (didChange) this.set('layout', layout) ;
|
1271
|
+
|
1272
|
+
return this ;
|
1273
|
+
},
|
1274
|
+
|
1275
|
+
/**
|
1276
|
+
The layout describes how you want your view to be positions on the
|
1277
|
+
screen. You can define the following properties:
|
1278
|
+
|
1279
|
+
- left: the left edge
|
1280
|
+
- top: the top edge
|
1281
|
+
- right: the right edge
|
1282
|
+
- bottom: the bottom edge
|
1283
|
+
- height: the height
|
1284
|
+
- width: the width
|
1285
|
+
- centerX: an offset from center X
|
1286
|
+
- centerY: an offset from center Y
|
1287
|
+
- minWidth: a minimum width
|
1288
|
+
- minHeight: a minimum height
|
1289
|
+
- maxWidth: a maximum width
|
1290
|
+
- maxHeight: a maximum height
|
1291
|
+
|
1292
|
+
Note that you can only use certain combinations to set layout. For
|
1293
|
+
example, you may set left/right or left/width, but not left/width/right,
|
1294
|
+
since that combination doesn't make sense.
|
1295
|
+
|
1296
|
+
Likewise, you may set a minWidth/minHeight, or maxWidth/maxHeight, but
|
1297
|
+
if you also set the width/height explicitly, then those constraints won't
|
1298
|
+
matter as much.
|
1299
|
+
|
1300
|
+
Layout is designed to maximize reliance on the browser's rendering
|
1301
|
+
engine to keep your app up to date.
|
1302
|
+
|
1303
|
+
@test in layoutStyle
|
1304
|
+
*/
|
1305
|
+
layout: { top: 0, left: 0, bottom: 0, right: 0 },
|
1306
|
+
|
1307
|
+
/**
|
1308
|
+
Converts a frame from the receiver's offset to the target offset. Both
|
1309
|
+
the receiver and the target must belong to the same pane. If you pass
|
1310
|
+
null, the conversion will be to the pane level.
|
1311
|
+
|
1312
|
+
Note that the context of a view's frame is the view's parent frame. In
|
1313
|
+
other words, if you want to convert the frame of your view to the global
|
1314
|
+
frame, then you should do:
|
1315
|
+
|
1316
|
+
{{{
|
1317
|
+
var pv = this.get('parentView'), frame = this.get('frame');
|
1318
|
+
var newFrame = pv ? pv.convertFrameToView(frame, null) : frame;
|
1319
|
+
}}}
|
1320
|
+
|
1321
|
+
@param {Rect} frame the source frame
|
1322
|
+
@param {SC.View} targetView the target view to convert to
|
1323
|
+
@returns {Rect} converted frame
|
1324
|
+
@test in converFrames
|
1325
|
+
*/
|
1326
|
+
convertFrameToView: function(frame, targetView) {
|
1327
|
+
var myX=0, myY=0, targetX=0, targetY=0, view = this, f ;
|
1328
|
+
|
1329
|
+
// walk up this side
|
1330
|
+
while (view) {
|
1331
|
+
f = view.get('frame'); myX += f.x; myY += f.y ;
|
1332
|
+
view = view.get('parentView') ;
|
1333
|
+
}
|
1334
|
+
|
1335
|
+
// walk up other size
|
1336
|
+
if (targetView) {
|
1337
|
+
view = targetView ;
|
1338
|
+
while (view) {
|
1339
|
+
f = view.get('frame'); targetX += f.x; targetY += f.y ;
|
1340
|
+
view = view.get('parentView') ;
|
1341
|
+
}
|
1342
|
+
}
|
1343
|
+
|
1344
|
+
// now we can figure how to translate the origin.
|
1345
|
+
myX = frame.x + myX - targetX ;
|
1346
|
+
myY = frame.y + myY - targetY ;
|
1347
|
+
return { x: myX, y: myY, width: frame.width, height: frame.height } ;
|
1348
|
+
},
|
1349
|
+
|
1350
|
+
/**
|
1351
|
+
Converts a frame offset in the coordinates of another view system to the
|
1352
|
+
reciever's view.
|
1353
|
+
|
1354
|
+
Note that the convext of a view's frame is relative to the view's
|
1355
|
+
parentFrame. For example, if you want to convert the frame of view that
|
1356
|
+
belongs to another view to the receiver's frame you would do:
|
1357
|
+
|
1358
|
+
{{{
|
1359
|
+
var frame = view.get('frame');
|
1360
|
+
var newFrame = this.convertFrameFromView(frame, view.get('parentView'));
|
1361
|
+
}}}
|
1362
|
+
|
1363
|
+
@param {Rect} frame the source frame
|
1364
|
+
@param {SC.View} targetView the target view to convert to
|
1365
|
+
@returns {Rect} converted frame
|
1366
|
+
@test in converFrames
|
1367
|
+
*/
|
1368
|
+
convertFrameFromView: function(frame, targetView) {
|
1369
|
+
var myX=0, myY=0, targetX=0, targetY=0, view = this, next, f ;
|
1370
|
+
|
1371
|
+
// walk up this side
|
1372
|
+
while (view) {
|
1373
|
+
f = view.get('frame'); myX += f.x; myY += f.y ;
|
1374
|
+
view = view.get('parentView') ;
|
1375
|
+
}
|
1376
|
+
|
1377
|
+
// walk up other size
|
1378
|
+
if (targetView) {
|
1379
|
+
view = targetView ;
|
1380
|
+
while(view) {
|
1381
|
+
f = view.get('frame'); targetX += f.x; targetY += f.y ;
|
1382
|
+
view = view.get('parentView') ;
|
1383
|
+
}
|
1384
|
+
}
|
1385
|
+
|
1386
|
+
// now we can figure how to translate the origin.
|
1387
|
+
myX = frame.x - myX + targetX ;
|
1388
|
+
myY = frame.y - myY + targetY ;
|
1389
|
+
return { x: myX, y: myY, width: frame.width, height: frame.height } ;
|
1390
|
+
},
|
1391
|
+
|
1392
|
+
/**
|
1393
|
+
Frame describes the current bounding rect for your view. This is always
|
1394
|
+
measured from the top-left corner of the parent view.
|
1395
|
+
|
1396
|
+
@property {Rect}
|
1397
|
+
@test in layoutStyle
|
1398
|
+
*/
|
1399
|
+
frame: function() {
|
1400
|
+
return this.computeFrameWithParentFrame(null) ;
|
1401
|
+
}.property().cacheable(),
|
1402
|
+
|
1403
|
+
/**
|
1404
|
+
Computes what the frame of this view would be if the parent were resized
|
1405
|
+
to the passed dimensions. You can use this method to project the size of
|
1406
|
+
a frame based on the resize behavior of the parent.
|
1407
|
+
|
1408
|
+
This method is used especially by the scroll view to automatically
|
1409
|
+
calculate when scrollviews should be visible.
|
1410
|
+
|
1411
|
+
Passing null for the parent dimensions will use the actual current
|
1412
|
+
parent dimensions. This is the same method used to calculate the current
|
1413
|
+
frame when it changes.
|
1414
|
+
|
1415
|
+
@param {Rect} pdim the projected parent dimensions
|
1416
|
+
@returns {Rect} the computed frame
|
1417
|
+
*/
|
1418
|
+
computeFrameWithParentFrame: function(pdim) {
|
1419
|
+
var layout = this.get('layout') ;
|
1420
|
+
var f = {} ;
|
1421
|
+
|
1422
|
+
// handle left aligned and left/right
|
1423
|
+
if (!SC.none(layout.left)) {
|
1424
|
+
f.x = Math.floor(layout.left) ;
|
1425
|
+
if (layout.width !== undefined) {
|
1426
|
+
f.width = Math.floor(layout.width) ;
|
1427
|
+
} else { // better have layout.right!
|
1428
|
+
if (!pdim) pdim = this.computeParentDimensions(layout) ;
|
1429
|
+
f.width = Math.floor(pdim.width - f.x - (layout.right || 0)) ;
|
1430
|
+
}
|
1431
|
+
|
1432
|
+
// handle right aligned
|
1433
|
+
} else if (!SC.none(layout.right)) {
|
1434
|
+
if (!pdim) pdim = this.computeParentDimensions(layout) ;
|
1435
|
+
if (SC.none(layout.width)) {
|
1436
|
+
f.width = pdim.width - layout.right ;
|
1437
|
+
f.x = 0 ;
|
1438
|
+
} else {
|
1439
|
+
f.width = Math.floor(layout.width || 0) ;
|
1440
|
+
f.x = Math.floor(pdim.width - layout.right - f.width) ;
|
1441
|
+
}
|
1442
|
+
|
1443
|
+
// handle centered
|
1444
|
+
} else if (!SC.none(layout.centerX)) {
|
1445
|
+
if (!pdim) pdim = this.computeParentDimensions(layout) ;
|
1446
|
+
f.width = Math.floor(layout.width || 0) ;
|
1447
|
+
f.x = Math.floor((pdim.width - f.width)/2 + layout.centerX) ;
|
1448
|
+
} else {
|
1449
|
+
f.x = 0 ; // fallback
|
1450
|
+
if (SC.none(layout.width)) {
|
1451
|
+
if (!pdim) pdim = this.computeParentDimensions(layout) ;
|
1452
|
+
f.width = Math.floor(pdim.width) ;
|
1453
|
+
} else f.width = layout.width ;
|
1454
|
+
}
|
1455
|
+
|
1456
|
+
// handle top aligned and top/bottom
|
1457
|
+
if (!SC.none(layout.top)) {
|
1458
|
+
f.y = Math.floor(layout.top) ;
|
1459
|
+
if (layout.height !== undefined) {
|
1460
|
+
f.height = Math.floor(layout.height) ;
|
1461
|
+
} else { // better have layout.bottm!
|
1462
|
+
if (!pdim) pdim = this.computeParentDimensions(layout) ;
|
1463
|
+
f.height = Math.floor(pdim.height - f.y - (layout.bottom || 0)) ;
|
1464
|
+
}
|
1465
|
+
|
1466
|
+
// handle bottom aligned
|
1467
|
+
} else if (!SC.none(layout.bottom)) {
|
1468
|
+
if (!pdim) pdim = this.computeParentDimensions(layout) ;
|
1469
|
+
if (SC.none(layout.height)) {
|
1470
|
+
f.height = pdim.height - layout.bottom ;
|
1471
|
+
f.y = 0 ;
|
1472
|
+
} else {
|
1473
|
+
f.height = Math.floor(layout.height || 0) ;
|
1474
|
+
f.y = Math.floor(pdim.height - layout.bottom - f.height) ;
|
1475
|
+
}
|
1476
|
+
|
1477
|
+
// handle centered
|
1478
|
+
} else if (!SC.none(layout.centerY)) {
|
1479
|
+
if (!pdim) pdim = this.computeParentDimensions(layout) ;
|
1480
|
+
f.height = Math.floor(layout.height || 0) ;
|
1481
|
+
f.y = Math.floor((pdim.height - f.height)/2 + layout.centerY) ;
|
1482
|
+
|
1483
|
+
// fallback
|
1484
|
+
} else {
|
1485
|
+
f.y = 0 ; // fallback
|
1486
|
+
if (SC.none(layout.height)) {
|
1487
|
+
if (!pdim) pdim = this.computeParentDimensions(layout) ;
|
1488
|
+
f.height = Math.floor(pdim.height) ;
|
1489
|
+
} else f.height = layout.height;
|
1490
|
+
}
|
1491
|
+
|
1492
|
+
// make sure the width/height fix min/max...
|
1493
|
+
if (!SC.none(layout.maxHeight) && (f.height > layout.maxHeight)) {
|
1494
|
+
f.height = layout.maxHeight ;
|
1495
|
+
}
|
1496
|
+
|
1497
|
+
if (!SC.none(layout.minHeight) && (f.height < layout.minHeight)) {
|
1498
|
+
f.height = layout.minHeight ;
|
1499
|
+
}
|
1500
|
+
|
1501
|
+
if (!SC.none(layout.maxWidth) && (f.width > layout.maxWidth)) {
|
1502
|
+
f.width = layout.maxWidth ;
|
1503
|
+
}
|
1504
|
+
|
1505
|
+
if (!SC.none(layout.minWidth) && (f.width < layout.minWidth)) {
|
1506
|
+
f.width = layout.minWidth ;
|
1507
|
+
}
|
1508
|
+
|
1509
|
+
// make sure width/height are never < 0
|
1510
|
+
if (f.height < 0) f.height = 0 ;
|
1511
|
+
if (f.width < 0) f.width = 0 ;
|
1512
|
+
|
1513
|
+
return f;
|
1514
|
+
},
|
1515
|
+
|
1516
|
+
computeParentDimensions: function(frame) {
|
1517
|
+
var ret, pv = this.get('parentView'), pf = (pv) ? pv.get('frame') : null ;
|
1518
|
+
|
1519
|
+
if (pf) {
|
1520
|
+
ret = { width: pf.width, height: pf.height };
|
1521
|
+
} else {
|
1522
|
+
var f = frame ;
|
1523
|
+
ret = {
|
1524
|
+
width: (f.left || 0) + (f.width || 0) + (f.right || 0),
|
1525
|
+
height: (f.top || 0) + (f.height || 0) + (f.bottom || 0)
|
1526
|
+
};
|
1527
|
+
}
|
1528
|
+
return ret ;
|
1529
|
+
},
|
1530
|
+
|
1531
|
+
/**
|
1532
|
+
The clipping frame returns the visible portion of the view, taking into
|
1533
|
+
account the clippingFrame of the parent view. Keep in mind that the
|
1534
|
+
clippingFrame is in the context of the view itself, not it's parent view.
|
1535
|
+
|
1536
|
+
Normally this will be calculate based on the intersection of your own
|
1537
|
+
clippingFrame and your parentView's clippingFrame.
|
1538
|
+
|
1539
|
+
@property {Rect}
|
1540
|
+
*/
|
1541
|
+
clippingFrame: function() {
|
1542
|
+
var pv= this.get('parentView'), f = this.get('frame'), ret = f ;
|
1543
|
+
if (pv) {
|
1544
|
+
pv = pv.get('clippingFrame') ;
|
1545
|
+
ret = SC.intersectRects(pv, f) ;
|
1546
|
+
}
|
1547
|
+
ret.x -= f.x ;
|
1548
|
+
ret.y -= f.y ;
|
1549
|
+
return ret ;
|
1550
|
+
}.property('parentView', 'frame').cacheable(),
|
1551
|
+
|
1552
|
+
/** @private
|
1553
|
+
Whenever the clippingFrame changes, this observer will fire, notifying
|
1554
|
+
child views that their frames have also changed.
|
1555
|
+
*/
|
1556
|
+
_sc_view_clippingFrameDidChange: function() {
|
1557
|
+
var cvs = this.get('childViews'), len = cvs.length, idx, cv ;
|
1558
|
+
for (idx=0; idx<len; ++idx) {
|
1559
|
+
cv = cvs[idx] ;
|
1560
|
+
if (!cv.hasStaticLayout) cv.notifyPropertyChange('clippingFrame') ;
|
1561
|
+
}
|
1562
|
+
}.observes('clippingFrame'),
|
1563
|
+
|
1564
|
+
/**
|
1565
|
+
This method may be called on your view whenever the parent view resizes.
|
1566
|
+
|
1567
|
+
The default version of this method will reset the frame and then call
|
1568
|
+
viewDidResize(). You will not usually override this method, but you may
|
1569
|
+
override the viewDidResize() method.
|
1570
|
+
|
1571
|
+
@returns {void}
|
1572
|
+
@test in viewDidResize
|
1573
|
+
*/
|
1574
|
+
parentViewDidResize: function() {
|
1575
|
+
var layout = this.get('layout') ;
|
1576
|
+
|
1577
|
+
// only resizes if the layout does something other than left/top - fixed
|
1578
|
+
// size.
|
1579
|
+
var isFixed = (
|
1580
|
+
(layout.left !== undefined) && (layout.top !== undefined) &&
|
1581
|
+
(layout.width !== undefined) && (layout.height !== undefined)
|
1582
|
+
);
|
1583
|
+
|
1584
|
+
if (!isFixed) {
|
1585
|
+
this.notifyPropertyChange('frame') ;
|
1586
|
+
this.viewDidResize() ;
|
1587
|
+
}
|
1588
|
+
},
|
1589
|
+
|
1590
|
+
/**
|
1591
|
+
This method is invoked on your view when the view resizes due to a layout
|
1592
|
+
change or due to the parent view resizing. You can override this method
|
1593
|
+
to implement your own layout if you like, such as performing a grid
|
1594
|
+
layout.
|
1595
|
+
|
1596
|
+
The default implementation simply calls parentViewDidResize on all of
|
1597
|
+
your children.
|
1598
|
+
|
1599
|
+
@returns {void}
|
1600
|
+
*/
|
1601
|
+
viewDidResize: function() {
|
1602
|
+
var cv = this.childViews, len = cv.length, idx, view ;
|
1603
|
+
for (idx=0; idx<len; ++idx) {
|
1604
|
+
view = cv[idx] ;
|
1605
|
+
if (view.parentViewDidResize) view.parentViewDidResize() ;
|
1606
|
+
}
|
1607
|
+
}.observes('layout'),
|
1608
|
+
|
1609
|
+
// Implementation note: As a general rule, paired method calls, such as
|
1610
|
+
// beginLiveResize/endLiveResize that are called recursively on the tree
|
1611
|
+
// should reverse the order when doing the final half of the call. This
|
1612
|
+
// ensures that the calls are propertly nested for any cleanup routines.
|
1613
|
+
//
|
1614
|
+
// -> View A.beginXXX()
|
1615
|
+
// -> View B.beginXXX()
|
1616
|
+
// -> View C.begitXXX()
|
1617
|
+
// -> View D.beginXXX()
|
1618
|
+
//
|
1619
|
+
// ...later on, endXXX methods are called in reverse order of beginXXX...
|
1620
|
+
//
|
1621
|
+
// <- View D.endXXX()
|
1622
|
+
// <- View C.endXXX()
|
1623
|
+
// <- View B.endXXX()
|
1624
|
+
// <- View A.endXXX()
|
1625
|
+
//
|
1626
|
+
// See the two methods below for an example implementation.
|
1627
|
+
|
1628
|
+
/**
|
1629
|
+
Call this method when you plan to begin a live resize. This will
|
1630
|
+
notify the receiver view and any of its children that are interested
|
1631
|
+
that the resize is about to begin.
|
1632
|
+
|
1633
|
+
@returns {SC.View} receiver
|
1634
|
+
@test in viewDidResize
|
1635
|
+
*/
|
1636
|
+
beginLiveResize: function() {
|
1637
|
+
// call before children have been notified...
|
1638
|
+
if (this.willBeginLiveResize) this.willBeginLiveResize() ;
|
1639
|
+
|
1640
|
+
// notify children in order
|
1641
|
+
var ary = this.get('childViews'), len = ary.length, idx, view ;
|
1642
|
+
for (idx=0; idx<len; ++idx) {
|
1643
|
+
view = ary[idx] ;
|
1644
|
+
if (view.beginLiveResize) view.beginLiveResize();
|
1645
|
+
}
|
1646
|
+
return this ;
|
1647
|
+
},
|
1648
|
+
|
1649
|
+
/**
|
1650
|
+
Call this method when you are finished with a live resize. This will
|
1651
|
+
notify the receiver view and any of its children that are interested
|
1652
|
+
that the live resize has ended.
|
1653
|
+
|
1654
|
+
@returns {SC.View} receiver
|
1655
|
+
@test in viewDidResize
|
1656
|
+
*/
|
1657
|
+
endLiveResize: function() {
|
1658
|
+
// notify children in *reverse* order
|
1659
|
+
var ary = this.get('childViews'), len = ary.length, idx, view ;
|
1660
|
+
for (idx=len-1; idx>=0; --idx) { // loop backwards
|
1661
|
+
view = ary[idx] ;
|
1662
|
+
if (view.endLiveResize) view.endLiveResize() ;
|
1663
|
+
}
|
1664
|
+
|
1665
|
+
// call *after* all children have been notified...
|
1666
|
+
if (this.didEndLiveResize) this.didEndLiveResize() ;
|
1667
|
+
return this ;
|
1668
|
+
},
|
1669
|
+
|
1670
|
+
/**
|
1671
|
+
layoutStyle describes the current styles to be written to your element
|
1672
|
+
based on the layout you defined. Both layoutStyle and frame reset when
|
1673
|
+
you edit the layout property. Both are read only.
|
1674
|
+
|
1675
|
+
Computes the layout style settings needed for the current anchor.
|
1676
|
+
|
1677
|
+
@property {Hash}
|
1678
|
+
@readOnly
|
1679
|
+
*/
|
1680
|
+
layoutStyle: function() {
|
1681
|
+
var layout = this.get('layout'), ret = {}, pdim = null;
|
1682
|
+
|
1683
|
+
// X DIRECTION
|
1684
|
+
|
1685
|
+
// handle left aligned and left/right
|
1686
|
+
if (!SC.none(layout.left)) {
|
1687
|
+
ret.left = Math.floor(layout.left);
|
1688
|
+
if (layout.width !== undefined) {
|
1689
|
+
ret.width = Math.floor(layout.width) ;
|
1690
|
+
ret.right = null ;
|
1691
|
+
} else {
|
1692
|
+
ret.width = null ;
|
1693
|
+
ret.right = Math.floor(layout.right || 0) ;
|
1694
|
+
}
|
1695
|
+
ret.marginLeft = 0 ;
|
1696
|
+
|
1697
|
+
// handle right aligned
|
1698
|
+
} else if (!SC.none(layout.right)) {
|
1699
|
+
ret.right = Math.floor(layout.right) ;
|
1700
|
+
ret.marginLeft = 0 ;
|
1701
|
+
|
1702
|
+
if (SC.none(layout.width)) {
|
1703
|
+
ret.left = 0;
|
1704
|
+
ret.width = null;
|
1705
|
+
} else {
|
1706
|
+
ret.left = null ;
|
1707
|
+
ret.width = Math.floor(layout.width || 0) ;
|
1708
|
+
}
|
1709
|
+
|
1710
|
+
// handle centered
|
1711
|
+
} else if (!SC.none(layout.centerX)) {
|
1712
|
+
ret.left = "50%";
|
1713
|
+
ret.width = Math.floor(layout.width || 0) ;
|
1714
|
+
ret.marginLeft = Math.floor(layout.centerX - ret.width/2) ;
|
1715
|
+
ret.right = null ;
|
1716
|
+
|
1717
|
+
// if width defined, assume top/left of zero
|
1718
|
+
} else if (!SC.none(layout.width)) {
|
1719
|
+
ret.left = 0;
|
1720
|
+
ret.right = null;
|
1721
|
+
ret.width = Math.floor(layout.width);
|
1722
|
+
ret.marginLeft = 0;
|
1723
|
+
|
1724
|
+
// fallback, full width.
|
1725
|
+
} else {
|
1726
|
+
ret.left = 0;
|
1727
|
+
ret.right = 0;
|
1728
|
+
ret.width = null ;
|
1729
|
+
ret.marginLeft= 0;
|
1730
|
+
}
|
1731
|
+
|
1732
|
+
// handle min/max
|
1733
|
+
ret.minWidth = (layout.minWidth === undefined) ? null : layout.minWidth;
|
1734
|
+
ret.maxWidth = (layout.maxWidth === undefined) ? null : layout.maxWidth;
|
1735
|
+
|
1736
|
+
// Y DIRECTION
|
1737
|
+
|
1738
|
+
// handle left aligned and left/right
|
1739
|
+
if (!SC.none(layout.top)) {
|
1740
|
+
ret.top = Math.floor(layout.top);
|
1741
|
+
if (layout.height !== undefined) {
|
1742
|
+
ret.height = Math.floor(layout.height) ;
|
1743
|
+
ret.bottom = null ;
|
1744
|
+
} else {
|
1745
|
+
ret.height = null ;
|
1746
|
+
ret.bottom = Math.floor(layout.bottom || 0) ;
|
1747
|
+
}
|
1748
|
+
ret.marginTop = 0 ;
|
1749
|
+
|
1750
|
+
// handle right aligned
|
1751
|
+
} else if (!SC.none(layout.bottom)) {
|
1752
|
+
ret.marginTop = 0 ;
|
1753
|
+
ret.bottom = Math.floor(layout.bottom) ;
|
1754
|
+
if (SC.none(layout.height)) {
|
1755
|
+
ret.top = 0;
|
1756
|
+
ret.height = null ;
|
1757
|
+
} else {
|
1758
|
+
ret.top = null ;
|
1759
|
+
ret.height = Math.floor(layout.height || 0) ;
|
1760
|
+
}
|
1761
|
+
|
1762
|
+
// handle centered
|
1763
|
+
} else if (!SC.none(layout.centerY)) {
|
1764
|
+
ret.top = "50%";
|
1765
|
+
ret.height = Math.floor(layout.height || 0) ;
|
1766
|
+
ret.marginTop = Math.floor(layout.centerY - ret.height/2) ;
|
1767
|
+
ret.bottom = null ;
|
1768
|
+
|
1769
|
+
} else if (!SC.none(layout.height)) {
|
1770
|
+
ret.top = 0;
|
1771
|
+
ret.bottom = null;
|
1772
|
+
ret.height = Math.floor(layout.height || 0);
|
1773
|
+
ret.marginTop = 0;
|
1774
|
+
|
1775
|
+
// fallback, full width.
|
1776
|
+
} else {
|
1777
|
+
ret.top = 0;
|
1778
|
+
ret.bottom = 0;
|
1779
|
+
ret.height = null ;
|
1780
|
+
ret.marginTop= 0;
|
1781
|
+
}
|
1782
|
+
|
1783
|
+
// handle min/max
|
1784
|
+
ret.minHeight = (layout.minHeight === undefined) ? null : layout.minHeight;
|
1785
|
+
ret.maxHeight = (layout.maxHeight === undefined) ? null : layout.maxHeight;
|
1786
|
+
|
1787
|
+
// if zIndex is set, use it. otherwise let default shine through
|
1788
|
+
ret.zIndex = SC.none(layout.zIndex) ? null : layout.zIndex.toString();
|
1789
|
+
|
1790
|
+
// if backgroundPosition is set, use it. otherwise let default shine through
|
1791
|
+
ret.backgroundPosition = SC.none(layout.backgroundPosition) ? null : layout.backgroundPosition.toString();
|
1792
|
+
|
1793
|
+
// set default values to null to allow built-in CSS to shine through
|
1794
|
+
// currently applies only to marginLeft & marginTop
|
1795
|
+
var dims = SC._VIEW_DEFAULT_DIMS, loc = dims.length, x;
|
1796
|
+
while(--loc >=0) {
|
1797
|
+
x = dims[loc];
|
1798
|
+
if (ret[x]===0) ret[x]=null;
|
1799
|
+
}
|
1800
|
+
|
1801
|
+
// convert any numbers into a number + "px".
|
1802
|
+
for(var key in ret) {
|
1803
|
+
var value = ret[key];
|
1804
|
+
if (typeof value === SC.T_NUMBER) ret[key] = (value + "px");
|
1805
|
+
}
|
1806
|
+
return ret ;
|
1807
|
+
}.property().cacheable(),
|
1808
|
+
|
1809
|
+
/**
|
1810
|
+
The view responsible for laying out this view. The default version
|
1811
|
+
returns the current parent view.
|
1812
|
+
*/
|
1813
|
+
layoutView: function() {
|
1814
|
+
return this.get('parentView') ;
|
1815
|
+
}.property('parentView').cacheable(),
|
1816
|
+
|
1817
|
+
/**
|
1818
|
+
This method is called whenever a property changes that invalidates the
|
1819
|
+
layout of the view. Changing the layout will do this automatically, but
|
1820
|
+
you can add others if you want.
|
1821
|
+
|
1822
|
+
@returns {SC.View} receiver
|
1823
|
+
*/
|
1824
|
+
layoutDidChange: function() {
|
1825
|
+
// console.log('%@.layoutDidChange()'.fmt(this));
|
1826
|
+
this.beginPropertyChanges() ;
|
1827
|
+
if (this.frame) this.notifyPropertyChange('frame') ;
|
1828
|
+
this.notifyPropertyChange('layoutStyle') ;
|
1829
|
+
this.endPropertyChanges() ;
|
1830
|
+
|
1831
|
+
// notify layoutView...
|
1832
|
+
var layoutView = this.get('layoutView');
|
1833
|
+
if (layoutView) {
|
1834
|
+
layoutView.set('childViewsNeedLayout', YES);
|
1835
|
+
layoutView.layoutDidChangeFor(this) ;
|
1836
|
+
if (layoutView.get('childViewsNeedLayout')) {
|
1837
|
+
layoutView.invokeOnce(layoutView.layoutChildViewsIfNeeded);
|
1838
|
+
}
|
1839
|
+
}
|
1840
|
+
|
1841
|
+
return this ;
|
1842
|
+
}.observes('layout'),
|
1843
|
+
|
1844
|
+
/**
|
1845
|
+
This this property to YES whenever the view needs to layout its child
|
1846
|
+
views. Normally this property is set automatically whenever the layout
|
1847
|
+
property for a child view changes.
|
1848
|
+
|
1849
|
+
@property {Boolean}
|
1850
|
+
*/
|
1851
|
+
childViewsNeedLayout: NO,
|
1852
|
+
|
1853
|
+
/**
|
1854
|
+
One of two methods that are invoked whenever one of your childViews
|
1855
|
+
layout changes. This method is invoked everytime a child view's layout
|
1856
|
+
changes to give you a chance to record the information about the view.
|
1857
|
+
|
1858
|
+
Since this method may be called many times during a single run loop, you
|
1859
|
+
should keep this method pretty short. The other method called when layout
|
1860
|
+
changes, layoutChildViews(), is invoked only once at the end of
|
1861
|
+
the run loop. You should do any expensive operations (including changing
|
1862
|
+
a childView's actual layer) in this other method.
|
1863
|
+
|
1864
|
+
Note that if as a result of running this method you decide that you do not
|
1865
|
+
need your layoutChildViews() method run later, you can set the
|
1866
|
+
childViewsNeedsLayout property to NO from this method and the layout
|
1867
|
+
method will not be called layer.
|
1868
|
+
|
1869
|
+
@param {SC.View} childView the view whose layout has changed.
|
1870
|
+
@returns {void}
|
1871
|
+
*/
|
1872
|
+
layoutDidChangeFor: function(childView) {
|
1873
|
+
var set = this._needLayoutViews ;
|
1874
|
+
if (!set) set = this._needLayoutViews = SC.Set.create();
|
1875
|
+
set.add(childView);
|
1876
|
+
},
|
1877
|
+
|
1878
|
+
/**
|
1879
|
+
Called your layout method if the view currently needs to layout some
|
1880
|
+
child views.
|
1881
|
+
|
1882
|
+
@param {Boolean} isVisible if true assume view is visible even if it is not.
|
1883
|
+
@returns {SC.View} receiver
|
1884
|
+
@test in layoutChildViews
|
1885
|
+
*/
|
1886
|
+
layoutChildViewsIfNeeded: function(isVisible) {
|
1887
|
+
if (!isVisible) isVisible = this.get('isVisibleInWindow');
|
1888
|
+
if (isVisible && this.get('childViewsNeedLayout')) {
|
1889
|
+
this.set('childViewsNeedLayout', NO);
|
1890
|
+
this.layoutChildViews();
|
1891
|
+
}
|
1892
|
+
return this ;
|
1893
|
+
},
|
1894
|
+
|
1895
|
+
/**
|
1896
|
+
Applies the current layout to the layer. This method is usually only
|
1897
|
+
called once per runloop. You can override this method to provide your
|
1898
|
+
own layout updating method if you want, though usually the better option
|
1899
|
+
is to override the layout method from the parent view.
|
1900
|
+
|
1901
|
+
The default implementation of this method simply calls the renderLayout()
|
1902
|
+
method on the views that need layout.
|
1903
|
+
|
1904
|
+
@returns {void}
|
1905
|
+
*/
|
1906
|
+
layoutChildViews: function() {
|
1907
|
+
var set = this._needLayoutViews, len = set ? set.length : 0, idx;
|
1908
|
+
var view, context, layer;
|
1909
|
+
for(idx=0;idx<len;idx++) {
|
1910
|
+
view = set[idx];
|
1911
|
+
view.updateLayout();
|
1912
|
+
}
|
1913
|
+
view = context = layer = null ; // cleanup
|
1914
|
+
set.clear(); // reset & reuse
|
1915
|
+
},
|
1916
|
+
|
1917
|
+
/**
|
1918
|
+
Invoked by the layoutChildViews method to update the layout on a
|
1919
|
+
particular view. This method creates a render context and calls the
|
1920
|
+
renderLayout() method, which is probably what you want to override instead
|
1921
|
+
of this.
|
1922
|
+
|
1923
|
+
You will not usually override this method, but you may call it if you
|
1924
|
+
implement layoutChildViews() in a view yourself.
|
1925
|
+
|
1926
|
+
@returns {SC.View} receiver
|
1927
|
+
@test in layoutChildViews
|
1928
|
+
*/
|
1929
|
+
updateLayout: function() {
|
1930
|
+
var layer = this.get('layer'), context;
|
1931
|
+
if (layer) {
|
1932
|
+
context = this.renderContext(layer);
|
1933
|
+
this.renderLayout(context);
|
1934
|
+
context.update();
|
1935
|
+
}
|
1936
|
+
layer = null ;
|
1937
|
+
return this ;
|
1938
|
+
},
|
1939
|
+
|
1940
|
+
/**
|
1941
|
+
Default method called by the layout view to actually apply the current
|
1942
|
+
layout to the layer. The default implementation simply assigns the
|
1943
|
+
current layoutStyle to the layer. This method is also called whenever
|
1944
|
+
the layer is first created.
|
1945
|
+
|
1946
|
+
@param {SC.RenderContext} the render context
|
1947
|
+
@returns {void}
|
1948
|
+
@test in layoutChildViews
|
1949
|
+
*/
|
1950
|
+
renderLayout: function(context, firstTime) {
|
1951
|
+
context.addStyle(this.get('layoutStyle'));
|
1952
|
+
}
|
1953
|
+
|
1954
|
+
/** walk like a duck */
|
1955
|
+
isView: YES
|
1956
|
+
|
1957
|
+
});
|
1958
|
+
|
1959
|
+
SC.View.mixin(/** @scope SC.View @static */ {
|
1960
|
+
|
1961
|
+
/** @private walk like a duck -- used by SC.Page */
|
1962
|
+
isViewClass: YES,
|
1963
|
+
|
1964
|
+
/**
|
1965
|
+
This method works just like extend() except that it will also preserve
|
1966
|
+
the passed attributes in case you want to use a view builder later, if
|
1967
|
+
needed.
|
1968
|
+
|
1969
|
+
@param {Hash} attrs Attributes to add to view
|
1970
|
+
@returns {Class} SC.View subclass to create
|
1971
|
+
@function
|
1972
|
+
*/
|
1973
|
+
design: function() {
|
1974
|
+
if (this.isDesign) return this; // only run design one time
|
1975
|
+
var ret = this.extend.apply(this, arguments);
|
1976
|
+
ret.isDesign = YES ;
|
1977
|
+
if (SC.ViewDesigner) {
|
1978
|
+
SC.ViewDesigner.didLoadDesign(ret, this, SC.A(arguments));
|
1979
|
+
}
|
1980
|
+
return ret ;
|
1981
|
+
},
|
1982
|
+
|
1983
|
+
/**
|
1984
|
+
Helper applies the layout to the prototype.
|
1985
|
+
*/
|
1986
|
+
layout: function(layout) {
|
1987
|
+
this.prototype.layout = layout ;
|
1988
|
+
return this ;
|
1989
|
+
},
|
1990
|
+
|
1991
|
+
/**
|
1992
|
+
Helper applies the classNames to the prototype
|
1993
|
+
*/
|
1994
|
+
classNames: function(sc) {
|
1995
|
+
sc = (this.prototype.classNames || []).concat(sc);
|
1996
|
+
this.prototype.classNames = sc;
|
1997
|
+
return this ;
|
1998
|
+
},
|
1999
|
+
|
2000
|
+
/**
|
2001
|
+
Help applies the tagName
|
2002
|
+
*/
|
2003
|
+
tagName: function(tg) {
|
2004
|
+
this.prototype.tagName = tg;
|
2005
|
+
return this ;
|
2006
|
+
},
|
2007
|
+
|
2008
|
+
/**
|
2009
|
+
Helper adds the childView
|
2010
|
+
*/
|
2011
|
+
childView: function(cv) {
|
2012
|
+
var childViews = this.prototype.childViews || [];
|
2013
|
+
if (childViews === this.superclass.prototype.childViews) childViews = childViews.slice();
|
2014
|
+
childViews.push(cv) ;
|
2015
|
+
this.prototype.childViews = childViews;
|
2016
|
+
return this ;
|
2017
|
+
},
|
2018
|
+
|
2019
|
+
/**
|
2020
|
+
Helper adds a binding to a design
|
2021
|
+
*/
|
2022
|
+
bind: function(keyName, path) {
|
2023
|
+
var p = this.prototype, s = this.superclass.prototype;
|
2024
|
+
var bindings = p._bindings ;
|
2025
|
+
if (!bindings || bindings === s._bindings) {
|
2026
|
+
bindings = p._bindings = (bindings || []).slice() ;
|
2027
|
+
}
|
2028
|
+
|
2029
|
+
keyName = keyName + "Binding";
|
2030
|
+
p[keyName] = path ;
|
2031
|
+
bindings.push(keyName);
|
2032
|
+
|
2033
|
+
return this ;
|
2034
|
+
},
|
2035
|
+
|
2036
|
+
/**
|
2037
|
+
Helper sets a generic property on a design.
|
2038
|
+
*/
|
2039
|
+
prop: function(keyName, value) {
|
2040
|
+
this.prototype[keyName] = value;
|
2041
|
+
return this ;
|
2042
|
+
},
|
2043
|
+
|
2044
|
+
/**
|
2045
|
+
Used to construct a localization for a view. The default implementation
|
2046
|
+
will simply return the passed attributes.
|
2047
|
+
*/
|
2048
|
+
localization: function(attrs, rootElement) {
|
2049
|
+
// add rootElement
|
2050
|
+
if (rootElement) attrs.rootElement = SC.$(rootElement).get(0);
|
2051
|
+
return attrs;
|
2052
|
+
},
|
2053
|
+
|
2054
|
+
/**
|
2055
|
+
Creates a view instance, first finding the DOM element you name and then
|
2056
|
+
using that as the root element. You should not use this method very
|
2057
|
+
often, but it is sometimes useful if you want to attach to already
|
2058
|
+
existing HTML.
|
2059
|
+
|
2060
|
+
@param {String|Element} element
|
2061
|
+
@param {Hash} attrs
|
2062
|
+
@returns {SC.View} instance
|
2063
|
+
*/
|
2064
|
+
viewFor: function(element, attrs) {
|
2065
|
+
var args = SC.$A(arguments); // prepare to edit
|
2066
|
+
if (SC.none(element)) {
|
2067
|
+
args.shift(); // remove if no element passed
|
2068
|
+
} else args[0] = { rootElement: SC.$(element).get(0) } ;
|
2069
|
+
var ret = this.create.apply(this, arguments) ;
|
2070
|
+
args = args[0] = null;
|
2071
|
+
return ret ;
|
2072
|
+
},
|
2073
|
+
|
2074
|
+
/**
|
2075
|
+
Create a new view with the passed attributes hash. If you have the
|
2076
|
+
Designer module loaded, this will also create a peer designer if needed.
|
2077
|
+
*/
|
2078
|
+
create: function() {
|
2079
|
+
var C=this, ret = new C(arguments);
|
2080
|
+
if (SC.ViewDesigner) {
|
2081
|
+
SC.ViewDesigner.didCreateView(ret, SC.$A(arguments));
|
2082
|
+
}
|
2083
|
+
return ret ;
|
2084
|
+
},
|
2085
|
+
|
2086
|
+
/**
|
2087
|
+
Applies the passed localization hash to the component views. Call this
|
2088
|
+
method before you call create(). Returns the receiver. Typically you
|
2089
|
+
will do something like this:
|
2090
|
+
|
2091
|
+
view = SC.View.design({...}).loc(localizationHash).create();
|
2092
|
+
|
2093
|
+
@param {Hash} loc
|
2094
|
+
@param rootElement {String} optional rootElement with prepped HTML
|
2095
|
+
@returns {SC.View} receiver
|
2096
|
+
*/
|
2097
|
+
loc: function(loc) {
|
2098
|
+
var childLocs = loc.childViews;
|
2099
|
+
delete loc.childViews; // clear out child views before applying to attrs
|
2100
|
+
|
2101
|
+
this.applyLocalizedAttributes(loc) ;
|
2102
|
+
if (SC.ViewDesigner) {
|
2103
|
+
SC.ViewDesigner.didLoadLocalization(this, SC.$A(arguments));
|
2104
|
+
}
|
2105
|
+
|
2106
|
+
// apply localization recursively to childViews
|
2107
|
+
var childViews = this.prototype.childViews, idx = childViews.length;
|
2108
|
+
while(--idx>=0) {
|
2109
|
+
var viewClass = childViews[idx];
|
2110
|
+
loc = childLocs[idx];
|
2111
|
+
if (loc && viewClass && viewClass.loc) viewClass.loc(loc) ;
|
2112
|
+
}
|
2113
|
+
|
2114
|
+
return this; // done!
|
2115
|
+
},
|
2116
|
+
|
2117
|
+
/**
|
2118
|
+
Internal method actually updates the localizated attributes on the view
|
2119
|
+
class. This is overloaded in design mode to also save the attributes.
|
2120
|
+
*/
|
2121
|
+
applyLocalizedAttributes: function(loc) {
|
2122
|
+
SC.mixin(this.prototype, loc) ;
|
2123
|
+
},
|
2124
|
+
|
2125
|
+
views: {}
|
2126
|
+
|
2127
|
+
}) ;
|
2128
|
+
|
2129
|
+
// .......................................................
|
2130
|
+
// OUTLET BUILDER
|
2131
|
+
//
|
2132
|
+
|
2133
|
+
/**
|
2134
|
+
Generates a computed property that will look up the passed property path
|
2135
|
+
the first time you try to get the value. Use this whenever you want to
|
2136
|
+
define an outlet that points to another view or object. The root object
|
2137
|
+
used for the path will be the receiver.
|
2138
|
+
*/
|
2139
|
+
SC.outlet = function(path) {
|
2140
|
+
return function(key) {
|
2141
|
+
return (this[key] = SC.objectForPropertyPath(path, this)) ;
|
2142
|
+
}.property();
|
2143
|
+
};
|
2144
|
+
|
2145
|
+
/** @private on unload clear cached divs. */
|
2146
|
+
SC.View.unload = function() {
|
2147
|
+
|
2148
|
+
// delete view items this way to ensure the views are cleared. The hash
|
2149
|
+
// itself may be owned by multiple view subclasses.
|
2150
|
+
var views = SC.View.views;
|
2151
|
+
if (views) {
|
2152
|
+
for(var key in views) {
|
2153
|
+
if (!views.hasOwnProperty(key)) continue ;
|
2154
|
+
delete views[key];
|
2155
|
+
}
|
2156
|
+
}
|
2157
|
+
|
2158
|
+
} ;
|
2159
|
+
|
2160
|
+
SC.Event.add(window, 'unload', SC.View, SC.View.unload) ;
|