Browse Source

[10.0][MIG]migrate web_widget_timepicker

pull/656/head
smurf-U 8 years ago
committed by Kaushal Prajapati
parent
commit
b97d2f1cda
  1. 26
      web_widget_timepicker/README.rst
  2. 8
      web_widget_timepicker/__manifest__.py
  3. 5
      web_widget_timepicker/static/src/css/web_widget_timepicker.css
  4. 30
      web_widget_timepicker/static/src/js/web_widget_timepicker.js
  5. 4
      web_widget_timepicker/static/src/lib/jquery.timepicker/jquery.timepicker.css
  6. 219
      web_widget_timepicker/static/src/lib/jquery.timepicker/jquery.timepicker.js
  7. 4
      web_widget_timepicker/static/src/xml/web_widget_timepicker.xml
  8. 28
      web_widget_timepicker/views/web_widget_timepicker_assets.xml

26
web_widget_timepicker/README.rst

@ -2,7 +2,6 @@
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
===============================
Timepicker widget in form views
===============================
@ -52,16 +51,10 @@ See the available options at `jquery-timepicker <https://github.com//jonthornton
.. |formview| image:: ./images/form_view.png
Known issues / Roadmap
======================
* No validation on options.
Credits
=======
* The module uses the `jquery-timepicker <https://cdnjs.com//libraries//jquery-timepicker>`_ plugin by Jon Thornton. This software is made available under the open source MIT License. © 2014 Jon Thornton and contributors
* The module uses the `jquery-timepicker <https://github.com//jonthornton//jquery-timepicker#timepicker-plugin-for-jquery>`_. plugin by Jon Thornton. This software is made available under the open source MIT License. © 2014 Jon Thornton and contributors
* Odoo Community Association (OCA)
@ -70,3 +63,20 @@ Contributors
------------
* Michael Fried <Michael.Fried@vividlab.de>
* Kaushal Prajapati <kbprajapati@live.com>
Maintainer
----------
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org
This module is maintained by the OCA.
OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.
To contribute to this module, please visit https://odoo-community.org.

8
web_widget_timepicker/__manifest__.py

@ -3,12 +3,14 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
"name": "Web Timepicker Widget",
"version": "9.0.1.0.0",
"author": "VividLab, Odoo Community Association (OCA)",
"version": "10.0.1.0.0",
"author": "VividLab, "
"Odoo Community Association (OCA), "
"Kaushal Prajapati",
"license": "AGPL-3",
"category": "Web",
"website": "http://www.vividlab.de",
'installable': False,
'installable': True,
"depends": [
"web",
],

5
web_widget_timepicker/static/src/css/web_widget_timepicker.css

@ -1,3 +1,6 @@
.oe_form_editable .oe_form .oe_form_field_time input {
.o_form_editable .o_form_field_time input {
width: 6em;
}
.o_form_field_time{
display: -webkit-inline-box !important;
}

30
web_widget_timepicker/static/src/js/web_widget_timepicker.js

@ -3,22 +3,22 @@ odoo.define('web_widget_timepicker', function (require) {
var core = require('web.core');
var formats = require('web.formats');
var common = require('web.form_common');
var common = require('web.form_common');
var TimePickerField = common.AbstractField.extend(common.ReinitializeFieldMixin, {
is_field_number: true,
is_field_number: true,
template: "TimePickerField",
internal_format: 'float_time',
widget_class: 'oe_form_field_time',
widget_class: 'o_form_field_time',
events: {
'change input': 'store_dom_value',
},
init: function (field_manager, node) {
this._super(field_manager, node);
this.internal_set_value(0);
this.options = _.defaults( this.options, {
this.options = _.defaults(this.options, {
step: 15,
selectOnBlur: true,
timeFormat: 'H:i',
@ -27,14 +27,14 @@ odoo.define('web_widget_timepicker', function (require) {
},
initialize_content: function() {
if(!this.get("effective_readonly")) {
this.$el.find('input').timepicker(this.options);
this.setupFocus(this.$('input'));
}
this.$el.find('input').timepicker(this.options);
this.setupFocus(this.$('input'));
}
},
is_syntax_valid: function() {
if (!this.get("effective_readonly") && this.$("input").size() > 0) {
try {
this.parse_value(this.$('input').val(),'');
this.parse_value(this.$('input').val(), '');
return true;
} catch(e) {
return false;
@ -55,28 +55,28 @@ odoo.define('web_widget_timepicker', function (require) {
height: height,
width: width
});
},
},
store_dom_value: function () {
if (!this.get('effective_readonly')) {
this.internal_set_value(
this.parse_value(
this.$('input').val(),''));
this.$('input').val(), ''));
}
},
parse_value: function(val, def) {
return formats.parse_value(val, {"widget": this.internal_format}, def);
return formats.parse_value(val, {"widget": this.internal_format}, def);
},
format_value: function(val, def) {
return formats.format_value(val, {"widget": this.internal_format}, def);
},
render_value: function() {
var show_value = this.format_value(this.get('value'),'');
var show_value = this.format_value(this.get('value'), '');
if (!this.get("effective_readonly")) {
this.$input = this.$el.find('input');
this.$input.val(show_value);
} else {
this.$(".oe_form_time_content").text(show_value);
this.$(".o_form_time_content").text(show_value);
}
},
});
@ -84,6 +84,6 @@ odoo.define('web_widget_timepicker', function (require) {
core.form_widget_registry.add('timepicker', TimePickerField);
return {
TimePickerField: TimePickerField,
TimePickerField: TimePickerField,
};
});

4
web_widget_timepicker/static/src/lib/jquery.timepicker/jquery.timepicker.css

@ -1,6 +1,6 @@
.ui-timepicker-wrapper {
overflow-y: auto;
height: 150px;
max-height: 150px;
width: 6.5em;
background: #fff;
border: 1px solid #ddd;
@ -69,4 +69,4 @@ li.ui-timepicker-selected .ui-timepicker-duration,
.ui-timepicker-list li.ui-timepicker-disabled:hover,
.ui-timepicker-list li.ui-timepicker-selected.ui-timepicker-disabled {
background: #f2f2f2;
}
}

219
web_widget_timepicker/static/src/lib/jquery.timepicker/jquery.timepicker.js

@ -1,5 +1,5 @@
/*!
* jquery-timepicker v1.10.1 - A jQuery timepicker plugin inspired by Google Calendar. It supports both mouse and keyboard navigation.
* jquery-timepicker v1.11.11 - A jQuery timepicker plugin inspired by Google Calendar. It supports both mouse and keyboard navigation.
* Copyright (c) 2015 Jon Thornton - http://jonthornton.github.com/jquery-timepicker/
* License: MIT
*/
@ -30,6 +30,58 @@
hrs: 'hrs'
};
var _DEFAULTS = {
appendTo: 'body',
className: null,
closeOnWindowScroll: false,
disableTextInput: false,
disableTimeRanges: [],
disableTouchKeyboard: false,
durationTime: null,
forceRoundTime: false,
maxTime: null,
minTime: null,
noneOption: false,
orientation: 'l',
roundingFunction: function(seconds, settings) {
if (seconds === null) {
return null;
} else if (typeof settings.step !== "number") {
// TODO: nearest fit irregular steps
return seconds;
} else {
var offset = seconds % (settings.step*60); // step is in minutes
var start = settings.minTime || 0;
// adjust offset by start mod step so that the offset is aligned not to 00:00 but to the start
offset -= start % (settings.step * 60);
if (offset >= settings.step*30) {
// if offset is larger than a half step, round up
seconds += (settings.step*60) - offset;
} else {
// round down
seconds -= offset;
}
return _moduloSeconds(seconds, settings);
}
},
scrollDefault: null,
selectOnBlur: false,
show2400: false,
showDuration: false,
showOn: ['click', 'focus'],
showOnFocus: true,
step: 30,
stopScrollPropagation: false,
timeFormat: 'g:ia',
typeaheadHighlight: true,
useSelect: false,
wrapHours: true
};
var methods = {
init: function(options)
{
@ -39,13 +91,13 @@
// pick up settings from data attributes
var attributeOptions = [];
for (var key in $.fn.timepicker.defaults) {
for (var key in _DEFAULTS) {
if (self.data(key)) {
attributeOptions[key] = self.data(key);
}
}
var settings = $.extend({}, $.fn.timepicker.defaults, attributeOptions, options);
var settings = $.extend({}, _DEFAULTS, options, attributeOptions);
if (settings.lang) {
_lang = $.extend(_lang, settings.lang);
@ -70,8 +122,10 @@
if (settings.disableTextInput) {
self.on('keydown.timepicker', _disableTextInputHandler);
}
self.on('cut.timepicker', _keyuphandler);
self.on('paste.timepicker', _keyuphandler);
_formatValue.call(self.get(0));
_formatValue.call(self.get(0), null, 'initial');
}
});
},
@ -165,6 +219,11 @@
}
}
// if not found or disabled, intelligently find first selectable element
if (!selected.length || selected.hasClass('ui-timepicker-disabled')) {
selected = list.find('li:not(.ui-timepicker-disabled):first');
}
if (selected && selected.length) {
var topOffset = list.scrollTop() + selected.position().top - selected.outerHeight();
list.scrollTop(topOffset);
@ -243,6 +302,8 @@
self.data('timepicker-settings', settings);
_formatValue.call(self.get(0), {'type':'change'}, 'initial');
if (list) {
list.remove();
self.data('timepicker-list', false);
@ -308,7 +369,9 @@
prettyTime = value;
}
_setTimeValue(self, prettyTime);
self.val(prettyTime);
_formatValue.call(self.get(0), {'type':'change'}, 'initial');
if (self.data('timepicker-list')) {
_setSelected(self, self.data('timepicker-list'));
}
@ -507,8 +570,8 @@
row.text(timeString);
} else {
var row = $('<li />');
row.addClass(timeInt % 86400 < 43200 ? 'ui-timepicker-am' : 'ui-timepicker-pm');
row.data('time', (timeInt <= 86400 ? timeInt : timeInt % 86400));
row.addClass((timeInt % _ONE_DAY) < (_ONE_DAY / 2) ? 'ui-timepicker-am' : 'ui-timepicker-pm');
row.data('time', _moduloSeconds(timeInt, settings));
row.text(timeString);
}
@ -570,7 +633,7 @@
appendTo.append(wrapped_list);
_setSelected(self, list);
list.on('mousedown touchstart', 'li', function(e) {
list.on('mousedown click', 'li', function(e) {
// hack: temporarily disable the focus handler
// to deal with the fact that IE fires 'focus'
@ -592,8 +655,8 @@
if (_selectValue(self)) {
self.trigger('hideTimepicker');
list.on('mouseup.timepicker touchend.timepicker', 'li', function(e) {
list.off('mouseup.timepicker touchend.timepicker');
list.on('mouseup.timepicker click.timepicker', 'li', function(e) {
list.off('mouseup.timepicker click.timepicker');
wrapped_list.hide();
});
}
@ -640,13 +703,21 @@
// event handler to decide whether to close timepicker
function _closeHandler(e)
{
if (e.target == window) {
// mobile Chrome fires focus events against window for some reason
return;
}
var target = $(e.target);
var input = target.closest('.ui-timepicker-input');
if (input.length === 0 && target.closest('.ui-timepicker-wrapper').length === 0) {
methods.hide();
$(document).unbind('.ui-timepicker');
$(window).unbind('.ui-timepicker');
if (target.closest('.ui-timepicker-input').length || target.closest('.ui-timepicker-wrapper').length) {
// active timepicker was focused. ignore
return;
}
methods.hide();
$(document).unbind('.ui-timepicker');
$(window).unbind('.ui-timepicker');
}
function _hideKeyboard(self)
@ -685,7 +756,8 @@
{
list.find('li').removeClass('ui-timepicker-selected');
var timeValue = _time2int(_getTimeValue(self), self.data('timepicker-settings'));
var settings = self.data('timepicker-settings');
var timeValue = _time2int(_getTimeValue(self), settings);
if (timeValue === null) {
return;
}
@ -699,19 +771,26 @@
list.scrollTop(list.scrollTop() + selected.position().top - selected.outerHeight());
}
selected.addClass('ui-timepicker-selected');
if (settings.forceRoundTime || selected.data('time') === timeValue) {
selected.addClass('ui-timepicker-selected');
}
}
}
function _formatValue(e, origin)
{
if (this.value === '' || origin == 'timepicker') {
if (origin == 'timepicker') {
return;
}
var self = $(this);
if (this.value === '') {
_setTimeValue(self, null, origin);
return;
}
if (self.is(':focus') && (!e || e.type != 'change')) {
return;
}
@ -726,8 +805,8 @@
var rangeError = false;
// check that the time in within bounds
if (settings.minTime !== null && seconds < settings.minTime
&& settings.maxTime !== null && seconds > settings.maxTime) {
if ((settings.minTime !== null && settings.maxTime !== null)
&& (seconds < settings.minTime || seconds > settings.maxTime)) {
rangeError = true;
}
@ -740,17 +819,21 @@
});
if (settings.forceRoundTime) {
seconds = settings.roundingFunction(seconds, settings);
var roundSeconds = settings.roundingFunction(seconds, settings);
if (roundSeconds != seconds) {
seconds = roundSeconds;
origin = null;
}
}
var prettyTime = _int2time(seconds, settings);
if (rangeError) {
if (_setTimeValue(self, prettyTime, 'error')) {
if (_setTimeValue(self, prettyTime, 'error') || e && e.type == 'change') {
self.trigger('timeRangeError');
}
} else {
_setTimeValue(self, prettyTime);
_setTimeValue(self, prettyTime, origin);
}
}
@ -779,7 +862,7 @@
self.data('ui-timepicker-value', value);
if (source == 'select') {
self.trigger('selectTime').trigger('changeTime').trigger('change', 'timepicker');
} else if (source != 'error') {
} else if (['error', 'initial'].indexOf(source) == -1) {
self.trigger('changeTime');
}
@ -830,6 +913,7 @@
case 13: // return
if (_selectValue(self)) {
_formatValue.call(self.get(0), {'type':'change'});
methods.hide.apply(this);
}
@ -909,6 +993,17 @@
return true;
}
if (e.type === 'paste' || e.type === 'cut') {
setTimeout(function () {
if (settings.typeaheadHighlight) {
_setSelected(self, list);
} else {
list.hide();
}
}, 0);
return;
}
switch (e.keyCode) {
case 96: // numpad numerals
@ -1124,10 +1219,11 @@
return null;
}
var unboundedHour = parseInt(time[2]*1, 10);
var hour = (unboundedHour > 24) ? unboundedHour % 24 : unboundedHour;
var hour = parseInt(time[2]*1, 10);
var ampm = time[1] || time[5];
var hours = hour;
var minutes = ( time[3]*1 || 0 );
var seconds = ( time[4]*1 || 0 );
if (hour <= 12 && ampm) {
var isPm = (ampm == _lang.pm || ampm == _lang.PM);
@ -1137,10 +1233,17 @@
} else {
hours = (hour + (isPm ? 12 : 0));
}
} else if (settings) {
var t = hour * 3600 + minutes * 60 + seconds;
if (t >= _ONE_DAY + (settings.show2400 ? 1 : 0)) {
if (settings.wrapHours === false) {
return null;
}
hours = hour % 24;
}
}
var minutes = ( time[3]*1 || 0 );
var seconds = ( time[4]*1 || 0 );
var timeInt = hours*3600 + minutes*60 + seconds;
// if no am/pm provided, intelligently guess based on the scrollDefault
@ -1158,6 +1261,14 @@
return ("0" + n).slice(-2);
}
function _moduloSeconds(seconds, settings) {
if (seconds == _ONE_DAY && settings.show2400) {
return seconds;
}
return seconds%_ONE_DAY;
}
// Plugin entry
$.fn.timepicker = function(method)
{
@ -1172,54 +1283,4 @@
else if(typeof method === "object" || !method) { return methods.init.apply(this, arguments); }
else { $.error("Method "+ method + " does not exist on jQuery.timepicker"); }
};
// Global defaults
$.fn.timepicker.defaults = {
appendTo: 'body',
className: null,
closeOnWindowScroll: false,
disableTextInput: false,
disableTimeRanges: [],
disableTouchKeyboard: false,
durationTime: null,
forceRoundTime: false,
maxTime: null,
minTime: null,
noneOption: false,
orientation: 'l',
roundingFunction: function(seconds, settings) {
if (seconds === null) {
return null;
} else if (typeof settings.step !== "number") {
// TODO: nearest fit irregular steps
return seconds;
} else {
var offset = seconds % (settings.step*60); // step is in minutes
if (offset >= settings.step*30) {
// if offset is larger than a half step, round up
seconds += (settings.step*60) - offset;
} else {
// round down
seconds -= offset;
}
if (seconds == _ONE_DAY && settings.show2400) {
return seconds;
}
return seconds%_ONE_DAY;
}
},
scrollDefault: null,
selectOnBlur: false,
show2400: false,
showDuration: false,
showOn: ['click', 'focus'],
showOnFocus: true,
step: 30,
stopScrollPropagation: false,
timeFormat: 'g:ia',
typeaheadHighlight: true,
useSelect: false
};
}));
}));

4
web_widget_timepicker/static/src/xml/web_widget_timepicker.xml

@ -2,7 +2,7 @@
<templates id="template" xml:space="preserve">
<t t-name="TimePickerField">
<span t-att-class="'oe_form_field '+widget.widget_class" t-att-style="widget.node.attrs.style">
<span t-att-class="'o_form_field '+widget.widget_class" t-att-style="widget.node.attrs.style">
<t t-if="!widget.get('effective_readonly')">
<input t-att-type="'text'"
class="o_timepicker_input"
@ -14,7 +14,7 @@
<span class="fa fa-clock-o o_timepicker_button"/>
</t>
<t t-if="widget.get('effective_readonly')">
<span class="oe_form_time_content"></span>
<span class="o_form_time_content"/>
</t>
</span>
</t>

28
web_widget_timepicker/views/web_widget_timepicker_assets.xml

@ -1,14 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<template id="web_widget_timepicker_assets_backend" name="web_widget_timepicker assets" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<script type="text/javascript" src="/web_widget_timepicker/static/src/lib/jquery.timepicker/jquery.timepicker.js"></script>
<script type="text/javascript" src="/web_widget_timepicker/static/src/js/web_widget_timepicker.js"></script>
<link rel="stylesheet" href="/web_widget_timepicker/static/src/lib/jquery.timepicker/jquery.timepicker.css"/>
<link rel="stylesheet" href="/web_widget_timepicker/static/src/css/web_widget_timepicker.css"/>
</xpath>
</template>
</data>
</openerp>
<odoo>
<template id="web_widget_timepicker_assets_backend"
name="web_widget_timepicker assets"
inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<script type="text/javascript"
src="/web_widget_timepicker/static/src/lib/jquery.timepicker/jquery.timepicker.js"/>
<script type="text/javascript"
src="/web_widget_timepicker/static/src/js/web_widget_timepicker.js"/>
<link rel="stylesheet"
href="/web_widget_timepicker/static/src/lib/jquery.timepicker/jquery.timepicker.css"/>
<link rel="stylesheet"
href="/web_widget_timepicker/static/src/css/web_widget_timepicker.css"/>
</xpath>
</template>
</odoo>
Loading…
Cancel
Save