diff --git a/app/assets/javascripts/datetimepicker.js b/app/assets/javascripts/datetimepicker.js
new file mode 100644
index 00000000..cba600d9
--- /dev/null
+++ b/app/assets/javascripts/datetimepicker.js
@@ -0,0 +1,17 @@
+$(document).ready(function(){
+
+ $('.date_picker').datetimepicker({
+ pickTime: false
+ });
+
+ $('.default_picker').datetimepicker();
+
+ $('.time_picker').datetimepicker({
+ pickDate: false
+ });
+
+ $('.separated_picker div').on("changeDate",function(){
+ $(this).siblings('input').val($(this).find('input').val() + ' ' + $(this).siblings('div').find('input').val());
+ });
+
+});
\ No newline at end of file
diff --git a/app/assets/javascripts/lib/bootstrap-datetimepicker.js b/app/assets/javascripts/lib/bootstrap-datetimepicker.js
new file mode 100644
index 00000000..0a24464d
--- /dev/null
+++ b/app/assets/javascripts/lib/bootstrap-datetimepicker.js
@@ -0,0 +1,1156 @@
+/**
+ * @license
+ * =========================================================
+ * bootstrap-datetimepicker.js
+ * http://www.eyecon.ro/bootstrap-datepicker
+ * =========================================================
+ * Copyright 2012 Stefan Petre
+ *
+ * Contributions:
+ * - Andrew Rowls
+ * - Thiago de Arruda
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =========================================================
+ */
+
+(function($) {
+
+ // Picker object
+ var smartPhone = (window.orientation != undefined);
+ var DateTimePicker = function(element, options) {
+ this.id = dpgId++;
+ this.init(element, options);
+ };
+
+ DateTimePicker.prototype = {
+ constructor: DateTimePicker,
+
+ init: function(element, options) {
+ var icon;
+ if (!(options.pickTime || options.pickDate))
+ throw new Error('Must choose at least one picker');
+ this.options = options;
+ this.$element = $(element);
+ this.language = options.language in dates ? options.language : 'en'
+ this.pickDate = options.pickDate;
+ this.pickTime = options.pickTime;
+ this.isInput = this.$element.is('input');
+ // this.component = this.$element.is('.input-prepend') ? this.$element.find('.add-on') : false;
+ this.component = this.$element.is('.input-append') ? this.$element.find('.add-on') : false;
+ this.format = options.format;
+ if (!this.format) {
+ if (this.isInput) this.format = this.$element.data('format');
+ else this.format = this.$element.find('input').data('format');
+ if (!this.format) this.format = 'MM/dd/yyyy';
+ }
+ this._compileFormat();
+ if (this.component) {
+ icon = this.component.find('i');
+ }
+ if (this.pickTime) {
+ if (icon && icon.length) this.timeIcon = icon.data('time-icon');
+ if (!this.timeIcon) this.timeIcon = 'icon-time';
+ icon.addClass(this.timeIcon);
+ }
+ if (this.pickDate) {
+ if (icon && icon.length) this.dateIcon = icon.data('date-icon');
+ if (!this.dateIcon) this.dateIcon = 'icon-calendar';
+ icon.removeClass(this.timeIcon);
+ icon.addClass(this.dateIcon);
+ }
+ this.widget = $(getTemplate(this.timeIcon, options.pickDate, options.pickTime, options.pick12HourFormat)).appendTo('body');
+ this.minViewMode = options.minViewMode||this.$element.data('date-minviewmode')||0;
+ if (typeof this.minViewMode === 'string') {
+ switch (this.minViewMode) {
+ case 'months':
+ this.minViewMode = 1;
+ break;
+ case 'years':
+ this.minViewMode = 2;
+ break;
+ default:
+ this.minViewMode = 0;
+ break;
+ }
+ }
+ this.viewMode = options.viewMode||this.$element.data('date-viewmode')||0;
+ if (typeof this.viewMode === 'string') {
+ switch (this.viewMode) {
+ case 'months':
+ this.viewMode = 1;
+ break;
+ case 'years':
+ this.viewMode = 2;
+ break;
+ default:
+ this.viewMode = 0;
+ break;
+ }
+ }
+ this.startViewMode = this.viewMode;
+ this.weekStart = options.weekStart||this.$element.data('date-weekstart')||0;
+ this.weekEnd = this.weekStart === 0 ? 6 : this.weekStart - 1;
+ this.fillDow();
+ this.fillMonths();
+ this.fillHours();
+ this.fillMinutes();
+ this.fillSeconds();
+ this.update();
+ this.showMode();
+ this._attachDatePickerEvents();
+ },
+
+ show: function(e) {
+ this.widget.show();
+ this.height = this.component ? this.component.outerHeight() : this.$element.outerHeight();
+ this.width = this.component ? this.component.outerWidth() : this.$element.outerWidth();
+ this.place();
+ this.$element.trigger({
+ type: 'show',
+ date: this._date
+ });
+ this._attachDatePickerGlobalEvents();
+ if (e) {
+ e.stopPropagation();
+ e.preventDefault();
+ }
+ },
+
+ hide: function() {
+ // Ignore event if in the middle of a picker transition
+ var collapse = this.widget.find('.collapse')
+ for (var i = 0; i < collapse.length; i++) {
+ var collapseData = collapse.eq(i).data('collapse');
+ if (collapseData && collapseData.transitioning)
+ return;
+ }
+ this.widget.hide();
+ this.viewMode = this.startViewMode;
+ this.showMode();
+ // this.set();
+ this.$element.trigger({
+ type: 'hide',
+ date: this._date
+ });
+ this.actions.showPicker.call(this);
+ this._detachDatePickerGlobalEvents();
+ },
+
+ set: function() {
+ var formatted = '';
+ if (!this._unset) formatted = this.formatDate(this._date);
+ if (!this.isInput) {
+ if (this.component){
+ var input = this.$element.find('input');
+ input.val(formatted);
+ this._resetMaskPos(input);
+ }
+ this.$element.data('date', formatted);
+ } else {
+ this.$element.val(formatted);
+ this._resetMaskPos(this.$element);
+ }
+ },
+
+ setValue: function(newDate) {
+ if (!newDate) {
+ this._unset = true;
+ } else {
+ this._unset = false;
+ }
+ if (typeof newDate === 'string') {
+ this._date = this.parseDate(newDate);
+ } else {
+ this._date = new Date(newDate);
+ }
+ this.set();
+ this.viewDate = UTCDate(this._date.getUTCFullYear(), this._date.getUTCMonth(), 1, 0, 0, 0, 0);
+ this.fillDate();
+ this.fillTime();
+ },
+
+ getDate: function() {
+ if (this._unset) return null;
+ return new Date(this._date.valueOf());
+ },
+
+ setDate: function(date) {
+ if (!date) this.setValue(null);
+ else this.setValue(date.valueOf());
+ },
+
+ getLocalDate: function() {
+ if (this._unset) return null;
+ var d = this._date;
+ return new Date(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(),
+ d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds(), d.getUTCMilliseconds());
+ },
+
+ setLocalDate: function(localDate) {
+ if (!localDate) this.setValue(null);
+ else
+ this.setValue(Date.UTC(
+ localDate.getFullYear(),
+ localDate.getMonth(),
+ localDate.getDate(),
+ localDate.getHours(),
+ localDate.getMinutes(),
+ localDate.getSeconds(),
+ localDate.getMilliseconds()));
+ },
+
+ place: function(){
+ var offset = this.component ? this.component.offset() : this.$element.offset(),
+ input = this.$element.find('input');
+ this.widget.css({
+ top: offset.top + this.height,
+ left: offset.left - input.outerWidth(),
+ });
+ },
+
+ notifyChange: function(){
+ this.$element.trigger({
+ type: 'changeDate',
+ date: this.getDate(),
+ localDate: this.getLocalDate()
+ });
+ },
+
+ update: function(newDate){
+ var dateStr = newDate;
+ if (!dateStr) {
+ if (this.isInput) {
+ dateStr = this.$element.val();
+ } else {
+ dateStr = this.$element.find('input').val();
+ }
+ if (!dateStr) {
+ var tmp = new Date()
+ this._date = UTCDate(tmp.getFullYear(),
+ tmp.getMonth(),
+ tmp.getDate(),
+ tmp.getHours(),
+ tmp.getMinutes(),
+ tmp.getSeconds(),
+ tmp.getMilliseconds())
+ } else {
+ this._date = this.parseDate(dateStr);
+ }
+ }
+ this.viewDate = UTCDate(this._date.getUTCFullYear(), this._date.getUTCMonth(), 1, 0, 0, 0, 0);
+ this.fillDate();
+ this.fillTime();
+ },
+
+ fillDow: function() {
+ var dowCnt = this.weekStart;
+ var html = '
';
+ while (dowCnt < this.weekStart + 7) {
+ html += '' + dates[this.language].daysMin[(dowCnt++) % 7] + ' | ';
+ }
+ html += '
';
+ this.widget.find('.datepicker-days thead').append(html);
+ },
+
+ fillMonths: function() {
+ var html = '';
+ var i = 0
+ while (i < 12) {
+ html += '' + dates[this.language].monthsShort[i++] + '';
+ }
+ this.widget.find('.datepicker-months td').append(html);
+ },
+
+ fillDate: function() {
+ var year = this.viewDate.getUTCFullYear();
+ var month = this.viewDate.getUTCMonth();
+ var currentDate = UTCDate(
+ this._date.getUTCFullYear(),
+ this._date.getUTCMonth(),
+ this._date.getUTCDate(),
+ 0, 0, 0, 0
+ );
+ this.widget.find('.datepicker-days th:eq(1)').text(
+ dates[this.language].months[month] + ' ' + year);
+ var prevMonth = UTCDate(year, month-1, 28, 0, 0, 0, 0);
+ var day = DPGlobal.getDaysInMonth(
+ prevMonth.getUTCFullYear(), prevMonth.getUTCMonth());
+ prevMonth.setUTCDate(day);
+ prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.weekStart + 7) % 7);
+ var nextMonth = new Date(prevMonth.valueOf());
+ nextMonth.setUTCDate(nextMonth.getUTCDate() + 42);
+ nextMonth = nextMonth.valueOf();
+ var html = [];
+ var clsName;
+ while (prevMonth.valueOf() < nextMonth) {
+ if (prevMonth.getUTCDay() === this.weekStart) {
+ html.push('');
+ }
+ clsName = '';
+ if (prevMonth.getUTCFullYear() < year ||
+ (prevMonth.getUTCFullYear() == year &&
+ prevMonth.getUTCMonth() < month)) {
+ clsName += ' old';
+ } else if (prevMonth.getUTCFullYear() > year ||
+ (prevMonth.getUTCFullYear() == year &&
+ prevMonth.getUTCMonth() > month)) {
+ clsName += ' new';
+ }
+ if (prevMonth.valueOf() === currentDate.valueOf()) {
+ clsName += ' active';
+ }
+ html.push('' + prevMonth.getUTCDate() + ' | ');
+ if (prevMonth.getUTCDay() === this.weekEnd) {
+ html.push('
');
+ }
+ prevMonth.setUTCDate(prevMonth.getUTCDate() + 1);
+ }
+ this.widget.find('.datepicker-days tbody').empty().append(html.join(''));
+ var currentYear = this._date.getUTCFullYear();
+
+ var months = this.widget.find('.datepicker-months').find(
+ 'th:eq(1)').text(year).end().find('span').removeClass('active');
+ if (currentYear === year) {
+ months.eq(this._date.getUTCMonth()).addClass('active');
+ }
+
+ html = '';
+ year = parseInt(year/10, 10) * 10;
+ var yearCont = this.widget.find('.datepicker-years').find(
+ 'th:eq(1)').text(year + '-' + (year + 9)).end().find('td');
+ year -= 1;
+ for (var i = -1; i < 11; i++) {
+ html += '' + year + '';
+ year += 1;
+ }
+ yearCont.html(html);
+ },
+
+ fillHours: function() {
+ var table = this.widget.find(
+ '.timepicker .timepicker-hours table');
+ table.parent().hide();
+ var html = '';
+ if (this.options.pick12HourFormat) {
+ var current = 1;
+ for (var i = 0; i < 3; i += 1) {
+ html += '';
+ for (var j = 0; j < 4; j += 1) {
+ var c = current.toString();
+ html += '' + padLeft(c, 2, '0') + ' | ';
+ current++;
+ }
+ html += '
'
+ }
+ } else {
+ var current = 0;
+ for (var i = 0; i < 6; i += 1) {
+ html += '';
+ for (var j = 0; j < 4; j += 1) {
+ var c = current.toString();
+ html += '' + padLeft(c, 2, '0') + ' | ';
+ current++;
+ }
+ html += '
'
+ }
+ }
+ table.html(html);
+ },
+
+ fillMinutes: function() {
+ var table = this.widget.find(
+ '.timepicker .timepicker-minutes table');
+ table.parent().hide();
+ var html = '';
+ var current = 0;
+ for (var i = 0; i < 3; i++) {
+ html += '';
+ for (var j = 0; j < 4; j += 1) {
+ var c = current.toString();
+ html += '' + padLeft(c, 2, '0') + ' | ';
+ current += 5;
+ }
+ html += '
';
+ }
+ table.html(html);
+ },
+
+ fillSeconds: function() {
+ var table = this.widget.find(
+ '.timepicker .timepicker-seconds table');
+ table.parent().hide();
+ var html = '';
+ var current = 0;
+ for (var i = 0; i < 5; i++) {
+ html += '';
+ for (var j = 0; j < 4; j += 1) {
+ var c = current.toString();
+ html += '' + padLeft(c, 2, '0') + ' | ';
+ current += 3;
+ }
+ html += '
';
+ }
+ table.html(html);
+ },
+
+ fillTime: function() {
+ if (!this._date)
+ return;
+ var timeComponents = this.widget.find('.timepicker span[data-time-component]');
+ var table = timeComponents.closest('table');
+ var is12HourFormat = this.options.pick12HourFormat;
+ var hour = this._date.getUTCHours();
+ var period = 'AM';
+ if (is12HourFormat) {
+ if (hour >= 12) period = 'PM';
+ if (hour === 0) hour = 12;
+ else if (hour != 12) hour = hour % 12;
+ this.widget.find(
+ '.timepicker [data-action=togglePeriod]').text(period);
+ }
+ hour = padLeft(hour.toString(), 2, '0');
+ var minute = padLeft(this._date.getUTCMinutes().toString(), 2, '0');
+ var second = padLeft(this._date.getUTCSeconds().toString(), 2, '0');
+ timeComponents.filter('[data-time-component=hours]').text(hour);
+ timeComponents.filter('[data-time-component=minutes]').text(minute);
+ timeComponents.filter('[data-time-component=seconds]').text(second);
+ },
+
+ click: function(e) {
+ e.stopPropagation();
+ e.preventDefault();
+ var target = $(e.target).closest('span, td, th');
+ if (target.length === 1) {
+ switch(target[0].nodeName.toLowerCase()) {
+ case 'th':
+ switch(target[0].className) {
+ case 'switch':
+ this.showMode(1);
+ break;
+ case 'prev':
+ case 'next':
+ var vd = this.viewDate;
+ var navFnc = DPGlobal.modes[this.viewMode].navFnc;
+ var step = DPGlobal.modes[this.viewMode].navStep;
+ if (target[0].className === 'prev') step = step * -1;
+ vd['set' + navFnc](vd['get' + navFnc]() + step);
+ this.fillDate();
+ this.set();
+ break;
+ }
+ break;
+ case 'span':
+ if (target.is('.month')) {
+ var month = target.parent().find('span').index(target);
+ this.viewDate.setUTCMonth(month);
+ } else {
+ var year = parseInt(target.text(), 10) || 0;
+ this.viewDate.setUTCFullYear(year);
+ }
+ if (this.viewMode !== 0) {
+ this._date = UTCDate(
+ this.viewDate.getUTCFullYear(),
+ this.viewDate.getUTCMonth(),
+ this.viewDate.getUTCDate(),
+ this._date.getUTCHours(),
+ this._date.getUTCMinutes(),
+ this._date.getUTCSeconds(),
+ this._date.getUTCMilliseconds()
+ );
+ this.notifyChange();
+ }
+ this.showMode(-1);
+ this.fillDate();
+ this.set();
+ break;
+ case 'td':
+ if (target.is('.day')) {
+ var day = parseInt(target.text(), 10) || 1;
+ var month = this.viewDate.getUTCMonth();
+ var year = this.viewDate.getUTCFullYear();
+ if (target.is('.old')) {
+ if (month === 0) {
+ month = 11;
+ year -= 1;
+ } else {
+ month -= 1;
+ }
+ } else if (target.is('.new')) {
+ if (month == 11) {
+ month = 0;
+ year += 1;
+ } else {
+ month += 1;
+ }
+ }
+ this._date = UTCDate(
+ year, month, day,
+ this._date.getUTCHours(),
+ this._date.getUTCMinutes(),
+ this._date.getUTCSeconds(),
+ this._date.getUTCMilliseconds()
+ );
+ this.viewDate = UTCDate(
+ year, month, Math.min(28, day) , 0, 0, 0, 0);
+ this.fillDate();
+ this.set();
+ this.notifyChange();
+ this.widget.hide();
+ }
+ break;
+ }
+ }
+ },
+
+ actions: {
+ incrementHours: function(e) {
+ this._date.setUTCHours(this._date.getUTCHours() + 1);
+ },
+
+ incrementMinutes: function(e) {
+ this._date.setUTCMinutes(this._date.getUTCMinutes() + 1);
+ },
+
+ // incrementSeconds: function(e) {
+ // this._date.setUTCSeconds(this._date.getUTCSeconds() + 1);
+ // },
+
+ decrementHours: function(e) {
+ this._date.setUTCHours(this._date.getUTCHours() - 1);
+ },
+
+ decrementMinutes: function(e) {
+ this._date.setUTCMinutes(this._date.getUTCMinutes() - 1);
+ },
+
+ // decrementSeconds: function(e) {
+ // this._date.setUTCSeconds(this._date.getUTCSeconds() - 1);
+ // },
+
+ togglePeriod: function(e) {
+ var hour = this._date.getUTCHours();
+ if (hour >= 12) hour -= 12;
+ else hour += 12;
+ this._date.setUTCHours(hour);
+ },
+
+ showPicker: function() {
+ this.widget.find('.timepicker > div:not(.timepicker-picker)').hide();
+ this.widget.find('.timepicker .timepicker-picker').show();
+ },
+
+ showHours: function() {
+ this.widget.find('.timepicker .timepicker-picker').hide();
+ this.widget.find('.timepicker .timepicker-hours').show();
+ },
+
+ showMinutes: function() {
+ this.widget.find('.timepicker .timepicker-picker').hide();
+ this.widget.find('.timepicker .timepicker-minutes').show();
+ },
+
+ // showSeconds: function() {
+ // this.widget.find('.timepicker .timepicker-picker').hide();
+ // this.widget.find('.timepicker .timepicker-seconds').show();
+ // },
+
+ selectHour: function(e) {
+ var tgt = $(e.target);
+ var value = parseInt(tgt.text(), 10);
+ if (this.options.pick12HourFormat) {
+ var current = this._date.getUTCHours();
+ if (current >= 12) {
+ if (value != 12) value = (value + 12) % 24;
+ } else {
+ if (value === 12) value = 0;
+ else value = value % 12;
+ }
+ }
+ this._date.setUTCHours(value);
+ this.actions.showPicker.call(this);
+ },
+
+ selectMinute: function(e) {
+ var tgt = $(e.target);
+ var value = parseInt(tgt.text(), 10);
+ this._date.setUTCMinutes(value);
+ this.actions.showPicker.call(this);
+ },
+
+ // selectSecond: function(e) {
+ // var tgt = $(e.target);
+ // var value = parseInt(tgt.text(), 10);
+ // this._date.setUTCSeconds(value);
+ // this.actions.showPicker.call(this);
+ // }
+ },
+
+ doAction: function(e) {
+ e.stopPropagation();
+ e.preventDefault();
+ if (!this._date) this._date = UTCDate(1970, 0, 0, 0, 0, 0, 0);
+ var action = $(e.currentTarget).data('action');
+ var rv = this.actions[action].apply(this, arguments);
+ this.set();
+ this.fillTime();
+ this.notifyChange();
+ return rv;
+ },
+
+ stopEvent: function(e) {
+ e.stopPropagation();
+ e.preventDefault();
+ },
+
+ // part of the following code was taken from
+ // http://cloud.github.com/downloads/digitalBush/jquery.maskedinput/jquery.maskedinput-1.3.js
+ keydown: function(e) {
+ var self = this, k = e.which, input = $(e.target);
+ if (k == 8 || k == 46) {
+ // backspace and delete cause the maskPosition
+ // to be recalculated
+ setTimeout(function() {
+ self._resetMaskPos(input);
+ });
+ }
+ },
+
+ keypress: function(e) {
+ var k = e.which;
+ if (k == 8 || k == 46) {
+ // For those browsers which will trigger
+ // keypress on backspace/delete
+ return;
+ }
+ var input = $(e.target);
+ var c = String.fromCharCode(k);
+ var val = input.val() || '';
+ val += c;
+ var mask = this._mask[this._maskPos];
+ if (!mask) {
+ return false;
+ }
+ if (mask.end != val.length) {
+ return;
+ }
+ if (!mask.pattern.test(val.slice(mask.start))) {
+ val = val.slice(0, val.length - 1);
+ while ((mask = this._mask[this._maskPos]) && mask.character) {
+ val += mask.character;
+ // advance mask position past static
+ // part
+ this._maskPos++;
+ }
+ val += c;
+ if (mask.end != val.length) {
+ input.val(val);
+ return false;
+ } else {
+ if (!mask.pattern.test(val.slice(mask.start))) {
+ input.val(val.slice(0, mask.start));
+ return false;
+ } else {
+ input.val(val);
+ this._maskPos++;
+ return false;
+ }
+ }
+ } else {
+ this._maskPos++;
+ }
+ },
+
+ change: function(e) {
+ var input = $(e.target);
+ var val = input.val();
+ if (this._formatPattern.test(val)) {
+ this.update();
+ this.setValue(this._date.getTime());
+ this.notifyChange();
+ this.set();
+ } else if (val && val.trim()) {
+ this.setValue(this._date.getTime());
+ if (this._date) this.set();
+ else input.val('');
+ } else {
+ if (this._date) {
+ this.setValue(null);
+ // unset the date when the input is
+ // erased
+ this.notifyChange();
+ }
+ }
+ this._resetMaskPos(input);
+ },
+
+ showMode: function(dir) {
+ if (dir) {
+ this.viewMode = Math.max(this.minViewMode, Math.min(
+ 2, this.viewMode + dir));
+ }
+ this.widget.find('.datepicker > div').hide().filter(
+ '.datepicker-'+DPGlobal.modes[this.viewMode].clsName).show();
+ },
+
+ destroy: function() {
+ this._detachDatePickerEvents();
+ this._detachDatePickerGlobalEvents();
+ this.widget.remove();
+ this.$element.removeData('datetimepicker');
+ this.component.removeData('datetimepicker');
+ },
+
+ formatDate: function(d) {
+ return this.format.replace(formatReplacer, function(match) {
+ var methodName, property, rv, len = match.length;
+ if (match === 'ms')
+ len = 1;
+ property = dateFormatComponents[match].property
+ if (property === 'Hours12') {
+ rv = d.getUTCHours();
+ if (rv === 0) rv = 12;
+ else if (rv !== 12) rv = rv % 12;
+ } else if (property === 'Period12') {
+ if (d.getUTCHours() >= 12) return 'PM';
+ else return 'AM';
+ } else {
+ methodName = 'get' + property;
+ rv = d[methodName]();
+ }
+ if (methodName === 'getUTCMonth') rv = rv + 1;
+ if (methodName === 'getUTCYear') rv = rv + 1900 - 2000;
+ return padLeft(rv.toString(), len, '0');
+ });
+ },
+
+ parseDate: function(str) {
+ var match, i, property, methodName, value, parsed = {};
+ if (!(match = this._formatPattern.exec(str)))
+ return null;
+ for (i = 1; i < match.length; i++) {
+ property = this._propertiesByIndex[i];
+ if (!property)
+ continue;
+ value = match[i];
+ if (/^\d+$/.test(value))
+ value = parseInt(value, 10);
+ parsed[property] = value;
+ }
+ return this._finishParsingDate(parsed);
+ },
+
+ _resetMaskPos: function(input) {
+ var val = input.val();
+ for (var i = 0; i < this._mask.length; i++) {
+ if (this._mask[i].end > val.length) {
+ // If the mask has ended then jump to
+ // the next
+ this._maskPos = i;
+ break;
+ } else if (this._mask[i].end === val.length) {
+ this._maskPos = i + 1;
+ break;
+ }
+ }
+ },
+
+ _finishParsingDate: function(parsed) {
+ var year, month, date, hours, minutes, seconds, milliseconds;
+ year = parsed.UTCFullYear;
+ if (parsed.UTCYear) year = 2000 + parsed.UTCYear;
+ if (!year) year = 1970;
+ if (parsed.UTCMonth) month = parsed.UTCMonth - 1;
+ else month = 0;
+ date = parsed.UTCDate || 1;
+ hours = parsed.UTCHours || 0;
+ minutes = parsed.UTCMinutes || 0;
+ seconds = parsed.UTCSeconds || 0;
+ milliseconds = parsed.UTCMilliseconds || 0;
+ if (parsed.Hours12) {
+ hours = parsed.Hours12;
+ }
+ if (parsed.Period12) {
+ if (/pm/i.test(parsed.Period12)) {
+ if (hours != 12) hours = (hours + 12) % 24;
+ } else {
+ hours = hours % 12;
+ }
+ }
+ return UTCDate(year, month, date, hours, minutes, seconds, milliseconds);
+ },
+
+ _compileFormat: function () {
+ var match, component, components = [], mask = [],
+ str = this.format, propertiesByIndex = {}, i = 0, pos = 0;
+ while (match = formatComponent.exec(str)) {
+ component = match[0];
+ if (component in dateFormatComponents) {
+ i++;
+ propertiesByIndex[i] = dateFormatComponents[component].property;
+ components.push('\\s*' + dateFormatComponents[component].getPattern(
+ this) + '\\s*');
+ mask.push({
+ pattern: new RegExp(dateFormatComponents[component].getPattern(
+ this)),
+ property: dateFormatComponents[component].property,
+ start: pos,
+ end: pos += component.length
+ });
+ }
+ else {
+ components.push(escapeRegExp(component));
+ mask.push({
+ pattern: new RegExp(escapeRegExp(component)),
+ character: component,
+ start: pos,
+ end: ++pos
+ });
+ }
+ str = str.slice(component.length);
+ }
+ this._mask = mask;
+ this._maskPos = 0;
+ this._formatPattern = new RegExp(
+ '^\\s*' + components.join('') + '\\s*$');
+ this._propertiesByIndex = propertiesByIndex;
+ },
+
+ _attachDatePickerEvents: function() {
+ var self = this;
+ // this handles date picker clicks
+ this.widget.on('click', '.datepicker *', $.proxy(this.click, this));
+ // this handles time picker clicks
+ this.widget.on('click', '[data-action]', $.proxy(this.doAction, this));
+ this.widget.on('mousedown', $.proxy(this.stopEvent, this));
+ if (this.pickDate && this.pickTime) {
+ this.widget.on('click.togglePicker', '.accordion-toggle', function(e) {
+ e.stopPropagation();
+ var $this = $(this);
+ var $parent = $this.closest('ul');
+ var expanded = $parent.find('.collapse.in');
+ var closed = $parent.find('.collapse:not(.in)');
+
+ if (expanded && expanded.length) {
+ var collapseData = expanded.data('collapse');
+ if (collapseData && collapseData.transitioning) return;
+ expanded.collapse('hide');
+ closed.collapse('show')
+ $this.find('i').toggleClass(self.timeIcon + ' ' + self.dateIcon);
+ self.$element.find('.add-on i').toggleClass(self.timeIcon + ' ' + self.dateIcon);
+ }
+ });
+ }
+ if (this.isInput) {
+ this.$element.on({
+ 'focus': $.proxy(this.show, this),
+ 'blur': $.proxy(this.hide, this),
+ 'change': $.proxy(this.change, this),
+ });
+ if (this.options.maskInput) {
+ this.$element.on({
+ 'keydown': $.proxy(this.keydown, this),
+ 'keypress': $.proxy(this.keypress, this)
+ });
+ }
+ } else {
+ this.$element.on({
+ 'focus': $.proxy(this.show, this),
+ 'blur': $.proxy(this.hide, this),
+ 'change': $.proxy(this.change, this),
+ }, 'input');
+ if (this.options.maskInput) {
+ this.$element.on({
+ 'keydown': $.proxy(this.keydown, this),
+ 'keypress': $.proxy(this.keypress, this)
+ }, 'input');
+ }
+ if (this.component){
+ this.component.on('click', $.proxy(this.show, this));
+ } else {
+ this.$element.on('click', $.proxy(this.show, this));
+ }
+ }
+ },
+
+ _attachDatePickerGlobalEvents: function() {
+ $(window).on(
+ 'resize.datetimepicker' + this.id, $.proxy(this.place, this));
+ if (!this.isInput) {
+ $(document).on(
+ 'mousedown.datetimepicker' + this.id, $.proxy(this.hide, this));
+ }
+ },
+
+ _detachDatePickerEvents: function() {
+ this.widget.off('click', '.datepicker *', this.click);
+ this.widget.off('click', '[data-action]');
+ this.widget.off('mousedown', this.stopEvent);
+ if (this.pickDate && this.pickTime) {
+ this.widget.off('click.togglePicker');
+ }
+ if (this.isInput) {
+ this.$element.off({
+ 'focus': this.show,
+ 'change': this.change,
+ });
+ if (this.options.maskInput) {
+ this.$element.off({
+ 'keydown': this.keydown,
+ 'keypress': this.keypress
+ });
+ }
+ } else {
+ this.$element.off({
+ 'change': this.change,
+ }, 'input');
+ if (this.options.maskInput) {
+ this.$element.off({
+ 'keydown': this.keydown,
+ 'keypress': this.keypress
+ }, 'input');
+ }
+ if (this.component){
+ this.component.off('click', this.show);
+ } else {
+ this.$element.off('click', this.show);
+ }
+ }
+ },
+
+ _detachDatePickerGlobalEvents: function () {
+ $(window).off('resize.datetimepicker' + this.id);
+ if (!this.isInput) {
+ $(document).off('mousedown.datetimepicker' + this.id);
+ }
+ }
+ };
+
+ $.fn.datetimepicker = function ( option, val ) {
+ return this.each(function () {
+ var $this = $(this),
+ data = $this.data('datetimepicker'),
+ options = typeof option === 'object' && option;
+ if (!data) {
+ $this.data('datetimepicker', (data = new DateTimePicker(
+ this, $.extend({}, $.fn.datetimepicker.defaults,options))));
+ }
+ if (typeof option === 'string') data[option](val);
+ });
+ };
+
+ $.fn.datetimepicker.defaults = {
+ maskInput: true,
+ pickDate: true,
+ pickTime: true,
+ pick12HourFormat: false
+ };
+ $.fn.datetimepicker.Constructor = DateTimePicker;
+ var dpgId = 0;
+ var dates = $.fn.datetimepicker.dates = {
+ en: {
+ days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+ "Friday", "Saturday", "Sunday"],
+ daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
+ daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
+ months: ["January", "February", "March", "April", "May", "June",
+ "July", "August", "September", "October", "November", "December"],
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
+ "Aug", "Sep", "Oct", "Nov", "Dec"]
+ }
+ };
+
+ var dateFormatComponents = {
+ dd: {property: 'UTCDate', getPattern: function() { return '(0?[1-9]|[1-2][0-9]|3[0-1])\\b';}},
+ MM: {property: 'UTCMonth', getPattern: function() {return '(0?[1-9]|1[0-2])\\b';}},
+ yy: {property: 'UTCYear', getPattern: function() {return '(\\d{2})\\b'}},
+ yyyy: {property: 'UTCFullYear', getPattern: function() {return '(\\d{4})\\b';}},
+ hh: {property: 'UTCHours', getPattern: function() {return '(0?[0-9]|1[0-9]|2[0-3])\\b';}},
+ mm: {property: 'UTCMinutes', getPattern: function() {return '(0?[0-9]|[1-5][0-9])\\b';}},
+ ss: {property: 'UTCSeconds', getPattern: function() {return '(0?[0-9]|[1-5][0-9])\\b';}},
+ ms: {property: 'UTCMilliseconds', getPattern: function() {return '([0-9]{1,3})\\b';}},
+ HH: {property: 'Hours12', getPattern: function() {return '(0?[1-9]|1[0-2])\\b';}},
+ PP: {property: 'Period12', getPattern: function() {return '(AM|PM|am|pm|Am|aM|Pm|pM)\\b';}}
+ };
+
+ var keys = [];
+ for (var k in dateFormatComponents) keys.push(k);
+ keys[keys.length - 1] += '\\b';
+ keys.push('.');
+
+ var formatComponent = new RegExp(keys.join('\\b|'));
+ keys.pop();
+ var formatReplacer = new RegExp(keys.join('\\b|'), 'g');
+
+ function escapeRegExp(str) {
+ // http://stackoverflow.com/questions/3446170/escape-string-for-use-in-javascript-regex
+ return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
+ }
+
+ function padLeft(s, l, c) {
+ if (l < s.length) return s;
+ else return Array(l - s.length + 1).join(c || ' ') + s;
+ }
+
+ function getTemplate(timeIcon, pickDate, pickTime, is12Hours) {
+ if (pickDate && pickTime) {
+ return (
+ ''
+ );
+ } else if (pickTime) {
+ return (
+ ''
+ );
+ } else {
+ return (
+ ''
+ );
+ }
+ }
+
+ function UTCDate() {
+ return new Date(Date.UTC.apply(Date, arguments));
+ }
+
+ var DPGlobal = {
+ modes: [
+ {
+ clsName: 'days',
+ navFnc: 'UTCMonth',
+ navStep: 1
+ },
+ {
+ clsName: 'months',
+ navFnc: 'UTCFullYear',
+ navStep: 1
+ },
+ {
+ clsName: 'years',
+ navFnc: 'UTCFullYear',
+ navStep: 10
+ }],
+ isLeapYear: function (year) {
+ return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0))
+ },
+ getDaysInMonth: function (year, month) {
+ return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]
+ },
+ headTemplate:
+ '' +
+ '' +
+ '‹ | ' +
+ ' | ' +
+ '› | ' +
+ '
' +
+ '',
+ contTemplate: ' |
'
+ };
+ DPGlobal.template =
+ '' +
+ '
' +
+ DPGlobal.headTemplate +
+ '' +
+ '
' +
+ '
' +
+ '' +
+ '
' +
+ DPGlobal.headTemplate +
+ DPGlobal.contTemplate+
+ '
'+
+ '
'+
+ ''+
+ '
'+
+ DPGlobal.headTemplate+
+ DPGlobal.contTemplate+
+ '
'+
+ '
';
+ var TPGlobal = {
+ hourTemplate: '',
+ minuteTemplate: '',
+ // secondTemplate: '',
+ };
+ TPGlobal.getTemplate = function(is12Hours) {
+ return (
+ '' +
+ '
' +
+ '' +
+ ' | ' +
+ ' | ' +
+ ' | ' +
+ // ' | ' +
+ // ' | ' +
+ // (is12Hours ? ' | ' : '') +
+ '
' +
+ '' +
+ '' + TPGlobal.hourTemplate + ' | ' +
+ ': | ' +
+ '' + TPGlobal.minuteTemplate + ' | ' +
+ // ': | ' +
+ // '' + TPGlobal.secondTemplate + ' | ' +
+ (is12Hours ?
+ ' | ' +
+ '' +
+ '' +
+ ' | ' : '') +
+ '
' +
+ '' +
+ ' | ' +
+ ' | ' +
+ ' | ' +
+ // ' | ' +
+ // ' | ' +
+ // (is12Hours ? ' | ' : '') +
+ '
' +
+ '
' +
+ '
' +
+ ''+
+ ''+
+ // ''
+ );
+ }
+
+
+})(window.jQuery)
diff --git a/app/assets/javascripts/new_admin.js b/app/assets/javascripts/new_admin.js
index 732eef1b..c5ec022e 100644
--- a/app/assets/javascripts/new_admin.js
+++ b/app/assets/javascripts/new_admin.js
@@ -19,4 +19,6 @@
//= require side_bar_history
//= require rss
//= require ajax_form
-//= require inc/ajax_setting
\ No newline at end of file
+//= require inc/ajax_setting
+//= require lib/bootstrap-datetimepicker
+//= require datetimepicker
\ No newline at end of file
diff --git a/app/assets/stylesheets/lib/bootstrap-datetimepicker.css b/app/assets/stylesheets/lib/bootstrap-datetimepicker.css
new file mode 100644
index 00000000..aaf685cb
--- /dev/null
+++ b/app/assets/stylesheets/lib/bootstrap-datetimepicker.css
@@ -0,0 +1,221 @@
+/*!
+* Datepicker for Bootstrap
+*
+* Copyright 2012 Stefan Petre
+* Licensed under the Apache License v2.0
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+*/
+.clearfix {
+ *zoom:1;
+}
+.clearfix:before,
+.clearfix:after {
+ display:table;
+ content:"";
+ line-height:0;
+}
+.clearfix:after {
+ clear:both;
+}
+.hide-text {
+ font:0/0 a;
+ color:transparent;
+ text-shadow:none;
+ background-color:transparent;
+ border:0;
+}
+.input-block-level {
+ display:block;
+ width:100%;
+ min-height:30px;
+ -webkit-box-sizing:border-box;
+ -moz-box-sizing:border-box;
+ box-sizing:border-box;
+}
+.bootstrap-datetimepicker-widget {
+ top:0;
+ left:0;
+ min-width: 113px;
+ padding:4px;
+ margin-top:1px;
+ -webkit-border-radius:4px;
+ -moz-border-radius:4px;
+ border-radius:4px;
+}
+.bootstrap-datetimepicker-widget:before {
+ content:'';
+ display:inline-block;
+ border-left:7px solid transparent;
+ border-right:7px solid transparent;
+ border-bottom:7px solid #ccc;
+ border-bottom-color:rgba(0,0,0,0.2);
+ position:absolute;
+ top:-7px;
+ left:6px;
+}
+.bootstrap-datetimepicker-widget:after {
+ content:'';
+ display:inline-block;
+ border-left:6px solid transparent;
+ border-right:6px solid transparent;
+ border-bottom:6px solid #fff;
+ position:absolute;
+ top:-6px;
+ left:7px;
+}
+.bootstrap-datetimepicker-widget .timepicker {
+ min-width: 110px;
+}
+.bootstrap-datetimepicker-widget>ul {
+ list-style-type:none;
+ margin:0;
+}
+.bootstrap-datetimepicker-widget .timepicker-hour,
+.bootstrap-datetimepicker-widget .timepicker-minute,
+.bootstrap-datetimepicker-widget .timepicker-second {
+ font-weight:bold;
+ font-size:1.2em;
+}
+.bootstrap-datetimepicker-widget table[data-hour-format="12"] .separator {
+ width:4px;
+ padding:0;
+ margin:0;
+}
+.bootstrap-datetimepicker-widget .datepicker>div {
+ display:none;
+}
+.bootstrap-datetimepicker-widget .picker-switch {
+ text-align:center;
+}
+.bootstrap-datetimepicker-widget table {
+ width:100%;
+ margin:0;
+}
+.bootstrap-datetimepicker-widget td,
+.bootstrap-datetimepicker-widget th {
+ text-align:center;
+ width:20px;
+ height:20px;
+ -webkit-border-radius:4px;
+ -moz-border-radius:4px;
+ border-radius:4px;
+ vertical-align: middle;
+}
+.bootstrap-datetimepicker-widget td.day:hover,
+.bootstrap-datetimepicker-widget td.hour:hover,
+.bootstrap-datetimepicker-widget td.minute:hover,
+.bootstrap-datetimepicker-widget td.second:hover {
+ background:#eee;
+ cursor:pointer;
+}
+.bootstrap-datetimepicker-widget td.old,
+.bootstrap-datetimepicker-widget td.new {
+ color:#999;
+}
+.bootstrap-datetimepicker-widget td.active,
+.bootstrap-datetimepicker-widget td.active:hover {
+ color:#fff;
+ background-color:#006dcc;
+ background-image:-moz-linear-gradient(top,#08c,#04c);
+ background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));
+ background-image:-webkit-linear-gradient(top,#08c,#04c);
+ background-image:-o-linear-gradient(top,#08c,#04c);
+ background-image:linear-gradient(to bottom,#08c,#04c);
+ background-repeat:repeat-x;
+ filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0044cc',GradientType=0);
+ border-color:#04c #04c #002a80;
+ border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);
+ *background-color:#04c;
+ filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);
+ color:#fff;
+ text-shadow:0 -1px 0 rgba(0,0,0,0.25);
+}
+.bootstrap-datetimepicker-widget td.active:hover,
+.bootstrap-datetimepicker-widget td.active:hover:hover,
+.bootstrap-datetimepicker-widget td.active:active,
+.bootstrap-datetimepicker-widget td.active:hover:active,
+.bootstrap-datetimepicker-widget td.active.active,
+.bootstrap-datetimepicker-widget td.active:hover.active,
+.bootstrap-datetimepicker-widget td.active.disabled,
+.bootstrap-datetimepicker-widget td.active:hover.disabled,
+.bootstrap-datetimepicker-widget td.active[disabled],
+.bootstrap-datetimepicker-widget td.active:hover[disabled] {
+ color:#fff;
+ background-color:#04c;
+ *background-color:#003bb3;
+}
+.bootstrap-datetimepicker-widget td.active:active,
+.bootstrap-datetimepicker-widget td.active:hover:active,
+.bootstrap-datetimepicker-widget td.active.active,
+.bootstrap-datetimepicker-widget td.active:hover.active {
+ background-color:#039 \9;
+}
+.bootstrap-datetimepicker-widget td span {
+ display:block;
+ width:100%;
+ height:54px;
+ line-height:54px;
+ float:left;
+ cursor:pointer;
+ -webkit-border-radius:4px;
+ -moz-border-radius:4px;
+ border-radius:4px;
+}
+.bootstrap-datetimepicker-widget .datepicker-months td span,
+.bootstrap-datetimepicker-widget .datepicker-years td span {
+ width: 50px;
+}
+.bootstrap-datetimepicker-widget td span:hover {
+ background:#eee;
+}
+.bootstrap-datetimepicker-widget td span.active {
+ color:#fff;
+ background-color:#006dcc;
+ background-image:-moz-linear-gradient(top,#08c,#04c);
+ background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));
+ background-image:-webkit-linear-gradient(top,#08c,#04c);
+ background-image:-o-linear-gradient(top,#08c,#04c);
+ background-image:linear-gradient(to bottom,#08c,#04c);
+ background-repeat:repeat-x;
+ filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0044cc',GradientType=0);
+ border-color:#04c #04c #002a80;
+ border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);
+ *background-color:#04c;
+ filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);
+ color:#fff;
+ text-shadow:0 -1px 0 rgba(0,0,0,0.25);
+}
+.bootstrap-datetimepicker-widget td span.active:hover,
+.bootstrap-datetimepicker-widget td span.active:active,
+.bootstrap-datetimepicker-widget td span.active.active,
+.bootstrap-datetimepicker-widget td span.active.disabled,
+.bootstrap-datetimepicker-widget td span.active[disabled] {
+ color:#fff;
+ background-color:#04c;
+ *background-color:#003bb3;
+}
+.bootstrap-datetimepicker-widget td span.active:active,
+.bootstrap-datetimepicker-widget td span.active.active {
+ background-color:#039 \9;
+}
+.bootstrap-datetimepicker-widget td span.old {
+ color:#999;
+}
+.bootstrap-datetimepicker-widget th.switch {
+ width:145px;
+}
+.bootstrap-datetimepicker-widget th.next,
+.bootstrap-datetimepicker-widget th.prev {
+ font-size:21px;
+}
+.bootstrap-datetimepicker-widget thead tr:first-child th {
+ cursor:pointer;
+}
+.bootstrap-datetimepicker-widget thead tr:first-child th:hover {
+ background:#eee;
+}
+.input-append.date .add-on i,
+.input-prepend.date .add-on i {
+ cursor:pointer;
+}
diff --git a/app/assets/stylesheets/new_admin.css.erb b/app/assets/stylesheets/new_admin.css.erb
index 2fb7e28e..494c760d 100644
--- a/app/assets/stylesheets/new_admin.css.erb
+++ b/app/assets/stylesheets/new_admin.css.erb
@@ -16,4 +16,5 @@
*= require isotope
*= require icons
*= require site-map
+ *= require lib/bootstrap-datetimepicker
*/
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index dbd906ca..128fef23 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -12,7 +12,7 @@ class ApplicationController < ActionController::Base
layout :layout_by_resource
- helper :admin
+ helper :admin, :orbit_form
before_filter :set_locale, :set_site, :prepare_for_mobile
helper_attr :site_valid_locales
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index e20a0c29..252ab78c 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -254,6 +254,10 @@ module ApplicationHelper
object.strftime("%Y-%m-%d")
end
+ def display_time(object)
+ object.strftime("%H:%M")
+ end
+
def share_links(object, key)
content_tag :div, :class => 'fb' do
concat social_share_button_tag(object.title, :fb_url => generate_fb_url(object,key), :image => "http://#{request.env['HTTP_HOST']}#{object.image_url}")
diff --git a/app/helpers/orbit_form_helper.rb b/app/helpers/orbit_form_helper.rb
new file mode 100644
index 00000000..9dd6728f
--- /dev/null
+++ b/app/helpers/orbit_form_helper.rb
@@ -0,0 +1,99 @@
+module OrbitFormHelper
+ def self.included(base)
+ ActionView::Helpers::FormBuilder.send(:include, Orbit::FormBuilder)
+ end
+
+ def datetime_picker(object_name, method, options = {})
+ options[:icon_time] ||= 'icons-clock'
+ options[:icon_date] ||= 'icons-calendar'
+ options[:input_class] ||= 'input-large'
+ options[:value] ||= options[:object][method] if options[:object] && options[:object][method]
+ case options[:picker_type]
+ when 'date'
+ content_tag :div, :id => options[:id], :class => options[:class] do
+ date_picker(object_name, method, options)
+ end
+ when 'time'
+ content_tag :div, :id => options[:id], :class => options[:class] do
+ time_picker(object_name, method, options)
+ end
+ when 'separated'
+ options[:label] ||= I18n.t('datetime_picker.separated.label')
+ content_tag :div, :id => options[:id], :class => "separated_picker #{options[:class]}" do
+ concat label_tag options[:label] unless options[:no_label]
+ concat hidden_field(object_name, method)
+ concat separated_picker(object_name, method, options)
+ end
+ else
+ content_tag :div, :id => options[:id], :class => options[:class] do
+ default_picker(object_name, method, options)
+ end
+ end
+ end
+
+ def date_picker(object_name, method, options)
+ custom = {}
+ custom[:format] = 'yyyy-MM-dd'
+ custom[:value] = display_date(options[:value]) if options[:value]
+ custom[:picker_class] = 'date_picker'
+ custom[:label] = options[:label] || I18n.t('datetime_picker.date.label')
+ custom[:placeholder] = options[:placeholder] || I18n.t('datetime_picker.date.placeholder')
+ picker(object_name, method, options.merge(custom))
+ end
+
+ def default_picker(object_name, method, options)
+ custom = {}
+ custom[:format] = 'yyyy-MM-dd hh:mm'
+ custom[:value] = display_date_time(options[:value]) if options[:value]
+ custom[:picker_class] = 'default_picker'
+ custom[:label] = options[:label] || I18n.t('datetime_picker.default.label')
+ custom[:placeholder] = options[:placeholder] || I18n.t('datetime_picker.default.placeholder')
+ picker(object_name, method, options.merge(custom))
+ end
+
+ def time_picker(object_name, method, options)
+ custom = {}
+ custom[:format] = 'hh:mm'
+ custom[:value] = display_time(options[:value]) if options[:value]
+ custom[:picker_class] = 'time_picker'
+ custom[:label] = options[:label] || I18n.t('datetime_picker.time.label')
+ custom[:placeholder] = options[:placeholder] || I18n.t('datetime_picker.time.placeholder')
+ picker(object_name, method, options.merge(custom))
+ end
+
+ def separated_picker(object_name, method, options)
+ custom = {}
+ custom[:no_label] = true
+ date_picker(nil, nil, options.merge(custom)) + time_picker(nil, nil, options.merge(custom))
+ end
+
+
+ def single_picker(object_name, method, options)
+ content_tag :div, :id => options[:id], :class => options[:class] do
+ picker(object_name, method, options)
+ end
+ end
+
+ def double_picker(object_name, method, options)
+
+ end
+
+ def picker(object_name, method, options)
+ content_tag :div, :class => "#{options[:picker_class]} input-append" do
+ concat label_tag options[:label] unless options[:no_label]
+ concat text_field object_name, method, :placeholder => options[:placeholder], :class => options[:input_class], 'data-format' => options[:format], :value => options[:value]
+ concat (content_tag :span, :class => 'add-on' do
+ content_tag :i, nil, 'data-time-icon' => options[:icon_time], 'data-date-icon' => options[:icon_date]
+ end)
+ end
+ end
+
+end
+
+module Orbit::FormBuilder
+ # ActionPack's metaprogramming would have done this for us, if FormHelper#labeled_input
+ # had been defined at load. Instead we define it ourselves here.
+ def datetime_picker(method, options = {})
+ @template.datetime_picker(@object_name, method, objectify_options(options))
+ end
+end
\ No newline at end of file
diff --git a/app/views/admin/ad_images/_form.html.erb b/app/views/admin/ad_images/_form.html.erb
index fd139347..5277b312 100644
--- a/app/views/admin/ad_images/_form.html.erb
+++ b/app/views/admin/ad_images/_form.html.erb
@@ -1,13 +1,7 @@
-<% content_for :page_specific_css do %>
- <%= stylesheet_link_tag "lib/datepicker" %>
-<% end %>
<% content_for :page_specific_javascript do %>
- <%= javascript_include_tag "lib/datepicker" %>
- <%= javascript_include_tag "lib/date.format.js" %>
<%= javascript_include_tag "inc/modal-preview" %>
<%= javascript_include_tag "/static/jquery.cycle.all.latest.js" %>
<%= javascript_include_tag "inc/jquery.imagesloaded.js" %>
-
<% end %>
@@ -21,51 +15,8 @@
-
-
- ▼
- <%= f.hidden_field :parse_post_date,:value => @ad_image.post_date.strftime('%Y / %m / %d') %>
- <%= f.hidden_field :parse_unpost_date,:value => @ad_image.unpost_date.strftime('%Y / %m / %d')%>
-
-
-
-
-
-
+ <%= f.datetime_picker :post_date, :picker_type => 'date', :label => t(:start_date) %>
+ <%= f.datetime_picker :unpost_date, :picker_type => 'date', :label => t(:end_date) %>
diff --git a/config/locales/picker.en.yml b/config/locales/picker.en.yml
new file mode 100644
index 00000000..999d9195
--- /dev/null
+++ b/config/locales/picker.en.yml
@@ -0,0 +1,14 @@
+en:
+
+ datetime_picker:
+ date:
+ label: Date
+ placeholder: "YYYY-MM-DD"
+ default:
+ label: Date and time
+ placeholder: "YYYY-MM-DD HH:MM"
+ separated:
+ label: Date and time
+ time:
+ label: Time
+ placeholder: "HH:MM"
\ No newline at end of file
diff --git a/config/locales/picker.zh_tw.yml b/config/locales/picker.zh_tw.yml
new file mode 100644
index 00000000..f92f47b0
--- /dev/null
+++ b/config/locales/picker.zh_tw.yml
@@ -0,0 +1,14 @@
+en:
+
+ datetime_picker:
+ date:
+ label: 日期
+ placeholder: "YYYY-MM-DD"
+ default:
+ label: 日期和時間
+ placeholder: "YYYY-MM-DD HH:MM"
+ separated:
+ label: 日期和時間
+ time:
+ label: 時間
+ placeholder: "HH:MM"
\ No newline at end of file
diff --git a/vendor/built_in_modules/announcement/app/views/panel/announcement/back_end/bulletins/_form.html.erb b/vendor/built_in_modules/announcement/app/views/panel/announcement/back_end/bulletins/_form.html.erb
index 77ac7c9e..e003f9cf 100644
--- a/vendor/built_in_modules/announcement/app/views/panel/announcement/back_end/bulletins/_form.html.erb
+++ b/vendor/built_in_modules/announcement/app/views/panel/announcement/back_end/bulletins/_form.html.erb
@@ -46,16 +46,10 @@
-
-
- <%= f.datetime_select :postdate, {:use_month_numbers => true, :order => [:day, :month, :year] }, {:class => 'span1'} %>
-
+ <%= f.datetime_picker :postdate, :picker_type => 'separated', :label => t(:start) %>
-
-
- <%= f.datetime_select :deadline, {:use_month_numbers => true, :prompt => { :month => 'Month', :day => 'Day', :year => 'Year'}, :order => [:day, :month, :year] }, {:class => 'span1'} %>
-
+ <%= f.datetime_picker :deadline, :picker_type => 'separated', :label => t(:end) %>