// Copyright (c) 2012 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; /** * A controlled setting indicator that can be placed on a setting as an * indicator that the value is controlled by some external entity such as * policy or an extension. * @constructor * @extends {HTMLSpanElement} */ var ControlledSettingIndicator = cr.ui.define('span'); ControlledSettingIndicator.prototype = { __proto__: HTMLSpanElement.prototype, /** * Decorates the base element to show the proper icon. */ decorate: function() { var self = this; // If there is a pref, track its controlledBy property in order to be able // to bring up the correct bubble. if (this.pref) { Preferences.getInstance().addEventListener(this.pref, function(event) { var controlledBy = event.value.controlledBy; self.controlledBy = controlledBy ? controlledBy : null; OptionsPage.hideBubble(); }); this.resetHandler = this.clearAssociatedPref_; } this.tabIndex = 0; this.setAttribute('role', 'button'); this.addEventListener('click', this); this.addEventListener('keydown', this); this.addEventListener('mousedown', this); }, /** * The given handler will be called when the user clicks on the 'reset to * recommended value' link shown in the indicator bubble. * @param {function()} handler The handler to be called. */ set resetHandler(handler) { this.resetHandler_ = handler; }, /** * Whether the indicator is currently showing a bubble. * @type {boolean} */ get showingBubble() { return !!this.showingBubble_; }, set showingBubble(showing) { if (showing) this.classList.add('showing-bubble'); else this.classList.remove('showing-bubble'); this.showingBubble_ = showing; }, /** * Clears the preference associated with this indicator. * @private */ clearAssociatedPref_: function() { Preferences.clearPref(this.pref, this.dialogPref); }, /** * Handle mouse and keyboard events, allowing the user to open and close a * bubble with further information. * @param {Event} event Mouse or keyboard event. */ handleEvent: function(event) { switch (event.type) { // Toggle the bubble on left click. Let any other clicks propagate. case 'click': if (event.button != 0) return; break; // Toggle the bubble when or is pressed. Let any other // key presses propagate. case 'keydown': switch (event.keyCode) { case 13: // Return. case 32: // Space. break; default: return; } break; // Blur focus when a mouse button is pressed, matching the behavior of // other Web UI elements. case 'mousedown': if (document.activeElement) document.activeElement.blur(); event.preventDefault(); return; } this.toggleBubble_(); event.preventDefault(); event.stopPropagation(); }, /** * Open or close a bubble with further information about the pref. * @private */ toggleBubble_: function() { if (this.showingBubble) { OptionsPage.hideBubble(); } else { var self = this; // Work out the popup text. defaultStrings = { 'policy': loadTimeData.getString('controlledSettingPolicy'), 'extension': loadTimeData.getString('controlledSettingExtension'), 'recommended': loadTimeData.getString('controlledSettingRecommended'), }; // No controller, no popup. if (!this.controlledBy || !(this.controlledBy in defaultStrings)) return; var text = defaultStrings[this.controlledBy]; // Apply text overrides. if (this.hasAttribute('text' + this.controlledBy)) text = this.getAttribute('text' + this.controlledBy); // Create the DOM tree. var content = document.createElement('div'); content.className = 'controlled-setting-bubble-content'; content.setAttribute('controlled-by', this.controlledBy); content.textContent = text; if (this.controlledBy == 'recommended' && this.resetHandler_) { var container = document.createElement('div'); var action = document.createElement('button'); action.classList.add('link-button'); action.classList.add('controlled-setting-bubble-action'); action.textContent = loadTimeData.getString('controlledSettingApplyRecommendation'); action.addEventListener('click', function(event) { self.resetHandler_(); }); container.appendChild(action); content.appendChild(container); } OptionsPage.showBubble(content, this); } }, }; /** * The name of the associated preference. * @type {string} */ cr.defineProperty(ControlledSettingIndicator, 'pref', cr.PropertyKind.ATTR); /** * Whether this indicator is part of a dialog. If so, changes made to the * associated preference take effect in the settings UI immediately but are * only actually committed when the user confirms the dialog. If the user * cancels the dialog instead, the changes are rolled back in the settings UI * and never committed. * @type {boolean} */ cr.defineProperty(ControlledSettingIndicator, 'dialogPref', cr.PropertyKind.BOOL_ATTR); /** * Whether the associated preference is controlled by a source other than the * user's setting (can be 'policy', 'extension', 'recommended' or unset). * @type {string} */ cr.defineProperty(ControlledSettingIndicator, 'controlledBy', cr.PropertyKind.ATTR); // Export. return { ControlledSettingIndicator: ControlledSettingIndicator }; });