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

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

Issue 736883002: Implement <select> Popup Menu using PagePopup (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years 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
OLDNEW
(Empty)
1 "use strict";
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
4 // found in the LICENSE file.
5
6 var global = {
7 argumentsReceived: false,
8 params: null,
9 picker: null
10 };
11
12 /**
13 * @param {Event} event
14 */
15 function handleMessage(event) {
16 window.removeEventListener("message", handleMessage, false);
17 initialize(JSON.parse(event.data));
18 global.argumentsReceived = true;
19 }
20
21 /**
22 * @param {!Object} args
23 */
24 function initialize(args) {
25 global.params = args;
26 var main = $("main");
27 main.innerHTML = "";
28 global.picker = new ListPicker(main, args);
29 }
30
31 function handleArgumentsTimeout() {
32 if (global.argumentsReceived)
33 return;
34 var args = {
35 };
36 initialize(args);
tkent 2014/12/16 05:42:39 initialize({});
keishi 2014/12/16 12:21:03 Done.
37 }
38
39 /**
40 * @constructor
41 * @param {!Element} element
42 * @param {!Object} config
43 */
44 function ListPicker(element, config) {
45 Picker.call(this, element, config);
46 this._selectElement = createElement("select");
47 this._element.appendChild(this._selectElement);
48 this._layout();
49 this._selectElement.focus();
50 this._selectElement.addEventListener("mouseover", this._handleMouseOver.bind (this), false);
51 this._selectElement.addEventListener("mouseup", this._handleMouseUp.bind(thi s), false);
52 this._selectElement.addEventListener("keydown", this._handleKeyDown.bind(thi s), false);
53 this._selectElement.addEventListener("input", this._handleInput.bind(this), false);
54 window.addEventListener("message", this._handleWindowMessage.bind(this), fal se);
55 window.addEventListener("mousemove", this._handleWindowMouseMove.bind(this), false);
56 window.addEventListener("mousemove", this._handleWindowMouseMove.bind(this), false);
57 this.lastMousePositionX = Infinity;
58 this.lastMousePositionY = Infinity;
59
60 // Not sure why but we need to delay this call so that offsetHeight is
61 // accurate. We wait for the window to resize to work around an issue
62 // of immediate resize requests getting mixed up.
63 this._handleWindowDidHideBound = this._handleWindowDidHide.bind(this);
64 window.addEventListener("didHide", this._handleWindowDidHideBound, false);
65 hideWindow();
66 }
67 ListPicker.prototype = Object.create(Picker.prototype);
68
69 ListPicker.prototype._handleWindowDidHide = function() {
70 this._fixWindowSize();
71 var selectedOption = this._selectElement.options[this._selectElement.selecte dIndex];
72 selectedOption.scrollIntoView(false);
73 window.removeEventListener("didHide", this._handleWindowDidHideBound, false) ;
74 };
75
76 ListPicker.prototype._handleWindowMessage = function(event) {
77 eval(event.data);
78 if (window.updateData.type === "update")
79 this._update(window.updateData);
80 delete window.updateData;
81 };
82
83 ListPicker.prototype._handleWindowMouseMove = function (event) {
84 this.lastMousePositionX = event.clientX;
85 this.lastMousePositionY = event.clientY;
86 };
87
88 ListPicker.prototype._handleMouseOver = function(event) {
89 if (event.toElement.tagName !== "OPTION")
90 return;
91 var savedScrollTop = this._selectElement.scrollTop;
92 event.toElement.selected = true;
93 this._selectElement.scrollTop = savedScrollTop;
94 };
95
96 ListPicker.prototype._handleMouseUp = function(event) {
97 if (event.target.tagName !== "OPTION")
98 return;
99 window.pagePopupController.setValueAndClosePopup(0, this._selectElement.valu e);
100 };
101
102 ListPicker.prototype._handleInput = function(event) {
103 window.pagePopupController.setValue(this._selectElement.value);
104 };
105
106 ListPicker.prototype._handleKeyDown = function(event) {
107 var key = event.keyIdentifier;
108 if (key === "U+001B") { // ESC
109 window.pagePopupController.closePopup();
110 event.preventDefault();
111 } else if (key === "Enter") {
112 window.pagePopupController.setValueAndClosePopup(0, this._selectElement. value);
113 event.preventDefault();
114 } else if (event.altKey && (key === "Down" || key === "Up")) {
115 // FIXME: We need to add a delay here because, if we do it immediately
tkent 2014/12/16 05:42:39 Is it possible to fix this FIXME? If not, let's r
keishi 2014/12/16 12:21:03 No. Removed.
116 // the key press event will be handled by HTMLSelectElement and this
117 // popup will be reopened.
118 setTimeout(function () {
119 window.pagePopupController.closePopup();
120 }, 0);
121 event.preventDefault();
122 }
123 };
124
125 ListPicker.prototype._fixWindowSize = function() {
126 this._selectElement.style.height = "";
127 this._selectElement.size = 20;
128 var maxHeight = this._selectElement.offsetHeight;
129 this._selectElement.style.height = "0";
130 var heightOutsideOfContent = this._selectElement.offsetHeight - this._select Element.clientHeight;
131 var desiredWindowHeight = this._selectElement.scrollHeight + heightOutsideOf Content;
132 this._selectElement.style.height = desiredWindowHeight + "px";
133 // FIXME: scrollHeight returns floored value so we needed this check.
tkent 2014/12/16 05:42:39 Ditto.
keishi 2014/12/16 12:21:03 Removed.
134 if (this._hasVerticalScrollbar())
135 desiredWindowHeight += 1;
136 if (desiredWindowHeight > maxHeight)
137 desiredWindowHeight = maxHeight;
138 var desiredWindowWidth = Math.max(this._config.anchorRectInScreen.width, thi s._selectElement.offsetWidth);
139 var windowRect = adjustWindowRect(desiredWindowWidth, desiredWindowHeight, t his._selectElement.offsetWidth, 0);
140 this._selectElement.style.width = windowRect.width + "px";
141 this._selectElement.style.height = windowRect.height + "px";
142 this._element.style.height = windowRect.height + "px";
143 setWindowRect(windowRect);
144 };
145
146 ListPicker.prototype._hasVerticalScrollbar = function() {
147 return this._selectElement.scrollWidth > this._selectElement.clientWidth;
148 };
149
150 ListPicker.prototype._listItemCount = function() {
151 return this._selectElement.querySelectorAll("option,optgroup,hr").length;
152 };
153
154 ListPicker.prototype._layout = function() {
155 for (var i = 0; i < this._config.children.length; ++i) {
156 this._selectElement.appendChild(this._createItemElement(this._config.chi ldren[i]));
157 }
158 this._selectElement.value = this._config.selectedIndex;
159 };
160
161 ListPicker.prototype._update = function(data) {
162 this._config.children = data.children;
163 var oldValue = this._selectElement.value;
164 while (this._selectElement.firstChild) {
165 this._selectElement.removeChild(this._selectElement.firstChild);
166 }
167 for (var i = 0; i < this._config.children.length; ++i) {
168 this._selectElement.appendChild(this._createItemElement(this._config.chi ldren[i]));
169 }
170 this._selectElement.value = this._config.selectedIndex;
171 var elementUnderMouse = document.elementFromPoint(this.lastMousePositionX, t his.lastMousePositionY);
172 var optionUnderMouse = elementUnderMouse && elementUnderMouse.closest("optio n");
173 if (optionUnderMouse)
174 optionUnderMouse.selected = true;
175 else
176 this._selectElement.value = oldValue;
177 this._fixWindowSize();
178 };
179
180 ListPicker.prototype._createItemElement = function(config) {
181 if (config.type === "option") {
182 var option = createElement("option");
183 option.appendChild(document.createTextNode(config.label));
184 option.value = config.value;
185 option.title = config.title;
186 option.disabled = config.disabled;
187 option.setAttribute("aria-label", config.ariaLabel);
188 this._applyItemStyle(option, config.style);
189 this._selectElement.appendChild(option);
190 return option;
191 } else if (config.type === "optgroup") {
192 var optgroup = createElement("optgroup");
193 optgroup.label = config.label;
194 optgroup.title = config.title;
195 optgroup.disabled = config.disabled;
196 optgroup.setAttribute("aria-label", config.ariaLabel);
197 this._applyItemStyle(optgroup, config.style);
198 for (var i = 0; i < config.children.length; ++i) {
199 optgroup.appendChild(this._createItemElement(config.children[i]));
200 }
201 this._selectElement.appendChild(optgroup);
202 return optgroup;
203 } else if (config.type === "separator") {
204 var hr = createElement("hr");
205 hr.title = config.title;
206 hr.disabled = config.disabled;
207 hr.setAttribute("aria-label", config.ariaLabel);
208 this._applyItemStyle(hr, config.style);
209 return hr;
210 }
211 };
212
213 ListPicker.prototype._applyItemStyle = function(element, styleConfig) {
214 element.style.color = styleConfig.color;
215 element.style.backgroundColor = styleConfig.backgroundColor;
216 element.style.fontSize = styleConfig.fontSize + "px";
217 element.style.fontWeight = styleConfig.fontWeight;
218 element.style.fontFamily = styleConfig.fontFamily.join(",");
219 element.style.visibility = styleConfig.visibility;
220 element.style.display = styleConfig.display;
221 element.style.direction = styleConfig.direction;
222 element.style.unicodeBidi = styleConfig.unicodeBidi;
223 };
224
225 if (window.dialogArguments) {
226 initialize(dialogArguments);
227 } else {
228 window.addEventListener("message", handleMessage, false);
229 window.setTimeout(handleArgumentsTimeout, 1000);
230 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698