UNPKG

hae

Version:

Mobile web UI based on Vux

251 lines (237 loc) 7.3 kB
import Eventor from '../../libs/eventor' // https://github.com/MoeKit/clocker var instances = [] var matchers = [] // Miliseconds matchers.push(/^[0-9]*$/.source) // Month/Day/Year [hours:minutes:seconds] matchers.push(/([0-9]{1,2}\/){2}[0-9]{4}( [0-9]{1,2}(:[0-9]{2}){2})?/ .source) // Year/Day/Month [hours:minutes:seconds] and // Year-Day-Month [hours:minutes:seconds] matchers.push(/[0-9]{4}([/-][0-9]{1,2}){2}( [0-9]{1,2}(:[0-9]{2}){2})?/ .source) // Cast the matchers to a regular expression object matchers = new RegExp(matchers.join('|')) // Parse a Date formatted has String to a native object function parseDateString (dateString) { // Pass through when a native object is sent if (dateString instanceof Date) { return dateString } // Caste string to date object if (String(dateString).match(matchers)) { // If looks like a milisecond value cast to number before // final casting (Thanks to @msigley) if (String(dateString).match(/^[0-9]*$/)) { dateString = Number(dateString) } // Replace dashes to slashes if (String(dateString).match(/-/)) { dateString = String(dateString).replace(/-/g, '/') } return new Date(dateString) } else { throw new Error('Couldn\'t cast `' + dateString + '` to a date object.') } } // Map to convert from a directive to offset object property var DIRECTIVE_KEY_MAP = { 'Y': 'years', 'm': 'months', 'w': 'weeks', 'D': 'days', 'H': 'hours', 'M': 'minutes', 'S': 'seconds' } // Returns an escaped regexp from the string function escapedRegExp (str) { var sanitize = str.toString().replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1') return new RegExp(sanitize) } // Time string formatter function strftime (offsetObject) { return function (format) { var directives = format.match(/%(-|!)?[A-Z]{1}(:[^]+)?/gi) var d2h = false if (directives.indexOf('%D') < 0 && directives.indexOf('%H') >= 0) { d2h = true } if (directives) { for (var i = 0, len = directives.length; i < len; ++i) { var directive = directives[i].match(/%(-|!)?([a-zA-Z]{1})(:[^]+)?/) var regexp = escapedRegExp(directive[0]) var modifier = directive[1] || '' var plural = directive[3] || '' var value = null var key = null // Get the key directive = directive[2] // Swap shot-versions directives if (DIRECTIVE_KEY_MAP.hasOwnProperty(directive)) { key = DIRECTIVE_KEY_MAP[directive] value = Number(offsetObject[key]) if (key === 'hours' && d2h) { value += Number(offsetObject['days']) * 24 } } if (value !== null) { // Pluralize if (modifier === '!') { value = pluralize(plural, value) } // Add zero-padding if (modifier === '') { if (value < 10) { value = '0' + value.toString() } } // Replace the directive format = format.replace(regexp, value.toString()) } } } format = format.replace('%_M1', offsetObject.minutes_1) .replace('%_M2', offsetObject.minutes_2) .replace('%_S1', offsetObject.seconds_1) .replace('%_S2', offsetObject.seconds_2) .replace('%_S3', offsetObject.seconds_3) .replace('%_H1', offsetObject.hours_1) .replace('%_H2', offsetObject.hours_2) .replace('%_H3', offsetObject.hours_3) .replace('%_D1', offsetObject.days_1) .replace('%_D2', offsetObject.days_2) .replace('%_D3', offsetObject.days_3) format = format.replace(/%%/, '%') return format } } // Pluralize function pluralize (format, count) { var plural = 's' var singular = '' if (format) { format = format.replace(/(:||\s)/gi, '').split(/,/) if (format.length === 1) { plural = format[0] } else { singular = format[0] plural = format[1] } } if (Math.abs(count) === 1) { return singular } else { return plural } } function splitNumber (number) { number = number + '' number = (number.length === 1 ? ('0' + number) : number) + '' return number.split('') } // The Final Countdown var Countdown = function (finalDate, option) { option = option || {} this.PRECISION = option.precision || 100 // 0.1 seconds, used to update the DOM this.interval = null this.offset = {} // Register this instance this.instanceNumber = instances.length instances.push(this) // Set the final date and start this.setFinalDate(finalDate) } Eventor.mixTo(Countdown) var pro = Countdown.prototype var fns = { start () { if (this.interval !== null) { clearInterval(this.interval) } var self = this this.update() this.interval = setInterval(function () { self.update() }, this.PRECISION) return this }, stop () { clearInterval(this.interval) this.interval = null this._dispatchEvent('stoped') return this }, toggle () { if (this.interval) { this.stop() } else { this.start() } return this }, pause () { return this.stop() }, resume () { return this.start() }, remove () { this.stop() instances[this.instanceNumber] = null }, setFinalDate (value) { this.finalDate = parseDateString(value) // Cast the given date return this }, getOffset () { this.totalSecsLeft = this.finalDate.getTime() - new Date().getTime() // In miliseconds this.totalSecsLeft = Math.ceil(this.totalSecsLeft / 1000) this.totalSecsLeft = this.totalSecsLeft < 0 ? 0 : this.totalSecsLeft // Calculate the offsets return { seconds: this.totalSecsLeft % 60, minutes: Math.floor(this.totalSecsLeft / 60) % 60, hours: Math.floor(this.totalSecsLeft / 60 / 60) % 24, days: Math.floor(this.totalSecsLeft / 60 / 60 / 24), weeks: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 7), months: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 30), years: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 365) } }, update () { // Calculate the offsets this.offset = this.getOffset() // split offset only for days, hours, minutes, seconds and two number like 45, do not support 100 var list = ['days', 'hours', 'minutes', 'seconds'] for (var i = 0; i < list.length; i++) { var key = list[i] var numbers = splitNumber(this.offset[key]) for (let n = 0; n < numbers.length; n++) { this.offset[`${key}_${n + 1}`] = numbers[n] } } // Dispatch an event if (this.totalSecsLeft === 0) { this.stop() this._dispatchEvent('finish') } else { this._dispatchEvent('update') } return this }, _dispatchEvent (eventName) { var event = {} event.finalDate = this.finalDate event.offset = this.offset event.strftime = strftime(this.offset) this.emit(eventName, event) this.emit('tick', event) } } for (var i in fns) { pro[i] = fns[i] } export default Countdown