1 2 3 Polymer('core-input', { 4 publish: { 5 /** 6 * Placeholder text that hints to the user what can be entered in 7 * the input. 8 * 9 * @attribute placeholder 10 * @type string 11 * @default '' 12 */ 13 placeholder: '', 14 15 /** 16 * If true, this input cannot be focused and the user cannot change 17 * its value. 18 * 19 * @attribute disabled 20 * @type boolean 21 * @default false 22 */ 23 disabled: false, 24 25 /** 26 * If true, the user cannot modify the value of the input. 27 * 28 * @attribute readonly 29 * @type boolean 30 * @default false 31 */ 32 readonly: false, 33 34 /** 35 * If true, this input will automatically gain focus on page load. 36 * 37 * @attribute autofocus 38 * @type boolean 39 * @default false 40 */ 41 autofocus: false, 42 43 /** 44 * If true, this input accepts multi-line input like a `<textarea>` 45 * 46 * @attribute multiline 47 * @type boolean 48 * @default false 49 */ 50 multiline: false, 51 52 /** 53 * (multiline only) The height of this text input in rows. The input 54 * will scroll internally if more input is entered beyond the size 55 * of the component. This property is meaningless if multiline is 56 * false. You can also set this property to "fit" and size the 57 * component with CSS to make the input fit the CSS size. 58 * 59 * @attribute rows 60 * @type number|'fit' 61 * @default 'fit' 62 */ 63 rows: 'fit', 64 65 /** 66 * The current value of this input. Changing inputValue programmatically 67 * will cause value to be out of sync. Instead, change value directly 68 * or call commit() after changing inputValue. 69 * 70 * @attribute inputValue 71 * @type string 72 * @default '' 73 */ 74 inputValue: '', 75 76 /** 77 * The value of the input committed by the user, either by changing the 78 * inputValue and blurring the input, or by hitting the `enter` key. 79 * 80 * @attribute value 81 * @type string 82 * @default '' 83 */ 84 value: '', 85 86 /** 87 * Set the input type. Not supported for `multiline`. 88 * 89 * @attribute type 90 * @type string 91 * @default text 92 */ 93 type: 'text', 94 95 /** 96 * If true, the input is invalid if its value is null. 97 * 98 * @attribute required 99 * @type boolean 100 * @default false 101 */ 102 required: false, 103 104 /** 105 * A regular expression to validate the input value against. See 106 * https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/HTML5/Constraint_validation#Validation-related_attributes 107 * for more info. Not supported if `multiline` is true. 108 * 109 * @attribute pattern 110 * @type string 111 * @default '.*' 112 */ 113 // FIXME(yvonne): The default is set to .* because we can't bind to pattern such 114 // that the attribute is unset if pattern is null. 115 pattern: '.*', 116 117 /** 118 * If set, the input is invalid if the value is less than this property. See 119 * https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/HTML5/Constraint_validation#Validation-related_attributes 120 * for more info. Not supported if `multiline` is true. 121 * 122 * @attribute min 123 */ 124 min: null, 125 126 /** 127 * If set, the input is invalid if the value is greater than this property. See 128 * https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/HTML5/Constraint_validation#Validation-related_attributes 129 * for more info. Not supported if `multiline` is true. 130 * 131 * @attribute max 132 */ 133 max: null, 134 135 /** 136 * If set, the input is invalid if the value is not `min` plus an integral multiple 137 * of this property. See 138 * https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/HTML5/Constraint_validation#Validation-related_attributes 139 * for more info. Not supported if `multiline` is true. 140 * 141 * @attribute step 142 */ 143 step: null, 144 145 /** 146 * The maximum length of the input value. 147 * 148 * @attribute maxlength 149 * @type number 150 */ 151 maxlength: null, 152 153 /** 154 * If this property is true, the text input's inputValue failed validation. 155 * 156 * @attribute invalid 157 * @type boolean 158 * @default false 159 */ 160 invalid: false 161 }, 162 163 ready: function() { 164 this.handleTabindex(this.getAttribute('tabindex')); 165 }, 166 167 invalidChanged: function() { 168 this.classList.toggle('invalid', this.invalid); 169 this.fire('input-'+ (this.invalid ? 'invalid' : 'valid'), {value: this.inputValue}); 170 }, 171 172 inputValueChanged: function() { 173 this.updateValidity_(); 174 }, 175 176 valueChanged: function() { 177 this.inputValue = this.value; 178 }, 179 180 requiredChanged: function() { 181 this.updateValidity_(); 182 }, 183 184 attributeChanged: function(attr, oldVal, curVal) { 185 if (attr === 'tabindex') { 186 this.handleTabindex(curVal); 187 } 188 }, 189 190 handleTabindex: function(tabindex) { 191 if (tabindex > 0) { 192 this.$.input.setAttribute('tabindex', -1); 193 } else { 194 this.$.input.removeAttribute('tabindex'); 195 } 196 }, 197 198 /** 199 * Commits the inputValue to value. 200 * 201 * @method commit 202 */ 203 commit: function() { 204 this.value = this.inputValue; 205 }, 206 207 updateValidity_: function() { 208 if (this.$.input.willValidate) { 209 this.invalid = !this.$.input.validity.valid; 210 } 211 }, 212 213 keydownAction: function() { 214 // for type = number, the value is the empty string unless the input is a valid number. 215 // FIXME(yvonne): check other types 216 if (this.type === 'number') { 217 this.async(function() { 218 this.updateValidity_(); 219 }); 220 } 221 }, 222 223 inputChangeAction: function() { 224 this.commit(); 225 if (!window.ShadowDOMPolyfill) { 226 // re-fire event that does not bubble across shadow roots 227 this.fire('change', null, this); 228 } 229 }, 230 231 focusAction: function(e) { 232 if (this.getAttribute('tabindex') > 0) { 233 // Forward focus to the inner input if tabindex is set on the element 234 // This will not cause an infinite loop because focus will not fire on the <input> 235 // again if it's already focused. 236 this.$.input.focus(); 237 } 238 }, 239 240 inputFocusAction: function(e) { 241 if (window.ShadowDOMPolyfill) { 242 // re-fire non-bubbling event if polyfill 243 this.fire('focus', null, this, false); 244 } 245 }, 246 247 inputBlurAction: function() { 248 if (window.ShadowDOMPolyfill) { 249 // re-fire non-bubbling event 250 this.fire('blur', null, this, false); 251 } 252 }, 253 254 blur: function() { 255 // forward blur method to the internal input / textarea element 256 this.$.input.blur(); 257 }, 258 259 click: function() { 260 // forward click method to the internal input / textarea element 261 this.$.input.click(); 262 }, 263 264 focus: function() { 265 // forward focus method to the internal input / textarea element 266 this.$.input.focus(); 267 }, 268 269 select: function() { 270 // forward select method to the internal input / textarea element 271 this.$.input.focus(); 272 }, 273 274 setSelectionRange: function(selectionStart, selectionEnd, selectionDirection) { 275 // forward setSelectionRange method to the internal input / textarea element 276 this.$.input.setSelectionRange(selectionStart, selectionEnd, selectionDirection); 277 }, 278 279 setRangeText: function(replacement, start, end, selectMode) { 280 // forward setRangeText method to the internal input element 281 if (!this.multiline) { 282 this.$.input.setRangeText(replacement, start, end, selectMode); 283 } 284 }, 285 286 stepDown: function(n) { 287 // forward stepDown method to the internal input element 288 if (!this.multiline) { 289 this.$.input.stepDown(n); 290 } 291 }, 292 293 stepUp: function(n) { 294 // forward stepUp method to the internal input element 295 if (!this.multiline) { 296 this.$.input.stepUp(n); 297 } 298 }, 299 300 get willValidate() { 301 return this.$.input.willValidate; 302 }, 303 304 get validity() { 305 return this.$.input.validity; 306 }, 307 308 get validationMessage() { 309 return this.$.input.validationMessage; 310 }, 311 312 checkValidity: function() { 313 var r = this.$.input.checkValidity(); 314 this.updateValidity_(); 315 return r; 316 }, 317 318 setCustomValidity: function(message) { 319 this.$.input.setCustomValidity(message); 320 this.updateValidity_(); 321 } 322 323 }); 324