| OLD | NEW |
| (Empty) |
| 1 (function() { | |
| 2 'use strict'; | |
| 3 | |
| 4 Polymer({ | |
| 5 is: 'paper-dropdown-menu-light', | |
| 6 | |
| 7 behaviors: [ | |
| 8 Polymer.IronButtonState, | |
| 9 Polymer.IronControlState, | |
| 10 Polymer.PaperRippleBehavior, | |
| 11 Polymer.IronFormElementBehavior, | |
| 12 Polymer.IronValidatableBehavior | |
| 13 ], | |
| 14 | |
| 15 properties: { | |
| 16 /** | |
| 17 * The derived "label" of the currently selected item. This value | |
| 18 * is the `label` property on the selected item if set, or else the | |
| 19 * trimmed text content of the selected item. | |
| 20 */ | |
| 21 selectedItemLabel: { | |
| 22 type: String, | |
| 23 notify: true, | |
| 24 readOnly: true | |
| 25 }, | |
| 26 | |
| 27 /** | |
| 28 * The last selected item. An item is selected if the dropdown menu ha
s | |
| 29 * a child with class `dropdown-content`, and that child triggers an | |
| 30 * `iron-select` event with the selected `item` in the `detail`. | |
| 31 * | |
| 32 * @type {?Object} | |
| 33 */ | |
| 34 selectedItem: { | |
| 35 type: Object, | |
| 36 notify: true, | |
| 37 readOnly: true | |
| 38 }, | |
| 39 | |
| 40 /** | |
| 41 * The value for this element that will be used when submitting in | |
| 42 * a form. It is read only, and will always have the same value | |
| 43 * as `selectedItemLabel`. | |
| 44 */ | |
| 45 value: { | |
| 46 type: String, | |
| 47 notify: true, | |
| 48 readOnly: true, | |
| 49 observer: '_valueChanged', | |
| 50 }, | |
| 51 | |
| 52 /** | |
| 53 * The label for the dropdown. | |
| 54 */ | |
| 55 label: { | |
| 56 type: String | |
| 57 }, | |
| 58 | |
| 59 /** | |
| 60 * The placeholder for the dropdown. | |
| 61 */ | |
| 62 placeholder: { | |
| 63 type: String | |
| 64 }, | |
| 65 | |
| 66 /** | |
| 67 * True if the dropdown is open. Otherwise, false. | |
| 68 */ | |
| 69 opened: { | |
| 70 type: Boolean, | |
| 71 notify: true, | |
| 72 value: false, | |
| 73 observer: '_openedChanged' | |
| 74 }, | |
| 75 | |
| 76 /** | |
| 77 * By default, the dropdown will constrain scrolling on the page | |
| 78 * to itself when opened. | |
| 79 * Set to true in order to prevent scroll from being constrained | |
| 80 * to the dropdown when it opens. | |
| 81 */ | |
| 82 allowOutsideScroll: { | |
| 83 type: Boolean, | |
| 84 value: false | |
| 85 }, | |
| 86 | |
| 87 /** | |
| 88 * Set to true to disable the floating label. Bind this to the | |
| 89 * `<paper-input-container>`'s `noLabelFloat` property. | |
| 90 */ | |
| 91 noLabelFloat: { | |
| 92 type: Boolean, | |
| 93 value: false, | |
| 94 reflectToAttribute: true | |
| 95 }, | |
| 96 | |
| 97 /** | |
| 98 * Set to true to always float the label. Bind this to the | |
| 99 * `<paper-input-container>`'s `alwaysFloatLabel` property. | |
| 100 */ | |
| 101 alwaysFloatLabel: { | |
| 102 type: Boolean, | |
| 103 value: false | |
| 104 }, | |
| 105 | |
| 106 /** | |
| 107 * Set to true to disable animations when opening and closing the | |
| 108 * dropdown. | |
| 109 */ | |
| 110 noAnimations: { | |
| 111 type: Boolean, | |
| 112 value: false | |
| 113 }, | |
| 114 | |
| 115 /** | |
| 116 * The orientation against which to align the menu dropdown | |
| 117 * horizontally relative to the dropdown trigger. | |
| 118 */ | |
| 119 horizontalAlign: { | |
| 120 type: String, | |
| 121 value: 'right' | |
| 122 }, | |
| 123 | |
| 124 /** | |
| 125 * The orientation against which to align the menu dropdown | |
| 126 * vertically relative to the dropdown trigger. | |
| 127 */ | |
| 128 verticalAlign: { | |
| 129 type: String, | |
| 130 value: 'top' | |
| 131 }, | |
| 132 | |
| 133 hasContent: { | |
| 134 type: Boolean, | |
| 135 readOnly: true | |
| 136 } | |
| 137 }, | |
| 138 | |
| 139 listeners: { | |
| 140 'tap': '_onTap' | |
| 141 }, | |
| 142 | |
| 143 keyBindings: { | |
| 144 'up down': 'open', | |
| 145 'esc': 'close' | |
| 146 }, | |
| 147 | |
| 148 hostAttributes: { | |
| 149 tabindex: 0, | |
| 150 role: 'combobox', | |
| 151 'aria-autocomplete': 'none', | |
| 152 'aria-haspopup': 'true' | |
| 153 }, | |
| 154 | |
| 155 observers: [ | |
| 156 '_selectedItemChanged(selectedItem)' | |
| 157 ], | |
| 158 | |
| 159 attached: function() { | |
| 160 // NOTE(cdata): Due to timing, a preselected value in a `IronSelectabl
e` | |
| 161 // child will cause an `iron-select` event to fire while the element i
s | |
| 162 // still in a `DocumentFragment`. This has the effect of causing | |
| 163 // handlers not to fire. So, we double check this value on attached: | |
| 164 var contentElement = this.contentElement; | |
| 165 if (contentElement && contentElement.selectedItem) { | |
| 166 this._setSelectedItem(contentElement.selectedItem); | |
| 167 } | |
| 168 }, | |
| 169 | |
| 170 /** | |
| 171 * The content element that is contained by the dropdown menu, if any. | |
| 172 */ | |
| 173 get contentElement() { | |
| 174 return Polymer.dom(this.$.content).getDistributedNodes()[0]; | |
| 175 }, | |
| 176 | |
| 177 /** | |
| 178 * Show the dropdown content. | |
| 179 */ | |
| 180 open: function() { | |
| 181 this.$.menuButton.open(); | |
| 182 }, | |
| 183 | |
| 184 /** | |
| 185 * Hide the dropdown content. | |
| 186 */ | |
| 187 close: function() { | |
| 188 this.$.menuButton.close(); | |
| 189 }, | |
| 190 | |
| 191 /** | |
| 192 * A handler that is called when `iron-select` is fired. | |
| 193 * | |
| 194 * @param {CustomEvent} event An `iron-select` event. | |
| 195 */ | |
| 196 _onIronSelect: function(event) { | |
| 197 this._setSelectedItem(event.detail.item); | |
| 198 }, | |
| 199 | |
| 200 /** | |
| 201 * A handler that is called when `iron-deselect` is fired. | |
| 202 * | |
| 203 * @param {CustomEvent} event An `iron-deselect` event. | |
| 204 */ | |
| 205 _onIronDeselect: function(event) { | |
| 206 this._setSelectedItem(null); | |
| 207 }, | |
| 208 | |
| 209 /** | |
| 210 * A handler that is called when the dropdown is tapped. | |
| 211 * | |
| 212 * @param {CustomEvent} event A tap event. | |
| 213 */ | |
| 214 _onTap: function(event) { | |
| 215 if (Polymer.Gestures.findOriginalTarget(event) === this) { | |
| 216 this.open(); | |
| 217 } | |
| 218 }, | |
| 219 | |
| 220 /** | |
| 221 * Compute the label for the dropdown given a selected item. | |
| 222 * | |
| 223 * @param {Element} selectedItem A selected Element item, with an | |
| 224 * optional `label` property. | |
| 225 */ | |
| 226 _selectedItemChanged: function(selectedItem) { | |
| 227 var value = ''; | |
| 228 if (!selectedItem) { | |
| 229 value = ''; | |
| 230 } else { | |
| 231 value = selectedItem.label || selectedItem.getAttribute('label') ||
selectedItem.textContent.trim(); | |
| 232 } | |
| 233 | |
| 234 this._setValue(value); | |
| 235 this._setSelectedItemLabel(value); | |
| 236 }, | |
| 237 | |
| 238 /** | |
| 239 * Compute the vertical offset of the menu based on the value of | |
| 240 * `noLabelFloat`. | |
| 241 * | |
| 242 * @param {boolean} noLabelFloat True if the label should not float | |
| 243 * above the input, otherwise false. | |
| 244 */ | |
| 245 _computeMenuVerticalOffset: function(noLabelFloat) { | |
| 246 // NOTE(cdata): These numbers are somewhat magical because they are | |
| 247 // derived from the metrics of elements internal to `paper-input`'s | |
| 248 // template. The metrics will change depending on whether or not the | |
| 249 // input has a floating label. | |
| 250 return noLabelFloat ? -4 : 8; | |
| 251 }, | |
| 252 | |
| 253 /** | |
| 254 * Returns false if the element is required and does not have a selectio
n, | |
| 255 * and true otherwise. | |
| 256 * @param {*=} _value Ignored. | |
| 257 * @return {boolean} true if `required` is false, or if `required` is tr
ue | |
| 258 * and the element has a valid selection. | |
| 259 */ | |
| 260 _getValidity: function(_value) { | |
| 261 return this.disabled || !this.required || (this.required && !!this.val
ue); | |
| 262 }, | |
| 263 | |
| 264 _openedChanged: function() { | |
| 265 var openState = this.opened ? 'true' : 'false'; | |
| 266 var e = this.contentElement; | |
| 267 if (e) { | |
| 268 e.setAttribute('aria-expanded', openState); | |
| 269 } | |
| 270 }, | |
| 271 | |
| 272 _computeLabelClass: function(noLabelFloat, alwaysFloatLabel, hasContent)
{ | |
| 273 var cls = ''; | |
| 274 if (noLabelFloat === true) { | |
| 275 return hasContent ? 'label-is-hidden' : ''; | |
| 276 } | |
| 277 | |
| 278 if (hasContent || alwaysFloatLabel === true) { | |
| 279 cls += ' label-is-floating'; | |
| 280 } | |
| 281 return cls; | |
| 282 }, | |
| 283 | |
| 284 _valueChanged: function() { | |
| 285 // Only update if it's actually different. | |
| 286 if (this.$.input && this.$.input.textContent !== this.value) { | |
| 287 this.$.input.textContent = this.value; | |
| 288 } | |
| 289 this._setHasContent(!!this.value); | |
| 290 }, | |
| 291 }); | |
| 292 })(); | |
| OLD | NEW |