Commit c9604416 authored by dpapad's avatar dpapad Committed by Commit bot

MD Settings: Migrating settings-dropdown-menu to use native select.

BUG=651513
CQ_INCLUDE_TRYBOTS=master.tryserver.chromium.linux:closure_compilation

Review-Url: https://codereview.chromium.org/2374253012
Cr-Commit-Position: refs/heads/master@{#422955}
parent cd20702d
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-dropdown-menu/paper-dropdown-menu-light.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-listbox/paper-listbox.html">
<link rel="import" href="/controls/pref_control_behavior.html">
<link rel="import" href="/i18n_setup.html">
<link rel="import" href="/md_select_css.html">
<link rel="import" href="/prefs/pref_util.html">
<link rel="import" href="/settings_shared_css.html">
<dom-module id="settings-dropdown-menu">
<template>
<style include="settings-shared"></style>
<paper-dropdown-menu-light id="dropdownMenu" label="[[menuLabel_]]"
on-iron-select="onSelect_" no-label-float vertical-align="auto"
disabled="[[shouldDisableMenu_(disabled, menuOptions.*)]]">
<paper-listbox class="dropdown-content" selected="{{selected_}}"
attr-for-selected="data-value">
<template is="dom-repeat" items="[[menuOptions]]" initial-count="5">
<button class="dropdown-item" role="option"
data-value$="[[item.value]]">
<style include="settings-shared md-select"></style>
<div class="select-wrapper">
<select id="dropdownMenu" on-change="onChange_" value="[[selected_]]"
disabled="[[shouldDisableMenu_(disabled, menuOptions)]]">
<template is="dom-repeat" items="[[menuOptions]]">
<option value="[[item.value]]" data-value$="[[item.value]]">
[[item.name]]
</button>
</option>
</template>
<button class="dropdown-item" role="option"
data-value$="[[notFoundValue_]]"
<option value="[[notFoundValue_]]"
hidden$="[[!isSelectedNotFound_(selected_)]]">
$i18n{custom}
</button>
</paper-listbox>
</paper-dropdown-menu-light>
</option>
</select>
<span class="select-underline"></span>
</div>
</template>
<script src="settings_dropdown_menu.js"></script>
</dom-module>
......@@ -30,16 +30,13 @@ Polymer({
is: 'settings-dropdown-menu',
properties: {
/** A text label for the drop-down menu. */
label: String,
/**
* List of options for the drop-down menu.
* @type {!DropdownMenuOptionList}
* @type {?DropdownMenuOptionList}
*/
menuOptions: {
type: Array,
value: function() { return []; },
value: null,
},
/** Whether the dropdown menu should be disabled. */
......@@ -49,15 +46,6 @@ Polymer({
value: false,
},
/**
* Either loading text or the label for the drop-down menu.
* @private
*/
menuLabel_: {
type: String,
value: function() { return loadTimeData.getString('loading'); },
},
/**
* The current selected value, as a string.
* @private
......@@ -79,40 +67,21 @@ Polymer({
],
observers: [
'checkSetup_(menuOptions)',
'updateSelected_(pref.value)',
'updateSelected_(menuOptions, pref.value)',
],
ready: function() {
this.checkSetup_(this.menuOptions);
},
/**
* Check to see if we have all the pieces needed to enable the control.
* @param {DropdownMenuOptionList} menuOptions
* @private
*/
checkSetup_: function(menuOptions) {
if (!this.menuOptions.length)
return;
// Do not set |menuLabel_| to a falsy value: http://goo.gl/OnKYko
// (paper-dropdown-menu#181).
this.menuLabel_ = this.label || ' ';
this.updateSelected_();
},
/**
* Pass the selection change to the pref value.
* @private
*/
onSelect_: function() {
if (!this.pref || this.selected_ == undefined ||
this.selected_ == this.notFoundValue_) {
onChange_: function() {
this.selected_ = this.$.dropdownMenu.value;
if (this.selected_ == this.notFoundValue_)
return;
}
var prefValue = Settings.PrefUtil.stringToPrefValue(
this.selected_, this.pref);
this.selected_, assert(this.pref));
if (prefValue !== undefined)
this.set('pref.value', prefValue);
},
......@@ -122,16 +91,21 @@ Polymer({
* @private
*/
updateSelected_: function() {
if (!this.pref || !this.menuOptions.length)
if (this.menuOptions === null || !this.menuOptions.length)
return;
var prefValue = this.pref.value;
var option = this.menuOptions.find(function(menuItem) {
return menuItem.value == prefValue;
});
if (option == undefined)
this.selected_ = this.notFoundValue_;
else
this.selected_ = Settings.PrefUtil.prefToString(this.pref);
// Need to wait for the dom-repeat to render, before assigning a value to
// |selected_|, otherwise select#value is not populated correctly.
this.async(function() {
this.selected_ = option == undefined ?
this.notFoundValue_ :
Settings.PrefUtil.prefToString(assert(this.pref));
}.bind(this));
},
/**
......@@ -148,6 +122,7 @@ Polymer({
* @private
*/
shouldDisableMenu_: function() {
return this.disabled || !this.menuOptions.length;
return this.disabled || this.menuOptions === null ||
this.menuOptions.length == 0;
},
});
......@@ -10,16 +10,25 @@ cr.define('settings_dropdown_menu', function() {
var dropdown;
/**
* The IronSelectable (paper-listbox) used internally by the dropdown
* menu.
* @type {Polymer.IronSelectableBehavior}
* The <select> used internally by the dropdown menu.
* @type {HTMLSelectElement}
*/
var selectable;
var selectElement;
function waitUntilDropdownUpdated() {
return new Promise(function(resolve) { dropdown.async(resolve); });
}
function simulateChangeEvent(value) {
selectElement.value = value;
selectElement.dispatchEvent(new CustomEvent('change'));
return waitUntilDropdownUpdated();
}
setup(function() {
PolymerTest.clearBody();
dropdown = document.createElement('settings-dropdown-menu');
selectable = dropdown.$$('paper-listbox');
selectElement = dropdown.$$('select');
document.body.appendChild(dropdown);
});
......@@ -34,19 +43,23 @@ cr.define('settings_dropdown_menu', function() {
{value: 300, name: 'Option 300'},
{value: 400, name: 'Option 400'}];
// IronSelectable uses a DOM observer, which uses a debouncer.
Polymer.dom.flush();
return waitUntilDropdownUpdated().then(function() {
// Initially selected item.
assertEquals('Option 100', selectable.selectedItem.textContent.trim());
assertEquals(
'Option 100',
selectElement.selectedOptions[0].textContent.trim());
// Selecting an item updates the pref.
selectable.selected = '200';
return simulateChangeEvent('200');
}).then(function() {
assertEquals(200, dropdown.pref.value);
// Updating the pref selects an item.
dropdown.set('pref.value', 400);
assertEquals('400', selectable.selected);
return waitUntilDropdownUpdated();
}).then(function() {
assertEquals('400', selectElement.value);
});
});
test('with string options', function testStringOptions() {
......@@ -60,18 +73,23 @@ cr.define('settings_dropdown_menu', function() {
{value: 'b', name: 'BBB'},
{value: 'c', name: 'CCC'},
{value: 'd', name: 'DDD'}];
Polymer.dom.flush();
return waitUntilDropdownUpdated().then(function() {
// Initially selected item.
assertEquals('CCC', selectable.selectedItem.textContent.trim());
assertEquals(
'CCC', selectElement.selectedOptions[0].textContent.trim());
// Selecting an item updates the pref.
selectable.selected = 'a';
return simulateChangeEvent('a');
}).then(function() {
assertEquals('a', dropdown.pref.value);
// Updating the pref selects an item.
dropdown.set('pref.value', 'b');
assertEquals('b', selectable.selected);
return waitUntilDropdownUpdated();
}).then(function() {
assertEquals('b', selectElement.value);
});
});
test('with custom value', function testCustomValue() {
......@@ -85,39 +103,44 @@ cr.define('settings_dropdown_menu', function() {
{value: 'b', name: 'BBB'},
{value: 'c', name: 'CCC'},
{value: 'd', name: 'DDD'}];
Polymer.dom.flush();
return waitUntilDropdownUpdated().then(function() {
// "Custom" initially selected.
assertEquals(dropdown.notFoundValue_, selectable.selected);
assertEquals(dropdown.notFoundValue_, selectElement.value);
// Pref should not have changed.
assertEquals('f', dropdown.pref.value);
});
});
function waitForTimeout(timeMs) {
return new Promise(function(resolve) { setTimeout(resolve, timeMs); });
}
test('delay setting options', function testDelayedOptions(done) {
test('delay setting options', function testDelayedOptions() {
dropdown.pref = {
key: 'test.number2',
type: chrome.settingsPrivate.PrefType.NUMBER,
value: 200,
};
setTimeout(function() {
assertEquals(
loadTimeData.getValue('loading'), dropdown.$.dropdownMenu.label);
console.log('running test');
return waitForTimeout(100).then(function() {
return waitUntilDropdownUpdated();
}).then(function() {
assertTrue(dropdown.$.dropdownMenu.disabled);
assertEquals(undefined, selectable.selected);
assertEquals('SETTINGS_DROPDOWN_NOT_FOUND_ITEM', selectElement.value);
dropdown.menuOptions = [{value: 100, name: 'Option 100'},
{value: 200, name: 'Option 200'},
{value: 300, name: 'Option 300'},
{value: 400, name: 'Option 400'}];
Polymer.dom.flush();
return waitUntilDropdownUpdated();
}).then(function() {
// Dropdown menu enables itself and selects the new menu option
// correpsonding to the pref value.
assertFalse(dropdown.$.dropdownMenu.disabled);
assertEquals('200', selectable.selected);
done();
}, 100);
assertEquals('200', selectElement.value);
});
});
});
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment