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

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

Issue 879503002: Add resources for the new <select> Popup Menu (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 5 years, 11 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
« no previous file with comments | « Source/web/resources/listPicker.css ('k') | public/blink_resources.grd » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 initialize({});
35 }
36
37 /**
38 * @constructor
39 * @param {!Element} element
40 * @param {!Object} config
41 */
42 function ListPicker(element, config) {
43 Picker.call(this, element, config);
44 this._selectElement = createElement("select");
45 this._element.appendChild(this._selectElement);
46 this._layout();
47 this._selectElement.focus();
48 this._selectElement.addEventListener("mouseover", this._handleMouseOver.bind (this), false);
49 this._selectElement.addEventListener("mouseup", this._handleMouseUp.bind(thi s), false);
50 this._selectElement.addEventListener("keydown", this._handleKeyDown.bind(thi s), false);
51 this._selectElement.addEventListener("change", this._handleChange.bind(this) , false);
52 window.addEventListener("message", this._handleWindowMessage.bind(this), fal se);
53 window.addEventListener("mousemove", this._handleWindowMouseMove.bind(this), false);
54 this.lastMousePositionX = Infinity;
55 this.lastMousePositionY = Infinity;
56
57 // Not sure why but we need to delay this call so that offsetHeight is
58 // accurate. We wait for the window to resize to work around an issue
59 // of immediate resize requests getting mixed up.
60 this._handleWindowDidHideBound = this._handleWindowDidHide.bind(this);
61 window.addEventListener("didHide", this._handleWindowDidHideBound, false);
62 hideWindow();
63 }
64 ListPicker.prototype = Object.create(Picker.prototype);
65
66 ListPicker.prototype._handleWindowDidHide = function() {
67 this._fixWindowSize();
68 var selectedOption = this._selectElement.options[this._selectElement.selecte dIndex];
69 selectedOption.scrollIntoView(false);
70 window.removeEventListener("didHide", this._handleWindowDidHideBound, false) ;
71 };
72
73 ListPicker.prototype._handleWindowMessage = function(event) {
74 eval(event.data);
75 if (window.updateData.type === "update")
76 this._update(window.updateData);
77 delete window.updateData;
78 };
79
80 ListPicker.prototype._handleWindowMouseMove = function (event) {
81 this.lastMousePositionX = event.clientX;
82 this.lastMousePositionY = event.clientY;
83 };
84
85 ListPicker.prototype._handleMouseOver = function(event) {
86 if (event.toElement.tagName !== "OPTION")
87 return;
88 var savedScrollTop = this._selectElement.scrollTop;
89 event.toElement.selected = true;
90 this._selectElement.scrollTop = savedScrollTop;
91 };
92
93 ListPicker.prototype._handleMouseUp = function(event) {
94 if (event.target.tagName !== "OPTION")
95 return;
96 window.pagePopupController.setValueAndClosePopup(0, this._selectElement.valu e);
97 };
98
99 ListPicker.prototype._handleChange = function(event) {
100 window.pagePopupController.setValue(this._selectElement.value);
101 };
102
103 ListPicker.prototype._handleKeyDown = function(event) {
104 var key = event.keyIdentifier;
105 if (key === "U+001B") { // ESC
106 window.pagePopupController.closePopup();
107 event.preventDefault();
108 } else if (key === "U+0009" /* TAB */ || key === "Enter") {
109 window.pagePopupController.setValueAndClosePopup(0, this._selectElement. value);
110 event.preventDefault();
111 } else if (event.altKey && (key === "Down" || key === "Up")) {
112 // We need to add a delay here because, if we do it immediately the key
113 // press event will be handled by HTMLSelectElement and this popup will
114 // be reopened.
115 setTimeout(function () {
116 window.pagePopupController.closePopup();
117 }, 0);
118 event.preventDefault();
119 } else {
120 // After a key press, we need to call setValue to reflect the selection
121 // to the owner element. We can handle most cases with the change
122 // event. But we need to call setValue even when the selection hasn't
123 // changed. So we call it here too. setValue will be called twice for
124 // some key presses but it won't matter.
125 window.pagePopupController.setValue(this._selectElement.value);
126 }
127 };
128
129 ListPicker.prototype._fixWindowSize = function() {
130 this._selectElement.style.height = "";
131 this._selectElement.size = 20;
132 var maxHeight = this._selectElement.offsetHeight;
133 this._selectElement.style.height = "0";
134 var heightOutsideOfContent = this._selectElement.offsetHeight - this._select Element.clientHeight;
135 var desiredWindowHeight = this._selectElement.scrollHeight + heightOutsideOf Content;
136 this._selectElement.style.height = desiredWindowHeight + "px";
137 // scrollHeight returns floored value so we needed this check.
138 if (this._hasVerticalScrollbar())
139 desiredWindowHeight += 1;
140 if (desiredWindowHeight > maxHeight)
141 desiredWindowHeight = maxHeight;
142 var desiredWindowWidth = Math.max(this._config.anchorRectInScreen.width, thi s._selectElement.offsetWidth);
143 var windowRect = adjustWindowRect(desiredWindowWidth, desiredWindowHeight, t his._selectElement.offsetWidth, 0);
144 this._selectElement.style.width = windowRect.width + "px";
145 this._selectElement.style.height = windowRect.height + "px";
146 this._element.style.height = windowRect.height + "px";
147 setWindowRect(windowRect);
148 };
149
150 ListPicker.prototype._hasVerticalScrollbar = function() {
151 return this._selectElement.scrollWidth > this._selectElement.clientWidth;
152 };
153
154 ListPicker.prototype._listItemCount = function() {
155 return this._selectElement.querySelectorAll("option,optgroup,hr").length;
156 };
157
158 ListPicker.prototype._layout = function() {
159 for (var i = 0; i < this._config.children.length; ++i) {
160 this._selectElement.appendChild(this._createItemElement(this._config.chi ldren[i]));
161 }
162 this._selectElement.value = this._config.selectedIndex;
163 };
164
165 ListPicker.prototype._update = function(data) {
166 this._config.children = data.children;
167 var oldValue = this._selectElement.value;
168 while (this._selectElement.firstChild) {
169 this._selectElement.removeChild(this._selectElement.firstChild);
170 }
171 for (var i = 0; i < this._config.children.length; ++i) {
172 this._selectElement.appendChild(this._createItemElement(this._config.chi ldren[i]));
173 }
174 this._selectElement.value = this._config.selectedIndex;
175 var elementUnderMouse = document.elementFromPoint(this.lastMousePositionX, t his.lastMousePositionY);
176 var optionUnderMouse = elementUnderMouse && elementUnderMouse.closest("optio n");
177 if (optionUnderMouse)
178 optionUnderMouse.selected = true;
179 else
180 this._selectElement.value = oldValue;
181 this._fixWindowSize();
182 };
183
184 ListPicker.prototype._createItemElement = function(config) {
185 if (config.type === "option") {
186 var option = createElement("option");
187 option.appendChild(document.createTextNode(config.label));
188 option.value = config.value;
189 option.title = config.title;
190 option.disabled = config.disabled;
191 option.setAttribute("aria-label", config.ariaLabel);
192 this._applyItemStyle(option, config.style);
193 this._selectElement.appendChild(option);
194 return option;
195 } else if (config.type === "optgroup") {
196 var optgroup = createElement("optgroup");
197 optgroup.label = config.label;
198 optgroup.title = config.title;
199 optgroup.disabled = config.disabled;
200 optgroup.setAttribute("aria-label", config.ariaLabel);
201 this._applyItemStyle(optgroup, config.style);
202 for (var i = 0; i < config.children.length; ++i) {
203 optgroup.appendChild(this._createItemElement(config.children[i]));
204 }
205 this._selectElement.appendChild(optgroup);
206 return optgroup;
207 } else if (config.type === "separator") {
208 var hr = createElement("hr");
209 hr.title = config.title;
210 hr.disabled = config.disabled;
211 hr.setAttribute("aria-label", config.ariaLabel);
212 this._applyItemStyle(hr, config.style);
213 return hr;
214 }
215 };
216
217 ListPicker.prototype._applyItemStyle = function(element, styleConfig) {
218 element.style.color = styleConfig.color;
219 element.style.backgroundColor = styleConfig.backgroundColor;
220 element.style.fontSize = styleConfig.fontSize + "px";
221 element.style.fontWeight = styleConfig.fontWeight;
222 element.style.fontFamily = styleConfig.fontFamily.join(",");
223 element.style.visibility = styleConfig.visibility;
224 element.style.display = styleConfig.display;
225 element.style.direction = styleConfig.direction;
226 element.style.unicodeBidi = styleConfig.unicodeBidi;
227 };
228
229 if (window.dialogArguments) {
230 initialize(dialogArguments);
231 } else {
232 window.addEventListener("message", handleMessage, false);
233 window.setTimeout(handleArgumentsTimeout, 1000);
234 }
OLDNEW
« no previous file with comments | « Source/web/resources/listPicker.css ('k') | public/blink_resources.grd » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698