aboutsummaryrefslogtreecommitdiff
path: root/catapult/third_party/polymer/components/iron-input/iron-input.html
diff options
context:
space:
mode:
Diffstat (limited to 'catapult/third_party/polymer/components/iron-input/iron-input.html')
-rw-r--r--catapult/third_party/polymer/components/iron-input/iron-input.html311
1 files changed, 311 insertions, 0 deletions
diff --git a/catapult/third_party/polymer/components/iron-input/iron-input.html b/catapult/third_party/polymer/components/iron-input/iron-input.html
new file mode 100644
index 00000000..ddb5277e
--- /dev/null
+++ b/catapult/third_party/polymer/components/iron-input/iron-input.html
@@ -0,0 +1,311 @@
+<!--
+@license
+Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
+This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
+The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
+The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
+Code distributed by Google as part of the polymer project is also
+subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
+-->
+
+<link rel="import" href="../polymer/polymer.html">
+<link rel="import" href="../iron-a11y-announcer/iron-a11y-announcer.html">
+<link rel="import" href="../iron-validatable-behavior/iron-validatable-behavior.html">
+
+<script>
+
+/*
+`<iron-input>` adds two-way binding and custom validators using `Polymer.IronValidatorBehavior`
+to `<input>`.
+
+### Two-way binding
+
+By default you can only get notified of changes to an `input`'s `value` due to user input:
+
+ <input value="{{myValue::input}}">
+
+`iron-input` adds the `bind-value` property that mirrors the `value` property, and can be used
+for two-way data binding. `bind-value` will notify if it is changed either by user input or by script.
+
+ <input is="iron-input" bind-value="{{myValue}}">
+
+### Custom validators
+
+You can use custom validators that implement `Polymer.IronValidatorBehavior` with `<iron-input>`.
+
+ <input is="iron-input" validator="my-custom-validator">
+
+### Stopping invalid input
+
+It may be desirable to only allow users to enter certain characters. You can use the
+`prevent-invalid-input` and `allowed-pattern` attributes together to accomplish this. This feature
+is separate from validation, and `allowed-pattern` does not affect how the input is validated.
+
+ <!-- only allow characters that match [0-9] -->
+ <input is="iron-input" prevent-invalid-input allowed-pattern="[0-9]">
+
+@hero hero.svg
+@demo demo/index.html
+*/
+
+ Polymer({
+
+ is: 'iron-input',
+
+ extends: 'input',
+
+ behaviors: [
+ Polymer.IronValidatableBehavior
+ ],
+
+ properties: {
+
+ /**
+ * Use this property instead of `value` for two-way data binding.
+ */
+ bindValue: {
+ observer: '_bindValueChanged',
+ type: String
+ },
+
+ /**
+ * Set to true to prevent the user from entering invalid input. If `allowedPattern` is set,
+ * any character typed by the user will be matched against that pattern, and rejected if it's not a match.
+ * Pasted input will have each character checked individually; if any character
+ * doesn't match `allowedPattern`, the entire pasted string will be rejected.
+ * If `allowedPattern` is not set, it will use the `type` attribute (only supported for `type=number`).
+ */
+ preventInvalidInput: {
+ type: Boolean
+ },
+
+ /**
+ * Regular expression that list the characters allowed as input.
+ * This pattern represents the allowed characters for the field; as the user inputs text,
+ * each individual character will be checked against the pattern (rather than checking
+ * the entire value as a whole). The recommended format should be a list of allowed characters;
+ * for example, `[a-zA-Z0-9.+-!;:]`
+ */
+ allowedPattern: {
+ type: String,
+ observer: "_allowedPatternChanged"
+ },
+
+ _previousValidInput: {
+ type: String,
+ value: ''
+ },
+
+ _patternAlreadyChecked: {
+ type: Boolean,
+ value: false
+ }
+
+ },
+
+ listeners: {
+ 'input': '_onInput',
+ 'keypress': '_onKeypress'
+ },
+
+ registered: function() {
+ // Feature detect whether we need to patch dispatchEvent (i.e. on FF and IE).
+ if (!this._canDispatchEventOnDisabled()) {
+ this._origDispatchEvent = this.dispatchEvent;
+ this.dispatchEvent = this._dispatchEventFirefoxIE;
+ }
+ },
+
+ created: function() {
+ Polymer.IronA11yAnnouncer.requestAvailability();
+ },
+
+ _canDispatchEventOnDisabled: function() {
+ var input = document.createElement('input');
+ var canDispatch = false;
+ input.disabled = true;
+
+ input.addEventListener('feature-check-dispatch-event', function() {
+ canDispatch = true;
+ });
+
+ try {
+ input.dispatchEvent(new Event('feature-check-dispatch-event'));
+ } catch(e) {}
+
+ return canDispatch;
+ },
+
+ /**
+ * @this {Node}
+ * @param {!Event} event
+ * @return {boolean}
+ */
+ _dispatchEventFirefoxIE: function(event) {
+ // Due to Firefox bug, events fired on disabled form controls can throw
+ // errors; furthermore, neither IE nor Firefox will actually dispatch
+ // events from disabled form controls; as such, we toggle disable around
+ // the dispatch to allow notifying properties to notify
+ // See issue #47 for details
+ var disabled = this.disabled;
+ this.disabled = false;
+ var defaultPrevented = this._origDispatchEvent(event);
+ this.disabled = disabled;
+ return defaultPrevented
+ },
+
+ get _patternRegExp() {
+ var pattern;
+ if (this.allowedPattern) {
+ pattern = new RegExp(this.allowedPattern);
+ } else {
+ switch (this.type) {
+ case 'number':
+ pattern = /[0-9.,e-]/;
+ break;
+ }
+ }
+ return pattern;
+ },
+
+ ready: function() {
+ this.bindValue = this.value;
+ },
+
+ /**
+ * @suppress {checkTypes}
+ */
+ _bindValueChanged: function() {
+ if (this.value !== this.bindValue) {
+ this.value = !(this.bindValue || this.bindValue === 0 || this.bindValue === false) ? '' : this.bindValue;
+ }
+ // manually notify because we don't want to notify until after setting value
+ this.fire('bind-value-changed', {value: this.bindValue});
+ },
+
+ _allowedPatternChanged: function() {
+ // Force to prevent invalid input when an `allowed-pattern` is set
+ this.preventInvalidInput = this.allowedPattern ? true : false;
+ },
+
+ _onInput: function() {
+ // Need to validate each of the characters pasted if they haven't
+ // been validated inside `_onKeypress` already.
+ if (this.preventInvalidInput && !this._patternAlreadyChecked) {
+ var valid = this._checkPatternValidity();
+ if (!valid) {
+ this._announceInvalidCharacter('Invalid string of characters not entered.');
+ this.value = this._previousValidInput;
+ }
+ }
+
+ this.bindValue = this.value;
+ this._previousValidInput = this.value;
+ this._patternAlreadyChecked = false;
+ },
+
+ _isPrintable: function(event) {
+ // What a control/printable character is varies wildly based on the browser.
+ // - most control characters (arrows, backspace) do not send a `keypress` event
+ // in Chrome, but the *do* on Firefox
+ // - in Firefox, when they do send a `keypress` event, control chars have
+ // a charCode = 0, keyCode = xx (for ex. 40 for down arrow)
+ // - printable characters always send a keypress event.
+ // - in Firefox, printable chars always have a keyCode = 0. In Chrome, the keyCode
+ // always matches the charCode.
+ // None of this makes any sense.
+
+ // For these keys, ASCII code == browser keycode.
+ var anyNonPrintable =
+ (event.keyCode == 8) || // backspace
+ (event.keyCode == 9) || // tab
+ (event.keyCode == 13) || // enter
+ (event.keyCode == 27); // escape
+
+ // For these keys, make sure it's a browser keycode and not an ASCII code.
+ var mozNonPrintable =
+ (event.keyCode == 19) || // pause
+ (event.keyCode == 20) || // caps lock
+ (event.keyCode == 45) || // insert
+ (event.keyCode == 46) || // delete
+ (event.keyCode == 144) || // num lock
+ (event.keyCode == 145) || // scroll lock
+ (event.keyCode > 32 && event.keyCode < 41) || // page up/down, end, home, arrows
+ (event.keyCode > 111 && event.keyCode < 124); // fn keys
+
+ return !anyNonPrintable && !(event.charCode == 0 && mozNonPrintable);
+ },
+
+ _onKeypress: function(event) {
+ if (!this.preventInvalidInput && this.type !== 'number') {
+ return;
+ }
+ var regexp = this._patternRegExp;
+ if (!regexp) {
+ return;
+ }
+
+ // Handle special keys and backspace
+ if (event.metaKey || event.ctrlKey || event.altKey)
+ return;
+
+ // Check the pattern either here or in `_onInput`, but not in both.
+ this._patternAlreadyChecked = true;
+
+ var thisChar = String.fromCharCode(event.charCode);
+ if (this._isPrintable(event) && !regexp.test(thisChar)) {
+ event.preventDefault();
+ this._announceInvalidCharacter('Invalid character ' + thisChar + ' not entered.');
+ }
+ },
+
+ _checkPatternValidity: function() {
+ var regexp = this._patternRegExp;
+ if (!regexp) {
+ return true;
+ }
+ for (var i = 0; i < this.value.length; i++) {
+ if (!regexp.test(this.value[i])) {
+ return false;
+ }
+ }
+ return true;
+ },
+
+ /**
+ * Returns true if `value` is valid. The validator provided in `validator` will be used first,
+ * then any constraints.
+ * @return {boolean} True if the value is valid.
+ */
+ validate: function() {
+ // First, check what the browser thinks. Some inputs (like type=number)
+ // behave weirdly and will set the value to "" if something invalid is
+ // entered, but will set the validity correctly.
+ var valid = this.checkValidity();
+
+ // Only do extra checking if the browser thought this was valid.
+ if (valid) {
+ // Empty, required input is invalid
+ if (this.required && this.value === '') {
+ valid = false;
+ } else if (this.hasValidator()) {
+ valid = Polymer.IronValidatableBehavior.validate.call(this, this.value);
+ }
+ }
+
+ this.invalid = !valid;
+ this.fire('iron-input-validate');
+ return valid;
+ },
+
+ _announceInvalidCharacter: function(message) {
+ this.fire('iron-announce', { text: message });
+ }
+ });
+
+ /*
+ The `iron-input-validate` event is fired whenever `validate()` is called.
+ @event iron-input-validate
+ */
+
+</script>