3
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
4
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
5
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
6
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
7
Code distributed by Google as part of the polymer project is also
8
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
11
<link rel="import" href="../polymer/polymer.html">
12
<link rel="import" href="../iron-a11y-keys-behavior/iron-a11y-keys-behavior.html">
13
<link rel="import" href="../iron-behaviors/iron-button-state.html">
14
<link rel="import" href="../iron-behaviors/iron-control-state.html">
15
<link rel="import" href="../iron-form-element-behavior/iron-form-element-behavior.html">
16
<link rel="import" href="../iron-icon/iron-icon.html">
17
<link rel="import" href="../iron-validatable-behavior/iron-validatable-behavior.html">
18
<link rel="import" href="../paper-input/paper-input.html">
19
<link rel="import" href="../paper-menu-button/paper-menu-button.html">
20
<link rel="import" href="../paper-ripple/paper-ripple.html">
21
<link rel="import" href="../paper-styles/default-theme.html">
23
<link rel="import" href="paper-dropdown-menu-icons.html">
24
<link rel="import" href="paper-dropdown-menu-shared-styles.html">
27
Material design: [Dropdown menus](https://www.google.com/design/spec/components/buttons.html#buttons-dropdown-buttons)
29
`paper-dropdown-menu` is similar to a native browser select element.
30
`paper-dropdown-menu` works with selectable content. The currently selected
31
item is displayed in the control. If no item is selected, the `label` is
36
<paper-dropdown-menu label="Your favourite pastry">
37
<paper-listbox class="dropdown-content">
38
<paper-item>Croissant</paper-item>
39
<paper-item>Donut</paper-item>
40
<paper-item>Financier</paper-item>
41
<paper-item>Madeleine</paper-item>
43
</paper-dropdown-menu>
45
This example renders a dropdown menu with 4 options.
47
The child element with the class `dropdown-content` is used as the dropdown
48
menu. This can be a [`paper-listbox`](paper-listbox), or any other or
49
element that acts like an [`iron-selector`](iron-selector).
51
Specifically, the menu child must fire an
52
[`iron-select`](iron-selector#event-iron-select) event when one of its
53
children is selected, and an [`iron-deselect`](iron-selector#event-iron-deselect)
54
event when a child is deselected. The selected or deselected item must
55
be passed as the event's `detail.item` property.
57
Applications can listen for the `iron-select` and `iron-deselect` events
58
to react when options are selected and deselected.
62
The following custom properties and mixins are also available for styling:
64
Custom property | Description | Default
65
----------------|-------------|----------
66
`--paper-dropdown-menu` | A mixin that is applied to the element host | `{}`
67
`--paper-dropdown-menu-disabled` | A mixin that is applied to the element host when disabled | `{}`
68
`--paper-dropdown-menu-ripple` | A mixin that is applied to the internal ripple | `{}`
69
`--paper-dropdown-menu-button` | A mixin that is applied to the internal menu button | `{}`
70
`--paper-dropdown-menu-input` | A mixin that is applied to the internal paper input | `{}`
71
`--paper-dropdown-menu-icon` | A mixin that is applied to the internal icon | `{}`
73
You can also use any of the `paper-input-container` and `paper-menu-button`
74
style mixins and custom properties to style the internal input and menu button
78
@element paper-dropdown-menu
83
<dom-module id="paper-dropdown-menu">
85
<style include="paper-dropdown-menu-shared-styles"></style>
87
<!-- this div fulfills an a11y requirement for combobox, do not remove -->
88
<div role="button"></div>
91
vertical-align="[[verticalAlign]]"
92
horizontal-align="[[horizontalAlign]]"
93
vertical-offset="[[_computeMenuVerticalOffset(noLabelFloat)]]"
94
disabled="[[disabled]]"
95
no-animations="[[noAnimations]]"
96
on-iron-select="_onIronSelect"
97
on-iron-deselect="_onIronDeselect"
99
<div class="dropdown-trigger">
100
<paper-ripple></paper-ripple>
101
<!-- paper-input has type="text" for a11y, do not remove -->
104
invalid="[[invalid]]"
106
disabled="[[disabled]]"
107
value="[[selectedItemLabel]]"
108
placeholder="[[placeholder]]"
109
error-message="[[errorMessage]]"
110
always-float-label="[[alwaysFloatLabel]]"
111
no-label-float="[[noLabelFloat]]"
113
<iron-icon icon="paper-dropdown-menu:arrow-drop-down" suffix></iron-icon>
116
<content id="content" select=".dropdown-content"></content>
125
is: 'paper-dropdown-menu',
128
Polymer.IronButtonState,
129
Polymer.IronControlState,
130
Polymer.IronFormElementBehavior,
131
Polymer.IronValidatableBehavior
136
* The derived "label" of the currently selected item. This value
137
* is the `label` property on the selected item if set, or else the
138
* trimmed text content of the selected item.
147
* The last selected item. An item is selected if the dropdown menu has
148
* a child with class `dropdown-content`, and that child triggers an
149
* `iron-select` event with the selected `item` in the `detail`.
160
* The value for this element that will be used when submitting in
161
* a form. It is read only, and will always have the same value
162
* as `selectedItemLabel`.
171
* The label for the dropdown.
178
* The placeholder for the dropdown.
185
* The error message to display when invalid.
192
* True if the dropdown is open. Otherwise, false.
198
observer: '_openedChanged'
202
* Set to true to disable the floating label. Bind this to the
203
* `<paper-input-container>`'s `noLabelFloat` property.
208
reflectToAttribute: true
212
* Set to true to always float the label. Bind this to the
213
* `<paper-input-container>`'s `alwaysFloatLabel` property.
221
* Set to true to disable animations when opening and closing the
230
* The orientation against which to align the menu dropdown
231
* horizontally relative to the dropdown trigger.
239
* The orientation against which to align the menu dropdown
240
* vertically relative to the dropdown trigger.
259
'aria-autocomplete': 'none',
260
'aria-haspopup': 'true'
264
'_selectedItemChanged(selectedItem)'
267
attached: function() {
268
// NOTE(cdata): Due to timing, a preselected value in a `IronSelectable`
269
// child will cause an `iron-select` event to fire while the element is
270
// still in a `DocumentFragment`. This has the effect of causing
271
// handlers not to fire. So, we double check this value on attached:
272
var contentElement = this.contentElement;
273
if (contentElement && contentElement.selectedItem) {
274
this._setSelectedItem(contentElement.selectedItem);
279
* The content element that is contained by the dropdown menu, if any.
281
get contentElement() {
282
return Polymer.dom(this.$.content).getDistributedNodes()[0];
286
* Show the dropdown content.
289
this.$.menuButton.open();
293
* Hide the dropdown content.
296
this.$.menuButton.close();
300
* A handler that is called when `iron-select` is fired.
302
* @param {CustomEvent} event An `iron-select` event.
304
_onIronSelect: function(event) {
305
this._setSelectedItem(event.detail.item);
309
* A handler that is called when `iron-deselect` is fired.
311
* @param {CustomEvent} event An `iron-deselect` event.
313
_onIronDeselect: function(event) {
314
this._setSelectedItem(null);
318
* A handler that is called when the dropdown is tapped.
320
* @param {CustomEvent} event A tap event.
322
_onTap: function(event) {
323
if (Polymer.Gestures.findOriginalTarget(event) === this) {
329
* Compute the label for the dropdown given a selected item.
331
* @param {Element} selectedItem A selected Element item, with an
332
* optional `label` property.
334
_selectedItemChanged: function(selectedItem) {
339
value = selectedItem.label || selectedItem.textContent.trim();
342
this._setValue(value);
343
this._setSelectedItemLabel(value);
347
* Compute the vertical offset of the menu based on the value of
350
* @param {boolean} noLabelFloat True if the label should not float
351
* above the input, otherwise false.
353
_computeMenuVerticalOffset: function(noLabelFloat) {
354
// NOTE(cdata): These numbers are somewhat magical because they are
355
// derived from the metrics of elements internal to `paper-input`'s
356
// template. The metrics will change depending on whether or not the
357
// input has a floating label.
358
return noLabelFloat ? -4 : 8;
362
* Returns false if the element is required and does not have a selection,
363
* and true otherwise.
364
* @param {*=} _value Ignored.
365
* @return {boolean} true if `required` is false, or if `required` is true
366
* and the element has a valid selection.
368
_getValidity: function(_value) {
369
return this.disabled || !this.required || (this.required && !!this.value);
372
_openedChanged: function() {
373
var openState = this.opened ? 'true' : 'false';
374
var e = this.contentElement;
376
e.setAttribute('aria-expanded', openState);