UNPKG

@inq/keypad-input

Version:

Keypad input for Touchscreen devices like a Kiosk

283 lines (266 loc) 9.01 kB
import {html, PolymerElement} from '@polymer/polymer/polymer-element.js'; /** * `keypad-input` * Keypad input for Touchscreen devices like a Kiosk * ### Styling * * `<paper-button>` provides the following custom properties and mixins * for styling: * * Custom property | Description | Default * ----------------|-------------|---------- * `--keypad-input-color` | Input font color and 60% opacity for placeholder | `#004` * `--keypad-input-padding` | Input Padding | `8px` * `--keypad-button-height` | Button Padding | `2.5em` * `--keypad-button-background` | Button Background | ` #f0ecec` * `--keypad-button-disabled-background` | Disabled Button Background | ` #ccc` * `--keypad-button-border` | Button Border | `0` * `--keypad-button-margin` | Button Margin | `5px` * `--keypad-button-padding` | Button Padding | `8px` * `--keypad-button-border-radius` | Button Border radius | `3px` * `--primary-color` | Primary font color for Button | `#565361` * `--disabled-color` | Disabled font color for Button | `#565361` * * @customElement * @polymer * @demo demo/index.html */ class KeypadInput extends PolymerElement { constructor() { super(); this.setAttribute('tabindex',1); } static get template() { return html` <style> :host { display: inline-block; margin: 10px; padding: 10px; min-width: 180px; } :host([disabled]:focus) { outline: none; } #input { display: block; border: 0; font-size: inherit; border-bottom: 1px solid #999; outline: none; margin-bottom: 20px; color: var(--keypad-input-color, #004); width: 100%; padding: var(--keypad-input-padding, 8px); box-sizing: border-box; } #input::-moz-placeholder { color: var(--keypad-input-color, #004); opacity: 0.8; } #input::-webkit-input-placeholder{ color: var(--keypad-input-color, #004); opacity: 0.8; } #input:-ms-input-placeholder { color: var(--keypad-input-color, #004); opacity: 0.8; } #input[hidden] { display: none; } .keypad .row { display: flex; flex-direction: row; } .row > button { height: var(--keypad-button-height, 2.5em); flex-grow: 1; background: var(--keypad-button-background, #f0ecec); margin: var(--keypad-button-margin, 5px); border: var(--keypad-button-border, 0); border-radius: var(--keypad-button-border-radius, 3px); padding: var(--keypad-button-padding, 8px); min-width: calc(33.34% - (2 * var(--keypad-button-margin, 5px))); outline: none; box-sizing: border-box; user-select: none; font-size: inherit; color: var(--primary-color, #565361); box-shadow: 0 1px 4px -3px #000; } .row > button[disabled] { opacity: 0.6; color: var(--disabled-color, #565361); background: var(--keypad-button-disabled-background, #ccc); box-shadow: none; } .row > button:hover:not([disabled]):not(:active) { box-shadow: 0 1px 6px -3px #000; } .row > button:active { box-shadow: none; } </style> <div class="container"> <input type="[[__inptType]]" id="input" on-click="__focusRoot" pattern="[0-9].[0-9]" readonly value="[[__value]]" placeholder="[[placeholder]]" tabindex="-1" hidden$="[[inputHidden]]" /> <div class="keypad" on-click="__handleKeyPadClick"> <div class="row"> <button disabled$="[[disabled]]" tabindex="-1" data-action="1">1</button> <button disabled$="[[disabled]]" tabindex="-1" data-action="2">2</button> <button disabled$="[[disabled]]" tabindex="-1" data-action="3">3</button> </div> <div class="row"> <button disabled$="[[disabled]]" tabindex="-1" data-action="4">4</button> <button disabled$="[[disabled]]" tabindex="-1" data-action="5">5</button> <button disabled$="[[disabled]]" tabindex="-1" data-action="6">6</button> </div> <div class="row"> <button disabled$="[[disabled]]" tabindex="-1" data-action="7">7</button> <button disabled$="[[disabled]]" tabindex="-1" data-action="8">8</button> <button disabled$="[[disabled]]" tabindex="-1" data-action="9">9</button> </div> <div class="row"> <button tabindex="-1" data-action="decimal" disabled$="[[__disableDecimal]]">.</button> <button disabled$="[[disabled]]" tabindex="-1" data-action="0">0</button> <button disabled$="[[disabled]]" tabindex="-1" data-action="backspace"></button> </div> </div> </div> `; } static get properties() { return { /** The output for the value entered */ value: { type: String, notify: true, computed: "__exportValue(__value)" }, __value: { type: String, notify: true, value: "" }, /** Making this true hides the inbuit input */ inputHidden: { type: Boolean, value: false }, /** This hides the input and replaces the characters with * */ secret: { type: Boolean, value: false }, /** Limit for entering the characters */ charLimit: { type: Number, value: 8 }, /** Placeholder for the inbuilt input */ placeholder: { type: String, value: "Enter PIN" }, /** Disables the decimal button on keypad */ disableDecimal: { type: Boolean, value: !1 }, __disableDecimal: { type: Boolean, computed: "__computeDisableDecimal(disabled, disableDecimal)" }, __inptType: { type: String, computed: "__computeInpType(secret)" }, /** Disables all buttons on keypad */ disabled: { type: Boolean, value: !1, observer: "__disabledChanged", reflectToAttribute: !0 } }; } __handleKeyPadClick(e) { const totalButtons = new Array(...this.shadowRoot.querySelectorAll(".keypad > .row > button")); const target = e.path ? e.path[0] : e.target; if(totalButtons.filter(b => b==target).length) { switch(e.target.dataset['action']) { case "decimal": if(!this.disableDecimal && this.__value && this.__value.indexOf(".")==-1) this.set("__value", this.__value + "."); break; case "backspace": this.__deleteFromValue(1); break default: this.__addToValue(e.target.dataset['action']); } } } __validateNativeInput(e) { if(e.key in ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"]) { this.shadowRoot.querySelector('button[data-action="' + e.key + '"]').click(); } else if (e.key == ".") { this.shadowRoot.querySelector('button[data-action="decimal"]').click(); } else if (e.key == "Backspace") { this.shadowRoot.querySelector('button[data-action="backspace"]').click(); e.preventDefault() // This is to handle history goBack } else if (e.key == "Delete") { if(e.code == "NumpadDecimal"){ this.shadowRoot.querySelector('button[data-action="decimal"]').click(); } else this.shadowRoot.querySelector('button[data-action="backspace"]').click(); } else if(e.key=="Enter") { /** * Fired when "Enter" key is pressed * * @event keypad-submit * @param {number} value Current Value. */ this.dispatchEvent(new CustomEvent("keypad-submit", { value: this.value })) } } __addToValue(v) { const numWithoutDecimal = this.__value.split(".").join(""); if(this.charLimit && numWithoutDecimal.length < this.charLimit) this.set("__value", this.__value + v); } __deleteFromValue(n) { if(this.__value.length) this.set("__value", this.__value.slice(0, this.__value.length-n)); } __exportValue(v) {return v} __computeInpType(f) { return f?"password":"text"; } connectedCallback() { super.connectedCallback(); this.addEventListener('keydown', this.__validateNativeInput) } disconnectedCallback() { super.disconnectedCallback(); this.removeEventListener('keydown', this.__validateNativeInput) } __focusRoot() { if(this.getAttribute('tabindex')!=-1) this.focus(); } __disabledChanged(nv,ov) { console.log(nv?1:0); this.setAttribute('tabindex',nv?-1:1); } __computeDisableDecimal(d,dd) { return d||dd; } } window.customElements.define('keypad-input', KeypadInput);