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.
Files changed (380) hide show
  1. checksums.yaml +8 -8
  2. data/CHANGELOG +4 -8
  3. data/VERSION.yml +2 -2
  4. data/lib/frameworks/sproutcore/Buildfile +5 -4
  5. data/lib/frameworks/sproutcore/CHANGELOG.md +274 -40
  6. data/lib/frameworks/sproutcore/CONTRIBUTORS.md +133 -0
  7. data/lib/frameworks/sproutcore/README.md +31 -144
  8. data/lib/frameworks/sproutcore/apps/showcase/controllers/source_tree_controller.js +9 -4
  9. data/lib/frameworks/sproutcore/apps/showcase/resources/stylesheet.css +5 -0
  10. data/lib/frameworks/sproutcore/apps/showcase/system/views_item_content.js +1 -1
  11. data/lib/frameworks/sproutcore/apps/showcase/views/split_views.js +15 -2
  12. data/lib/frameworks/sproutcore/apps/showcase/views/stacked_views.js +1 -1
  13. data/lib/frameworks/sproutcore/apps/tests/english.lproj/main_page.js +11 -1
  14. data/lib/frameworks/sproutcore/frameworks/ajax/mixins/websocket_delegate.js +90 -0
  15. data/lib/frameworks/sproutcore/frameworks/ajax/system/request.js +81 -5
  16. data/lib/frameworks/sproutcore/frameworks/ajax/system/response.js +23 -4
  17. data/lib/frameworks/sproutcore/frameworks/ajax/system/websocket.js +475 -0
  18. data/lib/frameworks/sproutcore/frameworks/ajax/tests/system/request.js +149 -26
  19. data/lib/frameworks/sproutcore/frameworks/ajax/tests/system/websocket.js +197 -0
  20. data/lib/frameworks/sproutcore/frameworks/ajax/tests/system/xhr_response_test.js +65 -0
  21. data/lib/frameworks/sproutcore/frameworks/bootstrap/system/loader.js +4 -0
  22. data/lib/frameworks/sproutcore/frameworks/core_foundation/child_view_layouts/horizontal_stack_layout.js +232 -52
  23. data/lib/frameworks/sproutcore/frameworks/core_foundation/child_view_layouts/vertical_stack_layout.js +235 -49
  24. data/lib/frameworks/sproutcore/frameworks/core_foundation/controllers/array.js +23 -13
  25. data/lib/frameworks/sproutcore/frameworks/core_foundation/controllers/object.js +3 -1
  26. data/lib/frameworks/sproutcore/frameworks/core_foundation/core.js +81 -1
  27. data/lib/frameworks/sproutcore/frameworks/core_foundation/english.lproj/ordinal.js +17 -0
  28. data/lib/frameworks/sproutcore/frameworks/core_foundation/ext/string.js +7 -0
  29. data/lib/frameworks/sproutcore/frameworks/{desktop/tests/views/disclosure/methods.js → core_foundation/french.lproj/ordinal.js} +7 -4
  30. data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/layout.js +2 -6
  31. data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/main.js +1 -1
  32. data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/pane.js +104 -69
  33. data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/pane_statechart.js +6 -1
  34. data/lib/frameworks/sproutcore/frameworks/core_foundation/protocols/child_view_layout_protocol.js +59 -0
  35. data/lib/frameworks/sproutcore/frameworks/core_foundation/protocols/view_transition_protocol.js +18 -1
  36. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/application.js +192 -0
  37. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/bezier_curves.js +52 -0
  38. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/color.js +384 -64
  39. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/core_query.js +6 -14
  40. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/device.js +21 -35
  41. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/event.js +72 -36
  42. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/locale.js +90 -34
  43. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/platform.js +55 -7
  44. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/render_context.js +20 -15
  45. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/req_anim_frame.js +9 -10
  46. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/root_responder.js +763 -542
  47. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/selection_set.js +4 -3
  48. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/sparse_array.js +1 -7
  49. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/string.js +14 -0
  50. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/touch.js +538 -0
  51. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/utils/rect.js +56 -1
  52. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/controllers/array/array_case.js +99 -4
  53. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/controllers/object/single_case.js +25 -19
  54. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/core_tests.js +75 -0
  55. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/ext/number_test.js +81 -0
  56. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/mixins/action_support.js +4 -4
  57. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/mixins/responder_context.js +4 -4
  58. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/mixins/string.js +19 -1
  59. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/system/color.js +36 -20
  60. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/system/root_responder/design_modes_test.js +83 -0
  61. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/system/root_responder/makeMainPane.js +7 -3
  62. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/system/root_responder/mouse_events.js +338 -0
  63. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/system/root_responder/root_responder.js +14 -89
  64. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/system/root_responder/touch.js +106 -0
  65. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/system/sparse_array.js +2 -2
  66. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/system/touch.js +136 -0
  67. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/system/utils/rect.js +42 -1
  68. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/pane/append_remove.js +11 -0
  69. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/pane/child_view.js +5 -5
  70. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/pane/design_mode_test.js +457 -0
  71. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/pane/sendEvent.js +36 -10
  72. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/background_color.js +44 -0
  73. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/border_frame_test.js +51 -24
  74. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/childViewLayout_test.js +176 -1
  75. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/clippingFrame.js +46 -16
  76. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/convertFrames.js +69 -15
  77. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/didAppendToDocument.js +2 -2
  78. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layout.js +7 -1
  79. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layoutDidChange.js +30 -10
  80. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layoutStyle.js +376 -71
  81. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/static_layout.js +0 -10
  82. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/viewDidResize.js +117 -34
  83. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/view_states_test.js +52 -2
  84. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view.js +656 -42
  85. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/animation.js +159 -38
  86. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/cursor.js +0 -7
  87. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/design_mode.js +206 -0
  88. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/enabled.js +0 -28
  89. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/keyboard.js +21 -6
  90. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/layout.js +372 -450
  91. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/layout_style.js +28 -13
  92. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/manipulation.js +22 -51
  93. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/statechart.js +59 -30
  94. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/theming.js +0 -29
  95. data/lib/frameworks/sproutcore/frameworks/datastore/mixins/relationship_support.js +22 -10
  96. data/lib/frameworks/sproutcore/frameworks/datastore/models/children_attribute.js +42 -36
  97. data/lib/frameworks/sproutcore/frameworks/datastore/models/many_attribute.js +54 -3
  98. data/lib/frameworks/sproutcore/frameworks/datastore/models/record.js +178 -59
  99. data/lib/frameworks/sproutcore/frameworks/datastore/models/record_attribute.js +2 -2
  100. data/lib/frameworks/sproutcore/frameworks/datastore/system/child_array.js +206 -132
  101. data/lib/frameworks/sproutcore/frameworks/datastore/system/many_array.js +214 -118
  102. data/lib/frameworks/sproutcore/frameworks/datastore/system/nested_store.js +96 -13
  103. data/lib/frameworks/sproutcore/frameworks/datastore/system/query.js +14 -4
  104. data/lib/frameworks/sproutcore/frameworks/datastore/system/record_array.js +82 -42
  105. data/lib/frameworks/sproutcore/frameworks/datastore/system/store.js +272 -177
  106. data/lib/frameworks/sproutcore/frameworks/datastore/tests/integration/store_interaction_test.js +54 -0
  107. data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/datetime_recordattribute.js +24 -16
  108. data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/many_attribute.js +6 -3
  109. data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/nested_records/data_store.js +267 -35
  110. data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/nested_records/nested_record.js +57 -46
  111. data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/nested_records/nested_record_array.js +150 -53
  112. data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/nested_records/nested_record_array_complex.js +57 -17
  113. data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/nested_records/nested_record_complex.js +13 -9
  114. data/lib/frameworks/sproutcore/frameworks/{experimental/frameworks/polymorphism → datastore}/tests/models/polymorphism/many.js +2 -2
  115. data/lib/frameworks/sproutcore/frameworks/{experimental/frameworks/polymorphism → datastore}/tests/models/polymorphism/simple.js +0 -0
  116. data/lib/frameworks/sproutcore/frameworks/{experimental/frameworks/polymorphism → datastore}/tests/models/polymorphism/single.js +12 -2
  117. data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/record/writeAttribute.js +20 -15
  118. data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/record_attribute.js +9 -2
  119. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/many_array/core_methods.js +80 -14
  120. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/autonomous_dataSourceCallbacks.js +280 -0
  121. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/autonomous_pushChanges.js +232 -0
  122. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/chain.js +31 -5
  123. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/query/parse.js +16 -2
  124. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/store/core_methods.js +60 -40
  125. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/store/materializeRecord.js +78 -0
  126. data/lib/frameworks/sproutcore/frameworks/datetime/frameworks/core/system/datetime.js +13 -1
  127. data/lib/frameworks/sproutcore/frameworks/datetime/frameworks/core/tests/system/datetime.js +20 -0
  128. data/lib/frameworks/sproutcore/frameworks/datetime/frameworks/localized/{resources → english.lproj}/strings.js +0 -0
  129. data/lib/frameworks/sproutcore/frameworks/datetime/frameworks/localized/french.lproj/strings.js +45 -0
  130. data/lib/frameworks/sproutcore/frameworks/designer/designers/object_designer.js +7 -3
  131. data/lib/frameworks/sproutcore/frameworks/desktop/mixins/collection_row_delegate.js +125 -44
  132. data/lib/frameworks/sproutcore/frameworks/desktop/panes/alert.js +139 -48
  133. data/lib/frameworks/sproutcore/frameworks/desktop/panes/draggable.js +202 -0
  134. data/lib/frameworks/sproutcore/frameworks/desktop/panes/menu.js +59 -56
  135. data/lib/frameworks/sproutcore/frameworks/desktop/panes/palette.js +13 -49
  136. data/lib/frameworks/sproutcore/frameworks/desktop/panes/picker.js +466 -305
  137. data/lib/frameworks/sproutcore/frameworks/desktop/protocols/drag_source.js +49 -12
  138. data/lib/frameworks/sproutcore/frameworks/desktop/render_delegates/slider.js +79 -21
  139. data/lib/frameworks/sproutcore/frameworks/desktop/render_delegates/split.js +12 -2
  140. data/lib/frameworks/sproutcore/frameworks/desktop/resources/menu_item_view.css +8 -0
  141. data/lib/frameworks/sproutcore/frameworks/desktop/resources/overlay-scroller.css +187 -0
  142. data/lib/frameworks/sproutcore/frameworks/desktop/system/drag.js +94 -30
  143. data/lib/frameworks/sproutcore/frameworks/desktop/tests/panes/alert/ui.js +163 -3
  144. data/lib/frameworks/sproutcore/frameworks/desktop/tests/panes/menu/methods.js +97 -78
  145. data/lib/frameworks/sproutcore/frameworks/desktop/tests/panes/menu/ui.js +61 -1
  146. data/lib/frameworks/sproutcore/frameworks/desktop/tests/panes/panel/methods.js +7 -3
  147. data/lib/frameworks/sproutcore/frameworks/desktop/tests/panes/panel/ui.js +47 -22
  148. data/lib/frameworks/sproutcore/frameworks/desktop/tests/panes/picker/methods.js +66 -9
  149. data/lib/frameworks/sproutcore/frameworks/desktop/tests/panes/picker/ui.js +21 -11
  150. data/lib/frameworks/sproutcore/frameworks/desktop/tests/panes/sheet/ui.js +12 -18
  151. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/button/methods.js +17 -14
  152. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/button/ui.js +2 -1
  153. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/checkbox/methods.js +9 -6
  154. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/collection/collection_fast_path.js +54 -21
  155. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/collection/content.js +52 -20
  156. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/collection/itemViewForContentIndex.js +94 -4
  157. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/collection/keyboard.js +177 -0
  158. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/collection/layerIdFor.js +13 -1
  159. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/collection/length.js +9 -9
  160. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/collection/mouse.js +18 -0
  161. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/date_field/methods.js +104 -0
  162. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/disclosure/ui.js +48 -49
  163. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/grid/drag_and_drop.js +22 -18
  164. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/grid/methods.js +17 -5
  165. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/link_view_test.js +136 -0
  166. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/list/contentIndexesInRect.js +77 -0
  167. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/list/drag_and_drop.js +53 -16
  168. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/list/layoutForContentIndex.js +41 -0
  169. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/list/rowDelegate.js +25 -25
  170. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/list/rowOffsetForContentIndex.js +102 -27
  171. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/list/{rowHeightForContentIndex.js → rowSizeForContentIndex.js} +7 -6
  172. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/list/ui_outline.js +2 -0
  173. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/list/ui_row_heights.js +70 -75
  174. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/list/ui_simple.js +29 -30
  175. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/list_item.js +57 -0
  176. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/menu_scroll_view/menu_scroll_view_test.js +206 -0
  177. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/progress/ui.js +15 -0
  178. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/radio/methods.js +15 -7
  179. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/scroll/integration.js +16 -11
  180. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/scroll/methods.js +164 -12
  181. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/scroll/scale.js +387 -0
  182. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/scroll/touch.js +549 -0
  183. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/scroll/ui.js +214 -45
  184. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/scroller.js +5 -5
  185. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/segmented/methods.js +73 -22
  186. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/segmented/ui.js +88 -3
  187. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/select/methods.js +8 -0
  188. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/slider/methods.js +16 -1
  189. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/slider/ui.js +54 -0
  190. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/split/dividers.js +21 -2
  191. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/static_content.js +31 -25
  192. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/tab/methods.js +109 -29
  193. data/lib/frameworks/sproutcore/frameworks/desktop/views/button.js +10 -1
  194. data/lib/frameworks/sproutcore/frameworks/desktop/views/checkbox.js +3 -0
  195. data/lib/frameworks/sproutcore/frameworks/desktop/views/collection.js +779 -603
  196. data/lib/frameworks/sproutcore/frameworks/desktop/views/date_field.js +106 -7
  197. data/lib/frameworks/sproutcore/frameworks/desktop/views/link_view.js +406 -0
  198. data/lib/frameworks/sproutcore/frameworks/desktop/views/list.js +437 -245
  199. data/lib/frameworks/sproutcore/frameworks/desktop/views/list_item.js +13 -0
  200. data/lib/frameworks/sproutcore/frameworks/desktop/views/menu_item.js +124 -62
  201. data/lib/frameworks/sproutcore/frameworks/desktop/views/menu_scroll.js +176 -597
  202. data/lib/frameworks/sproutcore/frameworks/desktop/views/menu_scroller_view.js +206 -0
  203. data/lib/frameworks/sproutcore/frameworks/desktop/views/popup_button.js +3 -0
  204. data/lib/frameworks/sproutcore/frameworks/desktop/views/progress.js +5 -4
  205. data/lib/frameworks/sproutcore/frameworks/desktop/views/radio.js +3 -0
  206. data/lib/frameworks/sproutcore/frameworks/desktop/views/scene.js +56 -158
  207. data/lib/frameworks/sproutcore/frameworks/desktop/views/scroll_view.js +2560 -0
  208. data/lib/frameworks/sproutcore/frameworks/desktop/views/scroller.js +458 -242
  209. data/lib/frameworks/sproutcore/frameworks/desktop/views/segmented.js +117 -54
  210. data/lib/frameworks/sproutcore/frameworks/desktop/views/select.js +18 -12
  211. data/lib/frameworks/sproutcore/frameworks/desktop/views/slider.js +162 -34
  212. data/lib/frameworks/sproutcore/frameworks/desktop/views/split.js +30 -15
  213. data/lib/frameworks/sproutcore/frameworks/desktop/views/split_divider.js +33 -7
  214. data/lib/frameworks/sproutcore/frameworks/desktop/views/static_content.js +22 -2
  215. data/lib/frameworks/sproutcore/frameworks/desktop/views/tab.js +47 -22
  216. data/lib/frameworks/sproutcore/frameworks/experimental/Buildfile +0 -6
  217. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/forms/views/form.js +2 -1
  218. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/forms/views/form_row.js +21 -21
  219. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/select_view/ext/menu.js +14 -3
  220. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/select_view/mixins/select_view_menu.js +24 -10
  221. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/select_view/tests/ext/menu_resizing.js +1 -1
  222. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/select_view/tests/mixins/select_view_menu/bindings.js +7 -4
  223. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/select_view/tests/mixins/select_view_menu/check_selected.js +7 -9
  224. data/lib/frameworks/sproutcore/frameworks/{desktop/tests/panes/select_button/methods.js → experimental/frameworks/select_view/tests/views/select/method.js} +54 -76
  225. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/select_view/tests/views/select/selected_item.js +35 -0
  226. data/lib/frameworks/sproutcore/frameworks/{desktop/tests/panes/select_button → experimental/frameworks/select_view/tests/views/select}/ui.js +107 -36
  227. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/select_view/views/select.js +225 -66
  228. data/lib/frameworks/sproutcore/frameworks/foundation/controllers/tree.js +39 -38
  229. data/lib/frameworks/sproutcore/frameworks/foundation/core.js +5 -18
  230. data/lib/frameworks/sproutcore/frameworks/foundation/debug/control_test_pane.js +12 -0
  231. data/lib/frameworks/sproutcore/frameworks/foundation/english.lproj/inflections.js +84 -0
  232. data/lib/frameworks/sproutcore/frameworks/foundation/french.lproj/inflections.js +41 -0
  233. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/auto_mixin.js +1 -0
  234. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/auto_resize.js +7 -0
  235. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/content_display.js +3 -4
  236. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/flowed_layout.js +6 -2
  237. data/lib/frameworks/sproutcore/frameworks/foundation/private/tree_item_observer.js +408 -239
  238. data/lib/frameworks/sproutcore/frameworks/foundation/render_delegates/canvas_image.js +1 -1
  239. data/lib/frameworks/sproutcore/frameworks/foundation/resources/text_field.css +2 -1
  240. data/lib/frameworks/sproutcore/frameworks/foundation/spanish.lproj/inflections.js +38 -0
  241. data/lib/frameworks/sproutcore/frameworks/foundation/system/benchmark.js +104 -76
  242. data/lib/frameworks/sproutcore/frameworks/foundation/system/string.js +20 -94
  243. data/lib/frameworks/sproutcore/frameworks/foundation/system/text_selection.js +33 -22
  244. data/lib/frameworks/sproutcore/frameworks/foundation/system/undo_manager.js +475 -0
  245. data/lib/frameworks/sproutcore/frameworks/foundation/tests/mixins/auto_resize_test.js +163 -1
  246. data/lib/frameworks/sproutcore/frameworks/foundation/tests/mixins/flowed_layout/tests.js +41 -0
  247. data/lib/frameworks/sproutcore/frameworks/foundation/tests/mixins/staticLayout.js +2 -5
  248. data/lib/frameworks/sproutcore/frameworks/foundation/tests/private/tree_item_observer/methods.js +268 -0
  249. data/lib/frameworks/sproutcore/frameworks/foundation/tests/system/undo_manager.js +231 -0
  250. data/lib/frameworks/sproutcore/frameworks/foundation/tests/views/container/ui.js +16 -0
  251. data/lib/frameworks/sproutcore/frameworks/foundation/tests/views/image/ui.js +27 -0
  252. data/lib/frameworks/sproutcore/frameworks/foundation/tests/views/text_field/methods.js +24 -0
  253. data/lib/frameworks/sproutcore/frameworks/foundation/tests/views/text_field/ui.js +135 -6
  254. data/lib/frameworks/sproutcore/frameworks/foundation/transitions/fade_transition.js +6 -0
  255. data/lib/frameworks/sproutcore/frameworks/foundation/transitions/pop_transition.js +7 -0
  256. data/lib/frameworks/sproutcore/frameworks/foundation/transitions/scale_transition.js +6 -0
  257. data/lib/frameworks/sproutcore/frameworks/foundation/transitions/slide_transition.js +4 -0
  258. data/lib/frameworks/sproutcore/frameworks/foundation/transitions/swap_dissolve_transition.js +3 -1
  259. data/lib/frameworks/sproutcore/frameworks/foundation/validators/credit_card.js +21 -21
  260. data/lib/frameworks/sproutcore/frameworks/foundation/views/container.js +65 -15
  261. data/lib/frameworks/sproutcore/frameworks/foundation/views/image.js +4 -1
  262. data/lib/frameworks/sproutcore/frameworks/foundation/views/label.js +1 -1
  263. data/lib/frameworks/sproutcore/frameworks/foundation/views/text_field.js +193 -213
  264. data/lib/frameworks/sproutcore/frameworks/jquery/{jquery-1.8.3-patched.js → jquery-1.11.1.js} +7507 -6684
  265. data/lib/frameworks/sproutcore/frameworks/routing/system/routes.js +28 -11
  266. data/lib/frameworks/sproutcore/frameworks/routing/tests/system/routes.js +26 -0
  267. data/lib/frameworks/sproutcore/frameworks/runtime/core.js +54 -25
  268. data/lib/frameworks/sproutcore/frameworks/runtime/ext/array.js +0 -6
  269. data/lib/frameworks/sproutcore/frameworks/runtime/ext/number.js +36 -0
  270. data/lib/frameworks/sproutcore/frameworks/runtime/ext/window.js +25 -0
  271. data/lib/frameworks/sproutcore/frameworks/runtime/mixins/array.js +3 -3
  272. data/lib/frameworks/sproutcore/frameworks/runtime/mixins/enumerable.js +1 -1
  273. data/lib/frameworks/sproutcore/frameworks/runtime/mixins/observable.js +156 -66
  274. data/lib/frameworks/sproutcore/frameworks/runtime/private/observer_set.js +2 -2
  275. data/lib/frameworks/sproutcore/frameworks/runtime/system/binding.js +150 -65
  276. data/lib/frameworks/sproutcore/frameworks/runtime/system/index_set.js +57 -11
  277. data/lib/frameworks/sproutcore/frameworks/runtime/system/object.js +68 -49
  278. data/lib/frameworks/sproutcore/frameworks/runtime/system/run_loop.js +14 -6
  279. data/lib/frameworks/sproutcore/frameworks/runtime/system/string.js +23 -23
  280. data/lib/frameworks/sproutcore/frameworks/runtime/tests/ext/number_test.js +44 -0
  281. data/lib/frameworks/sproutcore/frameworks/runtime/tests/mixins/array.js +0 -10
  282. data/lib/frameworks/sproutcore/frameworks/runtime/tests/mixins/enumerable/enumerable.js +340 -285
  283. data/lib/frameworks/sproutcore/frameworks/runtime/tests/system/binding.js +104 -3
  284. data/lib/frameworks/sproutcore/frameworks/runtime/tests/system/observer_set.js +14 -1
  285. data/lib/frameworks/sproutcore/frameworks/runtime/tests/system/string.js +15 -2
  286. data/lib/frameworks/sproutcore/frameworks/statechart/system/state.js +21 -18
  287. data/lib/frameworks/sproutcore/frameworks/statechart/system/statechart.js +52 -19
  288. data/lib/frameworks/sproutcore/frameworks/statechart/tests/event_handling/responder/pane.js +27 -24
  289. data/lib/frameworks/sproutcore/frameworks/template_view/controls/button.js +30 -0
  290. data/lib/frameworks/sproutcore/frameworks/template_view/ext/handlebars/bind.js +1 -1
  291. data/lib/frameworks/sproutcore/frameworks/template_view/ext/handlebars/collection.js +2 -0
  292. data/lib/frameworks/sproutcore/frameworks/template_view/ext/handlebars/view.js +1 -0
  293. data/lib/frameworks/sproutcore/frameworks/template_view/tests/mixins/template_helpers/checkbox_support.js +2 -2
  294. data/lib/frameworks/sproutcore/frameworks/template_view/tests/views/template/handlebars.js +4 -2
  295. data/lib/frameworks/sproutcore/frameworks/template_view/views/bindable_span.js +1 -1
  296. data/lib/frameworks/sproutcore/frameworks/template_view/views/template_collection.js +16 -14
  297. data/lib/frameworks/sproutcore/frameworks/testing/core.js +5 -3
  298. data/lib/frameworks/sproutcore/frameworks/testing/system/plan.js +13 -0
  299. data/lib/frameworks/sproutcore/lib/index.rhtml +2 -2
  300. data/lib/frameworks/sproutcore/phantomjs/test_runner.js +28 -7
  301. data/lib/frameworks/sproutcore/scripts/run_sc_server_master.sh +1 -1
  302. data/lib/frameworks/sproutcore/themes/ace/resources/_variables.css +2 -0
  303. data/lib/frameworks/sproutcore/themes/ace/resources/disclosure/ace/disclosure.css +1 -0
  304. data/lib/frameworks/sproutcore/themes/ace/resources/picker/popover/popover.css +3 -4
  305. data/lib/frameworks/sproutcore/themes/ace/resources/scroller/horizontal/horizontal.css +15 -15
  306. data/lib/frameworks/sproutcore/themes/ace/resources/scroller/horizontal/horizontal_overlay.css +74 -0
  307. data/lib/frameworks/sproutcore/themes/ace/resources/scroller/vertical/vertical.css +11 -13
  308. data/lib/frameworks/sproutcore/themes/ace/resources/scroller/vertical/vertical_overlay.css +74 -0
  309. data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/jumbo/knob-active.png +0 -0
  310. data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/jumbo/knob-active@2x.png +0 -0
  311. data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/jumbo/knob.png +0 -0
  312. data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/jumbo/knob@2x.png +0 -0
  313. data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/{22px → jumbo}/slider.css +9 -4
  314. data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/jumbo/track.png +0 -0
  315. data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/jumbo/track@2x.png +0 -0
  316. data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/regular/knob-active.png +0 -0
  317. data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/regular/knob-active@2x.png +0 -0
  318. data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/regular/knob.png +0 -0
  319. data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/regular/knob@2x.png +0 -0
  320. data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/regular/slider.css +32 -0
  321. data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/regular/track.png +0 -0
  322. data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/regular/track@2x.png +0 -0
  323. data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/slider.css +13 -0
  324. data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/small/knob-active.png +0 -0
  325. data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/small/knob-active@2x.png +0 -0
  326. data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/small/knob.png +0 -0
  327. data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/small/knob@2x.png +0 -0
  328. data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/small/slider.css +32 -0
  329. data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/small/track.png +0 -0
  330. data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/small/track@2x.png +0 -0
  331. data/lib/frameworks/sproutcore/themes/ace/resources/split/split.css +2 -3
  332. data/lib/sproutcore/builders/chance_file.rb +3 -3
  333. data/lib/sproutcore/helpers/minifier.rb +1 -0
  334. data/vendor/chance/lib/chance/instance.rb +34 -34
  335. data/vendor/chance/lib/chance/instance/spriting.rb +21 -16
  336. metadata +81 -58
  337. data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/visibility.js +0 -17
  338. data/lib/frameworks/sproutcore/frameworks/desktop/mixins/collection_fast_path.js +0 -710
  339. data/lib/frameworks/sproutcore/frameworks/desktop/mixins/scrollable.js +0 -267
  340. data/lib/frameworks/sproutcore/frameworks/desktop/resources/touch-scroller.css +0 -196
  341. data/lib/frameworks/sproutcore/frameworks/desktop/system/undo_manager.js +0 -224
  342. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/select_field/methods.js +0 -163
  343. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/select_field/ui.js +0 -177
  344. data/lib/frameworks/sproutcore/frameworks/desktop/views/scroll.js +0 -2053
  345. data/lib/frameworks/sproutcore/frameworks/desktop/views/select_button.js +0 -1024
  346. data/lib/frameworks/sproutcore/frameworks/desktop/views/select_field.js +0 -404
  347. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/menu/render_delegates/menu_scroller.js +0 -28
  348. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/menu/tests/menu/scroll.js +0 -235
  349. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/menu/views/menu/scroll.js +0 -363
  350. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/menu/views/menu/scroller.js +0 -250
  351. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/polymorphism/README.md +0 -47
  352. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/polymorphism/models/record.js +0 -134
  353. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/render_delegates/desktop_scroller.js +0 -92
  354. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/render_delegates/native_scroll.js +0 -25
  355. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/render_delegates/scroll.js +0 -33
  356. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/render_delegates/touch_scroller.js +0 -76
  357. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/tests/scroll/integration.js +0 -25
  358. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/tests/scroll/methods.js +0 -143
  359. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/tests/scroll/ui.js +0 -256
  360. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/core_scroll.js +0 -1164
  361. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/core_scroller.js +0 -332
  362. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/desktop/scroll.js +0 -236
  363. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/desktop/scroller.js +0 -347
  364. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/scroll.js +0 -15
  365. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/scroller.js +0 -10
  366. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/touch/scroll.js +0 -804
  367. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/touch/scroller.js +0 -133
  368. data/lib/frameworks/sproutcore/frameworks/foundation/tasks/preload_bundle.js +0 -41
  369. data/lib/frameworks/sproutcore/themes/ace/resources/scroller/horizontal/horizontal_touch.css +0 -91
  370. data/lib/frameworks/sproutcore/themes/ace/resources/scroller/vertical/vertical_touch.css +0 -92
  371. data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/14px/knob.png +0 -0
  372. data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/14px/knob_active.png +0 -0
  373. data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/14px/slider.css +0 -27
  374. data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/16px/knob.png +0 -0
  375. data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/16px/knob_active.png +0 -0
  376. data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/16px/slider.css +0 -27
  377. data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/22px/knob.png +0 -0
  378. data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/22px/knob_active.png +0 -0
  379. data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/22px/track.png +0 -0
  380. data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/track.png +0 -0
@@ -1,2053 +0,0 @@
1
- // ==========================================================================
2
- // Project: SproutCore - JavaScript Application Framework
3
- // Copyright: ©2006-2011 Strobe Inc. and contributors.
4
- // Portions ©2008-2011 Apple Inc. All rights reserved.
5
- // License: Licensed under MIT license (see license.js)
6
- // ==========================================================================
7
-
8
- sc_require('views/scroller');
9
-
10
- /**
11
- @static
12
- @type Number
13
- @default 0.95
14
- */
15
- SC.NORMAL_SCROLL_DECELERATION = 0.95;
16
-
17
- /**
18
- @static
19
- @type Number
20
- @default 0.85
21
- */
22
- SC.FAST_SCROLL_DECELERATION = 0.85;
23
-
24
- /** @class
25
- Implements a complete scroll view. This class uses a manual implementation
26
- of scrollers in order to properly support clipping frames.
27
-
28
- Important Events:
29
-
30
- - contentView frame size changes (to autoshow/hide scrollbar - adjust scrollbar size)
31
- - horizontalScrollOffset change
32
- - verticalScrollOffsetChanges
33
- - scroll wheel events
34
-
35
- @extends SC.View
36
- @since SproutCore 1.0
37
- */
38
- SC.ScrollView = SC.View.extend({
39
- /** @scope SC.ScrollView.prototype */
40
-
41
- /**
42
- @type Array
43
- @default ['sc-scroll-view']
44
- @see SC.View#classNames
45
- */
46
- classNames: ['sc-scroll-view'],
47
-
48
- // ..........................................................
49
- // PROPERTIES
50
- //
51
-
52
- /**
53
- Walk like a duck
54
-
55
- @type Boolean
56
- @default YES
57
- @readOnly
58
- */
59
- isScrollable: YES,
60
-
61
- /**
62
- The content view you want the scroll view to manage. This will be assigned to the contentView of the clipView also.
63
-
64
- @type SC.View
65
- @default null
66
- */
67
- contentView: null,
68
-
69
- /**
70
- The horizontal alignment for non-filling content inside of the ScrollView. Possible values:
71
-
72
- - SC.ALIGN_LEFT
73
- - SC.ALIGN_RIGHT
74
- - SC.ALIGN_CENTER
75
-
76
- @type String
77
- @default SC.ALIGN_LEFT
78
- */
79
- horizontalAlign: SC.ALIGN_LEFT,
80
-
81
- /**
82
- The vertical alignment for non-filling content inside of the ScrollView. Possible values:
83
-
84
- - SC.ALIGN_TOP
85
- - SC.ALIGN_BOTTOM
86
- - SC.ALIGN_MIDDLE
87
-
88
- @type String
89
- @default SC.ALIGN_TOP
90
- */
91
- verticalAlign: SC.ALIGN_TOP,
92
-
93
- /**
94
- The current horizontal scroll offset. Changing this value will update both the contentView and the horizontal scroller, if there is one.
95
-
96
- @field
97
- @type Number
98
- @default 0
99
- */
100
- horizontalScrollOffset: function (key, value) {
101
- if (value !== undefined) {
102
- var minOffset = this.minimumHorizontalScrollOffset(),
103
- maxOffset = this.get('maximumHorizontalScrollOffset');
104
- this._scroll_horizontalScrollOffset = Math.max(minOffset, Math.min(maxOffset, value));
105
- }
106
-
107
- return this._scroll_horizontalScrollOffset || 0;
108
- }.property().cacheable(),
109
-
110
- /**
111
- The current vertical scroll offset. Changing this value will update both the contentView and the vertical scroller, if there is one.
112
-
113
- @field
114
- @type Number
115
- @default 0
116
- */
117
- verticalScrollOffset: function (key, value) {
118
- if (value !== undefined) {
119
- var minOffset = this.get('minimumVerticalScrollOffset'),
120
- maxOffset = this.get('maximumVerticalScrollOffset');
121
- this._scroll_verticalScrollOffset = Math.max(minOffset, Math.min(maxOffset, value));
122
- }
123
-
124
- return this._scroll_verticalScrollOffset || 0;
125
- }.property().cacheable(),
126
-
127
- /** @private
128
- Calculates the maximum offset given content and container sizes, and the
129
- alignment.
130
- */
131
- maximumScrollOffset: function (contentSize, containerSize, align) {
132
- // if our content size is larger than or the same size as the container, it's quite
133
- // simple to calculate the answer. Otherwise, we need to do some fancy-pants
134
- // alignment logic (read: simple math)
135
- if (contentSize >= containerSize) return contentSize - containerSize;
136
-
137
- // alignment, yeah
138
- if (align === SC.ALIGN_LEFT || align === SC.ALIGN_TOP) {
139
- // if we left-align something, and it is smaller than the view, does that not mean
140
- // that it's maximum (and minimum) offset is 0, because it should be positioned at 0?
141
- return 0;
142
- } else if (align === SC.ALIGN_MIDDLE || align === SC.ALIGN_CENTER) {
143
- // middle align means the difference divided by two, because we want equal parts on each side.
144
- return 0 - Math.round((containerSize - contentSize) / 2);
145
- } else {
146
- // right align means the entire difference, because we want all that space on the left
147
- return 0 - (containerSize - contentSize);
148
- }
149
- },
150
-
151
- /** @private
152
- Calculates the minimum offset given content and container sizes, and the
153
- alignment.
154
- */
155
- minimumScrollOffset: function (contentSize, containerSize, align) {
156
- // if the content is larger than the container, we have no need to change the minimum
157
- // away from the natural 0 position.
158
- if (contentSize > containerSize) return 0;
159
-
160
- // alignment, yeah
161
- if (align === SC.ALIGN_LEFT || align === SC.ALIGN_TOP) {
162
- // if we left-align something, and it is smaller than the view, does that not mean
163
- // that it's maximum (and minimum) offset is 0, because it should be positioned at 0?
164
- return 0;
165
- } else if (align === SC.ALIGN_MIDDLE || align === SC.ALIGN_CENTER) {
166
- // middle align means the difference divided by two, because we want equal parts on each side.
167
- return 0 - Math.round((containerSize - contentSize) / 2);
168
- } else {
169
- // right align means the entire difference, because we want all that space on the left
170
- return 0 - (containerSize - contentSize);
171
- }
172
- },
173
-
174
- /**
175
- The maximum horizontal scroll offset allowed given the current contentView
176
- size and the size of the scroll view. If horizontal scrolling is
177
- disabled, this will always return 0.
178
-
179
- @field
180
- @type Number
181
- @default 0
182
- */
183
- maximumHorizontalScrollOffset: function () {
184
- var view = this.get('contentView');
185
- var contentWidth = view ? view.get('frame').width : 0,
186
- calculatedWidth = view ? view.get('calculatedWidth') : 0;
187
-
188
- // The following code checks if there is a calculatedWidth (collections)
189
- // to avoid looking at the incorrect value calculated by frame.
190
- if (calculatedWidth) {
191
- contentWidth = view.calculatedWidth;
192
- }
193
- contentWidth *= this._scale;
194
-
195
- var containerWidth = this.get('containerView').get('frame').width;
196
-
197
- // we still must go through minimumScrollOffset even if we can't scroll
198
- // because we need to adjust for alignment. So, just make sure it won't allow scrolling.
199
- if (!this.get('canScrollHorizontal')) contentWidth = Math.min(contentWidth, containerWidth);
200
- return this.maximumScrollOffset(contentWidth, containerWidth, this.get("horizontalAlign"));
201
- }.property(),
202
-
203
- /**
204
- The maximum vertical scroll offset allowed given the current contentView
205
- size and the size of the scroll view. If vertical scrolling is disabled,
206
- this will always return 0 (or whatever alignment dictates).
207
-
208
- @field
209
- @type Number
210
- @default 0
211
- */
212
- maximumVerticalScrollOffset: function () {
213
- var view = this.get('contentView'),
214
- contentHeight = (view && view.get('frame')) ? view.get('frame').height : 0,
215
- calculatedHeight = view ? view.get('calculatedHeight') : 0;
216
-
217
- // The following code checks if there is a calculatedWidth (collections)
218
- // to avoid looking at the incorrect value calculated by frame.
219
- if (calculatedHeight) {
220
- contentHeight = calculatedHeight;
221
- }
222
- contentHeight *= this._scale;
223
-
224
- var containerHeight = this.get('containerView').get('frame').height;
225
-
226
- // we still must go through minimumScrollOffset even if we can't scroll
227
- // because we need to adjust for alignment. So, just make sure it won't allow scrolling.
228
- if (!this.get('canScrollVertical')) contentHeight = Math.min(contentHeight, containerHeight);
229
- return this.maximumScrollOffset(contentHeight, containerHeight, this.get("verticalAlign"));
230
- }.property(),
231
-
232
-
233
- /**
234
- The minimum horizontal scroll offset allowed given the current contentView
235
- size and the size of the scroll view. If horizontal scrolling is
236
- disabled, this will always return 0 (or whatever alignment dictates).
237
-
238
- @field
239
- @type Number
240
- @default 0
241
- */
242
- minimumHorizontalScrollOffset: function () {
243
- var view = this.get('contentView');
244
- var contentWidth = view ? view.get('frame').width : 0,
245
- calculatedWidth = view ? view.get('calculatedWidth') : 0;
246
- // The following code checks if there is a calculatedWidth (collections)
247
- // to avoid looking at the incorrect value calculated by frame.
248
- if (calculatedWidth) {
249
- contentWidth = calculatedWidth;
250
- }
251
- contentWidth *= this._scale;
252
-
253
- var containerWidth = this.get('containerView').get('frame').width;
254
-
255
- // we still must go through minimumScrollOffset even if we can't scroll
256
- // because we need to adjust for alignment. So, just make sure it won't allow scrolling.
257
- if (!this.get('canScrollHorizontal')) contentWidth = Math.min(contentWidth, containerWidth);
258
- return this.minimumScrollOffset(contentWidth, containerWidth, this.get("horizontalAlign"));
259
- }.property(),
260
-
261
- /**
262
- The minimum vertical scroll offset allowed given the current contentView
263
- size and the size of the scroll view. If vertical scrolling is disabled,
264
- this will always return 0 (or whatever alignment dictates).
265
-
266
- @field
267
- @type Number
268
- @default 0
269
- */
270
- minimumVerticalScrollOffset: function () {
271
- var view = this.get('contentView');
272
- var contentHeight = (view && view.get('frame')) ? view.get('frame').height : 0,
273
- calculatedHeight = view ? view.get('calculatedHeight') : 0;
274
-
275
- // The following code checks if there is a calculatedWidth (collections)
276
- // to avoid looking at the incorrect value calculated by frame.
277
- if (calculatedHeight) {
278
- contentHeight = view.calculatedHeight;
279
- }
280
- contentHeight *= this._scale;
281
-
282
- var containerHeight = this.get('containerView').get('frame').height;
283
-
284
- // we still must go through minimumScrollOffset even if we can't scroll
285
- // because we need to adjust for alignment. So, just make sure it won't allow scrolling.
286
- if (!this.get('canScrollVertical')) contentHeight = Math.min(contentHeight, containerHeight);
287
- return this.minimumScrollOffset(contentHeight, containerHeight, this.get("verticalAlign"));
288
- }.property(),
289
-
290
-
291
- /**
292
- Amount to scroll one vertical line.
293
-
294
- Used by the default implementation of scrollDownLine() and scrollUpLine().
295
-
296
- @type Number
297
- @default 20
298
- */
299
- verticalLineScroll: 20,
300
-
301
- /**
302
- Amount to scroll one horizontal line.
303
-
304
- Used by the default implementation of scrollLeftLine() and
305
- scrollRightLine().
306
-
307
- @type Number
308
- @default 20
309
- */
310
- horizontalLineScroll: 20,
311
-
312
- /**
313
- Amount to scroll one vertical page.
314
-
315
- Used by the default implementation of scrollUpPage() and scrollDownPage().
316
-
317
- @field
318
- @type Number
319
- @default value of frame.height
320
- @observes frame
321
- */
322
- verticalPageScroll: function () {
323
- return this.get('frame').height;
324
- }.property('frame'),
325
-
326
- /**
327
- Amount to scroll one horizontal page.
328
-
329
- Used by the default implementation of scrollLeftPage() and
330
- scrollRightPage().
331
-
332
- @field
333
- @type Number
334
- @default value of frame.width
335
- @observes frame
336
- */
337
- horizontalPageScroll: function () {
338
- return this.get('frame').width;
339
- }.property('frame'),
340
-
341
-
342
- // ..........................................................
343
- // SCROLLERS
344
- //
345
-
346
- /**
347
- YES if the view should maintain a horizontal scroller. This property
348
- must be set when the view is created.
349
-
350
- @type Boolean
351
- @default YES
352
- */
353
- hasHorizontalScroller: YES,
354
-
355
- /**
356
- The horizontal scroller view class. This will be replaced with a view
357
- instance when the ScrollView is created unless hasHorizontalScroller is
358
- NO.
359
-
360
- @type SC.View
361
- @default SC.ScrollerView
362
- */
363
- horizontalScrollerView: SC.ScrollerView,
364
-
365
- /**
366
- The horizontal scroller view for touch. This will be replaced with a view
367
- instance when touch is enabled when the ScrollView is created unless
368
- hasHorizontalScroller is NO.
369
-
370
- @type SC.View
371
- @default SC.TouchScrollerView
372
- */
373
- horizontalTouchScrollerView: SC.TouchScrollerView,
374
-
375
- /**
376
- YES if the horizontal scroller should be visible. You can change this
377
- property value anytime to show or hide the horizontal scroller. If you
378
- do not want to use a horizontal scroller at all, you should instead set
379
- hasHorizontalScroller to NO to avoid creating a scroller view in the
380
- first place.
381
-
382
- @type Boolean
383
- @default YES
384
- */
385
- isHorizontalScrollerVisible: YES,
386
-
387
- /**
388
- Returns YES if the view both has a horizontal scroller, the scroller is
389
- visible.
390
-
391
- @field
392
- @type Boolean
393
- @default YES
394
- */
395
- canScrollHorizontal: function () {
396
- return !!(this.get('hasHorizontalScroller') &&
397
- this.get('horizontalScrollerView') &&
398
- this.get('isHorizontalScrollerVisible'));
399
- }.property('isHorizontalScrollerVisible').cacheable(),
400
-
401
- /**
402
- If YES, the horizontal scroller will autohide if the contentView is
403
- smaller than the visible area. You must set hasHorizontalScroller to YES
404
- for this property to have any effect.
405
-
406
- @type Boolean
407
- @default YES
408
- */
409
- autohidesHorizontalScroller: YES,
410
-
411
- /**
412
- YES if the view should maintain a vertical scroller. This property must
413
- be set when the view is created.
414
-
415
- @type Boolean
416
- @default YES
417
- */
418
- hasVerticalScroller: YES,
419
-
420
- /**
421
- The vertical scroller view class. This will be replaced with a view
422
- instance when the ScrollView is created unless hasVerticalScroller is NO.
423
-
424
- @type SC.View
425
- @default SC.ScrollerView
426
- */
427
- verticalScrollerView: SC.ScrollerView,
428
-
429
- /**
430
- The vertical touch scroller view class. This will be replaced with a view
431
- instance when the ScrollView is created.
432
-
433
- @type SC.View
434
- @default SC.TouchScrollerView
435
- */
436
- verticalTouchScrollerView: SC.TouchScrollerView,
437
-
438
- /**
439
- YES if the vertical scroller should be visible. You can change this
440
- property value anytime to show or hide the vertical scroller. If you do
441
- not want to use a vertical scroller at all, you should instead set
442
- hasVerticalScroller to NO to avoid creating a scroller view in the first
443
- place.
444
-
445
- @type Boolean
446
- @default YES
447
- */
448
- isVerticalScrollerVisible: YES,
449
-
450
- /**
451
- Returns YES if the view both has a horizontal scroller, the scroller is
452
- visible.
453
-
454
- @field
455
- @type Boolean
456
- @default YES
457
- */
458
- canScrollVertical: function () {
459
- return !!(this.get('hasVerticalScroller') &&
460
- this.get('verticalScrollerView') &&
461
- this.get('isVerticalScrollerVisible'));
462
- }.property('isVerticalScrollerVisible').cacheable(),
463
-
464
- /**
465
- If YES, the vertical scroller will autohide if the contentView is
466
- smaller than the visible area. You must set hasVerticalScroller to YES
467
- for this property to have any effect.
468
-
469
- @type Boolean
470
- @default YES
471
- */
472
- autohidesVerticalScroller: YES,
473
-
474
- /**
475
- Use this property to set the 'bottom' offset of your vertical scroller,
476
- to make room for a thumb view or other accessory view. Default is 0.
477
-
478
- @type Number
479
- @default 0
480
- */
481
- verticalScrollerBottom: 0,
482
-
483
- /**
484
- Use this to overlay the vertical scroller.
485
-
486
- This ensures that the container frame will not resize to accommodate the
487
- vertical scroller, hence overlaying the scroller on top of
488
- the container.
489
-
490
- @field
491
- @type Boolean
492
- @default NO
493
- */
494
- verticalOverlay: function () {
495
- if (SC.platform.touch) return YES;
496
- return NO;
497
- }.property().cacheable(),
498
-
499
- /**
500
- Use this to overlay the horizontal scroller.
501
-
502
- This ensures that the container frame will not resize to accommodate the
503
- horizontal scroller, hence overlaying the scroller on top of
504
- the container
505
-
506
- @field
507
- @type Boolean
508
- @default NO
509
- */
510
- horizontalOverlay: function () {
511
- if (SC.platform.touch) return YES;
512
- return NO;
513
- }.property().cacheable(),
514
-
515
- /**
516
- Use to control the positioning of the vertical scroller. If you do not
517
- set 'verticalOverlay' to YES, then the content view will be automatically
518
- sized to meet the left edge of the vertical scroller, wherever it may be.
519
- This allows you to easily, for example, have “one pixel higher and one
520
- pixel lower” scroll bars that blend into their parent views.
521
-
522
- If you do set 'verticalOverlay' to YES, then the scroller view will
523
- “float on top” of the content view.
524
-
525
- Example: { top: -1, bottom: -1, right: 0 }
526
-
527
- @type Hash
528
- @default null
529
- */
530
- verticalScrollerLayout: null,
531
-
532
- /**
533
- Use to control the positioning of the horizontal scroller. If you do not
534
- set 'horizontalOverlay' to YES, then the content view will be
535
- automatically sized to meet the top edge of the horizontal scroller,
536
- wherever it may be.
537
-
538
- If you do set 'horizontalOverlay' to YES, then the scroller view will
539
- “float on top” of the content view.
540
-
541
- Example: { left: 0, bottom: 0, right: 0 }
542
-
543
- @type Hash
544
- @default null
545
- */
546
- horizontalScrollerLayout: null,
547
-
548
- // ..........................................................
549
- // CUSTOM VIEWS
550
- //
551
-
552
- /**
553
- The container view that will contain your main content view. You can
554
- replace this property with your own custom subclass if you prefer.
555
-
556
- @type SC.ContainerView
557
- @default SC.ConainerView
558
- */
559
- containerView: SC.ContainerView.extend({}),
560
-
561
-
562
- // ..........................................................
563
- // METHODS
564
- //
565
-
566
- /**
567
- Scrolls the receiver to the specified x,y coordinate. This should be the
568
- offset into the contentView you want to appear at the top-left corner of
569
- the scroll view.
570
-
571
- This method will contain the actual scroll based on whether the view
572
- can scroll in the named direction and the maximum distance it can
573
- scroll.
574
-
575
- If you only want to scroll in one direction, pass null for the other
576
- direction. You can also optionally pass a Hash for the first parameter
577
- with x and y coordinates.
578
-
579
- @param {Number} x the x scroll location
580
- @param {Number} y the y scroll location
581
- @returns {SC.ScrollView} receiver
582
- */
583
- scrollTo: function (x, y) {
584
- // normalize params
585
- if (y === undefined && SC.typeOf(x) === SC.T_HASH) {
586
- y = x.y;
587
- x = x.x;
588
- }
589
-
590
- if (!SC.none(x)) {
591
- this.set('horizontalScrollOffset', x);
592
- }
593
-
594
- if (!SC.none(y)) {
595
- this.set('verticalScrollOffset', y);
596
- }
597
-
598
- return this;
599
- },
600
-
601
- /**
602
- Scrolls the receiver in the horizontal and vertical directions by the
603
- amount specified, if allowed. The actual scroll amount will be
604
- constrained by the current scroll view settings.
605
-
606
- If you only want to scroll in one direction, pass null or 0 for the other
607
- direction. You can also optionally pass a Hash for the first parameter
608
- with x and y coordinates.
609
-
610
- @param {Number} x change in the x direction (or hash)
611
- @param {Number} y change in the y direction
612
- @returns {SC.ScrollView} receiver
613
- */
614
- scrollBy: function (x, y) {
615
- // normalize params
616
- if (y === undefined && SC.typeOf(x) === SC.T_HASH) {
617
- y = x.y;
618
- x = x.x;
619
- }
620
-
621
- // if null, undefined, or 0, pass null; otherwise just add current offset
622
- x = (x) ? this.get('horizontalScrollOffset') + x : null;
623
- y = (y) ? this.get('verticalScrollOffset') + y : null;
624
- return this.scrollTo(x, y);
625
- },
626
-
627
- /**
628
- Scroll the view to make the view's frame visible. For this to make sense,
629
- the view should be a subview of the contentView. Otherwise the results
630
- will be undefined.
631
-
632
- @param {SC.View} view view to scroll or null to scroll receiver visible
633
- @returns {Boolean} YES if scroll position was changed
634
- */
635
- scrollToVisible: function (view) {
636
-
637
- // if no view is passed, do default
638
- if (arguments.length === 0) return sc_super();
639
-
640
- var contentView = this.get('contentView');
641
- if (!contentView) return NO; // nothing to do if no contentView.
642
-
643
- // get the frame for the view - should work even for views with static
644
- // layout, assuming it has been added to the screen.
645
- var vf = view.get('frame');
646
- if (!vf) return NO; // nothing to do
647
-
648
- // convert view's frame to an offset from the contentView origin. This
649
- // will become the new scroll offset after some adjustment.
650
- vf = contentView.convertFrameFromView(vf, view.get('parentView'));
651
-
652
- return this.scrollToRect(vf);
653
- },
654
-
655
- /**
656
- Scroll to the supplied rectangle.
657
- @param {Rect} rect Rectangle to scroll to.
658
- @returns {Boolean} YES if scroll position was changed.
659
- */
660
- scrollToRect: function (rect) {
661
- // find current visible frame.
662
- var vo = SC.cloneRect(this.get('containerView').get('frame'));
663
-
664
- vo.x = this.get('horizontalScrollOffset');
665
- vo.y = this.get('verticalScrollOffset');
666
-
667
- var origX = vo.x, origY = vo.y;
668
-
669
- // if top edge is not visible, shift origin
670
- vo.y -= Math.max(0, SC.minY(vo) - SC.minY(rect));
671
- vo.x -= Math.max(0, SC.minX(vo) - SC.minX(rect));
672
-
673
- // if bottom edge is not visible, shift origin
674
- vo.y += Math.max(0, SC.maxY(rect) - SC.maxY(vo));
675
- vo.x += Math.max(0, SC.maxX(rect) - SC.maxX(vo));
676
-
677
- // scroll to that origin.
678
- if ((origX !== vo.x) || (origY !== vo.y)) {
679
- this.scrollTo(vo.x, vo.y);
680
- return YES;
681
- } else return NO;
682
- },
683
-
684
-
685
- /**
686
- Scrolls the receiver down one or more lines if allowed. If number of
687
- lines is not specified, scrolls one line.
688
-
689
- @param {Number} lines number of lines
690
- @returns {SC.ScrollView} receiver
691
- */
692
- scrollDownLine: function (lines) {
693
- if (lines === undefined) lines = 1;
694
- return this.scrollBy(null, this.get('verticalLineScroll') * lines);
695
- },
696
-
697
- /**
698
- Scrolls the receiver up one or more lines if allowed. If number of
699
- lines is not specified, scrolls one line.
700
-
701
- @param {Number} lines number of lines
702
- @returns {SC.ScrollView} receiver
703
- */
704
- scrollUpLine: function (lines) {
705
- if (lines === undefined) lines = 1;
706
- return this.scrollBy(null, 0 - this.get('verticalLineScroll') * lines);
707
- },
708
-
709
- /**
710
- Scrolls the receiver right one or more lines if allowed. If number of
711
- lines is not specified, scrolls one line.
712
-
713
- @param {Number} lines number of lines
714
- @returns {SC.ScrollView} receiver
715
- */
716
- scrollRightLine: function (lines) {
717
- if (lines === undefined) lines = 1;
718
- return this.scrollTo(this.get('horizontalLineScroll') * lines, null);
719
- },
720
-
721
- /**
722
- Scrolls the receiver left one or more lines if allowed. If number of
723
- lines is not specified, scrolls one line.
724
-
725
- @param {Number} lines number of lines
726
- @returns {SC.ScrollView} receiver
727
- */
728
- scrollLeftLine: function (lines) {
729
- if (lines === undefined) lines = 1;
730
- return this.scrollTo(0 - this.get('horizontalLineScroll') * lines, null);
731
- },
732
-
733
- /**
734
- Scrolls the receiver down one or more page if allowed. If number of
735
- pages is not specified, scrolls one page. The page size is determined by
736
- the verticalPageScroll value. By default this is the size of the current
737
- scrollable area.
738
-
739
- @param {Number} pages number of lines
740
- @returns {SC.ScrollView} receiver
741
- */
742
- scrollDownPage: function (pages) {
743
- if (pages === undefined) pages = 1;
744
- return this.scrollBy(null, this.get('verticalPageScroll') * pages);
745
- },
746
-
747
- /**
748
- Scrolls the receiver up one or more page if allowed. If number of
749
- pages is not specified, scrolls one page. The page size is determined by
750
- the verticalPageScroll value. By default this is the size of the current
751
- scrollable area.
752
-
753
- @param {Number} pages number of lines
754
- @returns {SC.ScrollView} receiver
755
- */
756
- scrollUpPage: function (pages) {
757
- if (pages === undefined) pages = 1;
758
- return this.scrollBy(null, 0 - (this.get('verticalPageScroll') * pages));
759
- },
760
-
761
- /**
762
- Scrolls the receiver right one or more page if allowed. If number of
763
- pages is not specified, scrolls one page. The page size is determined by
764
- the verticalPageScroll value. By default this is the size of the current
765
- scrollable area.
766
-
767
- @param {Number} pages number of lines
768
- @returns {SC.ScrollView} receiver
769
- */
770
- scrollRightPage: function (pages) {
771
- if (pages === undefined) pages = 1;
772
- return this.scrollBy(this.get('horizontalPageScroll') * pages, null);
773
- },
774
-
775
- /**
776
- Scrolls the receiver left one or more page if allowed. If number of
777
- pages is not specified, scrolls one page. The page size is determined by
778
- the verticalPageScroll value. By default this is the size of the current
779
- scrollable area.
780
-
781
- @param {Number} pages number of lines
782
- @returns {SC.ScrollView} receiver
783
- */
784
- scrollLeftPage: function (pages) {
785
- if (pages === undefined) pages = 1;
786
- return this.scrollBy(0 - (this.get('horizontalPageScroll') * pages), null);
787
- },
788
-
789
- /** @private
790
- Adjusts the layout for the various internal views. This method is called
791
- once when the scroll view is first configured and then anytime a scroller
792
- is shown or hidden. You can call this method yourself as well to retile.
793
-
794
- You may also want to override this method to handle layout for any
795
- additional controls you have added to the view.
796
- */
797
- tile: function () {
798
- // get horizontal scroller/determine if we should have a scroller
799
- var hscroll = this.get('hasHorizontalScroller') ? this.get('horizontalScrollerView') : null;
800
- var hasHorizontal = hscroll && this.get('isHorizontalScrollerVisible');
801
-
802
- // get vertical scroller/determine if we should have a scroller
803
- var vscroll = this.get('hasVerticalScroller') ? this.get('verticalScrollerView') : null;
804
- var hasVertical = vscroll && this.get('isVerticalScrollerVisible');
805
-
806
- // get the containerView
807
- var clip = this.get('containerView');
808
- var clipLayout = { left: 0, top: 0 };
809
- var layout, vo, ho, vl, hl;
810
-
811
- var ht = ((hasHorizontal) ? hscroll.get('scrollbarThickness') : 0);
812
- var vt = (hasVertical) ? vscroll.get('scrollbarThickness') : 0;
813
-
814
- if (hasHorizontal) {
815
- hl = this.get('horizontalScrollerLayout');
816
- layout = {
817
- left: (hl ? hl.left : 0),
818
- bottom: (hl ? hl.bottom : 0),
819
- right: (hl ? hl.right + vt - 1 : vt - 1),
820
- height: ht
821
- };
822
- hscroll.set('layout', layout);
823
- ho = this.get('horizontalOverlay');
824
- clipLayout.bottom = ho ? 0 : (layout.bottom + ht);
825
- } else {
826
- clipLayout.bottom = 0;
827
- }
828
- if (hscroll) hscroll.set('isVisible', hasHorizontal);
829
-
830
- if (hasVertical) {
831
- ht = ht + this.get('verticalScrollerBottom');
832
- vl = this.get('verticalScrollerLayout');
833
- layout = {
834
- top: (vl ? vl.top : 0),
835
- bottom: (vl ? vl.bottom + ht : ht),
836
- right: (vl ? vl.right : 0),
837
- width: vt
838
- };
839
- vscroll.set('layout', layout);
840
- vo = this.get('verticalOverlay');
841
- clipLayout.right = vo ? 0 : (layout.right + vt);
842
- } else {
843
- clipLayout.right = 0;
844
- }
845
- if (vscroll) vscroll.set('isVisible', hasVertical);
846
-
847
- clip.adjust(clipLayout);
848
- },
849
-
850
- /** @private
851
- Called whenever a scroller visibility changes. Calls the tile() method.
852
- */
853
- scrollerVisibilityDidChange: function () {
854
- this.tile();
855
- }.observes('isVerticalScrollerVisible', 'isHorizontalScrollerVisible'),
856
-
857
- // ..........................................................
858
- // SCROLL WHEEL SUPPORT
859
- //
860
-
861
- /** @private */
862
- _scroll_wheelDeltaX: 0,
863
-
864
- /** @private */
865
- _scroll_wheelDeltaY: 0,
866
-
867
- /** @private */
868
- mouseWheel: function (evt) {
869
- if (!this.get('isEnabledInPane')) return NO;
870
-
871
- var horizontalScrollOffset = this.get('horizontalScrollOffset'),
872
- maximumHorizontalScrollOffset = this.get('maximumHorizontalScrollOffset'),
873
- maximumVerticalScrollOffset = this.get('maximumVerticalScrollOffset'),
874
- shouldScroll = NO,
875
- verticalScrollOffset = this.get('verticalScrollOffset');
876
-
877
- // Only attempt to scroll if we are allowed to scroll in the direction and
878
- // have room to scroll in the direction. Otherwise, ignore the event so
879
- // that an outer ScrollView may capture it.
880
- shouldScroll = ((this.get('canScrollHorizontal') &&
881
- (evt.wheelDeltaX < 0 && horizontalScrollOffset > 0) ||
882
- (evt.wheelDeltaX > 0 && horizontalScrollOffset < maximumHorizontalScrollOffset)) ||
883
- (this.get('canScrollVertical') &&
884
- (evt.wheelDeltaY < 0 && verticalScrollOffset > 0) ||
885
- (evt.wheelDeltaY > 0 && verticalScrollOffset < maximumVerticalScrollOffset)));
886
-
887
- if (shouldScroll) {
888
- this._scroll_wheelDeltaX += evt.wheelDeltaX;
889
- this._scroll_wheelDeltaY += evt.wheelDeltaY;
890
-
891
- this.invokeLater(this._scroll_mouseWheel, 10);
892
- }
893
-
894
- return shouldScroll;
895
- },
896
-
897
- /** @private */
898
- _scroll_mouseWheel: function () {
899
- this.scrollBy(this._scroll_wheelDeltaX, this._scroll_wheelDeltaY);
900
- if (SC.WHEEL_MOMENTUM && this._scroll_wheelDeltaY > 0) {
901
- this._scroll_wheelDeltaY = Math.floor(this._scroll_wheelDeltaY * 0.950);
902
- this._scroll_wheelDeltaY = Math.max(this._scroll_wheelDeltaY, 0);
903
- this.invokeLater(this._scroll_mouseWheel, 10);
904
- } else if (SC.WHEEL_MOMENTUM && this._scroll_wheelDeltaY < 0) {
905
- this._scroll_wheelDeltaY = Math.ceil(this._scroll_wheelDeltaY * 0.950);
906
- this._scroll_wheelDeltaY = Math.min(this._scroll_wheelDeltaY, 0);
907
- this.invokeLater(this._scroll_mouseWheel, 10);
908
- } else {
909
- this._scroll_wheelDeltaY = 0;
910
- this._scroll_wheelDeltaX = 0;
911
- }
912
- },
913
-
914
- /*..............................................
915
- SCALING SUPPORT
916
- */
917
-
918
- /**
919
- Determines whether scaling is allowed.
920
-
921
- @type Boolean
922
- @default NO
923
- */
924
- canScale: NO,
925
-
926
- /** @private
927
- The current scale.
928
- */
929
- _scale: 1.0,
930
-
931
- /**
932
- @field
933
- @type Number
934
- @default 1.0
935
- */
936
- scale: function (key, value) {
937
- if (value !== undefined) {
938
- this._scale = Math.min(Math.max(this.get("minimumScale"), value), this.get("maximumScale"));
939
- }
940
- return this._scale;
941
- }.property().cacheable(),
942
-
943
- /**
944
- The minimum scale.
945
-
946
- @type Number
947
- @default 0.25
948
- */
949
- minimumScale: 0.25,
950
-
951
- /**
952
- The maximum scale.
953
-
954
- @type Number
955
- @default 2.0
956
- */
957
- maximumScale: 2.0,
958
-
959
- /**
960
- Whether to automatically determine the scale range based on the size of the content.
961
-
962
- @type Boolean
963
- @default NO
964
- */
965
- autoScaleRange: NO,
966
-
967
- /** @private */
968
- _scale_css: "",
969
-
970
- /** @private */
971
- updateScale: function (scale) {
972
- var contentView = this.get("contentView");
973
- if (!contentView) return;
974
-
975
- if (contentView.isScalable) {
976
- this.get("contentView").applyScale(scale);
977
- this._scale_css = "";
978
- } else {
979
- this._scale_css = "scale3d(" + scale + ", " + scale + ", 1)";
980
- }
981
- },
982
-
983
-
984
- // ..........................................................
985
- // Touch Support
986
- //
987
-
988
- /**
989
- @type Boolean
990
- @default YES
991
- @readOnly
992
- */
993
- acceptsMultitouch: YES,
994
-
995
- /**
996
- The scroll deceleration rate.
997
-
998
- @type Number
999
- @default SC.NORMAL_SCROLL_DECELERATION
1000
- */
1001
- decelerationRate: SC.NORMAL_SCROLL_DECELERATION,
1002
-
1003
- /**
1004
- If YES, bouncing will always be enabled in the horizontal direction, even if the content
1005
- is smaller or the same size as the view.
1006
-
1007
- @type Boolean
1008
- @default NO
1009
- */
1010
- alwaysBounceHorizontal: NO,
1011
-
1012
- /**
1013
- If NO, bouncing will not be enabled in the vertical direction when the content is smaller
1014
- or the same size as the scroll view.
1015
-
1016
- @type Boolean
1017
- @default YES
1018
- */
1019
- alwaysBounceVertical: YES,
1020
-
1021
- /**
1022
- Whether to delay touches from passing through to the content.
1023
-
1024
- @type Boolean
1025
- @default YES
1026
- */
1027
- delaysContentTouches: YES,
1028
-
1029
- /** @private
1030
- If the view supports it, this
1031
- */
1032
- _touchScrollDidChange: function () {
1033
- if (this.get("contentView").touchScrollDidChange) {
1034
- this.get("contentView").touchScrollDidChange(
1035
- this._scroll_horizontalScrollOffset,
1036
- this._scroll_verticalScrollOffset
1037
- );
1038
- }
1039
-
1040
- // tell scrollers
1041
- if (this.verticalScrollerView && this.verticalScrollerView.touchScrollDidChange) {
1042
- this.verticalScrollerView.touchScrollDidChange(this._scroll_verticalScrollOffset);
1043
- }
1044
-
1045
- if (this.horizontalScrollerView && this.horizontalScrollerView.touchScrollDidChange) {
1046
- this.horizontalScrollerView.touchScrollDidChange(this._scroll_horizontalScrollOffset);
1047
- }
1048
- },
1049
-
1050
- /** @private */
1051
- _touchScrollDidStart: function () {
1052
- if (this.get("contentView").touchScrollDidStart) {
1053
- this.get("contentView").touchScrollDidStart(this._scroll_horizontalScrollOffset, this._scroll_verticalScrollOffset);
1054
- }
1055
-
1056
- // tell scrollers
1057
- if (this.verticalScrollerView && this.verticalScrollerView.touchScrollDidStart) {
1058
- this.verticalScrollerView.touchScrollDidStart(this._touch_verticalScrollOffset);
1059
- }
1060
- if (this.horizontalScrollerView && this.horizontalScrollerView.touchScrollDidStart) {
1061
- this.horizontalScrollerView.touchScrollDidStart(this._touch_horizontalScrollOffset);
1062
- }
1063
- },
1064
-
1065
- /** @private */
1066
- _touchScrollDidEnd: function () {
1067
- if (this.get("contentView").touchScrollDidEnd) {
1068
- this.get("contentView").touchScrollDidEnd(this._scroll_horizontalScrollOffset, this._scroll_verticalScrollOffset);
1069
- }
1070
-
1071
- // tell scrollers
1072
- if (this.verticalScrollerView && this.verticalScrollerView.touchScrollDidEnd) {
1073
- this.verticalScrollerView.touchScrollDidEnd(this._touch_verticalScrollOffset);
1074
- }
1075
-
1076
- if (this.horizontalScrollerView && this.horizontalScrollerView.touchScrollDidEnd) {
1077
- this.horizontalScrollerView.touchScrollDidEnd(this._touch_horizontalScrollOffset);
1078
- }
1079
- },
1080
-
1081
- /** @private */
1082
- _applyCSSTransforms: function (layer) {
1083
- var transform = "";
1084
- this.updateScale(this._scale);
1085
- transform += 'translate3d(' +
1086
- -this._scroll_horizontalScrollOffset +
1087
- 'px, ' +
1088
- -Math.round(this._scroll_verticalScrollOffset) +
1089
- 'px,0) ';
1090
- transform += this._scale_css;
1091
- if (layer) {
1092
- var style = layer.style;
1093
- style.webkitTransform = transform;
1094
- style.webkitTransformOrigin = "top left";
1095
- }
1096
- },
1097
-
1098
- /** @private */
1099
- captureTouch: function () {
1100
- return YES;
1101
- },
1102
-
1103
- /** @private */
1104
- touchGeneration: 0,
1105
-
1106
- /** @private */
1107
- touchStart: function (touch) {
1108
- var generation = ++this.touchGeneration;
1109
- if (!this.tracking && this.get("delaysContentTouches")) {
1110
- this.invokeLater(this.beginTouchesInContent, 150, generation);
1111
- } else if (!this.tracking) {
1112
- // NOTE: We still have to delay because we don't want to call touchStart
1113
- // while touchStart is itself being called...
1114
- this.invokeLater(this.beginTouchesInContent, 1, generation);
1115
- }
1116
- this.beginTouchTracking(touch, YES);
1117
- return YES;
1118
- },
1119
-
1120
- /** @private */
1121
- beginTouchesInContent: function (gen) {
1122
- if (gen !== this.touchGeneration) return;
1123
-
1124
- var touch = this.touch;
1125
-
1126
- // NOTE! On iPad it is possible that the timer set in touchStart() will not have yet fired and that touchEnd() will
1127
- // come in in the same Run Loop as the one that started with the call to touchStart(). The bad thing that happens is that
1128
- // even though we cleared this.touch, occasionally if touchEnd() comes in right at the end of the Run Loop and
1129
- // then the timer expires and starts a new Run Loop to call beginTouchesInContent(), that this.touch will STILL exist
1130
- // here. There's no explanation for it, and it's not 100% reproducible, but what happens is that if we try to capture
1131
- // the touch that has already ended, assignTouch() in RootResponder will check touch.hasEnded and throw an exception.
1132
-
1133
- // Therefore, don't capture a touch if the touch still exists and hasEnded
1134
- if (touch && this.tracking && !this.dragging && !touch.touch.scrollHasEnded && !touch.touch.hasEnded) {
1135
- // try to capture the touch
1136
- touch.touch.captureTouch(this, YES);
1137
-
1138
- if (!touch.touch.touchResponder) {
1139
- // if it DIDN'T WORK!!!!!
1140
- // then we need to take possession again.
1141
- touch.touch.makeTouchResponder(this);
1142
- } else {
1143
- // Otherwise, it did work, and if we had a pending scroll end, we must do it now
1144
- if (touch.needsScrollEnd) {
1145
- this._touchScrollDidEnd();
1146
- }
1147
- }
1148
- }
1149
- },
1150
-
1151
- /** @private
1152
- Initializes the start state of the gesture.
1153
-
1154
- We keep information about the initial location of the touch so we can
1155
- disambiguate between a tap and a drag.
1156
-
1157
- @param {Event} evt
1158
- */
1159
- beginTouchTracking: function (touch, starting) {
1160
- var avg = touch.averagedTouchesForView(this, starting);
1161
-
1162
- var verticalScrollOffset = this._scroll_verticalScrollOffset || 0,
1163
- horizontalScrollOffset = this._scroll_horizontalScrollOffset || 0,
1164
- startClipOffsetX = horizontalScrollOffset,
1165
- startClipOffsetY = verticalScrollOffset,
1166
- needsScrollEnd = NO,
1167
- contentWidth = 0,
1168
- contentHeight = 0,
1169
- existingTouch = this.touch,
1170
- viewFrame,
1171
- view;
1172
-
1173
- if (existingTouch && !SC.none(existingTouch.animationID)) {
1174
- // If a deceleration calculation is queued to run, we need to cancel it so
1175
- // it doesn't run after we begin touch tracking again.
1176
- window.cancelAnimationFrame(existingTouch.animationID);
1177
-
1178
- // get the scroll offsets
1179
- startClipOffsetX = this.touch.startClipOffset.x;
1180
- startClipOffsetY = this.touch.startClipOffset.y;
1181
- needsScrollEnd = YES;
1182
- }
1183
-
1184
- // calculate container+content width/height
1185
- view = this.get('contentView');
1186
-
1187
- if (view) {
1188
- viewFrame = view.get('frame');
1189
- contentWidth = viewFrame.width;
1190
- contentHeight = viewFrame.height;
1191
- }
1192
-
1193
- if (view.calculatedWidth && view.calculatedWidth !== 0) contentWidth = view.calculatedWidth;
1194
- if (view.calculatedHeight && view.calculatedHeight !== 0) contentHeight = view.calculatedHeight;
1195
-
1196
- var containerFrame = this.get('containerView').get('frame'),
1197
- containerWidth = containerFrame.width,
1198
- containerHeight = containerFrame.height;
1199
-
1200
-
1201
- // calculate position in content
1202
- var globalFrame = this.convertFrameToView(this.get("frame"), null),
1203
- positionInContentX = (horizontalScrollOffset + (avg.x - globalFrame.x)) / this._scale,
1204
- positionInContentY = (verticalScrollOffset + (avg.y - globalFrame.y)) / this._scale;
1205
-
1206
- this.touch = {
1207
- startTime: touch.timeStamp,
1208
- notCalculated: YES,
1209
-
1210
- enableScrolling: {
1211
- x: contentWidth * this._scale > containerWidth || this.get("alwaysBounceHorizontal"),
1212
- y: contentHeight * this._scale > containerHeight || this.get("alwaysBounceVertical")
1213
- },
1214
- scrolling: { x: NO, y: NO },
1215
-
1216
- enableBouncing: SC.platform.bounceOnScroll,
1217
-
1218
- // offsets and velocities
1219
- startClipOffset: { x: startClipOffsetX, y: startClipOffsetY },
1220
- lastScrollOffset: { x: horizontalScrollOffset, y: verticalScrollOffset },
1221
- startTouchOffset: { x: avg.x, y: avg.y },
1222
- scrollVelocity: { x: 0, y: 0 },
1223
-
1224
- startTouchOffsetInContent: { x: positionInContentX, y: positionInContentY },
1225
-
1226
- containerSize: { width: containerWidth, height: containerHeight },
1227
- contentSize: { width: contentWidth, height: contentHeight },
1228
-
1229
- startScale: this._scale,
1230
- startDistance: avg.d,
1231
- canScale: this.get("canScale") && SC.platform.pinchToZoom,
1232
- minimumScale: this.get("minimumScale"),
1233
- maximumScale: this.get("maximumScale"),
1234
-
1235
- globalFrame: globalFrame,
1236
-
1237
- // cache some things
1238
- layer: view.get('layer'), //contentView
1239
-
1240
- // some constants
1241
- resistanceCoefficient: 0.998,
1242
- resistanceAsymptote: 320,
1243
- decelerationFromEdge: 0.05,
1244
- accelerationToEdge: 0.1,
1245
-
1246
- // how much percent of the other drag direction you must drag to start dragging that direction too.
1247
- scrollTolerance: { x: 15, y: 15 },
1248
- scaleTolerance: 5,
1249
- secondaryScrollTolerance: 30,
1250
- scrollLock: 500,
1251
-
1252
- decelerationRate: this.get("decelerationRate"),
1253
-
1254
- // general status
1255
- lastEventTime: touch.timeStamp,
1256
-
1257
- // the touch used
1258
- touch: (starting ? touch : (this.touch ? this.touch.touch : null)),
1259
-
1260
- // needsScrollEnd will cause a scrollDidEnd even if this particular touch does not start a scroll.
1261
- // the reason for this is because we don't want to say we've stopped scrolling just because we got
1262
- // another touch, but simultaneously, we still need to send a touch end eventually.
1263
- // there are two cases in which this will be used:
1264
- //
1265
- // 1. If the touch was sent to content touches (in which case we will not be scrolling)
1266
- // 2. If the touch ends before scrolling starts (no scrolling then, either)
1267
- needsScrollEnd: needsScrollEnd
1268
- };
1269
-
1270
- if (!this.tracking) {
1271
- this.tracking = YES;
1272
- this.dragging = NO;
1273
- }
1274
- },
1275
-
1276
- /** @private */
1277
- _adjustForEdgeResistance: function (offset, minOffset, maxOffset, resistanceCoefficient, asymptote) {
1278
- var distanceFromEdge;
1279
-
1280
- // find distance from edge
1281
- if (offset < minOffset) distanceFromEdge = offset - minOffset;
1282
- else if (offset > maxOffset) distanceFromEdge = maxOffset - offset;
1283
- else return offset;
1284
-
1285
- // manipulate logarithmically
1286
- distanceFromEdge = Math.pow(resistanceCoefficient, Math.abs(distanceFromEdge)) * asymptote;
1287
-
1288
- // adjust mathematically
1289
- if (offset < minOffset) distanceFromEdge = distanceFromEdge - asymptote;
1290
- else distanceFromEdge = -distanceFromEdge + asymptote;
1291
-
1292
- // generate final value
1293
- return Math.min(Math.max(minOffset, offset), maxOffset) + distanceFromEdge;
1294
- },
1295
-
1296
- /** @private */
1297
- touchesDragged: function (evt) {
1298
- var avg = evt.averagedTouchesForView(this);
1299
-
1300
- this.updateTouchScroll(avg.x, avg.y, avg.d, evt.timeStamp);
1301
- },
1302
-
1303
- /** @private */
1304
- updateTouchScroll: function (touchX, touchY, distance, timeStamp) {
1305
- // get some vars
1306
- var touch = this.touch,
1307
- touchXInFrame = touchX - touch.globalFrame.x,
1308
- touchYInFrame = touchY - touch.globalFrame.y,
1309
- offsetY,
1310
- maxOffsetY,
1311
- offsetX,
1312
- maxOffsetX,
1313
- minOffsetX, minOffsetY,
1314
- touchScroll = touch.scrolling,
1315
- hAlign = this.get("horizontalAlign"),
1316
- vAlign = this.get("verticalAlign");
1317
-
1318
- // calculate new position in content
1319
- var positionInContentX = ((this._scroll_horizontalScrollOffset || 0) + touchXInFrame) / this._scale,
1320
- positionInContentY = ((this._scroll_verticalScrollOffset || 0) + touchYInFrame) / this._scale;
1321
-
1322
- // calculate deltas
1323
- var deltaX = positionInContentX - touch.startTouchOffsetInContent.x,
1324
- deltaY = positionInContentY - touch.startTouchOffsetInContent.y;
1325
-
1326
- var isDragging = touch.dragging;
1327
- if (!touchScroll.x && Math.abs(deltaX) > touch.scrollTolerance.x && touch.enableScrolling.x) {
1328
- // say we are scrolling
1329
- isDragging = YES;
1330
- touchScroll.x = YES;
1331
- touch.scrollTolerance.y = touch.secondaryScrollTolerance;
1332
-
1333
- // reset position
1334
- touch.startTouchOffset.x = touchX;
1335
- deltaX = 0;
1336
- }
1337
- if (!touchScroll.y && Math.abs(deltaY) > touch.scrollTolerance.y && touch.enableScrolling.y) {
1338
- // say we are scrolling
1339
- isDragging = YES;
1340
- touchScroll.y = YES;
1341
- touch.scrollTolerance.x = touch.secondaryScrollTolerance;
1342
-
1343
- // reset position
1344
- touch.startTouchOffset.y = touchY;
1345
- deltaY = 0;
1346
- }
1347
-
1348
- // handle scroll start
1349
- if (isDragging && !touch.dragging) {
1350
- touch.dragging = YES;
1351
- this.dragging = YES;
1352
- this._touchScrollDidStart();
1353
- }
1354
-
1355
- // calculate new offset
1356
- if (!touchScroll.x && !touchScroll.y && !touch.canScale) return;
1357
- if (touchScroll.x && !touchScroll.y) {
1358
- if (deltaX > touch.scrollLock && !touchScroll.y) touch.enableScrolling.y = NO;
1359
- }
1360
- if (touchScroll.y && !touchScroll.x) {
1361
- if (deltaY > touch.scrollLock && !touchScroll.x) touch.enableScrolling.x = NO;
1362
- }
1363
-
1364
- // handle scaling through pinch gesture
1365
- if (touch.canScale) {
1366
-
1367
- var startDistance = touch.startDistance, dd = distance - startDistance;
1368
- if (Math.abs(dd) > touch.scaleTolerance) {
1369
- touchScroll.y = YES; // if you scale, you can scroll.
1370
- touchScroll.x = YES;
1371
-
1372
- // we want to say something that was the startDistance away from each other should now be
1373
- // distance away. So, if we are twice as far away as we started...
1374
- var scale = touch.startScale * (distance / Math.max(startDistance, 50));
1375
-
1376
- var newScale = this._adjustForEdgeResistance(scale, touch.minimumScale, touch.maximumScale, touch.resistanceCoefficient, touch.resistanceAsymptote);
1377
- this.dragging = YES;
1378
- this._scale = newScale;
1379
- // var newPositionInContentX = positionInContentX * this._scale,
1380
- // newPositionInContentY = positionInContentY * this._scale;
1381
- }
1382
- }
1383
-
1384
- // these do exactly what they sound like. So, this comment is just to
1385
- // block off the code a bit
1386
- // In english, these calculate the minimum X/Y offsets
1387
- minOffsetX = this.minimumScrollOffset(touch.contentSize.width * this._scale, touch.containerSize.width, hAlign);
1388
- minOffsetY = this.minimumScrollOffset(touch.contentSize.height * this._scale, touch.containerSize.height, vAlign);
1389
-
1390
- // and now, maximum...
1391
- maxOffsetX = this.maximumScrollOffset(touch.contentSize.width * this._scale, touch.containerSize.width, hAlign);
1392
- maxOffsetY = this.maximumScrollOffset(touch.contentSize.height * this._scale, touch.containerSize.height, vAlign);
1393
-
1394
-
1395
- // So, the following is the completely written out algebra:
1396
- // (offsetY + touchYInFrame) / this._scale = touch.startTouchOffsetInContent.y
1397
- // offsetY + touchYInFrame = touch.startTouchOffsetInContent.y * this._scale;
1398
- // offsetY = touch.startTouchOffset * this._scale - touchYInFrame
1399
-
1400
- // and the result applied:
1401
- offsetX = touch.startTouchOffsetInContent.x * this._scale - touchXInFrame;
1402
- offsetY = touch.startTouchOffsetInContent.y * this._scale - touchYInFrame;
1403
-
1404
-
1405
- // we need to adjust for edge resistance, or, if bouncing is disabled, just stop flat.
1406
- if (touch.enableBouncing) {
1407
- offsetX = this._adjustForEdgeResistance(offsetX, minOffsetX, maxOffsetX, touch.resistanceCoefficient, touch.resistanceAsymptote);
1408
- offsetY = this._adjustForEdgeResistance(offsetY, minOffsetY, maxOffsetY, touch.resistanceCoefficient, touch.resistanceAsymptote);
1409
- } else {
1410
- offsetX = Math.max(minOffsetX, Math.min(maxOffsetX, offsetX));
1411
- offsetY = Math.max(minOffsetY, Math.min(maxOffsetY, offsetY));
1412
- }
1413
-
1414
- // and now, _if_ scrolling is enabled, set the new coordinates
1415
- if (touchScroll.x) this._scroll_horizontalScrollOffset = offsetX;
1416
- if (touchScroll.y) this._scroll_verticalScrollOffset = offsetY;
1417
-
1418
- // and apply the CSS transforms.
1419
- this._applyCSSTransforms(touch.layer);
1420
- this._touchScrollDidChange();
1421
-
1422
-
1423
- // now we must prepare for momentum scrolling by calculating the momentum.
1424
- if (timeStamp - touch.lastEventTime >= 1 || touch.notCalculated) {
1425
- touch.notCalculated = NO;
1426
- var horizontalOffset = this._scroll_horizontalScrollOffset;
1427
- var verticalOffset = this._scroll_verticalScrollOffset;
1428
-
1429
- touch.scrollVelocity.x = ((horizontalOffset - touch.lastScrollOffset.x) / Math.max(1, timeStamp - touch.lastEventTime)); // in px per ms
1430
- touch.scrollVelocity.y = ((verticalOffset - touch.lastScrollOffset.y) / Math.max(1, timeStamp - touch.lastEventTime)); // in px per ms
1431
- touch.lastScrollOffset.x = horizontalOffset;
1432
- touch.lastScrollOffset.y = verticalOffset;
1433
- touch.lastEventTime = timeStamp;
1434
- }
1435
- },
1436
-
1437
- /** @private */
1438
- touchEnd: function (touch) {
1439
- var touchStatus = this.touch,
1440
- avg = touch.averagedTouchesForView(this);
1441
-
1442
- touch.scrollHasEnded = YES;
1443
- if (avg.touchCount > 0) {
1444
- this.beginTouchTracking(touch, NO);
1445
- } else {
1446
- if (this.dragging) {
1447
- touchStatus.dragging = NO;
1448
-
1449
- // reset last event time
1450
- touchStatus.lastEventTime = touch.timeStamp;
1451
-
1452
- this.startDecelerationAnimation();
1453
- } else {
1454
- // well. The scrolling stopped. Let us tell everyone if there was a pending one that this non-drag op interrupted.
1455
- if (touchStatus.needsScrollEnd) this._touchScrollDidEnd();
1456
-
1457
- // this part looks weird, but it is actually quite simple.
1458
- // First, we send the touch off for capture+starting again, but telling it to return to us
1459
- // if nothing is found or if it is released.
1460
- touch.captureTouch(this, YES);
1461
-
1462
- // if we went anywhere, did anything, etc., call end()
1463
- if (touch.touchResponder && touch.touchResponder !== this) {
1464
- touch.end();
1465
- } else if (!touch.touchResponder || touch.touchResponder === this) {
1466
- // if it was released to us or stayed with us the whole time, or is for some
1467
- // wacky reason empty (in which case it is ours still). If so, and there is a next responder,
1468
- // relay to that.
1469
-
1470
- if (touch.nextTouchResponder) touch.makeTouchResponder(touch.nextTouchResponder);
1471
- } else {
1472
- // in this case, the view that captured it and changed responder should have handled
1473
- // everything for us.
1474
- }
1475
-
1476
- this.touch = null;
1477
- }
1478
-
1479
- this.tracking = NO;
1480
- this.dragging = NO;
1481
- }
1482
- },
1483
-
1484
- /** @private */
1485
- touchCancelled: function () {
1486
- var touchStatus = this.touch;
1487
-
1488
- // if we are decelerating, we don't want to stop that. That would be bad. Because there's no point.
1489
- if (!touchStatus || !touchStatus.animationID) {
1490
- this.beginPropertyChanges();
1491
- this.set("scale", this._scale);
1492
- this.set("verticalScrollOffset", this._scroll_verticalScrollOffset);
1493
- this.set("horizontalScrollOffset", this._scroll_horizontalScrollOffset);
1494
- this.endPropertyChanges();
1495
- this.tracking = NO;
1496
-
1497
- if (this.dragging) {
1498
- this._touchScrollDidEnd();
1499
- }
1500
-
1501
- this.dragging = NO;
1502
- this.touch = null;
1503
- }
1504
- },
1505
-
1506
- /** @private */
1507
- startDecelerationAnimation: function (evt) {
1508
- var touch = this.touch, self = this;
1509
- touch.decelerationVelocity = {
1510
- x: touch.scrollVelocity.x * 10,
1511
- y: touch.scrollVelocity.y * 10
1512
- };
1513
-
1514
- touch.animationID = window.requestAnimationFrame(function () {
1515
- self.decelerateAnimation();
1516
- });
1517
- },
1518
-
1519
- /** @private
1520
- Does bounce calculations, adjusting velocity.
1521
- */
1522
- bouncyBounce: function (velocity, value, minValue, maxValue, de, ac, additionalAcceleration) {
1523
- // we have 4 possible paths. On a higher level, we have two leaf paths that can be applied
1524
- // for either of two super-paths.
1525
- //
1526
- // The first path is if we are decelerating past an edge: in this case, this function must
1527
- // must enhance that deceleration. In this case, our math boils down to taking the amount
1528
- // by which we are past the edge, multiplying it by our deceleration factor, and reducing
1529
- // velocity by that amount.
1530
- //
1531
- // The second path is if we are not decelerating, but are still past the edge. In this case,
1532
- // we must start acceleration back _to_ the edge. The math here takes the distance we are from
1533
- // the edge, multiplies by the acceleration factor, and then performs two additional things:
1534
- // First, it speeds up the acceleration artificially with additionalAcceleration; this will
1535
- // make the stop feel more sudden, as it will still have this additional acceleration when it reaches
1536
- // the edge. Second, it ensures the result does not go past the final value, so we don't end up
1537
- // bouncing back and forth all crazy-like.
1538
- if (value < minValue) {
1539
- if (velocity < 0) velocity = velocity + ((minValue - value) * de);
1540
- else {
1541
- velocity = Math.min((minValue - value) * ac + additionalAcceleration, minValue - value - 0.01);
1542
- }
1543
- } else if (value > maxValue) {
1544
- if (velocity > 0) velocity = velocity - ((value - maxValue) * de);
1545
- else {
1546
- velocity = -Math.min((value - maxValue) * ac + additionalAcceleration, value - maxValue - 0.01);
1547
- }
1548
- }
1549
- return velocity;
1550
- },
1551
-
1552
- /** @private Decelerates the scrolling smoothly. */
1553
- decelerateAnimation: function () {
1554
- // get a bunch of properties. They are named well, so not much explanation of what they are...
1555
- // However, note maxOffsetX/Y takes into account the scale;
1556
- // also, newX/Y adds in the current deceleration velocity (the deceleration velocity will
1557
- // be changed later in this function).
1558
- var touch = this.touch,
1559
- scale = this._scale,
1560
- touchDim = touch.contentSize,
1561
- touchContainerDim = touch.containerSize,
1562
- hAlign = this.get("horizontalAlign"),
1563
- vAlign = this.get("verticalAlign"),
1564
- minOffsetX = this.minimumScrollOffset(touchDim.width * this._scale, touchContainerDim.width, hAlign),
1565
- minOffsetY = this.minimumScrollOffset(touchDim.height * this._scale, touchContainerDim.height, vAlign),
1566
- maxOffsetX = this.maximumScrollOffset(touchDim.width * this._scale, touchContainerDim.width, hAlign),
1567
- maxOffsetY = this.maximumScrollOffset(touchDim.height * this._scale, touchContainerDim.height, vAlign),
1568
-
1569
- now = Date.now(),
1570
- t = Math.max(now - touch.lastEventTime, 1),
1571
-
1572
- newX = this._scroll_horizontalScrollOffset + touch.decelerationVelocity.x * (t / 10),
1573
- newY = this._scroll_verticalScrollOffset + touch.decelerationVelocity.y * (t / 10);
1574
-
1575
- var de = touch.decelerationFromEdge, ac = touch.accelerationToEdge;
1576
-
1577
- // under a few circumstances, we may want to force a valid X/Y position.
1578
- // For instance, if bouncing is disabled, or if position was okay before
1579
- // adjusting scale.
1580
- var forceValidXPosition = !touch.enableBouncing, forceValidYPosition = !touch.enableBouncing;
1581
-
1582
- // determine if position was okay before adjusting scale (which we do, in
1583
- // a lovely, animated way, for the scaled out/in too far bounce-back).
1584
- // if the position was okay, then we are going to make sure that we keep the
1585
- // position okay when adjusting the scale.
1586
- //
1587
- // Position OKness, here, referring to if the position is valid (within
1588
- // minimum and maximum scroll offsets)
1589
- if (newX >= minOffsetX && newX <= maxOffsetX) forceValidXPosition = YES;
1590
- if (newY >= minOffsetY && newY <= maxOffsetY) forceValidYPosition = YES;
1591
-
1592
- // We are going to change scale in a moment, but the position should stay the
1593
- // same, if possible (unless it would be more jarring, as described above, in
1594
- // the case of starting with a valid position and ending with an invalid one).
1595
- //
1596
- // Because we are changing the scale, we need to make the position scale-neutral.
1597
- // we'll make it non-scale-neutral after applying scale.
1598
- //
1599
- // Question: might it be better to save the center position instead, so scaling
1600
- // bounces back around the center of the screen?
1601
- newX /= this._scale;
1602
- newY /= this._scale;
1603
-
1604
- // scale velocity (amount to change) starts out at 0 each time, because
1605
- // it is calculated by how far out of bounds it is, rather than by the
1606
- // previous such velocity.
1607
- var sv = 0;
1608
-
1609
- // do said calculation; we'll use the same bouncyBounce method used for everything
1610
- // else, but our adjustor that gives a minimum amount to change by and (which, as we'll
1611
- // discuss, is to make the stop feel slightly more like a stop), we'll leave at 0
1612
- // (scale doesn't really need it as much; if you disagree, at least come up with
1613
- // numbers more appropriate for scale than the ones for X/Y)
1614
- sv = this.bouncyBounce(sv, scale, touch.minimumScale, touch.maximumScale, de, ac, 0);
1615
-
1616
- // add the amount to scale. This is linear, rather than multiplicative. If you think
1617
- // it should be multiplicative (or however you say that), come up with a new formula.
1618
- this._scale = scale = scale + sv;
1619
-
1620
- // now we can convert newX/Y back to scale-specific coordinates...
1621
- newX *= this._scale;
1622
- newY *= this._scale;
1623
-
1624
- // It looks very weird if the content started in-bounds, but the scale animation
1625
- // made it not be in bounds; it causes the position to animate snapping back, and,
1626
- // well, it looks very weird. It is more proper to just make sure it stays in a valid
1627
- // position. So, we'll determine the new maximum/minimum offsets, and then, if it was
1628
- // originally a valid position, we'll adjust the new position to a valid position as well.
1629
-
1630
-
1631
- // determine new max offset
1632
- minOffsetX = this.minimumScrollOffset(touchDim.width * this._scale, touchContainerDim.width, hAlign);
1633
- minOffsetY = this.minimumScrollOffset(touchDim.height * this._scale, touchContainerDim.height, vAlign);
1634
- maxOffsetX = this.maximumScrollOffset(touchDim.width * this._scale, touchContainerDim.width, hAlign);
1635
- maxOffsetY = this.maximumScrollOffset(touchDim.height * this._scale, touchContainerDim.height, vAlign);
1636
-
1637
- // see if scaling messed up the X position (but ignore if 'tweren't right to begin with).
1638
- if (forceValidXPosition && (newX < minOffsetX || newX > maxOffsetX)) {
1639
- // Correct the position
1640
- newX = Math.max(minOffsetX, Math.min(newX, maxOffsetX));
1641
-
1642
- // also, make the velocity be ZERO; it is obviously not needed...
1643
- touch.decelerationVelocity.x = 0;
1644
- }
1645
-
1646
- // now the y
1647
- if (forceValidYPosition && (newY < minOffsetY || newY > maxOffsetY)) {
1648
- // again, correct it...
1649
- newY = Math.max(minOffsetY, Math.min(newY, maxOffsetY));
1650
-
1651
- // also, make the velocity be ZERO; it is obviously not needed...
1652
- touch.decelerationVelocity.y = 0;
1653
- }
1654
-
1655
-
1656
- // now that we are done modifying the position, we may update the actual scroll
1657
- this._scroll_horizontalScrollOffset = newX;
1658
- this._scroll_verticalScrollOffset = newY;
1659
-
1660
- this._applyCSSTransforms(touch.layer); // <- Does what it sounds like.
1661
-
1662
- this._touchScrollDidChange();
1663
-
1664
- // Now we have to adjust the velocities. The velocities are simple x and y numbers that
1665
- // get added to the scroll X/Y positions each frame.
1666
- // The default decay rate is .950 per frame. To achieve some semblance of accuracy, we
1667
- // make it to the power of the elapsed number of frames. This is not fully accurate,
1668
- // as this is applying the elapsed time between this frame and the previous time to
1669
- // modify the velocity for the next frame. My mind goes blank when I try to figure out
1670
- // a way to fix this (given that we don't want to change the velocity on the first frame),
1671
- // and as it seems to work great as-is, I'm just leaving it.
1672
- var decay = touch.decelerationRate,
1673
- decayXtime = Math.pow(decay, (t / 10));
1674
- touch.decelerationVelocity.y *= decayXtime;
1675
- touch.decelerationVelocity.x *= decayXtime;
1676
-
1677
- // We have a bouncyBounce method that adjusts the velocity for bounce. That is, if it is
1678
- // out of range and still going, it will slow it down. This step is decelerationFromEdge.
1679
- // If it is not moving (or has come to a stop from decelerating), but is still out of range,
1680
- // it will start it moving back into range (accelerationToEdge)
1681
- // we supply de and ac as these properties.
1682
- // The .3 artificially increases the acceleration by .3; this is actually to make the final
1683
- // stop a bit more abrupt.
1684
- touch.decelerationVelocity.x = this.bouncyBounce(touch.decelerationVelocity.x, newX, minOffsetX, maxOffsetX, de, ac, 0.3);
1685
- touch.decelerationVelocity.y = this.bouncyBounce(touch.decelerationVelocity.y, newY, minOffsetY, maxOffsetY, de, ac, 0.3);
1686
-
1687
- // if we ain't got no velocity... then we must be finished, as there is no where else to go.
1688
- // to determine our velocity, we take the absolue value, and use that; if it is less than .01, we
1689
- // must be done. Note that we check scale's most recent velocity, calculated above using bouncyBounce,
1690
- // as well.
1691
- var absXVelocity = Math.abs(touch.decelerationVelocity.x),
1692
- absYVelocity = Math.abs(touch.decelerationVelocity.y);
1693
- if (absYVelocity < 0.05 && absXVelocity < 0.05 && Math.abs(sv) < 0.05) {
1694
- // We can reset the animation id, as it will no longer be required, and we don't want to accidentally try to cancel it later.
1695
- touch.animationID = null;
1696
- this.touch = null;
1697
-
1698
- // trigger scroll end
1699
- this._touchScrollDidEnd();
1700
-
1701
- // set the scale, vertical, and horizontal offsets to what they technically already are,
1702
- // but don't know they are yet. This will finally update things like, say, the clipping frame.
1703
- SC.run(function () {
1704
- this.beginPropertyChanges();
1705
- this.set("scale", this._scale);
1706
- this.set("verticalScrollOffset", this._scroll_verticalScrollOffset);
1707
- this.set("horizontalScrollOffset", this._scroll_horizontalScrollOffset);
1708
- this.endPropertyChanges();
1709
- }, this);
1710
-
1711
- return;
1712
- }
1713
-
1714
- // We now set up the next round. We are doing this as raw as we possibly can, not touching the
1715
- // run loop at all. This speeds up performance drastically--keep in mind, we're on comparatively
1716
- // slow devices, here. So, we'll just make a closure, saving "this" into "self" and calling
1717
- // 10ms later (or however long it takes).
1718
-
1719
- // Note also that we save both the last event time (so we may calculate elapsed time) and the animation
1720
- // id we are creating, so we may cancel it in future.
1721
- var self = this;
1722
- touch.lastEventTime = Date.now();
1723
- touch.animationID = window.requestAnimationFrame(function () {
1724
- self.decelerateAnimation();
1725
- });
1726
- },
1727
-
1728
- // ..........................................................
1729
- // INTERNAL SUPPORT
1730
- //
1731
-
1732
- /** @private
1733
- Instantiate scrollers & container views as needed. Replace their classes
1734
- in the regular properties.
1735
- */
1736
- createChildViews: function () {
1737
- var childViews = [], view;
1738
-
1739
- // create the containerView. We must always have a container view.
1740
- // also, setup the contentView as the child of the containerView...
1741
- if (SC.none(view = this.containerView)) view = SC.ContainerView;
1742
-
1743
- childViews.push(this.containerView = this.createChildView(view, {
1744
- contentView: this.contentView,
1745
- isScrollContainer: YES
1746
- }));
1747
-
1748
- // and replace our own contentView...
1749
- this.contentView = this.containerView.get('contentView');
1750
-
1751
- // create a horizontal scroller view if needed...
1752
- view = SC.platform.touch ? this.get("horizontalTouchScrollerView") : this.get("horizontalScrollerView");
1753
- if (view) {
1754
- if (this.get('hasHorizontalScroller')) {
1755
- view = this.horizontalScrollerView = this.createChildView(view, {
1756
- layoutDirection: SC.LAYOUT_HORIZONTAL,
1757
- valueBinding: '*owner.horizontalScrollOffset'
1758
- });
1759
- childViews.push(view);
1760
- } else this.horizontalScrollerView = null;
1761
- }
1762
-
1763
- // create a vertical scroller view if needed...
1764
- view = SC.platform.touch ? this.get("verticalTouchScrollerView") : this.get("verticalScrollerView");
1765
- if (view) {
1766
- if (this.get('hasVerticalScroller')) {
1767
- view = this.verticalScrollerView = this.createChildView(view, {
1768
- layoutDirection: SC.LAYOUT_VERTICAL,
1769
- valueBinding: '*owner.verticalScrollOffset'
1770
- });
1771
- childViews.push(view);
1772
- } else this.verticalScrollerView = null;
1773
- }
1774
-
1775
- // set childViews array.
1776
- this.childViews = childViews;
1777
-
1778
- this.contentViewDidChange(); // setup initial display...
1779
- this.tile(); // set up initial tiling
1780
- },
1781
-
1782
- /** @private */
1783
- init: function () {
1784
- sc_super();
1785
-
1786
- // start observing initial content view. The content view's frame has
1787
- // already been setup in prepareDisplay so we don't need to call
1788
- // viewFrameDidChange...
1789
- this._scroll_contentView = this.get('contentView');
1790
- var contentView = this._scroll_contentView;
1791
-
1792
- if (contentView) {
1793
- contentView.addObserver('frame', this, 'contentViewFrameDidChange');
1794
- contentView.addObserver('calculatedWidth', this, 'contentViewFrameDidChange');
1795
- contentView.addObserver('calculatedHeight', this, 'contentViewFrameDidChange');
1796
- contentView.addObserver('layer', this, 'contentViewLayerDidChange');
1797
- }
1798
-
1799
- if (this.get('isVisibleInWindow')) this._scsv_registerAutoscroll();
1800
-
1801
- // Initialize cache values.
1802
- this._scroll_contentWidth = this._scroll_contentHeight = null;
1803
- },
1804
-
1805
- /** @private
1806
- Registers/deregisters view with SC.Drag for autoscrolling
1807
- */
1808
- _scsv_registerAutoscroll: function () {
1809
- if (this.get('isVisibleInWindow')) SC.Drag.addScrollableView(this);
1810
- else SC.Drag.removeScrollableView(this);
1811
- }.observes('isVisibleInWindow'),
1812
-
1813
- /** @private
1814
- Whenever the contentView is changed, we need to observe the content view's
1815
- frame to be notified whenever it's size changes.
1816
- */
1817
- contentViewDidChange: function () {
1818
- var newView = this.get('contentView'),
1819
- oldView = this._scroll_contentView;
1820
-
1821
- if (newView !== oldView) {
1822
-
1823
- // stop observing old content view
1824
- if (oldView) {
1825
- oldView.removeObserver('calculatedWidth', this, 'contentViewFrameDidChange');
1826
- oldView.removeObserver('calculatedHeight', this, 'contentViewFrameDidChange');
1827
- oldView.removeObserver('frame', this, 'contentViewFrameDidChange');
1828
- oldView.removeObserver('layer', this, 'contentViewLayerDidChange');
1829
- }
1830
-
1831
- // update cache
1832
- this._scroll_contentView = newView;
1833
- if (newView) {
1834
- newView.addObserver('frame', this, 'contentViewFrameDidChange');
1835
- newView.addObserver('calculatedWidth', this, 'contentViewFrameDidChange');
1836
- newView.addObserver('calculatedHeight', this, 'contentViewFrameDidChange');
1837
- newView.addObserver('layer', this, 'contentViewLayerDidChange');
1838
- }
1839
-
1840
- // replace container
1841
- this.containerView.set('contentView', newView);
1842
-
1843
- this.contentViewFrameDidChange();
1844
- }
1845
- }.observes('contentView'),
1846
-
1847
- /** @private
1848
- If we redraw after the initial render, we need to make sure that we reset
1849
- the scrollTop/scrollLeft properties on the content view. This ensures
1850
- that, for example, the scroll views displays correctly when switching
1851
- views out in a ContainerView.
1852
- */
1853
- render: function (context, firstTime) {
1854
- this.invokeLast(this.adjustElementScroll);
1855
-
1856
- if (firstTime) {
1857
- context.push('<div class="corner"></div>');
1858
- }
1859
- return sc_super();
1860
- },
1861
-
1862
- /** @private */
1863
- oldMaxHOffset: 0,
1864
-
1865
- /** @private */
1866
- oldMaxVOffset: 0,
1867
-
1868
- /** @private
1869
- Invoked whenever the contentView's frame changes. This will update the
1870
- scroller maximum and optionally update the scroller visibility if the
1871
- size of the contentView changes. We don't care about the origin since
1872
- that is tracked separately from the offset values.
1873
- */
1874
- contentViewFrameDidChange: function (force) {
1875
- var view = this.get('contentView'),
1876
- f = (view) ? view.get('frame') : null,
1877
- scale = this._scale,
1878
- width = 0,
1879
- height = 0,
1880
- dim, dimWidth, dimHeight;
1881
-
1882
- // If no view has been set yet, or it doesn't have a frame,
1883
- // we can avoid doing any work.
1884
- if (!view || !f) { return; }
1885
-
1886
- width = view.get('calculatedWidth') || f.width || 0;
1887
- height = view.get('calculatedHeight') || f.height || 0;
1888
-
1889
- width *= scale;
1890
- height *= scale;
1891
-
1892
- // cache out scroll settings...
1893
- if ((width === this._scroll_contentWidth) && (height === this._scroll_contentHeight)) return;
1894
- this._scroll_contentWidth = width;
1895
- this._scroll_contentHeight = height;
1896
-
1897
- dim = this.getPath('containerView.frame');
1898
- dimWidth = dim.width;
1899
- dimHeight = dim.height;
1900
-
1901
- if (this.get('hasHorizontalScroller') && (view = this.get('horizontalScrollerView'))) {
1902
- // decide if it should be visible or not
1903
- if (this.get('autohidesHorizontalScroller')) {
1904
- this.set('isHorizontalScrollerVisible', width > dimWidth);
1905
- }
1906
- view.setIfChanged('maximum', width - dimWidth);
1907
- view.setIfChanged('proportion', dimWidth / width);
1908
- }
1909
-
1910
- if (this.get('hasVerticalScroller') && (view = this.get('verticalScrollerView'))) {
1911
- // decide if it should be visible or not
1912
- if (this.get('autohidesVerticalScroller')) {
1913
- this.set('isVerticalScrollerVisible', height > dimHeight);
1914
- }
1915
- view.setIfChanged('maximum', height - dimHeight);
1916
- view.setIfChanged('proportion', dimHeight / height);
1917
- }
1918
-
1919
- // If there is no vertical scroller and auto hiding is on, make
1920
- // sure we are at the top if not already there
1921
- if (!this.get('isVerticalScrollerVisible') && (this.get('verticalScrollOffset') !== 0) &&
1922
- this.get('autohidesVerticalScroller')) {
1923
- this.set('verticalScrollOffset', 0);
1924
- }
1925
-
1926
- // Same thing for horizontal scrolling.
1927
- if (!this.get('isHorizontalScrollerVisible') && (this.get('horizontalScrollOffset') !== 0) &&
1928
- this.get('autohidesHorizontalScroller')) {
1929
- this.set('horizontalScrollOffset', 0);
1930
- }
1931
-
1932
- // This forces to recalculate the height of the frame when is at the bottom
1933
- // of the scroll and the content dimension are smaller that the previous one
1934
- var mxVOffSet = this.get('maximumVerticalScrollOffset'),
1935
- vOffSet = this.get('verticalScrollOffset'),
1936
- mxHOffSet = this.get('maximumHorizontalScrollOffset'),
1937
- hOffSet = this.get('horizontalScrollOffset'),
1938
- forceHeight = mxVOffSet < vOffSet,
1939
- forceWidth = mxHOffSet < hOffSet;
1940
- if (forceHeight || forceWidth) {
1941
- // Update the position of the content view to fit.
1942
- this.forceDimensionsRecalculation(forceWidth, forceHeight, vOffSet, hOffSet);
1943
- } else {
1944
- // Reapply the position. Most importantly, this reapplies the touch transforms on the content view in case they were overwritten.
1945
- this.invokeLast(this.adjustElementScroll);
1946
- }
1947
-
1948
- // send change notifications since they don't invalidate automatically
1949
- this.notifyPropertyChange('maximumVerticalScrollOffset');
1950
- this.notifyPropertyChange('maximumHorizontalScrollOffset');
1951
- },
1952
-
1953
- /** @private
1954
- If our frame changes, then we need to re-calculate the visibility of our
1955
- scrollers, etc.
1956
- */
1957
- frameDidChange: function () {
1958
- this._scroll_contentWidth = this._scroll_contentHeight = null;
1959
- this.contentViewFrameDidChange();
1960
- }.observes('frame'),
1961
-
1962
- /** @private
1963
- If the layer of the content view changes, we need to readjust the
1964
- scrollTop and scrollLeft properties on the new DOM element.
1965
- */
1966
- contentViewLayerDidChange: function () {
1967
- // Invalidate these cached values, as they're no longer valid
1968
- if (this._verticalScrollOffset !== 0) this._verticalScrollOffset = -1;
1969
- if (this._horizontalScrollOffset !== 0) this._horizontalScrollOffset = -1;
1970
- this.invokeLast(this.adjustElementScroll);
1971
- },
1972
-
1973
- /** @private
1974
- Whenever the horizontal scroll offset changes, update the scrollers and
1975
- edit the location of the contentView.
1976
- */
1977
- _scroll_horizontalScrollOffsetDidChange: function () {
1978
- this.invokeLast(this.adjustElementScroll);
1979
- }.observes('horizontalScrollOffset'),
1980
-
1981
- /** @private
1982
- Whenever the vertical scroll offset changes, update the scrollers and
1983
- edit the location of the contentView.
1984
- */
1985
- _scroll_verticalScrollOffsetDidChange: function () {
1986
- this.invokeLast(this.adjustElementScroll);
1987
- }.observes('verticalScrollOffset'),
1988
-
1989
- /** @private
1990
- Called at the end of the run loop to actually adjust the scrollTop
1991
- and scrollLeft properties of the container view.
1992
- */
1993
- adjustElementScroll: function () {
1994
- var container = this.get('containerView'),
1995
- content = this.get('contentView'),
1996
- verticalScrollOffset = this.get('verticalScrollOffset'),
1997
- horizontalScrollOffset = this.get('horizontalScrollOffset');
1998
-
1999
- // We notify the content view that its frame property has changed
2000
- // before we actually update the scrollTop/scrollLeft properties.
2001
- // This gives views that use incremental rendering a chance to render
2002
- // newly-appearing elements before they come into view.
2003
- if (content) {
2004
- // Use accelerated drawing if the browser supports it
2005
- if (SC.platform.touch) {
2006
- this._applyCSSTransforms(content.get('layer'));
2007
- }
2008
-
2009
- // Notify the child that its frame is changing.
2010
- if (content._viewFrameDidChange) { content._viewFrameDidChange(); }
2011
- }
2012
-
2013
- if (container && !SC.platform.touch) {
2014
- container = container.$()[0];
2015
-
2016
- if (container) {
2017
- if (verticalScrollOffset !== this._verticalScrollOffset) {
2018
- container.scrollTop = verticalScrollOffset;
2019
- this._verticalScrollOffset = verticalScrollOffset;
2020
- }
2021
-
2022
- if (horizontalScrollOffset !== this._horizontalScrollOffset) {
2023
- container.scrollLeft = horizontalScrollOffset;
2024
- this._horizontalScrollOffset = horizontalScrollOffset;
2025
- }
2026
- }
2027
- }
2028
- },
2029
-
2030
- /** @private */
2031
- forceDimensionsRecalculation: function (forceWidth, forceHeight, vOffSet, hOffSet) {
2032
- var oldScrollHOffset = hOffSet;
2033
- var oldScrollVOffset = vOffSet;
2034
- this.scrollTo(0, 0);
2035
-
2036
- if (forceWidth && forceHeight) {
2037
- this.scrollTo(this.get('maximumHorizontalScrollOffset'), this.get('maximumVerticalScrollOffset'));
2038
- }
2039
- if (forceWidth && !forceHeight) {
2040
- this.scrollTo(this.get('maximumHorizontalScrollOffset'), oldScrollVOffset);
2041
- }
2042
- if (!forceWidth && forceHeight) {
2043
- this.scrollTo(oldScrollHOffset, this.get('maximumVerticalScrollOffset'));
2044
- }
2045
- },
2046
-
2047
- /** @private */
2048
- _scroll_verticalScrollOffset: 0,
2049
-
2050
- /** @private */
2051
- _scroll_horizontalScrollOffset: 0
2052
-
2053
- });