isu-element
Version:
Polymer components for building web apps.
308 lines (290 loc) • 7.83 kB
JavaScript
import {html, PolymerElement} from "@polymer/polymer";
import '@polymer/paper-button/paper-button'
import './behaviors/isu-elements-shared-styles.js';
import '@polymer/iron-input';
import '@polymer/iron-icon';
import '@polymer/iron-icons';
import {mixinBehaviors} from "@polymer/polymer/lib/legacy/class";
import {BaseBehavior} from "./behaviors/base-behavior";
/**
*
* `isu-input-number`
*
* Example:
* ```html
* <div>
* <h4>Basic</h4>
* <isu-input-number id="inputNumber"></isu-input-number>
* <h4>步长,相关联label</h4>
* <isu-input-number id="inputNumber2" step="0.01" label="数量"></isu-input-number>
* <h4>最大输入值,最小输入值</h4>
* <isu-input-number id="inputNumber3" min="0" max="10"></isu-input-number>
* <h4>禁用</h4>
* <isu-input-number id="inputNumber4" disabled></isu-input-number>
* <h4>不要两个控制按钮</h4>
* <isu-input-number id="inputNumber5" no-controls></isu-input-number>
* <h4>精度为2</h4>
* <isu-input-number id="inputNumber6" precision="2" step="0.1"></isu-input-number>
* </div>
* ```
*
* ### Styling
*
* `<isu-button>` provides the following custom properties and mixins
* for styling:
*
* Custom property | Description | Default
* ----------------|-------------|----------
* `--isu-label` | Mixin applied to the button | {}
*
* @customElement
* @polymer
* @demo demo/isu-input-number/index.html
*/
class IsuInputNumber extends mixinBehaviors([BaseBehavior], PolymerElement) {
static get template() {
return html`
<style include="isu-elements-shared-styles">
:host {
display: flex;
font-family: var(--isu-ui-font-family) sans-serif;
font-size: var(--isu-ui-font-size);
border-radius: 4px;
outline: none;
}
.box {
display: inline-block;
border: 1px solid lightgray;
text-align: center;
line-height: 35px;
border-radius: 2px;
padding: 0px;
}
.icon-box {
width: 37px;
height: 37px;
background-color: transparent;
}
.icon {
width: 20px;
}
.input {
width: 120px;
font-size: 16px;
}
.isu-label {
text-align: right;
line-height: 37px;
@apply --isu-label
}
:host([disabled]) .box:hover {
cursor: no-drop;
}
:host([disabled]) .input {
color: lightgray;
}
:host([no-controls]) .input {
width: 190px;
}
.disabled {
color: lightgray;
}
.disabled:hover {
cursor: no-drop;
}
.hidden {
display: none;
}
</style>
<template is="dom-if" if="[[ toBoolean(label) ]]">
<div class="isu-label">[[label]]</div>
</template>
<button id="removeButton" class="box icon-box" disabled="[[disabled]]" data-args="[[step]]" on-click="minus">
<iron-icon class="icon" icon="icons:remove"></iron-icon>
</button>
<iron-input bind-value="{{value}}" id="input" disabled="[[disabled]]">
<input id="innerInput" class="box input" placeholder$="[[placeholder]]" type$="number" minlength$="[[minlength]]" rows$="[[rows]]"
maxlength$="[[maxlength]]" min$="{{min}}" max$="{{max}}" readonly$="[[disabled]]"
autocomplete="off" step="any" spellcheck="false" on-change="checkNum">
</iron-input>
<button id="addButton" class="box icon-box" on-click="add" data-args="[[step]]" disabled="[[disabled]]">
<iron-icon class="icon" icon="icons:add"></iron-icon>
</button>
`;
}
constructor() {
super();
}
static get properties() {
return {
/**
* The value of the input number
*
* @type Number
* @default 1
*/
value: {
type: Number,
value: 1,
notify: true
},
/**
* placeholder
*
* @type String
* @default 请输入
*/
placeholder: {
type: String,
value: '请输入'
},
/**
* minimum input number
*
* @type Number
* @default
*/
min: Number,
/**
* maximum input number
*
* @type Number
* @default
*/
max: Number,
/**
* Add and subtract steps
*
* @type Number
* @default 1
*/
step: {
type: Number,
value: 1
},
/**
* title before input number
*
* @type String
* @default
*/
label: String,
/**
* is disabled
*
* @type Boolean
* @default false
*/
disabled: {
type: Boolean,
value: false
},
/**
* Whether to display the control button or not
*
* @type Boolean
* @default false
*/
noControls: {
type: Boolean,
value: false
},
/**
*The precision of the input number
*
* @type Number
* @default
*/
precision: Number,
/**
*Can only enter multiples of step, step can not be null
*
* @type Boolean
* @default
*/
stepStrictly: {
type: Boolean,
value: false
},
}
}
static get observers() {
return [
'_valueChanged(value)',
'_noControlsChanged(noControls)',
'_precisionChanged(precision)'
]
}
connectedCallback() {
super.connectedCallback()
if (this.stepStrictly) {
this.set('value', Math.ceil(this.value / this.step) * this.step)
}
if (this.precision) {
this.set('value', Number(this.value).toFixed(this.precision))
}
}
_valueChanged(value) {
if (this.min !== null && this.min !== undefined) {
if (value <= this.min) {
this.set('value', this.min)
this.$.removeButton.classList.add('disabled')
} else {
this.$.removeButton.classList.remove('disabled')
}
}
if (this.max !== null && this.max !== undefined) {
if (value >= this.max) {
this.set('value', this.max)
this.$.addButton.classList.add('disabled')
} else {
this.$.addButton.classList.remove('disabled')
}
}
}
_precisionChanged(precision) {
if (precision) {
this.set('value', Number(this.value).toFixed(this.precision))
}
}
_noControlsChanged(noControls) {
if (noControls) {
this.$.removeButton.classList.add('hidden')
this.$.addButton.classList.add('hidden')
}
}
minus(e) {
this.value = this.calculate(this.value, e.currentTarget.dataArgs, '-')
}
add(e) {
this.value = this.calculate(this.value, e.currentTarget.dataArgs, '+')
}
calculate(oldValue, step, operator) {
let value = oldValue
if (this.stepStrictly) {
value = Math.ceil(value / step) * step
}
const decimal = step.toString().split(".")[1]
let digit = decimal ? decimal.length : 1
const pow = Math.pow(10, digit)
switch (operator) {
case '+':
const numAdd = Math.round((Number(value)*pow + step*pow)) / pow
return this.precision ? numAdd.toFixed(this.precision) : numAdd
case '-':
const numMinus = Math.round((Number(value)*pow - step*pow)) / pow
return this.precision ? numMinus.toFixed(this.precision) : numMinus
}
}
checkNum(e) {
const decimal = this.value.toString().split(".")[1]
const length = decimal ? decimal.length : 0
if (this.stepStrictly) {
this.set('value', Math.ceil(this.value / this.step) * this.step)
}
if(this.precision && length !== this.precision) {
this.set('value', Number(this.value).toFixed(this.precision))
}
}
}
window.customElements.define('isu-input-number', IsuInputNumber);