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

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

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

Powered by Google App Engine
This is Rietveld 408576698