Home | History | Annotate | Download | only in options
      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
      3 // found in the LICENSE file.
      4 
      5 cr.define('options', function() {
      6   var Preferences = options.Preferences;
      7 
      8   /**
      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
     11    * policy or an extension.
     12    * @constructor
     13    * @extends {HTMLSpanElement}
     14    */
     15   var ControlledSettingIndicator = cr.ui.define('span');
     16 
     17   ControlledSettingIndicator.prototype = {
     18     __proto__: cr.ui.BubbleButton.prototype,
     19 
     20     /**
     21      * Decorates the base element to show the proper icon.
     22      */
     23     decorate: function() {
     24       cr.ui.BubbleButton.prototype.decorate.call(this);
     25       this.classList.add('controlled-setting-indicator');
     26 
     27       // If there is a pref, track its controlledBy and recommendedValue
     28       // properties in order to be able to bring up the correct bubble.
     29       if (this.pref) {
     30         Preferences.getInstance().addEventListener(
     31             this.pref, this.handlePrefChange.bind(this));
     32         this.resetHandler = this.clearAssociatedPref_;
     33       }
     34     },
     35 
     36     /**
     37      * The given handler will be called when the user clicks on the 'reset to
     38      * recommended value' link shown in the indicator bubble. The |this| object
     39      * will be the indicator itself.
     40      * @param {function()} handler The handler to be called.
     41      */
     42     set resetHandler(handler) {
     43       this.resetHandler_ = handler;
     44     },
     45 
     46     /**
     47      * Clears the preference associated with this indicator.
     48      * @private
     49      */
     50     clearAssociatedPref_: function() {
     51       Preferences.clearPref(this.pref, !this.dialogPref);
     52     },
     53 
     54     /* Handle changes to the associated pref by hiding any currently visible
     55      * bubble and updating the controlledBy property.
     56      * @param {Event} event Pref change event.
     57      */
     58     handlePrefChange: function(event) {
     59       OptionsPage.hideBubble();
     60       if (event.value.controlledBy) {
     61         this.controlledBy =
     62             !this.value || String(event.value.value) == this.value ?
     63             event.value.controlledBy : null;
     64       } else if (event.value.recommendedValue != undefined) {
     65         this.controlledBy =
     66             !this.value || String(event.value.recommendedValue) == this.value ?
     67             'hasRecommendation' : null;
     68       } else {
     69         this.controlledBy = null;
     70       }
     71     },
     72 
     73     /**
     74      * Open or close a bubble with further information about the pref.
     75      * @private
     76      */
     77     toggleBubble_: function() {
     78       if (this.showingBubble) {
     79         OptionsPage.hideBubble();
     80       } else {
     81         var self = this;
     82 
     83         // Construct the bubble text.
     84         if (this.hasAttribute('plural')) {
     85           var defaultStrings = {
     86             'policy': loadTimeData.getString('controlledSettingsPolicy'),
     87             'extension': loadTimeData.getString('controlledSettingsExtension'),
     88           };
     89         } else {
     90           var defaultStrings = {
     91             'policy': loadTimeData.getString('controlledSettingPolicy'),
     92             'extension': loadTimeData.getString('controlledSettingExtension'),
     93             'recommended':
     94                 loadTimeData.getString('controlledSettingRecommended'),
     95             'hasRecommendation':
     96                 loadTimeData.getString('controlledSettingHasRecommendation'),
     97           };
     98         }
     99 
    100         // No controller, no bubble.
    101         if (!this.controlledBy || !(this.controlledBy in defaultStrings))
    102           return;
    103 
    104         var text = defaultStrings[this.controlledBy];
    105 
    106         // Apply text overrides.
    107         if (this.hasAttribute('text' + this.controlledBy))
    108           text = this.getAttribute('text' + this.controlledBy);
    109 
    110         // Create the DOM tree.
    111         var content = document.createElement('div');
    112         content.className = 'controlled-setting-bubble-content';
    113         content.setAttribute('controlled-by', this.controlledBy);
    114         content.textContent = text;
    115 
    116         if (this.controlledBy == 'hasRecommendation' && this.resetHandler_ &&
    117             !this.readOnly) {
    118           var container = document.createElement('div');
    119           var action = document.createElement('button');
    120           action.classList.add('link-button');
    121           action.classList.add('controlled-setting-bubble-action');
    122           action.textContent =
    123               loadTimeData.getString('controlledSettingFollowRecommendation');
    124           action.addEventListener('click', function(event) {
    125             self.resetHandler_();
    126           });
    127           container.appendChild(action);
    128           content.appendChild(container);
    129         }
    130 
    131         OptionsPage.showBubble(content, this.image, this, this.location);
    132       }
    133     },
    134   };
    135 
    136   /**
    137    * The name of the associated preference.
    138    * @type {string}
    139    */
    140   cr.defineProperty(ControlledSettingIndicator, 'pref', cr.PropertyKind.ATTR);
    141 
    142   /**
    143    * Whether this indicator is part of a dialog. If so, changes made to the
    144    * associated preference take effect in the settings UI immediately but are
    145    * only actually committed when the user confirms the dialog. If the user
    146    * cancels the dialog instead, the changes are rolled back in the settings UI
    147    * and never committed.
    148    * @type {boolean}
    149    */
    150   cr.defineProperty(ControlledSettingIndicator, 'dialogPref',
    151                     cr.PropertyKind.BOOL_ATTR);
    152 
    153   /**
    154    * The value of the associated preference that the indicator represents. If
    155    * this is not set, the indicator will be visible whenever any value is
    156    * enforced or recommended. If it is set, the indicator will be visible only
    157    * when the enforced or recommended value matches the value it represents.
    158    * This allows multiple indicators to be created for a set of radio buttons,
    159    * ensuring that only one of them is visible at a time.
    160    */
    161   cr.defineProperty(ControlledSettingIndicator, 'value',
    162                     cr.PropertyKind.ATTR);
    163 
    164   /**
    165    * The status of the associated preference:
    166    * - 'policy':            A specific value is enfoced by policy.
    167    * - 'extension':         A specific value is enforced by an extension.
    168    * - 'recommended':       A value is recommended by policy. The user could
    169    *                        override this recommendation but has not done so.
    170    * - 'hasRecommendation': A value is recommended by policy. The user has
    171    *                        overridden this recommendation.
    172    * - unset:               The value is controlled by the user alone.
    173    * @type {string}
    174    */
    175   cr.defineProperty(ControlledSettingIndicator, 'controlledBy',
    176                     cr.PropertyKind.ATTR);
    177 
    178   // Export.
    179   return {
    180     ControlledSettingIndicator: ControlledSettingIndicator
    181   };
    182 });
    183