Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 25 matching lines...) Expand all Loading... | |
| 36 | 36 |
| 37 /** | 37 /** |
| 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._element.appendChild(this._selectElement); | 47 this._element.appendChild(this._selectElement); |
| 47 this._layout(); | 48 this._layout(); |
| 48 this._selectElement.focus(); | |
| 49 this._selectElement.addEventListener("mouseup", this._handleMouseUp.bind(thi s), false); | 49 this._selectElement.addEventListener("mouseup", this._handleMouseUp.bind(thi s), false); |
| 50 this._selectElement.addEventListener("touchstart", this._handleTouchStart.bi nd(this), false); | 50 this._selectElement.addEventListener("touchstart", this._handleTouchStart.bi nd(this), false); |
| 51 this._selectElement.addEventListener("keydown", this._handleKeyDown.bind(thi s), false); | 51 this._selectElement.addEventListener("keydown", this._handleKeyDown.bind(thi s), false); |
| 52 this._selectElement.addEventListener("change", this._handleChange.bind(this) , false); | 52 this._selectElement.addEventListener("change", this._handleChange.bind(this) , false); |
| 53 window.addEventListener("message", this._handleWindowMessage.bind(this), fal se); | 53 window.addEventListener("message", this._handleWindowMessage.bind(this), fal se); |
| 54 window.addEventListener("mousemove", this._handleWindowMouseMove.bind(this), false); | 54 window.addEventListener("mousemove", this._handleWindowMouseMove.bind(this), false); |
| 55 window.addEventListener("touchmove", this._handleWindowTouchMove.bind(this), false); | 55 window.addEventListener("touchmove", this._handleWindowTouchMove.bind(this), false); |
| 56 window.addEventListener("touchend", this._handleWindowTouchEnd.bind(this), f alse); | 56 window.addEventListener("touchend", this._handleWindowTouchEnd.bind(this), f alse); |
| 57 this.lastMousePositionX = Infinity; | 57 this.lastMousePositionX = Infinity; |
| 58 this.lastMousePositionY = Infinity; | 58 this.lastMousePositionY = Infinity; |
| 59 this._selectionSetByMouseHover = false; | 59 this._selectionSetByMouseHover = false; |
| 60 | 60 |
| 61 this._trackingTouchId = null; | 61 this._trackingTouchId = null; |
| 62 | 62 |
| 63 this._handleWindowDidHide(); | 63 this._handleWindowDidHide(); |
| 64 this._selectElement.focus(); | |
| 65 this._selectElement.value = this._config.selectedIndex; | |
| 64 } | 66 } |
| 65 ListPicker.prototype = Object.create(Picker.prototype); | 67 ListPicker.prototype = Object.create(Picker.prototype); |
| 66 | 68 |
| 67 ListPicker.prototype._handleWindowDidHide = function() { | 69 ListPicker.prototype._handleWindowDidHide = function() { |
| 68 this._fixWindowSize(); | 70 this._fixWindowSize(); |
| 69 var selectedOption = this._selectElement.options[this._selectElement.selecte dIndex]; | 71 var selectedOption = this._selectElement.options[this._selectElement.selecte dIndex]; |
| 70 if (selectedOption) | 72 if (selectedOption) |
| 71 selectedOption.scrollIntoView(false); | 73 selectedOption.scrollIntoView(false); |
| 72 window.removeEventListener("didHide", this._handleWindowDidHideBound, false) ; | 74 window.removeEventListener("didHide", this._handleWindowDidHideBound, false) ; |
| 73 }; | 75 }; |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 169 // to the owner element. We can handle most cases with the change | 171 // to the owner element. We can handle most cases with the change |
| 170 // event. But we need to call setValue even when the selection hasn't | 172 // event. But we need to call setValue even when the selection hasn't |
| 171 // changed. So we call it here too. setValue will be called twice for | 173 // changed. So we call it here too. setValue will be called twice for |
| 172 // some key presses but it won't matter. | 174 // some key presses but it won't matter. |
| 173 window.pagePopupController.setValue(this._selectElement.value); | 175 window.pagePopupController.setValue(this._selectElement.value); |
| 174 } | 176 } |
| 175 }; | 177 }; |
| 176 | 178 |
| 177 ListPicker.prototype._fixWindowSize = function() { | 179 ListPicker.prototype._fixWindowSize = function() { |
| 178 this._selectElement.style.height = ""; | 180 this._selectElement.style.height = ""; |
| 179 this._selectElement.size = 20; | |
| 180 var maxHeight = this._selectElement.offsetHeight; | 181 var maxHeight = this._selectElement.offsetHeight; |
| 181 this._selectElement.style.height = "0"; | 182 // heightOutsideOfContent should be matched to border widths of the listbox |
| 182 var heightOutsideOfContent = this._selectElement.offsetHeight - this._select Element.clientHeight; | 183 // SELECT. See listPicker.css and html.css. |
| 184 var heightOutsideOfContent = 2; | |
| 183 var noScrollHeight = Math.round(this._calculateScrollHeight() + heightOutsid eOfContent); | 185 var noScrollHeight = Math.round(this._calculateScrollHeight() + heightOutsid eOfContent); |
| 184 var desiredWindowHeight = noScrollHeight; | 186 var desiredWindowHeight = noScrollHeight; |
| 185 var desiredWindowWidth = this._selectElement.offsetWidth; | 187 var desiredWindowWidth = this._selectElement.offsetWidth; |
| 186 var expectingScrollbar = false; | 188 var expectingScrollbar = false; |
| 187 if (desiredWindowHeight > maxHeight) { | 189 if (desiredWindowHeight > maxHeight) { |
| 188 desiredWindowHeight = maxHeight; | 190 desiredWindowHeight = maxHeight; |
| 189 // Setting overflow to auto does not increase width for the scrollbar | 191 // Setting overflow to auto does not increase width for the scrollbar |
| 190 // so we need to do it manually. | 192 // so we need to do it manually. |
| 191 desiredWindowWidth += getScrollbarWidth(); | 193 desiredWindowWidth += getScrollbarWidth(); |
| 192 expectingScrollbar = true; | 194 expectingScrollbar = true; |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 222 | 224 |
| 223 ListPicker.prototype._listItemCount = function() { | 225 ListPicker.prototype._listItemCount = function() { |
| 224 return this._selectElement.querySelectorAll("option,optgroup,hr").length; | 226 return this._selectElement.querySelectorAll("option,optgroup,hr").length; |
| 225 }; | 227 }; |
| 226 | 228 |
| 227 ListPicker.prototype._layout = function() { | 229 ListPicker.prototype._layout = function() { |
| 228 if (this._config.isRTL) | 230 if (this._config.isRTL) |
| 229 this._element.classList.add("rtl"); | 231 this._element.classList.add("rtl"); |
| 230 this._selectElement.style.backgroundColor = this._config.backgroundColor; | 232 this._selectElement.style.backgroundColor = this._config.backgroundColor; |
| 231 this._updateChildren(this._selectElement, this._config); | 233 this._updateChildren(this._selectElement, this._config); |
| 232 this._selectElement.value = this._config.selectedIndex; | |
| 233 }; | 234 }; |
| 234 | 235 |
| 235 ListPicker.prototype._update = function() { | 236 ListPicker.prototype._update = function() { |
| 236 var scrollPosition = this._selectElement.scrollTop; | 237 var scrollPosition = this._selectElement.scrollTop; |
| 237 var oldValue = this._selectElement.value; | 238 var oldValue = this._selectElement.value; |
| 238 this._layout(); | 239 this._layout(); |
| 240 this._selectElement.value = this._config.selectedIndex; | |
| 239 this._selectElement.scrollTop = scrollPosition; | 241 this._selectElement.scrollTop = scrollPosition; |
| 240 var optionUnderMouse = null; | 242 var optionUnderMouse = null; |
| 241 if (this._selectionSetByMouseHover) { | 243 if (this._selectionSetByMouseHover) { |
| 242 var elementUnderMouse = document.elementFromPoint(this.lastMousePosition X, this.lastMousePositionY); | 244 var elementUnderMouse = document.elementFromPoint(this.lastMousePosition X, this.lastMousePositionY); |
| 243 optionUnderMouse = elementUnderMouse && elementUnderMouse.closest("optio n"); | 245 optionUnderMouse = elementUnderMouse && elementUnderMouse.closest("optio n"); |
| 244 } | 246 } |
| 245 if (optionUnderMouse) | 247 if (optionUnderMouse) |
| 246 optionUnderMouse.selected = true; | 248 optionUnderMouse.selected = true; |
| 247 else | 249 else |
| 248 this._selectElement.value = oldValue; | 250 this._selectElement.value = oldValue; |
| 249 this._selectElement.scrollTop = scrollPosition; | 251 this._selectElement.scrollTop = scrollPosition; |
| 250 this.dispatchEvent("didUpdate"); | 252 this.dispatchEvent("didUpdate"); |
| 251 }; | 253 }; |
| 252 | 254 |
| 253 /** | 255 /** |
| 254 * @param {!Element} parent Select element or optgroup element. | 256 * @param {!Element} parent Select element or optgroup element. |
| 255 * @param {!Object} config | 257 * @param {!Object} config |
| 256 */ | 258 */ |
| 257 ListPicker.prototype._updateChildren = function(parent, config) { | 259 ListPicker.prototype._updateChildren = function(parent, config) { |
| 258 var outOfDateIndex = 0; | 260 var outOfDateIndex = 0; |
| 261 var fragment = null; | |
| 262 var inGroup = parent.tagName === "OPTGROUP"; | |
| 259 for (var i = 0; i < config.children.length; ++i) { | 263 for (var i = 0; i < config.children.length; ++i) { |
| 260 var childConfig = config.children[i]; | 264 var childConfig = config.children[i]; |
| 261 var item = this._findReusableItem(parent, childConfig, outOfDateIndex) | | this._createItemElement(childConfig); | 265 var item = this._findReusableItem(parent, childConfig, outOfDateIndex) | | this._createItemElement(childConfig); |
| 262 this._configureItem(item, childConfig, parent.tagName === "OPTGROUP"); | 266 this._configureItem(item, childConfig, inGroup); |
| 263 if (outOfDateIndex < parent.children.length) | 267 if (outOfDateIndex < parent.children.length) { |
| 264 parent.insertBefore(item, parent.children[outOfDateIndex]); | 268 parent.insertBefore(item, parent.children[outOfDateIndex]); |
| 265 else | 269 } else { |
| 266 parent.appendChild(item); | 270 if (!fragment) |
| 271 fragment = document.createDocumentFragment(); | |
| 272 fragment.appendChild(item); | |
| 273 } | |
| 267 outOfDateIndex++; | 274 outOfDateIndex++; |
| 268 } | 275 } |
| 276 if (fragment) { | |
| 277 parent.appendChild(fragment); | |
| 278 return; | |
|
keishi
2015/05/26 06:41:25
When you change from
<select><optgroup></optgroup>
| |
| 279 } | |
| 269 var unused = parent.children.length - outOfDateIndex; | 280 var unused = parent.children.length - outOfDateIndex; |
| 270 for (var i = 0; i < unused; i++) { | 281 for (var i = 0; i < unused; i++) { |
| 271 parent.removeChild(parent.lastElementChild); | 282 parent.removeChild(parent.lastElementChild); |
| 272 } | 283 } |
| 273 }; | 284 }; |
| 274 | 285 |
| 275 ListPicker.prototype._findReusableItem = function(parent, config, startIndex) { | 286 ListPicker.prototype._findReusableItem = function(parent, config, startIndex) { |
| 276 if (startIndex >= parent.children.length) | 287 if (startIndex >= parent.children.length) |
| 277 return null; | 288 return null; |
| 278 var tagName = "OPTION"; | 289 var tagName = "OPTION"; |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 294 if (config.type === "option") | 305 if (config.type === "option") |
| 295 element = createElement("option"); | 306 element = createElement("option"); |
| 296 else if (config.type === "optgroup") | 307 else if (config.type === "optgroup") |
| 297 element = createElement("optgroup"); | 308 element = createElement("optgroup"); |
| 298 else if (config.type === "separator") | 309 else if (config.type === "separator") |
| 299 element = createElement("hr"); | 310 element = createElement("hr"); |
| 300 return element; | 311 return element; |
| 301 }; | 312 }; |
| 302 | 313 |
| 303 ListPicker.prototype._applyItemStyle = function(element, styleConfig) { | 314 ListPicker.prototype._applyItemStyle = function(element, styleConfig) { |
| 304 element.style.color = styleConfig.color; | 315 if (!styleConfig) |
| 305 element.style.backgroundColor = styleConfig.backgroundColor; | 316 return; |
| 306 element.style.fontSize = styleConfig.fontSize + "px"; | 317 var style = element.style; |
| 307 element.style.fontWeight = styleConfig.fontWeight; | 318 style.visibility = styleConfig.visibility; |
| 308 element.style.fontFamily = styleConfig.fontFamily.join(","); | 319 style.display = styleConfig.display; |
| 309 element.style.fontStyle = styleConfig.fontStyle; | 320 style.direction = styleConfig.direction; |
| 310 element.style.fontVariant = styleConfig.fontVariant; | 321 style.unicodeBidi = styleConfig.unicodeBidi; |
| 311 element.style.visibility = styleConfig.visibility; | 322 if (!styleConfig.color) |
| 312 element.style.display = styleConfig.display; | 323 return; |
| 313 element.style.direction = styleConfig.direction; | 324 style.color = styleConfig.color; |
| 314 element.style.unicodeBidi = styleConfig.unicodeBidi; | 325 style.backgroundColor = styleConfig.backgroundColor; |
| 326 style.fontSize = styleConfig.fontSize + "px"; | |
| 327 style.fontWeight = styleConfig.fontWeight; | |
| 328 style.fontFamily = styleConfig.fontFamily.join(","); | |
| 329 style.fontStyle = styleConfig.fontStyle; | |
| 330 style.fontVariant = styleConfig.fontVariant; | |
| 315 }; | 331 }; |
| 316 | 332 |
| 317 ListPicker.prototype._configureItem = function(element, config, inGroup) { | 333 ListPicker.prototype._configureItem = function(element, config, inGroup) { |
| 318 if (config.type === "option") { | 334 if (config.type === "option") { |
| 319 element.label = config.label; | 335 element.label = config.label; |
| 320 element.value = config.value; | 336 element.value = config.value; |
| 321 element.title = config.title; | 337 element.title = config.title; |
| 322 element.disabled = config.disabled; | 338 element.disabled = config.disabled; |
| 323 element.setAttribute("aria-label", config.ariaLabel); | 339 element.setAttribute("aria-label", config.ariaLabel); |
| 324 element.style.webkitPaddingStart = this._config.paddingStart + "px"; | 340 element.style.webkitPaddingStart = this._config.paddingStart + "px"; |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 346 } | 362 } |
| 347 this._applyItemStyle(element, config.style); | 363 this._applyItemStyle(element, config.style); |
| 348 }; | 364 }; |
| 349 | 365 |
| 350 if (window.dialogArguments) { | 366 if (window.dialogArguments) { |
| 351 initialize(dialogArguments); | 367 initialize(dialogArguments); |
| 352 } else { | 368 } else { |
| 353 window.addEventListener("message", handleMessage, false); | 369 window.addEventListener("message", handleMessage, false); |
| 354 window.setTimeout(handleArgumentsTimeout, 1000); | 370 window.setTimeout(handleArgumentsTimeout, 1000); |
| 355 } | 371 } |
| OLD | NEW |