sproutcore 1.5.0.rc.1 → 1.5.0.rc.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (193) hide show
  1. data/CHANGELOG +4 -0
  2. data/VERSION.yml +1 -1
  3. data/lib/frameworks/sproutcore/Buildfile +9 -4
  4. data/lib/frameworks/sproutcore/README.md +1 -0
  5. data/lib/frameworks/sproutcore/design/{TestRunner_Design.gaffle → TestRunner_Design.graffle}/QuickLook/Preview.pdf +0 -0
  6. data/lib/frameworks/sproutcore/design/{TestRunner_Design.gaffle → TestRunner_Design.graffle}/QuickLook/Thumbnail.tiff +0 -0
  7. data/lib/frameworks/sproutcore/design/{TestRunner_Design.gaffle → TestRunner_Design.graffle}/data.plist +0 -0
  8. data/lib/frameworks/sproutcore/design/{TestRunner_Design.gaffle → TestRunner_Design.graffle}/image10.png +0 -0
  9. data/lib/frameworks/sproutcore/design/{TestRunner_Design.gaffle → TestRunner_Design.graffle}/image11.png +0 -0
  10. data/lib/frameworks/sproutcore/design/{TestRunner_Design.gaffle → TestRunner_Design.graffle}/image13.png +0 -0
  11. data/lib/frameworks/sproutcore/design/{TestRunner_Design.gaffle → TestRunner_Design.graffle}/image15.png +0 -0
  12. data/lib/frameworks/sproutcore/design/{TestRunner_Design.gaffle → TestRunner_Design.graffle}/image16.png +0 -0
  13. data/lib/frameworks/sproutcore/design/{TestRunner_Design.gaffle → TestRunner_Design.graffle}/image17.png +0 -0
  14. data/lib/frameworks/sproutcore/design/{TestRunner_Design.gaffle → TestRunner_Design.graffle}/image18.png +0 -0
  15. data/lib/frameworks/sproutcore/design/{TestRunner_Design.gaffle → TestRunner_Design.graffle}/image19.png +0 -0
  16. data/lib/frameworks/sproutcore/design/{TestRunner_Design.gaffle → TestRunner_Design.graffle}/image22.tiff +0 -0
  17. data/lib/frameworks/sproutcore/design/{TestRunner_Design.gaffle → TestRunner_Design.graffle}/image23.png +0 -0
  18. data/lib/frameworks/sproutcore/design/{TestRunner_Design.gaffle → TestRunner_Design.graffle}/image24.png +0 -0
  19. data/lib/frameworks/sproutcore/design/{TestRunner_Design.gaffle → TestRunner_Design.graffle}/image25.png +0 -0
  20. data/lib/frameworks/sproutcore/design/{TestRunner_Design.gaffle → TestRunner_Design.graffle}/image30.png +0 -0
  21. data/lib/frameworks/sproutcore/design/{TestRunner_Design.gaffle → TestRunner_Design.graffle}/image31.png +0 -0
  22. data/lib/frameworks/sproutcore/design/{TestRunner_Design.gaffle → TestRunner_Design.graffle}/image8.png +0 -0
  23. data/lib/frameworks/sproutcore/design/{TestRunner_Design.gaffle → TestRunner_Design.graffle}/image9.png +0 -0
  24. data/lib/frameworks/sproutcore/frameworks/animation/core.js +23 -25
  25. data/lib/frameworks/sproutcore/frameworks/bootstrap/system/browser.js +160 -0
  26. data/lib/frameworks/sproutcore/frameworks/core_foundation/controllers/array.js +73 -82
  27. data/lib/frameworks/sproutcore/frameworks/core_foundation/core.js +1 -3
  28. data/lib/frameworks/sproutcore/frameworks/{handlebars/extensions → core_foundation/ext/handlebars}/bind.js +110 -7
  29. data/lib/frameworks/sproutcore/frameworks/{handlebars/extensions → core_foundation/ext/handlebars}/collection.js +10 -7
  30. data/lib/frameworks/sproutcore/frameworks/{handlebars/extensions → core_foundation/ext/handlebars}/localization.js +1 -1
  31. data/lib/frameworks/sproutcore/frameworks/{handlebars/extensions → core_foundation/ext/handlebars}/view.js +4 -2
  32. data/lib/frameworks/sproutcore/frameworks/{handlebars/extensions.js → core_foundation/ext/handlebars.js} +0 -57
  33. data/lib/frameworks/sproutcore/frameworks/core_foundation/ext/object.js +1 -3
  34. data/lib/frameworks/sproutcore/frameworks/core_foundation/mixins/template_helpers/text_field_support.js +11 -0
  35. data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/main.js +1 -3
  36. data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/pane.js +2 -4
  37. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/application.js +14 -16
  38. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/builder.js +29 -37
  39. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/datetime.js +0 -0
  40. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/event.js +71 -19
  41. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/locale.js +3 -7
  42. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/page.js +5 -7
  43. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/selection_set.js +1 -3
  44. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/sparse_array.js +4 -0
  45. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/timer.js +21 -27
  46. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/utils.js +3 -5
  47. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/controllers/array/array_case.js +3 -3
  48. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/controllers/object/single_enumerable_case.js +1 -1
  49. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/system/sparse_array.js +1 -1
  50. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/template/handlebars.js +93 -1
  51. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/clippingFrame.js +1 -1
  52. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/convertLayouts.js +13 -11
  53. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layer.js +2 -6
  54. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layoutStyle.js +4 -4
  55. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/theme.js +2 -0
  56. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/view.js +4 -4
  57. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/template.js +6 -2
  58. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/template_collection.js +87 -32
  59. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/layout.js +21 -25
  60. data/lib/frameworks/sproutcore/frameworks/datastore/data_sources/cascade.js +15 -19
  61. data/lib/frameworks/sproutcore/frameworks/datastore/data_sources/data_source.js +114 -167
  62. data/lib/frameworks/sproutcore/frameworks/datastore/data_sources/fixtures.js +4 -4
  63. data/lib/frameworks/sproutcore/frameworks/datastore/models/child_attribute.js +4 -6
  64. data/lib/frameworks/sproutcore/frameworks/datastore/models/children_attribute.js +2 -4
  65. data/lib/frameworks/sproutcore/frameworks/datastore/models/fetched_attribute.js +7 -7
  66. data/lib/frameworks/sproutcore/frameworks/datastore/models/many_attribute.js +18 -20
  67. data/lib/frameworks/sproutcore/frameworks/datastore/models/record.js +74 -72
  68. data/lib/frameworks/sproutcore/frameworks/datastore/models/record_attribute.js +36 -29
  69. data/lib/frameworks/sproutcore/frameworks/datastore/models/single_attribute.js +2 -2
  70. data/lib/frameworks/sproutcore/frameworks/datastore/system/child_array.js +97 -78
  71. data/lib/frameworks/sproutcore/frameworks/datastore/system/many_array.js +117 -97
  72. data/lib/frameworks/sproutcore/frameworks/datastore/system/nested_store.js +13 -13
  73. data/lib/frameworks/sproutcore/frameworks/datastore/system/query.js +111 -108
  74. data/lib/frameworks/sproutcore/frameworks/datastore/system/record_array.js +231 -198
  75. data/lib/frameworks/sproutcore/frameworks/datastore/system/store.js +146 -145
  76. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/query/builders.js +21 -21
  77. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/record_array/flush.js +49 -50
  78. data/lib/frameworks/sproutcore/frameworks/datetime/{system → frameworks/core/system}/datetime.js +122 -171
  79. data/lib/frameworks/sproutcore/frameworks/datetime/{tests → frameworks/core/tests}/system/datetime.js +0 -0
  80. data/lib/frameworks/sproutcore/frameworks/datetime/{resources → frameworks/localized/resources}/strings.js +0 -0
  81. data/lib/frameworks/sproutcore/frameworks/datetime/frameworks/localized/system/datetime.js +91 -0
  82. data/lib/frameworks/sproutcore/frameworks/desktop/core.js +18 -2
  83. data/lib/frameworks/sproutcore/frameworks/desktop/mixins/border.js +23 -16
  84. data/lib/frameworks/sproutcore/frameworks/desktop/mixins/collection_fast_path.js +56 -45
  85. data/lib/frameworks/sproutcore/frameworks/desktop/mixins/collection_group.js +5 -2
  86. data/lib/frameworks/sproutcore/frameworks/desktop/mixins/collection_row_delegate.js +21 -19
  87. data/lib/frameworks/sproutcore/frameworks/desktop/mixins/collection_view_delegate.js +82 -77
  88. data/lib/frameworks/sproutcore/frameworks/desktop/mixins/navigation_builder.js +18 -12
  89. data/lib/frameworks/sproutcore/frameworks/desktop/mixins/scrollable.js +29 -17
  90. data/lib/frameworks/sproutcore/frameworks/desktop/panes/alert.js +148 -107
  91. data/lib/frameworks/sproutcore/frameworks/desktop/panes/menu.js +31 -16
  92. data/lib/frameworks/sproutcore/frameworks/desktop/panes/modal.js +16 -13
  93. data/lib/frameworks/sproutcore/frameworks/desktop/panes/palette.js +38 -17
  94. data/lib/frameworks/sproutcore/frameworks/desktop/panes/panel.js +37 -25
  95. data/lib/frameworks/sproutcore/frameworks/desktop/panes/picker.js +247 -144
  96. data/lib/frameworks/sproutcore/frameworks/desktop/panes/select_button.js +155 -100
  97. data/lib/frameworks/sproutcore/frameworks/desktop/panes/sheet.js +39 -17
  98. data/lib/frameworks/sproutcore/frameworks/desktop/protocols/drag_data_source.js +9 -6
  99. data/lib/frameworks/sproutcore/frameworks/desktop/protocols/drag_source.js +18 -22
  100. data/lib/frameworks/sproutcore/frameworks/desktop/protocols/drop_target.js +27 -17
  101. data/lib/frameworks/sproutcore/frameworks/desktop/system/drag.js +77 -44
  102. data/lib/frameworks/sproutcore/frameworks/desktop/system/undo_manager.js +68 -33
  103. data/lib/frameworks/sproutcore/frameworks/desktop/views/button.js +168 -110
  104. data/lib/frameworks/sproutcore/frameworks/desktop/views/checkbox.js +37 -5
  105. data/lib/frameworks/sproutcore/frameworks/desktop/views/collection.js +187 -123
  106. data/lib/frameworks/sproutcore/frameworks/desktop/views/date_field.js +73 -49
  107. data/lib/frameworks/sproutcore/frameworks/desktop/views/disclosure.js +34 -9
  108. data/lib/frameworks/sproutcore/frameworks/desktop/views/file.js +51 -14
  109. data/lib/frameworks/sproutcore/frameworks/desktop/views/grid.js +38 -8
  110. data/lib/frameworks/sproutcore/frameworks/desktop/views/image_button.js +15 -9
  111. data/lib/frameworks/sproutcore/frameworks/desktop/views/list.js +54 -34
  112. data/lib/frameworks/sproutcore/frameworks/desktop/views/list_item.js +113 -42
  113. data/lib/frameworks/sproutcore/frameworks/desktop/views/master_detail.js +84 -28
  114. data/lib/frameworks/sproutcore/frameworks/desktop/views/menu_item.js +67 -51
  115. data/lib/frameworks/sproutcore/frameworks/desktop/views/menu_scroll.js +122 -35
  116. data/lib/frameworks/sproutcore/frameworks/desktop/views/navigation.js +40 -16
  117. data/lib/frameworks/sproutcore/frameworks/desktop/views/navigation_bar.js +28 -18
  118. data/lib/frameworks/sproutcore/frameworks/desktop/views/popup_button.js +27 -31
  119. data/lib/frameworks/sproutcore/frameworks/desktop/views/progress.js +118 -68
  120. data/lib/frameworks/sproutcore/frameworks/desktop/views/radio.js +117 -61
  121. data/lib/frameworks/sproutcore/frameworks/desktop/views/scene.js +23 -16
  122. data/lib/frameworks/sproutcore/frameworks/desktop/views/scroll.js +241 -77
  123. data/lib/frameworks/sproutcore/frameworks/desktop/views/scroller.js +134 -69
  124. data/lib/frameworks/sproutcore/frameworks/desktop/views/segment.js +107 -25
  125. data/lib/frameworks/sproutcore/frameworks/desktop/views/segmented.js +125 -48
  126. data/lib/frameworks/sproutcore/frameworks/desktop/views/select.js +165 -69
  127. data/lib/frameworks/sproutcore/frameworks/desktop/views/select_field.js +73 -24
  128. data/lib/frameworks/sproutcore/frameworks/desktop/views/separator.js +19 -5
  129. data/lib/frameworks/sproutcore/frameworks/desktop/views/source_list.js +16 -4
  130. data/lib/frameworks/sproutcore/frameworks/desktop/views/source_list_group.js +14 -7
  131. data/lib/frameworks/sproutcore/frameworks/desktop/views/split.js +43 -37
  132. data/lib/frameworks/sproutcore/frameworks/desktop/views/split_divider.js +8 -1
  133. data/lib/frameworks/sproutcore/frameworks/desktop/views/stacked.js +14 -3
  134. data/lib/frameworks/sproutcore/frameworks/desktop/views/static_content.js +16 -2
  135. data/lib/frameworks/sproutcore/frameworks/desktop/views/tab.js +99 -0
  136. data/lib/frameworks/sproutcore/frameworks/desktop/views/thumb.js +13 -1
  137. data/lib/frameworks/sproutcore/frameworks/desktop/views/toolbar.js +58 -8
  138. data/lib/frameworks/sproutcore/frameworks/desktop/views/web.js +34 -18
  139. data/lib/frameworks/sproutcore/frameworks/desktop/views/well.js +25 -9
  140. data/lib/frameworks/sproutcore/frameworks/desktop/views/workspace.js +70 -36
  141. data/lib/frameworks/sproutcore/frameworks/foundation/controllers/tree.js +10 -5
  142. data/lib/frameworks/sproutcore/frameworks/foundation/debug/control_test_pane.js +28 -17
  143. data/lib/frameworks/sproutcore/frameworks/foundation/delegates/inline_text_field.js +41 -43
  144. data/lib/frameworks/sproutcore/frameworks/foundation/gestures/pinch.js +42 -4
  145. data/lib/frameworks/sproutcore/frameworks/foundation/gestures/swipe.js +94 -4
  146. data/lib/frameworks/sproutcore/frameworks/foundation/gestures/tap.js +41 -1
  147. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/auto_mixin.js +2 -0
  148. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/auto_resize.js +18 -9
  149. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/collection_content.js +7 -5
  150. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/content_display.js +7 -8
  151. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/content_value_support.js +34 -24
  152. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/control.js +48 -18
  153. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/inline_text_field.js +1 -0
  154. data/lib/frameworks/sproutcore/frameworks/foundation/system/utils/misc.js +1 -2
  155. data/lib/frameworks/sproutcore/frameworks/foundation/tasks/preload_bundle.js +1 -1
  156. data/lib/frameworks/sproutcore/frameworks/foundation/tests/mixins/inline_text_field/beginEditing.js +0 -11
  157. data/lib/frameworks/sproutcore/frameworks/foundation/validators/date_time.js +1 -1
  158. data/lib/frameworks/sproutcore/frameworks/foundation/views/text_field.js +8 -0
  159. data/lib/frameworks/sproutcore/frameworks/qunit/README.md +24 -0
  160. data/lib/frameworks/sproutcore/frameworks/qunit/package.json +21 -0
  161. data/lib/frameworks/sproutcore/frameworks/qunit/qunit/qunit.css +215 -0
  162. data/lib/frameworks/sproutcore/frameworks/qunit/qunit/qunit.js +1442 -0
  163. data/lib/frameworks/sproutcore/frameworks/qunit/test/headless.html +24 -0
  164. data/lib/frameworks/sproutcore/frameworks/qunit/test/index.html +18 -0
  165. data/lib/frameworks/sproutcore/frameworks/qunit/test/logs.html +17 -0
  166. data/lib/frameworks/sproutcore/frameworks/qunit/test/logs.js +150 -0
  167. data/lib/frameworks/sproutcore/frameworks/qunit/test/same.js +1421 -0
  168. data/lib/frameworks/sproutcore/frameworks/qunit/test/test.js +314 -0
  169. data/lib/frameworks/sproutcore/frameworks/runtime/core.js +1 -1
  170. data/lib/frameworks/sproutcore/frameworks/runtime/mixins/array.js +369 -60
  171. data/lib/frameworks/sproutcore/frameworks/runtime/mixins/enumerable.js +2 -405
  172. data/lib/frameworks/sproutcore/frameworks/runtime/mixins/observable.js +3 -9
  173. data/lib/frameworks/sproutcore/frameworks/runtime/private/property_chain.js +50 -45
  174. data/lib/frameworks/sproutcore/frameworks/runtime/system/binding.js +20 -1
  175. data/lib/frameworks/sproutcore/frameworks/runtime/system/object.js +0 -9
  176. data/lib/frameworks/sproutcore/frameworks/runtime/tests/core/guidFor.js +1 -1
  177. data/lib/frameworks/sproutcore/frameworks/runtime/tests/mixins/array.js +36 -14
  178. data/lib/frameworks/sproutcore/frameworks/runtime/tests/mixins/enumerable/enumerable.js +0 -34
  179. data/lib/frameworks/sproutcore/frameworks/runtime/tests/mixins/enumerable/enumerable_observers.js +50 -61
  180. data/lib/frameworks/sproutcore/frameworks/runtime/tests/mixins/observable/observable.js +2 -2
  181. data/lib/frameworks/sproutcore/frameworks/runtime/tests/mixins/observable/propertyChanges.js +1 -1
  182. data/lib/frameworks/sproutcore/frameworks/runtime/tests/mixins/observable/registerDependentKeys.js +45 -1
  183. data/lib/frameworks/sproutcore/frameworks/runtime/tests/mixins/propertyChanges.js +1 -1
  184. data/lib/frameworks/sproutcore/frameworks/runtime/tests/system/object/bindings.js +5 -0
  185. data/lib/frameworks/sproutcore/frameworks/runtime/tests/system/object/enhance.js +1 -1
  186. data/lib/frameworks/sproutcore/frameworks/testing/core.js +3 -0
  187. data/lib/frameworks/sproutcore/frameworks/testing/system/plan.js +0 -1
  188. data/lib/frameworks/sproutcore/frameworks/testing/system/runner.js +0 -1
  189. data/lib/gen/html_app/templates/apps/@target_name@/@target_name@.js +1 -1
  190. data/vendor/chance/lib/chance/instance.rb +8 -6
  191. metadata +41 -31
  192. data/lib/frameworks/sproutcore/frameworks/testing/jquery.js +0 -3559
  193. data/lib/frameworks/sproutcore/frameworks/testing/qunit.js +0 -827
@@ -1,4 +1,4 @@
1
- sc_require('extensions');
1
+ sc_require('ext/handlebars');
2
2
 
3
3
  /**
4
4
  Adds the `bind`, `bindAttr`, and `boundIf` helpers to Handlebars.
@@ -129,7 +129,7 @@ Handlebars.registerHelper('bindAttr', function(options) {
129
129
  // Handle classes differently, as we can bind multiple classes
130
130
  var classBindings = attrs['class'];
131
131
  if (classBindings != null) {
132
- var classResults = SC.Handlebars.bindClasses(view, classBindings, dataId);
132
+ var classResults = SC.Handlebars.bindClasses(this, classBindings, view, dataId);
133
133
  ret.push('class="'+classResults.join(' ')+'"');
134
134
  delete attrs['class'];
135
135
  }
@@ -140,13 +140,13 @@ Handlebars.registerHelper('bindAttr', function(options) {
140
140
  // current value of the property as an attribute.
141
141
  attrKeys.forEach(function(attr) {
142
142
  var property = attrs[attr];
143
- var value = view.getPath(property);
143
+ var value = this.getPath(property);
144
144
 
145
145
  // Add an observer to the view for when the property changes.
146
146
  // When the observer fires, find the element using the
147
147
  // unique data id and update the attribute to the new value.
148
- view.addObserver(property, function observer() {
149
- var result = view.getPath(property);
148
+ this.addObserver(property, function observer() {
149
+ var result = this.getPath(property);
150
150
  var elem = view.$("[data-handlebars-id='" + dataId + "']");
151
151
 
152
152
  // If we aren't able to find the element, it means the element
@@ -154,7 +154,7 @@ Handlebars.registerHelper('bindAttr', function(options) {
154
154
  // In that case, we can assume the template has been re-rendered
155
155
  // and we need to clean up the observer.
156
156
  if (elem.length === 0) {
157
- view.removeObserver(property, observer);
157
+ this.removeObserver(property, observer);
158
158
  return;
159
159
  }
160
160
 
@@ -182,9 +182,112 @@ Handlebars.registerHelper('bindAttr', function(options) {
182
182
  // Return the current value, in the form src="foo.jpg"
183
183
  ret.push(attr+'="'+value+'"');
184
184
  }
185
- });
185
+ }, this);
186
186
 
187
187
  // Add the unique identifier
188
188
  ret.push('data-handlebars-id="'+dataId+'"');
189
189
  return ret.join(' ');
190
190
  });
191
+
192
+ /**
193
+ Helper that, given a space-separated string of property paths and a context,
194
+ returns an array of class names. Calling this method also has the side effect
195
+ of setting up observers at those property paths, such that if they change,
196
+ the correct class name will be reapplied to the DOM element.
197
+
198
+ For example, if you pass the string "fooBar", it will first look up the "fooBar"
199
+ value of the context. If that value is YES, it will add the "foo-bar" class
200
+ to the current element (i.e., the dasherized form of "fooBar"). If the value
201
+ is a string, it will add that string as the class. Otherwise, it will not add
202
+ any new class name.
203
+
204
+ @param {SC.Object} context The context from which to lookup properties
205
+ @param {String} classBindings A string, space-separated, of class bindings to use
206
+ @param {SC.View} view The view in which observers should look for the element to update
207
+ @param {String} id Optional id use to lookup elements
208
+
209
+ @returns {Array} An array of class names to add
210
+ */
211
+ SC.Handlebars.bindClasses = function(context, classBindings, view, id) {
212
+ var ret = [], newClass, value, elem;
213
+
214
+ // Helper method to retrieve the property from the context and
215
+ // determine which class string to return, based on whether it is
216
+ // a Boolean or not.
217
+ var classStringForProperty = function(property) {
218
+ var val = context.getPath(property);
219
+
220
+ // If value is a Boolean and true, return the dasherized property
221
+ // name.
222
+ if (val === YES) {
223
+ // Normalize property path to be suitable for use
224
+ // as a class name. For exaple, content.foo.barBaz
225
+ // becomes bar-baz.
226
+ return property.split('.').get('lastObject').dasherize();
227
+
228
+ // If the value is not NO, undefined, or null, return the current
229
+ // value of the property.
230
+ } else if (val !== NO && val !== undefined && val !== null) {
231
+ return val;
232
+
233
+ // Nothing to display. Return null so that the old class is removed
234
+ // but no new class is added.
235
+ } else {
236
+ return null;
237
+ }
238
+ };
239
+
240
+ // For each property passed, loop through and setup
241
+ // an observer.
242
+ classBindings.split(' ').forEach(function(property) {
243
+
244
+ // Variable in which the old class value is saved. The observer function
245
+ // closes over this variable, so it knows which string to remove when
246
+ // the property changes.
247
+ var oldClass;
248
+
249
+ // Set up an observer on the context. If the property changes, toggle the
250
+ // class name.
251
+ var observer = function() {
252
+ // Get the current value of the property
253
+ newClass = classStringForProperty(property);
254
+ elem = id ? view.$("[data-handlebars-id='" + id + "']") : view.$();
255
+
256
+ // If we can't find the element anymore, a parent template has been
257
+ // re-rendered and we've been nuked. Remove the observer.
258
+ if (elem.length === 0) {
259
+ context.removeObserver(property, observer);
260
+ } else {
261
+ // If we had previously added a class to the element, remove it.
262
+ if (oldClass) {
263
+ elem.removeClass(oldClass);
264
+ }
265
+
266
+ // If necessary, add a new class. Make sure we keep track of it so
267
+ // it can be removed in the future.
268
+ if (newClass) {
269
+ elem.addClass(newClass);
270
+ oldClass = newClass;
271
+ } else {
272
+ oldClass = null;
273
+ }
274
+ }
275
+ };
276
+
277
+ context.addObserver(property, observer);
278
+
279
+ // We've already setup the observer; now we just need to figure out the correct
280
+ // behavior right now on the first pass through.
281
+ value = classStringForProperty(property);
282
+
283
+ if (value) {
284
+ ret.push(value);
285
+
286
+ // Make sure we save the current value so that it can be removed if the observer
287
+ // fires.
288
+ oldClass = value;
289
+ }
290
+ });
291
+
292
+ return ret;
293
+ };
@@ -1,4 +1,4 @@
1
- sc_require('extensions');
1
+ sc_require('ext/handlebars');
2
2
 
3
3
  Handlebars.registerHelper('collection', function(path, options) {
4
4
  var fn = options.fn;
@@ -27,15 +27,18 @@ Handlebars.registerHelper('collection', function(path, options) {
27
27
  }
28
28
 
29
29
  if(fn) {
30
+ var extensions = {
31
+ itemViewTemplate: fn,
32
+ inverseTemplate: inverse,
33
+ itemViewOptions: itemHash
34
+ };
35
+
30
36
  if(collectionClass.isClass) {
31
- collectionObject = collectionClass.create();
37
+ collectionObject = collectionClass.extend(extensions);
32
38
  } else {
39
+ SC.mixin(collectionClass, extensions);
33
40
  collectionObject = collectionClass;
34
41
  }
35
-
36
- collectionObject.itemViewTemplate = fn;
37
- collectionObject.inverseTemplate = inverse;
38
- collectionObject.itemViewOptions = itemHash;
39
42
  }
40
43
 
41
44
  options.fn = function() { return ""; };
@@ -44,7 +47,7 @@ Handlebars.registerHelper('collection', function(path, options) {
44
47
  });
45
48
 
46
49
  Handlebars.registerHelper('each', function(path, options) {
47
- options.hash.content = SC.getPath(this, path);
50
+ options.hash.contentBinding = SC.Binding.from('*'+path, this);
48
51
  options.hash.itemContextProperty = 'content';
49
52
  return Handlebars.helpers.collection.call(this, null, options);
50
53
  });
@@ -1,4 +1,4 @@
1
- sc_require('extensions');
1
+ sc_require('ext/handlebars');
2
2
 
3
3
  Handlebars.registerHelper('loc', function(property) {
4
4
  return property.loc();
@@ -1,4 +1,4 @@
1
- sc_require('extensions');
1
+ sc_require('ext/handlebars');
2
2
 
3
3
  SC.Handlebars.ViewHelper = SC.Object.create({
4
4
  helper: function(thisContext, path, options) {
@@ -28,6 +28,8 @@ SC.Handlebars.ViewHelper = SC.Object.create({
28
28
  if (!newView) { throw "Unable to find view at path '" + path + "'"; }
29
29
  }
30
30
 
31
+ if (hash.id) { hash.layerId = hash.id; }
32
+
31
33
  var contextOptions = {
32
34
  'id': hash.id,
33
35
  'class': hash['class'],
@@ -81,7 +83,7 @@ SC.Handlebars.ViewHelper = SC.Object.create({
81
83
 
82
84
  var classBindings = options.classBinding;
83
85
  if (classBindings) {
84
- SC.Handlebars.bindClasses(childView, classBindings).forEach(function(className) {
86
+ SC.Handlebars.bindClasses(childView, classBindings, childView).forEach(function(className) {
85
87
  context.setClass(className, YES);
86
88
  });
87
89
  }
@@ -1,5 +1,3 @@
1
- sc_require("handlebars");
2
-
3
1
  /**
4
2
  Prepares the Handlebars templating library for use inside SproutCore's view
5
3
  system.
@@ -73,58 +71,3 @@ Handlebars.registerHelper('helperMissing', function(path, options) {
73
71
  error = "%@ Handlebars error: Could not find property '%@' on object %@.";
74
72
  throw error.fmt(options.data.view, path, this);
75
73
  });
76
-
77
- /**
78
- Determines the classes to add based on an array of bindings (provided as strings),
79
- as well as adding observers to make sure the classes are up-to-date.
80
-
81
- @param {SC.View} view The view at add the classes to
82
- @param {String} classBindings A string, space-separated, of class bindings to use
83
- @param {String|Number} id Optional id to scope the observers/jQuery element to
84
- @returns {Array} An array of class names to add
85
- */
86
- SC.Handlebars.bindClasses = function(view, classBindings, id) {
87
- if (!view._classObservers) view._classObservers = {};
88
- id = id || '_default';
89
- var classObservers = view._classObservers[id],
90
- ret = [];
91
-
92
- // Teardown any existing observers on the view.
93
- if (classObservers) {
94
- for (var prop in classObservers) {
95
- if (classObservers.hasOwnProperty(prop)) {
96
- view.removeObserver(prop, classObservers[prop]);
97
- }
98
- }
99
- }
100
-
101
- classObservers = view._classObservers[id] = {};
102
-
103
- // For each property passed, loop through and setup
104
- // an observer.
105
- classBindings.split(' ').forEach(function(property) {
106
- // Normalize property path to be suitable for use
107
- // as a class name. For exaple, content.foo.barBaz
108
- // becomes bar-baz.
109
-
110
- var dasherizedProperty = property.split('.').get('lastObject').dasherize();
111
-
112
- // Set up an observer on the view. If the bound property
113
- // changes, toggle the class name
114
- var observer = (classObservers[property] = function() {
115
- var shouldDisplay = view.getPath(property);
116
- var elem = id !== '_default' ? view.$("[data-handlebars-id='" + id + "']") : view.$();
117
-
118
- if (elem.length === 0) {
119
- view.removeObserver(property, observer);
120
- } else {
121
- elem.toggleClass(dasherizedProperty, shouldDisplay);
122
- }
123
- });
124
-
125
- view.addObserver(property, observer);
126
- if (view.getPath(property)) ret.push(dasherizedProperty);
127
- });
128
-
129
- return ret;
130
- };
@@ -15,9 +15,7 @@ SC.mixin(SC.Object.prototype, /** @scope SC.Object.prototype */ {
15
15
  invoke a method after a period of time. The method should have the
16
16
  signature:
17
17
 
18
- {{{
19
- methodName: function(timer)
20
- }}}
18
+ methodName: function(timer)
21
19
 
22
20
  If you would prefer to pass your own parameters instead, you can instead
23
21
  call invokeLater() directly on the function object itself.
@@ -33,6 +33,17 @@ SC.TextFieldSupport = /** @scope SC.TextFieldSupport.prototype */{
33
33
  this.tryToPerform('blur', event);
34
34
  },
35
35
 
36
+ /** @private
37
+ Make sure our input value is synced with any bindings.
38
+ In some cases, such as auto-filling, a value can get
39
+ changed without an event firing. We could do this
40
+ on focusOut, but blur can potentially get called
41
+ after other events.
42
+ */
43
+ willLoseFirstResponder: function() {
44
+ this.notifyPropertyChange('value');
45
+ },
46
+
36
47
  keyUp: function(event) {
37
48
  if (event.keyCode === 13) {
38
49
  return this.tryToPerform('insertNewline', event);
@@ -17,9 +17,7 @@ sc_require('panes/pane');
17
17
  will also make itself key automatically. The default way to use the main
18
18
  pane is to simply add it to your page like this:
19
19
 
20
- {{{
21
- SC.MainPane.create().append();
22
- }}}
20
+ SC.MainPane.create().append();
23
21
 
24
22
  This will cause your root view to display. The default layout for a
25
23
  MainPane is to cover the entire document window and to resize with the
@@ -29,10 +29,8 @@ SC.MIXED_STATE = '__MIXED__' ;
29
29
  To make a pane visible, you need to add it to your HTML document. The
30
30
  simplest way to do this is to call the append() method:
31
31
 
32
- {{{
33
- myPane = SC.Pane.create();
34
- myPane.append(); // adds the pane to the document
35
- }}}
32
+ myPane = SC.Pane.create();
33
+ myPane.append(); // adds the pane to the document
36
34
 
37
35
  This will insert your pane into the end of your HTML document body, causing
38
36
  it to display on screen. It will also register your pane with the
@@ -7,25 +7,23 @@
7
7
 
8
8
  /** @class
9
9
 
10
- The root object for a SproutCore application. Usually you will create a
10
+ The root object for a SproutCore application. Usually you will create a
11
11
  single SC.Application instance as your root namespace. SC.Application is
12
12
  required if you intend to use SC.Responder to route events.
13
-
14
- h2. Example
15
-
16
- {{{
17
- Contacts = SC.Application.create({
18
- store: SC.Store.create(SC.Record.fixtures),
19
-
20
- // add other useful properties here
21
- });
22
- }}}
23
-
24
- h2. Sending Events
25
-
13
+
14
+ ## Example
15
+
16
+ Contacts = SC.Application.create({
17
+ store: SC.Store.create(SC.Record.fixtures),
18
+
19
+ // add other useful properties here
20
+ });
21
+
22
+ ## Sending Events
23
+
26
24
  You can send actions and events down an application-level responder chain
27
- by
28
-
25
+ by
26
+
29
27
  @extends SC.ResponderContext
30
28
  @since SproutCore 1.0
31
29
  */
@@ -12,41 +12,35 @@
12
12
  builder yourself, but you will often use instances of the Builder object to
13
13
  configure parts of the UI such as menus and views.
14
14
 
15
- h1. Anatomy of a Builder
15
+ # Anatomy of a Builder
16
16
 
17
17
  You can create a new Builder much like you would any other class in
18
18
  SproutCore. For example, you could create a new CoreQuery-type object with
19
19
  the following:
20
20
 
21
- {{{
22
- SC.$ = SC.Builder.create({
23
- // methods you can call go here.
24
- });
25
- }}}
21
+ SC.$ = SC.Builder.create({
22
+ // methods you can call go here.
23
+ });
26
24
 
27
25
  Unlike most classes in SproutCore, Builder objects are actually functions
28
26
  that you can call to create new instances. In the example above, to use
29
27
  the builder, you must call it like a function:
30
28
 
31
- {{{
32
- buildit = SC.$();
33
- }}}
29
+ buildit = SC.$();
34
30
 
35
31
  If you define an init() method on a builder, it will be invoked wheneve the
36
32
  builder is called as a function, including any passed params. Your init()
37
33
  method MUST return this, unlike regular SC objects. i.e.
38
34
 
39
- {{{
40
- SC.$ = SC.Builder.create({
41
- init: function(args) {
42
- this.args = SC.A(args);
43
- return this;
44
- }
45
- });
46
-
47
- buildit = SC.$('a', 'b');
48
- buildit.args => ['a','b']
49
- }}}
35
+ SC.$ = SC.Builder.create({
36
+ init: function(args) {
37
+ this.args = SC.A(args);
38
+ return this;
39
+ }
40
+ });
41
+
42
+ buildit = SC.$('a', 'b');
43
+ buildit.args => ['a','b']
50
44
 
51
45
  In addition to defining a function like this, all builder objects also have
52
46
  an 'fn' property that contains a hash of all of the helper methods defined
@@ -54,16 +48,14 @@
54
48
  addition "plugins" for the builder by simply adding new methods to the
55
49
  fn property.
56
50
 
57
- h1. Writing Builder Functions
51
+ # Writing Builder Functions
58
52
 
59
- All builders share a few things in comming:
53
+ All builders share a few things in common:
60
54
 
61
- - when a new builder is created, it's init() method will be called. The default version of this method simply copies the passed parameters into the builder as content, but you can override this with anything you want.
55
+ * when a new builder is created, it's init() method will be called. The default version of this method simply copies the passed parameters into the builder as content, but you can override this with anything you want.
56
+ * the content the builder works on is stored as indexed properties (i.e. 0,1,2,3, like an array). The builder should also have a length property if you want it treated like an array.
57
+ *- Builders also maintain a stack of previous builder instances which you can pop off at any time.
62
58
 
63
- - the content the builder works on is stored as indexed properties (i.e. 0,1,2,3, like an array). The builder should also have a length property if you want it treated like an array.
64
-
65
- - Builders also maintain a stack of previous builder instances which you can pop off at any time.
66
-
67
59
  To get content back out of a builder once you are ready with it, you can
68
60
  call the method done(). This will return an array or a single object, if
69
61
  the builder only works on a single item.
@@ -71,16 +63,16 @@
71
63
  You should write your methods using the getEach() iterator to work on your
72
64
  member objects. All builders implement SC.Enumerable in the fn() method.
73
65
 
74
- CoreQuery = SC.Builder.create({
75
- ...
76
- }) ;
77
-
78
- CoreQuery = new SC.Builder(properties) {
79
-
80
- } ;
81
-
82
- CoreQuery2 = CoreQuery.extend() {
83
- }
66
+ CoreQuery = SC.Builder.create({
67
+ ...
68
+ }) ;
69
+
70
+ CoreQuery = new SC.Builder(properties) {
71
+ ...
72
+ } ;
73
+
74
+ CoreQuery2 = CoreQuery.extend() {
75
+ }
84
76
 
85
77
  @constructor
86
78
  */
@@ -79,7 +79,7 @@ SC.Event = function(originalEvent) {
79
79
 
80
80
  // Normalize wheel delta values for mousewheel events
81
81
  if (this.type === 'mousewheel' || this.type === 'DOMMouseScroll' || this.type === 'MozMousePixelScroll') {
82
- var deltaMultiplier = 1,
82
+ var deltaMultiplier = SC.Event.MOUSE_WHEEL_MULTIPLIER,
83
83
  version = parseFloat(SC.browser.version);
84
84
 
85
85
  // normalize wheelDelta, wheelDeltaX, & wheelDeltaY for Safari
@@ -88,23 +88,10 @@ SC.Event = function(originalEvent) {
88
88
  this.wheelDeltaY = 0-(originalEvent.wheelDeltaY||0);
89
89
  this.wheelDeltaX = 0-(originalEvent.wheelDeltaX||0);
90
90
 
91
- // Check Chrome first since it also responds to safari
92
- if (!SC.browser.chrome) {
93
- // Scrolling in Safari 5.0.1, which is huge for some reason
94
- if (version >= 533.17 && version <= 533.19) {
95
- deltaMultiplier = 0.004;
96
-
97
- // Scrolling in Safari 5.0
98
- } else if (version < 533 || version >= 534) {
99
- deltaMultiplier = 40;
100
- }
101
- }
102
-
103
91
  // normalize wheelDelta for Firefox
104
92
  // note that we multiple the delta on FF to make it's acceleration more
105
93
  // natural.
106
94
  } else if (!SC.none(originalEvent.detail) && SC.browser.mozilla) {
107
- deltaMultiplier = 10;
108
95
  if (originalEvent.axis && (originalEvent.axis === originalEvent.HORIZONTAL_AXIS)) {
109
96
  this.wheelDeltaX = originalEvent.detail;
110
97
  this.wheelDeltaY = this.wheelDelta = 0;
@@ -119,6 +106,15 @@ SC.Event = function(originalEvent) {
119
106
  this.wheelDeltaX = 0 ;
120
107
  }
121
108
 
109
+ // we have a value over the limit and it wasn't caught when we generated MOUSE_WHEEL_MULTIPLIER
110
+ // this will happen as new Webkit-based browsers are released and we haven't covered them off
111
+ // in our browser detection. It'll scroll too quickly the first time, but we might as well learn
112
+ // and change our handling for the next scroll
113
+ if (this.wheelDelta > SC.Event.MOUSE_WHEEL_DELTA_LIMIT && !SC.Event._MOUSE_WHEEL_LIMIT_INVALIDATED) {
114
+ deltaMultiplier = SC.Event.MOUSE_WHEEL_MULTIPLIER = 0.004;
115
+ SC.Event._MOUSE_WHEEL_LIMIT_INVALIDATED = YES;
116
+ }
117
+
122
118
  this.wheelDelta *= deltaMultiplier;
123
119
  this.wheelDeltaX *= deltaMultiplier;
124
120
  this.wheelDeltaY *= deltaMultiplier;
@@ -129,6 +125,64 @@ SC.Event = function(originalEvent) {
129
125
 
130
126
  SC.mixin(SC.Event, /** @scope SC.Event */ {
131
127
 
128
+ /**
129
+ We need this because some browsers deliver different values
130
+ for mouse wheel deltas. Once the first mouse wheel event has
131
+ been run, this value will get set. Because we don't know the
132
+ maximum or minimum value ahead of time, if the event's delta
133
+ exceeds `SC.Event.MOUSE_WHEEL_DELTA_LIMIT`, this value can be
134
+ invalidated and changed during a later event.
135
+
136
+ @field
137
+ @type Number
138
+ @default 1
139
+ */
140
+ MOUSE_WHEEL_MULTIPLIER: (function() {
141
+ var deltaMultiplier = 1,
142
+ version = parseFloat(SC.browser.version),
143
+ didChange = NO;
144
+
145
+ if (SC.browser.webkit) {
146
+ // Check Chrome first since it also responds to safari
147
+ if (!SC.browser.chrome) {
148
+ // Scrolling in Safari 5.0.1, which is huge for some reason
149
+ if (version >= 533.17 && version <= 533.20) {
150
+ deltaMultiplier = 0.004;
151
+ didChange = YES;
152
+ // Scrolling in Safari 5.0
153
+ } else if (version < 533 || version >= 534) {
154
+ deltaMultiplier = 40;
155
+ didChange = YES;
156
+ }
157
+ }
158
+ } else if (SC.browser.mozilla) {
159
+ deltaMultiplier = 10;
160
+ didChange = YES;
161
+ }
162
+
163
+ if (didChange) { SC.Event._MOUSE_WHEEL_LIMIT_INVALIDATED = YES; }
164
+
165
+ return deltaMultiplier;
166
+ })(),
167
+
168
+ /**
169
+ This represents the limit in the delta before a different multiplier
170
+ will be applied. Because we can't generated an accurate mouse
171
+ wheel event ahead of time, and browsers deliver differing values
172
+ for mouse wheel deltas, this is necessary to ensure that
173
+ browsers that scale their values largely are dealt with correctly
174
+ in the future.
175
+
176
+ @type Number
177
+ @default 1000
178
+ */
179
+ MOUSE_WHEEL_DELTA_LIMIT: 1000,
180
+
181
+ /** @private
182
+ We only want to invalidate once
183
+ */
184
+ _MOUSE_WHEEL_LIMIT_INVALIDATED: NO,
185
+
132
186
  /**
133
187
  Standard method to create a new event. Pass the native browser event you
134
188
  wish to wrap if needed.
@@ -387,7 +441,7 @@ SC.mixin(SC.Event, /** @scope SC.Event */ {
387
441
  Trigger an event execution immediately. You can use this method to
388
442
  simulate arbitrary events on arbitary elements.
389
443
 
390
- h2. Limitations
444
+ ## Limitations
391
445
 
392
446
  Note that although this is based on the jQuery implementation, it is
393
447
  much simpler. Notably namespaced events are not supported and you cannot
@@ -396,11 +450,9 @@ SC.mixin(SC.Event, /** @scope SC.Event */ {
396
450
  If you need more advanced event handling, consider the SC.Responder
397
451
  functionality provided by SproutCore or use your favorite DOM library.
398
452
 
399
- h2. Example
453
+ ## Example
400
454
 
401
- {{{
402
- SC.Event.trigger(view.get('layer'), 'mousedown');
403
- }}}
455
+ SC.Event.trigger(view.get('layer'), 'mousedown');
404
456
 
405
457
  @param elem {Element} the target element
406
458
  @param eventType {String} the event type
@@ -15,21 +15,17 @@
15
15
  languages and saved at SC.Locale.current. This locale is used for
16
16
  localization, etc.
17
17
 
18
- h2. Creating a new locale
18
+ ## Creating a new locale
19
19
 
20
20
  You can create a locale by simply extending the SC.Locale class and adding
21
21
  it to the locales hash:
22
22
 
23
- {{{
24
- SC.Locale.locales['en'] = SC.Locale.extend({ .. config .. }) ;
25
- }}}
23
+ SC.Locale.locales['en'] = SC.Locale.extend({ .. config .. }) ;
26
24
 
27
25
  Alternatively, you could choose to base your locale on another locale by
28
26
  extending that locale:
29
27
 
30
- {{{
31
- SC.Locale.locales['en-US'] = SC.Locale.locales['en'].extend({ ... }) ;
32
- }}}
28
+ SC.Locale.locales['en-US'] = SC.Locale.locales['en'].extend({ ... }) ;
33
29
 
34
30
  Note that if you do not define your own strings property, then your locale
35
31
  will inherit any strings added to the parent locale. Otherwise you must
@@ -23,13 +23,11 @@ SC.Page = SC.Object.extend(
23
23
  to use the owner object as a target, (as well as other objects
24
24
  accessible through the owner object). E.g.
25
25
 
26
- {{{
27
- myButton: SC.ButtonView.design({
28
- title: 'Click me',
29
- target: SC.outlet('page.owner'),
30
- action: 'buttonClicked'
31
- })
32
- }}}
26
+ myButton: SC.ButtonView.design({
27
+ title: 'Click me',
28
+ target: SC.outlet('page.owner'),
29
+ action: 'buttonClicked'
30
+ })
33
31
 
34
32
  Usually, you'll set 'owner' to the object defined in core.js.
35
33
  */