sproutcore 1.6.0.rc.1-x86-mingw32 → 1.6.0.rc.2-x86-mingw32

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 (217) hide show
  1. data/CHANGELOG +31 -6
  2. data/{History.txt → History.rdoc} +0 -0
  3. data/{README.txt → README.rdoc} +3 -2
  4. data/Rakefile +15 -15
  5. data/{Todo.txt → Todo.rdoc} +0 -0
  6. data/VERSION.yml +1 -1
  7. data/lib/buildtasks/manifest.rake +11 -4
  8. data/lib/buildtasks/target.rake +20 -23
  9. data/lib/frameworks/sproutcore/CHANGELOG.md +36 -0
  10. data/lib/frameworks/sproutcore/frameworks/core_foundation/core.js +2 -42
  11. data/lib/frameworks/sproutcore/frameworks/core_foundation/ext/handlebars/bind.js +2 -1
  12. data/lib/frameworks/sproutcore/frameworks/core_foundation/ext/handlebars/collection.js +3 -1
  13. data/lib/frameworks/sproutcore/frameworks/core_foundation/mixins/template_helpers/checkbox_support.js +5 -5
  14. data/lib/frameworks/sproutcore/frameworks/core_foundation/mixins/template_helpers/text_field_support.js +29 -12
  15. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/event.js +4 -4
  16. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/mixins/template_helpers/text_field_support.js +9 -0
  17. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/template/collection.js +110 -0
  18. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/template_collection.js +63 -26
  19. data/lib/frameworks/sproutcore/frameworks/datastore/system/child_array.js +25 -5
  20. data/lib/frameworks/sproutcore/frameworks/datastore/system/record_array.js +3 -3
  21. data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/nested_records/nested_record_array.js +26 -3
  22. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/record_array/core_methods.js +74 -53
  23. data/lib/frameworks/sproutcore/frameworks/desktop/panes/alert.js +6 -7
  24. data/lib/frameworks/sproutcore/frameworks/desktop/panes/picker.js +6 -3
  25. data/lib/frameworks/sproutcore/frameworks/desktop/tests/panes/alert/ui.js +25 -1
  26. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/tab/methods.js +1 -3
  27. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/tab/ui.js +20 -1
  28. data/lib/frameworks/sproutcore/frameworks/desktop/views/select_field.js +1 -1
  29. data/lib/frameworks/sproutcore/frameworks/desktop/views/tab.js +46 -49
  30. data/lib/frameworks/sproutcore/frameworks/foundation/tests/views/container/ui.js +23 -0
  31. data/lib/frameworks/sproutcore/frameworks/foundation/views/container.js +14 -2
  32. data/lib/frameworks/sproutcore/frameworks/jquery/jquery-buffered.js +2 -76
  33. data/lib/frameworks/sproutcore/frameworks/jquery/jquery.js +3348 -1591
  34. data/lib/frameworks/sproutcore/frameworks/runtime/core.js +25 -5
  35. data/lib/frameworks/sproutcore/frameworks/runtime/system/index_set.js +0 -3
  36. data/lib/frameworks/sproutcore/frameworks/runtime/tests/core/objectForPropertyPath.js +10 -5
  37. data/lib/frameworks/sproutcore/frameworks/runtime/tests/core/requiredObjectForPropertyPath.js +29 -0
  38. data/lib/frameworks/sproutcore/frameworks/runtime/tests/private/observer_queue.js +98 -0
  39. data/lib/frameworks/sproutcore/themes/ace/resources/collection/normal/list_item.css +2 -2
  40. data/lib/frameworks/sproutcore/themes/ace/resources/split/split.css +1 -1
  41. data/lib/gen/language/Buildfile +1 -1
  42. data/lib/sproutcore.rb +1 -14
  43. data/lib/sproutcore/buildfile/string_ext.rb +0 -4
  44. data/lib/sproutcore/helpers/cssmin.rb +44 -59
  45. data/lib/sproutcore/helpers/text_helper.rb +11 -13
  46. data/lib/sproutcore/models/manifest.rb +4 -4
  47. data/lib/sproutcore/models/target.rb +11 -110
  48. data/lib/sproutcore/rack.rb +0 -1
  49. data/lib/sproutcore/rack/dev.rb +0 -1
  50. data/lib/sproutcore/rack/proxy.rb +9 -8
  51. data/lib/sproutcore/rack/service.rb +1 -1
  52. data/lib/sproutcore/render_engines/haml.rb +2 -5
  53. data/lib/sproutcore/tools/build.rb +2 -0
  54. data/lib/sproutcore/tools/docs.rb +7 -36
  55. data/lib/sproutcore/tools/manifest.rb +1 -1
  56. data/spec/buildtasks/target_spec.rb +9 -0
  57. data/spec/fixtures/real_world/frameworks/sproutcore/Buildfile +1 -1
  58. data/sproutcore.gemspec +3 -4
  59. data/vendor/chance/lib/chance/instance.rb +5 -8
  60. metadata +41 -207
  61. data/lib/doc_templates/jsdoc/allclasses.tmpl +0 -17
  62. data/lib/doc_templates/jsdoc/allfiles.tmpl +0 -56
  63. data/lib/doc_templates/jsdoc/class.tmpl +0 -487
  64. data/lib/doc_templates/jsdoc/index.tmpl +0 -38
  65. data/lib/doc_templates/jsdoc/publish.js +0 -170
  66. data/lib/doc_templates/jsdoc/static/default.css +0 -162
  67. data/lib/doc_templates/jsdoc/static/header.html +0 -2
  68. data/lib/doc_templates/jsdoc/static/index.html +0 -19
  69. data/lib/doc_templates/jsdoc/symbol.tmpl +0 -35
  70. data/lib/doc_templates/sproutcore/allclasses.tmpl +0 -0
  71. data/lib/doc_templates/sproutcore/allfiles.tmpl +0 -56
  72. data/lib/doc_templates/sproutcore/class.tmpl +0 -674
  73. data/lib/doc_templates/sproutcore/classes-json.tmpl +0 -55
  74. data/lib/doc_templates/sproutcore/index.tmpl +0 -62
  75. data/lib/doc_templates/sproutcore/publish.js +0 -346
  76. data/lib/doc_templates/sproutcore/static/default.css +0 -258
  77. data/lib/doc_templates/sproutcore/static/header.html +0 -2
  78. data/lib/doc_templates/sproutcore/static/index.html +0 -19
  79. data/lib/doc_templates/sproutcore/symbol.tmpl +0 -35
  80. data/lib/frameworks/sproutcore/frameworks/runtime/tests/private/observer_queue/isObservingSuspended.js +0 -55
  81. data/lib/sproutcore/rack/docs.rb +0 -24
  82. data/spec/fixtures/real_world/frameworks/sproutcore/apps/docs/PLACEHOLDER +0 -0
  83. data/vendor/jsdoc/README.txt +0 -151
  84. data/vendor/jsdoc/app/frame.js +0 -33
  85. data/vendor/jsdoc/app/frame/Chain.js +0 -102
  86. data/vendor/jsdoc/app/frame/Dumper.js +0 -144
  87. data/vendor/jsdoc/app/frame/Hash.js +0 -47
  88. data/vendor/jsdoc/app/frame/Link.js +0 -142
  89. data/vendor/jsdoc/app/frame/Namespace.js +0 -10
  90. data/vendor/jsdoc/app/frame/Opt.js +0 -134
  91. data/vendor/jsdoc/app/frame/Reflection.js +0 -26
  92. data/vendor/jsdoc/app/frame/String.js +0 -93
  93. data/vendor/jsdoc/app/frame/Testrun.js +0 -129
  94. data/vendor/jsdoc/app/handlers/FOODOC.js +0 -26
  95. data/vendor/jsdoc/app/handlers/XMLDOC.js +0 -26
  96. data/vendor/jsdoc/app/handlers/XMLDOC/DomReader.js +0 -159
  97. data/vendor/jsdoc/app/handlers/XMLDOC/XMLDoc.js +0 -16
  98. data/vendor/jsdoc/app/handlers/XMLDOC/XMLParse.js +0 -292
  99. data/vendor/jsdoc/app/lib/JSDOC.js +0 -98
  100. data/vendor/jsdoc/app/lib/JSDOC/DocComment.js +0 -200
  101. data/vendor/jsdoc/app/lib/JSDOC/DocTag.js +0 -294
  102. data/vendor/jsdoc/app/lib/JSDOC/JsDoc.js +0 -162
  103. data/vendor/jsdoc/app/lib/JSDOC/JsPlate.js +0 -100
  104. data/vendor/jsdoc/app/lib/JSDOC/Lang.js +0 -144
  105. data/vendor/jsdoc/app/lib/JSDOC/Parser.js +0 -109
  106. data/vendor/jsdoc/app/lib/JSDOC/PluginManager.js +0 -33
  107. data/vendor/jsdoc/app/lib/JSDOC/Symbol.js +0 -681
  108. data/vendor/jsdoc/app/lib/JSDOC/SymbolSet.js +0 -226
  109. data/vendor/jsdoc/app/lib/JSDOC/TextStream.js +0 -41
  110. data/vendor/jsdoc/app/lib/JSDOC/Token.js +0 -18
  111. data/vendor/jsdoc/app/lib/JSDOC/TokenReader.js +0 -332
  112. data/vendor/jsdoc/app/lib/JSDOC/TokenStream.js +0 -133
  113. data/vendor/jsdoc/app/lib/JSDOC/Util.js +0 -32
  114. data/vendor/jsdoc/app/lib/JSDOC/Walker.js +0 -453
  115. data/vendor/jsdoc/app/main.js +0 -74
  116. data/vendor/jsdoc/app/plugins/commentSrcJson.js +0 -19
  117. data/vendor/jsdoc/app/plugins/frameworkPrototype.js +0 -16
  118. data/vendor/jsdoc/app/plugins/functionCall.js +0 -10
  119. data/vendor/jsdoc/app/plugins/publishSrcHilite.js +0 -62
  120. data/vendor/jsdoc/app/plugins/sproutcoreTags.js +0 -26
  121. data/vendor/jsdoc/app/plugins/symbolLink.js +0 -9
  122. data/vendor/jsdoc/app/plugins/tagParamConfig.js +0 -31
  123. data/vendor/jsdoc/app/plugins/tagSynonyms.js +0 -43
  124. data/vendor/jsdoc/app/run.js +0 -346
  125. data/vendor/jsdoc/app/t/TestDoc.js +0 -144
  126. data/vendor/jsdoc/app/t/runner.js +0 -13
  127. data/vendor/jsdoc/app/test.js +0 -304
  128. data/vendor/jsdoc/app/test/addon.js +0 -24
  129. data/vendor/jsdoc/app/test/anon_inner.js +0 -14
  130. data/vendor/jsdoc/app/test/augments.js +0 -31
  131. data/vendor/jsdoc/app/test/augments2.js +0 -26
  132. data/vendor/jsdoc/app/test/borrows.js +0 -41
  133. data/vendor/jsdoc/app/test/borrows2.js +0 -23
  134. data/vendor/jsdoc/app/test/config.js +0 -22
  135. data/vendor/jsdoc/app/test/constructs.js +0 -18
  136. data/vendor/jsdoc/app/test/encoding.js +0 -10
  137. data/vendor/jsdoc/app/test/encoding_other.js +0 -12
  138. data/vendor/jsdoc/app/test/functions_anon.js +0 -39
  139. data/vendor/jsdoc/app/test/functions_nested.js +0 -33
  140. data/vendor/jsdoc/app/test/global.js +0 -13
  141. data/vendor/jsdoc/app/test/globals.js +0 -25
  142. data/vendor/jsdoc/app/test/ignore.js +0 -10
  143. data/vendor/jsdoc/app/test/inner.js +0 -16
  144. data/vendor/jsdoc/app/test/jsdoc_test.js +0 -477
  145. data/vendor/jsdoc/app/test/lend.js +0 -33
  146. data/vendor/jsdoc/app/test/memberof.js +0 -20
  147. data/vendor/jsdoc/app/test/memberof_constructor.js +0 -15
  148. data/vendor/jsdoc/app/test/name.js +0 -19
  149. data/vendor/jsdoc/app/test/namespace_nested.js +0 -23
  150. data/vendor/jsdoc/app/test/nocode.js +0 -13
  151. data/vendor/jsdoc/app/test/oblit_anon.js +0 -20
  152. data/vendor/jsdoc/app/test/overview.js +0 -20
  153. data/vendor/jsdoc/app/test/param_inline.js +0 -37
  154. data/vendor/jsdoc/app/test/params_optional.js +0 -8
  155. data/vendor/jsdoc/app/test/prototype.js +0 -17
  156. data/vendor/jsdoc/app/test/prototype_nested.js +0 -9
  157. data/vendor/jsdoc/app/test/prototype_oblit.js +0 -13
  158. data/vendor/jsdoc/app/test/prototype_oblit_constructor.js +0 -24
  159. data/vendor/jsdoc/app/test/public.js +0 -10
  160. data/vendor/jsdoc/app/test/shared.js +0 -42
  161. data/vendor/jsdoc/app/test/shared2.js +0 -2
  162. data/vendor/jsdoc/app/test/shortcuts.js +0 -22
  163. data/vendor/jsdoc/app/test/static_this.js +0 -13
  164. data/vendor/jsdoc/app/test/synonyms.js +0 -23
  165. data/vendor/jsdoc/app/test/tosource.js +0 -23
  166. data/vendor/jsdoc/app/test/variable_redefine.js +0 -14
  167. data/vendor/jsdoc/changes.txt +0 -47
  168. data/vendor/jsdoc/conf/sample.conf +0 -31
  169. data/vendor/jsdoc/java/build.xml +0 -36
  170. data/vendor/jsdoc/java/build_1.4.xml +0 -36
  171. data/vendor/jsdoc/java/classes/js.jar +0 -0
  172. data/vendor/jsdoc/java/src/JsDebugRun.java +0 -21
  173. data/vendor/jsdoc/java/src/JsRun.java +0 -21
  174. data/vendor/jsdoc/jsdebug.jar +0 -0
  175. data/vendor/jsdoc/jsrun.jar +0 -0
  176. data/vendor/jsdoc/t/TestDoc.js +0 -144
  177. data/vendor/jsdoc/t/runner.js +0 -13
  178. data/vendor/jsdoc/test.js +0 -304
  179. data/vendor/jsdoc/test/addon.js +0 -24
  180. data/vendor/jsdoc/test/anon_inner.js +0 -14
  181. data/vendor/jsdoc/test/augments.js +0 -31
  182. data/vendor/jsdoc/test/augments2.js +0 -26
  183. data/vendor/jsdoc/test/borrows.js +0 -41
  184. data/vendor/jsdoc/test/borrows2.js +0 -23
  185. data/vendor/jsdoc/test/config.js +0 -22
  186. data/vendor/jsdoc/test/constructs.js +0 -18
  187. data/vendor/jsdoc/test/encoding.js +0 -10
  188. data/vendor/jsdoc/test/encoding_other.js +0 -12
  189. data/vendor/jsdoc/test/functions_anon.js +0 -39
  190. data/vendor/jsdoc/test/functions_nested.js +0 -33
  191. data/vendor/jsdoc/test/global.js +0 -13
  192. data/vendor/jsdoc/test/globals.js +0 -25
  193. data/vendor/jsdoc/test/ignore.js +0 -10
  194. data/vendor/jsdoc/test/inner.js +0 -16
  195. data/vendor/jsdoc/test/jsdoc_test.js +0 -477
  196. data/vendor/jsdoc/test/lend.js +0 -33
  197. data/vendor/jsdoc/test/memberof.js +0 -20
  198. data/vendor/jsdoc/test/memberof_constructor.js +0 -15
  199. data/vendor/jsdoc/test/name.js +0 -19
  200. data/vendor/jsdoc/test/namespace_nested.js +0 -23
  201. data/vendor/jsdoc/test/nocode.js +0 -13
  202. data/vendor/jsdoc/test/oblit_anon.js +0 -20
  203. data/vendor/jsdoc/test/overview.js +0 -20
  204. data/vendor/jsdoc/test/param_inline.js +0 -37
  205. data/vendor/jsdoc/test/params_optional.js +0 -8
  206. data/vendor/jsdoc/test/prototype.js +0 -17
  207. data/vendor/jsdoc/test/prototype_nested.js +0 -9
  208. data/vendor/jsdoc/test/prototype_oblit.js +0 -13
  209. data/vendor/jsdoc/test/prototype_oblit_constructor.js +0 -24
  210. data/vendor/jsdoc/test/public.js +0 -10
  211. data/vendor/jsdoc/test/shared.js +0 -42
  212. data/vendor/jsdoc/test/shared2.js +0 -2
  213. data/vendor/jsdoc/test/shortcuts.js +0 -22
  214. data/vendor/jsdoc/test/static_this.js +0 -13
  215. data/vendor/jsdoc/test/synonyms.js +0 -23
  216. data/vendor/jsdoc/test/tosource.js +0 -23
  217. data/vendor/jsdoc/test/variable_redefine.js +0 -14
@@ -287,7 +287,7 @@ SC.mixin(SC.Event, /** @scope SC.Event */ {
287
287
  // Get the handlers queue for this element/eventType. If the queue does
288
288
  // not exist yet, create it and also setup the shared listener for this
289
289
  // eventType.
290
- var events = SC.data(elem, "events") || SC.data(elem, "events", {}) ,
290
+ var events = SC.data(elem, "sc_events") || SC.data(elem, "sc_events", {}) ,
291
291
  handlers = events[eventType];
292
292
  if (!handlers) {
293
293
  handlers = events[eventType] = {} ;
@@ -351,7 +351,7 @@ SC.mixin(SC.Event, /** @scope SC.Event */ {
351
351
  // around, causing it to be cloned in the process
352
352
  if (SC.browser.msie && elem.setInterval) elem = window;
353
353
 
354
- var handlers, key, events = SC.data(elem, "events") ;
354
+ var handlers, key, events = SC.data(elem, "sc_events") ;
355
355
  if (!events) return this ; // nothing to do if no events are registered
356
356
 
357
357
  // if no type is provided, remove all types for this element.
@@ -396,7 +396,7 @@ SC.mixin(SC.Event, /** @scope SC.Event */ {
396
396
  key = null ;
397
397
  for(key in events) break;
398
398
  if(!key) {
399
- SC.removeData(elem, "events") ;
399
+ SC.removeData(elem, "sc_events") ;
400
400
  delete this._elements[SC.guidFor(elem)]; // important to avoid leaks
401
401
  }
402
402
 
@@ -546,7 +546,7 @@ SC.mixin(SC.Event, /** @scope SC.Event */ {
546
546
  args[0] = event = SC.Event.normalizeEvent(event || window.event);
547
547
 
548
548
  // get the handlers for this event type
549
- handlers = (SC.data(this, "events") || {})[event.type];
549
+ handlers = (SC.data(this, "sc_events") || {})[event.type];
550
550
  if (!handlers) return NO ; // nothing to do
551
551
 
552
552
  // invoke all handlers
@@ -190,4 +190,13 @@
190
190
  SC.RootResponder.responder.keyup(new SC.Event({ type: 'keyup', keyCode: 27 }));
191
191
  equals(cancelCalled, 1, "calls cancel after pressing escape key");
192
192
  });
193
+
194
+ test("creates textarea tag if isMultiline", function() {
195
+ var view = SC.TextField.create({
196
+ isMultiline: YES
197
+ });
198
+ SC.run(function() { pane.appendChild(view); });
199
+ equals(view.$('textarea').length, 1, "view creates textarea tag instead of input");
200
+ });
201
+
193
202
  })();
@@ -272,3 +272,113 @@ test("should allow changing content property to be null", function() {
272
272
  view.set('content', null);
273
273
  equals(view.$('li').length, 0, "should not create any li elements");
274
274
  });
275
+
276
+ test("collection view within a collection view with default content should render content once", function() {
277
+ TemplateTests.InnerCollectionView = SC.TemplateCollectionView.extend();
278
+
279
+ TemplateTests.OuterItemView = SC.TemplateView.extend({
280
+ template: SC.Handlebars.compile('{{#collection "TemplateTests.InnerCollectionView" content=content.things}} {{content}} {{/collection}}')
281
+ });
282
+
283
+ TemplateTests.OuterCollectionView = SC.TemplateCollectionView.extend({
284
+ content: [
285
+ SC.Object.create({things: ['1', '2', '3']}),
286
+ SC.Object.create({things: ['4', '5']}),
287
+ SC.Object.create({things: ['6']})
288
+ ],
289
+ itemView: TemplateTests.OuterItemView
290
+ });
291
+
292
+ var view = SC.TemplateView.create({
293
+ template: SC.Handlebars.compile('{{collection "TemplateTests.OuterCollectionView"}}')
294
+ });
295
+
296
+ view.createLayer();
297
+
298
+ equals(view.$('ul ul:eq(0) li').length, 3, 'first nested collection view should have 3 list items');
299
+ equals(view.$('ul ul:eq(1) li').length, 2, 'second nested collection view should have 2 list items');
300
+ equals(view.$('ul ul:eq(2) li').length, 1, 'third nested collection view should have 1 list items');
301
+ });
302
+
303
+ test("collection view within a collection view should have the right childViews", function() {
304
+ TemplateTests.InnerCollectionView = SC.TemplateCollectionView.extend();
305
+
306
+ TemplateTests.OuterItemView = SC.TemplateView.extend({
307
+ template: SC.Handlebars.compile('{{#collection "TemplateTests.InnerCollectionView" content=content.things}} {{content}} {{/collection}}')
308
+ });
309
+
310
+ TemplateTests.OuterCollectionView = SC.TemplateCollectionView.extend({
311
+ content: [
312
+ SC.Object.create({things: ['1', '2', '3']}),
313
+ SC.Object.create({things: ['4', '5']}),
314
+ SC.Object.create({things: ['6']})
315
+ ],
316
+ itemView: TemplateTests.OuterItemView
317
+ });
318
+
319
+ var view = SC.TemplateView.create({
320
+ template: SC.Handlebars.compile('{{collection "TemplateTests.OuterCollectionView"}}')
321
+ });
322
+
323
+ view.createLayer();
324
+
325
+ var outer = view.childViews[0];
326
+ var firstInner = outer.childViews[0].childViews[0];
327
+ var secondInner = outer.childViews[1].childViews[0];
328
+ var thirdInner = outer.childViews[2].childViews[0];
329
+
330
+ ok(outer.kindOf(TemplateTests.OuterCollectionView), 'first child view should be instance of outer collection view');
331
+ ok(firstInner.kindOf(TemplateTests.InnerCollectionView), 'first child view of outer should be instance of inner');
332
+ ok(secondInner.kindOf(TemplateTests.InnerCollectionView), 'second child view of outer should be instance of inner');
333
+ ok(thirdInner.kindOf(TemplateTests.InnerCollectionView), 'third child view of outer should be instance of inner');
334
+ });
335
+
336
+ test("should render inverse template when its present and there is no content", function() {
337
+ TemplateTests.CollectionTestView = SC.TemplateCollectionView.create({
338
+ content: [],
339
+ inverseTemplate: SC.Handlebars.compile('<h1>inverse<h1>')
340
+ });
341
+
342
+ var view = SC.TemplateView.create({
343
+ template: SC.Handlebars.compile('{{collection "TemplateTests.CollectionTestView"}}')
344
+ });
345
+
346
+ view.createLayer();
347
+
348
+ equals(view.$('h1').text(), 'inverse', 'collection view with no content and inverse template should render inverse template')
349
+ });
350
+
351
+ test("should render inverse template name when its present and there is no content", function() {
352
+ TemplateTests.CollectionTestView = SC.TemplateCollectionView.create({
353
+ content: [],
354
+ inverseTemplateName: 'inverse_template',
355
+
356
+ templates: SC.Object.create({
357
+ inverse_template: function(dataSource) {
358
+ return "<h1>inverse template from file</h1>";
359
+ }
360
+ })
361
+ });
362
+
363
+ var view = SC.TemplateView.create({
364
+ template: SC.Handlebars.compile('{{collection "TemplateTests.CollectionTestView"}}')
365
+ });
366
+
367
+ view.createLayer();
368
+
369
+ equals(view.$('h1').text(), 'inverse template from file', 'collection view with no content and inverse template name should render template')
370
+ });
371
+
372
+ test("#collection helper should allow relative paths for the collection view class", function() {
373
+ var view = SC.TemplateView.create({
374
+ template: SC.Handlebars.compile('{{#collection "myCollectionView"}}{{content}}{{/collection}}'),
375
+ myCollectionView: SC.TemplateCollectionView.create({
376
+ content: ['foo', 'bar', 'baz']
377
+ })
378
+ });
379
+
380
+ SC.run(function() { view.createLayer(); });
381
+
382
+ equals(view.$('li').length, 3, '#collection should find relative collection view path');
383
+ });
384
+
@@ -30,6 +30,12 @@ SC.TemplateCollectionView = SC.TemplateView.extend(
30
30
  // In case a default content was set, trigger the child view creation
31
31
  // as soon as the empty layer was created
32
32
  didCreateLayer: function() {
33
+ // FIXME: didCreateLayer gets called multiple times when template collection
34
+ // views are nested - this is a hack to avoid rendering the content more
35
+ // than once.
36
+ if (this._sctcv_layerCreated) { return; }
37
+ this._sctcv_layerCreated = true;
38
+
33
39
  var content = this.get('content');
34
40
  if(content) {
35
41
  this.arrayContentDidChange(0, 0, content.get('length'));
@@ -64,6 +70,37 @@ SC.TemplateCollectionView = SC.TemplateView.extend(
64
70
  */
65
71
  itemViewTemplateName: null,
66
72
 
73
+ /**
74
+ A template to render when there is no content or the content length is 0.
75
+ */
76
+ inverseTemplate: function(key, value) {
77
+ if (value !== undefined) {
78
+ return value;
79
+ }
80
+
81
+ var templateName = this.get('inverseTemplateName'),
82
+ template = this.get('templates').get(templateName);
83
+
84
+ if (!template) {
85
+ //@if(debug)
86
+ if (templateName) {
87
+ SC.Logger.warn('%@ - Unable to find template "%@".'.fmt(this, templateName));
88
+ }
89
+ //@endif
90
+
91
+ return function() { return ''; };
92
+ }
93
+
94
+ return template;
95
+ }.property('inverseTemplateName').cacheable(),
96
+
97
+ /**
98
+ The name of a template to lookup if no inverse template is provided.
99
+
100
+ @property {String}
101
+ */
102
+ inverseTemplateName: null,
103
+
67
104
  itemContext: null,
68
105
 
69
106
  itemViewClass: function() {
@@ -207,42 +244,42 @@ SC.TemplateCollectionView = SC.TemplateView.extend(
207
244
  delete itemOptions['class'];
208
245
  delete itemOptions.classBinding;
209
246
 
210
- for (idx = 0; idx < len; idx++) {
211
- item = addedObjects.objectAt(idx);
212
- view = this.createChildView(itemViewClass.extend(itemOptions, {
213
- content: item,
214
- render: renderFunc,
215
- tagName: itemViewClass.prototype.tagName || this.get('itemTagName')
216
- }));
217
-
218
- var contextProperty = view.get('contextProperty');
219
- if (contextProperty) {
220
- view.set('context', view.get(contextProperty));
221
- }
222
-
223
- itemElem = view.createLayer().$();
224
- if (!insertAtElement) {
225
- elem.append(itemElem);
226
- } else {
227
- itemElem.insertAfter(insertAtElement);
228
- }
229
- insertAtElement = itemElem;
230
-
231
- addedViews.push(view);
247
+ for (idx = 0; idx < len; idx++) {
248
+ item = addedObjects.objectAt(idx);
249
+ childView = this.createChildView(itemViewClass.extend(itemOptions, {
250
+ content: item,
251
+ render: renderFunc,
252
+ tagName: itemViewClass.prototype.tagName || this.get('itemTagName')
253
+ }));
254
+
255
+ var contextProperty = childView.get('contextProperty');
256
+ if (contextProperty) {
257
+ childView.set('context', childView.get(contextProperty));
258
+ }
259
+
260
+ itemElem = childView.createLayer().$();
261
+ if (!insertAtElement) {
262
+ elem.append(itemElem);
263
+ } else {
264
+ itemElem.insertAfter(insertAtElement);
232
265
  }
266
+ insertAtElement = itemElem;
267
+
268
+ addedViews.push(childView);
269
+ }
233
270
 
234
271
  childViews.replace(start, 0, addedViews);
235
272
  }
236
273
 
237
274
  var inverseTemplate = this.get('inverseTemplate');
238
275
  if (childViews.get('length') === 0 && inverseTemplate) {
239
- view = this.createChildView(SC.TemplateView.extend({
276
+ childView = this.createChildView(SC.TemplateView.extend({
240
277
  template: inverseTemplate,
241
278
  content: this
242
279
  }));
243
- this.set('emptyView', view);
244
- view.createLayer().$().appendTo(elem);
245
- this.childViews = [view];
280
+ this.set('emptyView', childView);
281
+ childView.createLayer().$().appendTo(elem);
282
+ this.childViews = [childView];
246
283
  }
247
284
 
248
285
  // Because the layer has been modified, we need to invalidate the frame
@@ -172,7 +172,11 @@ SC.ChildArray = SC.Object.extend(SC.Enumerable, SC.Array,
172
172
  newRecs = this._processRecordsToHashes(recs);
173
173
  children.replace(idx, amt, newRecs);
174
174
  // notify that the record did change...
175
- if (newRecs !== this._prevChildren) this.recordPropertyDidChange();
175
+ if (newRecs !== this._prevChildren){
176
+ this._performRecordPropertyChange(null, false);
177
+ this.arrayContentWillChange(idx, amt, len);
178
+ this._childrenContentDidChange(idx, amt, len);
179
+ }
176
180
  record.recordDidChange(pname);
177
181
 
178
182
  return this;
@@ -219,10 +223,25 @@ SC.ChildArray = SC.Object.extend(SC.Enumerable, SC.Array,
219
223
  @returns {SC.ChildArray} itself.
220
224
  */
221
225
  recordPropertyDidChange: function(keys) {
226
+ this._performRecordPropertyChange(keys, true);
227
+ return this;
228
+ },
229
+
230
+ /** @private
231
+ Invoked when the object is changed from the parent or an outside source
232
+
233
+ will cause the entire array to reset
234
+
235
+ @param {SC.Array} keys optional
236
+ @param {Boolean} doReset optional
237
+ @returns {SC.ChildArray} itself.
238
+ */
239
+ _performRecordPropertyChange: function(keys, doReset){
222
240
  if (keys && !keys.contains(this.get('propertyName'))) return this;
223
241
 
224
242
  var children = this.get('readOnlyChildren'), oldLen = 0, newLen = 0;
225
243
  var prev = this._prevChildren, f = this._childrenContentDidChange;
244
+ doReset = SC.none(doReset) ? true : doReset;
226
245
 
227
246
  if (children === prev) return this; // nothing to do
228
247
 
@@ -245,11 +264,12 @@ SC.ChildArray = SC.Object.extend(SC.Enumerable, SC.Array,
245
264
 
246
265
  newLen = children.get('length');
247
266
  }
248
-
249
-
250
- this.arrayContentWillChange(0, oldLen, newLen);
251
267
  this._prevChildren = children;
252
- this._childrenContentDidChange(0, oldLen, newLen);
268
+
269
+ if (doReset){
270
+ this.arrayContentWillChange(0, oldLen, newLen);
271
+ this._childrenContentDidChange(0, oldLen, newLen);
272
+ }
253
273
 
254
274
  return this;
255
275
  },
@@ -316,11 +316,11 @@ SC.RecordArray = SC.Object.extend(SC.Enumerable, SC.Array,
316
316
 
317
317
  @returns {SC.RecordArray}
318
318
  */
319
- find: function(query, target) {
319
+ find: function(original, query, target) {
320
320
  if (query && query.isQuery) {
321
321
  return this.get('store').find(query.queryWithScope(this));
322
- } else return sc_super();
323
- },
322
+ } else return original.apply(this, SC.$A(arguments).slice(1));
323
+ }.enhance(),
324
324
 
325
325
  /**
326
326
  Call whenever you want to refresh the results of this query. This will
@@ -378,7 +378,30 @@ test("pushObject should trigger an arrayContentDidChange with only 1 added item"
378
378
  testParent.get('elements').pushObject({});
379
379
 
380
380
  equals(didChangeCalls.length, 1, 'didChange should only be called once');
381
- equals(didChangeCalls[0][0], 0, 'didChange should be called with a start index of 0 because we can\'t be sure about the order from the server');
382
- equals(didChangeCalls[0][1], 4, 'didChange should be called with a removed count of 4');
383
- equals(didChangeCalls[0][2], 5, 'didChange should be called with an added count of 5 because the items could have changed order on the server');
381
+ equals(didChangeCalls[0][0], 4, 'didChange should be called with a start index of 4');
382
+ equals(didChangeCalls[0][1], 0, 'didChange should be called with a removed count of 0');
383
+ equals(didChangeCalls[0][2], 1, 'didChange should be called with an added count of 1');
384
+ });
385
+
386
+ test("replace should trigger an arrayContentDidChange with only 1 added item", function() {
387
+ var didChangeCalls = [], target;
388
+
389
+ target = SC.Object.create({
390
+ willChange: function() {},
391
+ didChange: function() {
392
+ didChangeCalls.push(arguments);
393
+ }
394
+ });
395
+
396
+ testParent.get('elements').addArrayObservers({
397
+ target: target,
398
+ willChange: 'willChange',
399
+ didChange: 'didChange'
400
+ });
401
+ testParent.get('elements').replace(3, 1, [{}]);
402
+
403
+ equals(didChangeCalls.length, 1, 'didChange should only be called once');
404
+ equals(didChangeCalls[0][0], 3, 'didChange should be called with a start index of 3');
405
+ equals(didChangeCalls[0][1], 1, 'didChange should be called with a removed count of 1');
406
+ equals(didChangeCalls[0][2], 1, 'didChange should be called with an added count of 1');
384
407
  });
@@ -6,22 +6,28 @@
6
6
  /*globals module ok equals same test MyApp */
7
7
 
8
8
  // test core array-mapping methods for RecordArray
9
- var store, storeKey, json, rec, storeKeys, recs;
9
+ var store, storeKey, json, rec, storeKey2, json2, rec2, storeKeys, recs;
10
10
  module("SC.RecordArray core methods", {
11
11
  setup: function() {
12
12
  // setup dummy store
13
13
  store = SC.Store.create();
14
+
14
15
  storeKey = SC.Record.storeKeyFor('foo');
15
- json = { guid: "foo", foo: "bar" };
16
- store.writeDataHash(storeKey, json, SC.Record.READY_CLEAN);
17
-
18
-
19
- // get record
16
+ json = { guid: "foo", foo: "bar" };
17
+ store.writeDataHash(storeKey, json, SC.Record.READY_CLEAN);
18
+
19
+ storeKey2 = SC.Record.storeKeyFor('baz');
20
+ json2 = { guid: "baz", baz: "bash" };
21
+ store.writeDataHash(storeKey2, json2, SC.Record.READY_CLEAN);
22
+
23
+ // get records
20
24
  rec = store.materializeRecord(storeKey);
21
- equals(rec.get('foo'), 'bar', 'record should have json');
22
-
25
+ equals(rec.get('foo'), 'bar', 'precond - record should have json');
26
+ rec2 = store.materializeRecord(storeKey2);
27
+ equals(rec2.get('baz'), 'bash', 'precond - record 2 should have json');
28
+
23
29
  // get record array.
24
- storeKeys = [storeKey];
30
+ storeKeys = [storeKey, storeKey2];
25
31
  recs = SC.RecordArray.create({ store: store, storeKeys: storeKeys });
26
32
  }
27
33
  });
@@ -32,25 +38,25 @@ test("initial status", function() {
32
38
 
33
39
  // ..........................................................
34
40
  // LENGTH
35
- //
41
+ //
36
42
 
37
43
  test("should pass through length", function() {
38
- equals(recs.get('length'), storeKeys.length, 'rec should pass through length');
44
+ equals(recs.get('length'), storeKeys.length, 'rec should pass through length');
39
45
  });
40
46
 
41
47
  test("changing storeKeys length should change length of rec array also", function() {
42
48
 
43
49
  var oldlen = recs.get('length');
44
-
50
+
45
51
  storeKeys.pushObject(SC.Store.generateStoreKey()); // change length
46
-
52
+
47
53
  ok(storeKeys.length > oldlen, 'precond - storeKeys.length should have changed');
48
- equals(recs.get('length'), storeKeys.length, 'rec should pass through length');
54
+ equals(recs.get('length'), storeKeys.length, 'rec should pass through length');
49
55
  });
50
56
 
51
57
  // ..........................................................
52
58
  // objectAt
53
- //
59
+ //
54
60
 
55
61
  test("should materialize record for object", function() {
56
62
  equals(storeKeys[0], storeKey, 'precond - storeKeys[0] should be storeKey');
@@ -63,67 +69,70 @@ test("reading past end of array length should return undefined", function() {
63
69
 
64
70
  test("modifying the underlying storeKey should change the returned materialized record", function() {
65
71
  // read record once to make it materialized
66
- equals(recs.objectAt(0), rec, 'recs.objectAt(0) should materialize record');
67
-
72
+ equals(recs.objectAt(0), rec, 'recs.objectAt(0) should materialize record');
73
+
68
74
  // create a new record.
69
75
  SC.RunLoop.begin();
70
- var rec2 = store.createRecord(SC.Record, { foo: "rec2" });
76
+ var rec3 = store.createRecord(SC.Record, { foo: "rec3" });
71
77
  SC.RunLoop.end();
72
78
 
73
- var storeKey2 = rec2.get('storeKey');
74
-
79
+ var storeKey3 = rec3.get('storeKey');
80
+
75
81
  // add to beginning of storeKey array
76
- storeKeys.unshiftObject(storeKey2);
77
- equals(recs.get('length'), 2, 'should now have length of 2');
78
- equals(recs.objectAt(0), rec2, 'objectAt(0) should return new record');
79
- equals(recs.objectAt(1), rec, 'objectAt(1) should return old record');
82
+ storeKeys.unshiftObject(storeKey3);
83
+ equals(recs.get('length'), 3, 'should now have length of 3');
84
+ equals(recs.objectAt(0), rec3, 'objectAt(0) should return new record');
85
+ equals(recs.objectAt(1), rec, 'objectAt(1) should return old record 1');
86
+ equals(recs.objectAt(2), rec2, 'objectAt(2) should return old record 2');
80
87
  });
81
88
 
82
89
  test("reading a record not loaded in store should trigger retrieveRecord", function() {
83
90
  var callCount = 0;
84
91
 
85
- // patch up store to record a call and to make it look like data is not
92
+ // patch up store to record a call and to make it look like data is not
86
93
  // loaded.
87
94
  store.removeDataHash(storeKey, SC.Record.EMPTY);
88
95
  store.retrieveRecord = function() { callCount++; };
89
-
96
+
90
97
  equals(store.peekStatus(storeKeys.objectAt(0)), SC.Record.EMPTY, 'precond - storeKey must not be loaded');
91
-
98
+
92
99
  var rec = recs.objectAt(0);
93
100
  equals(callCount, 1, 'store.retrieveRecord() should have been called');
94
101
  });
95
102
 
96
103
  // ..........................................................
97
104
  // replace()
98
- //
105
+ //
99
106
 
100
107
  test("adding a record to the record array should pass through storeKeys", function() {
101
108
  // read record once to make it materialized
102
- equals(recs.objectAt(0), rec, 'recs.objectAt(0) should materialize record');
103
-
109
+ equals(recs.objectAt(0), rec, 'recs.objectAt(0) should materialize record');
110
+
104
111
  // create a new record.
105
112
  SC.RunLoop.begin();
106
- var rec2 = store.createRecord(SC.Record, { foo: "rec2" });
113
+ var rec3 = store.createRecord(SC.Record, { foo: "rec3" });
107
114
  SC.RunLoop.end();
108
-
109
- var storeKey2 = rec2.get('storeKey');
110
-
115
+
116
+ var storeKey3 = rec3.get('storeKey');
117
+
111
118
  // add record to beginning of record array
112
- recs.unshiftObject(rec2);
113
-
119
+ recs.unshiftObject(rec3);
120
+
114
121
  // verify record array
115
- equals(recs.get('length'), 2, 'should now have length of 2');
116
- equals(recs.objectAt(0), rec2, 'recs.objectAt(0) should return new record');
117
- equals(recs.objectAt(1), rec, 'recs.objectAt(1) should return old record');
118
-
122
+ equals(recs.get('length'), 3, 'should now have length of 3');
123
+ equals(recs.objectAt(0), rec3, 'recs.objectAt(0) should return new record');
124
+ equals(recs.objectAt(1), rec, 'recs.objectAt(1) should return old record 1');
125
+ equals(recs.objectAt(2), rec2, 'recs.objectAt(2) should return old record 2');
126
+
119
127
  // verify storeKeys
120
- equals(storeKeys.objectAt(0), storeKey2, 'storeKeys[0] should return new storeKey');
121
- equals(storeKeys.objectAt(1), storeKey, 'storeKeys[1] should return old storeKey');
128
+ equals(storeKeys.objectAt(0), storeKey3, 'storeKeys[0] should return new storeKey');
129
+ equals(storeKeys.objectAt(1), storeKey, 'storeKeys[1] should return old storeKey 1');
130
+ equals(storeKeys.objectAt(2), storeKey2, 'storeKeys[2] should return old storeKey 2');
122
131
  });
123
132
 
124
133
  // ..........................................................
125
134
  // Property Observing
126
- //
135
+ //
127
136
 
128
137
  test("changing the underlying storeKeys should notify observers of records", function() {
129
138
 
@@ -132,8 +141,8 @@ test("changing the underlying storeKeys should notify observers of records", fun
132
141
  cnt: 0,
133
142
  observer: function() { this.cnt++; }
134
143
  });
135
- recs.addObserver('[]', obj, obj.observer);
136
-
144
+ recs.addObserver('[]', obj, obj.observer);
145
+
137
146
  // now modify storeKeys
138
147
  storeKeys.pushObject(SC.Store.generateStoreKey());
139
148
  equals(obj.cnt, 1, 'observer should have fired after changing storeKeys');
@@ -145,7 +154,7 @@ test("swapping storeKey array should change recordArray and observers", function
145
154
  SC.RunLoop.begin();
146
155
  var rec2 = store.createRecord(SC.Record, { foo: "rec2" });
147
156
  SC.RunLoop.end();
148
-
157
+
149
158
  var storeKey2 = rec2.get('storeKey');
150
159
  var storeKeys2 = [storeKey2];
151
160
 
@@ -154,24 +163,36 @@ test("swapping storeKey array should change recordArray and observers", function
154
163
  cnt: 0,
155
164
  observer: function() { this.cnt++; }
156
165
  });
157
- recs.addObserver('[]', obj, obj.observer);
158
-
166
+ recs.addObserver('[]', obj, obj.observer);
167
+
159
168
  // read record once to make it materialized
160
- equals(recs.objectAt(0), rec, 'recs.objectAt(0) should materialize record');
161
-
169
+ equals(recs.objectAt(0), rec, 'recs.objectAt(0) should materialize record');
170
+
162
171
  // now swap storeKeys
163
172
  obj.cnt = 0 ;
164
173
  recs.set('storeKeys', storeKeys2);
165
-
174
+
166
175
  // verify observer fired and record changed
167
176
  equals(obj.cnt, 1, 'observer should have fired after swap');
168
177
  equals(recs.objectAt(0), rec2, 'recs.objectAt(0) should return new rec');
169
-
178
+
170
179
  // modify storeKey2, make sure observer fires and content changes
171
180
  obj.cnt = 0;
172
181
  storeKeys2.unshiftObject(storeKey);
173
182
  equals(obj.cnt, 1, 'observer should have fired after edit');
174
183
  equals(recs.get('length'), 2, 'should reflect new length');
175
- equals(recs.objectAt(0), rec, 'recs.objectAt(0) should return pushed rec');
184
+ equals(recs.objectAt(0), rec, 'recs.objectAt(0) should return pushed rec');
185
+
186
+ });
187
+
188
+ test("find works with query", function(){
189
+ var filtered = recs.find(SC.Query.create({ conditions: "foo = 'bar'" }));
190
+
191
+ equals(filtered.get('length'), 1);
192
+ equals(filtered.objectAt(0), rec);
193
+ });
176
194
 
195
+ test("find works as enumerable", function(){
196
+ var filtered = recs.find(function(r){ return r.get('foo') === 'bar'; });
197
+ equals(filtered, rec);
177
198
  });