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

Side by Side Diff: Source/web/resources/listPicker.js

Issue 1204163002: New SELECT Popup: Delay to create internal OPTION elements if there are many items. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: lower CSS class Created 5 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 | Annotate | Revision Log
« no previous file with comments | « Source/web/resources/listPicker.css ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 "use strict"; 1 "use strict";
2 // Copyright (c) 2014 The Chromium Authors. All rights reserved. 2 // Copyright (c) 2014 The Chromium Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be 3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file. 4 // found in the LICENSE file.
5 5
6 var global = { 6 var global = {
7 argumentsReceived: false, 7 argumentsReceived: false,
8 params: null, 8 params: null,
9 picker: null 9 picker: null
10 }; 10 };
(...skipping 27 matching lines...) Expand all
38 * @constructor 38 * @constructor
39 * @param {!Element} element 39 * @param {!Element} element
40 * @param {!Object} config 40 * @param {!Object} config
41 */ 41 */
42 function ListPicker(element, config) { 42 function ListPicker(element, config) {
43 Picker.call(this, element, config); 43 Picker.call(this, element, config);
44 window.pagePopupController.selectFontsFromOwnerDocument(document); 44 window.pagePopupController.selectFontsFromOwnerDocument(document);
45 this._selectElement = createElement("select"); 45 this._selectElement = createElement("select");
46 this._selectElement.size = 20; 46 this._selectElement.size = 20;
47 this._element.appendChild(this._selectElement); 47 this._element.appendChild(this._selectElement);
48 this._delayedChildrenConfig = null;
49 this._delayedChildrenConfigIndex = 0;
48 this._layout(); 50 this._layout();
49 this._selectElement.addEventListener("mouseup", this._handleMouseUp.bind(thi s), false); 51 this._selectElement.addEventListener("mouseup", this._handleMouseUp.bind(thi s), false);
50 this._selectElement.addEventListener("touchstart", this._handleTouchStart.bi nd(this), false); 52 this._selectElement.addEventListener("touchstart", this._handleTouchStart.bi nd(this), false);
51 this._selectElement.addEventListener("keydown", this._handleKeyDown.bind(thi s), false); 53 this._selectElement.addEventListener("keydown", this._handleKeyDown.bind(thi s), false);
52 this._selectElement.addEventListener("change", this._handleChange.bind(this) , false); 54 this._selectElement.addEventListener("change", this._handleChange.bind(this) , false);
53 window.addEventListener("message", this._handleWindowMessage.bind(this), fal se); 55 window.addEventListener("message", this._handleWindowMessage.bind(this), fal se);
54 window.addEventListener("mousemove", this._handleWindowMouseMove.bind(this), false); 56 window.addEventListener("mousemove", this._handleWindowMouseMove.bind(this), false);
55 window.addEventListener("touchmove", this._handleWindowTouchMove.bind(this), false); 57 window.addEventListener("touchmove", this._handleWindowTouchMove.bind(this), false);
56 window.addEventListener("touchend", this._handleWindowTouchEnd.bind(this), f alse); 58 window.addEventListener("touchend", this._handleWindowTouchEnd.bind(this), f alse);
57 this.lastMousePositionX = Infinity; 59 this.lastMousePositionX = Infinity;
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
245 optionUnderMouse = elementUnderMouse && elementUnderMouse.closest("optio n"); 247 optionUnderMouse = elementUnderMouse && elementUnderMouse.closest("optio n");
246 } 248 }
247 if (optionUnderMouse) 249 if (optionUnderMouse)
248 optionUnderMouse.selected = true; 250 optionUnderMouse.selected = true;
249 else 251 else
250 this._selectElement.value = oldValue; 252 this._selectElement.value = oldValue;
251 this._selectElement.scrollTop = scrollPosition; 253 this._selectElement.scrollTop = scrollPosition;
252 this.dispatchEvent("didUpdate"); 254 this.dispatchEvent("didUpdate");
253 }; 255 };
254 256
257 ListPicker.DelayedLayoutThreshold = 1000;
258
255 /** 259 /**
256 * @param {!Element} parent Select element or optgroup element. 260 * @param {!Element} parent Select element or optgroup element.
257 * @param {!Object} config 261 * @param {!Object} config
258 */ 262 */
259 ListPicker.prototype._updateChildren = function(parent, config) { 263 ListPicker.prototype._updateChildren = function(parent, config) {
260 var outOfDateIndex = 0; 264 var outOfDateIndex = 0;
261 var fragment = null; 265 var fragment = null;
262 var inGroup = parent.tagName === "OPTGROUP"; 266 var inGroup = parent.tagName === "OPTGROUP";
263 for (var i = 0; i < config.children.length; ++i) { 267 var lastListIndex = -1;
268 var limit = Math.max(this._config.selectedIndex, ListPicker.DelayedLayoutThr eshold);
269 var i;
270 for (i = 0; i < config.children.length; ++i) {
271 if (!inGroup && lastListIndex >= limit)
272 break;
264 var childConfig = config.children[i]; 273 var childConfig = config.children[i];
265 var item = this._findReusableItem(parent, childConfig, outOfDateIndex) | | this._createItemElement(childConfig); 274 var item = this._findReusableItem(parent, childConfig, outOfDateIndex) | | this._createItemElement(childConfig);
266 this._configureItem(item, childConfig, inGroup); 275 this._configureItem(item, childConfig, inGroup);
276 lastListIndex = item.value ? Number(item.value) : -1;
267 if (outOfDateIndex < parent.children.length) { 277 if (outOfDateIndex < parent.children.length) {
268 parent.insertBefore(item, parent.children[outOfDateIndex]); 278 parent.insertBefore(item, parent.children[outOfDateIndex]);
269 } else { 279 } else {
270 if (!fragment) 280 if (!fragment)
271 fragment = document.createDocumentFragment(); 281 fragment = document.createDocumentFragment();
272 fragment.appendChild(item); 282 fragment.appendChild(item);
273 } 283 }
274 outOfDateIndex++; 284 outOfDateIndex++;
275 } 285 }
276 if (fragment) { 286 if (fragment) {
277 parent.appendChild(fragment); 287 parent.appendChild(fragment);
288 } else {
289 var unused = parent.children.length - outOfDateIndex;
290 for (var j = 0; j < unused; j++) {
291 parent.removeChild(parent.lastElementChild);
292 }
293 }
294 if (i < config.children.length) {
295 // We don't bind |config.children| and |i| to _updateChildrenLater
296 // because config.children can get invalid before _updateChildrenLater
297 // is called.
298 this._delayedChildrenConfig = config.children;
299 this._delayedChildrenConfigIndex = i;
300 requestAnimationFrame(this._updateChildrenLater.bind(this));
301 }
302 };
303
304 ListPicker.prototype._updateChildrenLater = function(timeStamp) {
305 if (!this._delayedChildrenConfig)
278 return; 306 return;
307 var startIndex = this._delayedChildrenConfigIndex;
308 for (; this._delayedChildrenConfigIndex < this._delayedChildrenConfig.length && this._delayedChildrenConfigIndex - startIndex < ListPicker.DelayedLayoutThre shold; ++this._delayedChildrenConfigIndex) {
309 var childConfig = this._delayedChildrenConfig[this._delayedChildrenConfi gIndex];
310 var item = this._createItemElement(childConfig);
311 this._configureItem(item, childConfig, false);
312 this._selectElement.appendChild(item);
279 } 313 }
280 var unused = parent.children.length - outOfDateIndex; 314 if (this._delayedChildrenConfigIndex < this._delayedChildrenConfig.length)
281 for (var i = 0; i < unused; i++) { 315 requestAnimationFrame(this._updateChildrenLater.bind(this));
282 parent.removeChild(parent.lastElementChild); 316 else
283 } 317 this._delayedChildrenConfig = null;
318 this._selectElement.classList.add("wrap");
284 }; 319 };
285 320
286 ListPicker.prototype._findReusableItem = function(parent, config, startIndex) { 321 ListPicker.prototype._findReusableItem = function(parent, config, startIndex) {
287 if (startIndex >= parent.children.length) 322 if (startIndex >= parent.children.length)
288 return null; 323 return null;
289 var tagName = "OPTION"; 324 var tagName = "OPTION";
290 if (config.type === "optgroup") 325 if (config.type === "optgroup")
291 tagName = "OPTGROUP"; 326 tagName = "OPTGROUP";
292 else if (config.type === "separator") 327 else if (config.type === "separator")
293 tagName = "HR"; 328 tagName = "HR";
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
369 } 404 }
370 this._applyItemStyle(element, config.style); 405 this._applyItemStyle(element, config.style);
371 }; 406 };
372 407
373 if (window.dialogArguments) { 408 if (window.dialogArguments) {
374 initialize(dialogArguments); 409 initialize(dialogArguments);
375 } else { 410 } else {
376 window.addEventListener("message", handleMessage, false); 411 window.addEventListener("message", handleMessage, false);
377 window.setTimeout(handleArgumentsTimeout, 1000); 412 window.setTimeout(handleArgumentsTimeout, 1000);
378 } 413 }
OLDNEW
« no previous file with comments | « Source/web/resources/listPicker.css ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698