sproutcore 1.8.1 → 1.8.2.1

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  :major: 1
3
3
  :minor: 8
4
- :patch: 1
4
+ :patch: 2.1
@@ -1,5 +1,5 @@
1
- CHANGE LOG FOR 1.6+
2
- ===================
1
+ CHANGE LOG
2
+ ==========
3
3
 
4
4
  Edge
5
5
  ----------
@@ -18,6 +18,21 @@ Edge
18
18
 
19
19
  ### BUG FIXES
20
20
 
21
+
22
+ 1.8.2 - BUG FIXES
23
+ ----------
24
+
25
+ * Fixed syntax error in Datastore unit test. [c62a0a9]
26
+ * SC.SplitView can now mixin SC.SplitChild. [6f1586c]
27
+ * Thinned picker pane border divs so that they don't overlap the content view. [0b06db2]
28
+ * Prevents target property conflict when configuring button targets with SC.AlertPane. [0364b5c]
29
+ * Changed the aria-orientation of horizontal SC.ScrollView to 'horizontal' from 'vertical'. [c3ee69b]
30
+ * Allows SC.CollectionFastPath to work with sparse content by always returning an item view even when content isn't yet available. [020653b]
31
+ * Prevents SC.GridView from iterating over its content array in order to work with sparse content. [020653b]
32
+ * The 'mobile-safari' body class name is no longer being added in all browsers. [b491224]
33
+ * Enables pasting in SC.TextFieldView to notify that the value changed. [a51318b]
34
+ * Prevents default touch behavior being intercepted on <textarea> and <select> elements. [8093963]
35
+
21
36
  1.8.1 - BUG FIXES
22
37
  ----------
23
38
 
@@ -13,7 +13,7 @@ SC.setupBodyClassNames = function() {
13
13
  if (!el) return ;
14
14
 
15
15
  browser = SC.browser.current ;
16
- platform = SC.browser.windows ? 'windows' : SC.browser.mac ? 'mac' : 'other-platform' ;
16
+ platform = SC.browser.isWindows ? 'windows' : SC.browser.isMac ? 'mac' : 'other-platform' ;
17
17
  style = document.documentElement.style;
18
18
  shadows = (style.MozBoxShadow !== undefined) ||
19
19
  (style.webkitBoxShadow !== undefined) ||
@@ -46,7 +46,7 @@ SC.setupBodyClassNames = function() {
46
46
  }
47
47
 
48
48
  if(browser==="safari" || browser==="chrome") classNames.push('webkit');
49
- if (SC.browser.mobileSafari) classNames.push('mobile-safari') ;
49
+ if (SC.browser.isMobileSafari) classNames.push('mobile-safari') ;
50
50
  if ('createTouch' in document) classNames.push('touch');
51
51
  el.className = classNames.join(' ') ;
52
52
  } ;
@@ -1488,7 +1488,7 @@ SC.RootResponder = SC.Object.extend(
1488
1488
  ignoreTouchHandle: function(evt) {
1489
1489
  if(SC.browser.isMobileSafari){
1490
1490
  var tag = evt.target.tagName;
1491
- if(tag==="INPUT" || tag==="A"){
1491
+ if(tag==="INPUT" || tag==="TEXTAREA" || tag==="A" || tag==="SELECT"){
1492
1492
  evt.allowDefault();
1493
1493
  return YES;
1494
1494
  }
@@ -82,6 +82,29 @@ test("root_responder.makeKeyPane() : Should make the main pane as the key pane i
82
82
  equals(responder.get('keyPane'),lightPane);
83
83
  });
84
84
 
85
+ test("root_responder.ignoreTouchHandle() : Should ignore TEXTAREA, INPUT, A, and SELECT elements", function () {
86
+ var wasMobileSafari = SC.browser.isMobileSafari;
87
+ SC.browser.isMobileSafari = YES;
88
+
89
+ ["A", "INPUT", "TEXTAREA", "SELECT"].forEach(function (tag) {
90
+ ok(responder.ignoreTouchHandle({
91
+ target: { tagName: tag },
92
+ allowDefault: SC.K
93
+ }), "should pass touch events through to &lt;" + tag + "&gt;s");
94
+ });
95
+
96
+ ["AUDIO", "B", "Q", "BR", "BODY", "BUTTON", "CANVAS", "FORM",
97
+ "IFRAME", "IMG", "OPTION", "P", "PROGRESS", "STRONG",
98
+ "TABLE", "TBODY", "TR", "TH", "TD", "VIDEO"].forEach(function (tag) {
99
+ ok(!responder.ignoreTouchHandle({
100
+ target: { tagName: tag },
101
+ allowDefault: SC.K
102
+ }), "should NOT pass touch events through to &lt;" + tag + "&gt;s");
103
+ });
104
+
105
+ SC.browser.isMobileSafari = wasMobileSafari;
106
+ });
107
+
85
108
  //// CLEANUP
86
109
  /// Commenting out this two functions as the methods don't exist
87
110
  //// confirm with Charles
@@ -4,22 +4,22 @@
4
4
  // License: Licensed under MIT license (see license.js)
5
5
  // ==========================================================================
6
6
  /*globals module ok equals same test MyApp */
7
-
7
+
8
8
  // test parsing of query string
9
9
  var store, storeKey, rec1, rec2, rec3, rec4, rec5, MyApp, q;
10
10
  module("SC.Query comparison of records", {
11
11
  setup: function() {
12
-
12
+
13
13
  SC.RunLoop.begin();
14
-
14
+
15
15
  // setup dummy app and store
16
16
  MyApp = SC.Object.create({
17
17
  store: SC.Store.create()
18
18
  });
19
-
19
+
20
20
  // setup a dummy model
21
21
  MyApp.Foo = SC.Record.extend({});
22
-
22
+
23
23
  // load some data
24
24
  MyApp.store.loadRecords(MyApp.Foo, [
25
25
  { guid: 1, firstName: "John", lastName: "Doe", year: 1974 },
@@ -28,9 +28,9 @@ module("SC.Query comparison of records", {
28
28
  { guid: 4, firstName: "Johnny", lastName: "Cash", active: false },
29
29
  { guid: 5, firstName: "Bert", lastName: "Berthold", active: true }
30
30
  ]);
31
-
31
+
32
32
  SC.RunLoop.end();
33
-
33
+
34
34
  rec1 = MyApp.store.find(MyApp.Foo,1);
35
35
  rec2 = MyApp.store.find(MyApp.Foo,2);
36
36
  rec3 = MyApp.store.find(MyApp.Foo,3);
@@ -51,42 +51,42 @@ module("SC.Query comparison of records", {
51
51
  rec18 = MyApp.store.createRecord(MyApp.Foo, { firstName: "Amie", lastName: "Frontenac", active: true });
52
52
  rec19 = MyApp.store.createRecord(MyApp.Foo, { firstName: "Amelie", lastName: "Auguste", active: true });
53
53
  rec20 = MyApp.store.createRecord(MyApp.Foo, { firstName: "Percy", lastName: "Douglas", active: true });
54
-
54
+
55
55
  q = SC.Query.create();
56
56
  }
57
57
  });
58
-
59
-
58
+
59
+
60
60
  // ..........................................................
61
61
  // TESTS
62
- //
62
+ //
63
63
 
64
64
  test("parse() should work with conditions = null", function(){
65
65
  q.parse();
66
66
  });
67
-
67
+
68
68
  test("building the order", function() {
69
69
  // undefined orderBy
70
70
  q.orderBy = null;
71
71
  q.parse();
72
72
  equals(q._order.length, 0, 'order should be empty');
73
-
73
+
74
74
  // empty orderBy
75
75
  q.orderBy = "";
76
76
  q.parse();
77
77
  equals(q._order.length, 0, 'order should be empty');
78
-
78
+
79
79
  // single property
80
80
  q.orderBy = "firstName";
81
81
  q.parse();
82
82
  equals(q._order[0].propertyName,'firstName', 'propertyName should be firstName');
83
-
83
+
84
84
  // more properties
85
85
  q.orderBy = "lastName, firstName";
86
86
  q.parse();
87
87
  equals(q._order[0].propertyName,'lastName', 'propertyName should be lastName');
88
88
  equals(q._order[1].propertyName,'firstName', 'propertyName should be firstName');
89
-
89
+
90
90
  // more properties with direction
91
91
  q.orderBy = "lastName, firstName, year DESC";
92
92
  q.parse();
@@ -102,6 +102,8 @@ test("no order should result in comparison by guid", function() {
102
102
  q.orderBy = null;
103
103
  q.parse();
104
104
  equals(q.compare(rec1,rec2), -1, 'guid 1 should be before guid 2');
105
+ });
106
+
105
107
  /**
106
108
  This test was added to prove new code that switched from ordering by guid
107
109
  if there is no orderBy property on the query to ordering by storeKey if
@@ -147,34 +149,34 @@ test("comparing non existent properties", function() {
147
149
  q.parse();
148
150
  equals(q.compare(rec5,rec1), -1, 'null should be before 1974');
149
151
  });
150
-
152
+
151
153
  test("comparing null and boolean properties", function() {
152
154
  q.orderBy = "active";
153
155
  q.parse();
154
156
  equals(q.compare(rec3,rec4), -1, 'null should be before false');
155
157
  equals(q.compare(rec4,rec5), -1, 'false should be before true');
156
158
  });
157
-
159
+
158
160
  test("comparing number properties", function() {
159
161
  q.orderBy = "year";
160
162
  q.parse();
161
163
  equals(q.compare(rec1,rec2), -1, '1974 should be before 1975');
162
-
164
+
163
165
  q.orderBy = "year DESC";
164
166
  q.parse();
165
167
  equals(q.compare(rec1,rec2), 1, '1974 should be after 1975 with DESC');
166
- });
167
-
168
-
168
+ });
169
+
170
+
169
171
  test("comparing string properties", function() {
170
172
  q.orderBy = "firstName";
171
173
  q.parse();
172
174
  equals(q.compare(rec1,rec2), 1, 'John should be after Jane');
173
-
175
+
174
176
  q.orderBy = "firstName DESC";
175
177
  q.parse();
176
178
  equals(q.compare(rec1,rec2), -1, 'John should be before Jane with DESC');
177
- });
179
+ });
178
180
 
179
181
  test("comparing by equal properties should use guid for order", function() {
180
182
  q.orderBy = "lastName";
@@ -5,9 +5,9 @@
5
5
  // License: Licensed under MIT license (see license.js)
6
6
  // ==========================================================================
7
7
 
8
- /**
8
+ /**
9
9
  @namespace
10
-
10
+
11
11
  An experimental `CollectionView` mixin that makes it extremely fast under
12
12
  certain circumstances, including for mobile devices.
13
13
  */
@@ -19,12 +19,12 @@ SC.CollectionFastPath = {
19
19
  initMixin: function() {
20
20
  this._indexMap = {};
21
21
  },
22
-
22
+
23
23
  /**
24
24
  Returns the pool for a given example view.
25
-
25
+
26
26
  The pool is calculated based on the guid for the example view class.
27
-
27
+
28
28
  @param {SC.View} exampleView
29
29
  */
30
30
  poolForExampleView: function(exampleView) {
@@ -32,31 +32,31 @@ SC.CollectionFastPath = {
32
32
  if (!this[poolKey]) this[poolKey] = [];
33
33
  return this[poolKey];
34
34
  },
35
-
35
+
36
36
  /**
37
37
  Creates an item view from a given example view, configuring it with basic settings
38
38
  and the supplied attributes.
39
-
39
+
40
40
  @param {SC.View} exampleView
41
41
  @param {Hash} attrs
42
42
  */
43
43
  createItemViewFromExampleView: function(exampleView, attrs) {
44
44
  // create the example view
45
45
  var ret = this.createItemView(exampleView, null, attrs);
46
-
46
+
47
47
  // for our pooling, if it is poolable, mark the view as poolable and
48
48
  // give it a reference to its pool.
49
49
  if (ret.isPoolable) {
50
50
  ret.owningPool = this.poolForExampleView(exampleView);
51
51
  }
52
-
52
+
53
53
  // we will sometimes need to know what example view created the item view
54
54
  ret.createdFromExampleView = exampleView;
55
55
 
56
56
  // and now, return (duh)
57
57
  return ret;
58
58
  },
59
-
59
+
60
60
  /**
61
61
  @param {SC.View} itemView
62
62
  @param {Hash} attrs
@@ -78,7 +78,7 @@ SC.CollectionFastPath = {
78
78
  itemView.setIfChanged('page', this.page);
79
79
  itemView.endPropertyChanges();
80
80
  },
81
-
81
+
82
82
  /**
83
83
  Configures a pooled view, calling `.awakeFromPool` if it is defined.
84
84
 
@@ -88,15 +88,15 @@ SC.CollectionFastPath = {
88
88
  wakePooledView: function(itemView, attrs) {
89
89
  // configure
90
90
  this.configureItemView(itemView, attrs);
91
-
91
+
92
92
  // awake from the pool, etc.
93
93
  if (itemView.awakeFromPool) itemView.awakeFromPool(itemView.owningPool, this);
94
94
  },
95
-
95
+
96
96
  /**
97
97
  Gets an item view from an example view, from a pool if possible, and otherwise
98
98
  by generating it.
99
-
99
+
100
100
  @param {SC.View} exampleView
101
101
  @param {Hash} attrs
102
102
  */
@@ -104,7 +104,7 @@ SC.CollectionFastPath = {
104
104
  // we will try to get it from a pool. This will fill ret. If ret is not
105
105
  // filled, then we'll know to generate one.
106
106
  var ret;
107
-
107
+
108
108
  // if it is poolable, we just grab from the pool.
109
109
  if (exampleView.prototype.isPoolable) {
110
110
  var pool = this.poolForExampleView(exampleView);
@@ -113,18 +113,18 @@ SC.CollectionFastPath = {
113
113
  this.wakePooledView(ret, attrs);
114
114
  }
115
115
  }
116
-
116
+
117
117
  if (!ret) {
118
118
  ret = this.createItemViewFromExampleView(exampleView, attrs);
119
119
  }
120
-
120
+
121
121
  return ret;
122
122
  },
123
-
123
+
124
124
  /**
125
125
  Releases an item view. If the item view is pooled, it puts it into the pool;
126
126
  otherwise, this calls `.destroy()`.
127
-
127
+
128
128
  This is called for one of two purposes: to release a view that is no longer displaying,
129
129
  or to release an older cached version of a view that needed to be replaced because the
130
130
  example view changed.
@@ -137,30 +137,30 @@ SC.CollectionFastPath = {
137
137
  itemView.destroy();
138
138
  return;
139
139
  }
140
-
140
+
141
141
  // otherwise, we need to return to view
142
142
  var pool = itemView.owningPool;
143
143
  pool.push(itemView);
144
144
  if (itemView.hibernateInPool) itemView.hibernateInPool(pool, this);
145
145
  },
146
-
146
+
147
147
  /** @private
148
148
  Returns YES if the item at the index is a group.
149
149
  */
150
150
  contentIndexIsGroup: function(view, content, index) {
151
151
  var contentDelegate = this.get("contentDelegate");
152
-
152
+
153
153
  // setup our properties
154
154
  var groupIndexes = this.get('_contentGroupIndexes'), isGroupView = NO;
155
-
155
+
156
156
  // and do our checking
157
157
  isGroupView = groupIndexes && groupIndexes.contains(index);
158
158
  if (isGroupView) isGroupView = contentDelegate.contentIndexIsGroup(this, this.get("content"), index);
159
-
159
+
160
160
  // and return
161
161
  return isGroupView;
162
162
  },
163
-
163
+
164
164
  /** @private
165
165
  Determines the example view for a content index. There are two optional parameters that will
166
166
  speed things up: `contentObject` and `isGroupView`. If you don't supply them, they must be computed.
@@ -182,24 +182,24 @@ SC.CollectionFastPath = {
182
182
  if (key && item) ExampleView = item.get(key);
183
183
  if (!ExampleView) ExampleView = this.get('exampleView');
184
184
  }
185
-
185
+
186
186
  return ExampleView;
187
187
  },
188
-
188
+
189
189
  /** @private
190
190
  This may seem somewhat awkward, but it is for memory performance: this fills in a hash
191
191
  YOU provide with the properties for the given content index.
192
-
192
+
193
193
  Properties include both the attributes given to the view and some `CollectionView` tracking
194
194
  properties, most importantly the exampleView.
195
195
  */
196
196
  setAttributesForItem: function(item, index, attrs) {
197
- var del = this.get('contentDelegate'),
197
+ var del = this.get('contentDelegate'),
198
198
  isGroupView = this.contentIndexIsGroup(this, this.get('content'), index),
199
199
  ExampleView = this.exampleViewForItem(item, index),
200
200
  content = this.get("content");
201
-
202
- //
201
+
202
+ //
203
203
  // FIGURE OUT "NORMAL" ATTRIBUTES
204
204
  //
205
205
  attrs.createdFromExampleView = ExampleView;
@@ -218,11 +218,11 @@ SC.CollectionFastPath = {
218
218
  attrs.layout = this.layoutForContentIndex(index);
219
219
  if (!attrs.layout) attrs.layout = ExampleView.prototype.layout;
220
220
  },
221
-
221
+
222
222
  //
223
223
  // ITEM LOADING/DOM MANAGEMENT
224
224
  //
225
-
225
+
226
226
  /** @private
227
227
  Returns mapped item views for the supplied item.
228
228
  */
@@ -230,9 +230,9 @@ SC.CollectionFastPath = {
230
230
  if (!map) map = this._viewMap;
231
231
  return map[SC.guidFor(item)];
232
232
  },
233
-
233
+
234
234
  /** @private
235
- Returns the mapped view for an item at the specified index.
235
+ Returns the mapped view for an item at the specified index.
236
236
  */
237
237
  mappedViewForItem: function(item, idx, map) {
238
238
  if (!map) map = this._viewMap;
@@ -240,24 +240,24 @@ SC.CollectionFastPath = {
240
240
  if (!m) return undefined;
241
241
  return m[idx];
242
242
  },
243
-
243
+
244
244
  /** @private
245
245
  Maps a view to an item/index combination.
246
246
  */
247
247
  mapView: function(item, index, view, map) {
248
248
  // get the default view map if a map was not supplied
249
249
  if (!map) map = this._viewMap;
250
-
250
+
251
251
  // get the item map
252
252
  var g = SC.guidFor(item),
253
253
  imap = map[g];
254
254
  if (!imap) imap = map[g] = {_length: 0};
255
-
255
+
256
256
  // fill in the index
257
257
  imap[index] = view;
258
258
  imap._length++;
259
259
  },
260
-
260
+
261
261
  /** @private
262
262
  Unmaps a view from an item/index combination.
263
263
  */
@@ -265,20 +265,20 @@ SC.CollectionFastPath = {
265
265
  if (!map) map = this._viewMap;
266
266
  var g = SC.guidFor(item),
267
267
  imap = map[g];
268
-
268
+
269
269
  // return if there is nothing to do
270
270
  if (!imap) return;
271
-
271
+
272
272
  // remove
273
273
  if (imap[index]) {
274
274
  var v = imap[index];
275
275
  delete imap[index];
276
-
276
+
277
277
  imap._length--;
278
278
  if (imap._length <= 0) delete map[g];
279
279
  }
280
280
  },
281
-
281
+
282
282
  /**
283
283
  Returns the item view for the given content index.
284
284
  NOTE: THIS WILL ADD THE VIEW TO DOM TEMPORARILY (it will be cleaned if
@@ -289,53 +289,52 @@ SC.CollectionFastPath = {
289
289
  itemViewForContentIndex: function(index) {
290
290
  var content = this.get("content");
291
291
  if (!content) return;
292
-
292
+
293
293
  var item = content.objectAt(index);
294
- if (!item) return null;
295
-
294
+
296
295
  var exampleView = this.exampleViewForItem(item, index),
297
296
  view = this._indexMap[index];
298
-
297
+
299
298
  if (view && view.createdFromExampleView !== exampleView) {
300
299
  this.removeItemView(view);
301
300
  this.unmapView(item, index);
302
301
  view = null;
303
302
  }
304
-
303
+
305
304
  if (!view) {
306
305
  view = this.addItemView(exampleView, item, index);
307
306
  }
308
-
307
+
309
308
  return view;
310
309
  },
311
-
310
+
312
311
  /** @private
313
312
  Returns the nearest item view index to the supplied index mapped to the item.
314
313
  */
315
314
  nearestMappedViewIndexForItem: function(item, index, map) {
316
315
  var m = this.mappedViewsForItem(item, map);
317
316
  if (!m) return null;
318
-
317
+
319
318
  // keep track of nearest and the nearest distance
320
319
  var nearest = null, ndist = -1, dist = 0;
321
-
320
+
322
321
  // loop through
323
322
  for (var idx in m) {
324
323
  idx = parseInt(idx, 10);
325
324
  if (isNaN(idx)) continue;
326
325
  // get distance
327
326
  dist = Math.abs(index - idx);
328
-
327
+
329
328
  // compare to nearest distance
330
329
  if (ndist < 0 || dist < ndist) {
331
330
  ndist = dist;
332
331
  nearest = idx;
333
332
  }
334
333
  }
335
-
334
+
336
335
  return nearest;
337
336
  },
338
-
337
+
339
338
  /** @private
340
339
  Remaps the now showing views to their new indexes (if they have moved).
341
340
  */
@@ -353,11 +352,11 @@ SC.CollectionFastPath = {
353
352
  // first, find items which we can (that already exist, etc.)
354
353
  nowShowing.forEach(function(idx) {
355
354
  item = content.objectAt(idx);
356
-
355
+
357
356
  // determine if we have view(s) in the old map for the item
358
357
  var possibleExistingViews = this.mappedViewsForItem(item, oldMap);
359
358
  if (possibleExistingViews) {
360
-
359
+
361
360
  // if it is the same index, we just take it. End of story.
362
361
  if (possibleExistingViews[idx]) {
363
362
  var v = possibleExistingViews[idx];
@@ -373,14 +372,14 @@ SC.CollectionFastPath = {
373
372
  itemsToAdd.push(idx);
374
373
  }
375
374
  }, this);
376
-
375
+
377
376
  // now there are also some items which _could_ exist (but might not!)
378
377
  for (var idx = 0, len = mayExist.length; idx < len; idx++) {
379
378
  var newIdx = mayExist[idx];
380
379
  item = content.objectAt(newIdx);
381
380
  var nearestOldIndex = this.nearestMappedViewIndexForItem(item, newIdx, oldMap),
382
381
  nearestView;
383
-
382
+
384
383
  if (!SC.none(nearestOldIndex)) {
385
384
  nearestView = this.mappedViewForItem(item, nearestOldIndex, oldMap);
386
385
  var newExampleView = this.exampleViewForItem(item, newIdx);
@@ -397,10 +396,10 @@ SC.CollectionFastPath = {
397
396
  itemsToAdd.push(newIdx);
398
397
  }
399
398
  }
400
-
399
+
401
400
  return oldMap;
402
401
  },
403
-
402
+
404
403
  /**
405
404
  Reloads.
406
405
 
@@ -409,57 +408,57 @@ SC.CollectionFastPath = {
409
408
  */
410
409
  reloadIfNeeded: function(nowShowing, scrollOnly) {
411
410
  var content = this.get("content"), invalid;
412
-
411
+
413
412
  // we use the nowShowing to determine what should and should not be showing.
414
413
  if (!nowShowing || !nowShowing.isIndexSet) nowShowing = this.get('nowShowing');
415
-
414
+
416
415
  // we only update if this is a non-scrolling update.
417
416
  // don't worry: we'll actually update after the fact, and the invalid indexes should
418
417
  // be queued up nicely.
419
418
  if (!scrollOnly) {
420
419
  invalid = this._invalidIndexes;
421
420
  if (!invalid || !this.get('isVisibleInWindow')) return this;
422
- this._invalidIndexes = NO;
423
-
421
+ this._invalidIndexes = NO;
422
+
424
423
  // tell others we will be reloading
425
424
  if (invalid.isIndexSet && invalid.contains(nowShowing)) invalid = YES ;
426
425
  if (this.willReload) this.willReload(invalid === YES ? null : invalid);
427
426
  }
428
-
427
+
429
428
  // get arrays of items to add/remove
430
429
  var itemsToAdd = this._itemsToAdd || (this._itemsToAdd = []);
431
-
430
+
432
431
  // remap
433
432
  var oldMap = this.remapItemViews(nowShowing);
434
-
433
+
435
434
  // The oldMap has the items to remove, so supply it to processRemovals
436
435
  this.processRemovals(oldMap);
437
-
436
+
438
437
  // handle the invalid set (if it is present)
439
438
  if (invalid) {
440
439
  this.processUpdates(invalid === YES ? nowShowing : invalid);
441
440
  }
442
-
441
+
443
442
  // process items to add
444
443
  this.processAdds();
445
-
444
+
446
445
  // only clear the DOM pools if this is not during scrolling. Adding/removing is a
447
446
  // bad idea while scrolling :)
448
447
  if (!scrollOnly) this.clearDOMPools();
449
-
448
+
450
449
  // clear the lists
451
450
  itemsToAdd.length = 0;
452
-
451
+
453
452
  // and if this is a full reload, we need to adjust layout
454
453
  if (!scrollOnly) {
455
454
  var layout = this.computeLayout();
456
455
  if (layout) this.adjust(layout);
457
456
  if (this.didReload) this.didReload(invalid === YES ? null : invalid);
458
457
  }
459
-
458
+
460
459
  return this;
461
460
  },
462
-
461
+
463
462
  /**
464
463
  Loops through remove queue and removes.
465
464
 
@@ -472,17 +471,17 @@ SC.CollectionFastPath = {
472
471
  for (var itemIdx in imap) {
473
472
  itemIdx = parseInt(itemIdx, 10);
474
473
  if (isNaN(itemIdx)) continue;
475
-
474
+
476
475
  var view = imap[itemIdx];
477
-
476
+
478
477
  if (this._indexMap[itemIdx] === view) delete this._indexMap[itemIdx];
479
-
478
+
480
479
  view._isInCollection = NO;
481
480
  this.removeItemView(view);
482
481
  }
483
482
  }
484
483
  },
485
-
484
+
486
485
  /** @private
487
486
  Loops through update queue and... updates.
488
487
  */
@@ -497,23 +496,23 @@ SC.CollectionFastPath = {
497
496
  }
498
497
  }, this);
499
498
  },
500
-
499
+
501
500
  /** @private
502
501
  Loops through add queue and, well, adds.
503
502
  */
504
503
  processAdds: function() {
505
504
  var content = this.get("content");
506
-
505
+
507
506
  var add = this._itemsToAdd, idx, len = add.length, itemIdx, item;
508
507
  for (idx = 0; idx < len; idx++) {
509
508
  itemIdx = add[idx]; item = content.objectAt(itemIdx);
510
-
509
+
511
510
  // get example view and create item view
512
511
  var exampleView = this.exampleViewForItem(item, itemIdx);
513
512
  var view = this.addItemView(exampleView, item, itemIdx);
514
513
  }
515
514
  },
516
-
515
+
517
516
  /** @private
518
517
  Clear all DOM pools.
519
518
  */
@@ -523,34 +522,34 @@ SC.CollectionFastPath = {
523
522
  this.clearDOMPool(pools[p]);
524
523
  }
525
524
  },
526
-
525
+
527
526
  /**
528
527
  @type Number
529
528
  @default 10
530
529
  */
531
530
  domPoolSize: 10,
532
-
531
+
533
532
  /** @private
534
533
  Clears a specific DOM pool.
535
534
  */
536
535
  clearDOMPool: function(pool) {
537
536
  var idx, len = pool.length, item;
538
-
537
+
539
538
  // we skip one because there is a buffer area of one while scrolling
540
539
  for (idx = this.domPoolSize; idx < len; idx++) {
541
540
  item = pool[idx];
542
541
 
543
542
  // remove from DOM
544
543
  this.removeChild(item);
545
-
544
+
546
545
  // release the item
547
546
  this.releaseItemView(item);
548
547
  }
549
-
548
+
550
549
  // pool is cleared.
551
550
  pool.length = Math.min(pool.length, this.domPoolSize);
552
551
  },
553
-
552
+
554
553
  /** @private
555
554
  Returns the DOM pool for the given exampleView.
556
555
  */
@@ -560,7 +559,7 @@ SC.CollectionFastPath = {
560
559
  if (!pool) pool = pools[guid] = [];
561
560
  return pool;
562
561
  },
563
-
562
+
564
563
  /** @private
565
564
  Tries to find an item for the given example view in a dom pool.
566
565
  If one could not be found, returns `null`.
@@ -572,7 +571,7 @@ SC.CollectionFastPath = {
572
571
  if (view.wakeFromDOMPool) view.wakeFromDOMPool();
573
572
  return view;
574
573
  },
575
-
574
+
576
575
  /** @private
577
576
  Sends a view to a DOM pool.
578
577
  */
@@ -584,48 +583,48 @@ SC.CollectionFastPath = {
584
583
  view.set("layerId", SC.guidFor(view));
585
584
  if (view.sleepInDOMPool) view.sleepInDOMPool();
586
585
  },
587
-
586
+
588
587
  /** @private
589
588
  Adds an item view (grabbing the actual item from one of the pools if possible).
590
589
  */
591
590
  addItemView: function(exampleView, object, index) {
592
591
  var view, attrs = this._TMP_ATTRS || (this._TMP_ATTRS = {});
593
-
592
+
594
593
  // in any case, we need attributes
595
594
  this.setAttributesForItem(object, index, attrs);
596
-
595
+
597
596
  // try to get from DOM pool first
598
597
  if (view = this.itemFromDOMPool(exampleView)) {
599
598
  // set attributes
600
599
  this.configureItemView(view, attrs);
601
-
600
+
602
601
  // set that it is in the collection
603
602
  view._isInCollection = YES;
604
-
603
+
605
604
  // add to view map (if not used, it will be removed)
606
605
  this.mapView(object, index, view);
607
606
  this._indexMap[index] = view;
608
-
607
+
609
608
  // and that should have repositioned too
610
609
  return view;
611
610
  }
612
-
611
+
613
612
  // otherwise, just allocate a view
614
613
  view = this.allocateItemView(exampleView, attrs);
615
-
614
+
616
615
  // and then, add it
617
616
  this.appendChild(view);
618
-
617
+
619
618
  // set that it is in the collection.
620
619
  view._isInCollection = YES;
621
-
620
+
622
621
  // add to view map (if not used, it will be removed)
623
622
  this.mapView(object, index, view);
624
623
  this._indexMap[index] = view;
625
-
624
+
626
625
  return view;
627
626
  },
628
-
627
+
629
628
  /** @private
630
629
  Removes an item view.
631
630
  */
@@ -637,11 +636,11 @@ SC.CollectionFastPath = {
637
636
  }
638
637
  current._isInCollection = NO;
639
638
  },
640
-
639
+
641
640
  /**
642
641
  Updates the specified item view. If the view is not "layer cacheable" or the
643
642
  example view has changed, it will be redrawn.
644
-
643
+
645
644
  Otherwise, nothing will happen.
646
645
  */
647
646
  updateItemView: function(current, exampleView, object, index) {
@@ -650,7 +649,7 @@ SC.CollectionFastPath = {
650
649
  this.unmapView(current, index);
651
650
  delete this._indexMap[index];
652
651
  this.removeItemView(current, object, index);
653
-
652
+
654
653
  // add new and map
655
654
  var newView = this.addItemView(exampleView, object, index);
656
655
  } else {
@@ -660,8 +659,8 @@ SC.CollectionFastPath = {
660
659
  this.configureItemView(current, attrs);
661
660
  }
662
661
  },
663
-
664
-
662
+
663
+
665
664
  /** @private
666
665
  Tells `ScrollView` that this should receive live updates during touch scrolling.
667
666
  We are so fast, aren't we?
@@ -673,39 +672,39 @@ SC.CollectionFastPath = {
673
672
 
674
673
  /** @private */
675
674
  _tolerance: 100,
676
-
675
+
677
676
  /** @private */
678
677
  touchScrollDidChange: function(left, top) {
679
678
  // prevent getting too many in close succession.
680
679
  if (Date.now() - this._lastTouchScrollTime < 25) return;
681
-
680
+
682
681
  var clippingFrame = this.get('clippingFrame');
683
-
682
+
684
683
  var cf = this._inScrollClippingFrame || (this._inScrollClippingFrame = {x: 0, y: 0, width: 0, height: 0});
685
684
  cf.x = clippingFrame.x; cf.y = clippingFrame.y; cf.width = clippingFrame.width; cf.height = clippingFrame.height;
686
-
685
+
687
686
  // update
688
687
  cf.x = left;
689
688
  cf.y = top;
690
-
689
+
691
690
  var r = this.contentIndexesInRect(cf);
692
691
  if (!r) return; // no rect, do nothing.
693
-
694
- var len = this.get('length'),
692
+
693
+ var len = this.get('length'),
695
694
  max = r.get('max'), min = r.get('min');
696
695
 
697
696
  if (max > len || min < 0) {
698
697
  r = r.copy();
699
698
  r.remove(len, max-len).remove(min, 0-min).freeze();
700
699
  }
701
-
700
+
702
701
  if (this._lastNowShowing) {
703
702
  if (r.contains(this._lastNowShowing) && this._lastNowShowing.contains(r)) return;
704
703
  }
705
704
  this._lastNowShowing = r;
706
705
  this.reloadIfNeeded(r, YES);
707
-
706
+
708
707
  this._lastTouchScrollTime = Date.now();
709
708
  }
710
-
709
+
711
710
  };