UNPKG

npm-polymer-elements

Version:

Polymer Elements package for npm

272 lines (221 loc) 7.94 kB
<!-- @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="../paper-input/paper-input-behavior.html"> <link rel="import" href="../paper-input/paper-input-container.html"> <link rel="import" href="../paper-input/paper-input-error.html"> <link rel="import" href="../paper-styles/typography.html"> <link rel="import" href="../iron-input/iron-input.html"> <link rel="import" href="../iron-form-element-behavior/iron-form-element-behavior.html"> <link rel="import" href="../iron-flex-layout/iron-flex-layout.html"> <!-- `<gold-phone-input>` is a single-line text field with Material Design styling for entering a phone number. <gold-phone-input></gold-phone-input> It may include an optional label, which by default is "Phone number". <gold-phone-input label="call this"></gold-phone-input> ### Validation By default, the phone number is considered to be a US phone number, and will be validated according to the pattern `XXX-XXX-XXXX`, where `X` is a digit, and `-` is the separating dash. If you want to customize the input for a different area code or number pattern, use the `country-code` and `phone-number-pattern` attributes <gold-phone-input country-code="33" phone-number-pattern="X-XX-XX-XX-XX"> </gold-phone-input> The input can be automatically validated as the user is typing by using the `auto-validate` and `required` attributes. For manual validation, the element also has a `validate()` method, which returns the validity of the input as well sets any appropriate error messages and styles. See `Polymer.PaperInputBehavior` for more API docs. ### Styling See `Polymer.PaperInputContainer` for a list of custom properties used to style this element. `--gold-phone-input-country-code` | Mixin applied to the country code span @group Gold Elements @hero hero.svg @demo demo/index.html @class gold-phone-input --> <dom-module id="gold-phone-input"> <style> :host { display: block; } /* TODO: This should be a dropdown */ span { @apply(--paper-font-subhead); @apply(--paper-input-container-input); width: 40px; } .country-code { @apply(--gold-phone-input-country-code); } .container { @apply(--layout-horizontal); } /* TODO(notwaldorf): The style applied by paper-input-container is more * specific, and we need the important to override it. This will go away * once we can refactor this element to use the paper-input suffix */ label { left: 40px !important; } input { @apply(--layout-flex); } </style> <template> <paper-input-container id="container" disabled$="[[disabled]]" no-label-float="[[noLabelFloat]]" always-float-label="[[_computeAlwaysFloatLabel(alwaysFloatLabel,placeholder)]]" invalid="[[invalid]]"> <label hidden$="[[!label]]">[[label]]</label> <div class="container"> <span class="country-code">+[[countryCode]]</span> <input is="iron-input" id="input" aria-labelledby$="[[_ariaLabelledBy]]" aria-describedby$="[[_ariaDescribedBy]]" required$="[[required]]" bind-value="{{value}}" name$="[[name]]" allowed-pattern="[0-9\-]" autocomplete="tel" type="tel" prevent-invalid-input disabled$="[[disabled]]" invalid="{{invalid}}" autofocus$="[[autofocus]]" inputmode$="[[inputmode]]" placeholder$="[[placeholder]]" readonly$="[[readonly]]" maxlength$="[[maxlength]]" size$="[[size]]"> </div> <template is="dom-if" if="[[errorMessage]]"> <paper-input-error id="error">[[errorMessage]]</paper-input-error> </template> </paper-input-container> </template> </dom-module> <script> (function() { Polymer({ is: 'gold-phone-input', behaviors: [ Polymer.PaperInputBehavior, Polymer.IronFormElementBehavior ], properties: { /** * The label for this input. */ label: { type: String, value: 'Phone number' }, /* * The country code that should be recognized and parsed. */ countryCode: { type: String, value: '1' }, /* * The format of a valid phone number, including formatting but excluding * the country code. Use 'X' to denote the digits separated by dashes. */ phoneNumberPattern: { type: String, value: 'XXX-XXX-XXXX', observer: '_phoneNumberPatternChanged' }, value: { observer: '_onValueChanged' } }, observers: [ '_onFocusedChanged(focused)' ], ready: function() { // If there's an initial input, validate it. if (this.value) this._handleAutoValidate(); }, _phoneNumberPatternChanged: function() { // Transform the pattern into a regex the iron-input understands. var regex = ''; regex = this.phoneNumberPattern.replace(/\s/g, '\\s'); regex = regex.replace(/X/gi, '\\d'); regex = regex.replace(/\+/g, '\\+'); this.$.input.pattern = regex; }, /** * A handler that is called on input */ _onValueChanged: function(value, oldValue) { // The initial property assignment is handled by `ready`. if (oldValue == undefined) return; var start = this.$.input.selectionStart; var previousCharADash = value ? this.value.charAt(start - 1) == '-' : false; // Remove any already-applied formatting. value = value.replace(/-/g, ''); var shouldFormat = value.length <= this.phoneNumberPattern.replace(/-/g, '').length; var formattedValue = ''; // Fill in the dashes according to the specified pattern. var currentDashIndex = 0; var totalDashesAdded = 0; for (var i = 0; i < value.length; i++) { currentDashIndex = this.phoneNumberPattern.indexOf('-', currentDashIndex); // Since we remove any formatting first, we need to account added dashes // when counting the position of new dashes in the pattern. if (shouldFormat && i == (currentDashIndex - totalDashesAdded)) { formattedValue += '-'; currentDashIndex++; totalDashesAdded++; } formattedValue += value[i]; } this.updateValueAndPreserveCaret(formattedValue.trim()); // If the character right before the selection is a newly inserted // dash, we need to advance the selection to maintain the caret position. if (!previousCharADash && this.value.charAt(start - 1) == '-') { this.$.input.selectionStart = start + 1; this.$.input.selectionEnd = start + 1; } this._handleAutoValidate(); }, /** * Overidden from Polymer.PaperInputBehavior. */ validate: function() { // Update the container and its addons (i.e. the custom error-message). var valid = this.$.input.validate() this.$.container.invalid = !valid; this.$.container.updateAddons({ inputElement: this.$.input, value: this.value, invalid: !valid }); return valid; }, /** * Overidden from Polymer.IronControlState. */ _onFocusedChanged: function(focused) { if (!focused) { this._handleAutoValidate(); } } }) })(); </script>