diff options
Diffstat (limited to 'catapult/third_party/polymer/components/paper-dropdown-menu/paper-dropdown-menu.html')
-rw-r--r-- | catapult/third_party/polymer/components/paper-dropdown-menu/paper-dropdown-menu.html | 415 |
1 files changed, 415 insertions, 0 deletions
diff --git a/catapult/third_party/polymer/components/paper-dropdown-menu/paper-dropdown-menu.html b/catapult/third_party/polymer/components/paper-dropdown-menu/paper-dropdown-menu.html new file mode 100644 index 00000000..98ebeccf --- /dev/null +++ b/catapult/third_party/polymer/components/paper-dropdown-menu/paper-dropdown-menu.html @@ -0,0 +1,415 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../polymer/polymer.html"> +<link rel="import" href="../iron-a11y-keys-behavior/iron-a11y-keys-behavior.html"> +<link rel="import" href="../iron-behaviors/iron-button-state.html"> +<link rel="import" href="../iron-behaviors/iron-control-state.html"> +<link rel="import" href="../iron-form-element-behavior/iron-form-element-behavior.html"> +<link rel="import" href="../iron-icon/iron-icon.html"> +<link rel="import" href="../iron-validatable-behavior/iron-validatable-behavior.html"> +<link rel="import" href="../paper-input/paper-input.html"> +<link rel="import" href="../paper-menu-button/paper-menu-button.html"> +<link rel="import" href="../paper-ripple/paper-ripple.html"> +<link rel="import" href="../paper-styles/default-theme.html"> + +<link rel="import" href="paper-dropdown-menu-icons.html"> +<link rel="import" href="paper-dropdown-menu-shared-styles.html"> + +<!-- +Material design: [Dropdown menus](https://www.google.com/design/spec/components/buttons.html#buttons-dropdown-buttons) + +`paper-dropdown-menu` is similar to a native browser select element. +`paper-dropdown-menu` works with selectable content. The currently selected +item is displayed in the control. If no item is selected, the `label` is +displayed instead. + +Example: + + <paper-dropdown-menu label="Your favourite pastry"> + <paper-listbox class="dropdown-content"> + <paper-item>Croissant</paper-item> + <paper-item>Donut</paper-item> + <paper-item>Financier</paper-item> + <paper-item>Madeleine</paper-item> + </paper-listbox> + </paper-dropdown-menu> + +This example renders a dropdown menu with 4 options. + +The child element with the class `dropdown-content` is used as the dropdown +menu. This can be a [`paper-listbox`](paper-listbox), or any other or +element that acts like an [`iron-selector`](iron-selector). + +Specifically, the menu child must fire an +[`iron-select`](iron-selector#event-iron-select) event when one of its +children is selected, and an [`iron-deselect`](iron-selector#event-iron-deselect) +event when a child is deselected. The selected or deselected item must +be passed as the event's `detail.item` property. + +Applications can listen for the `iron-select` and `iron-deselect` events +to react when options are selected and deselected. + +### Styling + +The following custom properties and mixins are also available for styling: + +Custom property | Description | Default +----------------|-------------|---------- +`--paper-dropdown-menu` | A mixin that is applied to the element host | `{}` +`--paper-dropdown-menu-disabled` | A mixin that is applied to the element host when disabled | `{}` +`--paper-dropdown-menu-ripple` | A mixin that is applied to the internal ripple | `{}` +`--paper-dropdown-menu-button` | A mixin that is applied to the internal menu button | `{}` +`--paper-dropdown-menu-input` | A mixin that is applied to the internal paper input | `{}` +`--paper-dropdown-menu-icon` | A mixin that is applied to the internal icon | `{}` + +You can also use any of the `paper-input-container` and `paper-menu-button` +style mixins and custom properties to style the internal input and menu button +respectively. + +@group Paper Elements +@element paper-dropdown-menu +@hero hero.svg +@demo demo/index.html +--> + +<dom-module id="paper-dropdown-menu"> + <template> + <style include="paper-dropdown-menu-shared-styles"></style> + + <!-- this div fulfills an a11y requirement for combobox, do not remove --> + <span role="button"></span> + <paper-menu-button + id="menuButton" + vertical-align="[[verticalAlign]]" + horizontal-align="[[horizontalAlign]]" + dynamic-align="[[dynamicAlign]]" + vertical-offset="[[_computeMenuVerticalOffset(noLabelFloat)]]" + disabled="[[disabled]]" + no-animations="[[noAnimations]]" + on-iron-select="_onIronSelect" + on-iron-deselect="_onIronDeselect" + opened="{{opened}}" + close-on-activate + allow-outside-scroll="[[allowOutsideScroll]]" + restore-focus-on-close="[[restoreFocusOnClose]]"> + <div class="dropdown-trigger"> + <paper-ripple></paper-ripple> + <!-- paper-input has type="text" for a11y, do not remove --> + <paper-input + type="text" + invalid="[[invalid]]" + readonly + disabled="[[disabled]]" + value="[[selectedItemLabel]]" + placeholder="[[placeholder]]" + error-message="[[errorMessage]]" + always-float-label="[[alwaysFloatLabel]]" + no-label-float="[[noLabelFloat]]" + label="[[label]]"> + <iron-icon icon="paper-dropdown-menu:arrow-drop-down" suffix></iron-icon> + </paper-input> + </div> + <content id="content" select=".dropdown-content"></content> + </paper-menu-button> + </template> + + <script> + (function() { + 'use strict'; + + Polymer({ + is: 'paper-dropdown-menu', + + behaviors: [ + Polymer.IronButtonState, + Polymer.IronControlState, + Polymer.IronFormElementBehavior, + Polymer.IronValidatableBehavior + ], + + properties: { + /** + * The derived "label" of the currently selected item. This value + * is the `label` property on the selected item if set, or else the + * trimmed text content of the selected item. + */ + selectedItemLabel: { + type: String, + notify: true, + readOnly: true + }, + + /** + * The last selected item. An item is selected if the dropdown menu has + * a child with class `dropdown-content`, and that child triggers an + * `iron-select` event with the selected `item` in the `detail`. + * + * @type {?Object} + */ + selectedItem: { + type: Object, + notify: true, + readOnly: true + }, + + /** + * The value for this element that will be used when submitting in + * a form. It is read only, and will always have the same value + * as `selectedItemLabel`. + */ + value: { + type: String, + notify: true, + readOnly: true + }, + + /** + * The label for the dropdown. + */ + label: { + type: String + }, + + /** + * The placeholder for the dropdown. + */ + placeholder: { + type: String + }, + + /** + * The error message to display when invalid. + */ + errorMessage: { + type: String + }, + + /** + * True if the dropdown is open. Otherwise, false. + */ + opened: { + type: Boolean, + notify: true, + value: false, + observer: '_openedChanged' + }, + + /** + * By default, the dropdown will constrain scrolling on the page + * to itself when opened. + * Set to true in order to prevent scroll from being constrained + * to the dropdown when it opens. + */ + allowOutsideScroll: { + type: Boolean, + value: false + }, + + /** + * Set to true to disable the floating label. Bind this to the + * `<paper-input-container>`'s `noLabelFloat` property. + */ + noLabelFloat: { + type: Boolean, + value: false, + reflectToAttribute: true + }, + + /** + * Set to true to always float the label. Bind this to the + * `<paper-input-container>`'s `alwaysFloatLabel` property. + */ + alwaysFloatLabel: { + type: Boolean, + value: false + }, + + /** + * Set to true to disable animations when opening and closing the + * dropdown. + */ + noAnimations: { + type: Boolean, + value: false + }, + + /** + * The orientation against which to align the menu dropdown + * horizontally relative to the dropdown trigger. + */ + horizontalAlign: { + type: String, + value: 'right' + }, + + /** + * The orientation against which to align the menu dropdown + * vertically relative to the dropdown trigger. + */ + verticalAlign: { + type: String, + value: 'top' + }, + + /** + * If true, the `horizontalAlign` and `verticalAlign` properties will + * be considered preferences instead of strict requirements when + * positioning the dropdown and may be changed if doing so reduces + * the area of the dropdown falling outside of `fitInto`. + */ + dynamicAlign: { + type: Boolean + }, + + /** + * Whether focus should be restored to the dropdown when the menu closes. + */ + restoreFocusOnClose: { + type: Boolean, + value: true + }, + }, + + listeners: { + 'tap': '_onTap' + }, + + keyBindings: { + 'up down': 'open', + 'esc': 'close' + }, + + hostAttributes: { + role: 'combobox', + 'aria-autocomplete': 'none', + 'aria-haspopup': 'true' + }, + + observers: [ + '_selectedItemChanged(selectedItem)' + ], + + attached: function() { + // NOTE(cdata): Due to timing, a preselected value in a `IronSelectable` + // child will cause an `iron-select` event to fire while the element is + // still in a `DocumentFragment`. This has the effect of causing + // handlers not to fire. So, we double check this value on attached: + var contentElement = this.contentElement; + if (contentElement && contentElement.selectedItem) { + this._setSelectedItem(contentElement.selectedItem); + } + }, + + /** + * The content element that is contained by the dropdown menu, if any. + */ + get contentElement() { + return Polymer.dom(this.$.content).getDistributedNodes()[0]; + }, + + /** + * Show the dropdown content. + */ + open: function() { + this.$.menuButton.open(); + }, + + /** + * Hide the dropdown content. + */ + close: function() { + this.$.menuButton.close(); + }, + + /** + * A handler that is called when `iron-select` is fired. + * + * @param {CustomEvent} event An `iron-select` event. + */ + _onIronSelect: function(event) { + this._setSelectedItem(event.detail.item); + }, + + /** + * A handler that is called when `iron-deselect` is fired. + * + * @param {CustomEvent} event An `iron-deselect` event. + */ + _onIronDeselect: function(event) { + this._setSelectedItem(null); + }, + + /** + * A handler that is called when the dropdown is tapped. + * + * @param {CustomEvent} event A tap event. + */ + _onTap: function(event) { + if (Polymer.Gestures.findOriginalTarget(event) === this) { + this.open(); + } + }, + + /** + * Compute the label for the dropdown given a selected item. + * + * @param {Element} selectedItem A selected Element item, with an + * optional `label` property. + */ + _selectedItemChanged: function(selectedItem) { + var value = ''; + if (!selectedItem) { + value = ''; + } else { + value = selectedItem.label || selectedItem.getAttribute('label') || selectedItem.textContent.trim(); + } + + this._setValue(value); + this._setSelectedItemLabel(value); + }, + + /** + * Compute the vertical offset of the menu based on the value of + * `noLabelFloat`. + * + * @param {boolean} noLabelFloat True if the label should not float + * above the input, otherwise false. + */ + _computeMenuVerticalOffset: function(noLabelFloat) { + // NOTE(cdata): These numbers are somewhat magical because they are + // derived from the metrics of elements internal to `paper-input`'s + // template. The metrics will change depending on whether or not the + // input has a floating label. + return noLabelFloat ? -4 : 8; + }, + + /** + * Returns false if the element is required and does not have a selection, + * and true otherwise. + * @param {*=} _value Ignored. + * @return {boolean} true if `required` is false, or if `required` is true + * and the element has a valid selection. + */ + _getValidity: function(_value) { + return this.disabled || !this.required || (this.required && !!this.value); + }, + + _openedChanged: function() { + var openState = this.opened ? 'true' : 'false'; + var e = this.contentElement; + if (e) { + e.setAttribute('aria-expanded', openState); + } + } + }); + })(); + </script> +</dom-module> |