Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 cr.define('options', function() { | 5 cr.define('options', function() { |
| 6 var Preferences = options.Preferences; | 6 var Preferences = options.Preferences; |
| 7 | 7 |
| 8 /** | 8 /** |
| 9 * A controlled setting indicator that can be placed on a setting as an | 9 * A controlled setting indicator that can be placed on a setting as an |
| 10 * indicator that the value is controlled by some external entity such as | 10 * indicator that the value is controlled by some external entity such as |
| 11 * policy or an extension. | 11 * policy or an extension. |
| 12 * @constructor | 12 * @constructor |
| 13 * @extends {HTMLSpanElement} | 13 * @extends {HTMLSpanElement} |
| 14 */ | 14 */ |
| 15 var ControlledSettingIndicator = cr.ui.define('span'); | 15 var ControlledSettingIndicator = cr.ui.define('span'); |
| 16 | 16 |
| 17 ControlledSettingIndicator.prototype = { | 17 ControlledSettingIndicator.prototype = { |
| 18 __proto__: HTMLSpanElement.prototype, | 18 __proto__: HTMLSpanElement.prototype, |
| 19 | 19 |
| 20 /** | 20 /** |
| 21 * Decorates the base element to show the proper icon. | 21 * Decorates the base element to show the proper icon. |
| 22 */ | 22 */ |
| 23 decorate: function() { | 23 decorate: function() { |
| 24 var self = this; | 24 var self = this; |
| 25 | 25 |
| 26 // If there is a pref, track its controlledBy property in order to be able | 26 // If there is a pref, track its controlledBy and recommendedValue |
| 27 // to bring up the correct bubble. | 27 // properties in order to be able to bring up the correct bubble. |
| 28 if (this.pref) { | 28 if (this.pref) { |
| 29 Preferences.getInstance().addEventListener(this.pref, | 29 Preferences.getInstance().addEventListener( |
| 30 function(event) { | 30 this.pref, this.handlePrefChange.bind(this)); |
| 31 var controlledBy = event.value.controlledBy; | |
| 32 self.controlledBy = controlledBy ? controlledBy : null; | |
| 33 OptionsPage.hideBubble(); | |
| 34 }); | |
| 35 this.resetHandler = this.clearAssociatedPref_; | 31 this.resetHandler = this.clearAssociatedPref_; |
| 36 } | 32 } |
| 37 | 33 |
| 38 this.tabIndex = 0; | 34 this.tabIndex = 0; |
| 39 this.setAttribute('role', 'button'); | 35 this.setAttribute('role', 'button'); |
| 40 this.addEventListener('click', this); | 36 this.addEventListener('click', this); |
| 41 this.addEventListener('keydown', this); | 37 this.addEventListener('keydown', this); |
| 42 this.addEventListener('mousedown', this); | 38 this.addEventListener('mousedown', this); |
| 43 }, | 39 }, |
| 44 | 40 |
| 45 /** | 41 /** |
| 46 * The given handler will be called when the user clicks on the 'reset to | 42 * The given handler will be called when the user clicks on the 'reset to |
| 47 * recommended value' link shown in the indicator bubble. | 43 * recommended value' link shown in the indicator bubble. |
| 48 * @param {function()} handler The handler to be called. | 44 * @param {function()} handler The handler to be called. |
| 49 */ | 45 */ |
| 50 set resetHandler(handler) { | 46 set resetHandler(handler) { |
|
pneubeck (no reviews)
2012/10/04 18:56:11
Please make it clear in the comment with which 'th
bartfab (slow)
2012/10/04 19:17:15
Done.
| |
| 51 this.resetHandler_ = handler; | 47 this.resetHandler_ = handler; |
| 52 }, | 48 }, |
| 53 | 49 |
| 54 /** | 50 /** |
| 55 * Whether the indicator is currently showing a bubble. | 51 * Whether the indicator is currently showing a bubble. |
| 56 * @type {boolean} | 52 * @type {boolean} |
| 57 */ | 53 */ |
| 58 get showingBubble() { | 54 get showingBubble() { |
| 59 return !!this.showingBubble_; | 55 return !!this.showingBubble_; |
| 60 }, | 56 }, |
| 61 set showingBubble(showing) { | 57 set showingBubble(showing) { |
| 62 if (showing) | 58 if (showing) |
| 63 this.classList.add('showing-bubble'); | 59 this.classList.add('showing-bubble'); |
| 64 else | 60 else |
| 65 this.classList.remove('showing-bubble'); | 61 this.classList.remove('showing-bubble'); |
| 66 this.showingBubble_ = showing; | 62 this.showingBubble_ = showing; |
| 67 }, | 63 }, |
| 68 | 64 |
| 69 /** | 65 /** |
| 70 * Clears the preference associated with this indicator. | 66 * Clears the preference associated with this indicator. |
| 71 * @private | 67 * @private |
| 72 */ | 68 */ |
| 73 clearAssociatedPref_: function() { | 69 clearAssociatedPref_: function() { |
| 74 Preferences.clearPref(this.pref, this.dialogPref); | 70 Preferences.clearPref(this.pref, !this.dialogPref); |
| 71 }, | |
| 72 | |
| 73 /* Handle changes to the associated pref by hiding any currently visible | |
| 74 * bubble and updating the controlledBy property. | |
| 75 * @param {Event} event Pref change event. | |
| 76 */ | |
| 77 handlePrefChange: function(event) { | |
| 78 OptionsPage.hideBubble(); | |
| 79 if (this.type == 'radio') { | |
| 80 if (event.value.controlledBy) { | |
| 81 this.controlledBy = String(event.value.value) == this.value ? | |
| 82 event.value.controlledBy : null; | |
| 83 } else if (event.value.recommendedValue != undefined) { | |
| 84 this.controlledBy = | |
| 85 String(event.value.recommendedValue) == this.value ? | |
| 86 'hasRecommendation' : null; | |
| 87 } else { | |
| 88 this.controlledBy = null; | |
| 89 } | |
| 90 } else { | |
| 91 if (event.value.controlledBy) | |
| 92 this.controlledBy = event.value.controlledBy; | |
| 93 else if (event.value.recommendedValue != undefined) | |
| 94 this.controlledBy = 'hasRecommendation'; | |
| 95 else | |
| 96 this.controlledBy = null; | |
| 97 } | |
| 75 }, | 98 }, |
| 76 | 99 |
| 77 /** | 100 /** |
| 78 * Handle mouse and keyboard events, allowing the user to open and close a | 101 * Handle mouse and keyboard events, allowing the user to open and close a |
| 79 * bubble with further information. | 102 * bubble with further information. |
| 80 * @param {Event} event Mouse or keyboard event. | 103 * @param {Event} event Mouse or keyboard event. |
| 81 */ | 104 */ |
| 82 handleEvent: function(event) { | 105 handleEvent: function(event) { |
| 83 switch (event.type) { | 106 switch (event.type) { |
| 84 // Toggle the bubble on left click. Let any other clicks propagate. | 107 // Toggle the bubble on left click. Let any other clicks propagate. |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 113 /** | 136 /** |
| 114 * Open or close a bubble with further information about the pref. | 137 * Open or close a bubble with further information about the pref. |
| 115 * @private | 138 * @private |
| 116 */ | 139 */ |
| 117 toggleBubble_: function() { | 140 toggleBubble_: function() { |
| 118 if (this.showingBubble) { | 141 if (this.showingBubble) { |
| 119 OptionsPage.hideBubble(); | 142 OptionsPage.hideBubble(); |
| 120 } else { | 143 } else { |
| 121 var self = this; | 144 var self = this; |
| 122 | 145 |
| 123 // Work out the popup text. | 146 // Work out the bubble text. |
|
James Hawkins
2012/10/04 16:16:51
Can we change the wording from "Work out" to, say,
bartfab (slow)
2012/10/04 18:55:39
Done.
| |
| 124 defaultStrings = { | 147 defaultStrings = { |
| 125 'policy': loadTimeData.getString('controlledSettingPolicy'), | 148 'policy': loadTimeData.getString('controlledSettingPolicy'), |
| 126 'extension': loadTimeData.getString('controlledSettingExtension'), | 149 'extension': loadTimeData.getString('controlledSettingExtension'), |
| 127 'recommended': loadTimeData.getString('controlledSettingRecommended'), | 150 'recommended': loadTimeData.getString('controlledSettingRecommended'), |
| 151 'hasRecommendation': | |
| 152 loadTimeData.getString('controlledSettingHasRecommendation'), | |
| 128 }; | 153 }; |
| 129 | 154 |
| 130 // No controller, no popup. | 155 // No controller, no popup. |
|
pneubeck (no reviews)
2012/10/04 18:56:11
Nit: bubble
bartfab (slow)
2012/10/04 19:17:15
Done.
| |
| 131 if (!this.controlledBy || !(this.controlledBy in defaultStrings)) | 156 if (!this.controlledBy || !(this.controlledBy in defaultStrings)) |
| 132 return; | 157 return; |
| 133 | 158 |
| 134 var text = defaultStrings[this.controlledBy]; | 159 var text = defaultStrings[this.controlledBy]; |
| 135 | 160 |
| 136 // Apply text overrides. | 161 // Apply text overrides. |
| 137 if (this.hasAttribute('text' + this.controlledBy)) | 162 if (this.hasAttribute('text' + this.controlledBy)) |
| 138 text = this.getAttribute('text' + this.controlledBy); | 163 text = this.getAttribute('text' + this.controlledBy); |
| 139 | 164 |
| 140 // Create the DOM tree. | 165 // Create the DOM tree. |
|
pneubeck (no reviews)
2012/10/04 18:56:11
In general, instead of generating a DOM tree, I wo
bartfab (slow)
2012/10/04 19:17:15
Yes, this would be cleaner. I discussed this kind
| |
| 141 var content = document.createElement('div'); | 166 var content = document.createElement('div'); |
| 142 content.className = 'controlled-setting-bubble-content'; | 167 content.className = 'controlled-setting-bubble-content'; |
| 143 content.setAttribute('controlled-by', this.controlledBy); | 168 content.setAttribute('controlled-by', this.controlledBy); |
| 144 content.textContent = text; | 169 content.textContent = text; |
| 145 | 170 |
| 146 if (this.controlledBy == 'recommended' && this.resetHandler_) { | 171 if (this.controlledBy == 'hasRecommendation' && this.resetHandler_ && |
| 172 !this.readOnly) { | |
| 147 var container = document.createElement('div'); | 173 var container = document.createElement('div'); |
| 148 var action = document.createElement('button'); | 174 var action = document.createElement('button'); |
| 149 action.classList.add('link-button'); | 175 action.classList.add('link-button'); |
| 150 action.classList.add('controlled-setting-bubble-action'); | 176 action.classList.add('controlled-setting-bubble-action'); |
| 151 action.textContent = | 177 action.textContent = |
| 152 loadTimeData.getString('controlledSettingApplyRecommendation'); | 178 loadTimeData.getString('controlledSettingFollowRecommendation'); |
| 153 action.addEventListener('click', function(event) { | 179 action.addEventListener('click', function(event) { |
| 154 self.resetHandler_(); | 180 self.resetHandler_(); |
| 155 }); | 181 }); |
| 156 container.appendChild(action); | 182 container.appendChild(action); |
| 157 content.appendChild(container); | 183 content.appendChild(container); |
| 158 } | 184 } |
| 159 | 185 |
| 160 OptionsPage.showBubble(content, this); | 186 OptionsPage.showBubble(content, this); |
| 161 } | 187 } |
| 162 }, | 188 }, |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 173 * associated preference take effect in the settings UI immediately but are | 199 * associated preference take effect in the settings UI immediately but are |
| 174 * only actually committed when the user confirms the dialog. If the user | 200 * only actually committed when the user confirms the dialog. If the user |
| 175 * cancels the dialog instead, the changes are rolled back in the settings UI | 201 * cancels the dialog instead, the changes are rolled back in the settings UI |
| 176 * and never committed. | 202 * and never committed. |
| 177 * @type {boolean} | 203 * @type {boolean} |
| 178 */ | 204 */ |
| 179 cr.defineProperty(ControlledSettingIndicator, 'dialogPref', | 205 cr.defineProperty(ControlledSettingIndicator, 'dialogPref', |
| 180 cr.PropertyKind.BOOL_ATTR); | 206 cr.PropertyKind.BOOL_ATTR); |
| 181 | 207 |
| 182 /** | 208 /** |
| 183 * Whether the associated preference is controlled by a source other than the | 209 * The kind of input element that this indicator refers to. |
|
James Hawkins
2012/10/04 16:16:51
I think we need to make this more coupled to the e
bartfab (slow)
2012/10/04 18:55:39
I discussed this with Philipp at length. We think
pneubeck (no reviews)
2012/10/04 18:56:11
For comparison, I like the alternative in the oppo
| |
| 184 * user's setting (can be 'policy', 'extension', 'recommended' or unset). | 210 * @type {string} |
| 211 */ | |
| 212 cr.defineProperty(ControlledSettingIndicator, 'type', | |
| 213 cr.PropertyKind.ATTR); | |
| 214 | |
| 215 /** | |
| 216 * If this indicator refers to a radio button, the value of the associated | |
| 217 * preference that the radio button represents. | |
| 218 * @type {string} | |
| 219 */ | |
| 220 cr.defineProperty(ControlledSettingIndicator, 'value', | |
| 221 cr.PropertyKind.ATTR); | |
| 222 | |
| 223 /** | |
| 224 * The status of the associated preference: | |
| 225 * - 'policy': A specific value is enfoced by policy. | |
| 226 * - 'extension': A specific value is enforced by an extension. | |
| 227 * - 'recommended': A value is recommended by policy. The user could | |
| 228 * override this recommendation but has not done so. | |
| 229 * - 'hasRecommendation': A value is recommended by policy. The user has | |
| 230 * overridden this recommendation. | |
| 231 * - unset: The value is controlled by the user alone. | |
| 185 * @type {string} | 232 * @type {string} |
| 186 */ | 233 */ |
| 187 cr.defineProperty(ControlledSettingIndicator, 'controlledBy', | 234 cr.defineProperty(ControlledSettingIndicator, 'controlledBy', |
| 188 cr.PropertyKind.ATTR); | 235 cr.PropertyKind.ATTR); |
| 189 | 236 |
| 190 // Export. | 237 // Export. |
| 191 return { | 238 return { |
| 192 ControlledSettingIndicator: ControlledSettingIndicator | 239 ControlledSettingIndicator: ControlledSettingIndicator |
| 193 }; | 240 }; |
| 194 }); | 241 }); |
| OLD | NEW |