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 |