123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477 |
- import baseComponent from '../helpers/baseComponent'
- import classNames from '../helpers/libs/classNames'
- import locales from './locales/index'
- import { props } from './props'
- const DATETIME = 'datetime'
- const DATE = 'date'
- const TIME = 'time'
- const MONTH = 'month'
- const YEAR = 'year'
- const ONE_DAY = 24 * 60 * 60 * 1000
- function fomartArray(min, max, step = 1) {
- let i = min
- let result = []
- while (i <= max) {
- result.push(i)
- i+=step
- }
- return result
- }
- function getDaysInMonth(date) {
- return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate()
- }
- function pad(n) {
- return n < 10 ? `0${n}` : n + ''
- }
- function cloneDate(date) {
- return new Date(+date)
- }
- function setMonth(date, month) {
- date.setDate(Math.min(date.getDate(), getDaysInMonth(new Date(date.getFullYear(), month))))
- date.setMonth(month)
- }
- function valueToDate(value, props = {}) {
- if (!Array.isArray(value)) {
- if (typeof value === 'string') {
- value = value.replace(/\-/g, '/')
- }
- if (!isNaN(Number(value))) {
- value = Number(value)
- }
- return new Date(value)
- }
- const { mode, use12Hours } = props
- const now = new Date()
- const year = now.getFullYear()
- const month = now.getMonth()
- const day = now.getDate()
- const newValue = value.map((v) => Number(v))
- if (use12Hours && [DATETIME, TIME].includes(mode)) {
- const hourIndex = mode === DATETIME ? 3 : 0
- const ampmIndex = newValue.length - 1
- const ampm = Number(newValue[ampmIndex])
- let nhour = Number(newValue[hourIndex])
- if (ampm === 1) {
- if (nhour <= 12) {
- nhour += 12
- }
- nhour = nhour >= 24 ? 0 : nhour
- } else {
- if (nhour === 0) {
- nhour = 12
- }
- if (nhour > 12) {
- nhour -= 12
- }
- nhour = nhour >= 12 ? 0 : nhour
- }
- newValue.splice(hourIndex, 1, nhour)
- newValue.splice(ampmIndex, 1)
- }
- if (mode === TIME) {
- newValue.unshift(day)
- newValue.unshift(month)
- newValue.unshift(year)
- } else if (mode === MONTH) {
- newValue.push(day)
- } else if (mode === YEAR) {
- newValue.push(month)
- newValue.push(day)
- }
- while (newValue.length <= 6) {
- newValue.push(0)
- }
- return new Date(...newValue)
- }
- baseComponent({
- properties: props,
- data: {
- inputValue: [],
- options: [],
- },
- observers: {
- inputValue() {
- this.updatedCols()
- },
- value(value) {
- this.setValue(value)
- },
- ['mode, minuteStep, use12Hours, minDate, maxDate, minHour, maxHour, minMinute, maxMinute, lang']() {
- this.setValue(this.data.inputValue)
- },
- },
- methods: {
- getDefaultMinDate() {
- if (!this.defaultMinDate) {
- this.defaultMinDate = new Date(2000, 1, 1, 0, 0, 0)
- }
- return this.defaultMinDate
- },
- getDefaultMaxDate() {
- if (!this.defaultMaxDate) {
- this.defaultMaxDate = new Date(2030, 1, 1, 23, 59, 59)
- }
- return this.defaultMaxDate
- },
- getMinDate() {
- return this.data.minDate ? valueToDate(this.data.minDate, this.data) : this.getDefaultMinDate()
- },
- getMaxDate() {
- return this.data.maxDate ? valueToDate(this.data.maxDate, this.data) : this.getDefaultMaxDate()
- },
- getDateMember(type = 'min', member = 'year') {
- const methods = {
- min: 'getMinDate',
- max: 'getMaxDate',
- year: 'getFullYear',
- month: 'getMonth',
- day: 'getDate',
- hour: 'getHours',
- minute: 'getMinutes',
- }
- return this[methods[type]]()[methods[member]]()
- },
- getDisplayHour(rawHour) {
- // 12 hour am (midnight 00:00) -> 12 hour pm (noon 12:00) -> 12 hour am (midnight 00:00)
- if (this.data.use12Hours) {
- if (rawHour === 0) {
- rawHour = 12
- }
- if (rawHour > 12) {
- rawHour -= 12
- }
- return rawHour
- }
- return rawHour
- },
- setHours(date, hour) {
- if (this.data.use12Hours) {
- const dh = date.getHours()
- let nhour = hour
- nhour = dh >= 12 ? hour + 12 : hour
- nhour = nhour >= 24 ? 0 : nhour // Make sure no more than one day
- date.setHours(nhour)
- } else {
- date.setHours(hour)
- }
- },
- setAmPm(date, index) {
- if (index === 0) {
- date.setTime(+date - ONE_DAY / 2)
- } else {
- date.setTime(+date + ONE_DAY / 2)
- }
- },
- getNewDate(values, index) {
- const value = parseInt(values[index], 10)
- const { mode } = this.data
- let newValue = cloneDate(this.getDate())
- if (mode === DATETIME || mode === DATE || mode === YEAR || mode === MONTH) {
- switch (index) {
- case 0:
- newValue.setFullYear(value)
- break
- case 1:
- setMonth(newValue, value)
- break
- case 2:
- newValue.setDate(value)
- break
- case 3:
- this.setHours(newValue, value)
- break
- case 4:
- newValue.setMinutes(value)
- break
- case 5:
- this.setAmPm(newValue, value)
- break
- default:
- break
- }
- } else if (mode === TIME) {
- switch (index) {
- case 0:
- this.setHours(newValue, value)
- break
- case 1:
- newValue.setMinutes(value)
- break
- case 2:
- this.setAmPm(newValue, value)
- break
- default:
- break
- }
- }
- return this.clipDate(newValue)
- },
- clipDate(date) {
- const { mode } = this.data
- const minDate = this.getMinDate()
- const maxDate = this.getMaxDate()
- if (mode === DATETIME) {
- if (date < minDate) {
- return cloneDate(minDate)
- }
- if (date > maxDate) {
- return cloneDate(maxDate)
- }
- } else if (mode === DATE || mode === YEAR || mode === MONTH) {
- if (+date + ONE_DAY <= minDate) {
- return cloneDate(minDate)
- }
- if (date >= +maxDate + ONE_DAY) {
- return cloneDate(maxDate)
- }
- } else if (mode === TIME) {
- const maxHour = maxDate.getHours()
- const maxMinutes = maxDate.getMinutes()
- const minHour = minDate.getHours()
- const minMinutes = minDate.getMinutes()
- const hour = date.getHours()
- const minutes = date.getMinutes()
- if (hour < minHour || hour === minHour && minutes < minMinutes) {
- return cloneDate(minDate)
- }
- if (hour > maxHour || hour === maxHour && minutes > maxMinutes) {
- return cloneDate(maxDate)
- }
- }
- return date
- },
- getDate(d) {
- const date = d ? d : this.data.value
- return this.clipDate(date ? valueToDate(date, this.data) : this.getMinDate())
- },
- getDateData(date) {
- const { mode, lang } = this.data
- const locale = locales[lang]
- const selYear = date.getFullYear()
- const selMonth = date.getMonth()
- const minDateYear = this.getDateMember('min', 'year')
- const maxDateYear = this.getDateMember('max', 'year')
- const minDateMonth = this.getDateMember('min', 'month')
- const maxDateMonth = this.getDateMember('max', 'month')
- const minDateDay = this.getDateMember('min', 'day')
- const maxDateDay = this.getDateMember('max', 'day')
- const years = fomartArray(minDateYear, maxDateYear).map((i) => ({
- value: i + '',
- label: i + locale.year + '',
- }))
- if (mode === YEAR) {
- return [years]
- }
- const minMonth = minDateYear === selYear ? minDateMonth : 0
- const maxMonth = maxDateYear === selYear ? maxDateMonth : 11
- const months = fomartArray(minMonth, maxMonth).map((i) => ({
- value: i + '',
- label: i + 1 + locale.month + '',
- }))
- if (mode === MONTH) {
- return [years, months]
- }
- const minDay = minDateYear === selYear && minDateMonth === selMonth ? minDateDay : 1
- const maxDay = maxDateYear === selYear && maxDateMonth === selMonth ? maxDateDay : getDaysInMonth(date)
- const days = fomartArray(minDay, maxDay).map((i) => ({
- value: i + '',
- label: i + locale.day + '',
- }))
- return [years, months, days]
- },
- getTimeData(date) {
- let { minHour, maxHour, minMinute, maxMinute } = this.data
- const { mode, minuteStep, use12Hours, lang } = this.data
- const locale = locales[lang]
- const minDateMinute = this.getDateMember('min', 'minute')
- const maxDateMinute = this.getDateMember('max', 'minute')
- const minDateHour = this.getDateMember('min', 'hour')
- const maxDateHour = this.getDateMember('max', 'hour')
- const hour = date.getHours()
- if (mode === DATETIME) {
- const year = date.getFullYear()
- const month = date.getMonth()
- const day = date.getDate()
- const minDateYear = this.getDateMember('min', 'year')
- const maxDateYear = this.getDateMember('max', 'year')
- const minDateMonth = this.getDateMember('min', 'month')
- const maxDateMonth = this.getDateMember('max', 'month')
- const minDateDay = this.getDateMember('min', 'day')
- const maxDateDay = this.getDateMember('max', 'day')
- if (minDateYear === year && minDateMonth === month && minDateDay === day) {
- minHour = minDateHour
- if (minDateHour === hour) {
- minMinute = minDateMinute
- }
- }
- if (maxDateYear === year && maxDateMonth === month && maxDateDay === day) {
- maxHour = maxDateHour
- if (maxDateHour === hour) {
- maxMinute = maxDateMinute
- }
- }
- } else {
- minHour = minDateHour
- if (minDateHour === hour) {
- minMinute = minDateMinute
- }
- maxHour = maxDateHour
- if (maxDateHour === hour) {
- maxMinute = maxDateMinute
- }
- }
- let hours = []
- if (minHour === 0 && maxHour === 0 || minHour !== 0 && maxHour !== 0) {
- minHour = this.getDisplayHour(minHour)
- } else if (minHour === 0 && use12Hours) {
- minHour = 1
- hours.push({
- value: '0',
- label: locale.hour ? '12' + locale.hour : '12',
- })
- }
- maxHour = this.getDisplayHour(maxHour)
- hours = [...hours, ...fomartArray(minHour, maxHour).map((i) => ({
- value: i + '',
- label: locale.hour ? i + locale.hour + '' : pad(i),
- }))]
- const minutes = []
- const selMinute = date.getMinutes()
- for (let i = minMinute; i <= maxMinute; i += minuteStep) {
- minutes.push({
- value: i + '',
- label: locale.minute ? i + locale.minute + '' : pad(i),
- })
- if (selMinute > i && selMinute < i + minuteStep) {
- minutes.push({
- value: selMinute + '',
- label: locale.minute ? selMinute + locale.minute + '' : pad(selMinute),
- })
- }
- }
- const ampm = [{ value: '0', label: locale.am }, { value: '1', label: locale.pm }]
- return [hours, minutes].concat(use12Hours ? [ampm] : [])
- },
- getValueCols(d) {
- const { mode, use12Hours } = this.data
- const date = this.getDate(d)
- let cols = []
- let value = []
- if (mode === YEAR) {
- return {
- cols: this.getDateData(date),
- value: [date.getFullYear() + ''],
- }
- }
- if (mode === MONTH) {
- return {
- cols: this.getDateData(date),
- value: [date.getFullYear() + '', date.getMonth() + ''],
- }
- }
- if (mode === DATETIME || mode === DATE) {
- cols = this.getDateData(date)
- value = [date.getFullYear() + '', date.getMonth() + '', date.getDate() + '']
- }
- if (mode === DATETIME || mode === TIME) {
- cols = cols.concat(this.getTimeData(date))
- const hour = date.getHours()
- const selMinute = date.getMinutes()
- let dtValue = [hour + '', selMinute + '']
- let nhour = hour
- if (use12Hours) {
- nhour = hour === 0 ? 12 : (hour > 12 ? hour - 12 : hour)
- dtValue = [nhour + '', selMinute + '', (hour >= 12 ? 1 : 0) + '']
- }
- value = value.concat(dtValue)
- }
- return {
- value,
- cols,
- }
- },
- onValueChange(e) {
- const { value, index } = e.detail
- const newDate = this.getNewDate(value, index)
- const { value: newValue, cols: newCols } = this.getValueCols(newDate)
- const values = this.getValue(newValue, newCols)
- this.triggerEvent('valueChange', { ...e.detail, ...values, date: +newDate })
- },
- updatedCols() {
- const { cols } = this.getValueCols()
- this.setData({ cols })
- },
- updated(inputValue) {
- if (this.data.inputValue !== inputValue) {
- this.setData({
- inputValue,
- })
- }
- },
- setValue(value = this.data.inputValue) {
- const { value: inputValue } = this.getValueCols()
- this.updated(inputValue)
- },
- getValue(value = this.data.inputValue, cols = this.data.cols) {
- this.picker = this.picker || this.querySelector('#wux-picker')
- return {
- ...this.picker.getValue(value, cols),
- date: +this.getDate(),
- }
- },
- },
- attached() {
- this.setValue(this.data.value)
- },
- })
|