You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							477 lines
						
					
					
						
							16 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							477 lines
						
					
					
						
							16 KiB
						
					
					
				| import baseComponent from '../helpers/baseComponent' | |
| import classNames from '../helpers/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.selectComponent('#wux-picker') | |
|             return { | |
|                 ...this.picker.getValue(value, cols), | |
|                 date: +this.getDate(), | |
|             } | |
|         }, | |
|     }, | |
|     attached() { | |
|         this.setValue(this.data.value) | |
|     }, | |
| }) | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 |