ApplicationImpl cleanup, part 1:
[chromium-blink-merge.git] / third_party / polymer / v1_0 / components-chromium / iron-input / iron-input-extracted.js
blob7828cf48d59f37a92dbc48c301067f1ed4ef97f8
3 /*
4 `<iron-input>` adds two-way binding and custom validators using `Polymer.IronValidatorBehavior`
5 to `<input>`.
7 ### Two-way binding
9 By default you can only get notified of changes to an `input`'s `value` due to user input:
11 <input value="{{myValue::input}}">
13 `iron-input` adds the `bind-value` property that mirrors the `value` property, and can be used
14 for two-way data binding. `bind-value` will notify if it is changed either by user input or by script.
16 <input is="iron-input" bind-value="{{myValue}}">
18 ### Custom validators
20 You can use custom validators that implement `Polymer.IronValidatorBehavior` with `<iron-input>`.
22 <input is="iron-input" validator="my-custom-validator">
24 ### Stopping invalid input
26 It may be desirable to only allow users to enter certain characters. You can use the
27 `prevent-invalid-input` and `allowed-pattern` attributes together to accomplish this. This feature
28 is separate from validation, and `allowed-pattern` does not affect how the input is validated.
30 <!-- only allow characters that match [0-9] -->
31 <input is="iron-input" prevent-invalid-input allowed-pattern="[0-9]">
33 @hero hero.svg
34 @demo demo/index.html
37 Polymer({
39 is: 'iron-input',
41 extends: 'input',
43 behaviors: [
44 Polymer.IronValidatableBehavior
47 properties: {
49 /**
50 * Use this property instead of `value` for two-way data binding.
52 bindValue: {
53 observer: '_bindValueChanged',
54 type: String
57 /**
58 * Set to true to prevent the user from entering invalid input. The new input characters are
59 * matched with `allowedPattern` if it is set, otherwise it will use the `pattern` attribute if
60 * set, or the `type` attribute (only supported for `type=number`).
62 preventInvalidInput: {
63 type: Boolean
66 /**
67 * Regular expression to match valid input characters.
69 allowedPattern: {
70 type: String
73 _previousValidInput: {
74 type: String,
75 value: ''
78 _patternAlreadyChecked: {
79 type: Boolean,
80 value: false
85 listeners: {
86 'input': '_onInput',
87 'keypress': '_onKeypress'
90 get _patternRegExp() {
91 var pattern;
92 if (this.allowedPattern) {
93 pattern = new RegExp(this.allowedPattern);
94 } else if (this.pattern) {
95 pattern = new RegExp(this.pattern);
96 } else {
97 switch (this.type) {
98 case 'number':
99 pattern = /[0-9.,e-]/;
100 break;
103 return pattern;
106 ready: function() {
107 this.bindValue = this.value;
110 _bindValueChanged: function() {
111 if (this.value !== this.bindValue) {
112 this.value = !this.bindValue ? '' : this.bindValue;
114 // manually notify because we don't want to notify until after setting value
115 this.fire('bind-value-changed', {value: this.bindValue});
118 _onInput: function() {
119 // Need to validate each of the characters pasted if they haven't
120 // been validated inside `_onKeypress` already.
121 if (this.preventInvalidInput && !this._patternAlreadyChecked) {
122 var valid = this._checkPatternValidity();
123 if (!valid) {
124 this.value = this._previousValidInput;
128 this.bindValue = this.value;
129 this._previousValidInput = this.value;
130 this._patternAlreadyChecked = false;
133 _isPrintable: function(event) {
134 // What a control/printable character is varies wildly based on the browser.
135 // - most control characters (arrows, backspace) do not send a `keypress` event
136 // in Chrome, but the *do* on Firefox
137 // - in Firefox, when they do send a `keypress` event, control chars have
138 // a charCode = 0, keyCode = xx (for ex. 40 for down arrow)
139 // - printable characters always send a keypress event.
140 // - in Firefox, printable chars always have a keyCode = 0. In Chrome, the keyCode
141 // always matches the charCode.
142 // None of this makes any sense.
144 // For these keys, ASCII code == browser keycode.
145 var anyNonPrintable =
146 (event.keyCode == 8) || // backspace
147 (event.keyCode == 13) || // enter
148 (event.keyCode == 27); // escape
150 // For these keys, make sure it's a browser keycode and not an ASCII code.
151 var mozNonPrintable =
152 (event.keyCode == 19) || // pause
153 (event.keyCode == 20) || // caps lock
154 (event.keyCode == 45) || // insert
155 (event.keyCode == 46) || // delete
156 (event.keyCode == 144) || // num lock
157 (event.keyCode == 145) || // scroll lock
158 (event.keyCode > 32 && event.keyCode < 41) || // page up/down, end, home, arrows
159 (event.keyCode > 111 && event.keyCode < 124); // fn keys
161 return !anyNonPrintable && !(event.charCode == 0 && mozNonPrintable);
164 _onKeypress: function(event) {
165 if (!this.preventInvalidInput && this.type !== 'number') {
166 return;
168 var regexp = this._patternRegExp;
169 if (!regexp) {
170 return;
173 // Handle special keys and backspace
174 if (event.metaKey || event.ctrlKey || event.altKey)
175 return;
177 // Check the pattern either here or in `_onInput`, but not in both.
178 this._patternAlreadyChecked = true;
180 var thisChar = String.fromCharCode(event.charCode);
181 if (this._isPrintable(event) && !regexp.test(thisChar)) {
182 event.preventDefault();
186 _checkPatternValidity: function() {
187 var regexp = this._patternRegExp;
188 if (!regexp) {
189 return true;
191 for (var i = 0; i < this.value.length; i++) {
192 if (!regexp.test(this.value[i])) {
193 return false;
196 return true;
200 * Returns true if `value` is valid. The validator provided in `validator` will be used first,
201 * then any constraints.
202 * @return {boolean} True if the value is valid.
204 validate: function() {
205 // Empty, non-required input is valid.
206 if (!this.required && this.value == '') {
207 this.invalid = false;
208 return true;
211 var valid;
212 if (this.hasValidator()) {
213 valid = Polymer.IronValidatableBehavior.validate.call(this, this.value);
214 } else {
215 this.invalid = !this.validity.valid;
216 valid = this.validity.valid;
218 this.fire('iron-input-validate');
219 return valid;
225 The `iron-input-validate` event is fired whenever `validate()` is called.
226 @event iron-input-validate