OLD | NEW |
(Empty) | |
| 1 |
| 2 |
| 3 (function() { |
| 4 |
| 5 var paperInput = CoreStyle.g.paperInput = CoreStyle.g.paperInput || {}; |
| 6 paperInput.focusedColor = '#4059a9'; |
| 7 paperInput.invalidColor = '#d34336'; |
| 8 |
| 9 Polymer('paper-input', { |
| 10 |
| 11 /** |
| 12 * The label for this input. It normally appears as grey text inside |
| 13 * the text input and disappears once the user enters text. |
| 14 * |
| 15 * @attribute label |
| 16 * @type string |
| 17 * @default '' |
| 18 */ |
| 19 label: '', |
| 20 |
| 21 /** |
| 22 * If true, the label will "float" above the text input once the |
| 23 * user enters text instead of disappearing. |
| 24 * |
| 25 * @attribute floatingLabel |
| 26 * @type boolean |
| 27 * @default false |
| 28 */ |
| 29 floatingLabel: false, |
| 30 |
| 31 /** |
| 32 * (multiline only) If set to a non-zero value, the height of this |
| 33 * text input will grow with the value changes until it is maxRows |
| 34 * rows tall. If the maximum size does not fit the value, the text |
| 35 * input will scroll internally. |
| 36 * |
| 37 * @attribute maxRows |
| 38 * @type number |
| 39 * @default 0 |
| 40 */ |
| 41 maxRows: 0, |
| 42 |
| 43 /** |
| 44 * The message to display if the input value fails validation. If this |
| 45 * is unset or the empty string, a default message is displayed depending |
| 46 * on the type of validation error. |
| 47 * |
| 48 * @attribute error |
| 49 * @type string |
| 50 */ |
| 51 error: '', |
| 52 |
| 53 focused: false, |
| 54 pressed: false, |
| 55 |
| 56 attached: function() { |
| 57 if (this.multiline) { |
| 58 this.resizeInput(); |
| 59 window.requestAnimationFrame(function() { |
| 60 this.$.underlineContainer.classList.add('animating'); |
| 61 }.bind(this)); |
| 62 } |
| 63 }, |
| 64 |
| 65 resizeInput: function() { |
| 66 var height = this.$.inputClone.getBoundingClientRect().height; |
| 67 var bounded = this.maxRows > 0 || this.rows > 0; |
| 68 if (bounded) { |
| 69 var minHeight = this.$.minInputHeight.getBoundingClientRect().height; |
| 70 var maxHeight = this.$.maxInputHeight.getBoundingClientRect().height; |
| 71 height = Math.max(minHeight, Math.min(height, maxHeight)); |
| 72 } |
| 73 this.$.inputContainer.style.height = height + 'px'; |
| 74 this.$.underlineContainer.style.top = height + 'px'; |
| 75 }, |
| 76 |
| 77 prepareLabelTransform: function() { |
| 78 var toRect = this.$.floatedLabelSpan.getBoundingClientRect(); |
| 79 var fromRect = this.$.labelSpan.getBoundingClientRect(); |
| 80 if (toRect.width !== 0) { |
| 81 this.$.label.cachedTransform = 'scale(' + (toRect.width / fromRect.wid
th) + ') ' + |
| 82 'translateY(' + (toRect.bottom - fromRect.bottom) + 'px)'; |
| 83 } |
| 84 }, |
| 85 |
| 86 toggleLabel: function(force) { |
| 87 var v = force !== undefined ? force : this.inputValue; |
| 88 |
| 89 if (!this.floatingLabel) { |
| 90 this.$.label.classList.toggle('hidden', v); |
| 91 } |
| 92 |
| 93 if (this.floatingLabel && !this.focused) { |
| 94 this.$.label.classList.toggle('hidden', v); |
| 95 this.$.floatedLabel.classList.toggle('hidden', !v); |
| 96 } |
| 97 }, |
| 98 |
| 99 rowsChanged: function() { |
| 100 if (this.multiline && !isNaN(parseInt(this.rows))) { |
| 101 this.$.minInputHeight.innerHTML = ''; |
| 102 for (var i = 0; i < this.rows; i++) { |
| 103 this.$.minInputHeight.appendChild(document.createElement('br')); |
| 104 } |
| 105 this.resizeInput(); |
| 106 } |
| 107 }, |
| 108 |
| 109 maxRowsChanged: function() { |
| 110 if (this.multiline && !isNaN(parseInt(this.maxRows))) { |
| 111 this.$.maxInputHeight.innerHTML = ''; |
| 112 for (var i = 0; i < this.maxRows; i++) { |
| 113 this.$.maxInputHeight.appendChild(document.createElement('br')); |
| 114 } |
| 115 this.resizeInput(); |
| 116 } |
| 117 }, |
| 118 |
| 119 inputValueChanged: function() { |
| 120 this.super(); |
| 121 |
| 122 if (this.multiline) { |
| 123 var escaped = this.inputValue.replace(/\n/gm, '<br>'); |
| 124 if (!escaped || escaped.lastIndexOf('<br>') === escaped.length - 4) { |
| 125 escaped += ' '; |
| 126 } |
| 127 this.$.inputCloneSpan.innerHTML = escaped; |
| 128 this.resizeInput(); |
| 129 } |
| 130 |
| 131 this.toggleLabel(); |
| 132 }, |
| 133 |
| 134 labelChanged: function() { |
| 135 if (this.floatingLabel && this.$.floatedLabel && this.$.label) { |
| 136 // If the element is created programmatically, labelChanged is called
before |
| 137 // binding. Run the measuring code in async so the DOM is ready. |
| 138 this.async(function() { |
| 139 this.prepareLabelTransform(); |
| 140 }); |
| 141 } |
| 142 }, |
| 143 |
| 144 placeholderChanged: function() { |
| 145 this.label = this.placeholder; |
| 146 }, |
| 147 |
| 148 inputFocusAction: function() { |
| 149 if (!this.pressed) { |
| 150 if (this.floatingLabel) { |
| 151 this.$.floatedLabel.classList.remove('hidden'); |
| 152 this.$.floatedLabel.classList.add('focused'); |
| 153 this.$.floatedLabel.classList.add('focusedColor'); |
| 154 } |
| 155 this.$.label.classList.add('hidden'); |
| 156 this.$.underlineHighlight.classList.add('focused'); |
| 157 this.$.caret.classList.add('focused'); |
| 158 |
| 159 this.super(arguments); |
| 160 } |
| 161 this.focused = true; |
| 162 }, |
| 163 |
| 164 shouldFloatLabel: function() { |
| 165 // if type = number, the input value is the empty string until a valid n
umber |
| 166 // is entered so we must do some hacks here |
| 167 return this.inputValue || (this.type === 'number' && !this.validity.vali
d); |
| 168 }, |
| 169 |
| 170 inputBlurAction: function() { |
| 171 this.super(arguments); |
| 172 |
| 173 this.$.underlineHighlight.classList.remove('focused'); |
| 174 this.$.caret.classList.remove('focused'); |
| 175 |
| 176 if (this.floatingLabel) { |
| 177 this.$.floatedLabel.classList.remove('focused'); |
| 178 this.$.floatedLabel.classList.remove('focusedColor'); |
| 179 if (!this.shouldFloatLabel()) { |
| 180 this.$.floatedLabel.classList.add('hidden'); |
| 181 } |
| 182 } |
| 183 |
| 184 // type = number hack. see core-input for more info |
| 185 if (!this.shouldFloatLabel()) { |
| 186 this.$.label.classList.remove('hidden'); |
| 187 this.$.label.classList.add('animating'); |
| 188 this.async(function() { |
| 189 this.$.label.style.webkitTransform = 'none'; |
| 190 this.$.label.style.transform = 'none'; |
| 191 }); |
| 192 } |
| 193 |
| 194 this.focused = false; |
| 195 }, |
| 196 |
| 197 downAction: function(e) { |
| 198 if (this.disabled) { |
| 199 return; |
| 200 } |
| 201 |
| 202 if (this.focused) { |
| 203 return; |
| 204 } |
| 205 |
| 206 this.pressed = true; |
| 207 var rect = this.$.underline.getBoundingClientRect(); |
| 208 var right = e.x - rect.left; |
| 209 this.$.underlineHighlight.style.webkitTransformOriginX = right + 'px'; |
| 210 this.$.underlineHighlight.style.transformOriginX = right + 'px'; |
| 211 this.$.underlineHighlight.classList.remove('focused'); |
| 212 this.underlineAsync = this.async(function() { |
| 213 this.$.underlineHighlight.classList.add('pressed'); |
| 214 }, null, 200); |
| 215 |
| 216 // No caret animation if there is text in the input. |
| 217 if (!this.inputValue) { |
| 218 this.$.caret.classList.remove('focused'); |
| 219 } |
| 220 }, |
| 221 |
| 222 upAction: function(e) { |
| 223 if (this.disabled) { |
| 224 return; |
| 225 } |
| 226 |
| 227 if (!this.pressed) { |
| 228 return; |
| 229 } |
| 230 |
| 231 // if a touchevent caused the up, the synthentic mouseevents will blur |
| 232 // the input, make sure to prevent those from being generated. |
| 233 if (e._source === 'touch') { |
| 234 e.preventDefault(); |
| 235 } |
| 236 |
| 237 if (this.underlineAsync) { |
| 238 clearTimeout(this.underlineAsync); |
| 239 this.underlineAsync = null; |
| 240 } |
| 241 |
| 242 // Focus the input here to bring up the virtual keyboard. |
| 243 this.$.input.focus(); |
| 244 this.pressed = false; |
| 245 this.animating = true; |
| 246 |
| 247 this.$.underlineHighlight.classList.remove('pressed'); |
| 248 this.$.underlineHighlight.classList.add('animating'); |
| 249 this.async(function() { |
| 250 this.$.underlineHighlight.classList.add('focused'); |
| 251 }); |
| 252 |
| 253 // No caret animation if there is text in the input. |
| 254 if (!this.inputValue) { |
| 255 this.$.caret.classList.add('animating'); |
| 256 this.async(function() { |
| 257 this.$.caret.classList.add('focused'); |
| 258 }, null, 100); |
| 259 } |
| 260 |
| 261 if (this.floatingLabel) { |
| 262 this.$.label.classList.add('focusedColor'); |
| 263 this.$.label.classList.add('animating'); |
| 264 if (!this.$.label.cachedTransform) { |
| 265 this.prepareLabelTransform(); |
| 266 } |
| 267 this.$.label.style.webkitTransform = this.$.label.cachedTransform; |
| 268 this.$.label.style.transform = this.$.label.cachedTransform; |
| 269 } |
| 270 }, |
| 271 |
| 272 keydownAction: function() { |
| 273 this.super(); |
| 274 |
| 275 // more type = number hacks. see core-input for more info |
| 276 if (this.type === 'number') { |
| 277 this.async(function() { |
| 278 if (!this.inputValue) { |
| 279 this.toggleLabel(!this.validity.valid); |
| 280 } |
| 281 }); |
| 282 } |
| 283 }, |
| 284 |
| 285 keypressAction: function() { |
| 286 if (this.animating) { |
| 287 this.transitionEndAction(); |
| 288 } |
| 289 }, |
| 290 |
| 291 transitionEndAction: function(e) { |
| 292 this.animating = false; |
| 293 if (this.pressed) { |
| 294 return; |
| 295 } |
| 296 |
| 297 if (this.focused) { |
| 298 |
| 299 if (this.floatingLabel || this.inputValue) { |
| 300 this.$.label.classList.add('hidden'); |
| 301 } |
| 302 |
| 303 if (this.floatingLabel) { |
| 304 this.$.label.classList.remove('focusedColor'); |
| 305 this.$.label.classList.remove('animating'); |
| 306 this.$.floatedLabel.classList.remove('hidden'); |
| 307 this.$.floatedLabel.classList.add('focused'); |
| 308 this.$.floatedLabel.classList.add('focusedColor'); |
| 309 } |
| 310 |
| 311 this.async(function() { |
| 312 this.$.underlineHighlight.classList.remove('animating'); |
| 313 this.$.caret.classList.remove('animating'); |
| 314 }, null, 100); |
| 315 |
| 316 } else { |
| 317 |
| 318 this.$.label.classList.remove('animating'); |
| 319 |
| 320 } |
| 321 } |
| 322 |
| 323 }); |
| 324 |
| 325 }()); |
| 326 |
| 327 |
OLD | NEW |