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