sproutcore 0.9.17 → 0.9.18

Sign up to get free protection for your applications and to get access to all the features.
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 %>