ORIENT/modules/system/assets/ui/js/datepicker.js

354 lines
9.8 KiB
JavaScript

/*
* DatePicker plugin
*
* - Documentation: ../docs/datepicker.md
*
* Dependences:
* - Pikaday plugin (pikaday.js)
* - Pikaday jQuery addon (pikaday.jquery.js)
* - Clockpicker plugin (jquery-clockpicker.js)
* - Moment library (moment.js)
* - Moment Timezone library (moment.timezone.js)
*/
+function ($) { "use strict";
var Base = $.oc.foundation.base,
BaseProto = Base.prototype
var DatePicker = function (element, options) {
this.$el = $(element)
this.options = options || {}
$.oc.foundation.controlUtils.markDisposable(element)
Base.call(this)
this.init()
}
DatePicker.prototype = Object.create(BaseProto)
DatePicker.prototype.constructor = DatePicker
DatePicker.prototype.init = function() {
var self = this,
$form = this.$el.closest('form'),
changeMonitor = $form.data('oc.changeMonitor')
if (changeMonitor !== undefined) {
changeMonitor.pause()
}
this.dbDateTimeFormat = 'YYYY-MM-DD HH:mm:ss'
this.dbDateFormat = 'YYYY-MM-DD'
this.dbTimeFormat = 'HH:mm:ss'
this.$dataLocker = $('[data-datetime-value]', this.$el)
this.$datePicker = $('[data-datepicker]', this.$el)
this.$timePicker = $('[data-timepicker]', this.$el)
this.hasDate = !!this.$datePicker.length
this.hasTime = !!this.$timePicker.length
this.ignoreTimezone = this.$el.get(0).hasAttribute('data-ignore-timezone')
this.initRegion()
if (this.hasDate) {
this.initDatePicker()
}
if (this.hasTime) {
this.initTimePicker()
}
if (changeMonitor !== undefined) {
changeMonitor.resume()
}
this.$timePicker.on('change.oc.datepicker', function() {
if (!$.trim($(this).val())) {
self.emptyValues()
}
else {
self.onSelectTimePicker()
}
})
this.$datePicker.on('change.oc.datepicker', function() {
if (!$.trim($(this).val())) {
self.emptyValues()
}
})
this.$el.one('dispose-control', this.proxy(this.dispose))
}
DatePicker.prototype.dispose = function() {
this.$timePicker.off('change.oc.datepicker')
this.$datePicker.off('change.oc.datepicker')
this.$el.off('dispose-control', this.proxy(this.dispose))
this.$el.removeData('oc.datePicker')
this.$el = null
this.options = null
BaseProto.dispose.call(this)
}
//
// Datepicker
//
DatePicker.prototype.initDatePicker = function() {
var self = this,
dateFormat = this.getDateFormat(),
now = moment().tz(this.timezone).format(dateFormat)
var pikadayOptions = {
yearRange: this.options.yearRange,
firstDay: this.options.firstDay,
showWeekNumber: this.options.showWeekNumber,
format: dateFormat,
setDefaultDate: now,
onOpen: function() {
var $field = $(this._o.trigger)
$(this.el).css({
left: 'auto',
right: $(window).width() - $field.offset().left - $field.outerWidth()
})
},
onSelect: function() {
self.onSelectDatePicker.call(self, this.getMoment())
}
}
var lang = this.getLang('datepicker', false)
if (lang) {
pikadayOptions.i18n = lang
}
this.$datePicker.val(this.getDataLockerValue(dateFormat))
if (this.options.minDate) {
pikadayOptions.minDate = new Date(this.options.minDate)
}
if (this.options.maxDate) {
pikadayOptions.maxDate = new Date(this.options.maxDate)
}
this.$datePicker.pikaday(pikadayOptions)
}
DatePicker.prototype.onSelectDatePicker = function(pickerMoment) {
var pickerValue = pickerMoment.format(this.dbDateFormat)
var timeValue = this.getTimePickerValue()
var momentObj = moment
.tz(pickerValue + ' ' + timeValue, this.dbDateTimeFormat, this.timezone)
.tz(this.appTimezone)
var lockerValue = momentObj.format(this.dbDateTimeFormat)
this.$dataLocker.val(lockerValue)
}
// Returns in user preference timezone
DatePicker.prototype.getDatePickerValue = function() {
var value = this.$datePicker.val()
if (!this.hasDate || !value) {
return moment.tz(this.appTimezone)
.tz(this.timezone)
.format(this.dbDateFormat)
}
return moment(value, this.getDateFormat()).format(this.dbDateFormat)
}
DatePicker.prototype.getDateFormat = function() {
var format = 'YYYY-MM-DD'
if (this.options.format) {
format = this.options.format
}
else if (this.locale) {
format = moment()
.locale(this.locale)
.localeData()
.longDateFormat('l')
}
return format
}
//
// Timepicker
//
DatePicker.prototype.initTimePicker = function() {
this.$timePicker.clockpicker({
autoclose: 'true',
placement: 'bottom',
align: 'right',
twelvehour: this.isTimeTwelveHour()
// afterDone: this.proxy(this.onSelectTimePicker)
})
this.$timePicker.val(this.getDataLockerValue(this.getTimeFormat()))
}
DatePicker.prototype.onSelectTimePicker = function() {
var pickerValue = this.$timePicker.val()
var timeValue = moment(pickerValue, this.getTimeFormat()).format(this.dbTimeFormat)
var dateValue = this.getDatePickerValue()
var momentObj = moment
.tz(dateValue + ' ' + timeValue, this.dbDateTimeFormat, this.timezone)
.tz(this.appTimezone)
var lockerValue = momentObj.format(this.dbDateTimeFormat)
this.$dataLocker.val(lockerValue)
}
// Returns in user preference timezone
DatePicker.prototype.getTimePickerValue = function() {
var value = this.$timePicker.val()
if (!this.hasTime || !value) {
return moment.tz(this.appTimezone)
.tz(this.timezone)
.format(this.dbTimeFormat)
}
return moment(value, this.getTimeFormat()).format(this.dbTimeFormat)
}
DatePicker.prototype.getTimeFormat = function() {
return this.isTimeTwelveHour()
? 'hh:mm A'
: 'HH:mm'
}
DatePicker.prototype.isTimeTwelveHour = function() {
return false
// Disabled for now: The analog clock design is pretty good
// at representing time regardless of the format. If we want
// to enable this, there should be some way to disable it
// again via the form field options.
// var momentObj = moment()
// if (this.locale) {
// momentObj = momentObj.locale(this.locale)
// }
// return momentObj
// .localeData()
// .longDateFormat('LT')
// .indexOf('A') !== -1;
}
//
// Utilities
//
DatePicker.prototype.emptyValues = function() {
this.$dataLocker.val('')
this.$datePicker.val('')
this.$timePicker.val('')
}
DatePicker.prototype.getDataLockerValue = function(format) {
var value = this.$dataLocker.val()
return value
? this.getMomentLoadValue(value, format)
: null
}
DatePicker.prototype.getMomentLoadValue = function(value, format) {
var momentObj = moment.tz(value, this.appTimezone)
if (this.locale) {
momentObj = momentObj.locale(this.locale)
}
momentObj = momentObj.tz(this.timezone)
return momentObj.format(format)
}
DatePicker.prototype.initRegion = function() {
this.locale = $('meta[name="backend-locale"]').attr('content')
this.timezone = $('meta[name="backend-timezone"]').attr('content')
this.appTimezone = $('meta[name="app-timezone"]').attr('content')
if (!this.appTimezone) {
this.appTimezone = 'UTC'
}
if (!this.timezone) {
this.timezone = 'UTC'
}
// Set both timezones to UTC to disable converting between them
if (this.ignoreTimezone) {
this.appTimezone = 'UTC'
this.timezone = 'UTC'
}
}
DatePicker.prototype.getLang = function(name, defaultValue) {
if ($.oc === undefined || $.oc.lang === undefined) {
return defaultValue
}
return $.oc.lang.get(name, defaultValue)
}
DatePicker.DEFAULTS = {
minDate: null,
maxDate: null,
format: null,
yearRange: 10,
firstDay: 0,
showWeekNumber: false
}
// PLUGIN DEFINITION
// ============================
var old = $.fn.datePicker
$.fn.datePicker = function (option) {
var args = Array.prototype.slice.call(arguments, 1), items, result
items = this.each(function () {
var $this = $(this)
var data = $this.data('oc.datePicker')
var options = $.extend({}, DatePicker.DEFAULTS, $this.data(), typeof option == 'object' && option)
if (!data) $this.data('oc.datePicker', (data = new DatePicker(this, options)))
if (typeof option == 'string') result = data[option].apply(data, args)
if (typeof result != 'undefined') return false
})
return result ? result : items
}
$.fn.datePicker.Constructor = DatePicker
$.fn.datePicker.noConflict = function () {
$.fn.datePicker = old
return this
}
$(document).on('render', function() {
$('[data-control="datepicker"]').datePicker()
});
}(window.jQuery);