sproutcore 1.6.0.1 → 1.7.1.beta

Sign up to get free protection for your applications and to get access to all the features.
Files changed (143) hide show
  1. data/CHANGELOG +21 -0
  2. data/Gemfile +5 -0
  3. data/Rakefile +26 -13
  4. data/VERSION.yml +2 -2
  5. data/lib/Buildfile +43 -4
  6. data/lib/buildtasks/build.rake +10 -0
  7. data/lib/buildtasks/helpers/file_rule.rb +22 -0
  8. data/lib/buildtasks/helpers/file_rule_list.rb +137 -0
  9. data/lib/buildtasks/manifest.rake +133 -122
  10. data/lib/frameworks/sproutcore/CHANGELOG.md +69 -2
  11. data/lib/frameworks/sproutcore/apps/tests/english.lproj/strings.js +1 -0
  12. data/lib/frameworks/sproutcore/frameworks/bootstrap/system/browser.js +28 -22
  13. data/lib/frameworks/sproutcore/frameworks/core_foundation/controllers/array.js +9 -5
  14. data/lib/frameworks/sproutcore/frameworks/core_foundation/controllers/controller.js +1 -1
  15. data/lib/frameworks/sproutcore/frameworks/core_foundation/controls/button.js +18 -13
  16. data/lib/frameworks/sproutcore/frameworks/core_foundation/ext/handlebars/bind.js +5 -3
  17. data/lib/frameworks/sproutcore/frameworks/core_foundation/ext/handlebars/collection.js +2 -0
  18. data/lib/frameworks/sproutcore/frameworks/core_foundation/mixins/action_support.js +80 -0
  19. data/lib/frameworks/sproutcore/frameworks/core_foundation/mixins/template_helpers/text_field_support.js +84 -116
  20. data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/pane.js +8 -5
  21. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/event.js +157 -157
  22. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/platform.js +5 -3
  23. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/root_responder.js +6 -6
  24. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/sparse_array.js +10 -7
  25. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/mixins/action_support.js +106 -0
  26. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/template/collection.js +18 -0
  27. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/template/handlebars.js +71 -1
  28. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/attribute_bindings_test.js +38 -0
  29. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/class_name_bindings_test.js +47 -0
  30. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layoutChildViews.js +18 -18
  31. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layoutStyle.js +42 -10
  32. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/keyboard.js +26 -1
  33. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/layout_style.js +14 -8
  34. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view.js +158 -1
  35. data/lib/frameworks/sproutcore/frameworks/datastore/models/record.js +15 -2
  36. data/lib/frameworks/sproutcore/frameworks/datastore/models/record_attribute.js +108 -108
  37. data/lib/frameworks/sproutcore/frameworks/datastore/system/query.js +1 -1
  38. data/lib/frameworks/sproutcore/frameworks/datastore/system/record_array.js +2 -4
  39. data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/record/error_methods.js +2 -2
  40. data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/single_attribute.js +26 -0
  41. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/query/builders.js +7 -0
  42. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/record_array/error_methods.js +1 -1
  43. data/lib/frameworks/sproutcore/frameworks/datetime/frameworks/core/system/datetime.js +4 -1
  44. data/lib/frameworks/sproutcore/frameworks/datetime/frameworks/core/tests/system/datetime.js +6 -0
  45. data/lib/frameworks/sproutcore/frameworks/desktop/panes/menu.js +26 -5
  46. data/lib/frameworks/sproutcore/frameworks/desktop/panes/picker.js +97 -96
  47. data/lib/frameworks/sproutcore/frameworks/desktop/system/drag.js +4 -3
  48. data/lib/frameworks/sproutcore/frameworks/desktop/tests/panes/menu/ui.js +17 -4
  49. data/lib/frameworks/sproutcore/frameworks/desktop/views/collection.js +7 -7
  50. data/lib/frameworks/sproutcore/frameworks/desktop/views/menu_item.js +7 -5
  51. data/lib/frameworks/sproutcore/frameworks/desktop/views/scroll.js +12 -3
  52. data/lib/frameworks/sproutcore/frameworks/desktop/views/web.js +23 -14
  53. data/lib/frameworks/sproutcore/frameworks/experimental/Buildfile +5 -1
  54. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/menu/render_delegates/menu_scroller.js +28 -0
  55. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/menu/tests/menu/scroll.js +235 -0
  56. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/menu/views/menu/scroll.js +363 -0
  57. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/menu/views/menu/scroller.js +250 -0
  58. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/render_delegates/desktop_scroller.js +92 -0
  59. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/render_delegates/native_scroll.js +25 -0
  60. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/render_delegates/scroll.js +33 -0
  61. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/render_delegates/touch_scroller.js +76 -0
  62. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/tests/scroll/integration.js +50 -0
  63. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/tests/scroll/methods.js +143 -0
  64. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/tests/scroll/ui.js +258 -0
  65. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/core_scroll.js +1164 -0
  66. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/core_scroller.js +332 -0
  67. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/desktop/scroll.js +236 -0
  68. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/desktop/scroller.js +347 -0
  69. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/scroll.js +15 -0
  70. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/scroller.js +10 -0
  71. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/touch/scroll.js +804 -0
  72. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/touch/scroller.js +133 -0
  73. data/lib/frameworks/sproutcore/frameworks/foundation/resources/text_field.css +3 -3
  74. data/lib/frameworks/sproutcore/frameworks/foundation/validators/number.js +3 -1
  75. data/lib/frameworks/sproutcore/frameworks/foundation/views/text_field.js +3 -3
  76. data/lib/frameworks/sproutcore/frameworks/media/views/audio.js +2 -1
  77. data/lib/frameworks/sproutcore/frameworks/media/views/controls.js +2 -1
  78. data/lib/frameworks/sproutcore/frameworks/media/views/media_slider.js +2 -4
  79. data/lib/frameworks/sproutcore/frameworks/media/views/mini_controls.js +2 -4
  80. data/lib/frameworks/sproutcore/frameworks/media/views/simple_controls.js +2 -4
  81. data/lib/frameworks/sproutcore/frameworks/media/views/video.js +2 -2
  82. data/lib/frameworks/sproutcore/frameworks/routing/system/routes.js +29 -3
  83. data/lib/frameworks/sproutcore/frameworks/runtime/core.js +2 -2
  84. data/lib/frameworks/sproutcore/frameworks/runtime/debug/test_suites/array/replace.js +1 -1
  85. data/lib/frameworks/sproutcore/frameworks/runtime/private/property_chain.js +2 -1
  86. data/lib/frameworks/sproutcore/frameworks/runtime/system/binding.js +3 -3
  87. data/lib/frameworks/sproutcore/frameworks/runtime/system/index_set.js +2 -2
  88. data/lib/frameworks/sproutcore/frameworks/runtime/system/object.js +1 -1
  89. data/lib/frameworks/sproutcore/themes/ace/resources/collection/normal/list_item.css +2 -2
  90. data/lib/frameworks/sproutcore/themes/legacy_theme/english.lproj/segmented.css +1 -1
  91. data/lib/gen/app/templates/apps/@target_name@/Buildfile +3 -5
  92. data/lib/gen/app/templates/apps/@target_name@/resources/_theme.css +18 -0
  93. data/lib/gen/project/templates/@filename@/Buildfile +2 -2
  94. data/lib/sproutcore/builders/chance_file.rb +9 -16
  95. data/lib/sproutcore/builders/html.rb +2 -1
  96. data/lib/sproutcore/builders/minify.rb +4 -35
  97. data/lib/sproutcore/builders/module.rb +38 -1
  98. data/lib/sproutcore/builders/split.rb +63 -0
  99. data/lib/sproutcore/builders/strings.rb +7 -1
  100. data/lib/sproutcore/builders.rb +1 -0
  101. data/lib/sproutcore/helpers/css_split.rb +190 -0
  102. data/lib/sproutcore/helpers/entry_sorter.rb +2 -0
  103. data/lib/sproutcore/helpers/minifier.rb +40 -16
  104. data/lib/sproutcore/helpers/static_helper.rb +35 -17
  105. data/lib/sproutcore/helpers.rb +1 -1
  106. data/lib/sproutcore/models/manifest.rb +26 -0
  107. data/lib/sproutcore/models/target.rb +12 -1
  108. data/lib/sproutcore/rack/proxy.rb +244 -225
  109. data/lib/sproutcore/rack/restrict_ip.rb +67 -0
  110. data/lib/sproutcore/rack/service.rb +8 -2
  111. data/lib/sproutcore/rack.rb +1 -0
  112. data/lib/sproutcore/tools/build.rb +91 -43
  113. data/lib/sproutcore/tools/gen.rb +2 -3
  114. data/lib/sproutcore/tools/manifest.rb +22 -16
  115. data/lib/sproutcore/tools/server.rb +21 -0
  116. data/lib/sproutcore/tools.rb +102 -46
  117. data/lib/sproutcore.rb +30 -5
  118. data/spec/buildtasks/helpers/accept_list +22 -0
  119. data/spec/buildtasks/helpers/accept_list.rb +128 -0
  120. data/spec/buildtasks/helpers/list.json +11 -0
  121. data/spec/buildtasks/manifest/prepare_build_tasks/chance_2x_spec.rb +1 -39
  122. data/spec/buildtasks/manifest/prepare_build_tasks/chance_spec.rb +0 -38
  123. data/spec/buildtasks/manifest/prepare_build_tasks/combine_spec.rb +4 -4
  124. data/spec/buildtasks/manifest/prepare_build_tasks/module_spec.rb +2 -2
  125. data/spec/buildtasks/manifest/prepare_build_tasks/packed_2x_indirect_spec.rb +7 -16
  126. data/spec/buildtasks/manifest/prepare_build_tasks/packed_2x_spec.rb +7 -17
  127. data/spec/buildtasks/manifest/prepare_build_tasks/packed_spec.rb +11 -6
  128. data/spec/fixtures/builder_tests/Buildfile +2 -1
  129. data/spec/fixtures/builder_tests/apps/module_test/modules/required_module/core.js +0 -0
  130. data/spec/lib/builders/module_spec.rb +1 -1
  131. data/spec/spec_helper.rb +1 -0
  132. data/sproutcore.gemspec +4 -9
  133. data/vendor/chance/lib/chance/factory.rb +45 -0
  134. data/vendor/chance/lib/chance/instance/data_url.rb +0 -29
  135. data/vendor/chance/lib/chance/instance/slicing.rb +57 -4
  136. data/vendor/chance/lib/chance/instance/spriting.rb +112 -21
  137. data/vendor/chance/lib/chance/instance.rb +173 -28
  138. data/vendor/chance/lib/chance/parser.rb +80 -52
  139. data/vendor/chance/lib/chance.rb +25 -6
  140. data/vendor/sproutcore/SCCompiler.jar +0 -0
  141. data/vendor/sproutcore/lib/args4j-2.0.12.jar +0 -0
  142. data/vendor/sproutcore/lib/yuicompressor-2.4.2.jar +0 -0
  143. metadata +97 -38
@@ -0,0 +1,363 @@
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/menu/scroller');
9
+
10
+ /** @class
11
+
12
+ Implements a scroll view for menus. This class extends SC.ScrollView for
13
+ menus.
14
+
15
+ The main difference with SC.ScrollView is that there is only vertical
16
+ scrolling. Value Syncing between SC.MenuScrollView and SC.MenuScrollerView
17
+ is done using valueBinding.
18
+
19
+ @extends SC.ScrollView
20
+ @since SproutCore 1.6
21
+ */
22
+ SC.MenuScrollView = SC.ScrollView.extend(
23
+ /** @scope SC.MenuScrollView.prototype */{
24
+
25
+ /**
26
+ @type Array
27
+ @default ['sc-menu-scroll-view']
28
+ @see SC.View#classNames
29
+ */
30
+ classNames: ['sc-menu-scroll-view'],
31
+
32
+ // ..........................................................
33
+ // PROPERTIES
34
+ //
35
+
36
+ /**
37
+ The maximum horizontal scroll offset allowed given the current
38
+ contentView size and the size of the scroll view.
39
+
40
+ @type Number
41
+ @default 0
42
+ */
43
+ maximumHorizontalScrollOffset: 0,
44
+
45
+
46
+ // ..........................................................
47
+ // SCROLLERS
48
+ //
49
+
50
+ /**
51
+ @type Boolean
52
+ @default NO
53
+ */
54
+ hasHorizontalScroller: NO,
55
+
56
+ /**
57
+ @type Boolean
58
+ @default NO
59
+ */
60
+ isHorizontalScrollerVisible: NO,
61
+
62
+ /**
63
+ @type Boolean
64
+ @default NO
65
+ */
66
+ canScrollHorizontal: NO,
67
+
68
+ /**
69
+ @type Boolean
70
+ @default NO
71
+ */
72
+ autohidesHorizontalScroller: NO,
73
+
74
+ /**
75
+ YES if the view shuld maintain a vertical scroller.
76
+ This property must be set when the view is created.
77
+
78
+ @type Boolean
79
+ @default YES
80
+ */
81
+ hasVerticalScroller: YES,
82
+
83
+ /**
84
+ The vertical scroller view class. This will be replaced with a view
85
+ instance when the ScrollView is created unless hasVerticalScroller is NO.
86
+
87
+ @type SC.View
88
+ @default SC.MenuScrollerView
89
+ */
90
+ verticalScrollerView: SC.MenuScrollerView,
91
+ verticalScrollerView2: SC.MenuScrollerView,
92
+
93
+ /**
94
+ YES if the vertical scroller should be visible. For SC.MenuScroll the
95
+ vertical scroller is always there we just hide the arrows to scroll.
96
+
97
+ @type Boolean
98
+ @default YES
99
+ */
100
+ isVerticalScrollerVisible: YES,
101
+
102
+ /**
103
+ @type Boolean
104
+ @default YES
105
+ */
106
+ canScrollVertical: YES,
107
+
108
+ /**
109
+ If YES, the vertical scroller will autohide if the contentView is
110
+ smaller than the visible area. You must set `autohidesVerticalScroller`
111
+ or `hasVerticalScroller` to YES for this property to have any effect.
112
+
113
+ @type Boolean
114
+ @default YES
115
+ */
116
+ autohidesVerticalScrollers: YES,
117
+
118
+ /**
119
+ If YES, the vertical scroller will autohide (and show) both scrollers if the
120
+ contentView is smaller than the visible area.
121
+
122
+ @type Boolean
123
+ @default YES
124
+ */
125
+ autohidesVerticalScroller: YES,
126
+
127
+ /**
128
+ Use this property to set the 'bottom' offset of your vertical scroller,
129
+ to make room for a thumb view or other accessory view. Default is 0.
130
+
131
+ @type Number
132
+ @default 0
133
+ */
134
+ verticalScrollerBottom: 0,
135
+
136
+ /**
137
+ Control Size for Menu content: change verticalLineScroll
138
+
139
+ @type String
140
+ @default SC.REGULAR_CONTROL_SIZE
141
+ */
142
+ controlSize: SC.REGULAR_CONTROL_SIZE,
143
+
144
+ /**
145
+ Wants scroll notifications all the time.
146
+ @type Number
147
+ @default 0
148
+ */
149
+ incrementalRenderingDelta: 0,
150
+
151
+ // ..........................................................
152
+ // METHODS
153
+ //
154
+
155
+ _scmsv_lastVerticalScrollOffset: 0,
156
+
157
+ /** @private
158
+ Does internal adjustments to the scroll offset to account for the
159
+ scrollers appearing / disappearing.
160
+ */
161
+ _scmsv_verticalScrollOffsetDidChange: function () {
162
+ var vOffset = this._scmsv_lastVerticalScrollOffset,
163
+ offset = this.get('verticalScrollOffset'),
164
+ topThickness = this.getPath('verticalScrollerView.scrollerThickness');
165
+
166
+ if (vOffset !== offset && this.get('autohidesVerticalScrollers')) {
167
+ // When the top scroller appears...
168
+ if (vOffset === 0 && offset > 0) {
169
+ offset += topThickness;
170
+
171
+ // When the top scroller disappears...
172
+ } else if (vOffset > 0 && offset - topThickness <= 0) {
173
+ offset = 0;
174
+ }
175
+
176
+ this.set('verticalScrollOffset', offset);
177
+ this._scmsv_lastVerticalScrollOffset = offset;
178
+ }
179
+ }.observes('verticalScrollOffset'),
180
+
181
+ /** @private
182
+ Adjusts the layout for the various internal views. This method is called
183
+ once when the scroll view is first configured and then anytime a scroller
184
+ is shown or hidden. You can call this method yourself as well to retile.
185
+
186
+ You may also want to override this method to handle layout for any
187
+ additional controls you have added to the view.
188
+ */
189
+ tile: function () {
190
+ var vScroller, layout = { left: 0, top: 0, bottom: 0 },
191
+ hasScroller = this.get('hasVerticalScroller'),
192
+ isVisible = this.get('isVerticalScrollerVisible'),
193
+ vOffset = this.get('verticalScrollOffset'),
194
+ maxOffset = this.get('maximumVerticalScrollOffset'),
195
+ scrollerThickness, vScrollerIsVisible,
196
+ cView = this.get('contentView'),
197
+ cFrame = cView.get('frame'),
198
+ view = this.get('containerView'),
199
+ frame = view.get('frame');
200
+
201
+ this.set('canScrollVertical',
202
+ (cView.get('calculatedHeight') || cFrame.height || 0) * this._scale > this.get('frame').height);
203
+
204
+ // Fast path when the scrollers shouldn't be automatically hidden.
205
+ if (hasScroller && !this.get('autohidesVerticalScrollers')) {
206
+ vScroller = this.get('verticalScrollerView');
207
+ vScrollerIsVisible = vScroller && isVisible;
208
+ vScroller.set('isVisible', vScrollerIsVisible);
209
+ if (vScrollerIsVisible) {
210
+ layout.top = vScroller.get('scrollerThickness');
211
+ vScroller.set('layout', { height: layout.top, top: 0, right: 0, left: 0 });
212
+ }
213
+
214
+ vScroller = this.get('verticalScrollerView2');
215
+ vScrollerIsVisible = vScroller && isVisible;
216
+ vScroller.set('isVisible', vScrollerIsVisible);
217
+ if (vScrollerIsVisible) {
218
+ layout.bottom = vScroller.get('scrollerThickness');
219
+ vScroller.set('layout', { height: layout.bottom, bottom: 0, right: 0, left: 0 });
220
+ }
221
+
222
+ // Automatically hide scrollers.
223
+ } else {
224
+
225
+ // Top scrollbar calculations.
226
+ vScroller = hasScroller ? this.get('verticalScrollerView') : null;
227
+ vScrollerIsVisible = vScroller && isVisible;
228
+ if (vScrollerIsVisible) {
229
+ scrollerThickness = vScroller.get('scrollerThickness');
230
+ layout.top = (vOffset === 0) ? 0 : scrollerThickness; // Scrolled; show the scrollbar.
231
+ vScroller.set('layout', { height: layout.top, top: 0, right: 0, left: 0 });
232
+ }
233
+ vScroller.set('isVisible', vScrollerIsVisible && layout.top !== 0);
234
+
235
+ // Bottom scrollbar calculations
236
+ vScroller = hasScroller ? this.get('verticalScrollerView2') : null;
237
+ vScrollerIsVisible = vScroller && isVisible;
238
+ if (vScroller && isVisible) {
239
+ scrollerThickness = vScroller.get('scrollerThickness');
240
+
241
+ // Adjust for visible scrollers.
242
+ var padding = 0;
243
+ if (layout.top === 0 || view.getPath('layout.top') > 0) {
244
+ padding = view.getPath('layout.bottom') || 0;
245
+ padding = SC.none(padding) ? scrollerThickness : padding;
246
+ }
247
+
248
+ layout.bottom = cFrame && (vOffset < (cFrame.height - frame.height - padding)) ?
249
+ scrollerThickness : 0;
250
+ vScroller.set('layout', { height: layout.bottom, bottom: 0, right: 0, left: 0 });
251
+ }
252
+ vScroller.set('isVisible', vScrollerIsVisible && layout.bottom !== 0);
253
+ }
254
+
255
+ view.adjust(layout);
256
+ },
257
+
258
+ /** @private
259
+ Called whenever a scroller visibility changes. Calls the tile() method.
260
+ */
261
+ scrollerVisibilityDidChange: function () {
262
+ this.tile();
263
+ }.observes('isVerticalScrollerVisible', 'verticalScrollOffset'),
264
+
265
+
266
+ // ..........................................................
267
+ // INTERNAL SUPPORT
268
+ //
269
+
270
+ /** @private
271
+ Instantiate scrollers & container views as needed.
272
+ Replace their classes in the regular properties.
273
+ */
274
+ createChildViews: function () {
275
+ var childViews = [], view, view2, controlSize = this.get('controlSize');
276
+
277
+ // create the containerView. We must always have a container view.
278
+ // also, setup the contentView as the child of the containerView...
279
+ if (SC.none(view = this.containerView)) view = SC.ContainerView;
280
+
281
+ childViews.push(this.containerView = this.createChildView(view, {
282
+ contentView: this.contentView,
283
+ isScrollContainer: YES
284
+ }));
285
+
286
+ // and replace our own contentView...
287
+ this.contentView = this.containerView.get('contentView');
288
+
289
+ // create a vertical scroller
290
+ if ((view=this.verticalScrollerView) && (view2=this.verticalScrollerView2)) {
291
+ if (this.get('hasVerticalScroller')) {
292
+ view = this.verticalScrollerView = this.createChildView(view, {
293
+ layout: { top: 0, left: 0, right: 0 },
294
+ controlSize: controlSize,
295
+ valueBinding: '*owner.verticalScrollOffset'
296
+ });
297
+ childViews.push(view);
298
+ view2 = this.verticalScrollerView2 = this.createChildView(view2, {
299
+ scrollDown: YES,
300
+ layout: { bottom: 0, left: 0, right: 0 },
301
+ controlSize: controlSize,
302
+ valueBinding: '*owner.verticalScrollOffset'
303
+ });
304
+ childViews.push(view2);
305
+ } else {
306
+ this.verticalScrollerView = null;
307
+ this.verticalScrollerView2 = null;
308
+ }
309
+ }
310
+
311
+ // set childViews array.
312
+ this.childViews = childViews;
313
+
314
+ this.contentViewFrameDidChange(); // setup initial display...
315
+ this.tile(); // set up initial tiling
316
+ },
317
+
318
+ /** @private
319
+ Invoked whenever the contentView's frame changes. This will update the
320
+ scroller maxmimum and optionally update the scroller visibility if the
321
+ size of the contentView changes. We don't care about the origin since
322
+ that is tracked separately from the offset values.
323
+ */
324
+ contentViewFrameDidChange: function (force) {
325
+ var view = this.get('contentView'), view2,
326
+ f = (view) ? view.get('frame') : null,
327
+ scale = this._scale, height,
328
+ dim = this.get('frame'),
329
+ viewportHeight, elem;
330
+
331
+ // If no view has been set yet, or it doesn't have a frame,
332
+ // we can avoid doing any work.
333
+ if (!view || !f) { return; }
334
+
335
+ height = view.get('calculatedHeight') || f.height || 0;
336
+ height *= scale;
337
+
338
+ // cache out scroll settings...
339
+ if (!force && height === this._scroll_contentHeight) return;
340
+ this._scroll_contentHeight = height;
341
+
342
+
343
+ if (this.get('hasVerticalScroller') && (view = this.get('verticalScrollerView')) && (view2 = this.get('verticalScrollerView2'))) {
344
+ // decide if it should be visible or not
345
+ if (this.get('autohidesVerticalScroller')) {
346
+ this.set('isVerticalScrollerVisible', height > dim.height);
347
+ }
348
+ height -= this.get('verticalScrollerBottom');
349
+ viewportHeight = 0;
350
+ elem = this.containerView.$()[0];
351
+ if (elem) viewportHeight = elem.offsetHeight;
352
+ height = height - viewportHeight;
353
+ view.setIfChanged('maximum', height);
354
+ view2.setIfChanged('maximum', height);
355
+
356
+ this.tile(); // Retile to make sure scrollers become invisible / visible
357
+ }
358
+ },
359
+
360
+ /** @private */
361
+ _scroll_horizontalScrollOffsetDidChange: function () {}
362
+
363
+ });
@@ -0,0 +1,250 @@
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
+ /** @class
9
+
10
+ Implements a complete scroller view for menus.
11
+ This class implements the arrows displayed in a menu to scroll.
12
+
13
+ The main difference with `SC.ScrollerView` is that there is only vertical
14
+ scrollers. Value Syncing between `SC.MenuScrollView` and `SC.MenuScrollerView`
15
+ is done using valueBinding.
16
+
17
+ @extends SC.CoreScrollerView
18
+ @since SproutCore 1.6
19
+ */
20
+ SC.MenuScrollerView = SC.CoreScrollerView.extend(
21
+ /** @scope SC.MenuScrollerView.prototype */{
22
+
23
+ /**
24
+ @type Array
25
+ @default ['sc-menu-scroller-view']
26
+ @see SC.View#classNames
27
+ */
28
+ classNames: ['sc-menu-scroller-view'],
29
+
30
+ /**
31
+ @type Array
32
+ @default ['scrollDown']
33
+ @see SC.View#displayProperties
34
+ */
35
+ displayProperties: ['scrollDown'],
36
+
37
+ /**
38
+ @type String
39
+ @default 'menuScrollerRenderDelegate'
40
+ */
41
+ renderDelegateName: 'menuScrollerRenderDelegate',
42
+
43
+ // ..........................................................
44
+ // PROPERTIES
45
+ //
46
+
47
+ /**
48
+ Used to set the scrolling direction of the scroller.
49
+
50
+ @type Boolean
51
+ @default NO
52
+ */
53
+ scrollDown: NO,
54
+
55
+ /**
56
+ The maximum offset value for the scroller. This will be used to calculate
57
+ the internal height/width of the scroller itself. It is not necessarily
58
+ the same as the height of a scroll view's content view.
59
+
60
+ When set less than the height of the scroller, the scroller is disabled.
61
+
62
+ @type Number
63
+ @default 0
64
+ */
65
+ maximum: 0,
66
+
67
+ /**
68
+ YES if enable scrollbar, NO to disable it. Scrollbars will automatically
69
+ disable if the maximum scroll width does not exceed their capacity.
70
+
71
+ @type Boolean
72
+ @default YES
73
+ */
74
+ isEnabled: YES,
75
+
76
+ /**
77
+ This function overrides the default function in SC.Scroller as
78
+ menus only have vertical scrolling.
79
+
80
+ @field
81
+ @type String
82
+ @default 'verticalScrollOffset'
83
+ */
84
+ ownerScrollValueKey: function() {
85
+ return 'verticalScrollOffset';
86
+ }.property('layoutDirection').cacheable(),
87
+
88
+
89
+ // ..........................................................
90
+ // INTERNAL SUPPORT
91
+ //
92
+
93
+ /** @private */
94
+ init: function() {
95
+ // Set the scrollerThickness based on controlSize
96
+ switch (this.get('controlSize')) {
97
+ case SC.TINY_CONTROL_SIZE:
98
+ this.set('scrollerThickness', SC.MenuScrollerView.TINY_SCROLLER_THICKNESS);
99
+ break;
100
+ case SC.SMALL_CONTROL_SIZE:
101
+ this.set('scrollerThickness', SC.MenuScrollerView.SMALL_SCROLLER_THICKNESS);
102
+ break;
103
+ case SC.REGULAR_CONTROL_SIZE:
104
+ this.set('scrollerThickness', SC.MenuScrollerView.REGULAR_SCROLLER_THICKNESS);
105
+ break;
106
+ case SC.LARGE_CONTROL_SIZE:
107
+ this.set('scrollerThickness', SC.MenuScrollerView.LARGE_SCROLLER_THICKNESS);
108
+ break;
109
+ case SC.HUGE_CONTROL_SIZE:
110
+ this.set('scrollerThickness', SC.MenuScrollerView.HUGE_SCROLLER_THICKNESS);
111
+ break;
112
+ }
113
+
114
+ return sc_super();
115
+ },
116
+
117
+ /** @private */
118
+ mouseEntered: function(evt) {
119
+ this.set('isMouseOver', YES);
120
+ this._invokeScrollOnMouseOver();
121
+ },
122
+
123
+ /** @private */
124
+ mouseExited: function(evt) {
125
+ this.set('isMouseOver', NO);
126
+ },
127
+
128
+ mouseWheel: function (evt) {
129
+ var el = this.getPath('parentView.containerView.layer'),
130
+ rawEvent = evt.originalEvent;
131
+
132
+ if (el && rawEvent) {
133
+ try {
134
+ if (SC.typeOf(el.fireEvent) === SC.T_FUNCTION) { // IE
135
+ el.fireEvent(rawEvent.type, rawEvent);
136
+ } else { // W3C
137
+ el.dispatchEvent(rawEvent);
138
+ }
139
+ } catch (x) {
140
+ // Can't dispatch the event; give up.
141
+ }
142
+ }
143
+ },
144
+
145
+ /** @private */
146
+ _sc_scroller_armScrollTimer: function() {
147
+ if (!this._sc_scrollTimer) {
148
+ SC.RunLoop.begin();
149
+ var method = this._sc_scroller_scrollDidChange;
150
+ this._sc_scrollTimer = this.invokeLater(method, 50);
151
+ SC.RunLoop.end();
152
+ }
153
+ },
154
+
155
+ /** @private */
156
+ _sc_scroller_scrollDidChange: function() {
157
+ var now = (new Date()).getTime(),
158
+ last = this._sc_lastScroll,
159
+ layer = this.get('layer'),
160
+ scroll = 0;
161
+
162
+ if (last && (now - last) < 50) {
163
+ this._sc_scroller_armScrollTimer();
164
+
165
+ } else {
166
+ this._sc_scrollTimer = null;
167
+ this._sc_lastScroll = now;
168
+
169
+ SC.RunLoop.begin();
170
+ if (!this.get('isEnabled')) {
171
+ this._sc_scrollValue = scroll = layer.scrollTop;
172
+ this.set('value', scroll); // will now enforce minimum and maximum
173
+ }
174
+ SC.RunLoop.end();
175
+ }
176
+ },
177
+
178
+ /** @private
179
+ Scroll the menu if it is is an up or down arrow. This is called by
180
+ the function that simulates mouseOver.
181
+ */
182
+ _scrollMenu: function(){
183
+ var val = this.get('value'),
184
+ lineScroll = this.getPath('parentView.verticalLineScroll'),
185
+ newval;
186
+
187
+ if (this.get('scrollDown')) {
188
+ newval = val + lineScroll;
189
+ if (newval <= this.get('maximum')) {
190
+ this.set('value', newval);
191
+ }
192
+ } else {
193
+ newval = val - lineScroll;
194
+ if (newval >= 0) {
195
+ this.set('value', newval);
196
+ } else if (val <= this.verticalLineScroll && val > 0) {
197
+ this.set('value', 0);
198
+ }
199
+ }
200
+ return YES;
201
+ },
202
+
203
+ /** @private
204
+
205
+ We use this function to simulate mouseOver. It checks for the flag
206
+ isMouseOver which is turned on when mouseEntered is called and turned off
207
+ when mouseExited is called.
208
+ */
209
+ _invokeScrollOnMouseOver: function(){
210
+ this._scrollMenu();
211
+ if (this.get('isMouseOver')) {
212
+ this.invokeLater(this._invokeScrollOnMouseOver, 100);
213
+ }
214
+ }
215
+ });
216
+
217
+ /**
218
+ @static
219
+ @type Number
220
+ @default 18
221
+ */
222
+ SC.MenuScrollerView.REGULAR_SCROLLER_THICKNESS = 18;
223
+
224
+ /**
225
+ @static
226
+ @type Number
227
+ @default 10
228
+ */
229
+ SC.MenuScrollerView.TINY_SCROLLER_THICKNESS = 10;
230
+
231
+ /**
232
+ @static
233
+ @type Number
234
+ @default 14
235
+ */
236
+ SC.MenuScrollerView.SMALL_SCROLLER_THICKNESS = 14;
237
+
238
+ /**
239
+ @static
240
+ @type Number
241
+ @default 23
242
+ */
243
+ SC.MenuScrollerView.LARGE_SCROLLER_THICKNESS = 23;
244
+
245
+ /**
246
+ @static
247
+ @type Number
248
+ @default 26
249
+ */
250
+ SC.MenuScrollerView.HUGE_SCROLLER_THICKNESS = 26;
@@ -0,0 +1,92 @@
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
+
9
+ SC.BaseTheme.desktopScrollerRenderDelegate = SC.RenderDelegate.create({
10
+ className: 'desktop-scroller',
11
+
12
+ render: function (dataSource, context) {
13
+ var layoutDirection = dataSource.get('layoutDirection'),
14
+ isVertical = layoutDirection === SC.LAYOUT_VERTICAL,
15
+ isHorizontal = layoutDirection === SC.LAYOUT_HORIZONTAL;
16
+
17
+ context.setClass({
18
+ 'sc-vertical': isVertical,
19
+ 'sc-horizontal': isHorizontal,
20
+ disabled: !dataSource.get('isEnabled'),
21
+ 'controls-hidden': dataSource.get('controlsHidden')
22
+ });
23
+
24
+ context.push(
25
+ '<div class="track"></div>',
26
+ '<div class="cap"></div>',
27
+ dataSource.get('hasButtons') ?
28
+ '<div class="button-bottom"></div><div class="button-top"></div>' :
29
+ '<div class="endcap"></div>',
30
+ ('<div class="thumb" style="%@:' + dataSource.get('thumbLength') + 'px;' +
31
+ 'top:' + dataSource.get('thumbPosition') + 'px;">').
32
+ fmt(isVertical ? 'height' : 'width'),
33
+ '<div class="thumb-center"></div>',
34
+ '<div class="thumb-top"></div>',
35
+ '<div class="thumb-bottom"></div>',
36
+ '</div>');
37
+
38
+
39
+ context.attr('aria-orientation',
40
+ (layoutDirection === SC.LAYOUT_VERTICAL) ? 'vertical' : 'horizontal');
41
+ context.attr('aria-valuemax', dataSource.get('maximum'));
42
+ context.attr('aria-valuemin', dataSource.get('minimum'));
43
+ context.attr('aria-valuenow', dataSource.get('value'));
44
+ context.attr('aria-controls', dataSource.get('controlsId'));
45
+ },
46
+
47
+ update: function (dataSource, context) {
48
+ var layoutDirection = dataSource.get('layoutDirection'),
49
+ isVertical = layoutDirection === SC.LAYOUT_VERTICAL,
50
+ isHorizontal = layoutDirection === SC.LAYOUT_HORIZONTAL,
51
+ controlsAreHidden = dataSource.get('controlsHidden'),
52
+ thumb, K = 'desktopScrollerRenderDelegate';
53
+
54
+ context.setClass({
55
+ 'sc-vertical': isVertical,
56
+ 'sc-horizontal': isHorizontal,
57
+ disabled: !dataSource.get('isEnabled'),
58
+ 'controls-hidden': controlsAreHidden
59
+ });
60
+
61
+ if (dataSource.didChangeFor(K, 'maximum')) {
62
+ context.attr('aria-valuemax', dataSource.get('maximum'));
63
+ }
64
+
65
+ if (dataSource.didChangeFor(K, 'minimum')) {
66
+ context.attr('aria-valuemin', dataSource.get('minimum'));
67
+ }
68
+
69
+ if (dataSource.didChangeFor(K, 'value')) {
70
+ context.attr('aria-valuenow', dataSource.get('value'));
71
+ }
72
+
73
+ if (dataSource.didChangeFor(K, 'controlsId')) {
74
+ context.attr('aria-controls', dataSource.get('controlsId'));
75
+ }
76
+
77
+ // Don't bother if the controls are hidden.
78
+ if (!controlsAreHidden) {
79
+ thumb = context.find('.thumb');
80
+
81
+ if (dataSource.didChangeFor(K, 'thumbPosition')) {
82
+ thumb.css(layoutDirection === SC.LAYOUT_VERTICAL ?
83
+ 'top' : 'left', dataSource.get('thumbPosition'));
84
+ }
85
+
86
+ if (dataSource.didChangeFor(K, 'thumbLength')) {
87
+ thumb.css(layoutDirection === SC.LAYOUT_VERTICAL ?
88
+ 'height' : 'width', dataSource.get('thumbLength'));
89
+ }
90
+ }
91
+ }
92
+ });