OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 cr.define('options', function() { | |
6 | |
7 var Preferences = options.Preferences; | |
8 | |
9 /** | |
10 * Helper function update element's state from pref change event. | |
11 * @private | |
12 * @param {!HTMLElement} el The element to update. | |
13 * @param {!Event} event The pref change event. | |
14 */ | |
15 function updateElementState_(el, event) { | |
16 el.managed = event.value && event.value['managed'] != undefined ? | |
17 event.value['managed'] : false; | |
18 | |
19 // Managed UI elements can only be disabled as a result of being | |
20 // managed. They cannot be enabled as a result of a pref being | |
21 // unmanaged. | |
22 if (el.managed) | |
23 el.disabled = true; | |
24 | |
25 // Disable UI elements if backend says so. | |
26 if (!el.disabled && event.value && event.value['disabled']) | |
27 el.disabled = true; | |
28 } | |
29 | |
30 ///////////////////////////////////////////////////////////////////////////// | |
31 // PrefCheckbox class: | |
32 // TODO(jhawkins): Refactor all this copy-pasted code! | |
33 | |
34 // Define a constructor that uses an input element as its underlying element. | |
35 var PrefCheckbox = cr.ui.define('input'); | |
36 | |
37 PrefCheckbox.prototype = { | |
38 // Set up the prototype chain | |
39 __proto__: HTMLInputElement.prototype, | |
40 | |
41 /** | |
42 * Initialization function for the cr.ui framework. | |
43 */ | |
44 decorate: function() { | |
45 this.type = 'checkbox'; | |
46 var self = this; | |
47 | |
48 self.initializeValueType(self.getAttribute('value-type')); | |
49 | |
50 // Listen to pref changes. | |
51 Preferences.getInstance().addEventListener( | |
52 this.pref, | |
53 function(event) { | |
54 var value = event.value && event.value['value'] != undefined ? | |
55 event.value['value'] : event.value; | |
56 | |
57 // Invert pref value if inverted_pref == true. | |
58 if (self.inverted_pref) | |
59 self.checked = !Boolean(value); | |
60 else | |
61 self.checked = Boolean(value); | |
62 | |
63 updateElementState_(self, event); | |
64 }); | |
65 | |
66 // Listen to user events. | |
67 this.addEventListener( | |
68 'change', | |
69 function(e) { | |
70 var value = self.inverted_pref ? !self.checked : self.checked; | |
71 switch(self.valueType) { | |
72 case 'number': | |
73 Preferences.setIntegerPref(self.pref, | |
74 Number(value), self.metric); | |
75 break; | |
76 case 'boolean': | |
77 Preferences.setBooleanPref(self.pref, | |
78 value, self.metric); | |
79 break; | |
80 } | |
81 }); | |
82 }, | |
83 | |
84 /** | |
85 * Sets up options in checkbox element. | |
86 * @param {String} valueType The preference type for this checkbox. | |
87 */ | |
88 initializeValueType: function(valueType) { | |
89 this.valueType = valueType || 'boolean'; | |
90 }, | |
91 }; | |
92 | |
93 /** | |
94 * The preference name. | |
95 * @type {string} | |
96 */ | |
97 cr.defineProperty(PrefCheckbox, 'pref', cr.PropertyKind.ATTR); | |
98 | |
99 /** | |
100 * The user metric string. | |
101 * @type {string} | |
102 */ | |
103 cr.defineProperty(PrefCheckbox, 'metric', cr.PropertyKind.ATTR); | |
104 | |
105 /** | |
106 * Whether to use inverted pref value. | |
107 * @type {boolean} | |
108 */ | |
109 cr.defineProperty(PrefCheckbox, 'inverted_pref', cr.PropertyKind.BOOL_ATTR); | |
110 | |
111 ///////////////////////////////////////////////////////////////////////////// | |
112 // PrefRadio class: | |
113 | |
114 //Define a constructor that uses an input element as its underlying element. | |
115 var PrefRadio = cr.ui.define('input'); | |
116 | |
117 PrefRadio.prototype = { | |
118 // Set up the prototype chain | |
119 __proto__: HTMLInputElement.prototype, | |
120 | |
121 /** | |
122 * Initialization function for the cr.ui framework. | |
123 */ | |
124 decorate: function() { | |
125 this.type = 'radio'; | |
126 var self = this; | |
127 | |
128 // Listen to pref changes. | |
129 Preferences.getInstance().addEventListener(this.pref, | |
130 function(event) { | |
131 var value = event.value && event.value['value'] != undefined ? | |
132 event.value['value'] : event.value; | |
133 self.checked = String(value) == self.value; | |
134 | |
135 updateElementState_(self, event); | |
136 }); | |
137 | |
138 // Listen to user events. | |
139 // Use the 'click' event instead of 'change', because of a bug in WebKit | |
140 // which prevents 'change' from being sent when the user changes selection | |
141 // using the keyboard. | |
142 // https://bugs.webkit.org/show_bug.cgi?id=32013 | |
143 this.addEventListener('click', | |
144 function(e) { | |
145 if(self.value == 'true' || self.value == 'false') { | |
146 Preferences.setBooleanPref(self.pref, | |
147 self.value == 'true', self.metric); | |
148 } else { | |
149 Preferences.setIntegerPref(self.pref, | |
150 parseInt(self.value, 10), self.metric); | |
151 } | |
152 }); | |
153 }, | |
154 }; | |
155 | |
156 /** | |
157 * The preference name. | |
158 * @type {string} | |
159 */ | |
160 cr.defineProperty(PrefRadio, 'pref', cr.PropertyKind.ATTR); | |
161 | |
162 /** | |
163 * The user metric string. | |
164 * @type {string} | |
165 */ | |
166 cr.defineProperty(PrefRadio, 'metric', cr.PropertyKind.ATTR); | |
167 | |
168 ///////////////////////////////////////////////////////////////////////////// | |
169 // PrefNumeric class: | |
170 | |
171 // Define a constructor that uses an input element as its underlying element. | |
172 var PrefNumeric = function() {}; | |
173 PrefNumeric.prototype = { | |
174 // Set up the prototype chain | |
175 __proto__: HTMLInputElement.prototype, | |
176 | |
177 /** | |
178 * Initialization function for the cr.ui framework. | |
179 */ | |
180 decorate: function() { | |
181 var self = this; | |
182 | |
183 // Listen to pref changes. | |
184 Preferences.getInstance().addEventListener(this.pref, | |
185 function(event) { | |
186 self.value = event.value && event.value['value'] != undefined ? | |
187 event.value['value'] : event.value; | |
188 | |
189 updateElementState_(self, event); | |
190 }); | |
191 | |
192 // Listen to user events. | |
193 this.addEventListener('change', | |
194 function(e) { | |
195 if (this.validity.valid) { | |
196 Preferences.setIntegerPref(self.pref, self.value, self.metric); | |
197 } | |
198 }); | |
199 } | |
200 }; | |
201 | |
202 /** | |
203 * The preference name. | |
204 * @type {string} | |
205 */ | |
206 cr.defineProperty(PrefNumeric, 'pref', cr.PropertyKind.ATTR); | |
207 | |
208 /** | |
209 * The user metric string. | |
210 * @type {string} | |
211 */ | |
212 cr.defineProperty(PrefNumeric, 'metric', cr.PropertyKind.ATTR); | |
213 | |
214 ///////////////////////////////////////////////////////////////////////////// | |
215 // PrefNumber class: | |
216 | |
217 // Define a constructor that uses an input element as its underlying element. | |
218 var PrefNumber = cr.ui.define('input'); | |
219 | |
220 PrefNumber.prototype = { | |
221 // Set up the prototype chain | |
222 __proto__: PrefNumeric.prototype, | |
223 | |
224 /** | |
225 * Initialization function for the cr.ui framework. | |
226 */ | |
227 decorate: function() { | |
228 this.type = 'number'; | |
229 PrefNumeric.prototype.decorate.call(this); | |
230 | |
231 // Listen to user events. | |
232 this.addEventListener('input', | |
233 function(e) { | |
234 if (this.validity.valid) { | |
235 Preferences.setIntegerPref(self.pref, self.value, self.metric); | |
236 } | |
237 }); | |
238 } | |
239 }; | |
240 | |
241 ///////////////////////////////////////////////////////////////////////////// | |
242 // PrefRange class: | |
243 | |
244 // Define a constructor that uses an input element as its underlying element. | |
245 var PrefRange = cr.ui.define('input'); | |
246 | |
247 PrefRange.prototype = { | |
248 // Set up the prototype chain | |
249 __proto__: HTMLInputElement.prototype, | |
250 | |
251 /** | |
252 * The map from input range value to the corresponding preference value. | |
253 */ | |
254 valueMap: undefined, | |
255 | |
256 /** | |
257 * If true, the associated pref will be modified on each onchange event; | |
258 * otherwise, the pref will only be modified on the onmouseup event after | |
259 * the drag. | |
260 */ | |
261 continuous: true, | |
262 | |
263 /** | |
264 * Initialization function for the cr.ui framework. | |
265 */ | |
266 decorate: function() { | |
267 this.type = 'range'; | |
268 | |
269 // Update the UI when the pref changes. | |
270 Preferences.getInstance().addEventListener( | |
271 this.pref, this.onPrefChange_.bind(this)); | |
272 | |
273 // Listen to user events. | |
274 // TODO(jhawkins): Add onmousewheel handling once the associated WK bug is | |
275 // fixed. | |
276 // https://bugs.webkit.org/show_bug.cgi?id=52256 | |
277 this.onchange = this.onChange_.bind(this); | |
278 this.onkeyup = this.onmouseup = this.onInputUp_.bind(this); | |
279 }, | |
280 | |
281 /** | |
282 * Event listener that updates the UI when the underlying pref changes. | |
283 * @param {Event} event The event that details the pref change. | |
284 * @private | |
285 */ | |
286 onPrefChange_: function(event) { | |
287 var value = event.value && event.value['value'] != undefined ? | |
288 event.value['value'] : event.value; | |
289 if (value != undefined) | |
290 this.value = this.valueMap ? this.valueMap.indexOf(value) : value; | |
291 }, | |
292 | |
293 /** | |
294 * onchange handler that sets the pref when the user changes the value of | |
295 * the input element. | |
296 * @private | |
297 */ | |
298 onChange_: function(event) { | |
299 if (this.continuous) | |
300 this.setRangePref_(); | |
301 | |
302 if (this.notifyChange) | |
303 this.notifyChange(this, this.mapValueToRange_(this.value)); | |
304 }, | |
305 | |
306 /** | |
307 * Sets the integer value of |pref| to the value of this element. | |
308 * @private | |
309 */ | |
310 setRangePref_: function() { | |
311 Preferences.setIntegerPref( | |
312 this.pref, this.mapValueToRange_(this.value), this.metric); | |
313 | |
314 if (this.notifyPrefChange) | |
315 this.notifyPrefChange(this, this.mapValueToRange_(this.value)); | |
316 }, | |
317 | |
318 /** | |
319 * onkeyup/onmouseup handler that modifies the pref if |continuous| is | |
320 * false. | |
321 * @private | |
322 */ | |
323 onInputUp_: function(event) { | |
324 if (!this.continuous) | |
325 this.setRangePref_(); | |
326 }, | |
327 | |
328 /** | |
329 * Maps the value of this element into the range provided by the client, | |
330 * represented by |valueMap|. | |
331 * @param {number} value The value to map. | |
332 * @private | |
333 */ | |
334 mapValueToRange_: function(value) { | |
335 return this.valueMap ? this.valueMap[value] : value; | |
336 }, | |
337 | |
338 /** | |
339 * Called when the client has specified non-continuous mode and the value of | |
340 * the range control changes. | |
341 * @param {Element} el This element. | |
342 * @param {number} value The value of this element. | |
343 */ | |
344 notifyChange: function(el, value) { | |
345 }, | |
346 }; | |
347 | |
348 /** | |
349 * The preference name. | |
350 * @type {string} | |
351 */ | |
352 cr.defineProperty(PrefRange, 'pref', cr.PropertyKind.ATTR); | |
353 | |
354 /** | |
355 * The user metric string. | |
356 * @type {string} | |
357 */ | |
358 cr.defineProperty(PrefRange, 'metric', cr.PropertyKind.ATTR); | |
359 | |
360 ///////////////////////////////////////////////////////////////////////////// | |
361 // PrefSelect class: | |
362 | |
363 // Define a constructor that uses a select element as its underlying element. | |
364 var PrefSelect = cr.ui.define('select'); | |
365 | |
366 PrefSelect.prototype = { | |
367 // Set up the prototype chain | |
368 __proto__: HTMLSelectElement.prototype, | |
369 | |
370 /** | |
371 * Initialization function for the cr.ui framework. | |
372 */ | |
373 decorate: function() { | |
374 var self = this; | |
375 | |
376 // Listen to pref changes. | |
377 Preferences.getInstance().addEventListener(this.pref, | |
378 function(event) { | |
379 var value = event.value && event.value['value'] != undefined ? | |
380 event.value['value'] : event.value; | |
381 | |
382 // Make sure |value| is a string, because the value is stored as a | |
383 // string in the HTMLOptionElement. | |
384 value = value.toString(); | |
385 | |
386 updateElementState_(self, event); | |
387 | |
388 var found = false; | |
389 for (var i = 0; i < self.options.length; i++) { | |
390 if (self.options[i].value == value) { | |
391 self.selectedIndex = i; | |
392 found = true; | |
393 } | |
394 } | |
395 | |
396 // Item not found, select first item. | |
397 if (!found) | |
398 self.selectedIndex = 0; | |
399 | |
400 if (self.onchange != undefined) | |
401 self.onchange(event); | |
402 }); | |
403 | |
404 // Listen to user events. | |
405 this.addEventListener('change', | |
406 function(e) { | |
407 if (!self.dataType) { | |
408 console.error('undefined data type for <select> pref'); | |
409 return; | |
410 } | |
411 | |
412 switch(self.dataType) { | |
413 case 'number': | |
414 Preferences.setIntegerPref(self.pref, | |
415 self.options[self.selectedIndex].value, self.metric); | |
416 break; | |
417 case 'double': | |
418 Preferences.setDoublePref(self.pref, | |
419 self.options[self.selectedIndex].value, self.metric); | |
420 break; | |
421 case 'boolean': | |
422 var option = self.options[self.selectedIndex]; | |
423 var value = (option.value == 'true') ? true : false; | |
424 Preferences.setBooleanPref(self.pref, value, self.metric); | |
425 break; | |
426 case 'string': | |
427 Preferences.setStringPref(self.pref, | |
428 self.options[self.selectedIndex].value, self.metric); | |
429 break; | |
430 default: | |
431 console.error('unknown data type for <select> pref: ' + | |
432 self.dataType); | |
433 } | |
434 }); | |
435 }, | |
436 }; | |
437 | |
438 /** | |
439 * The preference name. | |
440 * @type {string} | |
441 */ | |
442 cr.defineProperty(PrefSelect, 'pref', cr.PropertyKind.ATTR); | |
443 | |
444 /** | |
445 * The user metric string. | |
446 * @type {string} | |
447 */ | |
448 cr.defineProperty(PrefSelect, 'metric', cr.PropertyKind.ATTR); | |
449 | |
450 /** | |
451 * The data type for the preference options. | |
452 * @type {string} | |
453 */ | |
454 cr.defineProperty(PrefSelect, 'dataType', cr.PropertyKind.ATTR); | |
455 | |
456 ///////////////////////////////////////////////////////////////////////////// | |
457 // PrefTextField class: | |
458 | |
459 // Define a constructor that uses an input element as its underlying element. | |
460 var PrefTextField = cr.ui.define('input'); | |
461 | |
462 PrefTextField.prototype = { | |
463 // Set up the prototype chain | |
464 __proto__: HTMLInputElement.prototype, | |
465 | |
466 /** | |
467 * Initialization function for the cr.ui framework. | |
468 */ | |
469 decorate: function() { | |
470 var self = this; | |
471 | |
472 // Listen to pref changes. | |
473 Preferences.getInstance().addEventListener(this.pref, | |
474 function(event) { | |
475 self.value = event.value && event.value['value'] != undefined ? | |
476 event.value['value'] : event.value; | |
477 | |
478 updateElementState_(self, event); | |
479 }); | |
480 | |
481 // Listen to user events. | |
482 this.addEventListener('change', | |
483 function(e) { | |
484 switch(self.dataType) { | |
485 case 'number': | |
486 Preferences.setIntegerPref(self.pref, self.value, self.metric); | |
487 break; | |
488 case 'double': | |
489 Preferences.setDoublePref(self.pref, self.value, self.metric); | |
490 break; | |
491 default: | |
492 Preferences.setStringPref(self.pref, self.value, self.metric); | |
493 break; | |
494 } | |
495 }); | |
496 | |
497 window.addEventListener('unload', | |
498 function() { | |
499 if (document.activeElement == self) | |
500 self.blur(); | |
501 }); | |
502 } | |
503 }; | |
504 | |
505 /** | |
506 * The preference name. | |
507 * @type {string} | |
508 */ | |
509 cr.defineProperty(PrefTextField, 'pref', cr.PropertyKind.ATTR); | |
510 | |
511 /** | |
512 * The user metric string. | |
513 * @type {string} | |
514 */ | |
515 cr.defineProperty(PrefTextField, 'metric', cr.PropertyKind.ATTR); | |
516 | |
517 /** | |
518 * The data type for the preference options. | |
519 * @type {string} | |
520 */ | |
521 cr.defineProperty(PrefTextField, 'dataType', cr.PropertyKind.ATTR); | |
522 | |
523 // Export | |
524 return { | |
525 PrefCheckbox: PrefCheckbox, | |
526 PrefNumber: PrefNumber, | |
527 PrefNumeric: PrefNumeric, | |
528 PrefRadio: PrefRadio, | |
529 PrefRange: PrefRange, | |
530 PrefSelect: PrefSelect, | |
531 PrefTextField: PrefTextField | |
532 }; | |
533 | |
534 }); | |
OLD | NEW |