blob: 8e31bfe6b2fe41c8241fd89c68a9e1ea564b69c9 [file] [log] [blame]
// Copyright 2015 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.
/**
* 'settings-dropdown-menu' is a control for displaying options
* in the settings.
*
* Example:
*
* <settings-dropdown-menu pref="{{prefs.foo}}">
* </settings-dropdown-menu>
*/
import '//resources/cr_elements/md_select_css.m.js';
import '//resources/cr_elements/policy/cr_policy_pref_indicator.m.js';
import '../settings_shared_css.js';
import '../settings_vars_css.js';
import {CrPolicyPrefBehavior} from '//resources/cr_elements/policy/cr_policy_pref_behavior.m.js';
import {assert} from '//resources/js/assert.m.js';
import {html, Polymer} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import {loadTimeData} from '../i18n_setup.js';
import {prefToString, stringToPrefValue} from '../prefs/pref_util.js';
import {PrefControlBehavior} from './pref_control_behavior.js';
/**
* The |name| is shown in the gui. The |value| us use to set or compare with
* the preference value.
* @typedef {{
* name: string,
* value: (number|string)
* }}
*/
let DropdownMenuOption;
/**
* @typedef {!Array<!DropdownMenuOption>}
*/
export let DropdownMenuOptionList;
Polymer({
is: 'settings-dropdown-menu',
_template: html`{__html_template__}`,
behaviors: [CrPolicyPrefBehavior, PrefControlBehavior],
properties: {
/**
* List of options for the drop-down menu.
* @type {!DropdownMenuOptionList}
*/
menuOptions: Array,
/** Whether the dropdown menu should be disabled. */
disabled: {
type: Boolean,
reflectToAttribute: true,
value: false,
},
/**
If this is a dictionary pref, this is the key for the item
we are interested in.
*/
prefKey: {
type: String,
value: null,
},
/**
* The value of the "custom" item.
* @private
*/
notFoundValue_: {
type: String,
value: 'SETTINGS_DROPDOWN_NOT_FOUND_ITEM',
readOnly: true,
},
/** Label for a11y purposes */
label: String,
},
observers: [
'updateSelected_(menuOptions, pref.value.*, prefKey)',
],
/** @override */
focus() {
this.$.dropdownMenu.focus();
},
/**
* Pass the selection change to the pref value.
* @private
*/
onChange_() {
const selected = this.$.dropdownMenu.value;
if (selected === this.notFoundValue_) {
return;
}
if (this.prefKey) {
assert(this.pref);
this.set(`pref.value.${this.prefKey}`, selected);
} else {
const prefValue = stringToPrefValue(selected, assert(this.pref));
if (prefValue !== undefined) {
this.set('pref.value', prefValue);
}
}
// settings-control-change only fires when the selection is changed to
// a valid property.
this.fire('settings-control-change');
},
/**
* Updates the selected item when the pref or menuOptions change.
* @private
*/
updateSelected_() {
if (this.menuOptions === undefined || this.pref === undefined ||
this.prefKey === undefined) {
return;
}
if (!this.menuOptions.length) {
return;
}
const prefValue = this.prefStringValue_();
const option = this.menuOptions.find(function(menuItem) {
return menuItem.value.toString() === prefValue;
});
// Wait for the dom-repeat to populate the <select> before setting
// <select>#value so the correct option gets selected.
this.async(() => {
this.$.dropdownMenu.value =
option === undefined ? this.notFoundValue_ : prefValue;
});
},
/**
* Gets the current value of the preference as a string.
* @return {string}
* @private
*/
prefStringValue_() {
if (this.prefKey) {
// Dictionary pref, values are always strings.
return this.pref.value[this.prefKey];
} else {
return prefToString(assert(this.pref));
}
},
/**
* @param {?DropdownMenuOptionList} menuOptions
* @param {string} prefValue
* @return {boolean}
* @private
*/
showNotFoundValue_(menuOptions, prefValue) {
if (menuOptions === undefined || prefValue === undefined) {
return false;
}
// Don't show "Custom" before the options load.
if (menuOptions === null || menuOptions.length === 0) {
return false;
}
const option = menuOptions.find((menuItem) => {
return menuItem.value.toString() === this.prefStringValue_();
});
return !option;
},
/**
* @return {boolean}
* @private
*/
shouldDisableMenu_() {
return this.disabled || this.isPrefEnforced() ||
this.menuOptions === undefined || this.menuOptions.length === 0;
},
});