sproutcore 1.10.3.1 → 1.11.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/CHANGELOG +4 -8
- data/VERSION.yml +2 -2
- data/lib/frameworks/sproutcore/Buildfile +5 -4
- data/lib/frameworks/sproutcore/CHANGELOG.md +274 -40
- data/lib/frameworks/sproutcore/CONTRIBUTORS.md +133 -0
- data/lib/frameworks/sproutcore/README.md +31 -144
- data/lib/frameworks/sproutcore/apps/showcase/controllers/source_tree_controller.js +9 -4
- data/lib/frameworks/sproutcore/apps/showcase/resources/stylesheet.css +5 -0
- data/lib/frameworks/sproutcore/apps/showcase/system/views_item_content.js +1 -1
- data/lib/frameworks/sproutcore/apps/showcase/views/split_views.js +15 -2
- data/lib/frameworks/sproutcore/apps/showcase/views/stacked_views.js +1 -1
- data/lib/frameworks/sproutcore/apps/tests/english.lproj/main_page.js +11 -1
- data/lib/frameworks/sproutcore/frameworks/ajax/mixins/websocket_delegate.js +90 -0
- data/lib/frameworks/sproutcore/frameworks/ajax/system/request.js +81 -5
- data/lib/frameworks/sproutcore/frameworks/ajax/system/response.js +23 -4
- data/lib/frameworks/sproutcore/frameworks/ajax/system/websocket.js +475 -0
- data/lib/frameworks/sproutcore/frameworks/ajax/tests/system/request.js +149 -26
- data/lib/frameworks/sproutcore/frameworks/ajax/tests/system/websocket.js +197 -0
- data/lib/frameworks/sproutcore/frameworks/ajax/tests/system/xhr_response_test.js +65 -0
- data/lib/frameworks/sproutcore/frameworks/bootstrap/system/loader.js +4 -0
- data/lib/frameworks/sproutcore/frameworks/core_foundation/child_view_layouts/horizontal_stack_layout.js +232 -52
- data/lib/frameworks/sproutcore/frameworks/core_foundation/child_view_layouts/vertical_stack_layout.js +235 -49
- data/lib/frameworks/sproutcore/frameworks/core_foundation/controllers/array.js +23 -13
- data/lib/frameworks/sproutcore/frameworks/core_foundation/controllers/object.js +3 -1
- data/lib/frameworks/sproutcore/frameworks/core_foundation/core.js +81 -1
- data/lib/frameworks/sproutcore/frameworks/core_foundation/english.lproj/ordinal.js +17 -0
- data/lib/frameworks/sproutcore/frameworks/core_foundation/ext/string.js +7 -0
- data/lib/frameworks/sproutcore/frameworks/{desktop/tests/views/disclosure/methods.js → core_foundation/french.lproj/ordinal.js} +7 -4
- data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/layout.js +2 -6
- data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/main.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/pane.js +104 -69
- data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/pane_statechart.js +6 -1
- data/lib/frameworks/sproutcore/frameworks/core_foundation/protocols/child_view_layout_protocol.js +59 -0
- data/lib/frameworks/sproutcore/frameworks/core_foundation/protocols/view_transition_protocol.js +18 -1
- data/lib/frameworks/sproutcore/frameworks/core_foundation/system/application.js +192 -0
- data/lib/frameworks/sproutcore/frameworks/core_foundation/system/bezier_curves.js +52 -0
- data/lib/frameworks/sproutcore/frameworks/core_foundation/system/color.js +384 -64
- data/lib/frameworks/sproutcore/frameworks/core_foundation/system/core_query.js +6 -14
- data/lib/frameworks/sproutcore/frameworks/core_foundation/system/device.js +21 -35
- data/lib/frameworks/sproutcore/frameworks/core_foundation/system/event.js +72 -36
- data/lib/frameworks/sproutcore/frameworks/core_foundation/system/locale.js +90 -34
- data/lib/frameworks/sproutcore/frameworks/core_foundation/system/platform.js +55 -7
- data/lib/frameworks/sproutcore/frameworks/core_foundation/system/render_context.js +20 -15
- data/lib/frameworks/sproutcore/frameworks/core_foundation/system/req_anim_frame.js +9 -10
- data/lib/frameworks/sproutcore/frameworks/core_foundation/system/root_responder.js +763 -542
- data/lib/frameworks/sproutcore/frameworks/core_foundation/system/selection_set.js +4 -3
- data/lib/frameworks/sproutcore/frameworks/core_foundation/system/sparse_array.js +1 -7
- data/lib/frameworks/sproutcore/frameworks/core_foundation/system/string.js +14 -0
- data/lib/frameworks/sproutcore/frameworks/core_foundation/system/touch.js +538 -0
- data/lib/frameworks/sproutcore/frameworks/core_foundation/system/utils/rect.js +56 -1
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/controllers/array/array_case.js +99 -4
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/controllers/object/single_case.js +25 -19
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/core_tests.js +75 -0
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/ext/number_test.js +81 -0
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/mixins/action_support.js +4 -4
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/mixins/responder_context.js +4 -4
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/mixins/string.js +19 -1
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/system/color.js +36 -20
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/system/root_responder/design_modes_test.js +83 -0
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/system/root_responder/makeMainPane.js +7 -3
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/system/root_responder/mouse_events.js +338 -0
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/system/root_responder/root_responder.js +14 -89
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/system/root_responder/touch.js +106 -0
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/system/sparse_array.js +2 -2
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/system/touch.js +136 -0
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/system/utils/rect.js +42 -1
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/pane/append_remove.js +11 -0
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/pane/child_view.js +5 -5
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/pane/design_mode_test.js +457 -0
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/pane/sendEvent.js +36 -10
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/background_color.js +44 -0
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/border_frame_test.js +51 -24
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/childViewLayout_test.js +176 -1
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/clippingFrame.js +46 -16
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/convertFrames.js +69 -15
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/didAppendToDocument.js +2 -2
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layout.js +7 -1
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layoutDidChange.js +30 -10
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layoutStyle.js +376 -71
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/static_layout.js +0 -10
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/viewDidResize.js +117 -34
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/view_states_test.js +52 -2
- data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view.js +656 -42
- data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/animation.js +159 -38
- data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/cursor.js +0 -7
- data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/design_mode.js +206 -0
- data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/enabled.js +0 -28
- data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/keyboard.js +21 -6
- data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/layout.js +372 -450
- data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/layout_style.js +28 -13
- data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/manipulation.js +22 -51
- data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/statechart.js +59 -30
- data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/theming.js +0 -29
- data/lib/frameworks/sproutcore/frameworks/datastore/mixins/relationship_support.js +22 -10
- data/lib/frameworks/sproutcore/frameworks/datastore/models/children_attribute.js +42 -36
- data/lib/frameworks/sproutcore/frameworks/datastore/models/many_attribute.js +54 -3
- data/lib/frameworks/sproutcore/frameworks/datastore/models/record.js +178 -59
- data/lib/frameworks/sproutcore/frameworks/datastore/models/record_attribute.js +2 -2
- data/lib/frameworks/sproutcore/frameworks/datastore/system/child_array.js +206 -132
- data/lib/frameworks/sproutcore/frameworks/datastore/system/many_array.js +214 -118
- data/lib/frameworks/sproutcore/frameworks/datastore/system/nested_store.js +96 -13
- data/lib/frameworks/sproutcore/frameworks/datastore/system/query.js +14 -4
- data/lib/frameworks/sproutcore/frameworks/datastore/system/record_array.js +82 -42
- data/lib/frameworks/sproutcore/frameworks/datastore/system/store.js +272 -177
- data/lib/frameworks/sproutcore/frameworks/datastore/tests/integration/store_interaction_test.js +54 -0
- data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/datetime_recordattribute.js +24 -16
- data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/many_attribute.js +6 -3
- data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/nested_records/data_store.js +267 -35
- data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/nested_records/nested_record.js +57 -46
- data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/nested_records/nested_record_array.js +150 -53
- data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/nested_records/nested_record_array_complex.js +57 -17
- data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/nested_records/nested_record_complex.js +13 -9
- data/lib/frameworks/sproutcore/frameworks/{experimental/frameworks/polymorphism → datastore}/tests/models/polymorphism/many.js +2 -2
- data/lib/frameworks/sproutcore/frameworks/{experimental/frameworks/polymorphism → datastore}/tests/models/polymorphism/simple.js +0 -0
- data/lib/frameworks/sproutcore/frameworks/{experimental/frameworks/polymorphism → datastore}/tests/models/polymorphism/single.js +12 -2
- data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/record/writeAttribute.js +20 -15
- data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/record_attribute.js +9 -2
- data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/many_array/core_methods.js +80 -14
- data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/autonomous_dataSourceCallbacks.js +280 -0
- data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/autonomous_pushChanges.js +232 -0
- data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/chain.js +31 -5
- data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/query/parse.js +16 -2
- data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/store/core_methods.js +60 -40
- data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/store/materializeRecord.js +78 -0
- data/lib/frameworks/sproutcore/frameworks/datetime/frameworks/core/system/datetime.js +13 -1
- data/lib/frameworks/sproutcore/frameworks/datetime/frameworks/core/tests/system/datetime.js +20 -0
- data/lib/frameworks/sproutcore/frameworks/datetime/frameworks/localized/{resources → english.lproj}/strings.js +0 -0
- data/lib/frameworks/sproutcore/frameworks/datetime/frameworks/localized/french.lproj/strings.js +45 -0
- data/lib/frameworks/sproutcore/frameworks/designer/designers/object_designer.js +7 -3
- data/lib/frameworks/sproutcore/frameworks/desktop/mixins/collection_row_delegate.js +125 -44
- data/lib/frameworks/sproutcore/frameworks/desktop/panes/alert.js +139 -48
- data/lib/frameworks/sproutcore/frameworks/desktop/panes/draggable.js +202 -0
- data/lib/frameworks/sproutcore/frameworks/desktop/panes/menu.js +59 -56
- data/lib/frameworks/sproutcore/frameworks/desktop/panes/palette.js +13 -49
- data/lib/frameworks/sproutcore/frameworks/desktop/panes/picker.js +466 -305
- data/lib/frameworks/sproutcore/frameworks/desktop/protocols/drag_source.js +49 -12
- data/lib/frameworks/sproutcore/frameworks/desktop/render_delegates/slider.js +79 -21
- data/lib/frameworks/sproutcore/frameworks/desktop/render_delegates/split.js +12 -2
- data/lib/frameworks/sproutcore/frameworks/desktop/resources/menu_item_view.css +8 -0
- data/lib/frameworks/sproutcore/frameworks/desktop/resources/overlay-scroller.css +187 -0
- data/lib/frameworks/sproutcore/frameworks/desktop/system/drag.js +94 -30
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/panes/alert/ui.js +163 -3
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/panes/menu/methods.js +97 -78
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/panes/menu/ui.js +61 -1
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/panes/panel/methods.js +7 -3
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/panes/panel/ui.js +47 -22
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/panes/picker/methods.js +66 -9
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/panes/picker/ui.js +21 -11
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/panes/sheet/ui.js +12 -18
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/button/methods.js +17 -14
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/button/ui.js +2 -1
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/checkbox/methods.js +9 -6
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/collection/collection_fast_path.js +54 -21
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/collection/content.js +52 -20
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/collection/itemViewForContentIndex.js +94 -4
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/collection/keyboard.js +177 -0
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/collection/layerIdFor.js +13 -1
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/collection/length.js +9 -9
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/collection/mouse.js +18 -0
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/date_field/methods.js +104 -0
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/disclosure/ui.js +48 -49
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/grid/drag_and_drop.js +22 -18
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/grid/methods.js +17 -5
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/link_view_test.js +136 -0
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/list/contentIndexesInRect.js +77 -0
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/list/drag_and_drop.js +53 -16
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/list/layoutForContentIndex.js +41 -0
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/list/rowDelegate.js +25 -25
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/list/rowOffsetForContentIndex.js +102 -27
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/list/{rowHeightForContentIndex.js → rowSizeForContentIndex.js} +7 -6
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/list/ui_outline.js +2 -0
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/list/ui_row_heights.js +70 -75
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/list/ui_simple.js +29 -30
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/list_item.js +57 -0
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/menu_scroll_view/menu_scroll_view_test.js +206 -0
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/progress/ui.js +15 -0
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/radio/methods.js +15 -7
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/scroll/integration.js +16 -11
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/scroll/methods.js +164 -12
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/scroll/scale.js +387 -0
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/scroll/touch.js +549 -0
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/scroll/ui.js +214 -45
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/scroller.js +5 -5
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/segmented/methods.js +73 -22
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/segmented/ui.js +88 -3
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/select/methods.js +8 -0
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/slider/methods.js +16 -1
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/slider/ui.js +54 -0
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/split/dividers.js +21 -2
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/static_content.js +31 -25
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/tab/methods.js +109 -29
- data/lib/frameworks/sproutcore/frameworks/desktop/views/button.js +10 -1
- data/lib/frameworks/sproutcore/frameworks/desktop/views/checkbox.js +3 -0
- data/lib/frameworks/sproutcore/frameworks/desktop/views/collection.js +779 -603
- data/lib/frameworks/sproutcore/frameworks/desktop/views/date_field.js +106 -7
- data/lib/frameworks/sproutcore/frameworks/desktop/views/link_view.js +406 -0
- data/lib/frameworks/sproutcore/frameworks/desktop/views/list.js +437 -245
- data/lib/frameworks/sproutcore/frameworks/desktop/views/list_item.js +13 -0
- data/lib/frameworks/sproutcore/frameworks/desktop/views/menu_item.js +124 -62
- data/lib/frameworks/sproutcore/frameworks/desktop/views/menu_scroll.js +176 -597
- data/lib/frameworks/sproutcore/frameworks/desktop/views/menu_scroller_view.js +206 -0
- data/lib/frameworks/sproutcore/frameworks/desktop/views/popup_button.js +3 -0
- data/lib/frameworks/sproutcore/frameworks/desktop/views/progress.js +5 -4
- data/lib/frameworks/sproutcore/frameworks/desktop/views/radio.js +3 -0
- data/lib/frameworks/sproutcore/frameworks/desktop/views/scene.js +56 -158
- data/lib/frameworks/sproutcore/frameworks/desktop/views/scroll_view.js +2560 -0
- data/lib/frameworks/sproutcore/frameworks/desktop/views/scroller.js +458 -242
- data/lib/frameworks/sproutcore/frameworks/desktop/views/segmented.js +117 -54
- data/lib/frameworks/sproutcore/frameworks/desktop/views/select.js +18 -12
- data/lib/frameworks/sproutcore/frameworks/desktop/views/slider.js +162 -34
- data/lib/frameworks/sproutcore/frameworks/desktop/views/split.js +30 -15
- data/lib/frameworks/sproutcore/frameworks/desktop/views/split_divider.js +33 -7
- data/lib/frameworks/sproutcore/frameworks/desktop/views/static_content.js +22 -2
- data/lib/frameworks/sproutcore/frameworks/desktop/views/tab.js +47 -22
- data/lib/frameworks/sproutcore/frameworks/experimental/Buildfile +0 -6
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/forms/views/form.js +2 -1
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/forms/views/form_row.js +21 -21
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/select_view/ext/menu.js +14 -3
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/select_view/mixins/select_view_menu.js +24 -10
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/select_view/tests/ext/menu_resizing.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/select_view/tests/mixins/select_view_menu/bindings.js +7 -4
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/select_view/tests/mixins/select_view_menu/check_selected.js +7 -9
- data/lib/frameworks/sproutcore/frameworks/{desktop/tests/panes/select_button/methods.js → experimental/frameworks/select_view/tests/views/select/method.js} +54 -76
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/select_view/tests/views/select/selected_item.js +35 -0
- data/lib/frameworks/sproutcore/frameworks/{desktop/tests/panes/select_button → experimental/frameworks/select_view/tests/views/select}/ui.js +107 -36
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/select_view/views/select.js +225 -66
- data/lib/frameworks/sproutcore/frameworks/foundation/controllers/tree.js +39 -38
- data/lib/frameworks/sproutcore/frameworks/foundation/core.js +5 -18
- data/lib/frameworks/sproutcore/frameworks/foundation/debug/control_test_pane.js +12 -0
- data/lib/frameworks/sproutcore/frameworks/foundation/english.lproj/inflections.js +84 -0
- data/lib/frameworks/sproutcore/frameworks/foundation/french.lproj/inflections.js +41 -0
- data/lib/frameworks/sproutcore/frameworks/foundation/mixins/auto_mixin.js +1 -0
- data/lib/frameworks/sproutcore/frameworks/foundation/mixins/auto_resize.js +7 -0
- data/lib/frameworks/sproutcore/frameworks/foundation/mixins/content_display.js +3 -4
- data/lib/frameworks/sproutcore/frameworks/foundation/mixins/flowed_layout.js +6 -2
- data/lib/frameworks/sproutcore/frameworks/foundation/private/tree_item_observer.js +408 -239
- data/lib/frameworks/sproutcore/frameworks/foundation/render_delegates/canvas_image.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/foundation/resources/text_field.css +2 -1
- data/lib/frameworks/sproutcore/frameworks/foundation/spanish.lproj/inflections.js +38 -0
- data/lib/frameworks/sproutcore/frameworks/foundation/system/benchmark.js +104 -76
- data/lib/frameworks/sproutcore/frameworks/foundation/system/string.js +20 -94
- data/lib/frameworks/sproutcore/frameworks/foundation/system/text_selection.js +33 -22
- data/lib/frameworks/sproutcore/frameworks/foundation/system/undo_manager.js +475 -0
- data/lib/frameworks/sproutcore/frameworks/foundation/tests/mixins/auto_resize_test.js +163 -1
- data/lib/frameworks/sproutcore/frameworks/foundation/tests/mixins/flowed_layout/tests.js +41 -0
- data/lib/frameworks/sproutcore/frameworks/foundation/tests/mixins/staticLayout.js +2 -5
- data/lib/frameworks/sproutcore/frameworks/foundation/tests/private/tree_item_observer/methods.js +268 -0
- data/lib/frameworks/sproutcore/frameworks/foundation/tests/system/undo_manager.js +231 -0
- data/lib/frameworks/sproutcore/frameworks/foundation/tests/views/container/ui.js +16 -0
- data/lib/frameworks/sproutcore/frameworks/foundation/tests/views/image/ui.js +27 -0
- data/lib/frameworks/sproutcore/frameworks/foundation/tests/views/text_field/methods.js +24 -0
- data/lib/frameworks/sproutcore/frameworks/foundation/tests/views/text_field/ui.js +135 -6
- data/lib/frameworks/sproutcore/frameworks/foundation/transitions/fade_transition.js +6 -0
- data/lib/frameworks/sproutcore/frameworks/foundation/transitions/pop_transition.js +7 -0
- data/lib/frameworks/sproutcore/frameworks/foundation/transitions/scale_transition.js +6 -0
- data/lib/frameworks/sproutcore/frameworks/foundation/transitions/slide_transition.js +4 -0
- data/lib/frameworks/sproutcore/frameworks/foundation/transitions/swap_dissolve_transition.js +3 -1
- data/lib/frameworks/sproutcore/frameworks/foundation/validators/credit_card.js +21 -21
- data/lib/frameworks/sproutcore/frameworks/foundation/views/container.js +65 -15
- data/lib/frameworks/sproutcore/frameworks/foundation/views/image.js +4 -1
- data/lib/frameworks/sproutcore/frameworks/foundation/views/label.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/foundation/views/text_field.js +193 -213
- data/lib/frameworks/sproutcore/frameworks/jquery/{jquery-1.8.3-patched.js → jquery-1.11.1.js} +7507 -6684
- data/lib/frameworks/sproutcore/frameworks/routing/system/routes.js +28 -11
- data/lib/frameworks/sproutcore/frameworks/routing/tests/system/routes.js +26 -0
- data/lib/frameworks/sproutcore/frameworks/runtime/core.js +54 -25
- data/lib/frameworks/sproutcore/frameworks/runtime/ext/array.js +0 -6
- data/lib/frameworks/sproutcore/frameworks/runtime/ext/number.js +36 -0
- data/lib/frameworks/sproutcore/frameworks/runtime/ext/window.js +25 -0
- data/lib/frameworks/sproutcore/frameworks/runtime/mixins/array.js +3 -3
- data/lib/frameworks/sproutcore/frameworks/runtime/mixins/enumerable.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/runtime/mixins/observable.js +156 -66
- data/lib/frameworks/sproutcore/frameworks/runtime/private/observer_set.js +2 -2
- data/lib/frameworks/sproutcore/frameworks/runtime/system/binding.js +150 -65
- data/lib/frameworks/sproutcore/frameworks/runtime/system/index_set.js +57 -11
- data/lib/frameworks/sproutcore/frameworks/runtime/system/object.js +68 -49
- data/lib/frameworks/sproutcore/frameworks/runtime/system/run_loop.js +14 -6
- data/lib/frameworks/sproutcore/frameworks/runtime/system/string.js +23 -23
- data/lib/frameworks/sproutcore/frameworks/runtime/tests/ext/number_test.js +44 -0
- data/lib/frameworks/sproutcore/frameworks/runtime/tests/mixins/array.js +0 -10
- data/lib/frameworks/sproutcore/frameworks/runtime/tests/mixins/enumerable/enumerable.js +340 -285
- data/lib/frameworks/sproutcore/frameworks/runtime/tests/system/binding.js +104 -3
- data/lib/frameworks/sproutcore/frameworks/runtime/tests/system/observer_set.js +14 -1
- data/lib/frameworks/sproutcore/frameworks/runtime/tests/system/string.js +15 -2
- data/lib/frameworks/sproutcore/frameworks/statechart/system/state.js +21 -18
- data/lib/frameworks/sproutcore/frameworks/statechart/system/statechart.js +52 -19
- data/lib/frameworks/sproutcore/frameworks/statechart/tests/event_handling/responder/pane.js +27 -24
- data/lib/frameworks/sproutcore/frameworks/template_view/controls/button.js +30 -0
- data/lib/frameworks/sproutcore/frameworks/template_view/ext/handlebars/bind.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/template_view/ext/handlebars/collection.js +2 -0
- data/lib/frameworks/sproutcore/frameworks/template_view/ext/handlebars/view.js +1 -0
- data/lib/frameworks/sproutcore/frameworks/template_view/tests/mixins/template_helpers/checkbox_support.js +2 -2
- data/lib/frameworks/sproutcore/frameworks/template_view/tests/views/template/handlebars.js +4 -2
- data/lib/frameworks/sproutcore/frameworks/template_view/views/bindable_span.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/template_view/views/template_collection.js +16 -14
- data/lib/frameworks/sproutcore/frameworks/testing/core.js +5 -3
- data/lib/frameworks/sproutcore/frameworks/testing/system/plan.js +13 -0
- data/lib/frameworks/sproutcore/lib/index.rhtml +2 -2
- data/lib/frameworks/sproutcore/phantomjs/test_runner.js +28 -7
- data/lib/frameworks/sproutcore/scripts/run_sc_server_master.sh +1 -1
- data/lib/frameworks/sproutcore/themes/ace/resources/_variables.css +2 -0
- data/lib/frameworks/sproutcore/themes/ace/resources/disclosure/ace/disclosure.css +1 -0
- data/lib/frameworks/sproutcore/themes/ace/resources/picker/popover/popover.css +3 -4
- data/lib/frameworks/sproutcore/themes/ace/resources/scroller/horizontal/horizontal.css +15 -15
- data/lib/frameworks/sproutcore/themes/ace/resources/scroller/horizontal/horizontal_overlay.css +74 -0
- data/lib/frameworks/sproutcore/themes/ace/resources/scroller/vertical/vertical.css +11 -13
- data/lib/frameworks/sproutcore/themes/ace/resources/scroller/vertical/vertical_overlay.css +74 -0
- data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/jumbo/knob-active.png +0 -0
- data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/jumbo/knob-active@2x.png +0 -0
- data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/jumbo/knob.png +0 -0
- data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/jumbo/knob@2x.png +0 -0
- data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/{22px → jumbo}/slider.css +9 -4
- data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/jumbo/track.png +0 -0
- data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/jumbo/track@2x.png +0 -0
- data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/regular/knob-active.png +0 -0
- data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/regular/knob-active@2x.png +0 -0
- data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/regular/knob.png +0 -0
- data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/regular/knob@2x.png +0 -0
- data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/regular/slider.css +32 -0
- data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/regular/track.png +0 -0
- data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/regular/track@2x.png +0 -0
- data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/slider.css +13 -0
- data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/small/knob-active.png +0 -0
- data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/small/knob-active@2x.png +0 -0
- data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/small/knob.png +0 -0
- data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/small/knob@2x.png +0 -0
- data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/small/slider.css +32 -0
- data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/small/track.png +0 -0
- data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/small/track@2x.png +0 -0
- data/lib/frameworks/sproutcore/themes/ace/resources/split/split.css +2 -3
- data/lib/sproutcore/builders/chance_file.rb +3 -3
- data/lib/sproutcore/helpers/minifier.rb +1 -0
- data/vendor/chance/lib/chance/instance.rb +34 -34
- data/vendor/chance/lib/chance/instance/spriting.rb +21 -16
- metadata +81 -58
- data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/visibility.js +0 -17
- data/lib/frameworks/sproutcore/frameworks/desktop/mixins/collection_fast_path.js +0 -710
- data/lib/frameworks/sproutcore/frameworks/desktop/mixins/scrollable.js +0 -267
- data/lib/frameworks/sproutcore/frameworks/desktop/resources/touch-scroller.css +0 -196
- data/lib/frameworks/sproutcore/frameworks/desktop/system/undo_manager.js +0 -224
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/select_field/methods.js +0 -163
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/select_field/ui.js +0 -177
- data/lib/frameworks/sproutcore/frameworks/desktop/views/scroll.js +0 -2053
- data/lib/frameworks/sproutcore/frameworks/desktop/views/select_button.js +0 -1024
- data/lib/frameworks/sproutcore/frameworks/desktop/views/select_field.js +0 -404
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/menu/render_delegates/menu_scroller.js +0 -28
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/menu/tests/menu/scroll.js +0 -235
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/menu/views/menu/scroll.js +0 -363
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/menu/views/menu/scroller.js +0 -250
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/polymorphism/README.md +0 -47
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/polymorphism/models/record.js +0 -134
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/render_delegates/desktop_scroller.js +0 -92
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/render_delegates/native_scroll.js +0 -25
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/render_delegates/scroll.js +0 -33
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/render_delegates/touch_scroller.js +0 -76
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/tests/scroll/integration.js +0 -25
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/tests/scroll/methods.js +0 -143
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/tests/scroll/ui.js +0 -256
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/core_scroll.js +0 -1164
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/core_scroller.js +0 -332
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/desktop/scroll.js +0 -236
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/desktop/scroller.js +0 -347
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/scroll.js +0 -15
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/scroller.js +0 -10
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/touch/scroll.js +0 -804
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/touch/scroller.js +0 -133
- data/lib/frameworks/sproutcore/frameworks/foundation/tasks/preload_bundle.js +0 -41
- data/lib/frameworks/sproutcore/themes/ace/resources/scroller/horizontal/horizontal_touch.css +0 -91
- data/lib/frameworks/sproutcore/themes/ace/resources/scroller/vertical/vertical_touch.css +0 -92
- data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/14px/knob.png +0 -0
- data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/14px/knob_active.png +0 -0
- data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/14px/slider.css +0 -27
- data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/16px/knob.png +0 -0
- data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/16px/knob_active.png +0 -0
- data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/16px/slider.css +0 -27
- data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/22px/knob.png +0 -0
- data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/22px/knob_active.png +0 -0
- data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/22px/track.png +0 -0
- data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/track.png +0 -0
@@ -4,7 +4,7 @@
|
|
4
4
|
// Portions ©2008-2011 Apple Inc. All rights reserved.
|
5
5
|
// License: Licensed under MIT license (see license.js)
|
6
6
|
// ==========================================================================
|
7
|
-
|
7
|
+
|
8
8
|
|
9
9
|
/**
|
10
10
|
A constant indicating an unsupported method, property or other.
|
@@ -81,25 +81,44 @@ SC.platform = SC.Object.create({
|
|
81
81
|
touch: (!SC.none(window.ontouchstart) || SC.browser.name === SC.BROWSER.android || 'ontouchstart' in document.documentElement) && SC.none(window._phantom),
|
82
82
|
|
83
83
|
/**
|
84
|
-
|
84
|
+
True if bouncing on scroll is expected in the current platform.
|
85
85
|
|
86
86
|
@type Boolean
|
87
87
|
*/
|
88
88
|
bounceOnScroll: SC.browser.os === SC.OS.ios,
|
89
89
|
|
90
90
|
/**
|
91
|
-
|
91
|
+
True if pinch-to-zoom is expected in the current platform.
|
92
92
|
|
93
93
|
@type Boolean
|
94
94
|
*/
|
95
|
-
pinchToZoom:
|
95
|
+
pinchToZoom: SC.browser.os === SC.OS.ios,
|
96
|
+
|
97
|
+
/**
|
98
|
+
A hash that contains properties that indicate support for new HTML5
|
99
|
+
a attributes.
|
100
|
+
|
101
|
+
For example, to test to see if the `download` attribute is supported,
|
102
|
+
you would verify that `SC.platform.a.download` is true.
|
103
|
+
|
104
|
+
@type Array
|
105
|
+
*/
|
106
|
+
a: function () {
|
107
|
+
var elem = document.createElement('a');
|
108
|
+
|
109
|
+
return {
|
110
|
+
download: !!('download' in elem),
|
111
|
+
media: !!('media' in elem),
|
112
|
+
ping: !!('ping' in elem),
|
113
|
+
};
|
114
|
+
}(),
|
96
115
|
|
97
116
|
/**
|
98
117
|
A hash that contains properties that indicate support for new HTML5
|
99
118
|
input attributes.
|
100
119
|
|
101
|
-
For example, to test to see if the placeholder attribute is supported,
|
102
|
-
you would verify that SC.platform.input.placeholder is
|
120
|
+
For example, to test to see if the `placeholder` attribute is supported,
|
121
|
+
you would verify that `SC.platform.input.placeholder` is true.
|
103
122
|
|
104
123
|
@type Array
|
105
124
|
*/
|
@@ -117,7 +136,8 @@ SC.platform = SC.Object.create({
|
|
117
136
|
|
118
137
|
return ret;
|
119
138
|
}(['autocomplete', 'readonly', 'list', 'size', 'required', 'multiple', 'maxlength',
|
120
|
-
|
139
|
+
'pattern', 'min', 'max', 'step', 'placeholder',
|
140
|
+
'selectionStart', 'selectionEnd', 'selectionDirection']),
|
121
141
|
|
122
142
|
/**
|
123
143
|
YES if the application is currently running as a standalone application.
|
@@ -396,6 +416,34 @@ SC.platform = SC.Object.create({
|
|
396
416
|
return !!document.createElement('canvas').getContext;
|
397
417
|
}(),
|
398
418
|
|
419
|
+
/**
|
420
|
+
Whether the browser supports the XHR2 ProgressEvent specification. This
|
421
|
+
reliably implies support for XMLHttpRequest 'loadstart' and 'progress'
|
422
|
+
events, as well as the terminal 'load', 'error' and 'abort' events. Support
|
423
|
+
for 'loadend', which fires no matter how the request terminats, is a bit
|
424
|
+
spottier and should be verified separately using `supportsXHR2LoadEndEvent`.
|
425
|
+
|
426
|
+
@type Boolean
|
427
|
+
*/
|
428
|
+
supportsXHR2ProgressEvent: ('ProgressEvent' in window),
|
429
|
+
|
430
|
+
/**
|
431
|
+
Whether the browser supports the XHR2 FormData specification.
|
432
|
+
|
433
|
+
@type Boolean
|
434
|
+
*/
|
435
|
+
supportsXHR2FormData: ('FormData' in window),
|
436
|
+
|
437
|
+
/**
|
438
|
+
Whether the browser supports the XHR2 ProgressEvent's loadend event. If not
|
439
|
+
supported, you should handle 'load', 'error' and 'abort' events instead.
|
440
|
+
|
441
|
+
@type Boolean
|
442
|
+
*/
|
443
|
+
supportsXHR2LoadEndEvent: function () {
|
444
|
+
return (new XMLHttpRequest).onloadend === null;
|
445
|
+
} (),
|
446
|
+
|
399
447
|
/**
|
400
448
|
Whether the browser supports the orientationchange event.
|
401
449
|
|
@@ -882,30 +882,35 @@ SC.RenderContext = SC.Builder.create(
|
|
882
882
|
// Add the updated styles to the internal styles object.
|
883
883
|
if (SC.typeOf(nameOrStyles) === SC.T_HASH) {
|
884
884
|
for (var key in nameOrStyles) {
|
885
|
-
|
886
|
-
|
887
|
-
value = nameOrStyles[key];
|
888
|
-
|
889
|
-
didChange = this._deleteComboStyles(styles, key) || didChange;
|
890
|
-
didChange = this._setOnHash(styles, key, value) || didChange;
|
885
|
+
// Call a separate function so that it may be optimized.
|
886
|
+
didChange = this._sc_setStyleFromObject(didChange, key, nameOrStyles, styles);
|
891
887
|
}
|
892
888
|
} else {
|
893
889
|
didChange = this._deleteComboStyles(styles, nameOrStyles);
|
894
890
|
didChange = this._setOnHash(styles, nameOrStyles, value) || didChange;
|
895
891
|
}
|
896
892
|
|
897
|
-
if
|
898
|
-
|
899
|
-
//
|
900
|
-
|
901
|
-
// Note: jQuery .css doesn't remove old styles
|
902
|
-
this.$().css(styles);
|
903
|
-
}
|
893
|
+
// Set the styles on the element if we have one already.
|
894
|
+
if (didChange && this._elem) {
|
895
|
+
// Note: jQuery .css doesn't remove old styles
|
896
|
+
this.$().css(styles);
|
904
897
|
}
|
905
898
|
|
906
899
|
return this;
|
907
900
|
},
|
908
901
|
|
902
|
+
/** @private Sets the style by key from the styles object. This allows for optimization outside of the for..in loop. */
|
903
|
+
_sc_setStyleFromObject: function (didChange, key, stylesObject, styles) {
|
904
|
+
if (!stylesObject.hasOwnProperty(key)) return false;
|
905
|
+
|
906
|
+
var value = stylesObject[key];
|
907
|
+
|
908
|
+
didChange = this._deleteComboStyles(styles, key) || didChange;
|
909
|
+
didChange = this._setOnHash(styles, key, value) || didChange;
|
910
|
+
|
911
|
+
return didChange;
|
912
|
+
},
|
913
|
+
|
909
914
|
/** @private */
|
910
915
|
_deleteComboStyles: function (styles, key) {
|
911
916
|
var comboStyles = SC.COMBO_STYLES[key],
|
@@ -926,10 +931,10 @@ SC.RenderContext = SC.Builder.create(
|
|
926
931
|
|
927
932
|
/** @private Sets or unsets the key:value on the hash and returns whether a change occurred. */
|
928
933
|
_setOnHash: function (hash, key, value) {
|
929
|
-
/*jshint eqnull:true*/
|
930
934
|
var cur = hash[key],
|
931
935
|
didChange = true;
|
932
936
|
|
937
|
+
/*jshint eqnull:true */
|
933
938
|
if (cur == null && value != null) {
|
934
939
|
hash[key] = value;
|
935
940
|
} else if (cur != null && value == null) {
|
@@ -1009,7 +1014,7 @@ SC.RenderContext = SC.Builder.create(
|
|
1009
1014
|
attr = elAttrs.item(i);
|
1010
1015
|
name = attr.nodeName;
|
1011
1016
|
if (name.match(/^(?!class|style).*$/i)) {
|
1012
|
-
attrs[name] = attr.
|
1017
|
+
attrs[name] = attr.value;
|
1013
1018
|
}
|
1014
1019
|
}
|
1015
1020
|
|
@@ -2,7 +2,7 @@
|
|
2
2
|
Polyfill for cross-browser backwards compatible window.requestAnimationFrame
|
3
3
|
support.
|
4
4
|
|
5
|
-
|
5
|
+
Modified from Erik Möller:
|
6
6
|
http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
|
7
7
|
*/
|
8
8
|
(function() {
|
@@ -14,18 +14,17 @@
|
|
14
14
|
'CancelRequestAnimationFrame'];
|
15
15
|
}
|
16
16
|
|
17
|
-
if (!window.requestAnimationFrame)
|
18
|
-
window.requestAnimationFrame = function(callback
|
17
|
+
if (!window.requestAnimationFrame) {
|
18
|
+
window.requestAnimationFrame = function(callback) {
|
19
19
|
var currTime = new Date().getTime();
|
20
20
|
var timeToCall = Math.max(0, 16 - (currTime - lastTime));
|
21
|
-
var id = window.setTimeout(function() { callback(
|
22
|
-
timeToCall);
|
21
|
+
var id = window.setTimeout(function() { callback(window.performance.now()); }, timeToCall);
|
23
22
|
lastTime = currTime + timeToCall;
|
24
23
|
return id;
|
25
24
|
};
|
25
|
+
}
|
26
26
|
|
27
|
-
if (!window.cancelAnimationFrame)
|
28
|
-
window.cancelAnimationFrame = function(id) {
|
29
|
-
|
30
|
-
|
31
|
-
}())
|
27
|
+
if (!window.cancelAnimationFrame) {
|
28
|
+
window.cancelAnimationFrame = function(id) { clearTimeout(id); };
|
29
|
+
}
|
30
|
+
}());
|
@@ -7,9 +7,10 @@
|
|
7
7
|
|
8
8
|
sc_require('system/ready');
|
9
9
|
sc_require('system/platform');
|
10
|
+
sc_require('system/touch');
|
10
11
|
|
11
12
|
/** Set to NO to leave the backspace key under the control of the browser.*/
|
12
|
-
SC.CAPTURE_BACKSPACE_KEY = NO;
|
13
|
+
SC.CAPTURE_BACKSPACE_KEY = NO ;
|
13
14
|
|
14
15
|
/** @class
|
15
16
|
|
@@ -57,7 +58,7 @@ SC.RootResponder = SC.Object.extend(
|
|
57
58
|
*/
|
58
59
|
panes: null,
|
59
60
|
|
60
|
-
init: function
|
61
|
+
init: function() {
|
61
62
|
sc_super();
|
62
63
|
this.panes = SC.Set.create();
|
63
64
|
},
|
@@ -91,24 +92,24 @@ SC.RootResponder = SC.Object.extend(
|
|
91
92
|
@param {SC.Pane} pane
|
92
93
|
@returns {SC.RootResponder}
|
93
94
|
*/
|
94
|
-
makeMainPane: function
|
95
|
-
var currentMain = this.get('mainPane');
|
96
|
-
if (currentMain === pane) return this; // nothing to do
|
95
|
+
makeMainPane: function(pane) {
|
96
|
+
var currentMain = this.get('mainPane') ;
|
97
|
+
if (currentMain === pane) return this ; // nothing to do
|
97
98
|
|
98
|
-
this.beginPropertyChanges();
|
99
|
+
this.beginPropertyChanges() ;
|
99
100
|
|
100
101
|
// change key focus if needed.
|
101
|
-
if (this.get('keyPane') === currentMain) this.makeKeyPane(pane);
|
102
|
+
if (this.get('keyPane') === currentMain) this.makeKeyPane(pane) ;
|
102
103
|
|
103
104
|
// change setting
|
104
|
-
this.set('mainPane', pane);
|
105
|
+
this.set('mainPane', pane) ;
|
105
106
|
|
106
107
|
// notify panes. This will allow them to remove themselves.
|
107
|
-
if (currentMain) currentMain.blurMainTo(pane);
|
108
|
-
if (pane) pane.focusMainFrom(currentMain);
|
108
|
+
if (currentMain) currentMain.blurMainTo(pane) ;
|
109
|
+
if (pane) pane.focusMainFrom(currentMain) ;
|
109
110
|
|
110
|
-
this.endPropertyChanges();
|
111
|
-
return this;
|
111
|
+
this.endPropertyChanges() ;
|
112
|
+
return this ;
|
112
113
|
},
|
113
114
|
|
114
115
|
// ..........................................................
|
@@ -136,7 +137,7 @@ SC.RootResponder = SC.Object.extend(
|
|
136
137
|
@param {SC.MenuPane} pane
|
137
138
|
@returns {SC.RootResponder} receiver
|
138
139
|
*/
|
139
|
-
makeMenuPane: function
|
140
|
+
makeMenuPane: function(pane) {
|
140
141
|
// Does the specified pane accept being the menu pane? If not, there's
|
141
142
|
// nothing to do.
|
142
143
|
if (pane && !pane.get('acceptsMenuPane')) {
|
@@ -164,10 +165,11 @@ SC.RootResponder = SC.Object.extend(
|
|
164
165
|
*/
|
165
166
|
keyPane: null,
|
166
167
|
|
167
|
-
/** @
|
168
|
-
A stack of
|
168
|
+
/** @private
|
169
|
+
A stack of previous key panes. Used to allow panes to resign key pane
|
170
|
+
status without having to know who had it before them.
|
169
171
|
|
170
|
-
|
172
|
+
NOTE: This property is not observable.
|
171
173
|
*/
|
172
174
|
previousKeyPanes: [],
|
173
175
|
|
@@ -180,32 +182,39 @@ SC.RootResponder = SC.Object.extend(
|
|
180
182
|
@param {SC.Pane} pane
|
181
183
|
@returns {SC.RootResponder} receiver
|
182
184
|
*/
|
183
|
-
makeKeyPane: function
|
185
|
+
makeKeyPane: function(pane) {
|
186
|
+
// Quick note about previousKeyPanes: if a pane is destroyed while in the
|
187
|
+
// previous panes stack, it will retain a reference to it here, causing a
|
188
|
+
// brief leak. The reference will be removed as soon as the panes above it
|
189
|
+
// in the stack resign, so it's rarely an issue, and fixing it would require
|
190
|
+
// a dedicated method and some extra coordination that's probably not worth
|
191
|
+
// it.
|
192
|
+
|
184
193
|
// Was a pane specified?
|
185
|
-
var newKeyPane, previousKeyPane, previousKeyPanes;
|
194
|
+
var newKeyPane, previousKeyPane, previousKeyPanes ;
|
186
195
|
|
187
196
|
if (pane) {
|
188
197
|
// Does the specified pane accept being the key pane? If not, there's
|
189
198
|
// nothing to do.
|
190
199
|
if (!pane.get('acceptsKeyPane')) {
|
191
|
-
return this;
|
200
|
+
return this ;
|
192
201
|
}
|
193
202
|
else {
|
194
203
|
// It does accept key pane status? Then push the current keyPane to
|
195
204
|
// the top of the stack and make the specified pane the new keyPane.
|
196
205
|
// First, though, do a sanity-check to make sure it's not already the
|
197
206
|
// key pane, in which case we have nothing to do.
|
198
|
-
previousKeyPane = this.get('keyPane');
|
207
|
+
previousKeyPane = this.get('keyPane') ;
|
199
208
|
if (previousKeyPane === pane) {
|
200
|
-
return this;
|
209
|
+
return this ;
|
201
210
|
}
|
202
211
|
else {
|
203
212
|
if (previousKeyPane) {
|
204
|
-
previousKeyPanes = this.get('previousKeyPanes');
|
205
|
-
previousKeyPanes.push(previousKeyPane);
|
213
|
+
previousKeyPanes = this.get('previousKeyPanes') ;
|
214
|
+
previousKeyPanes.push(previousKeyPane) ;
|
206
215
|
}
|
207
216
|
|
208
|
-
newKeyPane = pane;
|
217
|
+
newKeyPane = pane ;
|
209
218
|
}
|
210
219
|
}
|
211
220
|
} else {
|
@@ -214,16 +223,16 @@ SC.RootResponder = SC.Object.extend(
|
|
214
223
|
// attached and accepts key pane (its value for acceptsKeyPane might
|
215
224
|
// have changed in the meantime). Otherwise, we'll keep going up the
|
216
225
|
// stack.
|
217
|
-
previousKeyPane = this.get('keyPane');
|
218
|
-
previousKeyPanes = this.get('previousKeyPanes');
|
226
|
+
previousKeyPane = this.get('keyPane') ;
|
227
|
+
previousKeyPanes = this.get('previousKeyPanes') ;
|
219
228
|
|
220
|
-
newKeyPane = null;
|
229
|
+
newKeyPane = null ;
|
221
230
|
var candidate;
|
222
231
|
while (previousKeyPanes.length > 0) {
|
223
232
|
candidate = previousKeyPanes.pop();
|
224
233
|
if (candidate.get('isPaneAttached') && candidate.get('acceptsKeyPane')) {
|
225
|
-
newKeyPane = candidate;
|
226
|
-
break;
|
234
|
+
newKeyPane = candidate ;
|
235
|
+
break ;
|
227
236
|
}
|
228
237
|
}
|
229
238
|
}
|
@@ -232,20 +241,20 @@ SC.RootResponder = SC.Object.extend(
|
|
232
241
|
// If we found an appropriate candidate, make it the new key pane.
|
233
242
|
// Otherwise, make the main pane the key pane (if it accepts it).
|
234
243
|
if (!newKeyPane) {
|
235
|
-
var mainPane = this.get('mainPane');
|
236
|
-
if (mainPane && mainPane.get('acceptsKeyPane')) newKeyPane = mainPane;
|
244
|
+
var mainPane = this.get('mainPane') ;
|
245
|
+
if (mainPane && mainPane.get('acceptsKeyPane')) newKeyPane = mainPane ;
|
237
246
|
}
|
238
247
|
|
239
248
|
// now notify old and new key views of change after edit
|
240
|
-
if (previousKeyPane) previousKeyPane.willLoseKeyPaneTo(newKeyPane);
|
241
|
-
if (newKeyPane) newKeyPane.willBecomeKeyPaneFrom(previousKeyPane);
|
249
|
+
if (previousKeyPane) previousKeyPane.willLoseKeyPaneTo(newKeyPane) ;
|
250
|
+
if (newKeyPane) newKeyPane.willBecomeKeyPaneFrom(previousKeyPane) ;
|
242
251
|
|
243
|
-
this.set('keyPane', newKeyPane);
|
252
|
+
this.set('keyPane', newKeyPane) ;
|
244
253
|
|
245
|
-
if (newKeyPane) newKeyPane.didBecomeKeyPaneFrom(previousKeyPane);
|
246
|
-
if (previousKeyPane) previousKeyPane.didLoseKeyPaneTo(newKeyPane);
|
254
|
+
if (newKeyPane) newKeyPane.didBecomeKeyPaneFrom(previousKeyPane) ;
|
255
|
+
if (previousKeyPane) previousKeyPane.didLoseKeyPaneTo(newKeyPane) ;
|
247
256
|
|
248
|
-
return this;
|
257
|
+
return this ;
|
249
258
|
},
|
250
259
|
|
251
260
|
// ..........................................................
|
@@ -264,14 +273,14 @@ SC.RootResponder = SC.Object.extend(
|
|
264
273
|
|
265
274
|
@returns Rect
|
266
275
|
*/
|
267
|
-
computeWindowSize: function
|
276
|
+
computeWindowSize: function() {
|
268
277
|
var size, bod, docElement;
|
269
|
-
if
|
278
|
+
if(!this._bod || !this._docElement){
|
270
279
|
bod = document.body;
|
271
280
|
docElement = document.documentElement;
|
272
|
-
this._bod
|
273
|
-
this._docElement
|
274
|
-
}
|
281
|
+
this._bod=bod;
|
282
|
+
this._docElement=docElement;
|
283
|
+
}else{
|
275
284
|
bod = this._bod;
|
276
285
|
docElement = this._docElement;
|
277
286
|
}
|
@@ -280,7 +289,7 @@ SC.RootResponder = SC.Object.extend(
|
|
280
289
|
size = {
|
281
290
|
width: window.innerWidth,
|
282
291
|
height: window.innerHeight
|
283
|
-
};
|
292
|
+
} ;
|
284
293
|
} else if (docElement && docElement.clientHeight) {
|
285
294
|
size = {
|
286
295
|
width: docElement.clientWidth,
|
@@ -290,7 +299,7 @@ SC.RootResponder = SC.Object.extend(
|
|
290
299
|
size = {
|
291
300
|
width: bod.clientWidth,
|
292
301
|
height: bod.clientHeight
|
293
|
-
};
|
302
|
+
} ;
|
294
303
|
}
|
295
304
|
return size;
|
296
305
|
},
|
@@ -300,27 +309,46 @@ SC.RootResponder = SC.Object.extend(
|
|
300
309
|
|
301
310
|
@returns {Boolean}
|
302
311
|
*/
|
303
|
-
resize: function
|
312
|
+
resize: function() {
|
304
313
|
this._resize();
|
314
|
+
this._assignDesignMode();
|
305
315
|
|
306
316
|
return YES; //always allow normal processing to continue.
|
307
317
|
},
|
308
318
|
|
309
|
-
|
319
|
+
/** @private */
|
320
|
+
_resize: function() {
|
310
321
|
// calculate new window size...
|
311
322
|
var newSize = this.computeWindowSize(), oldSize = this.get('currentWindowSize');
|
312
323
|
this.set('currentWindowSize', newSize); // update size
|
313
324
|
|
314
325
|
if (!SC.rectsEqual(newSize, oldSize)) {
|
326
|
+
SC.run(function() {
|
327
|
+
//Notify orientation change. This is faster than waiting for the orientation
|
328
|
+
//change event.
|
329
|
+
SC.device.windowSizeDidChange(newSize);
|
330
|
+
|
331
|
+
// notify panes
|
332
|
+
if (this.panes) {
|
333
|
+
if (oldSize !== newSize) {
|
334
|
+
this.panes.invoke('windowSizeDidChange', oldSize, newSize);
|
335
|
+
}
|
336
|
+
}
|
337
|
+
}, this);
|
338
|
+
}
|
339
|
+
},
|
315
340
|
|
316
|
-
|
317
|
-
|
318
|
-
|
341
|
+
/** @private */
|
342
|
+
_assignDesignMode: function () {
|
343
|
+
var newDesignMode = this.computeDesignMode(),
|
344
|
+
oldDesignMode = this.get('currentDesignMode');
|
345
|
+
|
346
|
+
if (oldDesignMode !== newDesignMode) {
|
347
|
+
this.set('currentDesignMode', newDesignMode);
|
319
348
|
|
320
|
-
// notify panes
|
321
349
|
if (this.panes) {
|
322
|
-
SC.run(function
|
323
|
-
this.panes.invoke('
|
350
|
+
SC.run(function() {
|
351
|
+
this.panes.invoke('updateDesignMode', oldDesignMode, newDesignMode);
|
324
352
|
}, this);
|
325
353
|
}
|
326
354
|
}
|
@@ -340,46 +368,46 @@ SC.RootResponder = SC.Object.extend(
|
|
340
368
|
Handle window focus. Change hasFocus and add sc-focus CSS class
|
341
369
|
(removing sc-blur). Also notify panes.
|
342
370
|
*/
|
343
|
-
focus: function
|
371
|
+
focus: function(evt) {
|
344
372
|
if (!this.get('hasFocus')) {
|
345
373
|
SC.$('body').addClass('sc-focus').removeClass('sc-blur');
|
346
374
|
|
347
375
|
SC.run(function () {
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
}
|
376
|
+
// If the app is getting focus again set the first responder to the first
|
377
|
+
// valid firstResponder view in the view's tree
|
378
|
+
if(!SC.TABBING_ONLY_INSIDE_DOCUMENT && !SC.browser.isIE8OrLower){
|
379
|
+
var keyPane = SC.RootResponder.responder.get('keyPane');
|
380
|
+
if (keyPane) {
|
381
|
+
var nextValidKeyView = keyPane.get('nextValidKeyView');
|
382
|
+
if (nextValidKeyView) keyPane.makeFirstResponder(nextValidKeyView);
|
356
383
|
}
|
384
|
+
}
|
357
385
|
|
358
386
|
this.set('hasFocus', YES);
|
359
387
|
}, this);
|
360
388
|
}
|
361
389
|
|
362
|
-
return YES; // allow default
|
390
|
+
return YES ; // allow default
|
363
391
|
},
|
364
392
|
|
365
393
|
/**
|
366
394
|
Handle window focus event for IE. Listening to the focus event is not
|
367
395
|
reliable as per every focus event you receive you immediately get a blur
|
368
|
-
event (Only on IE of course;)
|
396
|
+
event (Only on IE of course ;)
|
369
397
|
*/
|
370
|
-
focusin: function
|
371
|
-
if
|
398
|
+
focusin: function(evt) {
|
399
|
+
if(this._focusTimeout) clearTimeout(this._focusTimeout);
|
372
400
|
this.focus(evt);
|
373
401
|
},
|
374
402
|
|
375
403
|
/**
|
376
404
|
Handle window blur event for IE. Listening to the focus event is not
|
377
405
|
reliable as per every focus event you receive you immediately get a blur
|
378
|
-
event (Only on IE of course;)
|
406
|
+
event (Only on IE of course ;)
|
379
407
|
*/
|
380
|
-
focusout: function
|
408
|
+
focusout: function(evt) {
|
381
409
|
var that = this;
|
382
|
-
this._focusTimeout = setTimeout(function
|
410
|
+
this._focusTimeout = setTimeout(function(){that.blur(evt);}, 300);
|
383
411
|
},
|
384
412
|
|
385
413
|
|
@@ -387,20 +415,128 @@ SC.RootResponder = SC.Object.extend(
|
|
387
415
|
Handle window focus. Change hasFocus and add sc-focus CSS class (removing
|
388
416
|
sc-blur). Also notify panes.
|
389
417
|
*/
|
390
|
-
blur: function
|
418
|
+
blur: function(evt) {
|
391
419
|
if (this.get('hasFocus')) {
|
392
420
|
SC.$('body').addClass('sc-blur').removeClass('sc-focus');
|
393
421
|
|
394
|
-
SC.run(function
|
422
|
+
SC.run(function() {
|
395
423
|
this.set('hasFocus', NO);
|
396
424
|
}, this);
|
397
425
|
}
|
398
|
-
return YES; // allow default
|
426
|
+
return YES ; // allow default
|
427
|
+
},
|
428
|
+
|
429
|
+
dragDidStart: function(drag) {
|
430
|
+
this._mouseDownView = drag ;
|
431
|
+
this._drag = drag ;
|
432
|
+
},
|
433
|
+
|
434
|
+
// ------------------------------------------------------------------------
|
435
|
+
// Design Modes
|
436
|
+
//
|
437
|
+
|
438
|
+
/** @private */
|
439
|
+
currentDesignMode: null,
|
440
|
+
|
441
|
+
/** @private Managed by SC.Application. */
|
442
|
+
designModes: function (key, value) {
|
443
|
+
if (SC.none(value)) {
|
444
|
+
// Clear previous values.
|
445
|
+
if (this._designModeNames) {
|
446
|
+
delete this._designModeNames;
|
447
|
+
delete this._designModeThresholds;
|
448
|
+
}
|
449
|
+
|
450
|
+
value = null;
|
451
|
+
} else {
|
452
|
+
this._prepOrderedArrays(value);
|
453
|
+
}
|
454
|
+
|
455
|
+
this._assignDesignMode();
|
456
|
+
|
457
|
+
return value;
|
458
|
+
}.property().cacheable(),
|
459
|
+
|
460
|
+
/** @private Determine the design mode based on area and pixel density. */
|
461
|
+
computeDesignMode: function () {
|
462
|
+
var designMode = null,
|
463
|
+
designModeNames = this._designModeNames,
|
464
|
+
designModeThresholds = this._designModeThresholds,
|
465
|
+
currentWindowSize,
|
466
|
+
area;
|
467
|
+
|
468
|
+
// Fast path!
|
469
|
+
if (!designModeNames) { return null; }
|
470
|
+
|
471
|
+
currentWindowSize = this.get('currentWindowSize');
|
472
|
+
area = (currentWindowSize.width * currentWindowSize.height);
|
473
|
+
var i, len;
|
474
|
+
for (i = 0, len = designModeThresholds.get('length'); i < len; i++) {
|
475
|
+
var layoutWidthThreshold = designModeThresholds.objectAt(i);
|
476
|
+
if (area < layoutWidthThreshold) {
|
477
|
+
designMode = designModeNames.objectAt(i);
|
478
|
+
break;
|
479
|
+
}
|
480
|
+
}
|
481
|
+
|
482
|
+
// If no smaller designMode was found, use the biggest designMode.
|
483
|
+
if (SC.none(designMode) && designModeNames && designModeNames.get('length') > 0) {
|
484
|
+
designMode = designModeNames.objectAt(i);
|
485
|
+
}
|
486
|
+
|
487
|
+
return SC.device.orientation === SC.PORTRAIT_ORIENTATION ? designMode + '_p' : designMode + '_l';
|
488
|
+
},
|
489
|
+
|
490
|
+
/** @private (semi-private)
|
491
|
+
Returns the fallback design mode for the given design mode. This is
|
492
|
+
primarily used by SC.View for the case where an adjustment isn't found
|
493
|
+
for the current design mode and we want to apply the next best design
|
494
|
+
mode as a fallback.
|
495
|
+
*/
|
496
|
+
fallbackDesignMode: function (designMode) {
|
497
|
+
var designModeNames = this._designModeNames,
|
498
|
+
index,
|
499
|
+
ret = null;
|
500
|
+
|
501
|
+
index = designModeNames.indexOf(designMode);
|
502
|
+
if (index >= 0) {
|
503
|
+
ret = designModeNames[index - 1];
|
504
|
+
}
|
505
|
+
|
506
|
+
return ret;
|
399
507
|
},
|
400
508
|
|
401
|
-
|
402
|
-
|
403
|
-
|
509
|
+
/** @private Prepares ordered design modes & widths arrays when designModes changes. */
|
510
|
+
_prepOrderedArrays: function (designModes) {
|
511
|
+
var designModeNames,
|
512
|
+
designModeThresholds;
|
513
|
+
|
514
|
+
// Order the design modes for easier access later.
|
515
|
+
if (designModes) {
|
516
|
+
designModeNames = this._designModeNames = [];
|
517
|
+
designModeThresholds = this._designModeThresholds = [];
|
518
|
+
|
519
|
+
var key;
|
520
|
+
|
521
|
+
outer:
|
522
|
+
for (key in designModes) {
|
523
|
+
var i, value;
|
524
|
+
|
525
|
+
// Assume that the keys will be ordered smallest to largest so run backwards.
|
526
|
+
value = designModes[key];
|
527
|
+
inner:
|
528
|
+
for (i = designModeThresholds.length - 1; i >= 0; i--) {
|
529
|
+
if (designModeThresholds[i] < value) {
|
530
|
+
// Exit early!
|
531
|
+
break inner;
|
532
|
+
}
|
533
|
+
}
|
534
|
+
|
535
|
+
i += 1;
|
536
|
+
designModeNames.splice(i, 0, key);
|
537
|
+
designModeThresholds.splice(i, 0, value);
|
538
|
+
}
|
539
|
+
}
|
404
540
|
},
|
405
541
|
|
406
542
|
// .......................................................
|
@@ -436,8 +572,8 @@ SC.RootResponder = SC.Object.extend(
|
|
436
572
|
@returns {Boolean} YES if action was performed, NO otherwise
|
437
573
|
@test in targetForAction
|
438
574
|
*/
|
439
|
-
sendAction: function
|
440
|
-
target = this.targetForAction(action, target, sender, pane, firstResponder);
|
575
|
+
sendAction: function( action, target, sender, pane, context, firstResponder) {
|
576
|
+
target = this.targetForAction(action, target, sender, pane, firstResponder) ;
|
441
577
|
|
442
578
|
// HACK: If the target is a ResponderContext, forward the action.
|
443
579
|
if (target && target.isResponderContext) {
|
@@ -445,14 +581,14 @@ SC.RootResponder = SC.Object.extend(
|
|
445
581
|
} else return target && target.tryToPerform(action, sender);
|
446
582
|
},
|
447
583
|
|
448
|
-
_responderFor: function
|
584
|
+
_responderFor: function(target, methodName, firstResponder) {
|
449
585
|
var defaultResponder = target ? target.get('defaultResponder') : null;
|
450
586
|
|
451
587
|
if (target) {
|
452
588
|
target = firstResponder || target.get('firstResponder') || target;
|
453
589
|
do {
|
454
|
-
if (target.respondsTo(methodName)) return target;
|
455
|
-
} while ((target = target.get('nextResponder')));
|
590
|
+
if (target.respondsTo(methodName)) return target ;
|
591
|
+
} while ((target = target.get('nextResponder'))) ;
|
456
592
|
}
|
457
593
|
|
458
594
|
// HACK: Eventually we need to normalize the sendAction() method between
|
@@ -489,11 +625,11 @@ SC.RootResponder = SC.Object.extend(
|
|
489
625
|
@param {firstResponder} a first responder to use
|
490
626
|
@returns {Object} target object or null if none found
|
491
627
|
*/
|
492
|
-
targetForAction: function
|
628
|
+
targetForAction: function(methodName, target, sender, pane, firstResponder) {
|
493
629
|
|
494
630
|
// 1. no action, no target...
|
495
631
|
if (!methodName || (SC.typeOf(methodName) !== SC.T_STRING)) {
|
496
|
-
return null;
|
632
|
+
return null ;
|
497
633
|
}
|
498
634
|
|
499
635
|
// 2. an explicit target was passed...
|
@@ -505,13 +641,13 @@ SC.RootResponder = SC.Object.extend(
|
|
505
641
|
|
506
642
|
if (target && !target.isResponderContext) {
|
507
643
|
if (target.respondsTo && !target.respondsTo(methodName)) {
|
508
|
-
target = null;
|
644
|
+
target = null ;
|
509
645
|
} else if (SC.typeOf(target[methodName]) !== SC.T_FUNCTION) {
|
510
|
-
target = null;
|
646
|
+
target = null ;
|
511
647
|
}
|
512
648
|
}
|
513
649
|
|
514
|
-
return target;
|
650
|
+
return target ;
|
515
651
|
}
|
516
652
|
|
517
653
|
// 3. an explicit pane was passed...
|
@@ -522,32 +658,32 @@ SC.RootResponder = SC.Object.extend(
|
|
522
658
|
|
523
659
|
// 4. no target or pane passed... try to find target in the active panes
|
524
660
|
// and the defaultResponder
|
525
|
-
var keyPane = this.get('keyPane'), mainPane = this.get('mainPane');
|
661
|
+
var keyPane = this.get('keyPane'), mainPane = this.get('mainPane') ;
|
526
662
|
|
527
663
|
// ...check key and main panes first
|
528
664
|
if (keyPane && (keyPane !== pane)) {
|
529
|
-
target = this._responderFor(keyPane, methodName);
|
665
|
+
target = this._responderFor(keyPane, methodName) ;
|
530
666
|
}
|
531
667
|
if (!target && mainPane && (mainPane !== keyPane)) {
|
532
|
-
target = this._responderFor(mainPane, methodName);
|
668
|
+
target = this._responderFor(mainPane, methodName) ;
|
533
669
|
}
|
534
670
|
|
535
671
|
// ...still no target? check the defaultResponder...
|
536
672
|
if (!target && (target = this.get('defaultResponder'))) {
|
537
673
|
if (SC.typeOf(target) === SC.T_STRING) {
|
538
|
-
target = SC.objectForPropertyPath(target);
|
539
|
-
if (target) this.set('defaultResponder', target); // cache if found
|
674
|
+
target = SC.objectForPropertyPath(target) ;
|
675
|
+
if (target) this.set('defaultResponder', target) ; // cache if found
|
540
676
|
}
|
541
677
|
if (target && !target.isResponderContext) {
|
542
678
|
if (target.respondsTo && !target.respondsTo(methodName)) {
|
543
|
-
target = null;
|
679
|
+
target = null ;
|
544
680
|
} else if (SC.typeOf(target[methodName]) !== SC.T_FUNCTION) {
|
545
|
-
target = null;
|
681
|
+
target = null ;
|
546
682
|
}
|
547
683
|
}
|
548
684
|
}
|
549
685
|
|
550
|
-
return target;
|
686
|
+
return target ;
|
551
687
|
},
|
552
688
|
|
553
689
|
/**
|
@@ -558,7 +694,10 @@ SC.RootResponder = SC.Object.extend(
|
|
558
694
|
@returns {SC.View} view instance or null
|
559
695
|
*/
|
560
696
|
targetViewForEvent: function (evt) {
|
561
|
-
|
697
|
+
var ret = null;
|
698
|
+
if (evt.target) { ret = SC.viewFor(evt.target); }
|
699
|
+
|
700
|
+
return ret;
|
562
701
|
},
|
563
702
|
|
564
703
|
/**
|
@@ -575,19 +714,19 @@ SC.RootResponder = SC.Object.extend(
|
|
575
714
|
@param {Object} target
|
576
715
|
@returns {Object} object that handled the event or null if not handled
|
577
716
|
*/
|
578
|
-
sendEvent: function
|
579
|
-
var pane, ret;
|
717
|
+
sendEvent: function(action, evt, target) {
|
718
|
+
var pane, ret ;
|
580
719
|
|
581
|
-
SC.run(function
|
720
|
+
SC.run(function() {
|
582
721
|
// get the target pane
|
583
|
-
if (target) pane = target.get('pane');
|
584
|
-
else pane = this.get('menuPane') || this.get('keyPane') || this.get('mainPane');
|
722
|
+
if (target) pane = target.get('pane') ;
|
723
|
+
else pane = this.get('menuPane') || this.get('keyPane') || this.get('mainPane') ;
|
585
724
|
|
586
725
|
// if we found a valid pane, send the event to it
|
587
|
-
ret = (pane) ? pane.sendEvent(action, evt, target) : null;
|
726
|
+
ret = (pane) ? pane.sendEvent(action, evt, target) : null ;
|
588
727
|
}, this);
|
589
728
|
|
590
|
-
return ret;
|
729
|
+
return ret ;
|
591
730
|
},
|
592
731
|
|
593
732
|
// .......................................................
|
@@ -607,16 +746,16 @@ SC.RootResponder = SC.Object.extend(
|
|
607
746
|
@param {Boolean} useCapture
|
608
747
|
@returns {SC.RootResponder} receiver
|
609
748
|
*/
|
610
|
-
listenFor: function
|
749
|
+
listenFor: function(keyNames, target, receiver, useCapture) {
|
611
750
|
receiver = receiver ? receiver : this;
|
612
|
-
keyNames.forEach(function
|
613
|
-
var method = receiver[keyName];
|
614
|
-
if (method) SC.Event.add(target, keyName, receiver, method, null, useCapture);
|
615
|
-
},
|
751
|
+
keyNames.forEach( function(keyName) {
|
752
|
+
var method = receiver[keyName] ;
|
753
|
+
if (method) SC.Event.add(target, keyName, receiver, method, null, useCapture) ;
|
754
|
+
},this) ;
|
616
755
|
|
617
|
-
target = null;
|
756
|
+
target = null ;
|
618
757
|
|
619
|
-
return receiver;
|
758
|
+
return receiver ;
|
620
759
|
},
|
621
760
|
|
622
761
|
/**
|
@@ -626,20 +765,20 @@ SC.RootResponder = SC.Object.extend(
|
|
626
765
|
|
627
766
|
@returns {void}
|
628
767
|
*/
|
629
|
-
setup: function
|
768
|
+
setup: function() {
|
630
769
|
// handle basic events
|
631
|
-
this.listenFor(['touchstart', 'touchmove', 'touchend', 'touchcancel', 'keydown', 'keyup', 'beforedeactivate', 'mousedown', 'mouseup', 'click', 'dblclick', 'mousemove', 'contextmenu'], document)
|
770
|
+
this.listenFor(['touchstart', 'touchmove', 'touchend', 'touchcancel', 'keydown', 'keyup', 'beforedeactivate', 'mousedown', 'mouseup', 'dragenter', 'dragover', 'dragleave', 'drop', 'click', 'dblclick', 'mousemove', 'contextmenu'], document)
|
632
771
|
.listenFor(['resize'], window);
|
633
772
|
|
634
|
-
if
|
773
|
+
if(SC.browser.isIE8OrLower) this.listenFor(['focusin', 'focusout'], document);
|
635
774
|
else this.listenFor(['focus', 'blur'], window);
|
636
775
|
|
637
776
|
// handle special case for keypress- you can't use normal listener to block
|
638
777
|
// the backspace key on Mozilla
|
639
778
|
if (this.keypress) {
|
640
779
|
if (SC.CAPTURE_BACKSPACE_KEY && SC.browser.isMozilla) {
|
641
|
-
var responder = this;
|
642
|
-
document.onkeypress = function
|
780
|
+
var responder = this ;
|
781
|
+
document.onkeypress = function(e) {
|
643
782
|
e = SC.Event.normalizeEvent(e);
|
644
783
|
return responder.keypress.call(responder, e);
|
645
784
|
};
|
@@ -702,19 +841,19 @@ SC.RootResponder = SC.Object.extend(
|
|
702
841
|
}
|
703
842
|
|
704
843
|
// handle these two events specially in IE
|
705
|
-
['drag', 'selectstart'].forEach(function
|
706
|
-
var method = this[keyName];
|
844
|
+
['drag', 'selectstart'].forEach(function(keyName) {
|
845
|
+
var method = this[keyName] ;
|
707
846
|
if (method) {
|
708
847
|
if (SC.browser.isIE) {
|
709
|
-
var responder = this;
|
848
|
+
var responder = this ;
|
710
849
|
|
711
|
-
document.body['on' + keyName] = function
|
850
|
+
document.body['on' + keyName] = function(e) {
|
712
851
|
// return method.call(responder, SC.Event.normalizeEvent(e));
|
713
852
|
return method.call(responder, SC.Event.normalizeEvent(event || window.event)); // this is IE :(
|
714
853
|
};
|
715
854
|
|
716
855
|
// be sure to cleanup memory leaks
|
717
|
-
|
856
|
+
SC.Event.add(window, 'unload', this, function() {
|
718
857
|
document.body['on' + keyName] = null;
|
719
858
|
});
|
720
859
|
|
@@ -741,8 +880,8 @@ SC.RootResponder = SC.Object.extend(
|
|
741
880
|
}
|
742
881
|
SC.Event.add(document, mousewheel, this, this.mousewheel);
|
743
882
|
|
744
|
-
//
|
745
|
-
this.set('currentWindowSize', this.computeWindowSize());
|
883
|
+
// Do some initial set up.
|
884
|
+
this.set('currentWindowSize', this.computeWindowSize()) ;
|
746
885
|
|
747
886
|
// TODO: Is this workaround still valid?
|
748
887
|
if (SC.browser.os === SC.OS.ios && SC.browser.name === SC.BROWSER.safari) {
|
@@ -757,7 +896,7 @@ SC.RootResponder = SC.Object.extend(
|
|
757
896
|
// Monkey patch RunLoop if we're in MobileSafari
|
758
897
|
var f = SC.RunLoop.prototype.endRunLoop, patch;
|
759
898
|
|
760
|
-
patch = function
|
899
|
+
patch = function() {
|
761
900
|
// Call original endRunLoop implementation.
|
762
901
|
if (f) f.apply(this, arguments);
|
763
902
|
|
@@ -832,10 +971,10 @@ SC.RootResponder = SC.Object.extend(
|
|
832
971
|
// Once the actual event name is determined, simply remove all the extras.
|
833
972
|
// This should prevent any problems with browsers that fire multiple events.
|
834
973
|
['transitionend', variation1, variation2, variation3].forEach(function (keyName) {
|
835
|
-
if (keyName
|
974
|
+
if (keyName !== actualEventName) {
|
836
975
|
SC.Event.remove(document, keyName, this, this[keyName]);
|
837
976
|
this[keyName] = null;
|
838
|
-
|
977
|
+
}
|
839
978
|
});
|
840
979
|
},
|
841
980
|
|
@@ -860,10 +999,10 @@ SC.RootResponder = SC.Object.extend(
|
|
860
999
|
// Once the actual event name is determined, simply remove all the extras.
|
861
1000
|
// This should prevent any problems with browsers that fire multiple events.
|
862
1001
|
['animationend', variation1, variation2, variation3].forEach(function (keyName) {
|
863
|
-
if (keyName
|
1002
|
+
if (keyName !== actualEventName) {
|
864
1003
|
SC.Event.remove(document, keyName, this, this[keyName]);
|
865
1004
|
this[keyName] = null;
|
866
|
-
|
1005
|
+
}
|
867
1006
|
});
|
868
1007
|
|
869
1008
|
actualEventName = SC.platform.animationiterationEventName;
|
@@ -871,7 +1010,7 @@ SC.RootResponder = SC.Object.extend(
|
|
871
1010
|
variation2 = lowerDomPrefix + 'AnimationIteration';
|
872
1011
|
variation3 = domPrefix + 'AnimationIteration';
|
873
1012
|
['animationiteration', variation1, variation2, variation3].forEach(function (keyName) {
|
874
|
-
if (keyName
|
1013
|
+
if (keyName !== actualEventName) {
|
875
1014
|
SC.Event.remove(document, keyName, this, this[keyName]);
|
876
1015
|
this[keyName] = null;
|
877
1016
|
}
|
@@ -882,7 +1021,7 @@ SC.RootResponder = SC.Object.extend(
|
|
882
1021
|
variation2 = lowerDomPrefix + 'AnimationStart';
|
883
1022
|
variation3 = domPrefix + 'AnimationStart';
|
884
1023
|
['animationstart', variation1, variation2, variation3].forEach(function (keyName) {
|
885
|
-
if (keyName
|
1024
|
+
if (keyName !== actualEventName) {
|
886
1025
|
SC.Event.remove(document, keyName, this, this[keyName]);
|
887
1026
|
this[keyName] = null;
|
888
1027
|
}
|
@@ -892,12 +1031,6 @@ SC.RootResponder = SC.Object.extend(
|
|
892
1031
|
// ...........................................................................
|
893
1032
|
// TOUCH SUPPORT
|
894
1033
|
//
|
895
|
-
/*
|
896
|
-
There are three events: touchStart, touchEnd and touchesDragged.
|
897
|
-
|
898
|
-
The touchStart and touchEnd events are called individually for each touch.
|
899
|
-
The touchesDragged events are sent to whichever view owns the touch event.
|
900
|
-
*/
|
901
1034
|
|
902
1035
|
/**
|
903
1036
|
@private
|
@@ -920,8 +1053,10 @@ SC.RootResponder = SC.Object.extend(
|
|
920
1053
|
|
921
1054
|
When views receive a touch event, they have the option to subscribe to it.
|
922
1055
|
They are then mapped to touch events and vice-versa. This returns touches mapped to the view.
|
1056
|
+
|
1057
|
+
This method is also available on SC.Touch objects, and you will usually call it from there.
|
923
1058
|
*/
|
924
|
-
touchesForView: function
|
1059
|
+
touchesForView: function(view) {
|
925
1060
|
if (this._touchedViews[SC.guidFor(view)]) {
|
926
1061
|
return this._touchedViews[SC.guidFor(view)].touches;
|
927
1062
|
}
|
@@ -929,43 +1064,54 @@ SC.RootResponder = SC.Object.extend(
|
|
929
1064
|
|
930
1065
|
/**
|
931
1066
|
Computes a hash with x, y, and d (distance) properties, containing the average position
|
932
|
-
of all touches, and the average distance of all touches from that average.
|
1067
|
+
of all touches, and the average distance of all touches from that average. This is useful
|
1068
|
+
for implementing scaling.
|
933
1069
|
|
934
|
-
This is
|
1070
|
+
This method is also available on SC.Touch objects, and you will usually call it from there.
|
1071
|
+
|
1072
|
+
@param {SC.View} view The view whose touches should be averaged.
|
1073
|
+
@param {SC.Touch} additionalTouch This method uses touchesForView; if you call it from
|
1074
|
+
touchStart, that touch will not yet be included in touchesForView. To accommodate this,
|
1075
|
+
you should pass the view to this method (or pass YES to SC.Touch#averagedTouchesForView's
|
1076
|
+
`addSelf` argument).
|
935
1077
|
*/
|
936
|
-
averagedTouchesForView: function
|
937
|
-
var
|
938
|
-
|
1078
|
+
averagedTouchesForView: function(view, additionalTouch) {
|
1079
|
+
var t = this.touchesForView(view),
|
1080
|
+
len, averaged, additionalTouchIsDuplicate;
|
939
1081
|
|
940
|
-
//
|
1082
|
+
// Each view gets its own cached average touches object for performance.
|
941
1083
|
averaged = view._scrr_averagedTouches || (view._scrr_averagedTouches = {});
|
942
1084
|
|
943
|
-
|
1085
|
+
// FAST PATH: no touches to track.
|
1086
|
+
if ((!t || t.length === 0) && !additionalTouch) {
|
944
1087
|
averaged.x = 0;
|
945
1088
|
averaged.y = 0;
|
946
1089
|
averaged.d = 0;
|
1090
|
+
averaged.velocityX = 0;
|
1091
|
+
averaged.velocityY = 0;
|
947
1092
|
averaged.touchCount = 0;
|
948
|
-
|
949
|
-
|
950
|
-
|
1093
|
+
}
|
1094
|
+
// Otherwise, average the touches.
|
1095
|
+
else {
|
1096
|
+
// Cache the array object used by this method. (Cleared at the end to prevent memory leaks.)
|
951
1097
|
var touches = this._averagedTouches_touches || (this._averagedTouches_touches = []);
|
952
|
-
touches.length = 0;
|
953
1098
|
|
954
1099
|
// copy touches into array
|
955
1100
|
if (t) {
|
956
1101
|
var i;
|
957
1102
|
len = t.length;
|
958
|
-
for
|
1103
|
+
for(i = 0; i < len; i++) {
|
959
1104
|
touches.push(t[i]);
|
1105
|
+
if (additionalTouch && t[i] === additionalTouch) additionalTouchIsDuplicate = YES;
|
960
1106
|
}
|
961
1107
|
}
|
962
1108
|
|
963
|
-
//
|
964
|
-
if (
|
1109
|
+
// Add additionalTouch if present and not duplicated.
|
1110
|
+
if (additionalTouch && !additionalTouchIsDuplicate) touches.push(additionalTouch);
|
965
1111
|
|
966
1112
|
// prepare variables for looping
|
967
1113
|
var idx, touch,
|
968
|
-
ax = 0, ay = 0, dx, dy, ad = 0;
|
1114
|
+
ax = 0, ay = 0, dx, dy, ad = 0, avx = 0, avy = 0;
|
969
1115
|
len = touches.length;
|
970
1116
|
|
971
1117
|
// first, add
|
@@ -973,11 +1119,15 @@ SC.RootResponder = SC.Object.extend(
|
|
973
1119
|
touch = touches[idx];
|
974
1120
|
ax += touch.pageX;
|
975
1121
|
ay += touch.pageY;
|
1122
|
+
avx += touch.velocityX;
|
1123
|
+
avy += touch.velocityY;
|
976
1124
|
}
|
977
1125
|
|
978
1126
|
// now, average
|
979
1127
|
ax /= len;
|
980
1128
|
ay /= len;
|
1129
|
+
avx /= len;
|
1130
|
+
avy /= len;
|
981
1131
|
|
982
1132
|
// distance
|
983
1133
|
for (idx = 0; idx < len; idx++) {
|
@@ -996,19 +1146,26 @@ SC.RootResponder = SC.Object.extend(
|
|
996
1146
|
|
997
1147
|
averaged.x = ax;
|
998
1148
|
averaged.y = ay;
|
1149
|
+
averaged.velocityX = avx;
|
1150
|
+
averaged.velocityY = avy;
|
999
1151
|
averaged.d = ad;
|
1000
1152
|
averaged.touchCount = len;
|
1153
|
+
|
1154
|
+
// Clear the touches array to prevent touch object leaks.
|
1155
|
+
touches.length = 0;
|
1001
1156
|
}
|
1002
1157
|
|
1003
1158
|
return averaged;
|
1004
1159
|
},
|
1005
1160
|
|
1006
|
-
assignTouch: function
|
1161
|
+
assignTouch: function(touch, view) {
|
1007
1162
|
// sanity-check
|
1008
1163
|
if (touch.hasEnded) throw new Error("Attempt to assign a touch that is already finished.");
|
1009
1164
|
|
1010
|
-
//
|
1165
|
+
// Fast path, the touch is already assigned to the view.
|
1011
1166
|
if (touch.view === view) return;
|
1167
|
+
|
1168
|
+
// unassign from old view if necessary
|
1012
1169
|
if (touch.view) {
|
1013
1170
|
this.unassignTouch(touch);
|
1014
1171
|
}
|
@@ -1029,12 +1186,14 @@ SC.RootResponder = SC.Object.extend(
|
|
1029
1186
|
this._touchedViews[SC.guidFor(view)].touchCount++;
|
1030
1187
|
},
|
1031
1188
|
|
1032
|
-
unassignTouch: function
|
1189
|
+
unassignTouch: function(touch) {
|
1033
1190
|
// find view entry
|
1034
1191
|
var view, viewEntry;
|
1035
1192
|
|
1036
|
-
//
|
1193
|
+
// Fast path, the touch is not assigned to a view.
|
1037
1194
|
if (!touch.view) return; // touch.view should===touch.touchResponder eventually :)
|
1195
|
+
|
1196
|
+
// get view
|
1038
1197
|
view = touch.view;
|
1039
1198
|
|
1040
1199
|
// get view entry
|
@@ -1053,7 +1212,7 @@ SC.RootResponder = SC.Object.extend(
|
|
1053
1212
|
touch.view = undefined;
|
1054
1213
|
},
|
1055
1214
|
|
1056
|
-
_flushQueuedTouchResponder: function
|
1215
|
+
_flushQueuedTouchResponder: function(){
|
1057
1216
|
if (this._queuedTouchResponder) {
|
1058
1217
|
var queued = this._queuedTouchResponder;
|
1059
1218
|
this._queuedTouchResponder = null;
|
@@ -1062,60 +1221,42 @@ SC.RootResponder = SC.Object.extend(
|
|
1062
1221
|
},
|
1063
1222
|
|
1064
1223
|
/**
|
1065
|
-
|
1066
|
-
for that touch.
|
1067
|
-
|
1068
|
-
|
1069
|
-
|
1070
|
-
|
1071
|
-
|
1072
|
-
|
1073
|
-
|
1074
|
-
|
1075
|
-
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1082
|
-
|
1083
|
-
|
1084
|
-
|
1085
|
-
to
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
1089
|
-
|
1090
|
-
|
1091
|
-
|
1092
|
-
This will give control back to the containing view. Maybe you only want to do it if it is a ScrollView?
|
1093
|
-
|
1094
|
-
if (
|
1095
|
-
Math.abs(touch.pageX - touch.startX) > 4 &&
|
1096
|
-
touch.nextTouchResponder &&
|
1097
|
-
touch.nextTouchResponder.isScrollable
|
1098
|
-
)
|
1099
|
-
touch.makeTouchResponder(touch.nextTouchResponder);
|
1100
|
-
|
1101
|
-
Possible gotcha: while you can do touch.nextTouchResponder, the responders are not chained in a linked list like
|
1102
|
-
normal responders, because each touch has its own responder stack. To navigate through the stack (or, though
|
1103
|
-
it is not recommended, change it), use touch.touchResponders (the raw stack array).
|
1104
|
-
|
1105
|
-
makeTouchResponder is called with an event object. However, it usually triggers custom touchStart/touchCancelled
|
1106
|
-
events on the views. The event object is passed so that functions such as stopPropagation may be called.
|
1224
|
+
This method attempts to change the responder for a particular touch. The touch's responder is the
|
1225
|
+
view which will receive touch events for that touch.
|
1226
|
+
|
1227
|
+
You will usually not call this method directly, instead calling one of the convenience methods on
|
1228
|
+
the touch itself. See documentation for SC.Touch for more.
|
1229
|
+
|
1230
|
+
Possible gotchas:
|
1231
|
+
|
1232
|
+
- Because this method must search for a view which implements touchStart (without returning NO),
|
1233
|
+
touchStart is called on the new responder before touchCancelled is called on the old one.
|
1234
|
+
- While a touch exposes its current responder at `touchResponder` and any previous stacked one at
|
1235
|
+
`nextTouchResponder`, their relationship is ad hoc and arbitrary, and so are not chained by
|
1236
|
+
`nextResponder` like in a standard responder chain. To query the touch's current responder stack
|
1237
|
+
(or, though it's not recommended, change it), check touch.touchResponders.
|
1238
|
+
|
1239
|
+
@param {SC.Touch} touch
|
1240
|
+
@param {SC.Responder} responder The view to assign to the touch. (It, or if bubbling then an ancestor,
|
1241
|
+
must implement touchStart.)
|
1242
|
+
@param {Boolean} shouldStack Whether the new responder should replace the old one, or stack with it.
|
1243
|
+
Stacked responders are easy to revert via `SC.Touch#restoreLastTouchResponder`.
|
1244
|
+
@param {Boolean|SC.Responder} bubblesTo If YES, will attempt to find a `touchStart` responder up the
|
1245
|
+
responder chain. If NO or undefined, will only check the passed responder. If you pass a responder
|
1246
|
+
for this argument, the attempt will bubble until it reaches the passed responder, allowing you to
|
1247
|
+
restrict the bubbling to a portion of the responder chain. ((Note that this responder will not be
|
1248
|
+
given an opportunity to respond to the event.)
|
1249
|
+
@returns {Boolean} Whether a valid touch responder was found and assigned.
|
1107
1250
|
*/
|
1108
|
-
makeTouchResponder: function
|
1109
|
-
|
1251
|
+
makeTouchResponder: function(touch, responder, shouldStack, bubblesTo) {
|
1110
1252
|
// In certain cases (SC.Gesture being one), we have to call makeTouchResponder
|
1111
1253
|
// from inside makeTouchResponder so we queue it up here.
|
1112
1254
|
if (this._isMakingTouchResponder) {
|
1113
|
-
this._queuedTouchResponder = [touch, responder, shouldStack,
|
1114
|
-
return;
|
1255
|
+
this._queuedTouchResponder = [touch, responder, shouldStack, bubblesTo];
|
1256
|
+
return YES; // um?
|
1115
1257
|
}
|
1116
1258
|
this._isMakingTouchResponder = YES;
|
1117
1259
|
|
1118
|
-
|
1119
1260
|
var stack = touch.touchResponders, touchesForView;
|
1120
1261
|
|
1121
1262
|
// find the actual responder (if any, I suppose)
|
@@ -1125,33 +1266,38 @@ SC.RootResponder = SC.Object.extend(
|
|
1125
1266
|
if (touch.touchResponder === responder) {
|
1126
1267
|
this._isMakingTouchResponder = NO;
|
1127
1268
|
this._flushQueuedTouchResponder();
|
1128
|
-
return;
|
1269
|
+
return YES; // more um
|
1129
1270
|
}
|
1130
1271
|
|
1131
1272
|
// send touchStart
|
1132
1273
|
// get the target pane
|
1133
1274
|
var pane;
|
1134
|
-
if (responder) pane = responder.get('pane');
|
1135
|
-
else pane = this.get('keyPane') || this.get('mainPane');
|
1275
|
+
if (responder) pane = responder.get('pane') ;
|
1276
|
+
else pane = this.get('keyPane') || this.get('mainPane') ;
|
1136
1277
|
|
1137
1278
|
// if the responder is not already in the stack...
|
1138
|
-
|
1139
1279
|
if (stack.indexOf(responder) < 0) {
|
1140
|
-
|
1141
|
-
if
|
1280
|
+
|
1281
|
+
// if we need to go up the view chain, do so via SC.Pane#sendEvent.
|
1282
|
+
if (bubblesTo) {
|
1142
1283
|
// if we found a valid pane, send the event to it
|
1143
1284
|
try {
|
1144
|
-
responder =
|
1285
|
+
responder = pane ? pane.sendEvent("touchStart", touch, responder, bubblesTo) : null ;
|
1145
1286
|
} catch (e) {
|
1146
1287
|
SC.Logger.error("Error in touchStart: " + e);
|
1147
1288
|
responder = null;
|
1148
1289
|
}
|
1149
1290
|
} else {
|
1150
|
-
|
1291
|
+
// If the responder doesn't currently have a touch, or it does but it accepts multitouch, test it. Otherwise it's cool.
|
1151
1292
|
if (responder && ((responder.get ? responder.get("acceptsMultitouch") : responder.acceptsMultitouch) || !responder.hasTouch)) {
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1293
|
+
// If it doesn't respond to touchStart, it's no good.
|
1294
|
+
if (!responder.respondsTo("touchStart")) {
|
1295
|
+
responder = null;
|
1296
|
+
}
|
1297
|
+
// If it returns NO from touchStart, it's no good. Otherwise it's cool.
|
1298
|
+
else if (responder.touchStart(touch) === NO) {
|
1299
|
+
responder = null;
|
1300
|
+
}
|
1155
1301
|
}
|
1156
1302
|
}
|
1157
1303
|
}
|
@@ -1204,26 +1350,38 @@ SC.RootResponder = SC.Object.extend(
|
|
1204
1350
|
}
|
1205
1351
|
}
|
1206
1352
|
|
1207
|
-
|
1353
|
+
// Unflag that this method is running, and flush the queue if any.
|
1208
1354
|
this._isMakingTouchResponder = NO;
|
1209
|
-
this._flushQueuedTouchResponder();
|
1355
|
+
this._flushQueuedTouchResponder(); // this may need to be &&'ed with the responder to give the correct return value...
|
1210
1356
|
|
1357
|
+
return !!responder;
|
1211
1358
|
},
|
1212
1359
|
|
1213
1360
|
/**
|
1214
|
-
|
1215
|
-
|
1216
|
-
|
1361
|
+
Before the touchStart event is sent up the usual responder chain, the views along that same responder chain
|
1362
|
+
are given the opportunity to capture the touch event, preventing child views (including the target) from
|
1363
|
+
hearing about it. This of course proceeds in the opposite direction from a usual event bubbling, starting at
|
1364
|
+
the target's first ancestor and proceeding towards the target. This method implements the capture phase.
|
1365
|
+
|
1366
|
+
If no view captures the touch, this method will return NO, and makeTouchResponder is then called for the
|
1367
|
+
target, proceeding with standard target-to-pane event bubbling for `touchStart`.
|
1217
1368
|
|
1218
|
-
|
1219
|
-
|
1369
|
+
For an example of captureTouch in action, see SC.ScrollView's touch handling, which by default captures the
|
1370
|
+
touch and holds it for 150ms to allow it to determine whether the user is tapping or scrolling.
|
1220
1371
|
|
1221
|
-
You usually
|
1222
|
-
touch.
|
1372
|
+
You will usually not call this method yourself, and if you do, you should call the corresponding convenience
|
1373
|
+
method on the touch itself.
|
1223
1374
|
|
1224
|
-
|
1375
|
+
@param {SC.Touch} touch The touch to offer up for capture.
|
1376
|
+
@param {?SC.Responder} startingPoint The view whose children should be given an opportunity to capture
|
1377
|
+
the event. (The starting point itself is not asked.)
|
1378
|
+
@param {Boolean} shouldStack Whether any capturing responder should stack with existing responders.
|
1379
|
+
Stacked responders are easy to revert via `SC.Touch#restoreLastTouchResponder`.
|
1380
|
+
|
1381
|
+
@returns {Boolean} Whether or not the touch was captured. If it was not, you should pass it to
|
1382
|
+
`makeTouchResponder` for standard event bubbling.
|
1225
1383
|
*/
|
1226
|
-
captureTouch: function
|
1384
|
+
captureTouch: function(touch, startingPoint, shouldStack) {
|
1227
1385
|
if (!startingPoint) startingPoint = this;
|
1228
1386
|
|
1229
1387
|
var target = touch.targetView, view = target,
|
@@ -1234,7 +1392,8 @@ SC.RootResponder = SC.Object.extend(
|
|
1234
1392
|
SC.Logger.info(' -- Received one touch on %@'.fmt(target.toString()));
|
1235
1393
|
}
|
1236
1394
|
//@endif
|
1237
|
-
//
|
1395
|
+
// Generate the captureTouch responder chain by working backwards from the target
|
1396
|
+
// to the starting point. (Don't include the starting point.)
|
1238
1397
|
while (view && (view !== startingPoint)) {
|
1239
1398
|
chain.unshift(view);
|
1240
1399
|
view = view.get('nextResponder');
|
@@ -1254,26 +1413,24 @@ SC.RootResponder = SC.Object.extend(
|
|
1254
1413
|
//@endif
|
1255
1414
|
|
1256
1415
|
// if so, make it the touch's responder
|
1257
|
-
this.makeTouchResponder(touch, view, shouldStack,
|
1258
|
-
return; // and that's all we need
|
1416
|
+
this.makeTouchResponder(touch, view, shouldStack, startingPoint); // (touch, target, should stack, bubbles back to startingPoint, or all the way up.)
|
1417
|
+
return YES; // and that's all we need
|
1259
1418
|
}
|
1260
1419
|
}
|
1261
1420
|
|
1262
1421
|
//@if (debug)
|
1263
|
-
if (SC.LOG_TOUCH_EVENTS) SC.Logger.info(" -- Didn't find a view that returned YES to captureTouch
|
1422
|
+
if (SC.LOG_TOUCH_EVENTS) SC.Logger.info(" -- Didn't find a view that returned YES to captureTouch.");
|
1264
1423
|
//@endif
|
1265
1424
|
|
1266
|
-
|
1267
|
-
// we need to figure out what view _will_
|
1268
|
-
// Thankfully, makeTouchResponder does exactly that: starts at the view it is supplied and keeps calling startTouch
|
1269
|
-
this.makeTouchResponder(touch, target, shouldStack, YES);
|
1425
|
+
return NO;
|
1270
1426
|
},
|
1271
1427
|
|
1428
|
+
//@if(debug)
|
1272
1429
|
/** @private
|
1273
1430
|
Artificially calls endTouch for any touch which is no longer present. This is necessary because
|
1274
1431
|
_sometimes_, WebKit ends up not sending endtouch.
|
1275
1432
|
*/
|
1276
|
-
endMissingTouches: function
|
1433
|
+
endMissingTouches: function(presentTouches) {
|
1277
1434
|
var idx, len = presentTouches.length, map = {}, end = [];
|
1278
1435
|
|
1279
1436
|
// make a map of what touches _are_ present
|
@@ -1288,19 +1445,24 @@ SC.RootResponder = SC.Object.extend(
|
|
1288
1445
|
}
|
1289
1446
|
|
1290
1447
|
// end said touches
|
1448
|
+
if (end.length) {
|
1449
|
+
console.warn('Ending missing touches: ' + end.toString());
|
1450
|
+
}
|
1291
1451
|
for (idx = 0, len = end.length; idx < len; idx++) {
|
1292
1452
|
this.endTouch(end[idx]);
|
1293
1453
|
this.finishTouch(end[idx]);
|
1294
1454
|
}
|
1295
1455
|
},
|
1456
|
+
//@endif
|
1296
1457
|
|
1297
1458
|
_touchCount: 0,
|
1459
|
+
|
1298
1460
|
/** @private
|
1299
1461
|
Ends a specific touch (for a bit, at least). This does not "finish" a touch; it merely calls
|
1300
1462
|
touchEnd, touchCancelled, etc. A re-dispatch (through recapture or makeTouchResponder) will terminate
|
1301
1463
|
the process; it would have to be restarted separately, through touch.end().
|
1302
1464
|
*/
|
1303
|
-
endTouch: function
|
1465
|
+
endTouch: function(touchEntry, action, evt) {
|
1304
1466
|
if (!action) { action = "touchEnd"; }
|
1305
1467
|
|
1306
1468
|
var responderIdx, responders, responder, originalResponder;
|
@@ -1333,16 +1495,15 @@ SC.RootResponder = SC.Object.extend(
|
|
1333
1495
|
@private
|
1334
1496
|
"Finishes" a touch. That is, it eradicates it from our touch entries and removes all responder, etc. properties.
|
1335
1497
|
*/
|
1336
|
-
finishTouch: function
|
1337
|
-
var elem;
|
1338
|
-
|
1498
|
+
finishTouch: function(touch) {
|
1339
1499
|
// ensure the touch is indeed unassigned.
|
1340
1500
|
this.unassignTouch(touch);
|
1341
1501
|
|
1342
1502
|
// If we rescued this touch's initial element, we should remove it
|
1343
1503
|
// from the DOM and garbage collect now. See setup() for an
|
1344
1504
|
// explanation of this bug/workaround.
|
1345
|
-
|
1505
|
+
var elem = touch._rescuedElement;
|
1506
|
+
if (elem) {
|
1346
1507
|
if (elem.swapNode && elem.swapNode.parentNode) {
|
1347
1508
|
elem.swapNode.parentNode.replaceChild(elem, elem.swapNode);
|
1348
1509
|
} else if (elem.parentNode === SC.touchHoldingPen) {
|
@@ -1353,7 +1514,6 @@ SC.RootResponder = SC.Object.extend(
|
|
1353
1514
|
elem = null;
|
1354
1515
|
}
|
1355
1516
|
|
1356
|
-
|
1357
1517
|
// clear responders (just to be thorough)
|
1358
1518
|
touch.touchResponders = null;
|
1359
1519
|
touch.touchResponder = null;
|
@@ -1375,18 +1535,19 @@ SC.RootResponder = SC.Object.extend(
|
|
1375
1535
|
@param {Event} evt the event
|
1376
1536
|
@returns {Boolean}
|
1377
1537
|
*/
|
1378
|
-
touchstart: function
|
1538
|
+
touchstart: function(evt) {
|
1379
1539
|
// Starting iOS5 touch events are handled by textfields.
|
1380
1540
|
// As a workaround just let the browser to use the default behavior.
|
1381
|
-
if
|
1541
|
+
if(this.ignoreTouchHandle(evt)) return YES;
|
1382
1542
|
|
1383
1543
|
var hidingTouchIntercept = NO;
|
1384
1544
|
|
1385
|
-
SC.run(function
|
1386
|
-
|
1545
|
+
SC.run(function() {
|
1546
|
+
//@if(debug)
|
1547
|
+
// When using breakpoints on touch start, we will lose the end touch event.
|
1387
1548
|
this.endMissingTouches(evt.touches);
|
1549
|
+
//@endif
|
1388
1550
|
|
1389
|
-
// as you were...
|
1390
1551
|
// loop through changed touches, calling touchStart, etc.
|
1391
1552
|
var idx, touches = evt.changedTouches, len = touches.length,
|
1392
1553
|
touch, touchEntry;
|
@@ -1418,18 +1579,16 @@ SC.RootResponder = SC.Object.extend(
|
|
1418
1579
|
// set the event (so default action, etc. can be stopped)
|
1419
1580
|
touchEntry.event = evt; // will be unset momentarily
|
1420
1581
|
|
1421
|
-
//
|
1422
|
-
//
|
1423
|
-
|
1424
|
-
|
1425
|
-
this.captureTouch(touchEntry, this);
|
1582
|
+
// First we allow any view in the responder chain to capture the touch, before triggering the standard touchStart
|
1583
|
+
// handler chain.
|
1584
|
+
var captured = this.captureTouch(touchEntry, this);
|
1585
|
+
if (!captured) this.makeTouchResponder(touchEntry, touchEntry.targetView, NO, YES); // (touch, target, shouldn't stack, bubbles all the way)
|
1426
1586
|
|
1427
1587
|
// Unset the reference to the original event so we can garbage collect.
|
1428
1588
|
touchEntry.event = null;
|
1429
1589
|
}
|
1430
1590
|
}, this);
|
1431
1591
|
|
1432
|
-
|
1433
1592
|
// hack for text fields
|
1434
1593
|
if (hidingTouchIntercept) {
|
1435
1594
|
return YES;
|
@@ -1442,12 +1601,12 @@ SC.RootResponder = SC.Object.extend(
|
|
1442
1601
|
@private
|
1443
1602
|
used to keep track of when a specific type of touch event was last handled, to see if it needs to be re-handled
|
1444
1603
|
*/
|
1445
|
-
touchmove: function
|
1604
|
+
touchmove: function(evt) {
|
1446
1605
|
// Starting iOS5 touch events are handled by textfields.
|
1447
1606
|
// As a workaround just let the browser to use the default behavior.
|
1448
|
-
if
|
1607
|
+
if(this.ignoreTouchHandle(evt)) return YES;
|
1449
1608
|
|
1450
|
-
SC.run(function
|
1609
|
+
SC.run(function() {
|
1451
1610
|
// pretty much all we gotta do is update touches, and figure out which views need updating.
|
1452
1611
|
var touches = evt.changedTouches, touch, touchEntry,
|
1453
1612
|
idx, len = touches.length, view, changedTouches, viewTouches, firstTouch,
|
@@ -1472,7 +1631,23 @@ SC.RootResponder = SC.Object.extend(
|
|
1472
1631
|
|
1473
1632
|
if (touchEntry.hidesTouchIntercept) hidingTouchIntercept = YES;
|
1474
1633
|
|
1475
|
-
// update touch
|
1634
|
+
// update touch velocity (moving average)
|
1635
|
+
var duration = evt.timeStamp - touchEntry.timeStamp,
|
1636
|
+
velocityLambda, latestXVelocity, latestYVelocity;
|
1637
|
+
// Given uneven timing between events, we should give less weight to shorter (less accurate)
|
1638
|
+
// events, with no consideration at all given zero-time events.
|
1639
|
+
if (duration !== 0) {
|
1640
|
+
// Lambda (how heavily we're weighting the latest number)
|
1641
|
+
velocityLambda = Math.min(1, duration / 80);
|
1642
|
+
// X
|
1643
|
+
latestXVelocity = (touch.pageX - touchEntry.pageX) / duration;
|
1644
|
+
touchEntry.velocityX = (1.0 - velocityLambda) * touchEntry.velocityX + velocityLambda * (latestXVelocity);
|
1645
|
+
// Y
|
1646
|
+
latestYVelocity = (touch.pageY - touchEntry.pageY) / duration;
|
1647
|
+
touchEntry.velocityY = (1.0 - velocityLambda) * touchEntry.velocityY + velocityLambda * (latestYVelocity);
|
1648
|
+
}
|
1649
|
+
|
1650
|
+
// update touch position et al.
|
1476
1651
|
touchEntry.pageX = touch.pageX;
|
1477
1652
|
touchEntry.pageY = touch.pageY;
|
1478
1653
|
touchEntry.clientX = touch.clientX;
|
@@ -1480,6 +1655,7 @@ SC.RootResponder = SC.Object.extend(
|
|
1480
1655
|
touchEntry.screenX = touch.screenX;
|
1481
1656
|
touchEntry.screenY = touch.screenY;
|
1482
1657
|
touchEntry.timeStamp = evt.timeStamp;
|
1658
|
+
touchEntry.type = evt.type;
|
1483
1659
|
touchEntry.event = evt;
|
1484
1660
|
|
1485
1661
|
// if the touch entry has a view
|
@@ -1513,15 +1689,22 @@ SC.RootResponder = SC.Object.extend(
|
|
1513
1689
|
// the first VIEW touch should be the touch info sent
|
1514
1690
|
viewTouches = this.touchesForView(view);
|
1515
1691
|
firstTouch = viewTouches.firstObject();
|
1692
|
+
|
1693
|
+
// Load the event up with data from the first touch. THIS IS FOR CONVENIENCE ONLY in cases where the developer
|
1694
|
+
// only cares about one touch.
|
1516
1695
|
evt.pageX = firstTouch.pageX;
|
1517
1696
|
evt.pageY = firstTouch.pageY;
|
1518
1697
|
evt.clientX = firstTouch.clientX;
|
1519
1698
|
evt.clientY = firstTouch.clientY;
|
1520
1699
|
evt.screenX = firstTouch.screenX;
|
1521
1700
|
evt.screenY = firstTouch.screenY;
|
1522
|
-
evt.
|
1701
|
+
evt.startX = firstTouch.startX;
|
1702
|
+
evt.startY = firstTouch.startY;
|
1703
|
+
evt.velocityX = firstTouch.velocityX;
|
1704
|
+
evt.velocityY = firstTouch.velocityY;
|
1705
|
+
evt.touchContext = this; // Injects the root responder so it can call e.g. `touchesForView`.
|
1523
1706
|
|
1524
|
-
//
|
1707
|
+
// Give the view a chance to handle touchesDragged. (Don't bubble; viewTouches is view-specific.)
|
1525
1708
|
view.tryToPerform("touchesDragged", evt, viewTouches);
|
1526
1709
|
}
|
1527
1710
|
|
@@ -1538,14 +1721,14 @@ SC.RootResponder = SC.Object.extend(
|
|
1538
1721
|
return evt.hasCustomEventHandling;
|
1539
1722
|
},
|
1540
1723
|
|
1541
|
-
touchend: function
|
1724
|
+
touchend: function(evt) {
|
1542
1725
|
var hidesTouchIntercept = NO;
|
1543
1726
|
|
1544
1727
|
// Starting iOS5 touch events are handled by textfields.
|
1545
1728
|
// As a workaround just let the browser to use the default behavior.
|
1546
|
-
if
|
1729
|
+
if(this.ignoreTouchHandle(evt)) return YES;
|
1547
1730
|
|
1548
|
-
SC.run(function
|
1731
|
+
SC.run(function() {
|
1549
1732
|
var touches = evt.changedTouches, touch, touchEntry,
|
1550
1733
|
idx, len = touches.length,
|
1551
1734
|
action = evt.isCancel ? "touchCancelled" : "touchEnd";
|
@@ -1559,7 +1742,23 @@ SC.RootResponder = SC.Object.extend(
|
|
1559
1742
|
// check if there is an entry
|
1560
1743
|
if (!touchEntry) continue;
|
1561
1744
|
|
1562
|
-
//
|
1745
|
+
// update touch velocity (moving average)
|
1746
|
+
var duration = evt.timeStamp - touchEntry.timeStamp,
|
1747
|
+
velocityLambda, latestXVelocity, latestYVelocity;
|
1748
|
+
// Given uneven timing between events, we should give less weight to shorter (less accurate)
|
1749
|
+
// events, with no consideration at all given zero-time events.
|
1750
|
+
if (duration !== 0) {
|
1751
|
+
// Lambda (how heavily we're weighting the latest number)
|
1752
|
+
velocityLambda = Math.min(1, duration / 80);
|
1753
|
+
// X
|
1754
|
+
latestXVelocity = (touch.pageX - touchEntry.pageX) / duration;
|
1755
|
+
touchEntry.velocityX = (1.0 - velocityLambda) * touchEntry.velocityX + velocityLambda * (latestXVelocity);
|
1756
|
+
// Y
|
1757
|
+
latestYVelocity = (touch.pageY - touchEntry.pageY) / duration;
|
1758
|
+
touchEntry.velocityY = (1.0 - velocityLambda) * touchEntry.velocityY + velocityLambda * (latestYVelocity);
|
1759
|
+
}
|
1760
|
+
|
1761
|
+
// update touch position et al.
|
1563
1762
|
touchEntry.timeStamp = evt.timeStamp;
|
1564
1763
|
touchEntry.pageX = touch.pageX;
|
1565
1764
|
touchEntry.pageY = touch.pageY;
|
@@ -1579,8 +1778,8 @@ SC.RootResponder = SC.Object.extend(
|
|
1579
1778
|
}
|
1580
1779
|
|
1581
1780
|
if (this._drag) {
|
1582
|
-
this._drag.tryToPerform('mouseUp', touch);
|
1583
|
-
this._drag = null;
|
1781
|
+
this._drag.tryToPerform('mouseUp', touch) ;
|
1782
|
+
this._drag = null ;
|
1584
1783
|
}
|
1585
1784
|
|
1586
1785
|
// unassign
|
@@ -1602,7 +1801,7 @@ SC.RootResponder = SC.Object.extend(
|
|
1602
1801
|
Handle touch cancel event. Works just like cancelling a touch for any other reason.
|
1603
1802
|
touchend handles it as a special case (sending cancel instead of end if needed).
|
1604
1803
|
*/
|
1605
|
-
touchcancel: function
|
1804
|
+
touchcancel: function(evt) {
|
1606
1805
|
evt.isCancel = YES;
|
1607
1806
|
this.touchend(evt);
|
1608
1807
|
},
|
@@ -1611,10 +1810,10 @@ SC.RootResponder = SC.Object.extend(
|
|
1611
1810
|
Ignore Touch events on textfields and links. starting iOS 5 textfields
|
1612
1811
|
get touch events. Textfields just need to get the default focus action.
|
1613
1812
|
*/
|
1614
|
-
ignoreTouchHandle: function
|
1615
|
-
if
|
1813
|
+
ignoreTouchHandle: function(evt) {
|
1814
|
+
if(SC.browser.isMobileSafari){
|
1616
1815
|
var tag = evt.target.tagName;
|
1617
|
-
if
|
1816
|
+
if(tag==="INPUT" || tag==="TEXTAREA" || tag==="A" || tag==="SELECT"){
|
1618
1817
|
evt.allowDefault();
|
1619
1818
|
return YES;
|
1620
1819
|
}
|
@@ -1635,8 +1834,8 @@ SC.RootResponder = SC.Object.extend(
|
|
1635
1834
|
|
1636
1835
|
@returns {Object} Object that handled evet or null
|
1637
1836
|
*/
|
1638
|
-
attemptKeyEquivalent: function
|
1639
|
-
var ret = null;
|
1837
|
+
attemptKeyEquivalent: function(evt) {
|
1838
|
+
var ret = null ;
|
1640
1839
|
|
1641
1840
|
// keystring is a method name representing the keys pressed (i.e
|
1642
1841
|
// 'alt_shift_escape')
|
@@ -1650,24 +1849,24 @@ SC.RootResponder = SC.Object.extend(
|
|
1650
1849
|
mainPane = this.get('mainPane');
|
1651
1850
|
|
1652
1851
|
if (menuPane) {
|
1653
|
-
ret = menuPane.performKeyEquivalent(keystring, evt);
|
1852
|
+
ret = menuPane.performKeyEquivalent(keystring, evt) ;
|
1654
1853
|
if (ret) return ret;
|
1655
1854
|
}
|
1656
1855
|
|
1657
1856
|
// Try the keyPane. If it's modal, then try the equivalent there but on
|
1658
1857
|
// nobody else.
|
1659
1858
|
if (keyPane) {
|
1660
|
-
ret = keyPane.performKeyEquivalent(keystring, evt);
|
1661
|
-
if (ret || keyPane.get('isModal')) return ret;
|
1859
|
+
ret = keyPane.performKeyEquivalent(keystring, evt) ;
|
1860
|
+
if (ret || keyPane.get('isModal')) return ret ;
|
1662
1861
|
}
|
1663
1862
|
|
1664
1863
|
// if not, then try the main pane
|
1665
|
-
if (!ret && mainPane && (mainPane
|
1864
|
+
if (!ret && mainPane && (mainPane!==keyPane)) {
|
1666
1865
|
ret = mainPane.performKeyEquivalent(keystring, evt);
|
1667
|
-
if (ret || mainPane.get('isModal')) return ret;
|
1866
|
+
if (ret || mainPane.get('isModal')) return ret ;
|
1668
1867
|
}
|
1669
1868
|
|
1670
|
-
return ret;
|
1869
|
+
return ret ;
|
1671
1870
|
},
|
1672
1871
|
|
1673
1872
|
_lastModifiers: null,
|
@@ -1677,7 +1876,7 @@ SC.RootResponder = SC.Object.extend(
|
|
1677
1876
|
We turn this into a flagsChanged keyboard event. Normally this does not
|
1678
1877
|
stop the normal browser behavior.
|
1679
1878
|
*/
|
1680
|
-
_handleModifierChanges: function
|
1879
|
+
_handleModifierChanges: function(evt) {
|
1681
1880
|
// if the modifier keys have changed, then notify the first responder.
|
1682
1881
|
var m;
|
1683
1882
|
m = this._lastModifiers = (this._lastModifiers || { alt: false, ctrl: false, shift: false });
|
@@ -1699,7 +1898,7 @@ SC.RootResponder = SC.Object.extend(
|
|
1699
1898
|
}
|
1700
1899
|
evt.modifiers = m; // save on event
|
1701
1900
|
|
1702
|
-
return (changed) ? (this.sendEvent('flagsChanged', evt) ? evt.hasCustomEventHandling : YES) : YES;
|
1901
|
+
return (changed) ? (this.sendEvent('flagsChanged', evt) ? evt.hasCustomEventHandling : YES) : YES ;
|
1703
1902
|
},
|
1704
1903
|
|
1705
1904
|
/** @private
|
@@ -1708,7 +1907,7 @@ SC.RootResponder = SC.Object.extend(
|
|
1708
1907
|
handles the event, then it will be sent as a regular keyDown event.
|
1709
1908
|
This function is only valid when called with a keydown event.
|
1710
1909
|
*/
|
1711
|
-
_isFunctionOrNonPrintableKey: function
|
1910
|
+
_isFunctionOrNonPrintableKey: function(evt) {
|
1712
1911
|
return !!(evt.altKey || evt.ctrlKey || evt.metaKey || SC.FUNCTION_KEYS[evt.which]);
|
1713
1912
|
},
|
1714
1913
|
|
@@ -1716,7 +1915,7 @@ SC.RootResponder = SC.Object.extend(
|
|
1716
1915
|
Determines if the event simply reflects a modifier key change. These
|
1717
1916
|
events may generate a flagsChanged event, but are otherwise ignored.
|
1718
1917
|
*/
|
1719
|
-
_isModifierKey: function
|
1918
|
+
_isModifierKey: function(evt) {
|
1720
1919
|
return !!SC.MODIFIER_KEYS[evt.charCode];
|
1721
1920
|
},
|
1722
1921
|
|
@@ -1747,16 +1946,16 @@ SC.RootResponder = SC.Object.extend(
|
|
1747
1946
|
https://developer.mozilla.org/en/DOM/KeyboardEvent
|
1748
1947
|
http://msdn.microsoft.com/library/ff974342.aspx
|
1749
1948
|
*/
|
1750
|
-
keydown: function
|
1949
|
+
keydown: function(evt) {
|
1751
1950
|
if (SC.none(evt)) return YES;
|
1752
1951
|
var keyCode = evt.keyCode;
|
1753
|
-
if (SC.browser.isMozilla && evt.keyCode
|
1952
|
+
if (SC.browser.isMozilla && evt.keyCode===9) {
|
1754
1953
|
this.keydownCounter = 1;
|
1755
1954
|
}
|
1756
1955
|
// Fix for IME input (japanese, mandarin).
|
1757
1956
|
// If the KeyCode is 229 wait for the keyup and
|
1758
1957
|
// trigger a keyDown if it is is enter onKeyup.
|
1759
|
-
if (keyCode
|
1958
|
+
if (keyCode===229){
|
1760
1959
|
this._IMEInputON = YES;
|
1761
1960
|
return this.sendEvent('keyDown', evt);
|
1762
1961
|
}
|
@@ -1771,7 +1970,7 @@ SC.RootResponder = SC.Object.extend(
|
|
1771
1970
|
}
|
1772
1971
|
|
1773
1972
|
// Firefox does NOT handle delete here...
|
1774
|
-
if (SC.browser.isMozilla && (evt.which === 8)) return true;
|
1973
|
+
if (SC.browser.isMozilla && (evt.which === 8)) return true ;
|
1775
1974
|
|
1776
1975
|
// modifier keys are handled separately by the 'flagsChanged' event
|
1777
1976
|
// send event for modifier key changes, but only stop processing if this
|
@@ -1785,29 +1984,29 @@ SC.RootResponder = SC.Object.extend(
|
|
1785
1984
|
// if this is a function or non-printable key, try to use this as a key
|
1786
1985
|
// equivalent. Otherwise, send as a keyDown event so that the focused
|
1787
1986
|
// responder can do something useful with the event.
|
1788
|
-
ret = YES;
|
1987
|
+
ret = YES ;
|
1789
1988
|
if (this._isFunctionOrNonPrintableKey(evt)) {
|
1790
1989
|
// otherwise, send as keyDown event. If no one was interested in this
|
1791
1990
|
// keyDown event (probably the case), just let the browser do its own
|
1792
1991
|
// processing.
|
1793
1992
|
|
1794
1993
|
// Arrow keys are handled in keypress for firefox
|
1795
|
-
if (keyCode
|
1994
|
+
if (keyCode>=37 && keyCode<=40 && SC.browser.isMozilla) return YES;
|
1796
1995
|
|
1797
|
-
ret = this.sendEvent('keyDown', evt);
|
1996
|
+
ret = this.sendEvent('keyDown', evt) ;
|
1798
1997
|
|
1799
1998
|
// attempt key equivalent if key not handled
|
1800
1999
|
if (!ret) {
|
1801
2000
|
SC.run(function () {
|
1802
|
-
|
2001
|
+
ret = !this.attemptKeyEquivalent(evt) ;
|
1803
2002
|
}, this);
|
1804
2003
|
} else {
|
1805
|
-
ret = evt.hasCustomEventHandling;
|
1806
|
-
if (ret) forceBlock = NO; // code asked explicitly to let delete go
|
2004
|
+
ret = evt.hasCustomEventHandling ;
|
2005
|
+
if (ret) forceBlock = NO ; // code asked explicitly to let delete go
|
1807
2006
|
}
|
1808
2007
|
}
|
1809
2008
|
|
1810
|
-
return forceBlock ? NO : ret;
|
2009
|
+
return forceBlock ? NO : ret ;
|
1811
2010
|
},
|
1812
2011
|
|
1813
2012
|
/** @private
|
@@ -1818,14 +2017,14 @@ SC.RootResponder = SC.Object.extend(
|
|
1818
2017
|
Normally ignore any function or non-printable key events. Otherwise, just
|
1819
2018
|
trigger a keyDown.
|
1820
2019
|
*/
|
1821
|
-
keypress: function
|
2020
|
+
keypress: function(evt) {
|
1822
2021
|
var ret,
|
1823
2022
|
keyCode = evt.keyCode,
|
1824
2023
|
isFirefox = SC.browser.isMozilla;
|
1825
2024
|
|
1826
|
-
if (isFirefox && evt.keyCode
|
2025
|
+
if (isFirefox && evt.keyCode===9) {
|
1827
2026
|
this.keydownCounter++;
|
1828
|
-
if (this.keydownCounter
|
2027
|
+
if (this.keydownCounter === 2) return YES;
|
1829
2028
|
}
|
1830
2029
|
|
1831
2030
|
// delete is handled in keydown() for most browsers
|
@@ -1833,27 +2032,27 @@ SC.RootResponder = SC.Object.extend(
|
|
1833
2032
|
//get the keycode and set it for which.
|
1834
2033
|
evt.which = keyCode;
|
1835
2034
|
ret = this.sendEvent('keyDown', evt);
|
1836
|
-
return ret ? (SC.allowsBackspaceToPreviousPage || evt.hasCustomEventHandling) : YES;
|
2035
|
+
return ret ? (SC.allowsBackspaceToPreviousPage || evt.hasCustomEventHandling) : YES ;
|
1837
2036
|
|
1838
2037
|
// normal processing. send keyDown for printable keys...
|
1839
2038
|
//there is a special case for arrow key repeating of events in FF.
|
1840
2039
|
} else {
|
1841
2040
|
var isFirefoxArrowKeys = (keyCode >= 37 && keyCode <= 40 && isFirefox),
|
1842
|
-
charCode
|
2041
|
+
charCode = evt.charCode;
|
1843
2042
|
|
1844
|
-
if ((charCode !== undefined && charCode === 0 && evt.keyCode
|
2043
|
+
if ((charCode !== undefined && charCode === 0 && evt.keyCode!==9) && !isFirefoxArrowKeys) return YES;
|
1845
2044
|
if (isFirefoxArrowKeys) evt.which = keyCode;
|
1846
2045
|
// we only want to rethrow if this is a printable key so that we don't
|
1847
2046
|
// duplicate the event sent in keydown when a modifier key is pressed.
|
1848
2047
|
if (isFirefoxArrowKeys || this._isPrintableKey(evt)) {
|
1849
2048
|
return this.sendEvent('keyDown', evt) ? evt.hasCustomEventHandling : YES;
|
1850
|
-
|
2049
|
+
}
|
1851
2050
|
}
|
1852
2051
|
},
|
1853
2052
|
|
1854
|
-
keyup: function
|
2053
|
+
keyup: function(evt) {
|
1855
2054
|
// to end the simulation of keypress in firefox set the _ffevt to null
|
1856
|
-
if
|
2055
|
+
if(this._ffevt) this._ffevt=null;
|
1857
2056
|
|
1858
2057
|
// modifier keys are handled separately by the 'flagsChanged' event
|
1859
2058
|
// send event for modifier key changes, but only stop processing if this is only a modifier change
|
@@ -1862,7 +2061,7 @@ SC.RootResponder = SC.Object.extend(
|
|
1862
2061
|
// Fix for IME input (japanese, mandarin).
|
1863
2062
|
// If the KeyCode is 229 wait for the keyup and
|
1864
2063
|
// trigger a keyDown if it is is enter onKeyup.
|
1865
|
-
if (this._IMEInputON && evt.keyCode
|
2064
|
+
if (this._IMEInputON && evt.keyCode===13){
|
1866
2065
|
evt.isIMEInput = YES;
|
1867
2066
|
this.sendEvent('keyDown', evt);
|
1868
2067
|
this._IMEInputON = NO;
|
@@ -1879,10 +2078,10 @@ SC.RootResponder = SC.Object.extend(
|
|
1879
2078
|
want to avoid this. Think of an autocomplete menu, you want to click on
|
1880
2079
|
the menu but don't loose focus.
|
1881
2080
|
*/
|
1882
|
-
beforedeactivate: function
|
2081
|
+
beforedeactivate: function(evt) {
|
1883
2082
|
var toElement = evt.toElement;
|
1884
|
-
if (toElement && toElement.tagName && toElement.tagName
|
1885
|
-
var view = SC
|
2083
|
+
if (toElement && toElement.tagName && toElement.tagName!=="IFRAME") {
|
2084
|
+
var view = SC.viewFor(toElement);
|
1886
2085
|
//The following line is necessary to allow/block text selection for IE,
|
1887
2086
|
// in combination with the selectstart event.
|
1888
2087
|
if (view && view.get('blocksIEDeactivate')) return NO;
|
@@ -1894,30 +2093,30 @@ SC.RootResponder = SC.Object.extend(
|
|
1894
2093
|
// MOUSE HANDLING
|
1895
2094
|
//
|
1896
2095
|
|
1897
|
-
mousedown: function
|
2096
|
+
mousedown: function(evt) {
|
1898
2097
|
// First, save the click count. The click count resets if the mouse down
|
1899
2098
|
// event occurs more than 250 ms later than the mouse up event or more
|
1900
2099
|
// than 8 pixels away from the mouse down event or if the button used is different.
|
1901
|
-
this._clickCount += 1;
|
2100
|
+
this._clickCount += 1 ;
|
1902
2101
|
if (!this._lastMouseUpAt || this._lastClickWhich !== evt.which || ((Date.now() - this._lastMouseUpAt) > 250)) {
|
1903
|
-
this._clickCount = 1;
|
2102
|
+
this._clickCount = 1 ;
|
1904
2103
|
} else {
|
1905
2104
|
var deltaX = this._lastMouseDownX - evt.clientX,
|
1906
2105
|
deltaY = this._lastMouseDownY - evt.clientY,
|
1907
|
-
distance = Math.sqrt(deltaX
|
2106
|
+
distance = Math.sqrt(deltaX*deltaX + deltaY*deltaY) ;
|
1908
2107
|
|
1909
|
-
if (distance > 8.0) this._clickCount = 1;
|
2108
|
+
if (distance > 8.0) this._clickCount = 1 ;
|
1910
2109
|
}
|
1911
|
-
evt.clickCount = this._clickCount;
|
2110
|
+
evt.clickCount = this._clickCount ;
|
1912
2111
|
|
1913
2112
|
this._lastClickWhich = evt.which;
|
1914
|
-
this._lastMouseDownX = evt.clientX;
|
1915
|
-
this._lastMouseDownY = evt.clientY;
|
2113
|
+
this._lastMouseDownX = evt.clientX ;
|
2114
|
+
this._lastMouseDownY = evt.clientY ;
|
1916
2115
|
|
1917
2116
|
var view = this.targetViewForEvent(evt);
|
1918
2117
|
|
1919
|
-
view = this._mouseDownView = this.sendEvent('mouseDown', evt, view);
|
1920
|
-
if (view && view.respondsTo('mouseDragged')) this._mouseCanDrag = YES;
|
2118
|
+
view = this._mouseDownView = this.sendEvent('mouseDown', evt, view) ;
|
2119
|
+
if (view && view.respondsTo('mouseDragged')) this._mouseCanDrag = YES ;
|
1921
2120
|
|
1922
2121
|
// Determine if any views took responsibility for the
|
1923
2122
|
// event. If so, save that information so we can prevent
|
@@ -1935,7 +2134,7 @@ SC.RootResponder = SC.Object.extend(
|
|
1935
2134
|
implemented, then no mouseUp event will be sent, but a click will be
|
1936
2135
|
sent.
|
1937
2136
|
*/
|
1938
|
-
mouseup: function
|
2137
|
+
mouseup: function(evt) {
|
1939
2138
|
var clickOrDoubleClickDidTrigger = NO,
|
1940
2139
|
dragView = this._drag,
|
1941
2140
|
handler = null;
|
@@ -1949,41 +2148,41 @@ SC.RootResponder = SC.Object.extend(
|
|
1949
2148
|
var view = this._mouseDownView,
|
1950
2149
|
targetView = this.targetViewForEvent(evt);
|
1951
2150
|
|
1952
|
-
|
1953
|
-
|
2151
|
+
// record click count.
|
2152
|
+
evt.clickCount = this._clickCount ;
|
1954
2153
|
|
1955
|
-
|
1956
|
-
|
1957
|
-
|
1958
|
-
|
2154
|
+
// attempt the mouseup call only if there's a target.
|
2155
|
+
// don't want a mouseup going to anyone unless they handled the mousedown...
|
2156
|
+
if (view) {
|
2157
|
+
handler = this.sendEvent('mouseUp', evt, view) ;
|
1959
2158
|
|
1960
|
-
|
1961
|
-
|
1962
|
-
|
1963
|
-
|
1964
|
-
|
2159
|
+
// try doubleClick
|
2160
|
+
if (!handler && (this._clickCount === 2)) {
|
2161
|
+
handler = this.sendEvent('doubleClick', evt, view) ;
|
2162
|
+
clickOrDoubleClickDidTrigger = YES;
|
2163
|
+
}
|
1965
2164
|
|
1966
|
-
|
1967
|
-
|
1968
|
-
|
1969
|
-
|
1970
|
-
}
|
2165
|
+
// try single click
|
2166
|
+
if (!handler) {
|
2167
|
+
handler = this.sendEvent('click', evt, view) ;
|
2168
|
+
clickOrDoubleClickDidTrigger = YES;
|
1971
2169
|
}
|
2170
|
+
}
|
1972
2171
|
|
1973
|
-
|
1974
|
-
|
2172
|
+
// try whoever's under the mouse if we haven't handle the mouse up yet
|
2173
|
+
if (!handler && !clickOrDoubleClickDidTrigger) {
|
1975
2174
|
|
1976
|
-
|
1977
|
-
|
1978
|
-
|
1979
|
-
|
2175
|
+
// try doubleClick
|
2176
|
+
if (this._clickCount === 2) {
|
2177
|
+
handler = this.sendEvent('doubleClick', evt, targetView);
|
2178
|
+
}
|
1980
2179
|
|
1981
|
-
|
1982
|
-
|
1983
|
-
|
1984
|
-
}
|
2180
|
+
// try singleClick
|
2181
|
+
if (!handler) {
|
2182
|
+
handler = this.sendEvent('click', evt, targetView) ;
|
1985
2183
|
}
|
1986
2184
|
}
|
2185
|
+
}
|
1987
2186
|
|
1988
2187
|
// cleanup
|
1989
2188
|
this._mouseCanDrag = NO;
|
@@ -1991,7 +2190,7 @@ SC.RootResponder = SC.Object.extend(
|
|
1991
2190
|
|
1992
2191
|
// Save timestamp of mouseup at last possible moment.
|
1993
2192
|
// (This is used to calculate double click events)
|
1994
|
-
this._lastMouseUpAt = Date.now();
|
2193
|
+
this._lastMouseUpAt = Date.now() ;
|
1995
2194
|
|
1996
2195
|
// Determine if any views took responsibility for the
|
1997
2196
|
// event. If so, save that information so we can prevent
|
@@ -2012,7 +2211,7 @@ SC.RootResponder = SC.Object.extend(
|
|
2012
2211
|
@param {Event} evt the click event
|
2013
2212
|
@returns {Boolean} whether the event should be propagated to the browser
|
2014
2213
|
*/
|
2015
|
-
click: function
|
2214
|
+
click: function(evt) {
|
2016
2215
|
if (!this._lastMouseUpCustomHandling || !this._lastMouseDownCustomHandling) {
|
2017
2216
|
evt.preventDefault();
|
2018
2217
|
evt.stopPropagation();
|
@@ -2022,7 +2221,7 @@ SC.RootResponder = SC.Object.extend(
|
|
2022
2221
|
return YES;
|
2023
2222
|
},
|
2024
2223
|
|
2025
|
-
dblclick: function
|
2224
|
+
dblclick: function(evt){
|
2026
2225
|
if (SC.browser.isIE8OrLower) {
|
2027
2226
|
this._clickCount = 2;
|
2028
2227
|
// this._onmouseup(evt);
|
@@ -2030,11 +2229,11 @@ SC.RootResponder = SC.Object.extend(
|
|
2030
2229
|
}
|
2031
2230
|
},
|
2032
2231
|
|
2033
|
-
mousewheel: function
|
2034
|
-
var view = this.targetViewForEvent(evt),
|
2035
|
-
|
2232
|
+
mousewheel: function(evt) {
|
2233
|
+
var view = this.targetViewForEvent(evt) ,
|
2234
|
+
handler = this.sendEvent('mouseWheel', evt, view) ;
|
2036
2235
|
|
2037
|
-
return (handler) ? evt.hasCustomEventHandling : YES;
|
2236
|
+
return (handler) ? evt.hasCustomEventHandling : YES ;
|
2038
2237
|
},
|
2039
2238
|
|
2040
2239
|
_lastHovered: null,
|
@@ -2048,7 +2247,7 @@ SC.RootResponder = SC.Object.extend(
|
|
2048
2247
|
If there is a target mouseDown view, then mouse moved events will also
|
2049
2248
|
trigger calls to mouseDragged.
|
2050
2249
|
*/
|
2051
|
-
mousemove: function
|
2250
|
+
mousemove: function(evt) {
|
2052
2251
|
|
2053
2252
|
if (SC.browser.isIE) {
|
2054
2253
|
if (this._lastMoveX === evt.clientX && this._lastMoveY === evt.clientY) return;
|
@@ -2059,7 +2258,7 @@ SC.RootResponder = SC.Object.extend(
|
|
2059
2258
|
this._lastMoveX = evt.clientX;
|
2060
2259
|
this._lastMoveY = evt.clientY;
|
2061
2260
|
|
2062
|
-
SC.run(function
|
2261
|
+
SC.run(function() {
|
2063
2262
|
var dragView = this._drag;
|
2064
2263
|
|
2065
2264
|
// make sure the view gets focus no matter what. FF is inconsistent
|
@@ -2068,60 +2267,217 @@ SC.RootResponder = SC.Object.extend(
|
|
2068
2267
|
// only do mouse[Moved|Entered|Exited|Dragged] if not in a drag session
|
2069
2268
|
// drags send their own events, e.g. drag[Moved|Entered|Exited]
|
2070
2269
|
if (dragView) {
|
2071
|
-
|
2072
|
-
|
2073
|
-
|
2270
|
+
//IE triggers mousemove at the same time as mousedown
|
2271
|
+
if(SC.browser.isIE){
|
2272
|
+
if (this._lastMouseDownX !== evt.clientX || this._lastMouseDownY !== evt.clientY) {
|
2074
2273
|
dragView.tryToPerform('mouseDragged', evt);
|
2075
|
-
|
2274
|
+
}
|
2076
2275
|
} else {
|
2077
2276
|
dragView.tryToPerform('mouseDragged', evt);
|
2078
|
-
|
2079
|
-
|
2277
|
+
}
|
2278
|
+
} else {
|
2080
2279
|
var lh = this._lastHovered || [], nh = [], loc, len,
|
2081
|
-
|
2280
|
+
view = this.targetViewForEvent(evt) ;
|
2281
|
+
|
2282
|
+
// first collect all the responding view starting with the
|
2283
|
+
// target view from the given mouse move event
|
2284
|
+
while (view && (view !== this)) {
|
2285
|
+
nh.push(view);
|
2286
|
+
view = view.get('nextResponder');
|
2287
|
+
}
|
2288
|
+
// next exit views that are no longer part of the
|
2289
|
+
// responding chain
|
2290
|
+
for (loc=0, len=lh.length; loc < len; loc++) {
|
2291
|
+
view = lh[loc] ;
|
2292
|
+
if (nh.indexOf(view) === -1 && !view.isDestroyed) { // Usually we don't want to have to manually check isDestroyed, but in this case we're explicitly checking an out-of-date cache.
|
2293
|
+
view.tryToPerform('mouseExited', evt);
|
2294
|
+
}
|
2295
|
+
}
|
2296
|
+
// finally, either perform mouse moved or mouse entered depending on
|
2297
|
+
// whether a responding view was or was not part of the last
|
2298
|
+
// hovered views
|
2299
|
+
for (loc=0, len=nh.length; loc < len; loc++) {
|
2300
|
+
view = nh[loc];
|
2301
|
+
if (lh.indexOf(view) !== -1) {
|
2302
|
+
view.tryToPerform('mouseMoved', evt);
|
2303
|
+
} else {
|
2304
|
+
view.tryToPerform('mouseEntered', evt);
|
2305
|
+
}
|
2306
|
+
}
|
2307
|
+
// Keep track of the view that were last hovered
|
2308
|
+
this._lastHovered = nh;
|
2309
|
+
// also, if a mouseDownView exists, call the mouseDragged action, if
|
2310
|
+
// it exists.
|
2311
|
+
if (this._mouseDownView) {
|
2312
|
+
if(SC.browser.isIE){
|
2313
|
+
if (this._lastMouseDownX !== evt.clientX && this._lastMouseDownY !== evt.clientY) {
|
2314
|
+
this._mouseDownView.tryToPerform('mouseDragged', evt);
|
2315
|
+
}
|
2316
|
+
}
|
2317
|
+
else {
|
2318
|
+
this._mouseDownView.tryToPerform('mouseDragged', evt);
|
2319
|
+
}
|
2320
|
+
}
|
2321
|
+
}
|
2322
|
+
}, this);
|
2323
|
+
},
|
2082
2324
|
|
2083
|
-
|
2084
|
-
|
2085
|
-
|
2086
|
-
|
2087
|
-
|
2088
|
-
|
2089
|
-
|
2090
|
-
|
2091
|
-
|
2092
|
-
|
2093
|
-
|
2094
|
-
|
2095
|
-
|
2096
|
-
|
2097
|
-
|
2098
|
-
|
2099
|
-
|
2100
|
-
|
2101
|
-
|
2102
|
-
|
2103
|
-
|
2104
|
-
|
2105
|
-
|
2106
|
-
|
2325
|
+
// These event handlers prevent default file handling, and enable the dataDrag API.
|
2326
|
+
/** @private The dragenter event comes from the browser when a data-ful drag enters any element. */
|
2327
|
+
dragenter: function(evt) {
|
2328
|
+
SC.run(function() { this._dragenter(evt); }, this);
|
2329
|
+
},
|
2330
|
+
/** @private */
|
2331
|
+
_dragenter: function(evt) {
|
2332
|
+
if (!this._dragCounter) {
|
2333
|
+
this._dragCounter = 1;
|
2334
|
+
}
|
2335
|
+
else this._dragCounter++;
|
2336
|
+
return this._dragover(evt);
|
2337
|
+
},
|
2338
|
+
/** @private The dragleave event comes from the browser when a data-ful drag leaves any element. */
|
2339
|
+
dragleave: function(evt) {
|
2340
|
+
SC.run(function() { this._dragleave(evt); }, this);
|
2341
|
+
},
|
2342
|
+
/** @private */
|
2343
|
+
_dragleave: function(evt) {
|
2344
|
+
this._dragCounter--;
|
2345
|
+
var ret = this._dragover(evt);
|
2346
|
+
return ret;
|
2347
|
+
},
|
2348
|
+
/** @private
|
2349
|
+
Dragleave doesn't fire reliably in all browsers, so this method forces it (scheduled below). Note
|
2350
|
+
that, being scheduled via SC.Timer, this method is already in a run loop.
|
2351
|
+
*/
|
2352
|
+
_forceDragLeave: function() {
|
2353
|
+
// Give it another runloop to ensure that we're not in the middle of a drag.
|
2354
|
+
this.invokeLast(function() {
|
2355
|
+
if (this._dragCounter === 0) return;
|
2356
|
+
this._dragCounter = 0;
|
2357
|
+
var evt = this._lastDraggedEvt;
|
2358
|
+
this._dragover(evt);
|
2359
|
+
});
|
2360
|
+
},
|
2361
|
+
/** @private This event fires continuously while the dataful drag is over the document. */
|
2362
|
+
dragover: function(evt) {
|
2363
|
+
SC.run(function() { this._dragover(evt); }, this);
|
2364
|
+
},
|
2365
|
+
/** @private */
|
2366
|
+
_dragover: function(evt) {
|
2367
|
+
// If it's a file being dragged, prevent the default (leaving the app and opening the file).
|
2368
|
+
if (evt.dataTransfer.types && (evt.dataTransfer.types.contains('Files') || evt.dataTransfer.types.contains('text/uri-list'))) {
|
2369
|
+
evt.preventDefault();
|
2370
|
+
evt.stopPropagation();
|
2371
|
+
// Set the default drag effect to 'none'. Views may reverse this if they wish.
|
2372
|
+
evt.dataTransfer.dropEffect = 'none';
|
2373
|
+
}
|
2374
|
+
|
2375
|
+
// Walk the responder chain, alerting anyone that would like to know.
|
2376
|
+
var ld = this._lastDraggedOver || [], nd = [], loc, len,
|
2377
|
+
view = this.targetViewForEvent(evt);
|
2378
|
+
|
2379
|
+
// Build the responder chain, starting with the view's target and (presumably) moving
|
2380
|
+
// up through parentViews to the pane.
|
2381
|
+
while (view && (view !== this)) {
|
2382
|
+
nd.push(view);
|
2383
|
+
view = view.get('nextResponder');
|
2384
|
+
}
|
2385
|
+
|
2386
|
+
// Invalidate the force-drag-leave timer, if we have one set up.
|
2387
|
+
if (this._dragLeaveTimer) this._dragLeaveTimer.invalidate();
|
2388
|
+
|
2389
|
+
// If this is our final drag event then we've left the document and everybody gets a
|
2390
|
+
// dataDragExited.
|
2391
|
+
if (this._dragCounter === 0) {
|
2392
|
+
for (loc = 0, len = nd.length; loc < len; loc++) {
|
2393
|
+
view = nd[loc];
|
2394
|
+
view.tryToPerform('dataDragExited', evt);
|
2395
|
+
}
|
2396
|
+
this._lastDraggedOver = this._lastDraggedEvt = this._dragLeaveTimer = null;
|
2397
|
+
}
|
2398
|
+
// Otherwise, we process the responder chain normally, ignoring dragleaves.
|
2399
|
+
// (We skip dragleave events because they are sent after the adjacent dragenter event; checking
|
2400
|
+
// through both stacks would result in views being exited, re-entered and re-exited each time.
|
2401
|
+
// As a consequence, views are left ignorant of a very small number of dragleave events; those
|
2402
|
+
// shouldn't end up being the crucial just-before-drop events, though, so they should be of no
|
2403
|
+
// consequence.)
|
2404
|
+
else if (evt.type !== 'dragleave') {
|
2405
|
+
// First, exit views that are no longer part of the responder chain, child to parent.
|
2406
|
+
for (loc = 0, len = ld.length; loc < len; loc++) {
|
2407
|
+
view = ld[loc];
|
2408
|
+
if (nd.indexOf(view) === -1) {
|
2409
|
+
view.tryToPerform('dataDragExited', evt);
|
2107
2410
|
}
|
2108
|
-
|
2109
|
-
|
2110
|
-
|
2111
|
-
|
2112
|
-
if (
|
2113
|
-
|
2114
|
-
if (this._lastMouseDownX !== evt.clientX && this._lastMouseDownY !== evt.clientY) {
|
2115
|
-
this._mouseDownView.tryToPerform('mouseDragged', evt);
|
2116
|
-
}
|
2117
|
-
}
|
2118
|
-
else {
|
2119
|
-
this._mouseDownView.tryToPerform('mouseDragged', evt);
|
2120
|
-
}
|
2411
|
+
}
|
2412
|
+
// Next, enter views that have just joined the responder chain, parent to child.
|
2413
|
+
for (loc = nd.length - 1; loc >= 0; loc--) {
|
2414
|
+
view = nd[loc];
|
2415
|
+
if (ld.indexOf(view) === -1) {
|
2416
|
+
view.tryToPerform('dataDragEntered', evt);
|
2121
2417
|
}
|
2122
2418
|
}
|
2123
|
-
|
2419
|
+
// Finally, send hover events to everybody.
|
2420
|
+
for (loc = 0, len = nd.length; loc < len; loc++) {
|
2421
|
+
view = nd[loc];
|
2422
|
+
view.tryToPerform('dataDragHovered', evt);
|
2423
|
+
}
|
2424
|
+
this._lastDraggedOver = nd;
|
2425
|
+
this._lastDraggedEvt = evt;
|
2426
|
+
// For browsers that don't reliably call a dragleave for every dragenter, we have a timer fallback.
|
2427
|
+
this._dragLeaveTimer = SC.Timer.schedule({ target: this, action: '_forceDragLeave', interval: 300 });
|
2428
|
+
}
|
2429
|
+
},
|
2430
|
+
|
2431
|
+
/** @private This event is called if the most recent dragover event returned with a non-"none" dropEffect. */
|
2432
|
+
drop: function(evt) {
|
2433
|
+
SC.run(function() { this._drop(evt); }, this);
|
2124
2434
|
},
|
2435
|
+
/** @private */
|
2436
|
+
_drop: function(evt) {
|
2437
|
+
// If it's a file being dragged, prevent the default (leaving the app and opening the file).
|
2438
|
+
if (evt.dataTransfer.types && (evt.dataTransfer.types.contains('Files') || evt.dataTransfer.types.contains('text/uri-list'))) {
|
2439
|
+
evt.preventDefault();
|
2440
|
+
evt.stopPropagation();
|
2441
|
+
// Set the default drag effect to 'none'. Views may reverse this if they wish.
|
2442
|
+
evt.dataTransfer.dropEffect = 'none';
|
2443
|
+
}
|
2444
|
+
|
2445
|
+
// Bubble up the responder chain until we have a successful responder.
|
2446
|
+
var ld = this._lastDraggedOver || [], nd = [], loc, len,
|
2447
|
+
view = this.targetViewForEvent(evt);
|
2448
|
+
|
2449
|
+
// First collect all the responding view starting with the target view from the given drag event.
|
2450
|
+
while (view && (view !== this)) {
|
2451
|
+
nd.push(view);
|
2452
|
+
view = view.get('nextResponder');
|
2453
|
+
}
|
2454
|
+
// Next, exit views that are no longer part of the responding chain. (This avoids the pixel-wide
|
2455
|
+
// edge case where a drop event fires on a new view without a final dragover event.)
|
2456
|
+
for (loc = 0, len = ld.length; loc < len; loc++) {
|
2457
|
+
view = ld[loc];
|
2458
|
+
if (nd.indexOf(view) === -1) {
|
2459
|
+
view.tryToPerform('dataDragExited', evt);
|
2460
|
+
}
|
2461
|
+
}
|
2462
|
+
// Next, bubble the drop event itself until we find someone that successfully responds.
|
2463
|
+
for (loc = 0, len = nd.length; loc < len; loc++) {
|
2464
|
+
view = nd[loc];
|
2465
|
+
if (view.tryToPerform('dataDragDropped', evt)) break;
|
2466
|
+
}
|
2467
|
+
// Finally, notify all interested views that the drag is dead and gone.
|
2468
|
+
for (loc = 0, len = nd.length; loc < len; loc++) {
|
2469
|
+
view = nd[loc];
|
2470
|
+
view.tryToPerform('dataDragExited', evt);
|
2471
|
+
}
|
2472
|
+
|
2473
|
+
// Reset caches and counters.
|
2474
|
+
this._lastDraggedOver = null;
|
2475
|
+
this._lastDraggedAt = null;
|
2476
|
+
this._dragCounter = 0;
|
2477
|
+
if (this._dragLeaveTimer) this._dragLeaveTimer.invalidate();
|
2478
|
+
this._dragLeaveTimer = null;
|
2479
|
+
},
|
2480
|
+
|
2125
2481
|
|
2126
2482
|
// these methods are used to prevent unnecessary text-selection in IE,
|
2127
2483
|
// there could be some more work to improve this behavior and make it
|
@@ -2130,22 +2486,22 @@ SC.RootResponder = SC.Object.extend(
|
|
2130
2486
|
|
2131
2487
|
_mouseCanDrag: YES,
|
2132
2488
|
|
2133
|
-
selectstart: function
|
2489
|
+
selectstart: function(evt) {
|
2134
2490
|
var targetView = this.targetViewForEvent(evt),
|
2135
2491
|
result = this.sendEvent('selectStart', evt, targetView);
|
2136
2492
|
|
2137
2493
|
// If the target view implements mouseDragged, then we want to ignore the
|
2138
2494
|
// 'selectstart' event.
|
2139
2495
|
if (targetView && targetView.respondsTo('mouseDragged')) {
|
2140
|
-
return (result !==
|
2496
|
+
return (result !==null ? YES: NO) && !this._mouseCanDrag;
|
2141
2497
|
} else {
|
2142
|
-
return (result !==
|
2498
|
+
return (result !==null ? YES: NO);
|
2143
2499
|
}
|
2144
2500
|
},
|
2145
2501
|
|
2146
|
-
drag: function
|
2502
|
+
drag: function() { return false; },
|
2147
2503
|
|
2148
|
-
contextmenu: function
|
2504
|
+
contextmenu: function(evt) {
|
2149
2505
|
var view = this.targetViewForEvent(evt),
|
2150
2506
|
ret;
|
2151
2507
|
|
@@ -2162,179 +2518,44 @@ SC.RootResponder = SC.Object.extend(
|
|
2162
2518
|
|
2163
2519
|
/* @private Handler for animationstart events. */
|
2164
2520
|
animationstart: function (evt) {
|
2165
|
-
|
2166
|
-
|
2521
|
+
var view = this.targetViewForEvent(evt) ;
|
2522
|
+
this.sendEvent('animationDidStart', evt, view) ;
|
2167
2523
|
|
2168
2524
|
return view ? evt.hasCustomEventHandling : YES;
|
2169
2525
|
},
|
2170
2526
|
|
2171
2527
|
/* @private Handler for animationiteration events. */
|
2172
2528
|
animationiteration: function (evt) {
|
2173
|
-
|
2174
|
-
|
2529
|
+
var view = this.targetViewForEvent(evt) ;
|
2530
|
+
this.sendEvent('animationDidIterate', evt, view) ;
|
2175
2531
|
|
2176
2532
|
return view ? evt.hasCustomEventHandling : YES;
|
2177
2533
|
},
|
2178
2534
|
|
2179
2535
|
/* @private Handler for animationend events. */
|
2180
2536
|
animationend: function (evt) {
|
2181
|
-
|
2182
|
-
|
2537
|
+
var view = this.targetViewForEvent(evt) ;
|
2538
|
+
this.sendEvent('animationDidEnd', evt, view) ;
|
2183
2539
|
|
2184
2540
|
return view ? evt.hasCustomEventHandling : YES;
|
2185
2541
|
},
|
2186
2542
|
|
2187
2543
|
/* @private Handler for transitionend events. */
|
2188
2544
|
transitionend: function (evt) {
|
2189
|
-
|
2190
|
-
|
2545
|
+
var view = this.targetViewForEvent(evt) ;
|
2546
|
+
this.sendEvent('transitionDidEnd', evt, view) ;
|
2191
2547
|
|
2192
2548
|
return view ? evt.hasCustomEventHandling : YES;
|
2193
2549
|
}
|
2194
2550
|
|
2195
2551
|
});
|
2196
2552
|
|
2197
|
-
/**
|
2198
|
-
@class SC.Touch
|
2199
|
-
Represents a touch.
|
2200
|
-
|
2201
|
-
Views receive touchStart and touchEnd.
|
2202
|
-
*/
|
2203
|
-
SC.Touch = function (touch, touchContext) {
|
2204
|
-
// get the raw target view (we'll refine later)
|
2205
|
-
this.touchContext = touchContext;
|
2206
|
-
this.identifier = touch.identifier; // for now, our internal id is WebKit's id.
|
2207
|
-
|
2208
|
-
var target = touch.target, targetView;
|
2209
|
-
if (target && SC.$(target).hasClass("touch-intercept")) {
|
2210
|
-
touch.target.style.webkitTransform = "translate3d(0px,-5000px,0px)";
|
2211
|
-
target = document.elementFromPoint(touch.pageX, touch.pageY);
|
2212
|
-
if (target) targetView = SC.$(target).view()[0];
|
2213
|
-
|
2214
|
-
this.hidesTouchIntercept = NO;
|
2215
|
-
if (target.tagName === "INPUT") {
|
2216
|
-
this.hidesTouchIntercept = touch.target;
|
2217
|
-
} else {
|
2218
|
-
touch.target.style.webkitTransform = "translate3d(0px,0px,0px)";
|
2219
|
-
}
|
2220
|
-
} else {
|
2221
|
-
targetView = touch.target ? SC.$(touch.target).view()[0] : null;
|
2222
|
-
}
|
2223
|
-
this.targetView = targetView;
|
2224
|
-
this.target = target;
|
2225
|
-
this.hasEnded = NO;
|
2226
|
-
this.type = touch.type;
|
2227
|
-
this.clickCount = 1;
|
2228
|
-
|
2229
|
-
this.view = undefined;
|
2230
|
-
this.touchResponder = this.nextTouchResponder = undefined;
|
2231
|
-
this.touchResponders = [];
|
2232
|
-
|
2233
|
-
this.startX = this.pageX = touch.pageX;
|
2234
|
-
this.startY = this.pageY = touch.pageY;
|
2235
|
-
this.clientX = touch.clientX;
|
2236
|
-
this.clientY = touch.clientY;
|
2237
|
-
this.screenX = touch.screenX;
|
2238
|
-
this.screenY = touch.screenY;
|
2239
|
-
};
|
2240
|
-
|
2241
|
-
SC.Touch.prototype = {
|
2242
|
-
/**@scope SC.Touch.prototype*/
|
2243
|
-
|
2244
|
-
unhideTouchIntercept: function () {
|
2245
|
-
var intercept = this.hidesTouchIntercept;
|
2246
|
-
if (intercept) {
|
2247
|
-
setTimeout(function () { intercept.style.webkitTransform = "translate3d(0px,0px,0px)"; }, 500);
|
2248
|
-
}
|
2249
|
-
},
|
2250
|
-
|
2251
|
-
/**
|
2252
|
-
Indicates that you want to allow the normal default behavior. Sets
|
2253
|
-
the hasCustomEventHandling property to YES but does not cancel the event.
|
2254
|
-
*/
|
2255
|
-
allowDefault: function () {
|
2256
|
-
if (this.event) this.event.hasCustomEventHandling = YES;
|
2257
|
-
},
|
2258
|
-
|
2259
|
-
/**
|
2260
|
-
If the touch is associated with an event, prevents default action on the event.
|
2261
|
-
*/
|
2262
|
-
preventDefault: function () {
|
2263
|
-
if (this.event) this.event.preventDefault();
|
2264
|
-
},
|
2265
|
-
|
2266
|
-
stopPropagation: function () {
|
2267
|
-
if (this.event) this.event.stopPropagation();
|
2268
|
-
},
|
2269
|
-
|
2270
|
-
stop: function () {
|
2271
|
-
if (this.event) this.event.stop();
|
2272
|
-
},
|
2273
|
-
|
2274
|
-
/**
|
2275
|
-
Removes from and calls touchEnd on the touch responder.
|
2276
|
-
*/
|
2277
|
-
end: function () {
|
2278
|
-
this.touchContext.endTouch(this);
|
2279
|
-
},
|
2280
|
-
|
2281
|
-
/**
|
2282
|
-
Changes the touch responder for the touch. If shouldStack === YES,
|
2283
|
-
the current responder will be saved so that the next responder may
|
2284
|
-
return to it.
|
2285
|
-
*/
|
2286
|
-
makeTouchResponder: function (responder, shouldStack, upViewChain) {
|
2287
|
-
this.touchContext.makeTouchResponder(this, responder, shouldStack, upViewChain);
|
2288
|
-
},
|
2289
|
-
|
2290
|
-
|
2291
|
-
/**
|
2292
|
-
Captures, or recaptures, the touch. This works from the touch's raw target view
|
2293
|
-
up to the startingPoint, and finds either a view that returns YES to captureTouch() or
|
2294
|
-
touchStart().
|
2295
|
-
*/
|
2296
|
-
captureTouch: function (startingPoint, shouldStack) {
|
2297
|
-
this.touchContext.captureTouch(this, startingPoint, shouldStack);
|
2298
|
-
},
|
2299
|
-
|
2300
|
-
/**
|
2301
|
-
Returns all touches for a specified view. Put as a convenience on the touch itself; this method
|
2302
|
-
is also available on the event.
|
2303
|
-
*/
|
2304
|
-
touchesForView: function (view) {
|
2305
|
-
return this.touchContext.touchesForView(view);
|
2306
|
-
},
|
2307
|
-
|
2308
|
-
/**
|
2309
|
-
Same as touchesForView, but sounds better for responders.
|
2310
|
-
*/
|
2311
|
-
touchesForResponder: function (responder) {
|
2312
|
-
return this.touchContext.touchesForView(responder);
|
2313
|
-
},
|
2314
|
-
|
2315
|
-
/**
|
2316
|
-
Returns average data--x, y, and d (distance)--for the touches owned by the supplied view.
|
2317
|
-
|
2318
|
-
addSelf adds this touch to the set being considered. This is useful from touchStart. If
|
2319
|
-
you use it from anywhere else, it will make this touch be used twice--so use caution.
|
2320
|
-
*/
|
2321
|
-
averagedTouchesForView: function (view, addSelf) {
|
2322
|
-
return this.touchContext.averagedTouchesForView(view, (addSelf ? this : null));
|
2323
|
-
}
|
2324
|
-
};
|
2325
|
-
|
2326
|
-
SC.mixin(SC.Touch, {
|
2327
|
-
create: function (touch, touchContext) {
|
2328
|
-
return new SC.Touch(touch, touchContext);
|
2329
|
-
}
|
2330
|
-
});
|
2331
|
-
|
2332
2553
|
/*
|
2333
2554
|
Invoked when the document is ready, but before main is called. Creates
|
2334
2555
|
an instance and sets up event listeners as needed.
|
2335
2556
|
*/
|
2336
|
-
SC.ready(SC.RootResponder, SC.RootResponder.ready = function
|
2557
|
+
SC.ready(SC.RootResponder, SC.RootResponder.ready = function() {
|
2337
2558
|
var r;
|
2338
|
-
r = SC.RootResponder.responder = SC.RootResponder.create();
|
2339
|
-
r.setup();
|
2559
|
+
r = SC.RootResponder.responder = SC.RootResponder.create() ;
|
2560
|
+
r.setup() ;
|
2340
2561
|
});
|