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