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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/resources/options2/pref_ui.js
diff --git a/chrome/browser/resources/options2/pref_ui.js b/chrome/browser/resources/options2/pref_ui.js
new file mode 100644
index 0000000000000000000000000000000000000000..0468f04be853dca84375a035feb5ae17deee2fe3
--- /dev/null
+++ b/chrome/browser/resources/options2/pref_ui.js
@@ -0,0 +1,723 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+cr.define('options', function() {
+
+ var Preferences = options.Preferences;
+
+ /**
+ * Allows an element to be disabled for several reasons.
+ * The element is disabled if at least one reason is true, and the reasons
+ * can be set separately.
+ * @private
+ * @param {!HTMLElement} el The element to update.
+ * @param {string} reason The reason for disabling the element.
+ * @param {boolean} disabled Whether the element should be disabled or enabled
+ * for the given |reason|.
+ */
+ function updateDisabledState_(el, reason, disabled) {
+ if (!el.disabledReasons)
+ el.disabledReasons = {};
+ if (el.disabled && (Object.keys(el.disabledReasons).length == 0)) {
+ // The element has been previously disabled without a reason, so we add
+ // one to keep it disabled.
+ el.disabledReasons['other'] = true;
+ }
+ if (!el.disabled) {
+ // If the element is not disabled, there should be no reason, except for
+ // 'other'.
+ delete el.disabledReasons['other'];
+ if (Object.keys(el.disabledReasons).length > 0)
+ console.error("Element is not disabled but should be");
+ }
+ if (disabled) {
+ el.disabledReasons[reason] = true;
+ } else {
+ delete el.disabledReasons[reason];
+ }
+ el.disabled = Object.keys(el.disabledReasons).length > 0;
+ }
+
+ /**
+ * Helper function to update element's state from pref change event.
+ * @private
+ * @param {!HTMLElement} el The element to update.
+ * @param {!Event} event The pref change event.
+ */
+ function updateElementState_(el, event) {
+ el.controlledBy = null;
+
+ if (!event.value)
+ return;
+
+ updateDisabledState_(el, 'notUserModifiable', event.value.disabled);
+
+ el.controlledBy = event.value['controlledBy'];
+
+ OptionsPage.updateManagedBannerVisibility();
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ // PrefCheckbox class:
+ // TODO(jhawkins): Refactor all this copy-pasted code!
+
+ // Define a constructor that uses an input element as its underlying element.
+ var PrefCheckbox = cr.ui.define('input');
+
+ PrefCheckbox.prototype = {
+ // Set up the prototype chain
+ __proto__: HTMLInputElement.prototype,
+
+ /**
+ * Initialization function for the cr.ui framework.
+ */
+ decorate: function() {
+ this.type = 'checkbox';
+ var self = this;
+
+ self.initializeValueType(self.getAttribute('value-type'));
+
+ // Listen to pref changes.
+ Preferences.getInstance().addEventListener(
+ this.pref,
+ function(event) {
+ var value = event.value && event.value['value'] != undefined ?
+ event.value['value'] : event.value;
+
+ // Invert pref value if inverted_pref == true.
+ if (self.inverted_pref)
+ self.checked = !Boolean(value);
+ else
+ self.checked = Boolean(value);
+
+ updateElementState_(self, event);
+ });
+
+ // Listen to user events.
+ this.addEventListener(
+ 'change',
+ function(e) {
+ if (self.customChangeHandler(e))
+ return;
+ var value = self.inverted_pref ? !self.checked : self.checked;
+ switch(self.valueType) {
+ case 'number':
+ Preferences.setIntegerPref(self.pref,
+ Number(value), self.metric);
+ break;
+ case 'boolean':
+ Preferences.setBooleanPref(self.pref,
+ value, self.metric);
+ break;
+ }
+ });
+ },
+
+ /**
+ * Sets up options in checkbox element.
+ * @param {String} valueType The preference type for this checkbox.
+ */
+ initializeValueType: function(valueType) {
+ this.valueType = valueType || 'boolean';
+ },
+
+ /**
+ * See |updateDisabledState_| above.
+ */
+ setDisabled: function(reason, disabled) {
+ updateDisabledState_(this, reason, disabled);
+ },
+
+ /**
+ * This method is called first while processing an onchange event. If it
+ * returns false, regular onchange processing continues (setting the
+ * associated pref, etc). If it returns true, the rest of the onchange is
+ * not performed. I.e., this works like stopPropagation or cancelBubble.
+ * @param {Event} event Change event.
+ */
+ customChangeHandler: function(event) {
+ return false;
+ },
+ };
+
+ /**
+ * The preference name.
+ * @type {string}
+ */
+ cr.defineProperty(PrefCheckbox, 'pref', cr.PropertyKind.ATTR);
+
+ /**
+ * Whether the preference is controlled by something else than the user's
+ * settings (either 'policy' or 'extension').
+ * @type {string}
+ */
+ cr.defineProperty(PrefCheckbox, 'controlledBy', cr.PropertyKind.ATTR);
+
+ /**
+ * The user metric string.
+ * @type {string}
+ */
+ cr.defineProperty(PrefCheckbox, 'metric', cr.PropertyKind.ATTR);
+
+ /**
+ * Whether to use inverted pref value.
+ * @type {boolean}
+ */
+ cr.defineProperty(PrefCheckbox, 'inverted_pref', cr.PropertyKind.BOOL_ATTR);
+
+ /////////////////////////////////////////////////////////////////////////////
+ // PrefRadio class:
+
+ //Define a constructor that uses an input element as its underlying element.
+ var PrefRadio = cr.ui.define('input');
+
+ PrefRadio.prototype = {
+ // Set up the prototype chain
+ __proto__: HTMLInputElement.prototype,
+
+ /**
+ * Initialization function for the cr.ui framework.
+ */
+ decorate: function() {
+ this.type = 'radio';
+ var self = this;
+
+ // Listen to pref changes.
+ Preferences.getInstance().addEventListener(this.pref,
+ function(event) {
+ var value = event.value && event.value['value'] != undefined ?
+ event.value['value'] : event.value;
+ self.checked = String(value) == self.value;
+
+ updateElementState_(self, event);
+ });
+
+ // Listen to user events.
+ this.addEventListener('change',
+ function(e) {
+ if(self.value == 'true' || self.value == 'false') {
+ Preferences.setBooleanPref(self.pref,
+ self.value == 'true', self.metric);
+ } else {
+ Preferences.setIntegerPref(self.pref,
+ parseInt(self.value, 10), self.metric);
+ }
+ });
+ },
+
+ /**
+ * See |updateDisabledState_| above.
+ */
+ setDisabled: function(reason, disabled) {
+ updateDisabledState_(this, reason, disabled);
+ },
+ };
+
+ /**
+ * The preference name.
+ * @type {string}
+ */
+ cr.defineProperty(PrefRadio, 'pref', cr.PropertyKind.ATTR);
+
+ /**
+ * Whether the preference is controlled by something else than the user's
+ * settings (either 'policy' or 'extension').
+ * @type {string}
+ */
+ cr.defineProperty(PrefRadio, 'controlledBy', cr.PropertyKind.ATTR);
+
+ /**
+ * The user metric string.
+ * @type {string}
+ */
+ cr.defineProperty(PrefRadio, 'metric', cr.PropertyKind.ATTR);
+
+ /////////////////////////////////////////////////////////////////////////////
+ // PrefNumeric class:
+
+ // Define a constructor that uses an input element as its underlying element.
+ var PrefNumeric = function() {};
+ PrefNumeric.prototype = {
+ // Set up the prototype chain
+ __proto__: HTMLInputElement.prototype,
+
+ /**
+ * Initialization function for the cr.ui framework.
+ */
+ decorate: function() {
+ var self = this;
+
+ // Listen to pref changes.
+ Preferences.getInstance().addEventListener(this.pref,
+ function(event) {
+ self.value = event.value && event.value['value'] != undefined ?
+ event.value['value'] : event.value;
+
+ updateElementState_(self, event);
+ });
+
+ // Listen to user events.
+ this.addEventListener('change',
+ function(e) {
+ if (this.validity.valid) {
+ Preferences.setIntegerPref(self.pref, self.value, self.metric);
+ }
+ });
+ },
+
+ /**
+ * See |updateDisabledState_| above.
+ */
+ setDisabled: function(reason, disabled) {
+ updateDisabledState_(this, reason, disabled);
+ },
+ };
+
+ /**
+ * The preference name.
+ * @type {string}
+ */
+ cr.defineProperty(PrefNumeric, 'pref', cr.PropertyKind.ATTR);
+
+ /**
+ * Whether the preference is controlled by something else than the user's
+ * settings (either 'policy' or 'extension').
+ * @type {string}
+ */
+ cr.defineProperty(PrefNumeric, 'controlledBy', cr.PropertyKind.ATTR);
+
+ /**
+ * The user metric string.
+ * @type {string}
+ */
+ cr.defineProperty(PrefNumeric, 'metric', cr.PropertyKind.ATTR);
+
+ /////////////////////////////////////////////////////////////////////////////
+ // PrefNumber class:
+
+ // Define a constructor that uses an input element as its underlying element.
+ var PrefNumber = cr.ui.define('input');
+
+ PrefNumber.prototype = {
+ // Set up the prototype chain
+ __proto__: PrefNumeric.prototype,
+
+ /**
+ * Initialization function for the cr.ui framework.
+ */
+ decorate: function() {
+ this.type = 'number';
+ PrefNumeric.prototype.decorate.call(this);
+
+ // Listen to user events.
+ this.addEventListener('input',
+ function(e) {
+ if (this.validity.valid) {
+ Preferences.setIntegerPref(self.pref, self.value, self.metric);
+ }
+ });
+ },
+
+ /**
+ * See |updateDisabledState_| above.
+ */
+ setDisabled: function(reason, disabled) {
+ updateDisabledState_(this, reason, disabled);
+ },
+ };
+
+ /////////////////////////////////////////////////////////////////////////////
+ // PrefRange class:
+
+ // Define a constructor that uses an input element as its underlying element.
+ var PrefRange = cr.ui.define('input');
+
+ PrefRange.prototype = {
+ // Set up the prototype chain
+ __proto__: HTMLInputElement.prototype,
+
+ /**
+ * The map from input range value to the corresponding preference value.
+ */
+ valueMap: undefined,
+
+ /**
+ * If true, the associated pref will be modified on each onchange event;
+ * otherwise, the pref will only be modified on the onmouseup event after
+ * the drag.
+ */
+ continuous: true,
+
+ /**
+ * Initialization function for the cr.ui framework.
+ */
+ decorate: function() {
+ this.type = 'range';
+
+ // Update the UI when the pref changes.
+ Preferences.getInstance().addEventListener(
+ this.pref, this.onPrefChange_.bind(this));
+
+ // Listen to user events.
+ // TODO(jhawkins): Add onmousewheel handling once the associated WK bug is
+ // fixed.
+ // https://bugs.webkit.org/show_bug.cgi?id=52256
+ this.onchange = this.onChange_.bind(this);
+ this.onkeyup = this.onmouseup = this.onInputUp_.bind(this);
+ },
+
+ /**
+ * Event listener that updates the UI when the underlying pref changes.
+ * @param {Event} event The event that details the pref change.
+ * @private
+ */
+ onPrefChange_: function(event) {
+ var value = event.value && event.value['value'] != undefined ?
+ event.value['value'] : event.value;
+ if (value != undefined)
+ this.value = this.valueMap ? this.valueMap.indexOf(value) : value;
+ },
+
+ /**
+ * onchange handler that sets the pref when the user changes the value of
+ * the input element.
+ * @private
+ */
+ onChange_: function(event) {
+ if (this.continuous)
+ this.setRangePref_();
+
+ if (this.notifyChange)
+ this.notifyChange(this, this.mapValueToRange_(this.value));
+ },
+
+ /**
+ * Sets the integer value of |pref| to the value of this element.
+ * @private
+ */
+ setRangePref_: function() {
+ Preferences.setIntegerPref(
+ this.pref, this.mapValueToRange_(this.value), this.metric);
+
+ if (this.notifyPrefChange)
+ this.notifyPrefChange(this, this.mapValueToRange_(this.value));
+ },
+
+ /**
+ * onkeyup/onmouseup handler that modifies the pref if |continuous| is
+ * false.
+ * @private
+ */
+ onInputUp_: function(event) {
+ if (!this.continuous)
+ this.setRangePref_();
+ },
+
+ /**
+ * Maps the value of this element into the range provided by the client,
+ * represented by |valueMap|.
+ * @param {number} value The value to map.
+ * @private
+ */
+ mapValueToRange_: function(value) {
+ return this.valueMap ? this.valueMap[value] : value;
+ },
+
+ /**
+ * Called when the client has specified non-continuous mode and the value of
+ * the range control changes.
+ * @param {Element} el This element.
+ * @param {number} value The value of this element.
+ */
+ notifyChange: function(el, value) {
+ },
+
+ /**
+ * See |updateDisabledState_| above.
+ */
+ setDisabled: function(reason, disabled) {
+ updateDisabledState_(this, reason, disabled);
+ },
+ };
+
+ /**
+ * The preference name.
+ * @type {string}
+ */
+ cr.defineProperty(PrefRange, 'pref', cr.PropertyKind.ATTR);
+
+ /**
+ * Whether the preference is controlled by something else than the user's
+ * settings (either 'policy' or 'extension').
+ * @type {string}
+ */
+ cr.defineProperty(PrefRange, 'controlledBy', cr.PropertyKind.ATTR);
+
+ /**
+ * The user metric string.
+ * @type {string}
+ */
+ cr.defineProperty(PrefRange, 'metric', cr.PropertyKind.ATTR);
+
+ /////////////////////////////////////////////////////////////////////////////
+ // PrefSelect class:
+
+ // Define a constructor that uses a select element as its underlying element.
+ var PrefSelect = cr.ui.define('select');
+
+ PrefSelect.prototype = {
+ // Set up the prototype chain
+ __proto__: HTMLSelectElement.prototype,
+
+ /**
+ * Initialization function for the cr.ui framework.
+ */
+ decorate: function() {
+ var self = this;
+
+ // Listen to pref changes.
+ Preferences.getInstance().addEventListener(this.pref,
+ function(event) {
+ var value = event.value && event.value['value'] != undefined ?
+ event.value['value'] : event.value;
+
+ // Make sure |value| is a string, because the value is stored as a
+ // string in the HTMLOptionElement.
+ value = value.toString();
+
+ updateElementState_(self, event);
+
+ var found = false;
+ for (var i = 0; i < self.options.length; i++) {
+ if (self.options[i].value == value) {
+ self.selectedIndex = i;
+ found = true;
+ }
+ }
+
+ // Item not found, select first item.
+ if (!found)
+ self.selectedIndex = 0;
+
+ if (self.onchange != undefined)
+ self.onchange(event);
+ });
+
+ // Listen to user events.
+ this.addEventListener('change',
+ function(e) {
+ if (!self.dataType) {
+ console.error('undefined data type for <select> pref');
+ return;
+ }
+
+ switch(self.dataType) {
+ case 'number':
+ Preferences.setIntegerPref(self.pref,
+ self.options[self.selectedIndex].value, self.metric);
+ break;
+ case 'double':
+ Preferences.setDoublePref(self.pref,
+ self.options[self.selectedIndex].value, self.metric);
+ break;
+ case 'boolean':
+ var option = self.options[self.selectedIndex];
+ var value = (option.value == 'true') ? true : false;
+ Preferences.setBooleanPref(self.pref, value, self.metric);
+ break;
+ case 'string':
+ Preferences.setStringPref(self.pref,
+ self.options[self.selectedIndex].value, self.metric);
+ break;
+ default:
+ console.error('unknown data type for <select> pref: ' +
+ self.dataType);
+ }
+ });
+ },
+
+ /**
+ * See |updateDisabledState_| above.
+ */
+ setDisabled: function(reason, disabled) {
+ updateDisabledState_(this, reason, disabled);
+ },
+ };
+
+ /**
+ * The preference name.
+ * @type {string}
+ */
+ cr.defineProperty(PrefSelect, 'pref', cr.PropertyKind.ATTR);
+
+ /**
+ * Whether the preference is controlled by something else than the user's
+ * settings (either 'policy' or 'extension').
+ * @type {string}
+ */
+ cr.defineProperty(PrefSelect, 'controlledBy', cr.PropertyKind.ATTR);
+
+ /**
+ * The user metric string.
+ * @type {string}
+ */
+ cr.defineProperty(PrefSelect, 'metric', cr.PropertyKind.ATTR);
+
+ /**
+ * The data type for the preference options.
+ * @type {string}
+ */
+ cr.defineProperty(PrefSelect, 'dataType', cr.PropertyKind.ATTR);
+
+ /////////////////////////////////////////////////////////////////////////////
+ // PrefTextField class:
+
+ // Define a constructor that uses an input element as its underlying element.
+ var PrefTextField = cr.ui.define('input');
+
+ PrefTextField.prototype = {
+ // Set up the prototype chain
+ __proto__: HTMLInputElement.prototype,
+
+ /**
+ * Initialization function for the cr.ui framework.
+ */
+ decorate: function() {
+ var self = this;
+
+ // Listen to pref changes.
+ Preferences.getInstance().addEventListener(this.pref,
+ function(event) {
+ self.value = event.value && event.value['value'] != undefined ?
+ event.value['value'] : event.value;
+
+ updateElementState_(self, event);
+ });
+
+ // Listen to user events.
+ this.addEventListener('change',
+ function(e) {
+ switch(self.dataType) {
+ case 'number':
+ Preferences.setIntegerPref(self.pref, self.value, self.metric);
+ break;
+ case 'double':
+ Preferences.setDoublePref(self.pref, self.value, self.metric);
+ break;
+ case 'url':
+ Preferences.setURLPref(self.pref, self.value, self.metric);
+ break;
+ default:
+ Preferences.setStringPref(self.pref, self.value, self.metric);
+ break;
+ }
+ });
+
+ window.addEventListener('unload',
+ function() {
+ if (document.activeElement == self)
+ self.blur();
+ });
+ },
+
+ /**
+ * See |updateDisabledState_| above.
+ */
+ setDisabled: function(reason, disabled) {
+ updateDisabledState_(this, reason, disabled);
+ },
+ };
+
+ /**
+ * The preference name.
+ * @type {string}
+ */
+ cr.defineProperty(PrefTextField, 'pref', cr.PropertyKind.ATTR);
+
+ /**
+ * Whether the preference is controlled by something else than the user's
+ * settings (either 'policy' or 'extension').
+ * @type {string}
+ */
+ cr.defineProperty(PrefTextField, 'controlledBy', cr.PropertyKind.ATTR);
+
+ /**
+ * The user metric string.
+ * @type {string}
+ */
+ cr.defineProperty(PrefTextField, 'metric', cr.PropertyKind.ATTR);
+
+ /**
+ * The data type for the preference options.
+ * @type {string}
+ */
+ cr.defineProperty(PrefTextField, 'dataType', cr.PropertyKind.ATTR);
+
+ /////////////////////////////////////////////////////////////////////////////
+ // PrefButton class:
+
+ // Define a constructor that uses a button element as its underlying element.
+ var PrefButton = cr.ui.define('button');
+
+ PrefButton.prototype = {
+ // Set up the prototype chain
+ __proto__: HTMLButtonElement.prototype,
+
+ /**
+ * Initialization function for the cr.ui framework.
+ */
+ decorate: function() {
+ var self = this;
+
+ // Listen to pref changes. This element behaves like a normal button and
+ // doesn't affect the underlying preference; it just becomes disabled
+ // when the preference is managed, and its value is false.
+ // This is useful for buttons that should be disabled when the underlying
+ // boolean preference is set to false by a policy or extension.
+ Preferences.getInstance().addEventListener(this.pref,
+ function(event) {
+ var e = {
+ value: {
+ 'disabled': event.value['disabled'] && !event.value['value'],
+ 'controlledBy': event.value['controlledBy']
+ }
+ };
+ updateElementState_(self, e);
+ });
+ },
+
+ /**
+ * See |updateDisabledState_| above.
+ */
+ setDisabled: function(reason, disabled) {
+ updateDisabledState_(this, reason, disabled);
+ },
+ };
+
+ /**
+ * The preference name.
+ * @type {string}
+ */
+ cr.defineProperty(PrefButton, 'pref', cr.PropertyKind.ATTR);
+
+ /**
+ * Whether the preference is controlled by something else than the user's
+ * settings (either 'policy' or 'extension').
+ * @type {string}
+ */
+ cr.defineProperty(PrefButton, 'controlledBy', cr.PropertyKind.ATTR);
+
+ // Export
+ return {
+ PrefCheckbox: PrefCheckbox,
+ PrefNumber: PrefNumber,
+ PrefNumeric: PrefNumeric,
+ PrefRadio: PrefRadio,
+ PrefRange: PrefRange,
+ PrefSelect: PrefSelect,
+ PrefTextField: PrefTextField,
+ PrefButton: PrefButton
+ };
+
+});
« 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