sproutcore 0.9.17 → 0.9.18

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 (72) hide show
  1. data/History.txt +45 -2
  2. data/Manifest.txt +10 -0
  3. data/Rakefile +1 -1
  4. data/app_generators/sproutcore/templates/sc-config +8 -2
  5. data/bin/sc-server +4 -0
  6. data/clients/sc_docs/english.lproj/body.css +0 -20
  7. data/clients/sc_docs/english.lproj/body.rhtml +1 -3
  8. data/clients/sc_docs/english.lproj/strings.js +1 -1
  9. data/clients/sc_docs/french.lproj/strings.js +14 -0
  10. data/clients/sc_test_runner/english.lproj/body.css +0 -20
  11. data/clients/sc_test_runner/english.lproj/body.rhtml +1 -3
  12. data/config/hoe.rb +1 -1
  13. data/frameworks/sproutcore/HISTORY +56 -1
  14. data/frameworks/sproutcore/debug/trace.js +81 -0
  15. data/frameworks/sproutcore/debug/unittest.js +2 -1
  16. data/frameworks/sproutcore/english.lproj/buttons.css +5 -2
  17. data/frameworks/sproutcore/english.lproj/core.css +0 -16
  18. data/frameworks/sproutcore/english.lproj/images/sc-theme-sprite.png +0 -0
  19. data/frameworks/sproutcore/english.lproj/splitview.css +83 -0
  20. data/frameworks/sproutcore/english.lproj/theme.css +21 -5
  21. data/frameworks/sproutcore/foundation/object.js +23 -0
  22. data/frameworks/sproutcore/foundation/string.js +4 -3
  23. data/frameworks/sproutcore/lib/core_views.rb +43 -8
  24. data/frameworks/sproutcore/lib/form_views.rb +2 -2
  25. data/frameworks/sproutcore/lib/index.rhtml +1 -1
  26. data/frameworks/sproutcore/mixins/enumerable.js +4 -8
  27. data/frameworks/sproutcore/mixins/selection_support.js +1 -1
  28. data/frameworks/sproutcore/models/collection.js +14 -3
  29. data/frameworks/sproutcore/models/record.js +6 -5
  30. data/frameworks/sproutcore/models/store.js +3 -3
  31. data/frameworks/sproutcore/panes/picker.js +1 -0
  32. data/frameworks/sproutcore/server/rails_server.js +4 -7
  33. data/frameworks/sproutcore/server/server.js +58 -1
  34. data/frameworks/sproutcore/tests/controllers/object.rhtml +1 -1
  35. data/frameworks/sproutcore/tests/models/collection.rhtml +160 -0
  36. data/frameworks/sproutcore/tests/models/model.rhtml +15 -3
  37. data/frameworks/sproutcore/tests/views/collection/base.rhtml +120 -47
  38. data/frameworks/sproutcore/tests/views/collection/source_list_rendering.rhtml +232 -0
  39. data/frameworks/sproutcore/tests/views/view/frame.rhtml +2 -2
  40. data/frameworks/sproutcore/tests/views/view/innerFrame.rhtml +87 -85
  41. data/frameworks/sproutcore/tests/views/view/scrollFrame.rhtml +25 -26
  42. data/frameworks/sproutcore/views/collection/collection.js +5 -1
  43. data/frameworks/sproutcore/views/field/select_field.js +1 -1
  44. data/frameworks/sproutcore/views/radio_group.js +2 -2
  45. data/frameworks/sproutcore/views/split.js +191 -174
  46. data/frameworks/sproutcore/views/split_divider.js +71 -68
  47. data/frameworks/sproutcore/views/view.js +65 -25
  48. data/lib/sproutcore.rb +4 -1
  49. data/lib/sproutcore/build_tools/html_builder.rb +50 -46
  50. data/lib/sproutcore/build_tools/resource_builder.rb +17 -5
  51. data/lib/sproutcore/bundle_installer.rb +3 -1
  52. data/lib/sproutcore/bundle_manifest.rb +4 -3
  53. data/lib/sproutcore/cssmin.rb +195 -0
  54. data/lib/sproutcore/generator_helper.rb +15 -0
  55. data/lib/sproutcore/helpers/capture_helper.rb +2 -22
  56. data/lib/sproutcore/helpers/dom_id_helper.rb +14 -0
  57. data/lib/sproutcore/helpers/static_helper.rb +6 -2
  58. data/lib/sproutcore/helpers/text_helper.rb +1 -1
  59. data/lib/sproutcore/merb.rb +2 -2
  60. data/lib/sproutcore/renderers/erubis.rb +43 -0
  61. data/lib/sproutcore/renderers/haml.rb +28 -0
  62. data/lib/sproutcore/renderers/sass.rb +42 -0
  63. data/lib/sproutcore/version.rb +1 -1
  64. data/lib/sproutcore/view_helpers.rb +40 -46
  65. data/sc_generators/controller/controller_generator.rb +1 -1
  66. data/sc_generators/language/USAGE +5 -7
  67. data/sc_generators/language/language_generator.rb +1 -1
  68. data/sc_generators/language/templates/strings.js +5 -1
  69. data/sc_generators/model/model_generator.rb +1 -1
  70. data/sc_generators/test/test_generator.rb +1 -1
  71. data/sc_generators/view/view_generator.rb +1 -1
  72. metadata +12 -5
@@ -216,6 +216,7 @@ SC.Record = SC.Object.extend(
216
216
  if (ret === undefined) {
217
217
  var attr = this._attributes ;
218
218
  ret = (attr) ? attr[key] : undefined ;
219
+ ret = ret || this[key] ; // also check properties...
219
220
  if (ret !== undefined) {
220
221
  var recordType = this._getRecordType(key+'Type') ;
221
222
  ret = this._propertyFromAttribute(ret, recordType) ;
@@ -248,7 +249,6 @@ SC.Record = SC.Object.extend(
248
249
  */
249
250
  recordDidChange: function() {
250
251
  this.incrementProperty('changeCount') ;
251
- if (SC.Store) SC.Store.recordDidChange(this) ;
252
252
  },
253
253
 
254
254
  /**
@@ -500,7 +500,7 @@ SC.Record = SC.Object.extend(
500
500
 
501
501
  _matchValue: function(recValue,value) {
502
502
  // if we get here with recValue as a record, we must compare by guid, so grab it
503
- if (recValue && recValue.primaryKey) recValue = recValue.get(recValue.primaryKey) ;
503
+ if (recValue && recValue.primaryKey) recValue = recValue.get(recValue.get('primaryKey')) ;
504
504
  var stringify = (value instanceof RegExp);
505
505
  if (stringify) {
506
506
  if (recValue == null) return false ;
@@ -648,7 +648,7 @@ SC.Record = SC.Object.extend(
648
648
  _convertValueOut: function(value,typeConverter,recordType) {
649
649
  if (typeConverter) return typeConverter(value,'out') ;
650
650
  if (recordType) {
651
- return (value) ? value.get(recordType.primaryKey) : null ;
651
+ return (value) ? value.get(recordType.primaryKey()) : null ;
652
652
  } else return value ;
653
653
  },
654
654
 
@@ -742,7 +742,7 @@ SC.Record.mixin(
742
742
  var conditions = opts.conditions || {} ;
743
743
  opts.conditions = conditions ;
744
744
 
745
- var privateKey = '_' + conditionKey ;
745
+ var privateKey = '_' + conditionKey + SC.generateGuid() ;
746
746
  return function() {
747
747
  if (!this[privateKey]) {
748
748
  var recordType = eval(recordTypeString);
@@ -781,7 +781,8 @@ SC.Record.Date = function(value,direction) {
781
781
  } else if (typeof(value) == "string") {
782
782
  // try to parse date. trim any decimal numbers at end since Rails sends
783
783
  // this sometimes.
784
- var ret = Date.parse(value.replace(/\.\d+$/,'')) ;
784
+ var ret = Date.parseDate(value.replace(/\.\d+$/,'')) ;
785
+ if (!ret) ret = new Date(value);
785
786
  if (ret) value = ret ;
786
787
  }
787
788
  return value ;
@@ -291,9 +291,9 @@ SC.Store = SC.Object.create(
291
291
  */
292
292
  recordDidChange: function(rec) {
293
293
  // add to changed records. This will eventually notify collections.
294
- var guid = rec._storeKey() ;
295
- changed = this.get('_changedRecords') || {};
296
- records = changed[guid] || {} ;
294
+ var guid = rec._storeKey(),
295
+ changed = this.get('_changedRecords') || {},
296
+ records = changed[guid] || {} ;
297
297
  records[rec._guid] = rec ;
298
298
 
299
299
  changed[guid] = records ;
@@ -33,6 +33,7 @@ SC.PickerPaneView = SC.OverlayPaneView.extend({
33
33
  } else {
34
34
  var wsize = SC.window.get('size') ;
35
35
  var psize = picker.get('size') ;
36
+ origin = {};
36
37
  origin.x = (wsize.width - psize.width) / 2 ;
37
38
  origin.y = (wsize.height - psize.height) / 2 ;
38
39
  }
@@ -53,14 +53,11 @@ require('server/rest_server') ;
53
53
  map.connect 'auth-token.js', :controller => 'application', :action => 'auth_token'
54
54
  }}}
55
55
 
56
- Copy-and-paste the default index template of SproutCore into your own
57
- client app. Refer to your new default index template by modifying the
58
- :layout option in your sc-config file. Lastly, within this default
59
- index template add a line to call auth-token.js on your rails server.
60
- For example:
61
-
56
+ Lastly, add a reference to the script to the :javascript_libs property
57
+ in your sc-config file, for example:
58
+
62
59
  {{{
63
- <script src="/sc/auth-token.js" type="text/javascript"></script>
60
+ c[:javascript_libs] = ['/sc/auth-token.js']
64
61
  }}}
65
62
 
66
63
 
@@ -288,7 +288,7 @@ SC.Server = SC.Object.extend({
288
288
  var key = r.get(primaryKey);
289
289
  if (key) { ids.push(key); context[key] = r; }
290
290
  });
291
- context._recordType = curRecords[0].recordType ; // default rec type.
291
+ context._recordType = this._instantiateRecordType(curRecords[0].get('type'), this.prefix, null) ; // default rec type.
292
292
 
293
293
  params = {
294
294
  requestContext: context,
@@ -503,6 +503,50 @@ SC.Server = SC.Object.extend({
503
503
  // ................................
504
504
  // PRIVATE METHODS
505
505
 
506
+ _prepareDataForRecords: function(data, server, defaultType) {
507
+ if (data === null) {
508
+ return null;
509
+ } else if ($type(data) == T_ARRAY) {
510
+ var that = this;
511
+ return data.map( function(d) {
512
+ return that._prepareDataForRecords(d, server, defaultType) ;
513
+ }) ;
514
+ } else if ($type(data) == T_HASH) {
515
+ data = server._camelizeData(data) ; // camelize the keys received back.
516
+ if (data.id) {
517
+ // convert the 'id' property to 'guid'
518
+ data.guid = data.id;
519
+ delete data.id;
520
+ }
521
+ data.recordType = server._instantiateRecordType(data.type, server.prefix, defaultType);
522
+ if (data.recordType) {
523
+ return data;
524
+ } else {
525
+ console.log("Data RecordType could not be instantiated!: "+data.type) ;
526
+ return null; // could not process.
527
+ }
528
+ } else {
529
+ console.log("Unknown data type in SC.Server#_prepareDataForRecords. Should be array or hash.") ;
530
+ return null; // could not process.
531
+ }
532
+ },
533
+
534
+ _instantiateRecordType: function(recordType, prefix, defaultType) {
535
+ if (recordType) {
536
+ var recordName = recordType.capitalize() ;
537
+ if (prefix) {
538
+ for (var prefixLoc = 0; prefixLoc < prefix.length; prefixLoc++) {
539
+ var prefixParts = prefix[prefixLoc].split('.');
540
+ var namespace = window;
541
+ for (var prefixPartsLoc = 0; prefixPartsLoc < prefixParts.length; prefixPartsLoc++) {
542
+ var namespace = namespace[prefixParts[prefixPartsLoc]] ;
543
+ }
544
+ if (namespace !== window) return namespace[recordName] ;
545
+ }
546
+ } else return window[recordName] ;
547
+ } else return defaultType;
548
+ },
549
+
506
550
  // places records from array into hash, sorted by resourceURL.
507
551
  _recordsByResource: function(records) {
508
552
  var ret = {} ;
@@ -590,6 +634,19 @@ SC.Server = SC.Object.extend({
590
634
 
591
635
  // handle other values
592
636
  } else return [rootKey,params].join('=') ;
637
+ },
638
+
639
+ init: function() {
640
+ sc_super();
641
+ SC.Server.addServer(this);
593
642
  }
594
643
 
595
644
  }) ;
645
+
646
+ SC.Server.servers = [];
647
+
648
+ SC.Server.addServer = function(server) {
649
+ var ary = SC.Server.servers;
650
+ ary.push(server);
651
+ SC.Server.servers = ary;
652
+ };
@@ -250,7 +250,7 @@ Test.context("SC.ObjectController", {
250
250
  var rcrds = Contact.collection();
251
251
  cc.set('content', rcrds);
252
252
  rcrds.refresh();
253
- var single = Contact.create({'test' : 'NAME1', 'value' : 0});
253
+ var single = Contact.newRecord({'test' : 'NAME1', 'value' : 0});
254
254
 
255
255
  rcrds.count().shouldEqual(1);
256
256
 
@@ -0,0 +1,160 @@
1
+ <% # ========================================================================
2
+ # Collection Unit Test
3
+ # ========================================================================
4
+ %>
5
+ <% content_for('final') do %>
6
+
7
+ <script>
8
+
9
+
10
+ //
11
+ // core.js stub
12
+ //
13
+ CollectionTest = SC.Object.create({
14
+
15
+ server: SC.Server.create({ prefix: ['CollectionTest'] }),
16
+
17
+ FIXTURES: []
18
+
19
+ }) ;
20
+
21
+ //
22
+ // fixtures stub
23
+ //
24
+ CollectionTest.FIXTURES = CollectionTest.FIXTURES.concat([
25
+
26
+ { guid: '1',
27
+ type: 'Employee',
28
+ name: "Anne",
29
+ sex: "Female"
30
+ },
31
+
32
+ { guid: '2',
33
+ type: 'Employee',
34
+ name: "Bob",
35
+ sex: "Male"
36
+ },
37
+
38
+ { guid: '3',
39
+ type: 'Employee',
40
+ name: "Alice",
41
+ sex: "Female"
42
+ },
43
+
44
+ { guid: '4',
45
+ type: 'Employee',
46
+ name: "Rachel",
47
+ sex: "Female"
48
+ },
49
+
50
+ { guid: '5',
51
+ type: 'Employee',
52
+ name: "Michael",
53
+ sex: "Male"
54
+ },
55
+
56
+ { guid: '6',
57
+ type: 'Employee',
58
+ name: "Barbara",
59
+ sex: "Female"
60
+ },
61
+
62
+ { guid: '7',
63
+ type: 'Employee',
64
+ name: "Richard",
65
+ sex: "Male"
66
+ }
67
+
68
+ ]);
69
+
70
+ //
71
+ // model classes
72
+ //
73
+ CollectionTest.Employee = SC.Record.extend({
74
+
75
+ }) ;
76
+
77
+ //
78
+ // main.js stub
79
+ //
80
+ CollectionTest.server.preload(CollectionTest.FIXTURES) ;
81
+
82
+ Test.context("Test basic functions of a collection", {
83
+
84
+ setup: function()
85
+ {
86
+ this.employees = CollectionTest.Employee.collection()
87
+
88
+ this.anne = CollectionTest.Employee.find('1');
89
+ this.bob = CollectionTest.Employee.find('2');
90
+ this.alice = CollectionTest.Employee.find('3');
91
+ this.rachel = CollectionTest.Employee.find('4');
92
+ this.michael = CollectionTest.Employee.find('5');
93
+ this.barbara = CollectionTest.Employee.find('6');
94
+ this.richard = CollectionTest.Employee.find('7');
95
+ },
96
+
97
+ teardown: function()
98
+ {
99
+ delete this.employees;
100
+ delete this.anne;
101
+ delete this.bob;
102
+ delete this.alice;
103
+ delete this.rachel;
104
+ delete this.michael;
105
+ delete this.barbara;
106
+ delete this.richard;
107
+ },
108
+
109
+ "Collection should initially be empty": function() {
110
+ assertNull(this.employees.get('records'));
111
+ },
112
+
113
+ "Collection should have 7 records upon refresh": function() {
114
+ this.employees.refresh();
115
+ this.employees.get('records').length.shouldEqual(7);
116
+ },
117
+
118
+ "Collections should NOT contain records that have NOT been added to the store": function() {
119
+ this.employees.refresh();
120
+ var originalLength = this.employees.get('records').length;
121
+ var newEmployee = CollectionTest.Employee.create({name: "Joe"});
122
+ this.employees.get('records').length.shouldEqual(originalLength);
123
+ },
124
+
125
+ "Collections should contain records that have been added to the store": function() {
126
+ this.employees.refresh();
127
+ var originalLength = this.employees.get('records').length;
128
+ var newEmployee = CollectionTest.Employee.newRecord({name: "Joe"});
129
+ this.employees.get('records').length.shouldEqual(originalLength + 1);
130
+ newEmployee.destroy();
131
+ },
132
+
133
+ "Collections should be properly ordered": function() {
134
+ var employeesByName = CollectionTest.Employee.collection({orderBy: ['name']});
135
+ employeesByName.refresh();
136
+ var names = employeesByName.get('records').map(function(e) { return e.get('name') });
137
+ assertIdentical(["Alice", "Anne", "Barbara", "Bob", "Michael", "Rachel", "Richard"].join(""), names.join(""));
138
+
139
+ var employeesBySex = CollectionTest.Employee.collection({orderBy: ['sex']});
140
+ employeesBySex.refresh();
141
+ var sexes = employeesBySex.get('records').map(function(e) { return e.get('sex') });
142
+ assertIdentical(["Female", "Female", "Female", "Female", "Male", "Male", "Male"].join(""), sexes.join(""));
143
+ },
144
+
145
+ "Collections should remain unchanged if a record is changed in a way that does not affect the order": function() {
146
+ var employeesBySex = CollectionTest.Employee.collection({orderBy: ['sex']});
147
+ employeesBySex.refresh();
148
+ var employeesOriginal = employeesBySex.get('records').map(function(e) { return e.get('guid') }).join(", ");
149
+
150
+ this.bob.set('name', 'Robert');
151
+ var employees = employeesBySex.get('records').map(function(e) { return e.get('guid') }).join(", ");
152
+
153
+ assertIdentical(employeesOriginal, employees);
154
+ }
155
+
156
+ });
157
+
158
+ </script>
159
+
160
+ <% end %>
@@ -89,12 +89,14 @@ Test.context("Test model comparisons with numeric guids", {
89
89
 
90
90
  teardown: function()
91
91
  {
92
- delete this.todoList;
92
+ delete this.todoList1;
93
+ delete this.todoList2;
93
94
  delete this.todo1;
94
95
  delete this.todo2;
96
+ delete this.todo3;
95
97
  },
96
98
 
97
- "Objects should exist in Store": function()
99
+ "Records should exist in Store": function()
98
100
  {
99
101
  assertNotNull(this.todoList1);
100
102
  assertNotNull(this.todoList2);
@@ -103,6 +105,15 @@ Test.context("Test model comparisons with numeric guids", {
103
105
  assertNotNull(this.todo3);
104
106
  },
105
107
 
108
+ "Records should have correct guid": function()
109
+ {
110
+ assertEqual(1, this.todoList1.get('guid'));
111
+ assertEqual(2, this.todoList2.get('guid'));
112
+ assertEqual(1, this.todo1.get('guid'));
113
+ assertEqual(2, this.todo2.get('guid'));
114
+ assertEqual(3, this.todo3.get('guid'));
115
+ },
116
+
106
117
  "Todo 1 and 2 should be related to TodoList 1": function()
107
118
  {
108
119
  assertIdentical(this.todoList1, this.todo1.get('todoList'));
@@ -175,7 +186,8 @@ Test.context("Test model comparisons with numeric guids", {
175
186
  "toString() should show model class name": function()
176
187
  {
177
188
  var re = /^ModelTest.Todo/;
178
- assert( this.todo1.toString().match(re), "Todo 1 toString() should start with ModelTest.Todo" );
189
+ var str = this.todo1.toString();
190
+ assert( str.match(re), "Todo 1 toString() should start with ModelTest.Todo, actually starts with " + str);
179
191
  }
180
192
 
181
193
  });
@@ -1,34 +1,67 @@
1
1
  <% content_for('final') do %>
2
2
  <script>
3
3
 
4
- Test.context("A SC.CollectionView with it's content set to a SC.CollectionController", {
4
+ // create some item data...
5
+ [
6
+ { guid: '1001', name: 'item one' },
7
+ { guid: '1002', name: 'item two' },
8
+ { guid: '1003', name: 'item three' },
9
+ { guid: '1004', name: 'item four' },
10
+ { guid: '1005', name: 'item five' },
11
+ { guid: '1006', name: 'item six' }
12
+ ].each(function(o){ SC.Store.addRecord(SC.Record.create(o)); });
13
+
14
+ // a collection to hold the items...
15
+ testCollection = SC.Record.collection();
16
+ testCollection.refresh();
17
+
18
+ // a controller for the collection...
19
+ testController = SC.CollectionController.create();
20
+
21
+ Test.context("A SC.CollectionView with it's content set to a SC.CollectionController 1", {
5
22
 
6
- "Should contain the same number of visible item views": function()
23
+ "Should scroll to the selected item": function()
7
24
  {
8
- testCollectionView.get('itemViews').length.shouldEqual(2);
25
+ testCollectionView.get('rootElement').scrollTop.shouldEqual(0);
26
+ testCollectionView.scrollToContent( testCollection.get('records').last() );
27
+ testCollectionView.get('itemViews').length.shouldEqual(3);
28
+ scrollView.get('rootElement').scrollTop.shouldEqual(30);
9
29
  },
10
30
 
11
- "Should update it's item views as it's controller is updated": function()
31
+ setup: function()
12
32
  {
13
- var valueOfFirstItemView = function() {
14
- var itemView = testCollectionView.get('itemViews').first() ;
15
- return (itemView) ? itemView.get('content').get('guid') : null ;
16
- } ;
33
+ // add a scroll view wrapper.
34
+ scrollView = SC.ScrollView.create() ;
35
+ scrollView.set('frame', { x: 10, y: 10, width: 100, height: 30 }) ;
36
+ SC.window.appendChild(scrollView) ;
17
37
 
18
- valueOfFirstItemView().shouldEqual('1001') ;
38
+ // create the view...
39
+ testCollectionView = SC.ListView.create({
40
+ contentValueKey: 'name',
41
+ contentBinding: 'testController.arrangedObjects',
42
+ selectionBinding: 'testController.selection'
43
+ }) ;
44
+ scrollView.set('content', testCollectionView) ;
19
45
 
20
- SC.Store.addRecord( SC.Record.create({ guid: '0999', name: 'item zero' }) );
21
-
22
- valueOfFirstItemView().shouldEqual('0999') ;
46
+ testController.set('content', testCollection) ;
23
47
  },
24
-
25
- "Should scroll to the selected item": function()
48
+
49
+ teardown: function()
26
50
  {
27
- testCollectionView.get('rootElement').scrollTop.shouldEqual(0);
28
- testCollectionView.scrollToContent( testCollection.get('records').last() );
29
- scrollView.get('rootElement').scrollTop.shouldEqual(30);
30
- },
51
+ // remove the view from SC.window
52
+ testCollectionView.removeFromParent() ;
53
+ scrollView.removeFromParent() ;
54
+
55
+ delete testCollectionView ;
56
+ delete scrollView ;
57
+
58
+ testController.set('content', null) ;
59
+ }
60
+
61
+ });
31
62
 
63
+ Test.context("A SC.CollectionView with it's content set to a SC.CollectionController 2", {
64
+
32
65
  "Should not scroll to the selected item if it's already fully visible": function()
33
66
  {
34
67
  scrollView.get('rootElement').scrollTop.shouldEqual(0);
@@ -40,50 +73,89 @@ Test.context("A SC.CollectionView with it's content set to a SC.CollectionContro
40
73
  {
41
74
  // add a scroll view wrapper.
42
75
  scrollView = SC.ScrollView.create() ;
43
- scrollView.set('frame', { x: 10, y: 10, width: 100, height: 30 });
44
- SC.window.appendChild(scrollView);
76
+ scrollView.set('frame', { x: 10, y: 10, width: 100, height: 30 }) ;
77
+ SC.window.appendChild(scrollView) ;
45
78
 
46
79
  // create the view...
47
- testCollectionView = SC.ListView.extend({
80
+ testCollectionView = SC.ListView.create({
48
81
  contentValueKey: 'name',
49
82
  contentBinding: 'testController.arrangedObjects',
50
83
  selectionBinding: 'testController.selection'
51
- }).create();
84
+ }) ;
52
85
  scrollView.set('content', testCollectionView) ;
86
+
87
+ testController.set('content', testCollection) ;
88
+ },
89
+
90
+ teardown: function()
91
+ {
92
+ // remove the view from SC.window
93
+ testCollectionView.removeFromParent() ;
94
+ scrollView.removeFromParent() ;
53
95
 
54
- // create some item data...
55
- [
56
- { guid: '1001', name: 'item one' },
57
- { guid: '1002', name: 'item two' },
58
- { guid: '1003', name: 'item three' },
59
- { guid: '1004', name: 'item four' },
60
- { guid: '1005', name: 'item five' },
61
- { guid: '1006', name: 'item six' }
62
- ].each(function(o){ SC.Store.addRecord(SC.Record.create(o)); });
96
+ delete testCollectionView ;
97
+ delete scrollView ;
63
98
 
64
- // a collection to hold the items...
65
- testCollection = SC.Record.collection();
66
- testCollection.refresh();
99
+ testController.set('content', null) ;
100
+ }
101
+
102
+ });
67
103
 
68
- // a controller for the collection...
69
- testController = SC.CollectionController.create();
70
- testController.set('content', testCollection);
104
+ Test.context("A SC.CollectionView with it's content set to a SC.CollectionController 3", {
105
+
106
+ "Should contain the same number of visible item views as it's controller has records": function()
107
+ {
108
+ testCollectionView.get('itemViews').length.shouldEqual(2);
109
+ },
110
+
111
+ "Should update it's item views as it's controller is updated": function()
112
+ {
113
+ var valueOfFirstItemView = function() {
114
+ var itemView = testCollectionView.get('itemViews').first() ;
115
+ return (itemView) ? itemView.get('content').get('guid') : null ;
116
+ } ;
117
+
118
+ valueOfFirstItemView().shouldEqual('1001') ;
119
+
120
+ var rec = SC.Record.create({ guid: '0999', name: 'item zero' });
121
+ SC.Store.addRecord( rec );
122
+
123
+ valueOfFirstItemView().shouldEqual('0999') ;
124
+ testCollectionView.get('itemViews').length.shouldEqual(2);
125
+
126
+ rec.destroy();
127
+ SC.Store.removeRecord(rec);
128
+ delete rec;
129
+ },
130
+
131
+ setup: function()
132
+ {
133
+ // add a scroll view wrapper.
134
+ scrollView = SC.ScrollView.create() ;
135
+ scrollView.set('frame', { x: 10, y: 10, width: 100, height: 30 }) ;
136
+ SC.window.appendChild(scrollView) ;
71
137
 
138
+ // create the view...
139
+ testCollectionView = SC.ListView.create({
140
+ contentValueKey: 'name',
141
+ contentBinding: 'testController.arrangedObjects',
142
+ selectionBinding: 'testController.selection'
143
+ }) ;
144
+ scrollView.set('content', testCollectionView) ;
145
+
146
+ testController.set('content', testCollection) ;
72
147
  },
148
+
73
149
  teardown: function()
74
150
  {
75
- // tell SC.Store to dump all the records...
76
- // otherwise, since SC.Store is shared across all tests (yuk!) we'll get shared fixtues
77
- testCollection.get('records').each(function(r){ SC.Store.removeRecord(r); });
78
-
79
- // remove the view from SC.window... again, no shared fixtures...
80
- testCollectionView.removeFromParent();
151
+ // remove the view from SC.window
152
+ testCollectionView.removeFromParent() ;
81
153
  scrollView.removeFromParent() ;
82
-
83
- delete testCollectionView;
84
- delete testCollection;
85
- delete testController;
154
+
155
+ delete testCollectionView ;
86
156
  delete scrollView ;
157
+
158
+ testController.set('content', null) ;
87
159
  }
88
160
 
89
161
  });
@@ -135,4 +207,5 @@ Test.context("A SC.CollectionView with it's content set to a SC.ArrayController"
135
207
  });
136
208
 
137
209
  </script>
210
+
138
211
  <% end %>