Remove tempusdominus dependency
Instead we use native input of type date, datetime-local and time to pop-up a calendar. Such input can not be directly used because we can not control the format, so we synchronize the value with a text input using the proper format. The text input is also parsed using the right format. issue9922 review339181002
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
* Remove tempusdominus dependency
|
||||
* Handle device cookie
|
||||
* Add breadcrumb as title of window form
|
||||
* Manage help for each selection
|
||||
|
||||
+1
-2
@@ -8,6 +8,7 @@ module.exports = function(grunt) {
|
||||
'src/rpc.js',
|
||||
'src/pyson.js',
|
||||
'src/session.js',
|
||||
'src/common.js',
|
||||
'src/model.js',
|
||||
'src/tab.js',
|
||||
'src/screen.js',
|
||||
@@ -18,7 +19,6 @@ module.exports = function(grunt) {
|
||||
'src/view/calendar.js',
|
||||
'src/view/list_form.js',
|
||||
'src/action.js',
|
||||
'src/common.js',
|
||||
'src/window.js',
|
||||
'src/wizard.js',
|
||||
'src/board.js',
|
||||
@@ -32,7 +32,6 @@ module.exports = function(grunt) {
|
||||
'bower_components/bootstrap',
|
||||
'bower_components/bootstrap/less',
|
||||
'bower_components/bootstrap-rtl-ondemand/less',
|
||||
'bower_components/tempusdominus-bootstrap-3/src/less/'
|
||||
];
|
||||
|
||||
// Project configuration.
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
"mousetrap": "^1.6",
|
||||
"bootstrap-rtl-ondemand": "^3.3.4-ondemand",
|
||||
"Sortable": "sortablejs#^1.8.4",
|
||||
"tempusdominus-bootstrap-3": "bootstrap-datetimepicker-v5-alpha#^5.0.0-alpha8",
|
||||
"popper.js": "https://unpkg.com/popper.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
+8
-12
@@ -280,17 +280,15 @@
|
||||
return date;
|
||||
};
|
||||
|
||||
Sao.common.format_datetime = function(date_format, time_format, date) {
|
||||
Sao.common.format_datetime = function(datetime_format, date) {
|
||||
if (!date) {
|
||||
return '';
|
||||
}
|
||||
return date.format(
|
||||
Sao.common.moment_format(date_format + ' ' + time_format));
|
||||
return date.format(Sao.common.moment_format(datetime_format));
|
||||
};
|
||||
|
||||
Sao.common.parse_datetime = function(date_format, time_format, value) {
|
||||
var date = moment(value,
|
||||
Sao.common.moment_format(date_format + ' ' + time_format));
|
||||
Sao.common.parse_datetime = function(datetime_format, value) {
|
||||
var date = moment(value, Sao.common.moment_format(datetime_format));
|
||||
if (date.isValid()) {
|
||||
date = Sao.DateTime(date.year(), date.month(), date.date(),
|
||||
date.hour(), date.minute(), date.second(),
|
||||
@@ -1969,9 +1967,8 @@
|
||||
'reference': convert_selection,
|
||||
'datetime': function() {
|
||||
var result = Sao.common.parse_datetime(
|
||||
Sao.common.date_format(context.date_format),
|
||||
this.time_format(field),
|
||||
value);
|
||||
Sao.common.date_format(context.date_format) + ' ' +
|
||||
this.time_format(field), value);
|
||||
return result;
|
||||
}.bind(this),
|
||||
'date': function() {
|
||||
@@ -2093,9 +2090,8 @@
|
||||
value);
|
||||
}
|
||||
return Sao.common.format_datetime(
|
||||
Sao.common.date_format(context.date_format),
|
||||
this.time_format(field),
|
||||
value);
|
||||
Sao.common.date_format(context.date_format) + ' ' +
|
||||
this.time_format(field), value);
|
||||
}.bind(this),
|
||||
'date': function() {
|
||||
return Sao.common.format_date(
|
||||
|
||||
-51
@@ -1171,55 +1171,4 @@ var Sao = {};
|
||||
.next('.modal-backdrop.in').removeClass('hidden');
|
||||
}
|
||||
|
||||
if ($.fn.datetimepicker) {
|
||||
// XXX: use Popper to place popup
|
||||
// cherry picked from tempusdominus-core.js
|
||||
$.fn.datetimepicker.prototype.constructor.Constructor.prototype._place = function _place(e) {
|
||||
var self = (e && e.data && e.data.picker) || this;
|
||||
if (self._options.sideBySide) {
|
||||
self._element.append(self.widget);
|
||||
return;
|
||||
}
|
||||
if (self._options.widgetParent) {
|
||||
self._options.widgetParent.append(self.widget);
|
||||
} else if (self._element.is('input')) {
|
||||
self._element.after(self.widget).parent();
|
||||
} else {
|
||||
self._element.children().first().after(self.widget);
|
||||
}
|
||||
|
||||
var reference = self.component[0];
|
||||
|
||||
if (!reference) {
|
||||
reference = self._element;
|
||||
}
|
||||
|
||||
// ReSharper disable once ConstructorCallNotUsed
|
||||
new Popper(reference, self.widget[0], {
|
||||
placement: 'bottom-start'
|
||||
});
|
||||
};
|
||||
|
||||
// XXX: Ensure to always return a date
|
||||
$.fn.datetimepicker.prototype.constructor.Constructor.prototype._getLastPickedDate = function _getLastPickedDate() {
|
||||
return this._dates[this._getLastPickedDateIndex()] || this.getMoment();
|
||||
};
|
||||
|
||||
// XXX: Add fallback index
|
||||
var setValue = $.fn.datetimepicker.prototype.constructor.Constructor.prototype._setValue;
|
||||
$.fn.datetimepicker.prototype.constructor.Constructor.prototype._setValue = function _setValue(targetMoment, index) {
|
||||
index = index || 0;
|
||||
return setValue.call(this, targetMoment, index);
|
||||
};
|
||||
|
||||
// XXX: trigger show/hide event without date
|
||||
var notifyEvent = $.fn.datetimepicker.prototype.constructor.Constructor.prototype._notifyEvent;
|
||||
$.fn.datetimepicker.prototype.constructor.Constructor.prototype._notifyEvent = function _notifyEvent(e) {
|
||||
if ((e.type === 'datetimepicker.hide') || (e.type === 'datetimepicker.show')) {
|
||||
this._element.trigger(e);
|
||||
} else {
|
||||
notifyEvent.call(this, e);
|
||||
}
|
||||
};
|
||||
}
|
||||
}());
|
||||
|
||||
+25
-5
@@ -2,7 +2,6 @@
|
||||
this repository contains the full copyright notices and license terms. */
|
||||
@import "bootstrap";
|
||||
@import "bootstrap-rtl";
|
||||
@import "_tempusdominus-bootstrap-3";
|
||||
@import "sao-variables";
|
||||
html[theme="default"] {
|
||||
@import "theme";
|
||||
@@ -686,6 +685,31 @@ input.column-boolean {
|
||||
.center-block();
|
||||
}
|
||||
|
||||
.form-date, .form-datetime, .form-time,
|
||||
.dict-date, .dict-datetime,
|
||||
.input-date, .input-datetime-local, .input-time,
|
||||
.editabletree-date, .editabletree-datetime, .editabletree-time {
|
||||
.icon-input {
|
||||
overflow-y: hidden;
|
||||
}
|
||||
input[type="date"], input[type="datetime-local"], input[type="time"] {
|
||||
min-width: 0;
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
width: calc(100% + 2em);
|
||||
left: -2em;
|
||||
|
||||
&::-webkit-calendar-picker-indicator {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dict-label {
|
||||
text-align: right;
|
||||
text-align: end;
|
||||
@@ -733,10 +757,6 @@ input.column-boolean {
|
||||
}
|
||||
}
|
||||
|
||||
.bootstrap-datetimepicker-widget.dropdown-menu {
|
||||
z-index: 2000;
|
||||
}
|
||||
|
||||
@media screen and (max-width: @screen-xs-max) {
|
||||
.treeview {
|
||||
height: calc(100vh - 370px);
|
||||
|
||||
+101
-62
@@ -491,6 +491,7 @@
|
||||
|
||||
var input;
|
||||
var entry;
|
||||
var format, date_format, time_format;
|
||||
switch (field.type) {
|
||||
case 'boolean':
|
||||
entry = input = jQuery('<select/>', {
|
||||
@@ -509,25 +510,29 @@
|
||||
input = entry.el;
|
||||
break;
|
||||
case 'date':
|
||||
case 'datetime':
|
||||
case 'time':
|
||||
var format;
|
||||
var date_format = Sao.common.date_format(
|
||||
format = Sao.common.date_format(
|
||||
this.screen.context.date_format);
|
||||
if (field.type == 'date') {
|
||||
format = date_format;
|
||||
} else {
|
||||
var time_format = new Sao.PYSON.Decoder({}).decode(
|
||||
field.format);
|
||||
time_format = Sao.common.moment_format(time_format);
|
||||
if (field.type == 'time') {
|
||||
format = time_format;
|
||||
} else if (field.type == 'datetime') {
|
||||
format = date_format + ' ' + time_format;
|
||||
}
|
||||
}
|
||||
entry = new Sao.ScreenContainer.Dates(
|
||||
format, prefix + field.name);
|
||||
input = entry.el;
|
||||
break;
|
||||
case 'datetime':
|
||||
date_format = Sao.common.date_format(
|
||||
this.screen.context.date_format);
|
||||
time_format = new Sao.PYSON.Decoder({}).decode(
|
||||
field.format);
|
||||
time_format = Sao.common.moment_format(time_format);
|
||||
format = date_format + ' ' + time_format;
|
||||
entry = new Sao.ScreenContainer.DateTimes(
|
||||
format, prefix + field.name);
|
||||
format, prefix + field.name);
|
||||
input = entry.el;
|
||||
break;
|
||||
case 'time':
|
||||
time_format = new Sao.PYSON.Decoder({}).decode(
|
||||
field.format);
|
||||
format = Sao.common.moment_format(time_format);
|
||||
entry = new Sao.ScreenContainer.Times(
|
||||
format, prefix + field.name);
|
||||
input = entry.el;
|
||||
break;
|
||||
case 'integer':
|
||||
@@ -631,75 +636,109 @@
|
||||
this.from.on('dp.change', this._from_changed.bind(this));
|
||||
},
|
||||
_get_value: function(entry, value) {
|
||||
return entry.find('input').val();
|
||||
return entry.find('input[type=text]').val();
|
||||
},
|
||||
_set_value: function(entry, value) {
|
||||
entry.data('DateTimePicker').date(value);
|
||||
entry.find('input[type=text]').val(value);
|
||||
},
|
||||
});
|
||||
|
||||
Sao.ScreenContainer.DateTimes = Sao.class_(
|
||||
Sao.ScreenContainer.Dates = Sao.class_(
|
||||
Sao.ScreenContainer.BetweenDates, {
|
||||
build_entry: function(placeholder, el) {
|
||||
_input: 'date',
|
||||
_input_format: '%Y-%m-%d',
|
||||
_format: Sao.common.format_date,
|
||||
_parse: Sao.common.parse_date,
|
||||
build_entry: function(placeholder, el) {
|
||||
var entry = jQuery('<div/>', {
|
||||
'class': 'input-group input-group-sm',
|
||||
'data-target-input': 'nearest',
|
||||
'class': ('input-group input-group-sm ' +
|
||||
'input-icon input-icon-secondary ' +
|
||||
'input-' + this._input),
|
||||
}).appendTo(el);
|
||||
entry.uniqueId();
|
||||
jQuery('<span/>', {
|
||||
'class': 'input-group-btn'
|
||||
}).append(jQuery('<button/>', {
|
||||
'class': 'btn btn-default',
|
||||
type: 'button',
|
||||
'tabindex': -1,
|
||||
'aria-label': Sao.i18n.gettext("Open the calendar"),
|
||||
'title': Sao.i18n.gettext("Open the calendar"),
|
||||
'data-target': '#' + entry.attr('id'),
|
||||
'data-toggle': 'datetimepicker',
|
||||
}).append(Sao.common.ICONFACTORY.get_icon_img('tryton-date')
|
||||
)).appendTo(entry);
|
||||
jQuery('<input/>', {
|
||||
'class': ('form-control input-sm datetimepicker-input ' +
|
||||
'mousetrap'),
|
||||
type: 'text',
|
||||
placeholder: placeholder,
|
||||
'data-target': '#' + entry.attr('id'),
|
||||
var date = jQuery('<input/>', {
|
||||
'type': 'text',
|
||||
'class': 'form-control input-sm mousetrap',
|
||||
}).appendTo(entry);
|
||||
entry.datetimepicker({
|
||||
'locale': Sao.common.moment_format(this.format),
|
||||
'keyBinds': null,
|
||||
'useCurrent': false,
|
||||
var input = jQuery('<input/>', {
|
||||
'type': this._input,
|
||||
'role': 'button',
|
||||
'tabindex': -1,
|
||||
});
|
||||
entry.on('datetimepicker.hide', function() {
|
||||
Sao.common.set_overflow(entry, 'hide');
|
||||
});
|
||||
entry.on('datetimepicker.show', function() {
|
||||
Sao.common.set_overflow(entry, 'show');
|
||||
});
|
||||
|
||||
var mousetrap = new Mousetrap(el[0]);
|
||||
input.click(function() {
|
||||
var value = this._parse(this.format, date.val());
|
||||
value = this._format(this._input_format, value);
|
||||
input.val(value);
|
||||
}.bind(this));
|
||||
input.change(function() {
|
||||
var value = input.val();
|
||||
if (value) {
|
||||
value = this._parse(this._input_format, value);
|
||||
value = this._format(this.format, value);
|
||||
date.val(value);
|
||||
date.focus();
|
||||
}
|
||||
}.bind(this));
|
||||
if (input[0].type == this._input) {
|
||||
var icon = jQuery('<div/>', {
|
||||
'class': 'icon-input icon-secondary',
|
||||
'aria-label': Sao.i18n.gettext("Open the calendar"),
|
||||
'title': Sao.i18n.gettext("Open the calendar"),
|
||||
}).appendTo(entry);
|
||||
input.appendTo(icon);
|
||||
Sao.common.ICONFACTORY.get_icon_img('tryton-date')
|
||||
.appendTo(icon);
|
||||
}
|
||||
var mousetrap = new Mousetrap(date[0]);
|
||||
|
||||
mousetrap.bind('enter', function(e, combo) {
|
||||
entry.datetimepicker('date');
|
||||
var value = this._parse(this.format, date.val());
|
||||
value = this._format(this.format, value);
|
||||
date.val(value);
|
||||
});
|
||||
mousetrap.bind('=', function(e, combo) {
|
||||
e.preventDefault();
|
||||
entry.datetimepicker('date', moment());
|
||||
date.val(this._format(this.format, moment()));
|
||||
});
|
||||
|
||||
Sao.common.DATE_OPERATORS.forEach(function(operator) {
|
||||
mousetrap.bind(operator[0], function(e, combo) {
|
||||
e.preventDefault();
|
||||
var date = entry.datetimepicker('date');
|
||||
date.add(operator[1]);
|
||||
entry.datetimepicker('date', date);
|
||||
});
|
||||
});
|
||||
var value = (this._parse(this.format, date.val()) ||
|
||||
Sao.DateTime());
|
||||
value.add(operator[1]);
|
||||
date.val(this._format(this.format, value));
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
return entry;
|
||||
},
|
||||
});
|
||||
|
||||
Sao.ScreenContainer.Numbers = Sao.class_(Sao.ScreenContainer.BetweenDates, {
|
||||
Sao.ScreenContainer.DateTimes = Sao.class_(
|
||||
Sao.ScreenContainer.Dates, {
|
||||
_input: 'datetime-local',
|
||||
_input_format: '%Y-%m-%dT%H:%M:%S',
|
||||
_format: Sao.common.format_datetime,
|
||||
_parse: Sao.common.parse_datetime,
|
||||
});
|
||||
|
||||
Sao.ScreenContainer.Times = Sao.class_(
|
||||
Sao.ScreenContainer.Dates, {
|
||||
_input: 'time',
|
||||
_input_format: '%H:%M:%S',
|
||||
_format: Sao.common.format_time,
|
||||
_parse: Sao.common.parse_time,
|
||||
build_entry: function(placeholder, el) {
|
||||
entry = Sao.ScreenContainer.Time._super.call(
|
||||
this, placeholder, el);
|
||||
if (~navigator.userAgent.indexOf("Firefox")) {
|
||||
// time input on Firefox does not have a pop-up
|
||||
entry.find('.icon-input').hide();
|
||||
}
|
||||
return entry;
|
||||
},
|
||||
});
|
||||
|
||||
Sao.ScreenContainer.Numbers = Sao.class_(Sao.ScreenContainer.Between, {
|
||||
init: function(id) {
|
||||
Sao.ScreenContainer.Numbers._super.init.call(this, id);
|
||||
this.from.change(this._from_changed.bind(this));
|
||||
|
||||
+131
-117
@@ -1559,55 +1559,68 @@ function eval_pyson(value){
|
||||
Sao.View.Form.Date = Sao.class_(Sao.View.Form.Widget, {
|
||||
class_: 'form-date',
|
||||
_width: '10em',
|
||||
_input: 'date',
|
||||
_input_format: '%Y-%m-%d',
|
||||
_format: Sao.common.format_date,
|
||||
_parse: Sao.common.parse_date,
|
||||
_default_format: '%x',
|
||||
init: function(view, attributes) {
|
||||
Sao.View.Form.Date._super.init.call(this, view, attributes);
|
||||
this.el = jQuery('<div/>', {
|
||||
'class': this.class_
|
||||
});
|
||||
this.date = this.labelled = jQuery('<div/>', {
|
||||
var group = this.labelled = jQuery('<div/>', {
|
||||
'class': ('input-group input-group-sm ' +
|
||||
'input-icon input-icon-primary'),
|
||||
'data-target-input': 'nearest',
|
||||
'input-icon input-icon-secondary'),
|
||||
}).appendTo(this.el);
|
||||
this.date = this.labelled = jQuery('<input/>', {
|
||||
'type': 'text',
|
||||
'class': 'form-control input-sm mousetrap',
|
||||
'name': attributes.name,
|
||||
}).appendTo(group);
|
||||
this.date.uniqueId();
|
||||
Sao.common.ICONFACTORY.get_icon_img('tryton-date')
|
||||
.appendTo(jQuery('<div/>', {
|
||||
'class': 'icon-input icon-primary',
|
||||
this.input = jQuery('<input/>', {
|
||||
'type': this._input,
|
||||
'role': 'button',
|
||||
'tabindex': -1,
|
||||
});
|
||||
this.input.click(function() {
|
||||
var value = this.get_value();
|
||||
value = this._format(this._input_format, value);
|
||||
this.input.val(value);
|
||||
}.bind(this));
|
||||
this.input.change(function() {
|
||||
var value = this.input.val();
|
||||
if (value) {
|
||||
value = this._parse(this._input_format, value);
|
||||
value = this._format(this.get_format(), value);
|
||||
this.date.val(value);
|
||||
this.date.focus();
|
||||
}
|
||||
}.bind(this));
|
||||
if (this.input[0].type == this._input) {
|
||||
var icon = jQuery('<div/>', {
|
||||
'class': 'icon-input icon-secondary',
|
||||
'aria-label': Sao.i18n.gettext("Open the calendar"),
|
||||
'title': Sao.i18n.gettext("Open the calendar"),
|
||||
'data-target': '#' + this.date.attr('id'),
|
||||
'data-toggle': 'datetimepicker',
|
||||
}).appendTo(this.date));
|
||||
this.input = jQuery('<input/>', {
|
||||
'type': 'text',
|
||||
'class': 'form-control input-sm datetimepicker-input mousetrap',
|
||||
'data-target': '#' + this.date.attr('id'),
|
||||
'name': attributes.name,
|
||||
}).appendTo(this.date);
|
||||
this.date.datetimepicker({
|
||||
'locale': moment.locale(),
|
||||
'keyBinds': null,
|
||||
'useCurrent': false,
|
||||
});
|
||||
}).appendTo(group);
|
||||
this.input.appendTo(icon);
|
||||
Sao.common.ICONFACTORY.get_icon_img('tryton-date')
|
||||
.appendTo(icon);
|
||||
}
|
||||
this.date.css('max-width', this._width);
|
||||
this.date.on('change.datetimepicker', this.focus_out.bind(this));
|
||||
this.date.on('datetimepicker.hide', function() {
|
||||
Sao.common.set_overflow(this.date, 'hide');
|
||||
}.bind(this));
|
||||
this.date.on('datetimepicker.show', function() {
|
||||
Sao.common.set_overflow(this.date, 'show');
|
||||
}.bind(this));
|
||||
var mousetrap = new Mousetrap(this.el[0]);
|
||||
this.date.change(this.focus_out.bind(this));
|
||||
var mousetrap = new Mousetrap(this.date[0]);
|
||||
|
||||
mousetrap.bind('enter', function(e, combo) {
|
||||
if (!this.date.find('input').prop('readonly')) {
|
||||
this.date.datetimepicker('date');
|
||||
if (!this.date.prop('readonly')) {
|
||||
this.focus_out();
|
||||
}
|
||||
}.bind(this));
|
||||
mousetrap.bind('=', function(e, combo) {
|
||||
if (!this.date.find('input').prop('readonly')) {
|
||||
e.preventDefault();
|
||||
this.date.datetimepicker('date', moment());
|
||||
this.date.val(this._format(this.get_format(), moment()));
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
@@ -1617,42 +1630,31 @@ function eval_pyson(value){
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
var date = this.date.datetimepicker('date');
|
||||
var date = this.get_value() || Sao.DateTime();
|
||||
date.add(operator[1]);
|
||||
this.date.datetimepicker('date', date);
|
||||
this.date.val(this._format(this.get_format(), date));
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
},
|
||||
get_format: function() {
|
||||
return this.field.date_format(this.record);
|
||||
if (this.field && this.record) {
|
||||
return this.field.date_format(this.record);
|
||||
} else {
|
||||
return this._default_format;
|
||||
}
|
||||
},
|
||||
get_value: function() {
|
||||
var value = this.date.datetimepicker('date');
|
||||
if (value) {
|
||||
value.isDate = true;
|
||||
}
|
||||
return value;
|
||||
return this._parse(this.get_format(), this.date.val());
|
||||
},
|
||||
display: function() {
|
||||
var record = this.record;
|
||||
var field = this.field;
|
||||
if (record && field) {
|
||||
this.date.datetimepicker(
|
||||
'format', Sao.common.moment_format(this.get_format()));
|
||||
}
|
||||
Sao.View.Form.Date._super.display.call(this);
|
||||
var value;
|
||||
if (record) {
|
||||
value = field.get_client(record);
|
||||
} else {
|
||||
value = null;
|
||||
}
|
||||
this.date.off('change.datetimepicker');
|
||||
try {
|
||||
this.date.datetimepicker('date', value);
|
||||
} finally {
|
||||
this.date.on('change.datetimepicker', this.focus_out.bind(this));
|
||||
}
|
||||
this.date.val(this._format(this.get_format(), value));
|
||||
},
|
||||
focus: function() {
|
||||
this.input.focus();
|
||||
@@ -1677,33 +1679,43 @@ function eval_pyson(value){
|
||||
Sao.View.Form.DateTime = Sao.class_(Sao.View.Form.Date, {
|
||||
class_: 'form-datetime',
|
||||
_width: '20em',
|
||||
_input: 'datetime-local',
|
||||
_input_format: '%Y-%m-%dT%H:%M:%S',
|
||||
_format: Sao.common.format_datetime,
|
||||
_parse: Sao.common.parse_datetime,
|
||||
_default_format: '%x %X',
|
||||
get_format: function() {
|
||||
var record = this.record;
|
||||
var field = this.field;
|
||||
return field.date_format(record) + ' ' + field.time_format(record);
|
||||
},
|
||||
get_value: function() {
|
||||
var value = this.date.datetimepicker('date');
|
||||
if (value) {
|
||||
value.isDateTime = true;
|
||||
if (this.field && this.record) {
|
||||
return (this.field.date_format(this.record) + ' ' +
|
||||
this.field.time_format(this.record));
|
||||
} else {
|
||||
return this._default_format;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Sao.View.Form.Time = Sao.class_(Sao.View.Form.Date, {
|
||||
class_: 'form-time',
|
||||
_width: '10em',
|
||||
get_format: function() {
|
||||
return this.field.time_format(this.record);
|
||||
},
|
||||
get_value: function() {
|
||||
var value = this.date.datetimepicker('date');
|
||||
if (value) {
|
||||
value.isTime = true;
|
||||
_input: 'time',
|
||||
_input_format: '%H:%M:%S',
|
||||
_format: Sao.common.format_time,
|
||||
_parse: Sao.common.parse_time,
|
||||
_default_format: '%X',
|
||||
init: function(view, attributes) {
|
||||
Sao.View.Form.Time._super.init.call(this, view, attributes);
|
||||
if (~navigator.userAgent.indexOf("Firefox")) {
|
||||
// time input on Firefox does not have a pop-up
|
||||
this.input.parent().hide();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
},
|
||||
get_format: function() {
|
||||
if (this.field && this.record) {
|
||||
return this.field.time_format(this.record);
|
||||
} else {
|
||||
return this._default_format;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Sao.View.Form.TimeDelta = Sao.class_(Sao.View.Form.Widget, {
|
||||
@@ -4734,76 +4746,78 @@ function eval_pyson(value){
|
||||
Sao.View.Form.Dict.Date = Sao.class_(Sao.View.Form.Dict.Entry, {
|
||||
class_: 'dict-date',
|
||||
format: '%x',
|
||||
_input: 'date',
|
||||
_input_format: '%Y-%m-%d',
|
||||
_format: Sao.common.format_date,
|
||||
_parse: Sao.common.parse_date,
|
||||
create_widget: function() {
|
||||
Sao.View.Form.Dict.Date._super.create_widget.call(this);
|
||||
this.date = this.input.parent();
|
||||
this.date.addClass('input-icon input-icon-primary');
|
||||
this.date.attr('data-target-input', 'nearest');
|
||||
this.date.uniqueId();
|
||||
Sao.common.ICONFACTORY.get_icon_img('tryton-date')
|
||||
.appendTo(jQuery('<div/>', {
|
||||
'class': 'icon-input icon-primary',
|
||||
var group = this.input.parent().find('.input-group-btn');
|
||||
this.input_date = jQuery('<input/>', {
|
||||
'type': this._input,
|
||||
'role': 'button',
|
||||
'tabindex': -1,
|
||||
});
|
||||
this.input_date.click(function() {
|
||||
var value = this.get_value();
|
||||
value = this._format(this._input_format, value);
|
||||
this.input_date.val(value);
|
||||
}.bind(this));
|
||||
this.input_date.change(function() {
|
||||
var value = this.input_date.val();
|
||||
if (value) {
|
||||
value = this._parse(this._input_format, value);
|
||||
value = this._format(this.format, value);
|
||||
this.input.val(value);
|
||||
this.input.focus();
|
||||
}
|
||||
}.bind(this));
|
||||
if (this.input_date[0].type == this._input) {
|
||||
var icon = jQuery('<div/>', {
|
||||
'class': 'btn btn-default',
|
||||
'aria-label': Sao.i18n.gettext("Open the calendar"),
|
||||
'title': Sao.i18n.gettext("Open the calendar"),
|
||||
'data-target': '#' + this.date.attr('id'),
|
||||
'data-toggle': 'datetimepicker',
|
||||
}).prependTo(this.date));
|
||||
this.input.addClass('datetimepicker-input');
|
||||
this.input.data('target', '#' + this.date.attr('id'));
|
||||
this.date.datetimepicker({
|
||||
'format': Sao.common.moment_format(this.format),
|
||||
'locale': moment.locale(),
|
||||
'keyBinds': null,
|
||||
'useCurrent': false,
|
||||
});
|
||||
this.date.on('change.datetimepicker',
|
||||
this.parent_widget.focus_out.bind(this.parent_widget));
|
||||
}).prependTo(group);
|
||||
this.input_date.appendTo(icon);
|
||||
Sao.common.ICONFACTORY.get_icon_img('tryton-date')
|
||||
.appendTo(icon);
|
||||
}
|
||||
var mousetrap = new Mousetrap(this.el[0]);
|
||||
|
||||
mousetrap.bind(['enter', '='], function(e, combo) {
|
||||
if (e.which != Sao.common.RETURN_KEYCODE) {
|
||||
e.preventDefault();
|
||||
}
|
||||
this.date.datetimepicker('date', moment());
|
||||
mousetrap.bind('enter', function(e, combo) {
|
||||
var value = this._parse(this.format, this.input.val());
|
||||
value = this._format(this.format, value);
|
||||
this.input.val(value);
|
||||
}.bind(this));
|
||||
mousetrap.bind('=', function(e, combo) {
|
||||
e.preventDefault();
|
||||
this.input.val(this._format(this.format, moment()));
|
||||
}.bind(this));
|
||||
|
||||
Sao.common.DATE_OPERATORS.forEach(function(operator) {
|
||||
mousetrap.bind(operator[0], function(e, combo) {
|
||||
e.preventDefault();
|
||||
var date = this.date.datetimepicker('date');
|
||||
var date = this.get_value() || Sao.DateTime();
|
||||
date.add(operator[1]);
|
||||
this.date.datetimepicker('date', date);
|
||||
this.input.val(this._format(this.format, date));
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
},
|
||||
get_value: function() {
|
||||
var value = this.date.datetimepicker('date');
|
||||
if (value) {
|
||||
value.isDate = true;
|
||||
}
|
||||
return value;
|
||||
return this._parse(this.format, this.input.val());
|
||||
},
|
||||
set_value: function(value) {
|
||||
this.date.off('change.datetimepicker');
|
||||
try {
|
||||
this.date.datetimepicker('date', value);
|
||||
} finally {
|
||||
this.date.on('change.datetimepicker',
|
||||
this.parent_widget.focus_out.bind(this.parent_widget));
|
||||
}
|
||||
}
|
||||
this.input.val(this._format(this.format, value));
|
||||
},
|
||||
});
|
||||
|
||||
Sao.View.Form.Dict.DateTime = Sao.class_(Sao.View.Form.Dict.Date, {
|
||||
class_: 'dict-datetime',
|
||||
format: '%x %X',
|
||||
get_value: function() {
|
||||
var value = this.date.datetimepicker('date');
|
||||
if (value) {
|
||||
value.isDateTime = true;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
_input: 'datetime-local',
|
||||
_input_format: '%Y-%m-%dT%H:%M:%S',
|
||||
_format: Sao.common.format_datetime,
|
||||
_parse: Sao.common.parse_datetime,
|
||||
});
|
||||
|
||||
Sao.View.Form.PYSON = Sao.class_(Sao.View.Form.Char, {
|
||||
|
||||
@@ -2617,11 +2617,6 @@
|
||||
init: function(view, attributes) {
|
||||
Sao.View.EditableTree.Date._super.init.call(
|
||||
this, view, attributes);
|
||||
// XXX: click event does not work in editable
|
||||
// so we manage it ourselves to toggle the picker.
|
||||
this.date.find('.icon-input').removeAttr('data-toggle').click(function() {
|
||||
this.date.datetimepicker('toggle');
|
||||
}.bind(this));
|
||||
Sao.View.EditableTree.editable_mixin(this);
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user