sproutcore 0.9.1 → 0.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (208) hide show
  1. data/History.txt +233 -0
  2. data/Manifest.txt +67 -34
  3. data/bin/sc-build +12 -1
  4. data/bin/sc-gen +1 -1
  5. data/bin/sproutcore +14 -0
  6. data/clients/sc_docs/controllers/docs.js +38 -8
  7. data/clients/sc_docs/english.lproj/body.css +80 -127
  8. data/clients/sc_docs/english.lproj/body.rhtml +43 -23
  9. data/clients/sc_docs/english.lproj/no_docs.rhtml +2 -1
  10. data/clients/sc_docs/english.lproj/tabs.rhtml +16 -0
  11. data/clients/sc_docs/main.js +14 -9
  12. data/clients/sc_docs/models/doc.js +1 -1
  13. data/clients/sc_docs/tests/controllers/docs.rhtml +1 -2
  14. data/clients/sc_docs/tests/models/doc.rhtml +1 -2
  15. data/clients/sc_docs/tests/views/doc_frame.rhtml +1 -2
  16. data/clients/sc_docs/tests/views/doc_label_view.rhtml +1 -2
  17. data/clients/sc_docs/views/doc_frame.js +1 -1
  18. data/clients/sc_test_runner/controllers/runner.js +31 -8
  19. data/clients/sc_test_runner/english.lproj/body.css +62 -122
  20. data/clients/sc_test_runner/english.lproj/body.rhtml +62 -26
  21. data/clients/sc_test_runner/main.js +1 -6
  22. data/clients/sc_test_runner/models/test.js +14 -1
  23. data/clients/sc_test_runner/views/runner_frame.js +4 -2
  24. data/clients/view_builder/builders/builder.js +339 -0
  25. data/clients/view_builder/builders/button.js +81 -0
  26. data/clients/view_builder/controllers/document.js +21 -0
  27. data/clients/view_builder/core.js +19 -0
  28. data/clients/view_builder/english.lproj/body.css +77 -0
  29. data/clients/view_builder/english.lproj/body.rhtml +41 -0
  30. data/clients/{sc_docs → view_builder}/english.lproj/controls.css +0 -0
  31. data/clients/view_builder/english.lproj/strings.js +14 -0
  32. data/clients/view_builder/main.js +38 -0
  33. data/clients/view_builder/tests/controllers/document.rhtml +20 -0
  34. data/clients/view_builder/tests/views/builder.rhtml +20 -0
  35. data/clients/view_builder/views/builder.js +23 -0
  36. data/frameworks/prototype/prototype.js +1 -1
  37. data/frameworks/sproutcore/Core.js +32 -7
  38. data/frameworks/sproutcore/README +1 -1
  39. data/frameworks/sproutcore/animation/animation.js +411 -0
  40. data/frameworks/sproutcore/controllers/array.js +17 -9
  41. data/frameworks/sproutcore/controllers/collection.js +9 -110
  42. data/frameworks/sproutcore/controllers/controller.js +1 -1
  43. data/frameworks/sproutcore/controllers/object.js +2 -1
  44. data/frameworks/sproutcore/drag/drag.js +267 -56
  45. data/frameworks/sproutcore/drag/drag_data_source.js +24 -16
  46. data/frameworks/sproutcore/drag/drag_source.js +53 -42
  47. data/frameworks/sproutcore/drag/drop_target.js +2 -2
  48. data/frameworks/sproutcore/english.lproj/buttons.css +337 -236
  49. data/frameworks/sproutcore/english.lproj/core.css +115 -0
  50. data/frameworks/sproutcore/english.lproj/icons.css +227 -0
  51. data/{clients/sc_docs → frameworks/sproutcore}/english.lproj/images/indicator.gif +0 -0
  52. data/frameworks/sproutcore/english.lproj/images/sc-theme-sprite.png +0 -0
  53. data/frameworks/sproutcore/english.lproj/images/sc-theme-ysprite.png +0 -0
  54. data/frameworks/sproutcore/english.lproj/images/shared-icons.png +0 -0
  55. data/frameworks/sproutcore/english.lproj/menu.css +1 -1
  56. data/frameworks/sproutcore/english.lproj/strings.js +1 -1
  57. data/frameworks/sproutcore/english.lproj/theme.css +405 -31
  58. data/frameworks/sproutcore/foundation/application.js +15 -11
  59. data/frameworks/sproutcore/foundation/benchmark.js +1 -1
  60. data/frameworks/sproutcore/foundation/binding.js +2 -2
  61. data/frameworks/sproutcore/foundation/date.js +1 -1
  62. data/frameworks/sproutcore/foundation/error.js +1 -1
  63. data/frameworks/sproutcore/foundation/input_manager.js +32 -21
  64. data/frameworks/sproutcore/foundation/mock.js +1 -1
  65. data/frameworks/sproutcore/foundation/node_descriptor.js +9 -6
  66. data/frameworks/sproutcore/foundation/object.js +249 -177
  67. data/frameworks/sproutcore/foundation/page.js +5 -2
  68. data/frameworks/sproutcore/foundation/path_module.js +11 -10
  69. data/frameworks/sproutcore/foundation/responder.js +5 -2
  70. data/frameworks/sproutcore/foundation/routes.js +17 -13
  71. data/frameworks/sproutcore/foundation/run_loop.js +249 -11
  72. data/frameworks/sproutcore/foundation/server.js +1 -1
  73. data/frameworks/sproutcore/foundation/set.js +3 -3
  74. data/frameworks/sproutcore/foundation/string.js +5 -3
  75. data/frameworks/sproutcore/foundation/timer.js +371 -0
  76. data/frameworks/sproutcore/foundation/undo_manager.js +1 -1
  77. data/frameworks/sproutcore/foundation/unittest.js +3 -3
  78. data/frameworks/sproutcore/foundation/utils.js +161 -2
  79. data/frameworks/sproutcore/globals/panels.js +1 -1
  80. data/frameworks/sproutcore/globals/popups.js +4 -3
  81. data/frameworks/sproutcore/globals/window.js +44 -4
  82. data/frameworks/sproutcore/lib/button_views.rb +328 -0
  83. data/frameworks/sproutcore/lib/collection_view.rb +80 -0
  84. data/frameworks/sproutcore/lib/core_views.rb +281 -0
  85. data/frameworks/sproutcore/lib/form_views.rb +253 -0
  86. data/frameworks/sproutcore/lib/index.rhtml +2 -0
  87. data/frameworks/sproutcore/lib/menu_views.rb +88 -0
  88. data/frameworks/sproutcore/{foundation → mixins}/array.js +60 -29
  89. data/frameworks/sproutcore/mixins/control.js +265 -0
  90. data/frameworks/sproutcore/mixins/delegate_support.js +66 -0
  91. data/frameworks/sproutcore/{foundation → mixins}/observable.js +176 -6
  92. data/frameworks/sproutcore/mixins/scrollable.js +245 -0
  93. data/frameworks/sproutcore/mixins/selection_support.js +148 -0
  94. data/frameworks/sproutcore/mixins/validatable.js +152 -0
  95. data/frameworks/sproutcore/models/collection.js +5 -5
  96. data/frameworks/sproutcore/models/record.js +1 -1
  97. data/frameworks/sproutcore/models/store.js +1 -1
  98. data/frameworks/sproutcore/panes/dialog.js +1 -1
  99. data/frameworks/sproutcore/panes/manager.js +1 -1
  100. data/frameworks/sproutcore/panes/menu.js +1 -1
  101. data/frameworks/sproutcore/panes/overlay.js +2 -2
  102. data/frameworks/sproutcore/panes/panel.js +1 -1
  103. data/frameworks/sproutcore/panes/picker.js +1 -1
  104. data/frameworks/sproutcore/tests/controllers/array.rhtml +44 -4
  105. data/frameworks/sproutcore/tests/foundation/timer/invalidate.rhtml +33 -0
  106. data/frameworks/sproutcore/tests/foundation/timer/invokeLater.rhtml +145 -0
  107. data/frameworks/sproutcore/tests/foundation/timer/isPaused.rhtml +70 -0
  108. data/frameworks/sproutcore/tests/foundation/timer/schedule.rhtml +145 -0
  109. data/frameworks/sproutcore/tests/views/{scroll.rhtml → checkbox.rhtml} +3 -3
  110. data/frameworks/sproutcore/tests/views/{collection.rhtml → collection/base.rhtml} +33 -32
  111. data/frameworks/sproutcore/tests/views/collection/incremental_rendering.rhtml +260 -0
  112. data/frameworks/sproutcore/tests/views/image_cell.rhtml +19 -0
  113. data/frameworks/sproutcore/tests/views/label_item.rhtml +2 -4
  114. data/frameworks/sproutcore/tests/views/list.rhtml +2 -3
  115. data/frameworks/sproutcore/tests/views/list_item.rhtml +20 -0
  116. data/frameworks/sproutcore/tests/views/slider.rhtml +20 -0
  117. data/frameworks/sproutcore/tests/views/text_cell.rhtml +19 -0
  118. data/frameworks/sproutcore/tests/views/view/clippingFrame.rhtml +395 -0
  119. data/frameworks/sproutcore/tests/views/view/frame.rhtml +353 -0
  120. data/frameworks/sproutcore/tests/views/view/innerFrame.rhtml +347 -0
  121. data/frameworks/sproutcore/tests/views/view/isVisibleInWindow.rhtml +148 -0
  122. data/frameworks/sproutcore/tests/views/view/scrollFrame.rhtml +468 -0
  123. data/frameworks/sproutcore/validators/credit_card.js +33 -13
  124. data/frameworks/sproutcore/validators/date.js +26 -6
  125. data/frameworks/sproutcore/validators/email.js +21 -3
  126. data/frameworks/sproutcore/validators/not_empty.js +11 -1
  127. data/frameworks/sproutcore/validators/number.js +18 -4
  128. data/frameworks/sproutcore/validators/password.js +12 -1
  129. data/frameworks/sproutcore/validators/validator.js +204 -194
  130. data/frameworks/sproutcore/views/{button.js → button/button.js} +96 -94
  131. data/frameworks/sproutcore/views/button/checkbox.js +29 -0
  132. data/frameworks/sproutcore/views/button/disclosure.js +42 -0
  133. data/frameworks/sproutcore/views/button/radio.js +29 -0
  134. data/frameworks/sproutcore/views/{collection.js → collection/collection.js} +1373 -1024
  135. data/frameworks/sproutcore/views/collection/grid.js +124 -46
  136. data/frameworks/sproutcore/views/collection/image_cell.js +17 -46
  137. data/frameworks/sproutcore/views/collection/list.js +45 -35
  138. data/frameworks/sproutcore/views/collection/source_list.js +386 -0
  139. data/frameworks/sproutcore/views/collection/table.js +118 -0
  140. data/frameworks/sproutcore/views/container.js +7 -2
  141. data/frameworks/sproutcore/views/error_explanation.js +23 -10
  142. data/frameworks/sproutcore/views/{checkbox_field.js → field/checkbox_field.js} +16 -6
  143. data/frameworks/sproutcore/views/field/field.js +219 -0
  144. data/frameworks/sproutcore/views/{radio_field.js → field/radio_field.js} +27 -12
  145. data/frameworks/sproutcore/views/{select_field.js → field/select_field.js} +116 -90
  146. data/frameworks/sproutcore/views/{text_field.js → field/text_field.js} +57 -8
  147. data/frameworks/sproutcore/views/{textarea_field.js → field/textarea_field.js} +13 -3
  148. data/frameworks/sproutcore/views/filter_button.js +2 -2
  149. data/frameworks/sproutcore/views/form.js +3 -3
  150. data/frameworks/sproutcore/views/image.js +128 -21
  151. data/frameworks/sproutcore/views/inline_text_editor.js +1 -1
  152. data/frameworks/sproutcore/views/label.js +149 -92
  153. data/frameworks/sproutcore/views/list_item.js +225 -0
  154. data/frameworks/sproutcore/views/menu_item.js +10 -4
  155. data/frameworks/sproutcore/views/pagination.js +11 -4
  156. data/frameworks/sproutcore/views/popup_button.js +25 -21
  157. data/frameworks/sproutcore/views/popup_menu.js +10 -4
  158. data/frameworks/sproutcore/views/progress.js +29 -16
  159. data/frameworks/sproutcore/views/radio_group.js +1 -1
  160. data/frameworks/sproutcore/views/scroll.js +60 -20
  161. data/frameworks/sproutcore/views/segmented.js +1 -1
  162. data/frameworks/sproutcore/views/slider.js +132 -0
  163. data/frameworks/sproutcore/views/source_list_group.js +130 -0
  164. data/frameworks/sproutcore/views/spinner.js +1 -1
  165. data/frameworks/sproutcore/views/split.js +292 -0
  166. data/frameworks/sproutcore/views/split_divider.js +109 -0
  167. data/frameworks/sproutcore/views/tab.js +1 -1
  168. data/frameworks/sproutcore/views/toolbar.js +1 -1
  169. data/frameworks/sproutcore/views/view.js +1272 -591
  170. data/generators/client/templates/english.lproj/body.css +1 -1
  171. data/generators/controller/controller_generator.rb +1 -1
  172. data/generators/controller/templates/test.rhtml +2 -1
  173. data/generators/model/templates/test.rhtml +1 -1
  174. data/generators/test/templates/test.rhtml +1 -1
  175. data/generators/view/templates/test.rhtml +1 -1
  176. data/jsdoc/templates/sproutcore/class.tmpl +241 -338
  177. data/jsdoc/templates/sproutcore/default.css +105 -155
  178. data/jsdoc/templates/sproutcore/index.tmpl +43 -8
  179. data/jsdoc/templates/sproutcore/publish.js +9 -4
  180. data/lib/sproutcore/build_tools/html_builder.rb +29 -13
  181. data/lib/sproutcore/build_tools/resource_builder.rb +1 -1
  182. data/lib/sproutcore/bundle.rb +86 -25
  183. data/lib/sproutcore/jsdoc.rb +2 -0
  184. data/lib/sproutcore/version.rb +1 -1
  185. data/lib/sproutcore/view_helpers.rb +36 -3
  186. data/tasks/deployment.rake +1 -1
  187. metadata +69 -36
  188. data/clients/sc_docs/english.lproj/icons/small/next.png +0 -0
  189. data/clients/sc_docs/english.lproj/icons/small/reset.png +0 -0
  190. data/clients/sc_docs/english.lproj/images/gradients.png +0 -0
  191. data/clients/sc_docs/english.lproj/images/toolbar.png +0 -0
  192. data/clients/sc_docs/english.lproj/warning.rhtml +0 -6
  193. data/clients/sc_test_runner/english.lproj/warning.rhtml +0 -6
  194. data/frameworks/sproutcore/english.lproj/buttons.png +0 -0
  195. data/frameworks/sproutcore/english.lproj/collections.css +0 -82
  196. data/frameworks/sproutcore/english.lproj/images/buttons-sprite.png +0 -0
  197. data/frameworks/sproutcore/views/collection/collection_item.js +0 -36
  198. data/frameworks/sproutcore/views/collection/text_cell.js +0 -128
  199. data/frameworks/sproutcore/views/field.js +0 -214
  200. data/frameworks/sproutcore/views/workspace.js +0 -170
  201. data/generators/client/templates/english.lproj/controls.css +0 -0
  202. data/generators/framework/templates/english.lproj/body.css +0 -0
  203. data/generators/framework/templates/english.lproj/body.rhtml +0 -3
  204. data/generators/framework/templates/english.lproj/controls.css +0 -0
  205. data/lib/sproutcore/view_helpers/button_views.rb +0 -302
  206. data/lib/sproutcore/view_helpers/core_views.rb +0 -292
  207. data/lib/sproutcore/view_helpers/form_views.rb +0 -258
  208. data/lib/sproutcore/view_helpers/menu_views.rb +0 -94
@@ -0,0 +1,386 @@
1
+ // ==========================================================================
2
+ // SC.SourceListView
3
+ // ==========================================================================
4
+
5
+ require('views/collection/collection') ;
6
+ require('views/button/disclosure');
7
+ require('views/source_list_group');
8
+
9
+ SC.BENCHMARK_SOURCE_LIST_VIEW = NO ;
10
+
11
+ /** @class
12
+
13
+ Displays a source list like the source list in iTunes.
14
+
15
+ @extends SC.CollectionView
16
+ @author Charles Jolley
17
+ @version 1.0
18
+ */
19
+ SC.SourceListView = SC.CollectionView.extend(
20
+ /** @scope SC.SourceListView.prototype */ {
21
+
22
+ emptyElement: '<div class="sc-source-list-view"></div>',
23
+
24
+ /**
25
+ name of property on the content object to use for the source list text.
26
+ */
27
+ contentValueKey: null,
28
+
29
+ /**
30
+ Set to YES if you want source list items to display an icon.
31
+
32
+ If this property is set, list items will leave space for a display
33
+ icon to the left of the text label. To actually display an icon in that
34
+ space, you will also need to set the contenIconUrlProperty or the
35
+ contentIconClassNameProperty or both.
36
+ */
37
+ hasContentIcon: NO,
38
+
39
+ /**
40
+ Set if YES if you want the source list to display a branch arrow.
41
+
42
+ If this property is set, list items will leave space on the right edge
43
+ to display a branch arrow, indicating the user can click on the item to
44
+ reveal a menu or another level of content.
45
+
46
+ To actually display a branch arrow, you must also set the
47
+ contentIsBranchKey.
48
+ */
49
+ hasContentBranch: NO,
50
+
51
+ /**
52
+ Name of the content object property that contains the icon .
53
+
54
+ This is the *name* of the property you want the list items to inspect
55
+ on content objects to retrieve an icon image URL. For example, if you
56
+ set this property to 'icon', then the icon displayed for each item will
57
+ be the URL returned by content.get('icon').
58
+
59
+ The value of this property must be either a URL or a CSS class name. If
60
+ you use a CSS class name, then the image src will be set to a blank
61
+ image and the class name will be applied automatically so you can use
62
+ spriting. If a URL is returned it will be set as the src property on
63
+ the image tag.
64
+ */
65
+ contentIconKey: null,
66
+
67
+ /**
68
+ Name of content object property that contains the unread count.
69
+
70
+ The unread count is used to indicate to a user when an item in the
71
+ source list contains items that need their attention. If the unread
72
+ count on a content object is a non-zero number, it will be displayed on
73
+ the right side of the list item.
74
+
75
+ This is the *name* of the property you want the list item to inspect
76
+ on content objects to receive the unread count for the item. For example,
77
+ if you set this property to "unread", then the unread count will be
78
+ the value returned by content.get('unread').
79
+
80
+ If you do not want to use unread counts, leave this property to null.
81
+ */
82
+ contentUnreadCountKey: null,
83
+
84
+ /**
85
+ Name of the content object property that contains the branch state.
86
+
87
+ If an item is a branch, then a branch arrow will be displayed at the
88
+ right edge indicating that clicking on the item will reveal another
89
+ level or content or possibly a popup menu.
90
+
91
+ To display the branch, you must also set hasContentBranch to YES.
92
+
93
+ This is the *name* of the property you want the list item to inspect
94
+ on the content objects to retrieve the branch state. For example, if
95
+ you set this property to "isBranch", then the branch state will be the
96
+ value returned by content.get('isBranch').
97
+ */
98
+ contentIsBranchKey: null,
99
+
100
+ /**
101
+ Key that contains the group name.
102
+
103
+ If set, the title shown in the group label will be the value returned
104
+ by this property on the group object.
105
+ */
106
+ groupTitleKey: null,
107
+
108
+ /**
109
+ Key that contains group visibility.
110
+
111
+ If set, the group label will display a disclosure triangle matching the
112
+ value of this property.
113
+ */
114
+ groupVisibleKey: null,
115
+
116
+ /**
117
+ The common row height for list view items.
118
+
119
+ The value should be an integer expressed in pixels.
120
+ */
121
+ rowHeight: 32,
122
+
123
+ /**
124
+ Source list view items are usually list item views. You can override
125
+ this if you wish.
126
+ */
127
+ exampleView: SC.ListItemView,
128
+
129
+ /**
130
+ The standard group view provided by source list view generally
131
+ provides all the functionality you need.
132
+ */
133
+ exampleGroupView: SC.SourceListGroupView,
134
+
135
+
136
+ // .......................................
137
+ // LAYOUT METHODS
138
+ //
139
+
140
+ // whenever updateChildren is called with a deep method, flush the
141
+ // cached group rows to make sure we get an accurate count.
142
+ updateChildren: function(deep) {
143
+ if (deep) this._groupRows = null ;
144
+ return arguments.callee.base.apply(this, arguments) ;
145
+ },
146
+
147
+ // determines if the group at the specified content index is visible or
148
+ // not. This will look either at a property on the group or on the
149
+ // SourceListGroupView.
150
+ groupAtContentIndexIsVisible: function(contentIndex) {
151
+
152
+ if (!this.get('groupBy')) return YES; // no grouping
153
+
154
+ // get the group value and try to find a matching view, which may
155
+ // or may not exist yet.
156
+ var groupValue = this.groupValueAtContentIndex(contentIndex) ;
157
+ var groupView = this.groupViewForGroupValue(groupValue) ;
158
+
159
+ // if the groupView exists, use that. The visible state is stored here
160
+ // in case the group does not actually support storing its own visibility.
161
+ // ignore groupView if it does not support isGroupVisible
162
+ var ret = YES ;
163
+ if (groupView) ret = groupView.get('isGroupVisible') ;
164
+
165
+ // otherwise try to get from the group itself.
166
+ if (((ret === undefined) || (ret === null) || !groupView) && groupValue && groupValue.get) {
167
+ var key = this.get('groupVisibleKey') ;
168
+ if (key) ret = !!groupValue.get(key) ;
169
+ }
170
+
171
+ // if the above methods failed for some reason, just leave the group visible
172
+ if ((ret === undefined) || (ret === null)) ret = YES ;
173
+
174
+ return ret ;
175
+ },
176
+
177
+ // calculates the number of rows consumed by each group. stores a hash of
178
+ // contentIndexes and rows.
179
+ computedGroupRows: function() {
180
+ if (this._groupRows) return this._groupRows;
181
+
182
+ var loc = 0 ;
183
+ var content = Array.from(this.get('content')) ;
184
+ var max = content.get('length') ;
185
+
186
+ var ret = {} ;
187
+ while(loc < max) {
188
+ var range = this.groupRangeForContentIndex(loc) ;
189
+ var isVisible = this.groupAtContentIndexIsVisible(range.start) ;
190
+ ret[range.start] = (isVisible) ? range.length : 0 ;
191
+
192
+ // add a header row space if neede
193
+ var groupValue = this.groupValueAtContentIndex(range.start) ;
194
+ if (groupValue != null) ret[range.start]++ ;
195
+
196
+ loc = (range.length <= 0) ? max : SC.maxRange(range) ;
197
+ }
198
+
199
+ return this._groupRows = ret ;
200
+ },
201
+
202
+ // Returns the number of rows in the specified range.
203
+ countRowsInRange: function(range) {
204
+ var groupRows = this.computedGroupRows() ;
205
+ var max = SC.maxRange(range) ;
206
+ var loc = SC.minRange(range) ;
207
+ var ret = 0 ;
208
+
209
+ while(loc < max) {
210
+ var range = this.groupRangeForContentIndex(loc) ;
211
+ loc = (range.length <= 0) ? max : SC.maxRange(range) ;
212
+ ret += groupRows[range.start] || (range+1);
213
+ }
214
+ return ret ;
215
+ },
216
+
217
+ computeFrame: function() {
218
+ var content = this.get('content') ;
219
+ var rowHeight = this.get('rowHeight') || 20 ;
220
+
221
+ // find number of groups.
222
+ var rows = this.countRowsInRange({ start: 0, length: content.get('length') });
223
+ if (rows <= 0) rows = 0 ;
224
+
225
+ // get parent width
226
+ var parent = this.get('parentNode') ;
227
+ var f = (parent) ? parent.get('innerFrame') : { width: 100, height: 100 };
228
+ f.x = f.y = 0;
229
+ f.height = Math.max(f.height, rows * rowHeight) ;
230
+ return f ;
231
+ },
232
+
233
+
234
+ // disable incremental rendering for now
235
+ contentRangeInFrame: function(frame) {
236
+ var content =this.get('content') ;
237
+ var len = (content) ? content.get('length') : 0 ;
238
+ var ret = { start: 0, length: len } ;
239
+ return ret ;
240
+ },
241
+
242
+
243
+ /** @private */
244
+ layoutItemView: function(itemView, contentIndex, firstLayout) {
245
+ if (SC.BENCHMARK_SOURCE_LIST_VIEW) {
246
+ SC.Benchmark.start('SC.SourceListView.layoutItemViewsFor') ;
247
+ }
248
+
249
+ // if itemView's group is not visible, then just set to invisible.
250
+ if (!this.groupAtContentIndexIsVisible(contentIndex)) {
251
+ itemView.set('isVisible', false) ;
252
+ } else {
253
+
254
+ // if item was not visible, make it visible. Also force layout.
255
+ if (!itemView.get('isVisible')) {
256
+ firstLayout = YES ;
257
+ itemView.set('isVisible', true) ;
258
+ }
259
+
260
+ var rowHeight = this.get('rowHeight') || 0 ;
261
+
262
+ // layout relative to top of group. Leave open row for title
263
+ var range = this.groupRangeForContentIndex(contentIndex) ;
264
+ contentIndex = (contentIndex - range.start) ;
265
+
266
+ var groupValue = this.groupValueAtContentIndex(range.start) ;
267
+ if (groupValue != null) contentIndex++ ;
268
+
269
+ var f = {
270
+ x: 0,
271
+ y: contentIndex*rowHeight,
272
+ height: rowHeight,
273
+ width: this.get('innerFrame').width
274
+ } ;
275
+
276
+ if (firstLayout || !SC.rectsEqual(itemView.get('frame'), f)) {
277
+ itemView.set('frame', f) ;
278
+ }
279
+
280
+ }
281
+
282
+ if (SC.BENCHMARK_SOURCE_LIST_VIEW) {
283
+ SC.Benchmark.end('SC.SourceListView.layoutItemViewsFor') ;
284
+ }
285
+ },
286
+
287
+ layoutGroupView: function(groupView, groupValue, contentIndexHint, firstLayout) {
288
+
289
+ if (SC.BENCHMARK_SOURCE_LIST_VIEW) {
290
+ SC.Benchmark.start('SC.SourceListView.layoutGroupView') ;
291
+ }
292
+
293
+ //console.log('layoutGroupView', groupValue) ;
294
+
295
+ // find the range this group will belong to
296
+ var range = this.groupRangeForContentIndex(contentIndexHint) ;
297
+ var isVisible = this.groupAtContentIndexIsVisible(range.start) ;
298
+
299
+ var priorRows = this.countRowsInRange({ start: 0, length: range.start }) ;
300
+ var rowHeight = this.get('rowHeight') || 0 ;
301
+ var parentView = groupView.get('parentView') || this ;
302
+ var rows = (isVisible) ? range.length : 0 ;
303
+ if (groupValue != null) rows++ ;
304
+
305
+ var f = {
306
+ x: 0,
307
+ y: priorRows*rowHeight,
308
+ height: rowHeight * rows,
309
+ width: (parentView || this).get('innerFrame').width
310
+ } ;
311
+
312
+ if (firstLayout || !SC.rectsEqual(groupView.get('frame'), f)) {
313
+ groupView.set('frame', f) ;
314
+ }
315
+
316
+ if (SC.BENCHMARK_SOURCE_LIST_VIEW) {
317
+ SC.Benchmark.end('SC.SourceListView.layoutGroupView') ;
318
+ }
319
+ },
320
+
321
+ // .......................................
322
+ // INSERTION POINT METHODS
323
+ //
324
+
325
+ insertionOrientation: SC.VERTICAL_ORIENTATION,
326
+
327
+ insertionPointClass: SC.View.extend({
328
+ emptyElement: '<div class="list-insertion-point"><span class="anchor"></span></div>'
329
+ }),
330
+
331
+ showInsertionPointBefore: function(itemView) {
332
+ if (!itemView) return ;
333
+
334
+ if (!this._insertionPointView) {
335
+ this._insertionPointView = this.insertionPointClass.create() ;
336
+ } ;
337
+
338
+ var insertionPoint = this._insertionPointView ;
339
+ f = { height: 0, x: 8, y: itemView.get('frame').y, width: itemView.owner.get('frame').width };
340
+ insertionPoint.set('frame', f) ;
341
+
342
+ if (insertionPoint.parentNode != itemView.parentNode) {
343
+ itemView.parentNode.appendChild(insertionPoint) ;
344
+ }
345
+ },
346
+
347
+ hideInsertionPoint: function() {
348
+ var insertionPoint = this._insertionPointView ;
349
+ if (insertionPoint) insertionPoint.removeFromParent() ;
350
+ },
351
+
352
+ // We can do this much faster programatically using the rowHeight
353
+ insertionIndexForLocation: function(loc) {
354
+ var f = this.get('innerFrame') ;
355
+ var sf = this.get('scrollFrame') ;
356
+ var rowHeight = this.get('rowHeight') || 0 ;
357
+
358
+ // find the offset to work with.
359
+ var offset = loc.y - f.y - sf.y ;
360
+ var ret = -1; // the return value
361
+
362
+ // search groups until we find one that matches
363
+ var top = 0;
364
+ var idx = 0 ;
365
+ while((ret<0) && (range = this.groupRangeForContentIndex(idx)).length>0){
366
+ var max = top + ((range.length+1) * rowHeight) ;
367
+
368
+ // the offset is within the group, find the row in the group. Remember
369
+ // that the top row is actually the label, so we should return -1 if
370
+ // we hit there.
371
+ if (max >= offset) {
372
+ offset -= top ;
373
+ ret = Math.floor((offset / rowHeight) + 0.4) ;
374
+ if (ret < 1) return -1 ; // top row!
375
+ ret = (ret - 1) + idx ;
376
+
377
+ // we are not yet within the group, go on to the next group.
378
+ } else {
379
+ idx += range.length ;
380
+ top = max ;
381
+ }
382
+ }
383
+ return ret ;
384
+ }
385
+
386
+ }) ;
@@ -0,0 +1,118 @@
1
+ // ==========================================================================
2
+ // SC.TableView
3
+ // ==========================================================================
4
+
5
+ require('views/collection/collection') ;
6
+ require('views/label');
7
+
8
+ /** @class
9
+
10
+ Displays a table view with columns
11
+
12
+ @extends SC.CollectionView
13
+ @author Charles Jolley
14
+ @version 1.0
15
+ */
16
+ SC.TableView = SC.CollectionView.extend(
17
+ /** @scope SC.TableView.prototype */ {
18
+
19
+ emptyElement: '<div class="sc-table-view"></div>',
20
+
21
+ /**
22
+ The common row height for list view items.
23
+
24
+ If you set this property, then the TableView will be able to use this
25
+ property to perform absolute layout of its children and to minimize t
26
+ number of actual views it has to create.
27
+
28
+ The value should be an integer expressed in pixels.
29
+ */
30
+ rowHeight: 20,
31
+
32
+ /**
33
+ The default example item view will render text-based items.
34
+
35
+ You can override this as you wish.
36
+ */
37
+ exampleView: SC.LabelView,
38
+
39
+ insertionOrientation: SC.VERTICAL_ORIENTATION,
40
+
41
+ contentRangeInFrame: function(frame) {
42
+ var rowHeight = this.get('rowHeight') || 0 ;
43
+ var min = Math.max(0,Math.floor(SC.minY(frame) / rowHeight)-1) ;
44
+ var max = Math.ceil(SC.maxY(frame) / rowHeight) ;
45
+ var ret = { start: min, length: max - min } ;
46
+ // console.log('contentRangeInFrame(%@) = %@'.fmt($H(frame).inspect(), $H(ret).inspect()));
47
+ //if (frame.height < 100) debugger ;
48
+ return ret ;
49
+ },
50
+
51
+ /** @private */
52
+ layoutItemView: function(itemView, contentIndex, firstLayout) {
53
+ if (!itemView) debugger ;
54
+ SC.Benchmark.start('SC.TableView.layoutItemViewsFor') ;
55
+
56
+ var rowHeight = this.get('rowHeight') || 0 ;
57
+ var parentView = itemView.get('parentView') ;
58
+ var f = {
59
+ x: 0,
60
+ y: contentIndex*rowHeight,
61
+ height: rowHeight,
62
+ width: (parentView || this).get('innerFrame').width
63
+ } ;
64
+
65
+ if (firstLayout || !SC.rectsEqual(itemView.get('frame'), f)) {
66
+ itemView.set('frame', f) ;
67
+ }
68
+ SC.Benchmark.end('SC.TableView.layoutItemViewsFor') ;
69
+ },
70
+
71
+ computeFrame: function() {
72
+ var content = this.get('content') ;
73
+ var rows = (content) ? content.get('length') : 0 ;
74
+ var rowHeight = this.get('rowHeight') || 20 ;
75
+
76
+ var parent = this.get('parentNode') ;
77
+ var f = (parent) ? parent.get('innerFrame') : { width: 100, height: 100 } ;
78
+
79
+ f.x = f.y = 0;
80
+ f.height = Math.max(f.height, rows * rowHeight) ;
81
+ // console.log('computeFrame(%@)'.fmt($H(f).inspect())) ;
82
+ return f ;
83
+ },
84
+
85
+ insertionPointClass: SC.View.extend({
86
+ emptyElement: '<div class="list-insertion-point"><span class="anchor"></span></div>'
87
+ }),
88
+
89
+ showInsertionPointBefore: function(itemView) {
90
+ if (!itemView) return ;
91
+
92
+ if (!this._insertionPointView) {
93
+ this._insertionPointView = this.insertionPointClass.create() ;
94
+ } ;
95
+
96
+ var insertionPoint = this._insertionPointView ;
97
+ f = { height: 0, x: 8, y: itemView.get('frame').y, width: itemView.owner.get('frame').width };
98
+ insertionPoint.set('frame', f) ;
99
+
100
+ if (insertionPoint.parentNode != itemView.parentNode) {
101
+ itemView.parentNode.appendChild(insertionPoint) ;
102
+ }
103
+ },
104
+
105
+ hideInsertionPoint: function() {
106
+ var insertionPoint = this._insertionPointView ;
107
+ if (insertionPoint) insertionPoint.removeFromParent() ;
108
+ },
109
+
110
+ // We can do this much faster programatically using the rowHeight
111
+ insertionIndexForLocation: function(loc) {
112
+ var f = this.get('innerFrame') ;
113
+ var sf = this.get('scrollFrame') ;
114
+ var ret = Math.floor(((loc.y - f.y - sf.y) / this.get('rowHeight')) + 0.4) ;
115
+ return ret ;
116
+ }
117
+
118
+ }) ;