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

Side by Side Diff: chrome/browser/resources/options2/pref_ui.js

Issue 8895023: Options2: Pull the trigger. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: DIAF. Created 9 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 // 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 * Allows an element to be disabled for several reasons.
11 * The element is disabled if at least one reason is true, and the reasons
12 * can be set separately.
13 * @private
14 * @param {!HTMLElement} el The element to update.
15 * @param {string} reason The reason for disabling the element.
16 * @param {boolean} disabled Whether the element should be disabled or enabled
17 * for the given |reason|.
18 */
19 function updateDisabledState_(el, reason, disabled) {
20 if (!el.disabledReasons)
21 el.disabledReasons = {};
22 if (el.disabled && (Object.keys(el.disabledReasons).length == 0)) {
23 // The element has been previously disabled without a reason, so we add
24 // one to keep it disabled.
25 el.disabledReasons['other'] = true;
26 }
27 if (!el.disabled) {
28 // If the element is not disabled, there should be no reason, except for
29 // 'other'.
30 delete el.disabledReasons['other'];
31 if (Object.keys(el.disabledReasons).length > 0)
32 console.error("Element is not disabled but should be");
33 }
34 if (disabled) {
35 el.disabledReasons[reason] = true;
36 } else {
37 delete el.disabledReasons[reason];
38 }
39 el.disabled = Object.keys(el.disabledReasons).length > 0;
40 }
41
42 /**
43 * Helper function to update element's state from pref change event.
44 * @private
45 * @param {!HTMLElement} el The element to update.
46 * @param {!Event} event The pref change event.
47 */
48 function updateElementState_(el, event) {
49 el.controlledBy = null;
50
51 if (!event.value)
52 return;
53
54 updateDisabledState_(el, 'notUserModifiable', event.value.disabled);
55
56 el.controlledBy = event.value['controlledBy'];
57
58 OptionsPage.updateManagedBannerVisibility();
59 }
60
61 /////////////////////////////////////////////////////////////////////////////
62 // PrefCheckbox class:
63 // TODO(jhawkins): Refactor all this copy-pasted code!
64
65 // Define a constructor that uses an input element as its underlying element.
66 var PrefCheckbox = cr.ui.define('input');
67
68 PrefCheckbox.prototype = {
69 // Set up the prototype chain
70 __proto__: HTMLInputElement.prototype,
71
72 /**
73 * Initialization function for the cr.ui framework.
74 */
75 decorate: function() {
76 this.type = 'checkbox';
77 var self = this;
78
79 self.initializeValueType(self.getAttribute('value-type'));
80
81 // Listen to pref changes.
82 Preferences.getInstance().addEventListener(
83 this.pref,
84 function(event) {
85 var value = event.value && event.value['value'] != undefined ?
86 event.value['value'] : event.value;
87
88 // Invert pref value if inverted_pref == true.
89 if (self.inverted_pref)
90 self.checked = !Boolean(value);
91 else
92 self.checked = Boolean(value);
93
94 updateElementState_(self, event);
95 });
96
97 // Listen to user events.
98 this.addEventListener(
99 'change',
100 function(e) {
101 if (self.customChangeHandler(e))
102 return;
103 var value = self.inverted_pref ? !self.checked : self.checked;
104 switch(self.valueType) {
105 case 'number':
106 Preferences.setIntegerPref(self.pref,
107 Number(value), self.metric);
108 break;
109 case 'boolean':
110 Preferences.setBooleanPref(self.pref,
111 value, self.metric);
112 break;
113 }
114 });
115 },
116
117 /**
118 * Sets up options in checkbox element.
119 * @param {String} valueType The preference type for this checkbox.
120 */
121 initializeValueType: function(valueType) {
122 this.valueType = valueType || 'boolean';
123 },
124
125 /**
126 * See |updateDisabledState_| above.
127 */
128 setDisabled: function(reason, disabled) {
129 updateDisabledState_(this, reason, disabled);
130 },
131
132 /**
133 * This method is called first while processing an onchange event. If it
134 * returns false, regular onchange processing continues (setting the
135 * associated pref, etc). If it returns true, the rest of the onchange is
136 * not performed. I.e., this works like stopPropagation or cancelBubble.
137 * @param {Event} event Change event.
138 */
139 customChangeHandler: function(event) {
140 return false;
141 },
142 };
143
144 /**
145 * The preference name.
146 * @type {string}
147 */
148 cr.defineProperty(PrefCheckbox, 'pref', cr.PropertyKind.ATTR);
149
150 /**
151 * Whether the preference is controlled by something else than the user's
152 * settings (either 'policy' or 'extension').
153 * @type {string}
154 */
155 cr.defineProperty(PrefCheckbox, 'controlledBy', cr.PropertyKind.ATTR);
156
157 /**
158 * The user metric string.
159 * @type {string}
160 */
161 cr.defineProperty(PrefCheckbox, 'metric', cr.PropertyKind.ATTR);
162
163 /**
164 * Whether to use inverted pref value.
165 * @type {boolean}
166 */
167 cr.defineProperty(PrefCheckbox, 'inverted_pref', cr.PropertyKind.BOOL_ATTR);
168
169 /////////////////////////////////////////////////////////////////////////////
170 // PrefRadio class:
171
172 //Define a constructor that uses an input element as its underlying element.
173 var PrefRadio = cr.ui.define('input');
174
175 PrefRadio.prototype = {
176 // Set up the prototype chain
177 __proto__: HTMLInputElement.prototype,
178
179 /**
180 * Initialization function for the cr.ui framework.
181 */
182 decorate: function() {
183 this.type = 'radio';
184 var self = this;
185
186 // Listen to pref changes.
187 Preferences.getInstance().addEventListener(this.pref,
188 function(event) {
189 var value = event.value && event.value['value'] != undefined ?
190 event.value['value'] : event.value;
191 self.checked = String(value) == self.value;
192
193 updateElementState_(self, event);
194 });
195
196 // Listen to user events.
197 this.addEventListener('change',
198 function(e) {
199 if(self.value == 'true' || self.value == 'false') {
200 Preferences.setBooleanPref(self.pref,
201 self.value == 'true', self.metric);
202 } else {
203 Preferences.setIntegerPref(self.pref,
204 parseInt(self.value, 10), self.metric);
205 }
206 });
207 },
208
209 /**
210 * See |updateDisabledState_| above.
211 */
212 setDisabled: function(reason, disabled) {
213 updateDisabledState_(this, reason, disabled);
214 },
215 };
216
217 /**
218 * The preference name.
219 * @type {string}
220 */
221 cr.defineProperty(PrefRadio, 'pref', cr.PropertyKind.ATTR);
222
223 /**
224 * Whether the preference is controlled by something else than the user's
225 * settings (either 'policy' or 'extension').
226 * @type {string}
227 */
228 cr.defineProperty(PrefRadio, 'controlledBy', cr.PropertyKind.ATTR);
229
230 /**
231 * The user metric string.
232 * @type {string}
233 */
234 cr.defineProperty(PrefRadio, 'metric', cr.PropertyKind.ATTR);
235
236 /////////////////////////////////////////////////////////////////////////////
237 // PrefNumeric class:
238
239 // Define a constructor that uses an input element as its underlying element.
240 var PrefNumeric = function() {};
241 PrefNumeric.prototype = {
242 // Set up the prototype chain
243 __proto__: HTMLInputElement.prototype,
244
245 /**
246 * Initialization function for the cr.ui framework.
247 */
248 decorate: function() {
249 var self = this;
250
251 // Listen to pref changes.
252 Preferences.getInstance().addEventListener(this.pref,
253 function(event) {
254 self.value = event.value && event.value['value'] != undefined ?
255 event.value['value'] : event.value;
256
257 updateElementState_(self, event);
258 });
259
260 // Listen to user events.
261 this.addEventListener('change',
262 function(e) {
263 if (this.validity.valid) {
264 Preferences.setIntegerPref(self.pref, self.value, self.metric);
265 }
266 });
267 },
268
269 /**
270 * See |updateDisabledState_| above.
271 */
272 setDisabled: function(reason, disabled) {
273 updateDisabledState_(this, reason, disabled);
274 },
275 };
276
277 /**
278 * The preference name.
279 * @type {string}
280 */
281 cr.defineProperty(PrefNumeric, 'pref', cr.PropertyKind.ATTR);
282
283 /**
284 * Whether the preference is controlled by something else than the user's
285 * settings (either 'policy' or 'extension').
286 * @type {string}
287 */
288 cr.defineProperty(PrefNumeric, 'controlledBy', cr.PropertyKind.ATTR);
289
290 /**
291 * The user metric string.
292 * @type {string}
293 */
294 cr.defineProperty(PrefNumeric, 'metric', cr.PropertyKind.ATTR);
295
296 /////////////////////////////////////////////////////////////////////////////
297 // PrefNumber class:
298
299 // Define a constructor that uses an input element as its underlying element.
300 var PrefNumber = cr.ui.define('input');
301
302 PrefNumber.prototype = {
303 // Set up the prototype chain
304 __proto__: PrefNumeric.prototype,
305
306 /**
307 * Initialization function for the cr.ui framework.
308 */
309 decorate: function() {
310 this.type = 'number';
311 PrefNumeric.prototype.decorate.call(this);
312
313 // Listen to user events.
314 this.addEventListener('input',
315 function(e) {
316 if (this.validity.valid) {
317 Preferences.setIntegerPref(self.pref, self.value, self.metric);
318 }
319 });
320 },
321
322 /**
323 * See |updateDisabledState_| above.
324 */
325 setDisabled: function(reason, disabled) {
326 updateDisabledState_(this, reason, disabled);
327 },
328 };
329
330 /////////////////////////////////////////////////////////////////////////////
331 // PrefRange class:
332
333 // Define a constructor that uses an input element as its underlying element.
334 var PrefRange = cr.ui.define('input');
335
336 PrefRange.prototype = {
337 // Set up the prototype chain
338 __proto__: HTMLInputElement.prototype,
339
340 /**
341 * The map from input range value to the corresponding preference value.
342 */
343 valueMap: undefined,
344
345 /**
346 * If true, the associated pref will be modified on each onchange event;
347 * otherwise, the pref will only be modified on the onmouseup event after
348 * the drag.
349 */
350 continuous: true,
351
352 /**
353 * Initialization function for the cr.ui framework.
354 */
355 decorate: function() {
356 this.type = 'range';
357
358 // Update the UI when the pref changes.
359 Preferences.getInstance().addEventListener(
360 this.pref, this.onPrefChange_.bind(this));
361
362 // Listen to user events.
363 // TODO(jhawkins): Add onmousewheel handling once the associated WK bug is
364 // fixed.
365 // https://bugs.webkit.org/show_bug.cgi?id=52256
366 this.onchange = this.onChange_.bind(this);
367 this.onkeyup = this.onmouseup = this.onInputUp_.bind(this);
368 },
369
370 /**
371 * Event listener that updates the UI when the underlying pref changes.
372 * @param {Event} event The event that details the pref change.
373 * @private
374 */
375 onPrefChange_: function(event) {
376 var value = event.value && event.value['value'] != undefined ?
377 event.value['value'] : event.value;
378 if (value != undefined)
379 this.value = this.valueMap ? this.valueMap.indexOf(value) : value;
380 },
381
382 /**
383 * onchange handler that sets the pref when the user changes the value of
384 * the input element.
385 * @private
386 */
387 onChange_: function(event) {
388 if (this.continuous)
389 this.setRangePref_();
390
391 if (this.notifyChange)
392 this.notifyChange(this, this.mapValueToRange_(this.value));
393 },
394
395 /**
396 * Sets the integer value of |pref| to the value of this element.
397 * @private
398 */
399 setRangePref_: function() {
400 Preferences.setIntegerPref(
401 this.pref, this.mapValueToRange_(this.value), this.metric);
402
403 if (this.notifyPrefChange)
404 this.notifyPrefChange(this, this.mapValueToRange_(this.value));
405 },
406
407 /**
408 * onkeyup/onmouseup handler that modifies the pref if |continuous| is
409 * false.
410 * @private
411 */
412 onInputUp_: function(event) {
413 if (!this.continuous)
414 this.setRangePref_();
415 },
416
417 /**
418 * Maps the value of this element into the range provided by the client,
419 * represented by |valueMap|.
420 * @param {number} value The value to map.
421 * @private
422 */
423 mapValueToRange_: function(value) {
424 return this.valueMap ? this.valueMap[value] : value;
425 },
426
427 /**
428 * Called when the client has specified non-continuous mode and the value of
429 * the range control changes.
430 * @param {Element} el This element.
431 * @param {number} value The value of this element.
432 */
433 notifyChange: function(el, value) {
434 },
435
436 /**
437 * See |updateDisabledState_| above.
438 */
439 setDisabled: function(reason, disabled) {
440 updateDisabledState_(this, reason, disabled);
441 },
442 };
443
444 /**
445 * The preference name.
446 * @type {string}
447 */
448 cr.defineProperty(PrefRange, 'pref', cr.PropertyKind.ATTR);
449
450 /**
451 * Whether the preference is controlled by something else than the user's
452 * settings (either 'policy' or 'extension').
453 * @type {string}
454 */
455 cr.defineProperty(PrefRange, 'controlledBy', cr.PropertyKind.ATTR);
456
457 /**
458 * The user metric string.
459 * @type {string}
460 */
461 cr.defineProperty(PrefRange, 'metric', cr.PropertyKind.ATTR);
462
463 /////////////////////////////////////////////////////////////////////////////
464 // PrefSelect class:
465
466 // Define a constructor that uses a select element as its underlying element.
467 var PrefSelect = cr.ui.define('select');
468
469 PrefSelect.prototype = {
470 // Set up the prototype chain
471 __proto__: HTMLSelectElement.prototype,
472
473 /**
474 * Initialization function for the cr.ui framework.
475 */
476 decorate: function() {
477 var self = this;
478
479 // Listen to pref changes.
480 Preferences.getInstance().addEventListener(this.pref,
481 function(event) {
482 var value = event.value && event.value['value'] != undefined ?
483 event.value['value'] : event.value;
484
485 // Make sure |value| is a string, because the value is stored as a
486 // string in the HTMLOptionElement.
487 value = value.toString();
488
489 updateElementState_(self, event);
490
491 var found = false;
492 for (var i = 0; i < self.options.length; i++) {
493 if (self.options[i].value == value) {
494 self.selectedIndex = i;
495 found = true;
496 }
497 }
498
499 // Item not found, select first item.
500 if (!found)
501 self.selectedIndex = 0;
502
503 if (self.onchange != undefined)
504 self.onchange(event);
505 });
506
507 // Listen to user events.
508 this.addEventListener('change',
509 function(e) {
510 if (!self.dataType) {
511 console.error('undefined data type for <select> pref');
512 return;
513 }
514
515 switch(self.dataType) {
516 case 'number':
517 Preferences.setIntegerPref(self.pref,
518 self.options[self.selectedIndex].value, self.metric);
519 break;
520 case 'double':
521 Preferences.setDoublePref(self.pref,
522 self.options[self.selectedIndex].value, self.metric);
523 break;
524 case 'boolean':
525 var option = self.options[self.selectedIndex];
526 var value = (option.value == 'true') ? true : false;
527 Preferences.setBooleanPref(self.pref, value, self.metric);
528 break;
529 case 'string':
530 Preferences.setStringPref(self.pref,
531 self.options[self.selectedIndex].value, self.metric);
532 break;
533 default:
534 console.error('unknown data type for <select> pref: ' +
535 self.dataType);
536 }
537 });
538 },
539
540 /**
541 * See |updateDisabledState_| above.
542 */
543 setDisabled: function(reason, disabled) {
544 updateDisabledState_(this, reason, disabled);
545 },
546 };
547
548 /**
549 * The preference name.
550 * @type {string}
551 */
552 cr.defineProperty(PrefSelect, 'pref', cr.PropertyKind.ATTR);
553
554 /**
555 * Whether the preference is controlled by something else than the user's
556 * settings (either 'policy' or 'extension').
557 * @type {string}
558 */
559 cr.defineProperty(PrefSelect, 'controlledBy', cr.PropertyKind.ATTR);
560
561 /**
562 * The user metric string.
563 * @type {string}
564 */
565 cr.defineProperty(PrefSelect, 'metric', cr.PropertyKind.ATTR);
566
567 /**
568 * The data type for the preference options.
569 * @type {string}
570 */
571 cr.defineProperty(PrefSelect, 'dataType', cr.PropertyKind.ATTR);
572
573 /////////////////////////////////////////////////////////////////////////////
574 // PrefTextField class:
575
576 // Define a constructor that uses an input element as its underlying element.
577 var PrefTextField = cr.ui.define('input');
578
579 PrefTextField.prototype = {
580 // Set up the prototype chain
581 __proto__: HTMLInputElement.prototype,
582
583 /**
584 * Initialization function for the cr.ui framework.
585 */
586 decorate: function() {
587 var self = this;
588
589 // Listen to pref changes.
590 Preferences.getInstance().addEventListener(this.pref,
591 function(event) {
592 self.value = event.value && event.value['value'] != undefined ?
593 event.value['value'] : event.value;
594
595 updateElementState_(self, event);
596 });
597
598 // Listen to user events.
599 this.addEventListener('change',
600 function(e) {
601 switch(self.dataType) {
602 case 'number':
603 Preferences.setIntegerPref(self.pref, self.value, self.metric);
604 break;
605 case 'double':
606 Preferences.setDoublePref(self.pref, self.value, self.metric);
607 break;
608 case 'url':
609 Preferences.setURLPref(self.pref, self.value, self.metric);
610 break;
611 default:
612 Preferences.setStringPref(self.pref, self.value, self.metric);
613 break;
614 }
615 });
616
617 window.addEventListener('unload',
618 function() {
619 if (document.activeElement == self)
620 self.blur();
621 });
622 },
623
624 /**
625 * See |updateDisabledState_| above.
626 */
627 setDisabled: function(reason, disabled) {
628 updateDisabledState_(this, reason, disabled);
629 },
630 };
631
632 /**
633 * The preference name.
634 * @type {string}
635 */
636 cr.defineProperty(PrefTextField, 'pref', cr.PropertyKind.ATTR);
637
638 /**
639 * Whether the preference is controlled by something else than the user's
640 * settings (either 'policy' or 'extension').
641 * @type {string}
642 */
643 cr.defineProperty(PrefTextField, 'controlledBy', cr.PropertyKind.ATTR);
644
645 /**
646 * The user metric string.
647 * @type {string}
648 */
649 cr.defineProperty(PrefTextField, 'metric', cr.PropertyKind.ATTR);
650
651 /**
652 * The data type for the preference options.
653 * @type {string}
654 */
655 cr.defineProperty(PrefTextField, 'dataType', cr.PropertyKind.ATTR);
656
657 /////////////////////////////////////////////////////////////////////////////
658 // PrefButton class:
659
660 // Define a constructor that uses a button element as its underlying element.
661 var PrefButton = cr.ui.define('button');
662
663 PrefButton.prototype = {
664 // Set up the prototype chain
665 __proto__: HTMLButtonElement.prototype,
666
667 /**
668 * Initialization function for the cr.ui framework.
669 */
670 decorate: function() {
671 var self = this;
672
673 // Listen to pref changes. This element behaves like a normal button and
674 // doesn't affect the underlying preference; it just becomes disabled
675 // when the preference is managed, and its value is false.
676 // This is useful for buttons that should be disabled when the underlying
677 // boolean preference is set to false by a policy or extension.
678 Preferences.getInstance().addEventListener(this.pref,
679 function(event) {
680 var e = {
681 value: {
682 'disabled': event.value['disabled'] && !event.value['value'],
683 'controlledBy': event.value['controlledBy']
684 }
685 };
686 updateElementState_(self, e);
687 });
688 },
689
690 /**
691 * See |updateDisabledState_| above.
692 */
693 setDisabled: function(reason, disabled) {
694 updateDisabledState_(this, reason, disabled);
695 },
696 };
697
698 /**
699 * The preference name.
700 * @type {string}
701 */
702 cr.defineProperty(PrefButton, 'pref', cr.PropertyKind.ATTR);
703
704 /**
705 * Whether the preference is controlled by something else than the user's
706 * settings (either 'policy' or 'extension').
707 * @type {string}
708 */
709 cr.defineProperty(PrefButton, 'controlledBy', cr.PropertyKind.ATTR);
710
711 // Export
712 return {
713 PrefCheckbox: PrefCheckbox,
714 PrefNumber: PrefNumber,
715 PrefNumeric: PrefNumeric,
716 PrefRadio: PrefRadio,
717 PrefRange: PrefRange,
718 PrefSelect: PrefSelect,
719 PrefTextField: PrefTextField,
720 PrefButton: PrefButton
721 };
722
723 });
OLDNEW
« no previous file with comments | « chrome/browser/resources/options2/personal_options_profile_list.js ('k') | chrome/browser/resources/options2/preferences.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698