OLD | NEW |
| (Empty) |
1 <!-- | |
2 @license | |
3 Copyright (c) 2015 The Polymer Project Authors. All rights reserved. | |
4 This code may only be used under the BSD style license found at http://polymer.g
ithub.io/LICENSE.txt | |
5 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt | |
6 The complete set of contributors may be found at http://polymer.github.io/CONTRI
BUTORS.txt | |
7 Code distributed by Google as part of the polymer project is also | |
8 subject to an additional IP rights grant found at http://polymer.github.io/PATEN
TS.txt | |
9 --> | |
10 | |
11 <link rel="import" href="../polymer/polymer.html"> | |
12 <link rel="import" href="../iron-validatable-behavior/iron-validatable-behavior.
html"> | |
13 | |
14 <script> | |
15 | |
16 /* | |
17 `<iron-input>` adds two-way binding and custom validators using `Polymer.IronVal
idatorBehavior` | |
18 to `<input>`. | |
19 | |
20 ### Two-way binding | |
21 | |
22 By default you can only get notified of changes to an `input`'s `value` due to u
ser input: | |
23 | |
24 <input value="{{myValue::input}}"> | |
25 | |
26 `iron-input` adds the `bind-value` property that mirrors the `value` property, a
nd can be used | |
27 for two-way data binding. `bind-value` will notify if it is changed either by us
er input or by script. | |
28 | |
29 <input is="iron-input" bind-value="{{myValue}}"> | |
30 | |
31 ### Custom validators | |
32 | |
33 You can use custom validators that implement `Polymer.IronValidatorBehavior` wit
h `<iron-input>`. | |
34 | |
35 <input is="iron-input" validator="my-custom-validator"> | |
36 | |
37 ### Stopping invalid input | |
38 | |
39 It may be desirable to only allow users to enter certain characters. You can use
the | |
40 `prevent-invalid-input` and `allowed-pattern` attributes together to accomplish
this. This feature | |
41 is separate from validation, and `allowed-pattern` does not affect how the input
is validated. | |
42 | |
43 <!-- only allow characters that match [0-9] --> | |
44 <input is="iron-input" prevent-invalid-input allowed-pattern="[0-9]"> | |
45 | |
46 @hero hero.svg | |
47 @demo demo/index.html | |
48 */ | |
49 | |
50 Polymer({ | |
51 | |
52 is: 'iron-input', | |
53 | |
54 extends: 'input', | |
55 | |
56 behaviors: [ | |
57 Polymer.IronValidatableBehavior | |
58 ], | |
59 | |
60 properties: { | |
61 | |
62 /** | |
63 * Use this property instead of `value` for two-way data binding. | |
64 */ | |
65 bindValue: { | |
66 observer: '_bindValueChanged', | |
67 type: String | |
68 }, | |
69 | |
70 /** | |
71 * Set to true to prevent the user from entering invalid input. The new in
put characters are | |
72 * matched with `allowedPattern` if it is set, otherwise it will use the `
pattern` attribute if | |
73 * set, or the `type` attribute (only supported for `type=number`). | |
74 */ | |
75 preventInvalidInput: { | |
76 type: Boolean | |
77 }, | |
78 | |
79 /** | |
80 * Regular expression to match valid input characters. | |
81 */ | |
82 allowedPattern: { | |
83 type: String | |
84 }, | |
85 | |
86 _previousValidInput: { | |
87 type: String, | |
88 value: '' | |
89 }, | |
90 | |
91 _patternAlreadyChecked: { | |
92 type: Boolean, | |
93 value: false | |
94 } | |
95 | |
96 }, | |
97 | |
98 listeners: { | |
99 'input': '_onInput', | |
100 'keypress': '_onKeypress' | |
101 }, | |
102 | |
103 get _patternRegExp() { | |
104 var pattern; | |
105 if (this.allowedPattern) { | |
106 pattern = new RegExp(this.allowedPattern); | |
107 } else if (this.pattern) { | |
108 pattern = new RegExp(this.pattern); | |
109 } else { | |
110 switch (this.type) { | |
111 case 'number': | |
112 pattern = /[0-9.,e-]/; | |
113 break; | |
114 } | |
115 } | |
116 return pattern; | |
117 }, | |
118 | |
119 ready: function() { | |
120 this.bindValue = this.value; | |
121 }, | |
122 | |
123 _bindValueChanged: function() { | |
124 if (this.value !== this.bindValue) { | |
125 this.value = !this.bindValue ? '' : this.bindValue; | |
126 } | |
127 // manually notify because we don't want to notify until after setting val
ue | |
128 this.fire('bind-value-changed', {value: this.bindValue}); | |
129 }, | |
130 | |
131 _onInput: function() { | |
132 // Need to validate each of the characters pasted if they haven't | |
133 // been validated inside `_onKeypress` already. | |
134 if (this.preventInvalidInput && !this._patternAlreadyChecked) { | |
135 var valid = this._checkPatternValidity(); | |
136 if (!valid) { | |
137 this.value = this._previousValidInput; | |
138 } | |
139 } | |
140 | |
141 this.bindValue = this.value; | |
142 this._previousValidInput = this.value; | |
143 this._patternAlreadyChecked = false; | |
144 }, | |
145 | |
146 _isPrintable: function(event) { | |
147 // What a control/printable character is varies wildly based on the browse
r. | |
148 // - most control characters (arrows, backspace) do not send a `keypress`
event | |
149 // in Chrome, but the *do* on Firefox | |
150 // - in Firefox, when they do send a `keypress` event, control chars have | |
151 // a charCode = 0, keyCode = xx (for ex. 40 for down arrow) | |
152 // - printable characters always send a keypress event. | |
153 // - in Firefox, printable chars always have a keyCode = 0. In Chrome, the
keyCode | |
154 // always matches the charCode. | |
155 // None of this makes any sense. | |
156 | |
157 // For these keys, ASCII code == browser keycode. | |
158 var anyNonPrintable = | |
159 (event.keyCode == 8) || // backspace | |
160 (event.keyCode == 13) || // enter | |
161 (event.keyCode == 27); // escape | |
162 | |
163 // For these keys, make sure it's a browser keycode and not an ASCII code. | |
164 var mozNonPrintable = | |
165 (event.keyCode == 19) || // pause | |
166 (event.keyCode == 20) || // caps lock | |
167 (event.keyCode == 45) || // insert | |
168 (event.keyCode == 46) || // delete | |
169 (event.keyCode == 144) || // num lock | |
170 (event.keyCode == 145) || // scroll lock | |
171 (event.keyCode > 32 && event.keyCode < 41) || // page up/down, end, ho
me, arrows | |
172 (event.keyCode > 111 && event.keyCode < 124); // fn keys | |
173 | |
174 return !anyNonPrintable && !(event.charCode == 0 && mozNonPrintable); | |
175 }, | |
176 | |
177 _onKeypress: function(event) { | |
178 if (!this.preventInvalidInput && this.type !== 'number') { | |
179 return; | |
180 } | |
181 var regexp = this._patternRegExp; | |
182 if (!regexp) { | |
183 return; | |
184 } | |
185 | |
186 // Handle special keys and backspace | |
187 if (event.metaKey || event.ctrlKey || event.altKey) | |
188 return; | |
189 | |
190 // Check the pattern either here or in `_onInput`, but not in both. | |
191 this._patternAlreadyChecked = true; | |
192 | |
193 var thisChar = String.fromCharCode(event.charCode); | |
194 if (this._isPrintable(event) && !regexp.test(thisChar)) { | |
195 event.preventDefault(); | |
196 } | |
197 }, | |
198 | |
199 _checkPatternValidity: function() { | |
200 var regexp = this._patternRegExp; | |
201 if (!regexp) { | |
202 return true; | |
203 } | |
204 for (var i = 0; i < this.value.length; i++) { | |
205 if (!regexp.test(this.value[i])) { | |
206 return false; | |
207 } | |
208 } | |
209 return true; | |
210 }, | |
211 | |
212 /** | |
213 * Returns true if `value` is valid. The validator provided in `validator` w
ill be used first, | |
214 * then any constraints. | |
215 * @return {boolean} True if the value is valid. | |
216 */ | |
217 validate: function() { | |
218 // Empty, non-required input is valid. | |
219 if (!this.required && this.value == '') { | |
220 this.invalid = false; | |
221 return true; | |
222 } | |
223 | |
224 var valid; | |
225 if (this.hasValidator()) { | |
226 valid = Polymer.IronValidatableBehavior.validate.call(this, this.value); | |
227 } else { | |
228 this.invalid = !this.validity.valid; | |
229 valid = this.validity.valid; | |
230 } | |
231 this.fire('iron-input-validate'); | |
232 return valid; | |
233 } | |
234 | |
235 }); | |
236 | |
237 /* | |
238 The `iron-input-validate` event is fired whenever `validate()` is called. | |
239 @event iron-input-validate | |
240 */ | |
241 | |
242 </script> | |
OLD | NEW |