<!-- @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="../../bower_components/polymer/polymer.html"> <link rel="import" href="../../bower_components/paper-styles/default-theme.html"> <link rel="import" href="../../bower_components/paper-input/paper-input.html"> <link rel="import" href="../../bower_components/paper-menu-button/paper-menu-button.html"> <link rel="import" href="../../bower_components/paper-ripple/paper-ripple.html"> <link rel="import" href="../../bower_components/iron-a11y-keys-behavior/iron-a11y-keys-behavior.html"> <link rel="import" href="../../bower_components/iron-behaviors/iron-control-state.html"> <link rel="import" href="../../bower_components/iron-behaviors/iron-button-state.html"> <link rel="import" href="../../bower_components/iron-icons/iron-icons.html"> <link rel="import" href="../../bower_components/iron-icon/iron-icon.html"> <link rel="import" href="../../bower_components/iron-selector/iron-selectable.html"> <link rel="import" href="../../bower_components/iron-form-element-behavior/iron-form-element-behavior.html"> <link rel="import" href="../../bower_components/iron-validatable-behavior/iron-validatable-behavior.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. The child element with the class `dropdown-content` will be used as the dropdown menu. It could be a `paper-menu` or element that triggers `iron-select` when selecting its children. Example: <paper-dropdown-menu label="Your favourite pastry"> <paper-menu class="dropdown-content"> <paper-item>Croissant</paper-item> <paper-item>Donut</paper-item> <paper-item>Financier</paper-item> <paper-item>Madeleine</paper-item> </paper-menu> </paper-dropdown-menu> This example renders a dropdown menu with 4 options. Similarly to using `iron-select`, `iron-deselect` events will cause the current selection of the `paper-dropdown-menu` to be cleared. ### 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-input-search"> <style> :host { display: inline-block; position: relative; text-align: left; cursor: pointer; /* NOTE(cdata): Both values are needed, since some phones require the * value to be `transparent`. */ -webkit-tap-highlight-color: rgba(0,0,0,0); -webkit-tap-highlight-color: transparent; --paper-input-container-input: { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; max-width: 100%; box-sizing: border-box; /*cursor: pointer;*/ }; @apply(--paper-dropdown-menu); } :host([disabled]) { @apply(--paper-dropdown-menu-disabled); } :host([noink]) paper-ripple { display: none; } :host([no-label-float]) paper-ripple { top: 8px; } paper-ripple { top: 12px; left: 0px; bottom: 8px; right: 0px; @apply(--paper-dropdown-menu-ripple); } paper-menu-button { display: block; padding: 0; @apply(--paper-dropdown-menu-button); } paper-input { @apply(--paper-dropdown-menu-input); } iron-icon { /*color: var(--disabled-text-color);*/ color: #2196F3; @apply(--paper-dropdown-menu-icon); } </style> <template> <paper-menu-button id="menuButton" vertical-align="top" horizontal-align="left" vertical-offset="[[_computeMenuVerticalOffset(noLabelFloat)]]" disabled="[[disabled]]" no-animations="[[noAnimations]]" on-iron-select="_onIronSelect" on-iron-deselect="_onIronDeselect" opened="{{opened}}"> <div class="dropdown-trigger"> <!--<paper-ripple></paper-ripple>--> <paper-input id="inputField" invalid="[[invalid]]" value="{{inputValue}}" placeholder="[[placeholder]]" always-float-label="[[alwaysFloatLabel]]" no-label-float="[[noLabelFloat]]" label="[[label]]"> <iron-icon icon="search" prefix></iron-icon> <iron-icon icon="arrow-drop-down" suffix></iron-icon> </paper-input> </div> <content id="content" select=".dropdown-content"></content> </paper-menu-button> </template> </dom-module> <script> (function() { 'use strict'; Polymer({ is: 'paper-input-search', /** * Fired when the dropdown opens. * * @event paper-dropdown-open */ /** * Fired when the dropdown closes. * * @event paper-dropdown-close */ behaviors: [ Polymer.IronControlState, Polymer.IronButtonState, 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 }, /** * True if the dropdown is open. Otherwise, false. */ opened: { type: Boolean, notify: true, 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 }, inputValue: { type: String, value: undefined, observer: '_fireInputValue' }, fireInputValue: { type: Boolean, value: true, } }, listeners: { 'tap': '_onTap' }, keyBindings: { 'up down': 'open', 'esc': 'close' }, hostAttributes: { role: 'group', '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); } }, _fireInputValue: function() {//console.log(this.inputValue); if(this.fireInputValue) {//change NO DDL this.fire('paper-input-search_input-value', {inputValue: this.inputValue}); if(this.contentElement.selectedItem){ // this._setSelectedItem(null); this.contentElement.select(-1); // console.log("deselected"); } } this.fireInputValue = true; }, /** * 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) { // console.log("select"); this.fireInputValue = false; this._setSelectedItem(event.detail.item); this.inputValue = event.detail.item.label || event.detail.item.textContent.trim(); }, /** * A handler that is called when `iron-deselect` is fired. * * @param {CustomEvent} event An `iron-deselect` event. */ _onIronDeselect: function(event) { // console.log("deselect"); this.fireInputValue = false; 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(); } this.async(function(){this.$.inputField.$.input.focus();},200);//to improve // console.log(this.selectedItemLabel); // console.log(this.value); // console.log(this.$.inputField.value); // console.log(this.inputValue); }, /** * 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.textContent.trim(); // } // // this._setValue(value); // this._setSelectedItemLabel(value); // this.inputValue = selectedItem.label || selectedItem.textContent.trim(); // }, /** * 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; return noLabelFloat ? 46-4 : 46+8; // return 64; }, /** * Returns false if the element is required and does not have a selection, * and true otherwise. * @return {Boolean} true if `required` is false, or if `required` is true * and the element has a valid selection. */ _getValidity: function() { return this.disabled || !this.required || (this.required && this.value); } }); })(); </script>