|
|
- (function($K)
- {
- var datepickerId = 0;
-
- $K.add('module', 'datepicker', {
- translations: {
- en: {
- "days": [ 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun' ],
- "months": ['', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ],
- "months-short": ['', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
- }
- },
- init: function(app, context)
- {
- this.app = app;
- this.$doc = app.$doc;
- this.$win = app.$win;
- this.$body = app.$body;
- this.lang = app.lang;
- this.animate = app.animate;
-
- // defaults
- var defaults = {
- year: false,
- month: false,
- day: false,
- format: '%d.%m.%Y', // %d, %m, %F, %M, %Y
- embed: false,
- target: false,
- selectYear: false,
- sundayFirst: false,
- startDate: false, // string
- endDate: false, // string
- animationOpen: 'slideDown',
- animationClose: 'slideUp',
- };
-
- // context
- this.context = context;
- this.params = context.getParams(defaults);
- this.$element = context.getElement();
- this.$target = context.getTarget();
-
- // local
- this.uuid = datepickerId++;
- this.namespace = '.kube.datepicker-' + this.uuid;
- this.dateRegexp = /^(.*?)(\/|\.|,|\s|\-)(.*?)(?:\/|\.|,|\s|\-)(.*?)$/;
- this.value = '';
- this.today = {};
- this.current = {};
- this.next = {};
- this.prev = {};
- this.selected = {};
- },
-
- // public
- start: function()
- {
- this.$element.attr('uuid', this.uuid);
-
- // start / end date
- this._buildStartEndDate();
-
- // create datepicker
- this.$datepicker = $K.create('class.datepicker.box', this.app, this);
- this.$datepicker.build();
-
- // append
- if (this.params.embed)
- {
- this.build();
- this.update();
-
- this.$datepicker.addClass('is-embed');
- this.$element.append(this.$datepicker);
- }
- else
- {
- this.$datepicker.addClass('is-hidden');
- this.$body.append(this.$datepicker);
- this.$element.on('click' + this.namespace, this._open.bind(this));
- }
- },
- stop: function()
- {
- this._disableEvents();
-
- this.$datepicker.remove();
-
- this.$element.off(this.namespace);
- this.$element.removeClass('datepicker-in');
- },
- build: function()
- {
- this._buildValue();
- this._buildTodayDate();
- this._buildSelectedDate();
- this._buildCurrentDate();
- },
- update: function()
- {
- this._buildPrevNextDate();
-
- this.$grid = $K.create('class.datepicker.grid', this.app, this);
- this.$grid.build();
-
- this.$datepicker.setControls(this.prev, this.next);
- this.$datepicker.setMonth(this.lang.get('months')[this.current.month]);
- this.$datepicker.setYear(this.current.year);
- this.$datepicker.setGrid(this.$grid);
- },
-
- // SET
- setDate: function(e)
- {
- e.preventDefault();
-
- var $item = $K.dom(e.target);
- if ($item.attr('data-disabled') === true) return this._close();
-
- var obj = {
- day: $item.attr('data-day'),
- month: $item.attr('data-month'),
- year: $item.attr('data-year')
- };
-
- var date = this._convertDateToFormat(obj);
-
- if (this.params.embed === false)
- {
- var $target = (this.$target.length !== 0) ? this.$target : this.$element;
-
- if ($target.get().tagName === 'INPUT')
- {
- $target.val(date);
- }
- else
- {
- $target.text(date);
- }
-
- this._close();
- }
-
- this.app.broadcast('datepicker.set', this, date, obj);
- },
- setNextMonth: function(e)
- {
- e.preventDefault();
-
- this.current = this.next;
- this.update();
- },
- setPrevMonth: function(e)
- {
- e.preventDefault();
-
- this.current = this.prev;
- this.update();
- },
- setYear: function()
- {
- this.current.year = this.$datepicker.getYearFromSelect();
- this.selected.day = false;
-
- this.$datepicker.setYear(this.current.year);
-
- this.update();
- },
-
- // BUILD
- _buildValue: function()
- {
- var $target = (this.$target.length !== 0) ? this.$target : this.$element;
-
- this.value = ($target.get().tagName === 'INPUT') ? $target.val() : $target.text().trim();
- },
- _buildTodayDate: function()
- {
- var date = new Date();
-
- this.today = {
- year: date.getFullYear(),
- month: parseInt(date.getMonth() + 1),
- day: parseInt(date.getDate())
- };
- },
- _buildSelectedDate: function()
- {
- this.selected = this._parseDateString(this.value);
-
- // set from params
- if (this.value === '')
- {
- this.selected.year = (this.params.year) ? this.params.year : this.selected.year;
- this.selected.month = (this.params.month) ? parseInt(this.params.month) : this.selected.month;
- this.selected.day = false;
- }
- },
- _buildCurrentDate: function()
- {
- this.current = this.selected;
- },
- _buildPrevNextDate: function()
- {
- // prev
- var date = this._getPrevYearAndMonth(this.current.year, this.current.month);
- this.prev = {
- year: date.year,
- month: date.month
- };
-
- // next
- var date = this._getNextYearAndMonth(this.current.year, this.current.month);
- this.next = {
- year: date.year,
- month: date.month
- };
- },
- _buildStartEndDate: function()
- {
- this.params.startDate = (this.params.startDate) ? this._parseDateString(this.params.startDate) : false;
- this.params.endDate = (this.params.endDate) ? this._parseDateString(this.params.endDate) : false;
- },
- _buildPosition: function()
- {
- this.position = {};
-
- var pos = this.$element.offset();
- var height = this.$element.innerHeight();
- var width = this.$element.innerWidth();
-
- var datepickerWidth = this.$datepicker.innerWidth();
- var datepickerHeight = this.$datepicker.innerHeight();
-
- var windowWidth = this.$win.width();
- var documentHeight = this.$doc.height();
-
- var right = 0;
- var left = pos.left;
- var top = pos.top + height + 1;
-
- this.position.type = 'left';
-
- if ((left + datepickerWidth) > windowWidth)
- {
- this.position.type = 'right';
- right = (windowWidth - (left + width));
- }
-
- if ((top + datepickerHeight) > documentHeight)
- {
- this.params.animationOpen = 'show';
- this.params.animationClose = 'hide';
-
- top = (top - datepickerHeight - height - 2);
- }
-
- this.position.top = top;
- this.position.left = left;
- this.position.right = right;
- },
-
- // OPEN
- _open: function(e)
- {
- if (e) e.preventDefault();
-
- if (this._isOpened()) return;
-
- this._closeAll();
- this.app.broadcast('datepicker.open', this);
-
- this.build();
- this.update();
-
- this._buildPosition();
- this._setPosition();
-
- this.animate.run(this.$datepicker, this.params.animationOpen, this._opened.bind(this));
- },
- _opened: function()
- {
- this._enableEvents();
- this.$element.addClass('datepicker-in');
- this.$datepicker.addClass('is-open');
- this.app.broadcast('datepicker.opened', this);
- },
- _isOpened: function()
- {
- return this.$datepicker.hasClass('is-open');
- },
-
- // CLOSE
- _close: function(e)
- {
- if (e && $K.dom(e.target).closest('.datepicker').length !== 0)
- {
- return;
- }
-
- if (!this._isOpened()) return;
-
- this.app.broadcast('datepicker.close', this);
- this.animate.run(this.$datepicker, this.params.animationClose, this._closed.bind(this));
- },
- _closed: function()
- {
- this._disableEvents();
- this.$datepicker.removeClass('is-open');
- this.$element.removeClass('datepicker-in');
- this.app.broadcast('datepicker.closed', this);
- },
- _closeAll: function()
- {
- $K.dom('.datepicker.is-open').each(function(node)
- {
- var $el = $K.dom(node);
- var id = $el.attr('data-uuid');
-
- this.$doc.off('.kube.datepicker-' + id);
- this.$win.off('.kube.datepicker-' + id);
-
- $el.removeClass('is-open');
- $el.addClass('is-hidden');
-
- }.bind(this));
-
- $K.dom('.datepicker-in').removeClass('datepicker-in');
- },
-
- // EVENTS
- _handleKeyboard: function(e)
- {
- if (e.which === 27) this._close();
- },
- _enableEvents: function()
- {
- this.$doc.on('keyup' + this.namespace, this._handleKeyboard.bind(this));
- this.$doc.on('click' + this.namespace + ' touchstart' + this.namespace, this._close.bind(this));
- this.$win.on('resize' + this.namespace, this._resizePosition.bind(this));
- },
- _disableEvents: function()
- {
- this.$doc.off(this.namespace);
- this.$win.off(this.namespace);
- },
-
- // POSITION
- _resizePosition: function()
- {
- this._buildPosition();
- this._setPosition();
- },
- _setPosition: function()
- {
- var left = 'auto';
- var right = this.position.right + 'px';
-
- if (this.position.type === 'left')
- {
- left = this.position.left + 'px',
- right = 'auto';
- }
-
- this.$datepicker.css({ top: this.position.top + 'px', left: left, right: right });
- },
-
- // PARSE
- _parseDateString: function(str)
- {
- var obj = {};
- var date = str.match(this.dateRegexp);
- var format = this.params.format.match(this.dateRegexp);
-
- obj.year = (date === null) ? this.today.year : parseInt(date[4]);
-
- if (format[1] === '%m' || format[1] === '%M' || format[1] === '%F')
- {
- obj.month = (date === null) ? this.today.month : this._parseMonth(format[1], date[1]);
- obj.day = (date === null) ? false : parseInt(date[3]);
- }
- else
- {
- obj.month = (date === null) ? this.today.month : this._parseMonth(format[3], date[3]);
- obj.day = (date === null) ? false : parseInt(date[1]);
- }
-
- obj.splitter = (date === null) ? '.' : date[2];
-
- return obj;
- },
- _parseMonth: function(type, month)
- {
- var index = parseInt(month);
-
- if (type === '%M') index = this.lang.get('months-short').indexOf(month);
- else if (type === '%F') index = this.lang.get('months').indexOf(month);
-
- return index;
- },
-
- // CONVERT
- _convertDateToFormat: function(obj)
- {
- var formated = this.params.format.replace('%d', obj.day);
- formated = formated.replace('%F', this.lang.get('months')[obj.month]);
- formated = formated.replace('%m', this._addZero(obj.month));
- formated = formated.replace('%M', this.lang.get('months-short')[obj.month]);
- formated = formated.replace('%Y', obj.year);
-
- return formated;
- },
- _addZero: function(str)
- {
- str = Number(str);
- return (str < 10) ? '0' + str : str;
- },
-
- // GET
- _getPrevYearAndMonth: function(year, month)
- {
- var date = {
- year: year,
- month: parseInt(month) - 1
- };
-
- if (date.month <= 0)
- {
- date.month = 12;
- date.year--;
- }
-
- return date;
- },
- _getNextYearAndMonth: function(year, month)
- {
- var date = {
- year: year,
- month: parseInt(month) + 1
- };
-
- if (date.month > 12)
- {
- date.month = 1;
- date.year++;
- }
-
- return date;
- }
- });
- })(Kube);
- (function($K)
- {
- $K.add('class', 'datepicker.box', {
- extends: ['dom'],
- init: function(app, datepicker)
- {
- this.app = app;
- this.lang = app.lang;
- this.datepicker = datepicker;
- this.params = datepicker.params;
- this.namespace = datepicker.namespace;
- this.selected = datepicker.selected;
- },
- build: function()
- {
- this._buildBox();
- this._buildHead();
- this._buildControlPrev();
- this._buildMonthBox();
- this._buildControlNext();
- this._buildWeekdays();
- this._buildBody();
- },
- getYearFromSelect: function()
- {
- return Number(this.$yearSelect.val());
- },
- setMonth: function(month)
- {
- this.$month.html(month);
- },
- setYear: function(year)
- {
- this.$yearValue.html(year);
-
- if (this.params.selectYear && this.$yearSelect)
- {
- this.$yearSelect.val(year);
- }
- },
- setGrid: function($grid)
- {
- this.$dbody.html('');
- this.$dbody.append($grid);
- },
- setControls: function(prev, next)
- {
- var buildDate = function(obj, d)
- {
- d = (d) ? d : obj.day;
-
- return new Date(obj.year + '/' + obj.month + '/' + d);
- }
-
- if (this.params.startDate)
- {
- var datePrev = buildDate(prev, 31);
- var start = buildDate(this.params.startDate);
- var fn = (start.getTime() > datePrev.getTime()) ? 'hide' : 'show';
-
- this.$prev[fn]();
- }
-
- if (this.params.endDate)
- {
- var dateNext = buildDate(next, 1);
- var end = buildDate(this.params.endDate);
- var fn = (end.getTime() < dateNext.getTime()) ? 'hide' : 'show';
-
- this.$next[fn]();
- }
- },
- // private
- _buildBox: function()
- {
- this.parse('<div>');
- this.addClass('datepicker');
- },
- _buildHead: function()
- {
- this.$head = $K.dom('<div class="datepicker-head">');
- this.append(this.$head);
- },
- _buildControlPrev: function()
- {
- this.$prev = $K.dom('<span class="datepicker-control datepicker-control-prev" />').html('<');
- this.$prev.on('click' + this.namespace, this.datepicker.setPrevMonth.bind(this.datepicker));
- this.$head.append(this.$prev);
- },
- _buildControlNext: function()
- {
- this.$next = $K.dom('<span class="datepicker-control datepicker-control-next" />').html('>');
- this.$next.on('click' + this.namespace, this.datepicker.setNextMonth.bind(this.datepicker));
- this.$head.append(this.$next);
- },
- _buildMonthBox: function()
- {
- this.$monthBox = $K.dom('<div class="datepicker-month-box">');
- this.$head.append(this.$monthBox);
-
- this._buildMonth();
- this._buildYear();
- this._buildYearSelect();
- },
- _buildMonth: function()
- {
- this.$month = $K.dom('<span />');
- this.$monthBox.append(this.$month);
- },
- _buildYear: function()
- {
- this.$year = $K.dom('<span />');
- this.$yearValue = $K.dom('<span />');
- this.$year.append(this.$yearValue);
-
- this.$monthBox.append(this.$year);
- },
- _buildYearSelect: function()
- {
- if (!this.params.selectYear) return;
-
- var now = new Date();
- var start = (this.params.startDate) ? this.params.startDate.year : (now.getFullYear() - 99);
- var end = (this.params.endDate) ? this.params.endDate.year : now.getFullYear();
-
- if ((end - start) < 2)
- {
- return;
- }
-
- this.$yearSelect = $K.dom('<select />');
- this.$year.append(this.$yearSelect);
- this.$year.append('<span class="datepicker-select-year-caret" />');
- this.$year.addClass('datepicker-select-year');
-
- for (var i = start; i <= end; i++)
- {
- var $option = $K.dom('<option value="' + i + '">' + i + '</option>');
- this.$yearSelect.append($option);
- }
-
- this.$yearSelect.on('change' + this.namespace, this.datepicker.setYear.bind(this.datepicker));
-
- },
- _buildWeekdays: function()
- {
- this.$weekdays = $K.dom('<div class="datepicker-weekdays">');
-
- var result = [];
- if (this.params.sundayFirst)
- {
- var last = this.lang.get('days').slice(6);
- result = this.lang.get('days').slice(0, 6);
- result.unshift(last[0]);
- }
- else
- {
- result = this.lang.get('days');
- }
-
- for (var i = 0; i < result.length; i++)
- {
- var tr = $K.dom('<span>').html(result[i]);
- this.$weekdays.append(tr);
- }
-
- this.append(this.$weekdays);
- },
- _buildBody: function()
- {
- this.$dbody = $K.dom('<div class="datepicker-body">');
- this.append(this.$dbody);
- }
-
-
- });
- })(Kube);
- (function($K)
- {
- $K.add('class', 'datepicker.grid', {
- extends: ['dom'],
- init: function(app, datepicker)
- {
- this.app = app;
- this.lang = app.lang;
- this.datepicker = datepicker;
- this.params = datepicker.params;
- this.namespace = datepicker.namespace;
- this.today = datepicker.today;
- this.selected = datepicker.selected;
- this.current = datepicker.current;
- this.prev = datepicker.prev;
- this.next = datepicker.next;
-
- // local
- this.daysInMonth = [0,31,28,31,30,31,30,31,31,30,31,30,31];
- },
- build: function()
- {
- this.parse('<div class="datepicker-grid">');
-
- var daysInCurrentMonth = this._getDaysInCurrentMonth();
- var daysInPrevMonth = this._getDaysInPrevMonth();
- var daysInNextMonth = this._getDaysInNextMonth();
-
- // start index
- var d = new Date(this.current.year, this.current.month - 1, 1);
- var startIndex = (this.params.sundayFirst) ? d.getDay() + 1 : ((!d.getDay()) ? 7 : d.getDay());
-
- var daysPrevMonthStart = daysInPrevMonth - startIndex + 2;
- var startCurrent = 8 - startIndex;
-
- var y = 1, c = 1, obj;
- for (var z = 0; z < 6; z++)
- {
- var tr = $K.dom('<div class="datepicker-row">');
-
- for (var i = 0; i < 7; i++)
- {
- if (z === 0)
- {
- var dayPrev = daysPrevMonthStart + i;
- if (dayPrev > daysInPrevMonth)
- {
-
- // current day
- obj = this._buildGridObj(i, y, this.current, false, false);
- y++;
- }
- else
- {
- // prev day
- obj = this._buildGridObj(i, dayPrev, this.prev, false, true);
- }
- }
- else if (y > daysInCurrentMonth)
- {
- // next day
- obj = this._buildGridObj(i, c, this.next, true, false);
- c++;
-
- }
- else
- {
- // current day
- obj = this._buildGridObj(i, y, this.current, false, false);
- y++;
- }
-
- tr.append(this._buildGridDay(obj));
- }
-
- this.append(tr);
- }
- },
-
- // private
- _buildGridObj: function(i, day, date, next, prev)
- {
- return {
- day: day,
- next: next,
- prev: prev,
- year: date.year,
- month: date.month,
- date: this._getGridDay(date.year, date.month, day),
- selected: this._isSelectedDate(date.year, date.month, day),
- today: this._isTodayDate(date.year, date.month, day),
- weekend: (i > 4),
- disabled: this._isDisabledDate(date.year, date.month, day)
- };
- },
- _buildGridDay: function(obj)
- {
- var td = $K.dom('<div class="datepicker-cell">');
-
- if (obj.next || obj.prev)
- {
- td.addClass('is-out');
- }
-
- if (obj.selected) td.addClass('is-selected');
- if (obj.today) td.addClass('is-today');
- if (obj.weekend && this.params.weekend) td.addClass('is-weekend');
- if (obj.disabled) td.addClass('is-disabled');
-
- var $item = $K.dom('<a>');
-
- $item.html(obj.day);
- $item.attr('href', '#');
-
- $item.attr('data-disabled', obj.disabled);
- $item.attr('data-date', obj.date);
- $item.attr('data-day', obj.day);
- $item.attr('data-month', obj.month);
- $item.attr('data-year', obj.year);
-
- $item.on('click', this.datepicker.setDate.bind(this.datepicker));
-
- return td.append($item);
-
- },
- _isSelectedDate: function(year, month, day)
- {
- return (this.selected.year === year && this.selected.month === month && this.selected.day === day);
- },
- _isTodayDate: function(year, month, day)
- {
- return (this.today.year === year && this.today.month === month && this.today.day === day);
- },
- _isDisabledDate: function(year, month, day)
- {
- var date = new Date(year + '/' + month + '/' + day);
-
- if (this.params.startDate)
- {
- var dateStart = new Date(this.params.startDate.year + '/' + this.params.startDate.month + '/' + this.params.startDate.day);
- if (date.getTime() < dateStart.getTime())
- {
- return true;
- }
- }
-
- if (this.params.endDate)
- {
- var dateEnd = new Date(this.params.endDate.year + '/' + this.params.endDate.month + '/' + this.params.endDate.day);
- if (date.getTime() > dateEnd.getTime())
- {
- return true;
- }
- }
-
- return false;
- },
- _getGridDay: function(year, month, day)
- {
- return year + '-' + month + '-' + day;
- },
- _getDaysInCurrentMonth: function()
- {
- return this._getDaysInMonth(this.current.year, this.current.month);
- },
- _getDaysInPrevMonth: function()
- {
- return this._getDaysInMonth(this.prev.year, this.prev.month);
- },
- _getDaysInNextMonth: function()
- {
- return this._getDaysInMonth(this.next.year, this.next.month);
- },
- _getDaysInMonth: function (year, month)
- {
- return (((0 === (year%4)) && ((0 !== (year%100)) || (0 === (year%400)))) && (month === 1)) ? 29 : this.daysInMonth[month];
- }
- });
- })(Kube);
|