import getFloatedTargetPos from '../utils/getFloatedTargetPos' import supportDom from '../decorators/supportDom' import { getHours, getMinutes, range, toPixel } from '../utils'
@supportDom export default class TimeMenu {
constructor() { this.date = null this.isVisible = false this.init() } init() { this.addMenu() this.addEvents() } getMenuItems(step) { const dayMins = 24 * 60 return range(0, dayMins, step) .reduce((arr, mins) => { const hour = parseInt(mins / 60, 10) const min = mins % 60 arr.push({ hour, min }) return arr }, []) .map(({ hour, min }) => { return `<div class="time-menu-item" data-hour="${hour}" data-minute="${min}">${hour}:${min.toString().padStart(2, '0')}</div>` }) .join('') } addMenu() { const dom = document.createElement('div') dom.className = 'time-menu' document.body.appendChild(dom) this.dom = dom } addEvents() { this.addEvent(this.dom, 'click', event => { const { dataset } = event.target if ('hour' in dataset) { const res = { hour: parseInt(dataset.hour, 10), minute: parseInt(dataset.minute, 10) } this.fire('click', event, res) } }) } pos(src) { const { dom } = this const { pos } = getFloatedTargetPos({ src, target: dom, place: 'bottom', align: 'right', offset: 4 }) dom.style.left = toPixel(pos.left) dom.style.top = toPixel(pos.top) } setActiveNode(node, active) { if (active) { return node.classList.add('active') } node.classList.remove('active') } updateItems(date) { const hour = getHours(date).toString() const minute = getMinutes(date).toString() Array.from(this.dom.childNodes) .forEach(node => { const { hour: datasetHour, minute: datasetMinute } = node.dataset const hourEqualed = (datasetHour === hour) const minuteEqualed = (datasetMinute === minute) if (hourEqualed && (datasetMinute === '0')) { this.dom.scrollTop = node.offsetTop } const active = (hourEqualed && minuteEqualed) this.setActiveNode(node, active) }) } show({ src, date, step = 30 }) { const { dom } = this dom.innerHTML = this.getMenuItems(step) dom.style.opacity = 0 dom.style.display = 'block' this.pos(src) this.updateItems(date) dom.style.opacity = 1 this.isVisible = true } hide() { this.dom.style.left = '-100%' this.dom.style.bottom = '-100%' this.dom.style.display = 'none' this.isVisible = false } destroy() { this.dom.remove() }
}