sproutcore 1.6.0.1 → 1.7.1.beta

Sign up to get free protection for your applications and to get access to all the features.
Files changed (143) hide show
  1. data/CHANGELOG +21 -0
  2. data/Gemfile +5 -0
  3. data/Rakefile +26 -13
  4. data/VERSION.yml +2 -2
  5. data/lib/Buildfile +43 -4
  6. data/lib/buildtasks/build.rake +10 -0
  7. data/lib/buildtasks/helpers/file_rule.rb +22 -0
  8. data/lib/buildtasks/helpers/file_rule_list.rb +137 -0
  9. data/lib/buildtasks/manifest.rake +133 -122
  10. data/lib/frameworks/sproutcore/CHANGELOG.md +69 -2
  11. data/lib/frameworks/sproutcore/apps/tests/english.lproj/strings.js +1 -0
  12. data/lib/frameworks/sproutcore/frameworks/bootstrap/system/browser.js +28 -22
  13. data/lib/frameworks/sproutcore/frameworks/core_foundation/controllers/array.js +9 -5
  14. data/lib/frameworks/sproutcore/frameworks/core_foundation/controllers/controller.js +1 -1
  15. data/lib/frameworks/sproutcore/frameworks/core_foundation/controls/button.js +18 -13
  16. data/lib/frameworks/sproutcore/frameworks/core_foundation/ext/handlebars/bind.js +5 -3
  17. data/lib/frameworks/sproutcore/frameworks/core_foundation/ext/handlebars/collection.js +2 -0
  18. data/lib/frameworks/sproutcore/frameworks/core_foundation/mixins/action_support.js +80 -0
  19. data/lib/frameworks/sproutcore/frameworks/core_foundation/mixins/template_helpers/text_field_support.js +84 -116
  20. data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/pane.js +8 -5
  21. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/event.js +157 -157
  22. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/platform.js +5 -3
  23. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/root_responder.js +6 -6
  24. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/sparse_array.js +10 -7
  25. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/mixins/action_support.js +106 -0
  26. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/template/collection.js +18 -0
  27. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/template/handlebars.js +71 -1
  28. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/attribute_bindings_test.js +38 -0
  29. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/class_name_bindings_test.js +47 -0
  30. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layoutChildViews.js +18 -18
  31. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layoutStyle.js +42 -10
  32. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/keyboard.js +26 -1
  33. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/layout_style.js +14 -8
  34. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view.js +158 -1
  35. data/lib/frameworks/sproutcore/frameworks/datastore/models/record.js +15 -2
  36. data/lib/frameworks/sproutcore/frameworks/datastore/models/record_attribute.js +108 -108
  37. data/lib/frameworks/sproutcore/frameworks/datastore/system/query.js +1 -1
  38. data/lib/frameworks/sproutcore/frameworks/datastore/system/record_array.js +2 -4
  39. data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/record/error_methods.js +2 -2
  40. data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/single_attribute.js +26 -0
  41. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/query/builders.js +7 -0
  42. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/record_array/error_methods.js +1 -1
  43. data/lib/frameworks/sproutcore/frameworks/datetime/frameworks/core/system/datetime.js +4 -1
  44. data/lib/frameworks/sproutcore/frameworks/datetime/frameworks/core/tests/system/datetime.js +6 -0
  45. data/lib/frameworks/sproutcore/frameworks/desktop/panes/menu.js +26 -5
  46. data/lib/frameworks/sproutcore/frameworks/desktop/panes/picker.js +97 -96
  47. data/lib/frameworks/sproutcore/frameworks/desktop/system/drag.js +4 -3
  48. data/lib/frameworks/sproutcore/frameworks/desktop/tests/panes/menu/ui.js +17 -4
  49. data/lib/frameworks/sproutcore/frameworks/desktop/views/collection.js +7 -7
  50. data/lib/frameworks/sproutcore/frameworks/desktop/views/menu_item.js +7 -5
  51. data/lib/frameworks/sproutcore/frameworks/desktop/views/scroll.js +12 -3
  52. data/lib/frameworks/sproutcore/frameworks/desktop/views/web.js +23 -14
  53. data/lib/frameworks/sproutcore/frameworks/experimental/Buildfile +5 -1
  54. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/menu/render_delegates/menu_scroller.js +28 -0
  55. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/menu/tests/menu/scroll.js +235 -0
  56. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/menu/views/menu/scroll.js +363 -0
  57. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/menu/views/menu/scroller.js +250 -0
  58. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/render_delegates/desktop_scroller.js +92 -0
  59. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/render_delegates/native_scroll.js +25 -0
  60. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/render_delegates/scroll.js +33 -0
  61. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/render_delegates/touch_scroller.js +76 -0
  62. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/tests/scroll/integration.js +50 -0
  63. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/tests/scroll/methods.js +143 -0
  64. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/tests/scroll/ui.js +258 -0
  65. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/core_scroll.js +1164 -0
  66. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/core_scroller.js +332 -0
  67. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/desktop/scroll.js +236 -0
  68. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/desktop/scroller.js +347 -0
  69. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/scroll.js +15 -0
  70. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/scroller.js +10 -0
  71. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/touch/scroll.js +804 -0
  72. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/touch/scroller.js +133 -0
  73. data/lib/frameworks/sproutcore/frameworks/foundation/resources/text_field.css +3 -3
  74. data/lib/frameworks/sproutcore/frameworks/foundation/validators/number.js +3 -1
  75. data/lib/frameworks/sproutcore/frameworks/foundation/views/text_field.js +3 -3
  76. data/lib/frameworks/sproutcore/frameworks/media/views/audio.js +2 -1
  77. data/lib/frameworks/sproutcore/frameworks/media/views/controls.js +2 -1
  78. data/lib/frameworks/sproutcore/frameworks/media/views/media_slider.js +2 -4
  79. data/lib/frameworks/sproutcore/frameworks/media/views/mini_controls.js +2 -4
  80. data/lib/frameworks/sproutcore/frameworks/media/views/simple_controls.js +2 -4
  81. data/lib/frameworks/sproutcore/frameworks/media/views/video.js +2 -2
  82. data/lib/frameworks/sproutcore/frameworks/routing/system/routes.js +29 -3
  83. data/lib/frameworks/sproutcore/frameworks/runtime/core.js +2 -2
  84. data/lib/frameworks/sproutcore/frameworks/runtime/debug/test_suites/array/replace.js +1 -1
  85. data/lib/frameworks/sproutcore/frameworks/runtime/private/property_chain.js +2 -1
  86. data/lib/frameworks/sproutcore/frameworks/runtime/system/binding.js +3 -3
  87. data/lib/frameworks/sproutcore/frameworks/runtime/system/index_set.js +2 -2
  88. data/lib/frameworks/sproutcore/frameworks/runtime/system/object.js +1 -1
  89. data/lib/frameworks/sproutcore/themes/ace/resources/collection/normal/list_item.css +2 -2
  90. data/lib/frameworks/sproutcore/themes/legacy_theme/english.lproj/segmented.css +1 -1
  91. data/lib/gen/app/templates/apps/@target_name@/Buildfile +3 -5
  92. data/lib/gen/app/templates/apps/@target_name@/resources/_theme.css +18 -0
  93. data/lib/gen/project/templates/@filename@/Buildfile +2 -2
  94. data/lib/sproutcore/builders/chance_file.rb +9 -16
  95. data/lib/sproutcore/builders/html.rb +2 -1
  96. data/lib/sproutcore/builders/minify.rb +4 -35
  97. data/lib/sproutcore/builders/module.rb +38 -1
  98. data/lib/sproutcore/builders/split.rb +63 -0
  99. data/lib/sproutcore/builders/strings.rb +7 -1
  100. data/lib/sproutcore/builders.rb +1 -0
  101. data/lib/sproutcore/helpers/css_split.rb +190 -0
  102. data/lib/sproutcore/helpers/entry_sorter.rb +2 -0
  103. data/lib/sproutcore/helpers/minifier.rb +40 -16
  104. data/lib/sproutcore/helpers/static_helper.rb +35 -17
  105. data/lib/sproutcore/helpers.rb +1 -1
  106. data/lib/sproutcore/models/manifest.rb +26 -0
  107. data/lib/sproutcore/models/target.rb +12 -1
  108. data/lib/sproutcore/rack/proxy.rb +244 -225
  109. data/lib/sproutcore/rack/restrict_ip.rb +67 -0
  110. data/lib/sproutcore/rack/service.rb +8 -2
  111. data/lib/sproutcore/rack.rb +1 -0
  112. data/lib/sproutcore/tools/build.rb +91 -43
  113. data/lib/sproutcore/tools/gen.rb +2 -3
  114. data/lib/sproutcore/tools/manifest.rb +22 -16
  115. data/lib/sproutcore/tools/server.rb +21 -0
  116. data/lib/sproutcore/tools.rb +102 -46
  117. data/lib/sproutcore.rb +30 -5
  118. data/spec/buildtasks/helpers/accept_list +22 -0
  119. data/spec/buildtasks/helpers/accept_list.rb +128 -0
  120. data/spec/buildtasks/helpers/list.json +11 -0
  121. data/spec/buildtasks/manifest/prepare_build_tasks/chance_2x_spec.rb +1 -39
  122. data/spec/buildtasks/manifest/prepare_build_tasks/chance_spec.rb +0 -38
  123. data/spec/buildtasks/manifest/prepare_build_tasks/combine_spec.rb +4 -4
  124. data/spec/buildtasks/manifest/prepare_build_tasks/module_spec.rb +2 -2
  125. data/spec/buildtasks/manifest/prepare_build_tasks/packed_2x_indirect_spec.rb +7 -16
  126. data/spec/buildtasks/manifest/prepare_build_tasks/packed_2x_spec.rb +7 -17
  127. data/spec/buildtasks/manifest/prepare_build_tasks/packed_spec.rb +11 -6
  128. data/spec/fixtures/builder_tests/Buildfile +2 -1
  129. data/spec/fixtures/builder_tests/apps/module_test/modules/required_module/core.js +0 -0
  130. data/spec/lib/builders/module_spec.rb +1 -1
  131. data/spec/spec_helper.rb +1 -0
  132. data/sproutcore.gemspec +4 -9
  133. data/vendor/chance/lib/chance/factory.rb +45 -0
  134. data/vendor/chance/lib/chance/instance/data_url.rb +0 -29
  135. data/vendor/chance/lib/chance/instance/slicing.rb +57 -4
  136. data/vendor/chance/lib/chance/instance/spriting.rb +112 -21
  137. data/vendor/chance/lib/chance/instance.rb +173 -28
  138. data/vendor/chance/lib/chance/parser.rb +80 -52
  139. data/vendor/chance/lib/chance.rb +25 -6
  140. data/vendor/sproutcore/SCCompiler.jar +0 -0
  141. data/vendor/sproutcore/lib/args4j-2.0.12.jar +0 -0
  142. data/vendor/sproutcore/lib/yuicompressor-2.4.2.jar +0 -0
  143. metadata +97 -38
@@ -12,33 +12,33 @@ sc_require('models/record');
12
12
  A RecordAttribute describes a single attribute on a record. It is used to
13
13
  generate computed properties on records that can automatically convert data
14
14
  types and verify data.
15
-
16
- When defining an attribute on an SC.Record, you can configure it this way:
17
-
18
- title: SC.Record.attr(String, {
15
+
16
+ When defining an attribute on an SC.Record, you can configure it this way:
17
+
18
+ title: SC.Record.attr(String, {
19
19
  defaultValue: 'Untitled',
20
20
  isRequired: YES|NO
21
21
  })
22
-
23
- In addition to having predefined transform types, there is also a way to
22
+
23
+ In addition to having predefined transform types, there is also a way to
24
24
  set a computed relationship on an attribute. A typical example of this would
25
- be if you have record with a parentGuid attribute, but are not able to
25
+ be if you have record with a parentGuid attribute, but are not able to
26
26
  determine which record type to map to before looking at the guid (or any
27
- other attributes). To set up such a computed property, you can attach a
27
+ other attributes). To set up such a computed property, you can attach a
28
28
  function in the attribute definition of the SC.Record subclass:
29
-
29
+
30
30
  relatedToComputed: SC.Record.toOne(function() {
31
31
  return (this.readAttribute('relatedToComputed').indexOf("foo")==0) ? MyApp.Foo : MyApp.Bar;
32
32
  })
33
-
34
- Notice that we are not using .get() to avoid another transform which would
33
+
34
+ Notice that we are not using .get() to avoid another transform which would
35
35
  trigger an infinite loop.
36
-
36
+
37
37
  You usually will not work with RecordAttribute objects directly, though you
38
38
  may extend the class in any way that you like to create a custom attribute.
39
39
 
40
40
  A number of default RecordAttribute types are defined on the SC.Record.
41
-
41
+
42
42
  @extends SC.Object
43
43
  @see SC.Record
44
44
  @see SC.ManyAttribute
@@ -60,75 +60,75 @@ SC.RecordAttribute = SC.Object.extend(
60
60
  value will be substituted instead. Note that `defaultValue`s are not
61
61
  converted, so the value should be in the output type expected by the
62
62
  attribute.
63
-
63
+
64
64
  If you use a `defaultValue` function, the arguments given to it are the
65
65
  record instance and the key.
66
-
66
+
67
67
  @type Object|function
68
68
  @default null
69
69
  */
70
70
  defaultValue: null,
71
-
71
+
72
72
  /**
73
73
  The attribute type. Must be either an object class or a property path
74
- naming a class. The built in handler allows all native types to pass
74
+ naming a class. The built in handler allows all native types to pass
75
75
  through, converts records to ids and dates to UTF strings.
76
-
76
+
77
77
  If you use the `attr()` helper method to create a RecordAttribute instance,
78
78
  it will set this property to the first parameter you pass.
79
-
79
+
80
80
  @type Object|String
81
81
  @default String
82
82
  */
83
83
  type: String,
84
-
84
+
85
85
  /**
86
86
  The underlying attribute key name this attribute should manage. If this
87
87
  property is left empty, then the key will be whatever property name this
88
88
  attribute assigned to on the record. If you need to provide some kind
89
89
  of alternate mapping, this provides you a way to override it.
90
-
90
+
91
91
  @type String
92
92
  @default null
93
93
  */
94
94
  key: null,
95
-
95
+
96
96
  /**
97
97
  If `YES`, then the attribute is required and will fail validation unless
98
98
  the property is set to a non-null or undefined value.
99
-
99
+
100
100
  @type Boolean
101
101
  @default NO
102
102
  */
103
103
  isRequired: NO,
104
-
104
+
105
105
  /**
106
106
  If `NO` then attempts to edit the attribute will be ignored.
107
-
107
+
108
108
  @type Boolean
109
109
  @default YES
110
110
  */
111
- isEditable: YES,
112
-
111
+ isEditable: YES,
112
+
113
113
  /**
114
- If set when using the Date format, expect the ISO8601 date format.
114
+ If set when using the Date format, expect the ISO8601 date format.
115
115
  This is the default.
116
-
116
+
117
117
  @type Boolean
118
118
  @default YES
119
119
  */
120
120
  useIsoDate: YES,
121
-
121
+
122
122
  /**
123
123
  Can only be used for toOne or toMany relationship attributes. If YES,
124
124
  this flag will ensure that any related objects will also be marked
125
- dirty when this record dirtied.
126
-
127
- Useful when you might have multiple related objects that you want to
125
+ dirty when this record dirtied.
126
+
127
+ Useful when you might have multiple related objects that you want to
128
128
  consider in an 'aggregated' state. For instance, by changing a child
129
- object (image) you might also want to automatically mark the parent
129
+ object (image) you might also want to automatically mark the parent
130
130
  (album) dirty as well.
131
-
131
+
132
132
  @type Boolean
133
133
  @default NO
134
134
  */
@@ -154,16 +154,16 @@ SC.RecordAttribute = SC.Object.extend(
154
154
  @default NO
155
155
  */
156
156
  lazilyInstantiate: NO,
157
-
157
+
158
158
  // ..........................................................
159
159
  // HELPER PROPERTIES
160
- //
161
-
160
+ //
161
+
162
162
  /**
163
163
  Returns the type, resolved to a class. If the type property is a regular
164
- class, returns the type unchanged. Otherwise attempts to lookup the
164
+ class, returns the type unchanged. Otherwise attempts to lookup the
165
165
  type as a property path.
166
-
166
+
167
167
  @property
168
168
  @type Object
169
169
  @default String
@@ -173,12 +173,12 @@ SC.RecordAttribute = SC.Object.extend(
173
173
  if (SC.typeOf(ret) === SC.T_STRING) ret = SC.requiredObjectForPropertyPath(ret);
174
174
  return ret ;
175
175
  }.property('type').cacheable(),
176
-
176
+
177
177
  /**
178
178
  Finds the transform handler. Attempts to find a transform that you
179
179
  registered using registerTransform for this attribute's type, otherwise
180
180
  defaults to using the default transform for String.
181
-
181
+
182
182
  @property
183
183
  @type Transform
184
184
  */
@@ -186,7 +186,7 @@ SC.RecordAttribute = SC.Object.extend(
186
186
  var klass = this.get('typeClass') || String,
187
187
  transforms = SC.RecordAttribute.transforms,
188
188
  ret ;
189
-
189
+
190
190
  // walk up class hierarchy looking for a transform handler
191
191
  while(klass && !(ret = transforms[SC.guidFor(klass)])) {
192
192
  // check if super has create property to detect SC.Object's
@@ -194,20 +194,20 @@ SC.RecordAttribute = SC.Object.extend(
194
194
  // otherwise return the function transform handler
195
195
  else klass = SC.T_FUNCTION ;
196
196
  }
197
-
197
+
198
198
  return ret ;
199
199
  }.property('typeClass').cacheable(),
200
-
200
+
201
201
  // ..........................................................
202
202
  // LOW-LEVEL METHODS
203
- //
204
-
205
- /**
206
- Converts the passed value into the core attribute value. This will apply
203
+ //
204
+
205
+ /**
206
+ Converts the passed value into the core attribute value. This will apply
207
207
  any format transforms. You can install standard transforms by adding to
208
- the `SC.RecordAttribute.transforms` hash. See
208
+ the `SC.RecordAttribute.transforms` hash. See
209
209
  SC.RecordAttribute.registerTransform() for more.
210
-
210
+
211
211
  @param {SC.Record} record The record instance
212
212
  @param {String} key The key used to access this attribute on the record
213
213
  @param {Object} value The property value before being transformed
@@ -217,10 +217,10 @@ SC.RecordAttribute = SC.Object.extend(
217
217
  var transform = this.get('transform'),
218
218
  type = this.get('typeClass'),
219
219
  children;
220
-
220
+
221
221
  if (transform && transform.to) {
222
222
  value = transform.to(value, this, type, record, key) ;
223
-
223
+
224
224
  // if the transform needs to do something when its children change, we need to set up an observer for it
225
225
  if(!SC.none(value) && (children = transform.observesChildren)) {
226
226
  var i, len = children.length,
@@ -229,27 +229,27 @@ SC.RecordAttribute = SC.Object.extend(
229
229
  record: record,
230
230
  key: key
231
231
  };
232
-
232
+
233
233
  for(i = 0; i < len; i++) value.addObserver(children[i], this, this._SCRA_childObserver, context);
234
234
  }
235
235
  }
236
-
236
+
237
237
  return value ;
238
238
  },
239
-
239
+
240
240
  /**
241
241
  @private
242
-
242
+
243
243
  Shared observer used by any attribute whose transform creates a seperate
244
244
  object that needs to write back to the datahash when it changes. For
245
245
  example, when enumerable content changes on a `SC.Set` attribute, it
246
246
  writes back automatically instead of forcing you to call `.set` manually.
247
-
247
+
248
248
  This functionality can be used by setting an array named
249
249
  observesChildren on your transform containing the names of keys to
250
250
  observe. When one of them triggers it will call childDidChange on your
251
251
  transform with the same arguments as to and from.
252
-
252
+
253
253
  @param {Object} obj The transformed value that is being observed
254
254
  @param {String} key The key used to access this attribute on the record
255
255
  @param {Object} prev Previous value (not used)
@@ -258,15 +258,15 @@ SC.RecordAttribute = SC.Object.extend(
258
258
  _SCRA_childObserver: function(obj, key, prev, context) {
259
259
  // write the new value back to the record
260
260
  this.call(context.record, context.key, obj);
261
-
261
+
262
262
  // mark the attribute as dirty
263
263
  context.record.notifyPropertyChange(context.key);
264
264
  },
265
265
 
266
- /**
267
- Converts the passed value from the core attribute value. This will apply
266
+ /**
267
+ Converts the passed value from the core attribute value. This will apply
268
268
  any format transforms. You can install standard transforms by adding to
269
- the `SC.RecordAttribute.transforms` hash. See
269
+ the `SC.RecordAttribute.transforms` hash. See
270
270
  `SC.RecordAttribute.registerTransform()` for more.
271
271
 
272
272
  @param {SC.Record} record The record instance
@@ -277,7 +277,7 @@ SC.RecordAttribute = SC.Object.extend(
277
277
  fromType: function(record, key, value) {
278
278
  var transform = this.get('transform'),
279
279
  type = this.get('typeClass');
280
-
280
+
281
281
  if (transform && transform.from) {
282
282
  value = transform.from(value, this, type, record, key);
283
283
  }
@@ -289,7 +289,7 @@ SC.RecordAttribute = SC.Object.extend(
289
289
  parent record, since `SC.RecordAttribute` uses `isProperty` to masquerade
290
290
  as a computed property. Get expects a property be a function, thus we
291
291
  need to implement call.
292
-
292
+
293
293
  @param {SC.Record} record The record instance
294
294
  @param {String} key The key used to access this attribute on the record
295
295
  @param {Object} value The property value if called as a setter
@@ -297,13 +297,13 @@ SC.RecordAttribute = SC.Object.extend(
297
297
  */
298
298
  call: function(record, key, value) {
299
299
  var attrKey = this.get('key') || key, nvalue;
300
-
300
+
301
301
  if ((value !== undefined) && this.get('isEditable')) {
302
- // careful: don't overwrite value here. we want the return value to
302
+ // careful: don't overwrite value here. we want the return value to
303
303
  // cache.
304
304
  nvalue = this.fromType(record, key, value) ; // convert to attribute.
305
- record.writeAttribute(attrKey, nvalue);
306
- }
305
+ record.writeAttribute(attrKey, nvalue);
306
+ }
307
307
 
308
308
  nvalue = value = record.readAttribute(attrKey);
309
309
  if (SC.none(value) && (value = this.get('defaultValue'))) {
@@ -315,40 +315,40 @@ SC.RecordAttribute = SC.Object.extend(
315
315
  }
316
316
  }
317
317
  } else value = this.toType(record, key, value);
318
-
318
+
319
319
  return value ;
320
320
  },
321
321
 
322
322
  // ..........................................................
323
323
  // INTERNAL SUPPORT
324
- //
325
-
324
+ //
325
+
326
326
  /** @private - Make this look like a property so that `get()` will call it. */
327
327
  isProperty: YES,
328
-
328
+
329
329
  /** @private - Make this look cacheable */
330
330
  isCacheable: YES,
331
-
331
+
332
332
  /** @private - needed for KVO `property()` support */
333
333
  dependentKeys: [],
334
-
334
+
335
335
  /** @private */
336
336
  init: function() {
337
337
  sc_super();
338
338
  // setup some internal properties needed for KVO - faking 'cacheable'
339
- this.cacheKey = "__cache__" + SC.guidFor(this) ;
340
- this.lastSetValueKey = "__lastValue__" + SC.guidFor(this) ;
339
+ this.cacheKey = "__cache__recattr__" + SC.guidFor(this) ;
340
+ this.lastSetValueKey = "__lastValue__recattr__" + SC.guidFor(this) ;
341
341
  }
342
342
  }) ;
343
343
 
344
344
  // ..........................................................
345
345
  // CLASS METHODS
346
- //
346
+ //
347
347
 
348
348
  SC.RecordAttribute.mixin(
349
349
  /** @scope SC.RecordAttribute.prototype */{
350
350
  /**
351
- The default method used to create a record attribute instance. Unlike
351
+ The default method used to create a record attribute instance. Unlike
352
352
  `create()`, takes an `attributeType` as the first parameter which will be
353
353
  set on the attribute itself. You can pass a string naming a class or a
354
354
  class itself.
@@ -365,7 +365,7 @@ SC.RecordAttribute.mixin(
365
365
  },
366
366
 
367
367
  /** @private
368
- Hash of registered transforms by class guid.
368
+ Hash of registered transforms by class guid.
369
369
  */
370
370
  transforms: {},
371
371
 
@@ -373,13 +373,13 @@ SC.RecordAttribute.mixin(
373
373
  Call to register a transform handler for a specific type of object. The
374
374
  object you pass can be of any type as long as it responds to the following
375
375
  methods
376
-
376
+
377
377
  - `to(value, attr, klass, record, key)` converts the passed value
378
378
  (which will be of the class expected by the attribute) into the
379
379
  underlying attribute value
380
380
  - `from(value, attr, klass, record, key)` converts the underyling
381
381
  attribute value into a value of the class
382
-
382
+
383
383
  You can also provide an array of keys to observer on the return value.
384
384
  When any of these change, your from method will be called to write the
385
385
  changed object back to the record. For example:
@@ -409,7 +409,7 @@ SC.RecordAttribute.mixin(
409
409
 
410
410
  // ..........................................................
411
411
  // STANDARD ATTRIBUTE TRANSFORMS
412
- //
412
+ //
413
413
 
414
414
  // Object, String, Number just pass through.
415
415
 
@@ -431,8 +431,8 @@ SC.RecordAttribute.registerTransform(Number, {
431
431
 
432
432
  /** @private - generic converter for Strings */
433
433
  SC.RecordAttribute.registerTransform(String, {
434
- /** @private -
435
- convert an arbitrary object value to a String
434
+ /** @private -
435
+ convert an arbitrary object value to a String
436
436
  allow null through as that will be checked separately
437
437
  */
438
438
  to: function(obj) {
@@ -453,7 +453,7 @@ SC.RecordAttribute.registerTransform(Array, {
453
453
  }
454
454
  return obj;
455
455
  },
456
-
456
+
457
457
  observesChildren: ['[]']
458
458
  });
459
459
 
@@ -477,7 +477,7 @@ SC.RecordAttribute.registerTransform(SC.Record, {
477
477
  if (SC.none(id) || (id==="")) return null;
478
478
  else return store.find(recordType, id);
479
479
  },
480
-
480
+
481
481
  /** @private - convert a record instance to a record id */
482
482
  from: function(record) { return record ? record.get('id') : null; }
483
483
  });
@@ -491,7 +491,7 @@ SC.RecordAttribute.registerTransform(SC.T_FUNCTION, {
491
491
  var store = parentRecord.get('store');
492
492
  return store.find(recordType, id);
493
493
  },
494
-
494
+
495
495
  /** @private - convert a record instance to a record id */
496
496
  from: function(record) { return record.get('id'); }
497
497
  });
@@ -508,7 +508,7 @@ SC.RecordAttribute.registerTransform(Date, {
508
508
 
509
509
  var ret ;
510
510
  str = str.toString() || '';
511
-
511
+
512
512
  if (attr.get('useIsoDate')) {
513
513
  var regexp = "([0-9]{4})(-([0-9]{2})(-([0-9]{2})" +
514
514
  "(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\\.([0-9]+))?)?" +
@@ -531,34 +531,34 @@ SC.RecordAttribute.registerTransform(Date, {
531
531
 
532
532
  offset -= date.getTimezoneOffset();
533
533
  time = (Number(date) + (offset * 60 * 1000));
534
-
534
+
535
535
  ret = new Date();
536
536
  ret.setTime(Number(time));
537
537
  } else ret = new Date(Date.parse(str));
538
538
  return ret ;
539
539
  },
540
-
540
+
541
541
  _dates: {},
542
-
542
+
543
543
  /** @private - pad with leading zeroes */
544
- _zeropad: function(num) {
545
- return ((num<0) ? '-' : '') + ((num<10) ? '0' : '') + Math.abs(num);
544
+ _zeropad: function(num) {
545
+ return ((num<0) ? '-' : '') + ((num<10) ? '0' : '') + Math.abs(num);
546
546
  },
547
-
547
+
548
548
  /** @private - convert a date to a string */
549
- from: function(date) {
549
+ from: function(date) {
550
550
 
551
551
  if (SC.none(date)) { return null; }
552
552
 
553
553
  var ret = this._dates[date.getTime()];
554
- if (ret) return ret ;
555
-
554
+ if (ret) return ret ;
555
+
556
556
  // figure timezone
557
557
  var zp = this._zeropad,
558
558
  tz = 0-date.getTimezoneOffset()/60;
559
-
559
+
560
560
  tz = (tz === 0) ? 'Z' : '%@:00'.fmt(zp(tz));
561
-
561
+
562
562
  this._dates[date.getTime()] = ret = "%@-%@-%@T%@:%@:%@%@".fmt(
563
563
  zp(date.getFullYear()),
564
564
  zp(date.getMonth()+1),
@@ -567,7 +567,7 @@ SC.RecordAttribute.registerTransform(Date, {
567
567
  zp(date.getMinutes()),
568
568
  zp(date.getSeconds()),
569
569
  tz) ;
570
-
570
+
571
571
  return ret ;
572
572
  }
573
573
  });
@@ -576,18 +576,18 @@ if (SC.DateTime && !SC.RecordAttribute.transforms[SC.guidFor(SC.DateTime)]) {
576
576
  /**
577
577
  Registers a transform to allow `SC.DateTime` to be used as a record
578
578
  attribute, ie `SC.Record.attr(SC.DateTime);`
579
-
579
+
580
580
  Because `SC.RecordAttribute` is in the datastore framework and
581
581
  `SC.DateTime` in the foundation framework, and we don't know which
582
582
  framework is being loaded first, this chunck of code is duplicated in
583
583
  both frameworks.
584
-
584
+
585
585
  IF YOU EDIT THIS CODE MAKE SURE YOU COPY YOUR CHANGES to
586
586
  `record_attribute.js.`
587
587
  */
588
588
 
589
589
  SC.RecordAttribute.registerTransform(SC.DateTime, {
590
-
590
+
591
591
  /** @private
592
592
  Convert a String to a DateTime
593
593
  */
@@ -597,7 +597,7 @@ if (SC.DateTime && !SC.RecordAttribute.transforms[SC.guidFor(SC.DateTime)]) {
597
597
  var format = attr.get('format');
598
598
  return SC.DateTime.parse(str, format ? format : SC.DateTime.recordFormat);
599
599
  },
600
-
600
+
601
601
  /** @private
602
602
  Convert a DateTime to a String
603
603
  */
@@ -607,7 +607,7 @@ if (SC.DateTime && !SC.RecordAttribute.transforms[SC.guidFor(SC.DateTime)]) {
607
607
  return dt.toFormattedString(format ? format : SC.DateTime.recordFormat);
608
608
  }
609
609
  });
610
-
610
+
611
611
  }
612
612
 
613
613
  /**
@@ -617,10 +617,10 @@ SC.RecordAttribute.registerTransform(SC.Set, {
617
617
  to: function(value, attr, type, record, key) {
618
618
  return SC.Set.create(value);
619
619
  },
620
-
620
+
621
621
  from: function(value, attr, type, record, key) {
622
622
  return value.toArray();
623
623
  },
624
-
624
+
625
625
  observesChildren: ['[]']
626
626
  });
@@ -1429,7 +1429,7 @@ SC.Query.mixin( /** @scope SC.Query */ {
1429
1429
 
1430
1430
  // pass one or more recordTypes.
1431
1431
  if (recordType && recordType.isEnumerable) {
1432
- opts.recordsTypes = recordType;
1432
+ opts.recordTypes = recordType;
1433
1433
  } else opts.recordType = recordType;
1434
1434
 
1435
1435
  // set conditions and params if needed
@@ -551,9 +551,7 @@ SC.RecordArray = SC.Object.extend(SC.Enumerable, SC.Array,
551
551
  // otherwise, lookup all storeKeys for the named recordType...
552
552
  } else if (recordType = query.get('expandedRecordTypes')) {
553
553
  sourceKeys = SC.IndexSet.create();
554
- recordType.forEach(function(cur) {
555
- sourceKeys.addEach(store.storeKeysFor(recordType));
556
- });
554
+ sourceKeys.addEach(store.storeKeysFor(recordType));
557
555
  }
558
556
 
559
557
  // loop through storeKeys to determine if it belongs in this query or
@@ -635,7 +633,7 @@ SC.RecordArray = SC.Object.extend(SC.Enumerable, SC.Array,
635
633
  @type Boolean
636
634
  */
637
635
  isError: function() {
638
- return this.get('status') & SC.Record.ERROR;
636
+ return !!(this.get('status') & SC.Record.ERROR);
639
637
  }.property('status').cacheable(),
640
638
 
641
639
  /**
@@ -45,8 +45,8 @@ test("Verify error methods behave correctly", function() {
45
45
  store.dataSourceDidError(storeKey, SC.Record.GENERIC_ERROR);
46
46
  SC.RunLoop.end();
47
47
 
48
- ok(thing1.get('isError'), "isError on thing1 should be YES");
49
- ok(!thing2.get('isError'), "isError on thing2 should be NO");
48
+ ok((thing1.get('isError') === YES), "isError on thing1 should be YES");
49
+ ok((thing2.get('isError') === NO), "isError on thing2 should be NO");
50
50
 
51
51
  equals(thing1.get('errorObject'), SC.Record.GENERIC_ERROR,
52
52
  "get('errorObject') on thing1 should return the correct error object");
@@ -282,3 +282,29 @@ test("isEditable NO should not fire property change observer", function() {
282
282
  rec5.removeObserver('readOnlyRelatedTo', modifierListener);
283
283
  });
284
284
 
285
+ test("adding toOne pointing to non existing class should throw error", function() {
286
+ var message;
287
+ try {
288
+ MyApp.InvalidModel = SC.Record.extend({
289
+ foo: SC.Record.toOne(MyApp.DoesNotExist)
290
+ });
291
+ } catch (x) {
292
+ message = x;
293
+ }
294
+
295
+ same(message, 'Attempted to create toOne attribute with undefined recordType. Did you forget to sc_require a dependency?');
296
+ });
297
+
298
+ test("adding toMany pointing to non existing class should throw error", function() {
299
+ var message;
300
+ try {
301
+ MyApp.InvalidModel = SC.Record.extend({
302
+ foo: SC.Record.toMany(MyApp.DoesNotExist)
303
+ });
304
+ } catch (x) {
305
+ message = x;
306
+ }
307
+
308
+ same(message, 'Attempted to create toMany attribute with undefined recordType. Did you forget to sc_require a dependency?');
309
+ });
310
+
@@ -144,6 +144,13 @@ function performBasicTests(methodName, loc) {
144
144
  equals(q5, q4, 'second call for different conditions should return cache');
145
145
  });
146
146
 
147
+ test("query with record types and conditions hash", function() {
148
+
149
+ var q = invokeWith([TestRecord, TestRecord2], {});
150
+ queryEquals(q, loc, [TestRecord, TestRecord2], null, 'first query');
151
+
152
+ });
153
+
147
154
  test("query with no record type and with conditions", function() {
148
155
  var q1, q2;
149
156
 
@@ -43,7 +43,7 @@ test("Verify error methods behave correctly", function() {
43
43
  store.dataSourceDidErrorQuery(q, SC.Record.GENERIC_ERROR);
44
44
  SC.RunLoop.end();
45
45
 
46
- ok(things.get('isError'), "isError on things array should be YES");
46
+ ok((things.get('isError') === YES), "isError on things array should be YES");
47
47
 
48
48
  equals(things.get('errorObject'), SC.Record.GENERIC_ERROR,
49
49
  "get('errorObject') on things array should return the correct error object");
@@ -975,7 +975,10 @@ SC.DateTime.mixin(SC.Comparable,
975
975
  }
976
976
 
977
977
  if (!SC.none(opts.meridian) && !SC.none(opts.hour)) {
978
- if (opts.meridian === 1) opts.hour = (opts.hour + 12) % 24;
978
+ if ((opts.meridian === 1 && opts.hour !== 12)
979
+ || (opts.meridian === 0 && opts.hour === 12)) {
980
+ opts.hour = (opts.hour + 12) % 24;
981
+ }
979
982
  delete opts.meridian;
980
983
  }
981
984
 
@@ -306,6 +306,12 @@ test('parse', function() {
306
306
  timeShouldBeEqualToHash(
307
307
  SC.DateTime.parse('71-01-01 00:00:00', '%y-%m-%d %H:%M:%S'),
308
308
  { year: 1971, month: 1, day: 1, hour: 0, minute: 0, second: 0, millisecond: 0 });
309
+ timeShouldBeEqualToHash(
310
+ SC.DateTime.parse('71-01-01 12:00 AM', '%y-%m-%d %i:%M %p'),
311
+ { year: 1971, month: 1, day: 1, hour: 0, minute: 0, second: 0, millisecond: 0 });
312
+ timeShouldBeEqualToHash(
313
+ SC.DateTime.parse('71-01-01 12:00 PM', '%y-%m-%d %i:%M %p'),
314
+ { year: 1971, month: 1, day: 1, hour: 12, minute: 0, second: 0, millisecond: 0 });
309
315
  });
310
316
 
311
317
  test('parse with time zones',function() {