Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(824)

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/ui/ListControl.js

Issue 2916743002: [DevTools] Introduce Common.List used as a backend for list controls (Closed)
Patch Set: Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 /** 5 /**
6 * @template T 6 * @template T
7 * @interface 7 * @interface
8 */ 8 */
9 UI.ListDelegate = function() {}; 9 UI.ListDelegate = function() {};
10 10
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
57 this.element = createElement('div'); 57 this.element = createElement('div');
58 this.element.style.overflowY = 'auto'; 58 this.element.style.overflowY = 'auto';
59 this._topElement = this.element.createChild('div'); 59 this._topElement = this.element.createChild('div');
60 this._bottomElement = this.element.createChild('div'); 60 this._bottomElement = this.element.createChild('div');
61 this._firstIndex = 0; 61 this._firstIndex = 0;
62 this._lastIndex = 0; 62 this._lastIndex = 0;
63 this._renderedHeight = 0; 63 this._renderedHeight = 0;
64 this._topHeight = 0; 64 this._topHeight = 0;
65 this._bottomHeight = 0; 65 this._bottomHeight = 0;
66 66
67 /** @type {!Array<T>} */ 67 /** @type {!Common.List<T>} */
68 this._items = []; 68 this._source = new Common.List();
einbinder 2017/05/31 23:23:08 Shouldn't this be passed in by the client?
dgozman 2017/06/01 01:03:02 Well, it's convenient for most of the clients to n
69 this._source.addEventListener(Common.List.Events.ItemsReplaced, this._replac edItemsInRange, this);
70
69 /** @type {!Map<T, !Element>} */ 71 /** @type {!Map<T, !Element>} */
70 this._itemToElement = new Map(); 72 this._itemToElement = new Map();
71 this._selectedIndex = -1; 73 this._selectedIndex = -1;
74 /** @type {?T} */
75 this._selectedItem = null;
72 76
73 this.element.tabIndex = -1; 77 this.element.tabIndex = -1;
74 this.element.addEventListener('click', this._onClick.bind(this), false); 78 this.element.addEventListener('click', this._onClick.bind(this), false);
75 this.element.addEventListener('keydown', this._onKeyDown.bind(this), false); 79 this.element.addEventListener('keydown', this._onKeyDown.bind(this), false);
76 80
77 this._delegate = delegate; 81 this._delegate = delegate;
78 this._mode = mode || UI.ListMode.EqualHeightItems; 82 this._mode = mode || UI.ListMode.EqualHeightItems;
79 this._fixedHeight = 0; 83 this._fixedHeight = 0;
80 this._variableOffsets = new Int32Array(0); 84 this._variableOffsets = new Int32Array(0);
81 this._clearContents(); 85 this._clearContents();
82 86
83 if (this._mode !== UI.ListMode.NonViewport) { 87 if (this._mode !== UI.ListMode.NonViewport) {
84 this.element.addEventListener('scroll', () => { 88 this.element.addEventListener('scroll', () => {
85 this._updateViewport(this.element.scrollTop, this.element.offsetHeight); 89 this._updateViewport(this.element.scrollTop, this.element.offsetHeight);
86 }, false); 90 }, false);
87 } 91 }
88 } 92 }
89 93
90 /** 94 /**
91 * @return {number} 95 * @param {!Common.List<T>} source
92 */ 96 */
93 length() { 97 setSource(source) {
94 return this._items.length; 98 this._itemToElement.clear();
99 var length = this._source.length();
100 this._source.removeEventListener(Common.List.Events.ItemsReplaced, this._rep lacedItemsInRange, this);
101 this._source = source;
102 this._source.addEventListener(Common.List.Events.ItemsReplaced, this._replac edItemsInRange, this);
103 this.invalidateRange(0, length);
95 } 104 }
96 105
97 /** 106 /**
98 * @param {number} index 107 * @return {!Common.List<T>}
99 * @return {T}
100 */ 108 */
101 itemAtIndex(index) { 109 source() {
102 return this._items[index]; 110 return this._source;
103 } 111 }
104 112
105 /** 113 /**
106 * @param {T} item 114 * @param {!Common.Event} event
107 */ 115 */
108 pushItem(item) { 116 _replacedItemsInRange(event) {
109 this.replaceItemsInRange(this._items.length, this._items.length, [item]); 117 var data = /** @type {{index: number, removed: !Array<T>, inserted: number}} */ (event.data);
110 } 118 var from = data.index;
119 var to = from + data.removed.length;
111 120
112 /** 121 var oldSelectedItem = this._selectedItem;
113 * @return {T}
114 */
115 popItem() {
116 return this.removeItemAtIndex(this._items.length - 1);
117 }
118
119 /**
120 * @param {number} index
121 * @param {T} item
122 */
123 insertItemAtIndex(index, item) {
124 this.replaceItemsInRange(index, index, [item]);
125 }
126
127 /**
128 * @param {T} item
129 * @param {function(T, T):number} comparator
130 */
131 insertItemWithComparator(item, comparator) {
132 var index = this._items.lowerBound(item, comparator);
133 this.insertItemAtIndex(index, item);
134 }
135
136 /**
137 * @param {T} item
138 * @return {number}
139 */
140 indexOfItem(item) {
141 return this._items.indexOf(item);
142 }
143
144 /**
145 * @param {number} index
146 * @return {T}
147 */
148 removeItemAtIndex(index) {
149 var result = this._items[index];
150 this.replaceItemsInRange(index, index + 1, []);
151 return result;
152 }
153
154 /**
155 * @param {T} item
156 */
157 removeItem(item) {
158 var index = this._items.indexOf(item);
159 if (index === -1) {
160 console.error('Attempt to remove non-existing item');
161 return;
162 }
163 this.removeItemAtIndex(index);
164 }
165
166 /**
167 * @param {number} from
168 * @param {number} to
169 * @param {!Array<T>} items
170 */
171 replaceItemsInRange(from, to, items) {
172 var oldSelectedItem = this._selectedIndex !== -1 ? this._items[this._selecte dIndex] : null;
173 var oldSelectedElement = oldSelectedItem ? (this._itemToElement.get(oldSelec tedItem) || null) : null; 122 var oldSelectedElement = oldSelectedItem ? (this._itemToElement.get(oldSelec tedItem) || null) : null;
174 123 for (var i = 0; i < data.removed.length; i++)
175 for (var i = from; i < to; i++) 124 this._itemToElement.delete(data.removed[i]);
176 this._itemToElement.delete(this._items[i]); 125 this._invalidate(from, to, data.inserted);
177 if (items.length < 10000) {
178 this._items.splice.bind(this._items, from, to - from).apply(null, items);
179 } else {
180 // Splice may fail with too many arguments.
181 var before = this._items.slice(0, from);
182 var after = this._items.slice(to);
183 this._items = [].concat(before, items, after);
184 }
185 this._invalidate(from, to, items.length);
186 126
187 if (this._selectedIndex >= to) { 127 if (this._selectedIndex >= to) {
188 this._selectedIndex += items.length - (to - from); 128 this._selectedIndex += data.inserted - (to - from);
129 this._selectedItem = this._source.itemAtIndex(this._selectedIndex);
189 } else if (this._selectedIndex >= from) { 130 } else if (this._selectedIndex >= from) {
190 var index = this._findFirstSelectable(from + items.length, +1, false); 131 var index = this._findFirstSelectable(from + data.inserted, +1, false);
191 if (index === -1) 132 if (index === -1)
192 index = this._findFirstSelectable(from - 1, -1, false); 133 index = this._findFirstSelectable(from - 1, -1, false);
193 this._select(index, oldSelectedItem, oldSelectedElement); 134 this._select(index, oldSelectedItem, oldSelectedElement);
194 } 135 }
195 } 136 }
196 137
197 /** 138 /**
198 * @param {!Array<T>} items 139 * @param {T} item
199 */ 140 */
200 replaceAllItems(items) { 141 refreshItem(item) {
201 this.replaceItemsInRange(0, this._items.length, items); 142 var index = this.source().indexOfItem(item);
202 } 143 if (index === -1) {
203 144 console.error('Item to refresh is not present');
204 refreshAllItems() { 145 return;
205 this.refreshItemsInRange(0, this._items.length); 146 }
206 } 147 this._itemToElement.delete(item);
207 148 this.invalidateRange(index, index + 1);
208 /**
209 * @param {number} from
210 * @param {number} to
211 */
212 refreshItemsInRange(from, to) {
213 for (var i = from; i < to; i++)
214 this._itemToElement.delete(this._items[i]);
215 this.invalidateRange(from, to);
216 if (this._selectedIndex !== -1) 149 if (this._selectedIndex !== -1)
217 this._select(this._selectedIndex, null, null); 150 this._select(this._selectedIndex, null, null);
218 } 151 }
219 152
220 /** 153 /**
221 * @param {number} from 154 * @param {number} from
222 * @param {number} to 155 * @param {number} to
223 */ 156 */
224 invalidateRange(from, to) { 157 invalidateRange(from, to) {
225 this._invalidate(from, to, to - from); 158 this._invalidate(from, to, to - from);
226 } 159 }
227 160
228 viewportResized() { 161 viewportResized() {
229 if (this._mode === UI.ListMode.NonViewport) 162 if (this._mode === UI.ListMode.NonViewport)
230 return; 163 return;
231 // TODO(dgozman): try to keep visible scrollTop the same. 164 // TODO(dgozman): try to keep visible scrollTop the same.
232 var scrollTop = this.element.scrollTop; 165 var scrollTop = this.element.scrollTop;
233 var viewportHeight = this.element.offsetHeight; 166 var viewportHeight = this.element.offsetHeight;
234 this._clearViewport(); 167 this._clearViewport();
235 this._updateViewport(Number.constrain(scrollTop, 0, this._totalHeight() - vi ewportHeight), viewportHeight); 168 this._updateViewport(Number.constrain(scrollTop, 0, this._totalHeight() - vi ewportHeight), viewportHeight);
236 } 169 }
237 170
238 invalidateItemHeight() { 171 invalidateItemHeight() {
239 if (this._mode !== UI.ListMode.EqualHeightItems) { 172 if (this._mode !== UI.ListMode.EqualHeightItems) {
240 console.error('Only supported in equal height items mode'); 173 console.error('Only supported in equal height items mode');
241 return; 174 return;
242 } 175 }
243 this._fixedHeight = 0; 176 this._fixedHeight = 0;
244 if (this._items.length) { 177 if (this._source.length()) {
245 this._itemToElement.clear(); 178 this._itemToElement.clear();
246 this._invalidate(0, this._items.length, this._items.length); 179 this._invalidate(0, this._source.length(), this._source.length());
247 } 180 }
248 } 181 }
249 182
250 /** 183 /**
251 * @param {?Node} node 184 * @param {?Node} node
252 * @return {?T} 185 * @return {?T}
253 */ 186 */
254 itemForNode(node) { 187 itemForNode(node) {
255 while (node && node.parentNodeOrShadowHost() !== this.element) 188 while (node && node.parentNodeOrShadowHost() !== this.element)
256 node = node.parentNodeOrShadowHost(); 189 node = node.parentNodeOrShadowHost();
257 if (!node) 190 if (!node)
258 return null; 191 return null;
259 var element = /** @type {!Element} */ (node); 192 var element = /** @type {!Element} */ (node);
260 var index = this._items.findIndex(item => this._itemToElement.get(item) === element); 193 var index = this._source.findIndex(item => this._itemToElement.get(item) === element);
261 return index !== -1 ? this._items[index] : null; 194 return index !== -1 ? this._source.itemAtIndex(index) : null;
262 } 195 }
263 196
264 /** 197 /**
265 * @param {T} item 198 * @param {T} item
266 * @param {boolean=} center 199 * @param {boolean=} center
267 */ 200 */
268 scrollItemIntoView(item, center) { 201 scrollItemIntoView(item, center) {
269 var index = this._items.indexOf(item); 202 var index = this._source.indexOfItem(item);
270 if (index === -1) { 203 if (index === -1) {
271 console.error('Attempt to scroll onto missing item'); 204 console.error('Attempt to scroll onto missing item');
272 return; 205 return;
273 } 206 }
274 this._scrollIntoView(index, center); 207 this._scrollIntoView(index, center);
275 } 208 }
276 209
277 /** 210 /**
278 * @return {?T} 211 * @return {?T}
279 */ 212 */
280 selectedItem() { 213 selectedItem() {
281 return this._selectedIndex === -1 ? null : this._items[this._selectedIndex]; 214 return this._selectedItem;
282 } 215 }
283 216
284 /** 217 /**
285 * @return {number} 218 * @return {number}
286 */ 219 */
287 selectedIndex() { 220 selectedIndex() {
288 return this._selectedIndex; 221 return this._selectedIndex;
289 } 222 }
290 223
291 /** 224 /**
292 * @param {?T} item 225 * @param {?T} item
293 * @param {boolean=} center 226 * @param {boolean=} center
294 * @param {boolean=} dontScroll 227 * @param {boolean=} dontScroll
295 */ 228 */
296 selectItem(item, center, dontScroll) { 229 selectItem(item, center, dontScroll) {
297 var index = -1; 230 var index = -1;
298 if (item !== null) { 231 if (item !== null) {
299 index = this._items.indexOf(item); 232 index = this._source.indexOfItem(item);
300 if (index === -1) { 233 if (index === -1) {
301 console.error('Attempt to select missing item'); 234 console.error('Attempt to select missing item');
302 return; 235 return;
303 } 236 }
304 if (!this._delegate.isItemSelectable(item)) { 237 if (!this._delegate.isItemSelectable(item)) {
305 console.error('Attempt to select non-selectable item'); 238 console.error('Attempt to select non-selectable item');
306 return; 239 return;
307 } 240 }
308 } 241 }
309 if (this._selectedIndex !== index) 242 if (this._selectedIndex !== index)
310 this._select(index); 243 this._select(index);
311 if (index !== -1 && !dontScroll) 244 if (index !== -1 && !dontScroll)
312 this._scrollIntoView(index, center); 245 this._scrollIntoView(index, center);
313 } 246 }
314 247
315 /** 248 /**
316 * @param {boolean=} canWrap 249 * @param {boolean=} canWrap
317 * @param {boolean=} center 250 * @param {boolean=} center
318 * @return {boolean} 251 * @return {boolean}
319 */ 252 */
320 selectPreviousItem(canWrap, center) { 253 selectPreviousItem(canWrap, center) {
321 if (this._selectedIndex === -1 && !canWrap) 254 if (this._selectedIndex === -1 && !canWrap)
322 return false; 255 return false;
323 var index = this._selectedIndex === -1 ? this._items.length - 1 : this._sele ctedIndex - 1; 256 var index = this._selectedIndex === -1 ? this._source.length() - 1 : this._s electedIndex - 1;
324 index = this._findFirstSelectable(index, -1, !!canWrap); 257 index = this._findFirstSelectable(index, -1, !!canWrap);
325 if (index !== -1) { 258 if (index !== -1) {
326 this._scrollIntoView(index, center); 259 this._scrollIntoView(index, center);
327 this._select(index); 260 this._select(index);
328 return true; 261 return true;
329 } 262 }
330 return false; 263 return false;
331 } 264 }
332 265
333 /** 266 /**
(...skipping 14 matching lines...) Expand all
348 return false; 281 return false;
349 } 282 }
350 283
351 /** 284 /**
352 * @param {boolean=} center 285 * @param {boolean=} center
353 * @return {boolean} 286 * @return {boolean}
354 */ 287 */
355 selectItemPreviousPage(center) { 288 selectItemPreviousPage(center) {
356 if (this._mode === UI.ListMode.NonViewport) 289 if (this._mode === UI.ListMode.NonViewport)
357 return false; 290 return false;
358 var index = this._selectedIndex === -1 ? this._items.length - 1 : this._sele ctedIndex; 291 var index = this._selectedIndex === -1 ? this._source.length() - 1 : this._s electedIndex;
359 index = this._findPageSelectable(index, -1); 292 index = this._findPageSelectable(index, -1);
360 if (index !== -1) { 293 if (index !== -1) {
361 this._scrollIntoView(index, center); 294 this._scrollIntoView(index, center);
362 this._select(index); 295 this._select(index);
363 return true; 296 return true;
364 } 297 }
365 return false; 298 return false;
366 } 299 }
367 300
368 /** 301 /**
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
437 break; 370 break;
438 } 371 }
439 if (selected) 372 if (selected)
440 event.consume(); 373 event.consume();
441 } 374 }
442 375
443 /** 376 /**
444 * @return {number} 377 * @return {number}
445 */ 378 */
446 _totalHeight() { 379 _totalHeight() {
447 return this._offsetAtIndex(this._items.length); 380 return this._offsetAtIndex(this._source.length());
448 } 381 }
449 382
450 /** 383 /**
451 * @param {number} offset 384 * @param {number} offset
452 * @return {number} 385 * @return {number}
453 */ 386 */
454 _indexAtOffset(offset) { 387 _indexAtOffset(offset) {
455 if (this._mode === UI.ListMode.NonViewport) 388 if (this._mode === UI.ListMode.NonViewport)
456 throw 'There should be no offset conversions in non-viewport mode'; 389 throw 'There should be no offset conversions in non-viewport mode';
457 if (!this._items.length || offset < 0) 390 if (!this._source.length() || offset < 0)
458 return 0; 391 return 0;
459 if (this._mode === UI.ListMode.VariousHeightItems) { 392 if (this._mode === UI.ListMode.VariousHeightItems) {
460 return Math.min( 393 return Math.min(
461 this._items.length - 1, this._variableOffsets.lowerBound(offset, undef ined, 0, this._items.length)); 394 this._source.length() - 1, this._variableOffsets.lowerBound(offset, un defined, 0, this._source.length()));
462 } 395 }
463 if (!this._fixedHeight) 396 if (!this._fixedHeight)
464 this._measureHeight(); 397 this._measureHeight();
465 return Math.min(this._items.length - 1, Math.floor(offset / this._fixedHeigh t)); 398 return Math.min(this._source.length() - 1, Math.floor(offset / this._fixedHe ight));
466 } 399 }
467 400
468 /** 401 /**
469 * @param {number} index 402 * @param {number} index
470 * @return {!Element} 403 * @return {!Element}
471 */ 404 */
472 _elementAtIndex(index) { 405 _elementAtIndex(index) {
473 var item = this._items[index]; 406 var item = this._source.itemAtIndex(index);
474 var element = this._itemToElement.get(item); 407 var element = this._itemToElement.get(item);
475 if (!element) { 408 if (!element) {
476 element = this._delegate.createElementForItem(item); 409 element = this._delegate.createElementForItem(item);
477 this._itemToElement.set(item, element); 410 this._itemToElement.set(item, element);
478 } 411 }
479 return element; 412 return element;
480 } 413 }
481 414
482 /** 415 /**
483 * @param {number} index 416 * @param {number} index
484 * @return {number} 417 * @return {number}
485 */ 418 */
486 _offsetAtIndex(index) { 419 _offsetAtIndex(index) {
487 if (this._mode === UI.ListMode.NonViewport) 420 if (this._mode === UI.ListMode.NonViewport)
488 throw 'There should be no offset conversions in non-viewport mode'; 421 throw 'There should be no offset conversions in non-viewport mode';
489 if (!this._items.length) 422 if (!this._source.length())
490 return 0; 423 return 0;
491 if (this._mode === UI.ListMode.VariousHeightItems) 424 if (this._mode === UI.ListMode.VariousHeightItems)
492 return this._variableOffsets[index]; 425 return this._variableOffsets[index];
493 if (!this._fixedHeight) 426 if (!this._fixedHeight)
494 this._measureHeight(); 427 this._measureHeight();
495 return index * this._fixedHeight; 428 return index * this._fixedHeight;
496 } 429 }
497 430
498 _measureHeight() { 431 _measureHeight() {
499 this._fixedHeight = this._delegate.heightForItem(this._items[0]); 432 this._fixedHeight = this._delegate.heightForItem(this._source.itemAtIndex(0) );
500 if (!this._fixedHeight) 433 if (!this._fixedHeight)
501 this._fixedHeight = UI.measurePreferredSize(this._elementAtIndex(0), this. element).height; 434 this._fixedHeight = UI.measurePreferredSize(this._elementAtIndex(0), this. element).height;
502 } 435 }
503 436
504 /** 437 /**
505 * @param {number} index 438 * @param {number} index
506 * @param {?T=} oldItem 439 * @param {?T=} oldItem
507 * @param {?Element=} oldElement 440 * @param {?Element=} oldElement
508 */ 441 */
509 _select(index, oldItem, oldElement) { 442 _select(index, oldItem, oldElement) {
510 if (oldItem === undefined) 443 if (oldItem === undefined)
511 oldItem = this._selectedIndex !== -1 ? this._items[this._selectedIndex] : null; 444 oldItem = this._selectedItem;
512 if (oldElement === undefined) 445 if (oldElement === undefined)
513 oldElement = this._itemToElement.get(oldItem) || null; 446 oldElement = this._itemToElement.get(oldItem) || null;
514 this._selectedIndex = index; 447 this._selectedIndex = index;
515 var newItem = this._selectedIndex !== -1 ? this._items[this._selectedIndex] : null; 448 this._selectedItem = index === -1 ? null : this._source.itemAtIndex(index);
449 var newItem = this._selectedItem;
516 var newElement = this._selectedIndex !== -1 ? this._elementAtIndex(index) : null; 450 var newElement = this._selectedIndex !== -1 ? this._elementAtIndex(index) : null;
517 this._delegate.selectedItemChanged(oldItem, newItem, /** @type {?Element} */ (oldElement), newElement); 451 this._delegate.selectedItemChanged(oldItem, newItem, /** @type {?Element} */ (oldElement), newElement);
518 } 452 }
519 453
520 /** 454 /**
521 * @param {number} index 455 * @param {number} index
522 * @param {number} direction 456 * @param {number} direction
523 * @param {boolean} canWrap 457 * @param {boolean} canWrap
524 * @return {number} 458 * @return {number}
525 */ 459 */
526 _findFirstSelectable(index, direction, canWrap) { 460 _findFirstSelectable(index, direction, canWrap) {
527 var length = this._items.length; 461 var length = this._source.length();
528 if (!length) 462 if (!length)
529 return -1; 463 return -1;
530 for (var step = 0; step <= length; step++) { 464 for (var step = 0; step <= length; step++) {
531 if (index < 0 || index >= length) { 465 if (index < 0 || index >= length) {
532 if (!canWrap) 466 if (!canWrap)
533 return -1; 467 return -1;
534 index = (index + length) % length; 468 index = (index + length) % length;
535 } 469 }
536 if (this._delegate.isItemSelectable(this._items[index])) 470 if (this._delegate.isItemSelectable(this._source.itemAtIndex(index)))
537 return index; 471 return index;
538 index += direction; 472 index += direction;
539 } 473 }
540 return -1; 474 return -1;
541 } 475 }
542 476
543 /** 477 /**
544 * @param {number} index 478 * @param {number} index
545 * @param {number} direction 479 * @param {number} direction
546 * @return {number} 480 * @return {number}
547 */ 481 */
548 _findPageSelectable(index, direction) { 482 _findPageSelectable(index, direction) {
549 var lastSelectable = -1; 483 var lastSelectable = -1;
550 var startOffset = this._offsetAtIndex(index); 484 var startOffset = this._offsetAtIndex(index);
551 // Compensate for zoom rounding errors with -1. 485 // Compensate for zoom rounding errors with -1.
552 var viewportHeight = this.element.offsetHeight - 1; 486 var viewportHeight = this.element.offsetHeight - 1;
553 while (index >= 0 && index < this._items.length) { 487 while (index >= 0 && index < this._source.length()) {
554 if (this._delegate.isItemSelectable(this._items[index])) { 488 if (this._delegate.isItemSelectable(this._source.itemAtIndex(index))) {
555 if (Math.abs(this._offsetAtIndex(index) - startOffset) >= viewportHeight ) 489 if (Math.abs(this._offsetAtIndex(index) - startOffset) >= viewportHeight )
556 return index; 490 return index;
557 lastSelectable = index; 491 lastSelectable = index;
558 } 492 }
559 index += direction; 493 index += direction;
560 } 494 }
561 return lastSelectable; 495 return lastSelectable;
562 } 496 }
563 497
564 /** 498 /**
(...skipping 17 matching lines...) Expand all
582 * @param {number} to 516 * @param {number} to
583 * @param {number} inserted 517 * @param {number} inserted
584 */ 518 */
585 _invalidate(from, to, inserted) { 519 _invalidate(from, to, inserted) {
586 if (this._mode === UI.ListMode.NonViewport) { 520 if (this._mode === UI.ListMode.NonViewport) {
587 this._invalidateNonViewportMode(from, to - from, inserted); 521 this._invalidateNonViewportMode(from, to - from, inserted);
588 return; 522 return;
589 } 523 }
590 524
591 if (this._mode === UI.ListMode.VariousHeightItems) { 525 if (this._mode === UI.ListMode.VariousHeightItems) {
592 this._reallocateVariableOffsets(this._items.length + 1, from + 1); 526 this._reallocateVariableOffsets(this._source.length() + 1, from + 1);
593 for (var i = from + 1; i <= this._items.length; i++) 527 for (var i = from + 1; i <= this._source.length(); i++) {
594 this._variableOffsets[i] = this._variableOffsets[i - 1] + this._delegate .heightForItem(this._items[i - 1]); 528 this._variableOffsets[i] =
529 this._variableOffsets[i - 1] + this._delegate.heightForItem(this._so urce.itemAtIndex(i - 1));
530 }
595 } 531 }
596 532
597 var viewportHeight = this.element.offsetHeight; 533 var viewportHeight = this.element.offsetHeight;
598 var totalHeight = this._totalHeight(); 534 var totalHeight = this._totalHeight();
599 var scrollTop = this.element.scrollTop; 535 var scrollTop = this.element.scrollTop;
600 536
601 if (this._renderedHeight < viewportHeight || totalHeight < viewportHeight) { 537 if (this._renderedHeight < viewportHeight || totalHeight < viewportHeight) {
602 this._clearViewport(); 538 this._clearViewport();
603 this._updateViewport(Number.constrain(scrollTop, 0, totalHeight - viewport Height), viewportHeight); 539 this._updateViewport(Number.constrain(scrollTop, 0, totalHeight - viewport Height), viewportHeight);
604 return; 540 return;
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
716 this._firstIndex = firstIndex; 652 this._firstIndex = firstIndex;
717 this._lastIndex = lastIndex; 653 this._lastIndex = lastIndex;
718 this._topHeight = this._offsetAtIndex(firstIndex); 654 this._topHeight = this._offsetAtIndex(firstIndex);
719 this._topElement.style.height = this._topHeight + 'px'; 655 this._topElement.style.height = this._topHeight + 'px';
720 this._bottomHeight = totalHeight - this._offsetAtIndex(lastIndex); 656 this._bottomHeight = totalHeight - this._offsetAtIndex(lastIndex);
721 this._bottomElement.style.height = this._bottomHeight + 'px'; 657 this._bottomElement.style.height = this._bottomHeight + 'px';
722 this._renderedHeight = totalHeight; 658 this._renderedHeight = totalHeight;
723 this.element.scrollTop = scrollTop; 659 this.element.scrollTop = scrollTop;
724 } 660 }
725 }; 661 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698