sproutcore 1.11.0.rc2 → 1.11.0.rc3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. checksums.yaml +8 -8
  2. data/CHANGELOG +10 -0
  3. data/VERSION.yml +1 -1
  4. data/lib/frameworks/sproutcore/CHANGELOG.md +114 -1
  5. data/lib/frameworks/sproutcore/apps/showcase/views/views_item_view.js +1 -7
  6. data/lib/frameworks/sproutcore/apps/showcase/views/views_list_view.js +9 -9
  7. data/lib/frameworks/sproutcore/frameworks/ajax/system/request.js +167 -5
  8. data/lib/frameworks/sproutcore/frameworks/ajax/system/response.js +24 -8
  9. data/lib/frameworks/sproutcore/frameworks/core_foundation/child_view_layouts/stack_layout.js +737 -0
  10. data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/layout.js +0 -6
  11. data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/pane.js +11 -7
  12. data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/pane_statechart.js +7 -11
  13. data/lib/frameworks/sproutcore/frameworks/core_foundation/protocols/child_view_layout_protocol.js +8 -3
  14. data/lib/frameworks/sproutcore/frameworks/core_foundation/protocols/observable_protocol.js +9 -6
  15. data/lib/frameworks/sproutcore/frameworks/{desktop/protocols/responder.js → core_foundation/protocols/responder_protocol.js} +83 -17
  16. data/lib/frameworks/sproutcore/frameworks/core_foundation/protocols/{sparse_array_delegate.js → sparse_array_delegate_protocol.js} +11 -7
  17. data/lib/frameworks/sproutcore/frameworks/core_foundation/protocols/view_transition_protocol.js +11 -6
  18. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/color.js +2 -2
  19. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/page.js +0 -22
  20. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/root_responder.js +61 -56
  21. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/main_pane.js +2 -2
  22. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/pane/append_remove.js +3 -3
  23. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/animation.js +63 -39
  24. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/border_frame_test.js +28 -28
  25. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/createLayer.js +10 -4
  26. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layout.js +102 -1
  27. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layoutDidChange.js +4 -4
  28. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layoutStyle.js +103 -103
  29. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/replaceAllChildren_test.js +1 -1
  30. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/view.js +77 -1
  31. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/view_states_test.js +18 -17
  32. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view.js +42 -49
  33. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/animation.js +5 -6
  34. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/enabled.js +16 -5
  35. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/layout.js +241 -102
  36. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/layout_style.js +1 -4
  37. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/manipulation.js +0 -11
  38. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/statechart.js +993 -610
  39. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/theming.js +3 -2
  40. data/lib/frameworks/sproutcore/frameworks/datastore/data_sources/data_source.js +6 -11
  41. data/lib/frameworks/sproutcore/frameworks/datastore/system/nested_store.js +94 -27
  42. data/lib/frameworks/sproutcore/frameworks/datastore/system/query.js +133 -53
  43. data/lib/frameworks/sproutcore/frameworks/datastore/system/store.js +30 -35
  44. data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/record/writeAttribute.js +3 -2
  45. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/writeDataHash.js +73 -29
  46. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/store/conflictedStoreKeys_test.js +156 -0
  47. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/store/dataSourceCallbacks.js +61 -37
  48. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/store/find.js +2 -2
  49. data/lib/frameworks/sproutcore/frameworks/datetime/frameworks/core/system/datetime.js +68 -39
  50. data/lib/frameworks/sproutcore/frameworks/designer/tests/coders/page.js +1 -2
  51. data/lib/frameworks/sproutcore/frameworks/desktop/panes/panel.js +8 -6
  52. data/lib/frameworks/sproutcore/frameworks/desktop/panes/picker.js +80 -14
  53. data/lib/frameworks/sproutcore/frameworks/desktop/panes/sheet.js +2 -2
  54. data/lib/frameworks/sproutcore/frameworks/desktop/protocols/{drag_data_source.js → drag_data_source_protocol.js} +16 -10
  55. data/lib/frameworks/sproutcore/frameworks/desktop/protocols/{drag_source.js → drag_source_protocol.js} +28 -26
  56. data/lib/frameworks/sproutcore/frameworks/desktop/protocols/{drop_target.js → drop_target_protocol.js} +73 -75
  57. data/lib/frameworks/sproutcore/frameworks/desktop/system/drag.js +4 -4
  58. data/lib/frameworks/sproutcore/frameworks/desktop/tests/panes/panel/ui.js +39 -23
  59. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/collection/mouse.js +120 -97
  60. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/list/rowSizeForContentIndex.js +26 -25
  61. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/scroll/ui.js +3 -3
  62. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/segmented/ui.js +5 -0
  63. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/split/{dividers.js → dividers_test.js} +38 -38
  64. data/lib/frameworks/sproutcore/frameworks/desktop/views/collection.js +29 -14
  65. data/lib/frameworks/sproutcore/frameworks/desktop/views/menu_scroll.js +2 -1
  66. data/lib/frameworks/sproutcore/frameworks/desktop/views/scroll_view.js +13 -18
  67. data/lib/frameworks/sproutcore/frameworks/desktop/views/segmented.js +41 -35
  68. data/lib/frameworks/sproutcore/frameworks/desktop/views/slider.js +14 -14
  69. data/lib/frameworks/sproutcore/frameworks/desktop/views/split.js +41 -26
  70. data/lib/frameworks/sproutcore/frameworks/desktop/views/static_content.js +2 -12
  71. data/lib/frameworks/sproutcore/frameworks/foundation/gestures/tap.js +2 -2
  72. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/auto_resize.js +14 -10
  73. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/gesturable.js +104 -63
  74. data/lib/frameworks/sproutcore/frameworks/foundation/protocols/swap_transition_protocol.js +9 -4
  75. data/lib/frameworks/sproutcore/frameworks/foundation/tests/mixins/auto_mixin_tests.js +1 -2
  76. data/lib/frameworks/sproutcore/frameworks/foundation/tests/mixins/auto_resize_test.js +33 -33
  77. data/lib/frameworks/sproutcore/frameworks/foundation/tests/transitions/view_transitions_test.js +5 -5
  78. data/lib/frameworks/sproutcore/frameworks/foundation/tests/views/container/methods.js +0 -4
  79. data/lib/frameworks/sproutcore/frameworks/foundation/tests/views/container/transition_test.js +0 -4
  80. data/lib/frameworks/sproutcore/frameworks/foundation/tests/views/container/ui.js +0 -2
  81. data/lib/frameworks/sproutcore/frameworks/foundation/views/text_field.js +12 -8
  82. data/lib/frameworks/sproutcore/frameworks/media/resources/silence.mp3 +0 -0
  83. data/lib/frameworks/sproutcore/frameworks/media/tests/audio.js +69 -0
  84. data/lib/frameworks/sproutcore/frameworks/media/views/audio.js +1 -0
  85. data/lib/frameworks/sproutcore/frameworks/runtime/core.js +2 -2
  86. data/lib/frameworks/sproutcore/frameworks/runtime/mixins/observable.js +11 -4
  87. data/lib/frameworks/sproutcore/frameworks/runtime/protocols/mixin_protocol.js +150 -0
  88. data/lib/frameworks/sproutcore/frameworks/runtime/system/binding.js +447 -137
  89. data/lib/frameworks/sproutcore/frameworks/runtime/system/object.js +9 -15
  90. data/lib/frameworks/sproutcore/frameworks/runtime/system/set.js +19 -17
  91. data/lib/frameworks/sproutcore/frameworks/runtime/tests/system/binding.js +188 -16
  92. data/lib/frameworks/sproutcore/frameworks/statechart/system/state.js +1 -1
  93. data/lib/frameworks/sproutcore/frameworks/template_view/panes/template.js +0 -3
  94. data/lib/frameworks/sproutcore/frameworks/template_view/tests/panes/template.js +0 -17
  95. data/lib/frameworks/sproutcore/frameworks/template_view/tests/views/template/collection.js +43 -26
  96. data/lib/frameworks/sproutcore/frameworks/template_view/views/bindable_span.js +9 -2
  97. data/lib/frameworks/sproutcore/themes/ace/resources/collection/normal/list.css +0 -1
  98. data/lib/frameworks/sproutcore/themes/ace/resources/scroll/scroll.css +3 -0
  99. data/sproutcore.gemspec +3 -3
  100. metadata +19 -17
  101. data/lib/frameworks/sproutcore/frameworks/core_foundation/child_view_layouts/horizontal_stack_layout.js +0 -465
  102. data/lib/frameworks/sproutcore/frameworks/core_foundation/child_view_layouts/vertical_stack_layout.js +0 -472
  103. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/build.js +0 -87
  104. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/build_children.js +0 -89
@@ -0,0 +1,737 @@
1
+ // ==========================================================================
2
+ // Project: SproutCore
3
+ // Copyright: @2013 7x7 Software, Inc.
4
+ // License: Licensed under MIT license (see license.js)
5
+ // ==========================================================================
6
+ sc_require('views/view');
7
+
8
+ /** @private Shared stack plugin (may be horizontal or vertical). */
9
+ function _SC_VIEW_STACK_PLUGIN (direction) {
10
+ this.direction = direction;
11
+ }
12
+
13
+ /** @private Properties to observe on child views that affect the overall child view layout. */
14
+ _SC_VIEW_STACK_PLUGIN.prototype.childLayoutProperties = ['marginBefore', 'marginAfter', 'isVisible'];
15
+
16
+ /** @private When resizeToFit is false, then we need to know when the view's frame changes. */
17
+ _SC_VIEW_STACK_PLUGIN.prototype.layoutDependsOnSize = function (view) {
18
+ var options = view.get('childViewLayoutOptions');
19
+
20
+ if (options) {
21
+ return SC.none(options.resizeToFit) ? false : !options.resizeToFit;
22
+ } else {
23
+ return false;
24
+ }
25
+ };
26
+
27
+ /** @private */
28
+ _SC_VIEW_STACK_PLUGIN.prototype.layoutChildViews = function (view) {
29
+ var childViews = view.get('childViews'),
30
+ options = view.get('childViewLayoutOptions') || {},
31
+ resizeToFit = SC.none(options.resizeToFit) ? true : options.resizeToFit,
32
+ lastMargin = 0, // Used to avoid adding spacing to the final margin.
33
+ marginAfter = options.paddingBefore || 0,
34
+ paddingAfter = options.paddingAfter || 0,
35
+ firstPosition = 0,
36
+ provisionedSpace = 0,
37
+ autoFillAvailableSpace = 0,
38
+ totalAvailableSpace = 0,
39
+ totalFillAvailableSpaceRatio = 0,
40
+ spacing = options.spacing || 0,
41
+ sizeDimension = this.direction === 'vertical' ? 'height' : 'width',
42
+ minSizeDimension = this.direction === 'vertical' ? 'minHeight' : 'minWidth',
43
+ startDimension = this.direction === 'vertical' ? 'top' : 'left',
44
+ childView,
45
+ fillRatio,
46
+ layout,
47
+ marginBefore,
48
+ i, len;
49
+
50
+ // if the view is not configured to resize to fit content, then we give a chance to the children to fill the available space
51
+ // we make a 1st pass to check the conditions, to evaluate the available space and the proportions between children
52
+ if (!resizeToFit) {
53
+
54
+ totalAvailableSpace = view.get('frame')[sizeDimension];
55
+
56
+ // if the view is not configured to resize and it doesn't have yet a height/width, it doesn't make sense to layout children
57
+ if (!totalAvailableSpace) {
58
+ return;
59
+ }
60
+
61
+ for (i = 0, len = childViews.get('length'); i < len; i++) {
62
+ childView = childViews.objectAt(i);
63
+
64
+ // Ignore child views with useAbsoluteLayout true, useStaticLayout true or that are not visible.
65
+ if (!childView.get('isVisible') ||
66
+ childView.get('useAbsoluteLayout') ||
67
+ childView.get('useStaticLayout')) {
68
+ continue;
69
+ }
70
+
71
+ layout = childView.get('layout');
72
+
73
+ // Determine the top/left margin.
74
+ marginBefore = childView.get('marginBefore') || 0;
75
+ provisionedSpace += Math.max(marginAfter, marginBefore);
76
+
77
+ // if the height/width is not set, let's check if is possible to resize the view
78
+ if (SC.none(layout[sizeDimension])) {
79
+ fillRatio = childView.get('fillRatio');
80
+
81
+ if (!SC.none(fillRatio)) {
82
+ totalFillAvailableSpaceRatio += fillRatio;
83
+ } else {
84
+ // if none of the child views has fillRatio defined, allow the last one to stretch and fill the available space.
85
+ if (i === len - 1 && totalFillAvailableSpaceRatio === 0) {
86
+ totalFillAvailableSpaceRatio = 1;
87
+ }
88
+ //@if(debug)
89
+ // Add some developer support.
90
+ else {
91
+ // even if we don't have a height/width set, as last instance we accept the presence of minHeight/minWidth
92
+ if (SC.none(layout[minSizeDimension]))
93
+ {
94
+ if (this.direction === 'vertical') {
95
+ SC.warn('Developer Warning: The SC.View.VERTICAL_STACK plugin requires that each childView layout contains at least a height or has a configured fillRatio. The layout may also optionally contain left and right, left and width, right and width or centerX and width. The childView %@ has an invalid layout/fillRatio: %@'.fmt(childView, SC.stringFromLayout(layout)));
96
+ } else {
97
+ SC.warn('Developer Warning: The SC.View.HORIZONTAL_STACK plugin requires that each childView layout contains at least a width or has a configured fillRatio. The layout may also optionally contain top and bottom, top and height, bottom and height or centerY and height. The childView %@ has an invalid layout/fillRatio: %@'.fmt(childView, SC.stringFromLayout(layout)));
98
+ }
99
+ return;
100
+ }
101
+ }
102
+ //@endif
103
+ }
104
+ } else {
105
+ provisionedSpace += childView.get('borderFrame')[sizeDimension];
106
+ }
107
+
108
+ // Determine the bottom/right margin.
109
+ lastMargin = childView.get('marginAfter') || 0;
110
+ marginAfter = lastMargin || spacing;
111
+ }
112
+
113
+ // consider the end padding when calculating the provisionedSpace
114
+ if (provisionedSpace !== 0 || totalFillAvailableSpaceRatio !== 0) {
115
+ provisionedSpace += Math.max(lastMargin, paddingAfter);
116
+ }
117
+
118
+ autoFillAvailableSpace = Math.max(0, totalAvailableSpace - provisionedSpace);
119
+ }
120
+
121
+ // reset the references for the effective layout
122
+ lastMargin = 0;
123
+ marginAfter = options.paddingBefore || 0;
124
+ paddingAfter = options.paddingAfter || 0;
125
+
126
+ for (i = 0, len = childViews.get('length'); i < len; i++) {
127
+ var size,
128
+ adjustStart,
129
+ adjustEnd;
130
+
131
+ childView = childViews.objectAt(i);
132
+
133
+ // Ignore child views with useAbsoluteLayout true, useStaticLayout true or that are not visible.
134
+ if (!childView.get('isVisible') ||
135
+ childView.get('useAbsoluteLayout') ||
136
+ childView.get('useStaticLayout')) {
137
+ continue;
138
+ }
139
+
140
+ layout = childView.get('layout');
141
+
142
+ //@if(debug)
143
+ // Add some developer support. The case of !resizeToFit was already checked above
144
+ if (resizeToFit && SC.none(layout[sizeDimension]) && SC.none(layout[minSizeDimension])) {
145
+ if (this.direction === 'vertical') {
146
+ SC.warn('Developer Warning: The SC.View.VERTICAL_STACK plugin, when configured with resizeToFit, requires that each childView layout contains at least a height/minHeight and optionally also left and right, left and width, right and width or centerX and width. The childView %@ has an invalid layout: %@'.fmt(childView, SC.stringFromLayout(layout)));
147
+ } else {
148
+ SC.warn('Developer Warning: The SC.View.HORIZONTAL_STACK plugin, when configured with resizeToFit, requires that each childView layout contains at least a width/minWidth and optionally also top and bottom, top and height, bottom and height or centerY and height. The childView %@ has an invalid layout: %@'.fmt(childView, SC.stringFromLayout(layout)));
149
+ }
150
+ return;
151
+ }
152
+ //@endif
153
+
154
+ // Determine the top/left margin.
155
+ marginBefore = childView.get('marginBefore') || 0;
156
+ firstPosition += Math.max(marginAfter, marginBefore);
157
+
158
+ // Try to avoid useless adjustments to top/left or bottom/right or top/left then bottom/right.
159
+ // The required adjustments will be merged into a single call
160
+ adjustStart = layout[startDimension] !== firstPosition;
161
+
162
+ childView.beginPropertyChanges();
163
+ if (!resizeToFit && !layout[sizeDimension]) {
164
+ var endDimension = this.direction === 'vertical' ? 'bottom' : 'right',
165
+ endPosition;
166
+
167
+ fillRatio = childView.get('fillRatio');
168
+
169
+ // if the last child doesn't define fillRatio, default it to 1 as above during the 1st pass
170
+ if (i === len - 1 && SC.none(fillRatio)) {
171
+ fillRatio = 1;
172
+ }
173
+
174
+ // we should get here only in two cases: 1. child defines fillRatio, 2. child defines a minHeight
175
+ // if both defined, we prefer to handle fillRatio, the other case being handled below by the normal adjustment to top/left
176
+ if (!SC.none(fillRatio)) {
177
+ var currentAvailableSpaceRatio = (fillRatio / totalFillAvailableSpaceRatio);
178
+
179
+ // calculate the height/width according to fillRatio and totalFillAvailableSpaceRatio
180
+ // but set the bottom/right position so any subsequent layout is not considering the height/width as fixed
181
+ size = Math.ceil(autoFillAvailableSpace * currentAvailableSpaceRatio);
182
+
183
+ // INCOMPLETE: We need to flag this view as constrained and re-compute all the auto-fill amounts
184
+ // Constrain the height/width to the maximum height/width allowed.
185
+ // var maxHeight = layout.maxHeight;
186
+ // if (!SC.none(maxHeight)) {
187
+ // // Constrain the height/width according to maxHeight/maxWidth. Which frees up additional available space for further child views.
188
+ // if (size > maxSize) {
189
+ // size = maxSize;
190
+ // }
191
+ // }
192
+
193
+ // Determine the bottom/right position. If the position overflows (i.e. goes negative) because of rounding up, stop at 0.
194
+ endPosition = Math.max(0, totalAvailableSpace - firstPosition - size);
195
+ adjustEnd = layout[endDimension] !== endPosition;
196
+
197
+ if (adjustEnd) {
198
+ childView.adjust(endDimension, endPosition);
199
+ }
200
+ }
201
+ }
202
+
203
+ if (adjustStart) {
204
+ childView.adjust(startDimension, firstPosition);
205
+ }
206
+ childView.endPropertyChanges();
207
+
208
+ firstPosition += childView.get('borderFrame')[sizeDimension];
209
+
210
+ // Determine the bottom/right margin.
211
+ lastMargin = childView.get('marginAfter') || 0;
212
+ marginAfter = lastMargin || spacing;
213
+ }
214
+
215
+ // If the current size is 0 (all children are hidden), it doesn't make sense to add the padding
216
+ if (firstPosition !== 0) {
217
+ firstPosition += Math.max(lastMargin, paddingAfter);
218
+ }
219
+
220
+ // Adjust our frame to fit as well, this ensures that scrolling works.
221
+ if (resizeToFit && view.get('layout')[sizeDimension] !== firstPosition) {
222
+ view.adjust(sizeDimension, firstPosition);
223
+ }
224
+ };
225
+
226
+
227
+ SC.mixin(SC.View,
228
+ /** @scope SC.View */ {
229
+
230
+ /**
231
+ This child layout plugin automatically positions the view's child views in a
232
+ horizontal stack and optionally adjusts the view's width to fit. It does this
233
+ by checking the width of each child view and positioning the following child
234
+ views accordingly. Afterwards, by default, any time that a child view's
235
+ width or visibility changes, the view will use this plugin to re-adjust all
236
+ following child views' positions and potentially its own width appropriately.
237
+
238
+ This allows you to stack absolutely positioned views that dynamically change
239
+ their width and/or visibility without having to resort to using browser
240
+ flow layout.
241
+
242
+ For example,
243
+
244
+ MyApp.MyView = SC.View.extend({
245
+
246
+ // Child views will be stacked in order horizontally.
247
+ childViewLayout: SC.View.HORIZONTAL_STACK,
248
+
249
+ // The order of child views is important!
250
+ childViews: ['sectionA', 'sectionB', 'sectionC'],
251
+
252
+ // The view will resize itself to fit its children.
253
+ // i.e. We don't need to specify layout.width, this is automatic.
254
+ // The actual layout will become { left: 10, bottom: 20, top: 20, width: 270 } initially.
255
+ layout: { left: 10, bottom: 20, top: 20 },
256
+
257
+ sectionA: SC.View.design({
258
+
259
+ // We don't need to specify layout.left, this is automatic.
260
+ // The actual layout will become { left: 0, bottom: 0, top: 0, width: 100 } initially.
261
+ layout: { width: 100 }
262
+
263
+ }),
264
+
265
+ sectionB: SC.View.design({
266
+
267
+ // We don't need to specify layout.left, this is automatic.
268
+ // The actual layout will become { border: 1, left: 100, bottom: 0, top: 0, width: 50 } initially.
269
+ layout: { border: 1, width: 50 }
270
+
271
+ }),
272
+
273
+ sectionC: SC.View.design({
274
+
275
+ // We don't need to specify layout.left, this is automatic.
276
+ // The actual layout will become { left: 150, bottom: 10, top: 10, width: 120 } initially.
277
+ layout: { right: 10, top: 10, width: 120 }
278
+
279
+ })
280
+
281
+ });
282
+
283
+ ## Modify the default behavior with `childViewLayoutOptions`
284
+
285
+ To modify the plugin behavior for all child view layouts, you can set the
286
+ following child view layout options in `childViewLayoutOptions` on the view:
287
+
288
+ - paddingBefore - Adds padding before the first child view. Default: 0
289
+ - paddingAfter - Adds padding after the last child view. Default: 0
290
+ - spacing - Adds spacing between each child view. Default: 0
291
+ - resizeToFit - Whether to resize the view to fit the child views (requires that each child view has a layout width). Default: true
292
+
293
+ For example,
294
+
295
+ MyApp.MyView = SC.View.extend({
296
+
297
+ // Child views will be stacked in order horizontally.
298
+ childViewLayout: SC.View.HORIZONTAL_STACK,
299
+
300
+ // Change the behavior of the HORIZONTAL_STACK plugin
301
+ childViewLayoutOptions: {
302
+ paddingBefore: 10,
303
+ paddingAfter: 20,
304
+ spacing: 5
305
+ },
306
+
307
+ // The order of child views is important!
308
+ childViews: ['sectionA', 'sectionB', 'sectionC'],
309
+
310
+ // The view will resize itself to fit its children. The actual layout will become { left: 10, bottom: 20, top: 20, width: 310 }
311
+ layout: { left: 10, bottom: 20, top: 20 }, // Don't need to specify layout.width, this is automatic.
312
+
313
+ sectionA: SC.View.design({
314
+
315
+ // Actual layout will become { left: 10, bottom: 0, top: 0, width: 100 }
316
+ layout: { width: 100 } // Don't need to specify layout.left, this is automatic.
317
+
318
+ }),
319
+
320
+ sectionB: SC.View.design({
321
+
322
+ // Actual layout will become { border: 1, left: 115, bottom: 0, top: 0, width: 50 }
323
+ layout: { border: 1, width: 50 } // Don't need to specify layout.left, this is automatic.
324
+
325
+ }),
326
+
327
+ sectionC: SC.View.design({
328
+
329
+ // Actual layout will become { left: 170, top: 10, bottom: 10, width: 120 }
330
+ layout: { top: 10, bottom: 10, width: 120 } // Don't need to specify layout.left, this is automatic.
331
+
332
+ })
333
+
334
+ });
335
+
336
+ If `resizeToFit` is set to `false`, the view will not adjust itself to fit
337
+ its child views. This means that when `resizeToFit` is false, the view should
338
+ specify its width component in its layout. A direct effect of this is the
339
+ possibility for the child views to automatically expand or shrink in order to
340
+ fill the empty, unclaimed space of the view.
341
+
342
+ This available space is shared between all children that don't specify a fixed width
343
+ such that their final width is calculated proportionally to the value of the
344
+ property `fillRatio`.
345
+
346
+ For simplicity, when none of the children specifies `fillRatio`,
347
+ you can ignore the last child view's layout width and the last child view
348
+ will stretch to fill the parent view.
349
+
350
+ For example,
351
+
352
+ MyApp.MyView = SC.View.extend({
353
+
354
+ // Child views will be stacked in order horizontally.
355
+ childViewLayout: SC.View.HORIZONTAL_STACK,
356
+
357
+ // Change the behavior of the HORIZONTAL_STACK plugin
358
+ childViewLayoutOptions: {
359
+ paddingBefore: 10,
360
+ paddingAfter: 20,
361
+ spacing: 5,
362
+ resizeToFit: false // Setting this to false, so that the child views stretch/contract to fit the parent's size.
363
+ },
364
+
365
+ // The order of child views is important!
366
+ childViews: ['sectionA', 'sectionB', 'sectionC'],
367
+
368
+ // The parent view will not resize itself to fit its contents, so we specify the width.
369
+ layout: { left: 10, bottom: 20, top: 20, width: 500 },
370
+
371
+ sectionA: SC.View.design({
372
+
373
+ // We don't need to specify layout.left, this is automatic. This child will not stretch, its width is set.
374
+ // Actual layout will become { left: 10, bottom: 0, top: 0, width: 100 }
375
+ layout: { width: 100 }
376
+
377
+ }),
378
+
379
+ sectionB: SC.View.design({
380
+
381
+ // The unclaimed space so far is 500 - 10 - 100 - 5 - 5 - 20, or 360px. This space will be shared between
382
+ // the two last sections, because we won't specity a width on them.
383
+ // This view will get 1/3 of the available space, because the other flexibile view has a ratio of 2.
384
+ fillRatio: 1,
385
+
386
+ // This section will take 1/3 * 360px = 120px.
387
+ // Actual layout will become { border: 1, left: 115, bottom: 0, top: 0, right: 265 }, in other words, width == 120
388
+ // We don't need to specify layout.left, layout.right or layout.width, this is automatic.
389
+ layout: { border: 1 }
390
+
391
+ }),
392
+
393
+ sectionC: SC.View.design({
394
+
395
+ // This view will get 2/3 of the available space, because the other flexibile view has a ratio of 1.
396
+ fillRatio: 2,
397
+
398
+ // This section will take 2/3 * 360px = 240px.
399
+ // Actual layout will become { left: 240, top: 10, bottom: 10, right: 20 }, in other words, width == 240
400
+ // We don't need to specify layout.left, layout.right or layout.width, this is automatic.
401
+ layout: { top: 10, bottom: 10 }
402
+
403
+ })
404
+
405
+ });
406
+
407
+ ## Modify specific child view layouts
408
+
409
+ To adjust the child layout on a granular level per child view, you can
410
+ also set the following properties on each child view:
411
+
412
+ - marginBefore - Specify the minimum spacing above the child view.
413
+ - marginAfter - Specify the minimum spacing below the child view.
414
+ - useAbsoluteLayout - Don't include this child view in automatic layout, use absolute positioning based on the child view's `layout` property.
415
+ - useStaticLayout - Don't include this child view in automatic layout. This child view uses relative positioning and is not eligible for automatic layout.
416
+ - isVisible - Non-visible child views are not included in the stack.
417
+ - fillRatio - When the parent view is configured with a fixed dimension, children not specifying a width but specifying fillRatio will be resized to fill the unclaimed space proportionally to this ratio.
418
+
419
+ For example,
420
+
421
+ MyApp.MyView = SC.View.extend({
422
+
423
+ // Child views will be stacked in order horizontally.
424
+ childViewLayout: SC.View.HORIZONTAL_STACK,
425
+
426
+ // Actual layout will become { left: 10, right: 10, top: 20, width: 570 }
427
+ layout: { left: 10, right: 10, top: 20 },
428
+
429
+ // Keep the child views ordered!
430
+ childViews: ['sectionA', 'float', 'sectionB', 'sectionC'],
431
+
432
+ sectionA: SC.View.design({
433
+ // Actual layout will become { left: 0, right: 50, top: 0, width: 100 }
434
+ layout: { right: 50, width: 100 },
435
+ // The following child view will be at least 50px further right.
436
+ marginAfter: 50
437
+ }),
438
+
439
+ float: SC.View.design({
440
+ // This view will not be included in automatic layout and will not effect the stack.
441
+ layout: { top: 5, right: 5, height: 50, width: 50 },
442
+ useAbsoluteLayout: true
443
+ }),
444
+
445
+ sectionB: SC.View.design({
446
+ // Actual layout will become { left: 1500, right: 0, top: 0, width: 120 }
447
+ layout: { width: 120 }
448
+ }),
449
+
450
+ sectionC: SC.View.design({
451
+ // Actual layout will become { left: 470, bottom: 0, top: 0, width: 100 }
452
+ layout: { width: 100 },
453
+ // This child view will be at least 200px to the right of the previous.
454
+ marginBefore: 200
455
+ })
456
+
457
+ });
458
+
459
+ ### A Note About Spacing
460
+
461
+ Note that the spacing attribute in `childViewLayoutOptions` becomes the
462
+ _minimum margin between child views, without explicitly overriding it from
463
+ both sides using `marginAfter` and `marginBefore`_. For example, if `spacing`
464
+ is 25, setting `marginAfter` to 10 on a child view will not result in the
465
+ next child view being 10px to the right of it, unless the next child view also
466
+ specified `marginBefore` as 10.
467
+
468
+ What this means is that it takes less configuration if you set `spacing` to
469
+ be the _smallest margin you wish to exist between child views_ and then use
470
+ the overrides to grow the margin if necessary. For example, if `spacing`
471
+ is 5, setting `marginAfter` to 10 on a child view will result in the next
472
+ child view being 10px to the right of it, without having to also specify
473
+ `marginBefore` on that next child view.
474
+
475
+ @extends SC.ChildViewLayoutProtocol
476
+ @since Version 1.10
477
+ */
478
+ HORIZONTAL_STACK: new _SC_VIEW_STACK_PLUGIN('horizontal'),
479
+
480
+ /**
481
+ This child layout plugin automatically positions the view's child views in a
482
+ vertical stack and optionally adjusts the view's height to fit. It does this
483
+ by checking the height of each child view and positioning the following child
484
+ view accordingly. Afterwards, by default, any time that a child view's
485
+ height or visibility changes, the view will use this plugin to re-adjust all
486
+ following child views' positions and potentially its own height appropriately.
487
+
488
+ This allows you to stack absolutely positioned views that dynamically change
489
+ their height and/or visibility without having to resort to using browser
490
+ flow layout.
491
+
492
+ A typical usage scenario is a long "form" made of multiple subsection
493
+ views. If we want to adjust the height of a subsection, to make space for
494
+ an error label for example, it would be a lot of work to manually
495
+ reposition all the following sections below it. A much easier to code and
496
+ cleaner solution is to just set the childViewLayout plugin on the wrapper
497
+ view.
498
+
499
+ For example,
500
+
501
+ MyApp.MyView = SC.View.extend({
502
+
503
+ // Child views will be stacked in order vertically.
504
+ childViewLayout: SC.View.VERTICAL_STACK,
505
+
506
+ // The order of child views is important!
507
+ childViews: ['sectionA', 'sectionB', 'sectionC'],
508
+
509
+ // The view will resize itself to fit its children.
510
+ // i.e. We don't need to specify layout.height, this is automatic.
511
+ // The actual layout will become { left: 10, right: 10, top: 20, height: 270 } initially.
512
+ layout: { left: 10, right: 10, top: 20 },
513
+
514
+ sectionA: SC.View.design({
515
+
516
+ // We don't need to specify layout.top, this is automatic.
517
+ // The actual layout will become { left: 0, right: 0, top: 0, height: 100 } initially.
518
+ layout: { height: 100 }
519
+
520
+ }),
521
+
522
+ sectionB: SC.View.design({
523
+
524
+ // We don't need to specify layout.top, this is automatic.
525
+ // The actual layout will become { border: 1, left: 0, right: 0, top: 100, height: 50 } initially.
526
+ layout: { border: 1, height: 50 }
527
+
528
+ }),
529
+
530
+ sectionC: SC.View.design({
531
+
532
+ // We don't need to specify layout.top, this is automatic.
533
+ // The actual layout will become { left: 10, right: 10, top: 150, height: 120 } initially.
534
+ layout: { left: 10, right: 10, height: 120 }
535
+
536
+ })
537
+
538
+ });
539
+
540
+ ## Modify the default behavior with `childViewLayoutOptions`
541
+
542
+ To modify the plugin behavior for all child view layouts, you can set the
543
+ following child view layout options in `childViewLayoutOptions` on the view:
544
+
545
+ - paddingBefore - Adds padding before the first child view. Default: 0
546
+ - paddingAfter - Adds padding after the last child view. Default: 0
547
+ - spacing - Adds spacing between each child view. Default: 0
548
+ - resizeToFit - Whether to resize the view to fit the child views (requires that each child view has a layout height). Default: true
549
+
550
+ For example,
551
+
552
+ MyApp.MyView = SC.View.extend({
553
+
554
+ // Child views will be stacked in order vertically.
555
+ childViewLayout: SC.View.VERTICAL_STACK,
556
+
557
+ // Change the behavior of the VERTICAL_STACK plugin
558
+ childViewLayoutOptions: {
559
+ paddingBefore: 10,
560
+ paddingAfter: 20,
561
+ spacing: 5
562
+ },
563
+
564
+ // The order of child views is important!
565
+ childViews: ['sectionA', 'sectionB', 'sectionC'],
566
+
567
+ // The actual layout will become { left: 10, right: 10, top: 20, height: 310 } initially.
568
+ layout: { left: 10, right: 10, top: 20 }, // Don't need to specify layout.height, this is automatic.
569
+
570
+ sectionA: SC.View.design({
571
+
572
+ // We don't need to specify layout.top, this is automatic.
573
+ // The actual layout will become { left: 0, right: 0, top: 10, height: 100 } initially.
574
+ layout: { height: 100 }
575
+
576
+ }),
577
+
578
+ sectionB: SC.View.design({
579
+
580
+ // We don't need to specify layout.top, this is automatic.
581
+ // The actual layout will become { border: 1, left: 0, right: 0, top: 115, height: 50 } initially.
582
+ layout: { border: 1, height: 50 }
583
+
584
+ }),
585
+
586
+ sectionC: SC.View.design({
587
+
588
+ // We don't need to specify layout.top, this is automatic.
589
+ // The actual layout will become { left: 10, right: 10, top: 170, height: 120 } initially.
590
+ layout: { left: 10, right: 10, height: 120 }
591
+
592
+ })
593
+
594
+ });
595
+
596
+ If `resizeToFit` is set to `false`, the view will not adjust itself to fit
597
+ its child views. This means that when `resizeToFit` is false, the view should
598
+ specify its height component in its layout. A direct effect is the possibility for
599
+ the child views to automatically extend or shrink in order to fill the empty, unclaimed space.
600
+ This available space is shared between the children not specifying a fixed height
601
+ and their final dimension is calculated proportionally to the value of the
602
+ property `fillRatio`.
603
+ For simplicity, when none of the children specifies `fillRatio`,
604
+ you can ignore the last child view's layout height if you want the last child view
605
+ to stretch to fill the parent view.
606
+
607
+ For example,
608
+
609
+ MyApp.MyView = SC.View.extend({
610
+
611
+ // Child views will be stacked in order vertically.
612
+ childViewLayout: SC.View.VERTICAL_STACK,
613
+
614
+ // Change the behavior of the VERTICAL_STACK plugin
615
+ childViewLayoutOptions: {
616
+ paddingBefore: 10,
617
+ paddingAfter: 20,
618
+ spacing: 5,
619
+ resizeToFit: false
620
+ },
621
+
622
+ // The order of child views is important!
623
+ childViews: ['sectionA', 'sectionB', 'sectionC'],
624
+
625
+ // Actual layout will become { left: 10, right: 10, top: 20, height: 500 }
626
+ layout: { left: 10, right: 10, top: 20, height: 500 }, // Need to specify layout.height.
627
+
628
+ sectionA: SC.View.design({
629
+
630
+ // We don't need to specify layout.top, this is automatic. This child will not stretch, its height is set.
631
+ // The actual layout will become { left: 0, right: 0, top: 10, height: 100 } initially.
632
+ layout: { height: 100 }
633
+
634
+ }),
635
+
636
+ sectionB: SC.View.design({
637
+
638
+ // The unclaimed space so far is 500 - 10 - 100 - 5 - 5 - 20, or 360px. This space will be shared between
639
+ // the two last sections, because we won't specity a height on them.
640
+ // This view will get 1/3 of the available space, because the other flexibile view has a ratio of 2.
641
+ fillRatio: 1,
642
+
643
+ // This section will take 1/3 * 360px = 120px.
644
+ // Actual layout will become { border: 1, left: 0, right: 0, top: 115, bottom: 265 }, in other words, height == 120
645
+ // We don't need to specify layout.top, layout.bottom or layout.height, this is automatic.
646
+ layout: { border: 1 }
647
+
648
+ }),
649
+
650
+ sectionC: SC.View.design({
651
+
652
+ // This view will get 2/3 of the available space, because the other flexibile view has a ratio of 1.
653
+ fillRatio: 2,
654
+
655
+ // This section will take 2/3 * 360px = 240px.
656
+ // Actual layout will become { left: 10, right: 10, top: 240, bottom: 20 }, in other words, height == 240
657
+ // We don't need to specify layout.top, layout.bottom or layout.height, this is automatic.
658
+ layout: { left: 10, right: 10 }
659
+
660
+ })
661
+
662
+ });
663
+
664
+ ## Modify specific child view layouts
665
+
666
+ To adjust the child layout on a granular level per child view, you can
667
+ also set the following properties on each child view:
668
+
669
+ - marginBefore - Specify the minimum spacing above the child view.
670
+ - marginAfter - Specify the minimum spacing below the child view.
671
+ - useAbsoluteLayout - Don't include this child view in automatic layout, use absolute positioning based on the child view's `layout` property.
672
+ - useStaticLayout - Don't include this child view in automatic layout. This child view uses relative positioning and is not eligible for automatic layout.
673
+ - isVisible - Non-visible child views are not included in the stack.
674
+ - fillRatio - When the parent view is configured with a fixed dimension, children not specifying a height but specifying fillRatio will be resized to fill the unclaimed space proportionally to this ratio.
675
+
676
+ For example,
677
+
678
+ MyApp.MyView = SC.View.extend({
679
+
680
+ // Child views will be stacked in order vertically.
681
+ childViewLayout: SC.View.VERTICAL_STACK,
682
+
683
+ // Actual layout will become { left: 10, right: 10, top: 20, height: 570 }
684
+ layout: { left: 10, right: 10, top: 20 },
685
+
686
+ // Keep the child views ordered!
687
+ childViews: ['sectionA', 'float', 'sectionB', 'sectionC'],
688
+
689
+ sectionA: SC.View.design({
690
+ // Actual layout will become { left: 0, right: 50, top: 0, height: 100 }
691
+ layout: { right: 50, height: 100 },
692
+ // The following child view will be at least 50px further down.
693
+ marginAfter: 50
694
+ }),
695
+
696
+ float: SC.View.design({
697
+ // This view will not be included in automatic layout and will not effect the stack.
698
+ layout: { top: 5, right: 5, width: 50, height: 50 },
699
+ useAbsoluteLayout: true
700
+ }),
701
+
702
+ sectionB: SC.View.design({
703
+ // Actual layout will become { left: 0, right: 0, top: 150, height: 120 }
704
+ layout: { height: 120 }
705
+ }),
706
+
707
+ sectionC: SC.View.design({
708
+ // Actual layout will become { left: 0, bottom: 0, top: 470, height: 100 }
709
+ layout: { height: 100 },
710
+ // This child view will be at least 200px below the previous.
711
+ marginBefore: 200
712
+ })
713
+
714
+ });
715
+
716
+ ### A Note About Spacing
717
+
718
+ Note that the spacing attribute in `childViewLayoutOptions` becomes the
719
+ _minimum margin between child views, without explicitly overriding it from
720
+ both sides using `marginAfter` and `marginBefore`_. For example, if `spacing`
721
+ is 25, setting `marginAfter` to 10 on a child view will not result in the
722
+ next child view being 10px below it, unless the next child view also
723
+ specified `marginBefore` as 10.
724
+
725
+ What this means is that it takes less configuration if you set `spacing` to
726
+ be the _smallest margin you wish to exist between child views_ and then use
727
+ the overrides to grow the margin if necessary. For example, if `spacing`
728
+ is 5, setting `marginAfter` to 10 on a child view will result in the next
729
+ child view being 10px below it, without having to also specify `marginBefore`
730
+ on that next child view.
731
+
732
+ @extends SC.ChildViewLayoutProtocol
733
+ @since Version 1.10
734
+ */
735
+ VERTICAL_STACK: new _SC_VIEW_STACK_PLUGIN('vertical')
736
+
737
+ });