isu-elements
Version:
Polymer components for building web apps.
612 lines (595 loc) • 19.5 kB
JavaScript
import { html, PolymerElement } from '@polymer/polymer'
import '@polymer/paper-dialog'
import './behaviors/isu-elements-shared-styles.js'
import './isu-grid-layout'
import { mixinBehaviors } from '@polymer/polymer/lib/legacy/class'
import '@webcomponents/shadycss/entrypoints/apply-shim.js'
import { BaseBehavior } from './behaviors/base-behavior'
import '@polymer/iron-icon'
import '@polymer/iron-icons'
import './isu-select'
import './utils/jedate/js/jedate'
import { FormatBehavior } from './behaviors/format-behavior'
/**
*
* `isu-input-jedate`
*
* Example:
* ```html
* if you want to use this component, you need to import jedate.css in the host html document manually. It`s relative path is ./utils/jedate/skin/jedate.css
*
* <isu-input-jedate class="input-date multi" label="年选择" format="YYYY" placeholder="YYYY" required></isu-input-jedate>
* <isu-input-jedate class="input-date multi" label="年月选择" format="YYYY-MM" placeholder="YYYY-MM"></isu-input-jedate>
* <isu-input-jedate class="input-date multi" label="年月日选择" format="MM-DD-YYYY" placeholder="MM-DD-YYYY"></isu-input-jedate>
* <isu-input-jedate class="input-date multi" label="年月日时分秒选择" festival min="1900-01-01" max="2099-12-31"
* format="YYYY-MM-DD hh:mm:ss" placeholder="YYYY-MM-DD hh:mm:ss"></isu-input-jedate>
* <isu-input-jedate class="input-date multi" label="时分秒选择" format="hh:mm:ss" min="01:02:08" max="15:25:35" placeholder="hh:mm:ss"></isu-input-jedate>
*
* <isu-input-jedate class="input-date multi" label="年月日选择" format="YYYY-MM-DD" placeholder="YYYY-MM-DD" language="en"></isu-input-jedate>
*<isu-input-jedate class="input-date multi" id="testBlue" label="蓝色主题" format="YYYY-MM-DD hh:mm:ss"
* placeholder="YYYY-MM-DD hh:mm:ss"></isu-input-jedate>
*<script>
* testBlue.theme = {bgcolor:'#00A1CB',pnColor:'#00CCFF'}
*</script>
*<isu-input-jedate label="年范围选择" format="YYYY" placeholder="YYYY" range=" ~ "></isu-input-jedate>
*<isu-input-jedate label="年月范围选择" format="YYYY-MM" placeholder="YYYY-MM" range=" To "></isu-input-jedate>
*<isu-input-jedate label="日范围选择" format="YYYY-MM-DD" placeholder="YYYY-MM-DD" range=" 至 "></isu-input-jedate>
*<isu-input-jedate label="年范围选择" format="YYYY" placeholder="YYYY" range=" ~ " multi-pane="false"></isu-input-jedate>
*<isu-input-jedate label="年月范围选择" format="YYYY-MM" placeholder="YYYY-MM" range=" To " ></isu-input-jedate>
*<isu-input-jedate label="日范围选择" format="YYYY-MM-DD" placeholder="YYYY-MM-DD" range=" 至 " ></isu-input-jedate>
*<isu-input-jedate label="日时分秒范围选择" format="YYYY-MM-DD hh:mm:ss" placeholder="YYYY-MM-DD hh:mm:ss" range=" ~ "></isu-input-jedate>
*<isu-input-jedate label="时分秒范围选择" format="hh:mm:ss" placeholder="hh:mm:ss" range=" To "></isu-input-jedate>
*<isu-input-jedate label="时分范围选择" format="hh:mm" placeholder="hh:mm" range=" 至 "></isu-input-jedate>
*<isu-input-jedate label="自定义格式" format="YYYY年MM月DD日" placeholder="YYYY年MM月DD日"></isu-input-jedate>
*<isu-input-jedate label="自定义格式" format="MM-DD-YYYY" placeholder="MM-DD-YYYY"></isu-input-jedate>
*<isu-input-jedate label="自定义格式" format="DD/MM/YYYY" placeholder="DD/MM/YYYY"></isu-input-jedate>
*<isu-input-jedate id="multiPane7" label="自定义格式(双面板)" format="DD/MM/YYYY" placeholder="DD/MM/YYYY" range=" 至 " multi-pane="false"></isu-input-jedate>
*<isu-input-jedate label="默认初始赋值" format="YYYY-MM-DD" placeholder="YYYY年MM月DD日" isinit-val></isu-input-jedate>
*<isu-input-jedate label="只读" format="YYYY年MM月DD日" placeholder="YYYY年MM月DD日" bind-data="1517760000000" readonly></isu-input-jedate>
* ```
*
* @customElement
* @polymer
* @demo demo/isu-input-jedate/index.html
*/
class IsuInputJedate extends mixinBehaviors([BaseBehavior, FormatBehavior], PolymerElement) {
static get template () {
return html`
<style include="isu-elements-shared-styles">
:host {
display: flex;
width: var(--isu-input-jedate-width, 320px);
height: var(--isu-input-jedate-height, var(--isu-default-line-height, 34px));
line-height: var(--isu-input-jedate-height, var(--isu-default-line-height, 34px));
font-family: var(--isu-ui-font-family), sans-serif;
font-size: var(--isu-ui-font-size);
}
:host .jeinpbox{
width: 200px;
margin-right: 10px;
vertical-align: middle;
flex: 1;
display: flex;
line-height: inherit;
position: relative;
}
:host .jeinput{
display: block;
width: 100%;
padding-left: 10px;
height: var(--isu-input-jedate-height, 34px);
float:left;
line-height: var(--isu-input-jedate-height, 34px);
border: 1px solid #e6e6e6;
border-radius: 3px;
background-color: #fcfcfc;
box-sizing: border-box;
}
:host .input__container {
flex: 1;
display: flex;
line-height: inherit;
min-width: 0;
position: relative;
}
.isu-label {
position: relative;
}
:host([data-invalid]) .jeinput {
border-color: var(--isu-ui-color_pink)!important;
}
:host([required]) .input__container::before {
content: "*";
color: red;
position: absolute;
left: -8px;
line-height: inherit;
--isu-required
}
:host([readonly]) .jeinput {
cursor: default;
}
.view-text {
--isu-view-text
}
</style>
<template is="dom-if" if="[[ toBoolean(label) ]]">
<div class="isu-label-div"><span class$="isu-label [[fontSize]]">[[label]]</span><span class="isu-label-after-extension"></span></div>
</template>
<div class$="input__container [[fontSize]]" id="input__jedate">
<div class="jeinpbox"><input type="text" id$="[[id]]" class$="jeinput [[fontSize]]" readonly$="[[readonly]]" placeholder$="[[placeholder]]" value="{{ value::input }}"></div>
<div class="prompt-tip__container" data-prompt$="[[prompt]]">
<div class="prompt-tip">
<iron-icon class="prompt-tip-icon" icon="social:sentiment-very-dissatisfied"></iron-icon>
[[prompt]]
</div>
</div>
</div>
<template is="dom-if" if="[[_isView(isView, readonly)]]">
<div class$="view-text [[fontSize]]">
<span>{{value}}</span>
</div>
</template>
`
}
static get properties () {
return {
/**
* The value of the input, return a date string format to `yyyy-MM-dd`.
* @type {string}
*/
value: {
type: String,
notify: true
},
/**
* The value of the input, return a timestamp
* @type {Number}
*/
timestamp: {
type: String,
notify: true
},
/**
* The label of the input.
*/
label: {
type: String
},
/**
* The placeholder of the input.
*/
placeholder: {
type: String,
value: '请输入'
},
/**
* Set to true, if the input is required.
* @type {boolean}
* @default false
*/
required: {
type: Boolean,
value: false,
reflectToAttribute: true
},
/**
* Set to true, if the input is readonly.
* @type {boolean}
* @default false
*/
readonly: {
type: Boolean,
value: false,
reflectToAttribute: true
},
/**
* The minimum date which can be chosen. It should be a string format to `YYYY-MM-DD`.
* @type {string}
*/
min: {
type: String
},
/**
* The maximum date which can be chosen. It should be a string format to `YYYY-MM-DD`.
* @type {string}
*/
max: {
type: String
},
/**
* The format of the date
* @type {string}
* @default 'YYYY-MM-DD'
*/
format: {
type: String,
value: 'YYYY-MM-DD'
},
/**
* Double panel or not, show double panel if multiPane is false
* @type {boolean}
* @default true
*/
multiPane: {
type: Boolean,
value: true
},
/**
* Whether it is displayed as a fixed calender or not, if false, displayed as a fixed calender
* @type {boolean}
* @default true
*/
isShow: {
type: Boolean,
value: true
},
/**
* Close the shell layer after selecting date, if false, close the shell layer after selecting date
* @type {boolean}
* @default true
*/
onClose: {
type: Boolean,
value: true
},
/**
* If it is not empty and not false, a range selection will be made. eg: " 至 "," ~ "," To "
* @type {string}
* @default false
*/
range: {
type: String,
value: false
},
/**
* Whether it is an internal event or not. It is an internal event by default.
* @type {string}
* @default 'click'
*/
trigger: {
type: String,
value: 'click'
},
/**
* Custom date bouncer`s offset position,the length is 0, bouncer will automactically find the position.
* @type {array}
* @default []
*/
position: {
type: Array,
value: []
},
/**
* Whether initialize the time or not. Does not initialize the time by default.
* @type {boolean}
* @default false
*/
isinitVal: {
type: Boolean,
value: false
},
/**
* Initialize the date, add or minus the day, time, minute
* @type {boolean}
* @default false
*/
initDate: {
type: Object,
value: {}
},
/**
* Whether to turn on the time selection or not
* @type {boolean}
* @default true
*/
isTime: {
type: Boolean,
value: true
},
/**
* Whether to display the clear button
* @type {boolean}
* @default true
*/
isClear: {
type: Boolean,
value: true
},
/**
* Whether to display the today or this mounth button
* @type {boolean}
* @default true
*/
isToday: {
type: Boolean,
value: true
},
/**
* Whether to display the ok button
* @type {boolean}
* @default true
*/
isYes: {
type: Boolean,
value: true
},
/**
* Whether to display the lunar festival
* @type {boolean}
* @default false
*/
festival: {
type: Boolean,
value: false
},
/**
* Valid date and non-valid date. eg: ["0[4-7]$,1[1-5]$,2[58]$",true]
* @type {array}
* @default []
*/
valiDate: {
type: Array,
value: []
},
/**
* Whether the position is fixed or not. The position is located in the input box when it is true, and the position is centered when it is false
* @type {boolean}
* @default true
*/
fixed: {
type: Boolean,
value: true
},
/**
* Custom theme colors
* @type {object}
* @default {}
*/
theme: {
type: Object,
value: {}
},
/**
* language,'en'/'cn'
* @type {string}
* @default 'cn'
*/
language: {
type: String,
value: 'cn'
},
/**
* Custom methods
* @type {object}
* @default {}
*/
method: {
type: Object,
value: {}
},
/**
* Methods executed before the interface loads
* @type {function}
* @default null
*/
before: {
type: Function,
value: null
},
/**
* Methods executed after the interface loads
* @type {function}
* @default null
*/
succeed: {
type: Function,
value: null
},
/**
* The level height of the pop-up layer
* @type {number}
* @default 2099
*/
zIndex: {
type: Number,
value: 2099
},
/**
* The shortcut to date selection
* @type {array}
* @default []
*/
shortcut: {
type: Array,
value: []
},
/**
* The set of selected values, if there is a range there are two values in the set, if there is no range, there is only one value. Each value in the set is timestamp.
* @type {array}
* @default []
*/
selectedItems: {
type: Array,
value: []
},
id: {
type: String,
value: 'test' + Math.floor(Math.random() * 10000)
},
dateArray: {
type: Array,
value: []
},
/**
* The prompt tip to show when input is invalid.
* @type String
*/
prompt: {
type: String
},
/**
* The prompt tip's position. top/bottom
* @type String
* @default ''
*/
promptPosition: {
type: String,
value: ''
},
/**
* The text mode display requires readonly=true to take effect
* @type {boolean}
* @default false
* */
isView: {
type: Boolean,
value: false
},
_jedate: {
type: Object
}
}
}
static get observers () {
return [
'_idChanged(id)',
'_valueChanged(value)',
'_timestampChanged(timestamp)',
'getInvalidAttribute(required, value)',
'__isViewChanged(isView,readonly)'
]
}
static get is () {
return 'isu-input-jedate'
}
_valueChanged (value) {
if (this.format.indexOf('YYYY') !== -1) {
if (this.dateArray.length > 0) {
const dateArray = this.dateArray.map(item => {
let date = `${item.YYYY}-${item.MM}`
date += this.format.indexOf('DD') !== -1 ? `-${item.DD}` : ''
date += this.format.indexOf('hh') !== -1 ? ` ${item.hh}` : ''
date += this.format.indexOf('mm') !== -1 ? `:${item.mm}` : ''
date += this.format.indexOf('ss') !== -1 ? `:${item.ss}` : ''
return +new Date(date)
})
this.set('timestamp', dateArray[0])
this.set('selectedItems', dateArray)
} else if (!this.isEmptyObject(value)) {
this.set('timestamp', this.dateToTimestamp(value))
} else if (this.value === '') {
this.set('timestamp', '')
}
}
if (this._jedate && value !== undefined && value != null) {
// 手动清空输入框的值,否则的话无法清除
if (this.timestamp === '') {
this._jedate.valCell.value = ''
}
this._jedate.setValue(value)
}
}
donefun (e) {
this.set('dateArray', e.date)
this.set('value', e.val)
}
clearfun () {
this.set('dateArray', [])
this.set('value', null)
}
before () {
}
succeed () {
}
_timestampChanged (timestamp) {
const convertDate = this.timestamp ? FormatBehavior.formatDate(this.timestamp, this.format) : ''
if (this._jedate && this.timestamp != null && this.timestamp !== undefined) {
this._jedate.setValue(convertDate)
// 手动清空输入框的值,否则的话无法清除
if (this.timestamp === '') {
this._jedate.valCell.value = ''
}
this.set('dateArray', [])
}
this.set('value', convertDate)
}
_idChanged (id) {
const convertDate = this.timestamp ? FormatBehavior.formatDate(this.timestamp, this.format) : (this.value ? this.value : null)
if (!this.readonly) {
const self = this
const enLang = {
name: 'en',
month: ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'],
weeks: ['SUN', 'MON', 'TUR', 'WED', 'THU', 'FRI', 'SAT'],
times: ['Hour', 'Minute', 'Second'],
timetxt: ['Time', 'Start Time', 'End Time'],
backtxt: 'Back',
clear: 'Clear',
today: 'Now',
yes: 'Confirm',
close: 'Close'
}
const options = {
minDate: this.min, // 最小日期
maxDate: this.max, // 最大日期
format: this.format,
isShow: this.isShow, // 是否显示为固定日历,为false的时候固定显示
multiPane: this.multiPane, // 是否为双面板,为false是展示双面板
onClose: this.onClose, // 是否为选中日期后关闭弹层,为false时选中日期后关闭弹层
range: this.range, // 如果不为空且不为false,则会进行区域选择,例如 " 至 "," ~ "," To "
trigger: this.trigger, // 是否为内部触发事件,默认为内部触发事件
position: this.position, // 自定义日期弹层的偏移位置,长度为0,弹层自动查找位置
valiDate: this.valiDate, // 有效日期与非有效日期,例如 ["0[4-7]$,1[1-5]$,2[58]$",true]
isinitVal: this.isinitVal, // 是否初始化时间,默认不初始化时间
initDate: this.initDate, // 初始化时间,加减 天 时 分
isTime: this.isTime, // 是否开启时间选择
isClear: this.isClear, // 是否显示清空按钮
isToday: this.isToday, // 是否显示今天或本月按钮
isYes: this.isYes, // 是否显示确定按钮
festival: this.festival, // 是否显示农历节日
fixed: this.fixed, // 是否静止定位,为true时定位在输入框,为false时居中定位
zIndex: this.zIndex, // 弹出层的层级高度
method: this.method, // 自定义方法
theme: this.theme, // 自定义主题色
shortcut: this.shortcut, // 日期选择的快捷方式
donefun: this.donefun.bind(this), // 选中日期完成的回调
clearfun: this.clearfun.bind(this), // 清空日期后的回调
before: this.before, // 在界面加载之前执行
succeed: this.succeed // 在界面加载之后执行
}
if (this.language === 'en') {
options.language = enLang
}
this._jedate = jeDate(self.root.querySelector(`#${self.id}`), options)
if (this.timestamp) {
this._jedate.setValue(convertDate)
}
}
this.set('value', convertDate)
}
validate () {
super.validate()
return this.required ? this.value && this.value.length > 0 : true
}
__isViewChanged (isView, readonly) {
this.$.input__jedate.style.display = (this.readonly && isView) ? 'none' : 'flex'
}
_isView (isView, readonly) {
return isView && readonly
}
ready () {
super.ready()
const links = [...document.getElementsByTagName('link')]
const isJedateLink = links.some(item => item.href.includes('/utils/jedate/skin/jedate.css'))
if (!isJedateLink) {
const link = document.createElement('link')
link.type = 'text/css'
link.rel = 'stylesheet'
link.href = '/utils/jedate/skin/jedate.css'
const head = document.getElementsByTagName('head')[0]
head.appendChild(link)
}
}
}
window.customElements.define(IsuInputJedate.is, IsuInputJedate)