[IMP] web: pager: editable feature + documentation

Pager's state can now be edited (mainly to change the limit,
but the range of values as well).
This commit is contained in:
Aaron Bohy
2015-06-18 13:51:56 +02:00
parent 6070dc201e
commit 5f72fb8e10
3 changed files with 145 additions and 37 deletions
@@ -341,6 +341,17 @@ function float_is_zero (value, decimals) {
return Math.abs(round_precision(value, epsilon)) < epsilon;
};
/**
* Confines a value inside an interval
* @param {Number} [val] the value to confine
* @param {Number} [min] the minimum of the interval
* @param {Number} [max] the maximum of the interval
* @return val if val is in [min, max], min if val < min and max otherwise
*/
function confine (val, min, max) {
return Math.max(min, Math.min(max, val));
}
function assert (bool) {
if (!bool) {
throw new Error("AssertionError");
@@ -413,6 +424,7 @@ return {
round_precision: round_precision,
round_decimals: round_decimals,
float_is_zero: float_is_zero,
confine: confine,
assert: assert,
xor: xor,
DropMisordered: DropMisordered,
+130 -34
View File
@@ -1,6 +1,7 @@
odoo.define('web.Pager', function (require) {
"use strict";
var utils = require('web.utils');
var Widget = require('web.Widget');
var direction = {
@@ -12,13 +13,22 @@ var Pager = Widget.extend({
template: "Pager",
events: {
'click .o-pager-previous': 'previous',
'click .o-pager-next': 'next',
'click .o_pager_previous': 'previous',
'click .o_pager_next': 'next',
'click .o_pager_value': '_edit',
},
// pager goes from 1 to size (included).
// current value is current_min (if limit === 1)
// or the interval [current_min, current_min + limit[ if limit > 1
/**
* The pager goes from 1 to size (included).
* The current value is current_min if limit === 1
* or the interval [current_min, current_min + limit[ if limit > 1
* @param {Widget} [parent] the parent widget
* @param {int} [size] the total number of elements
* @param {int} [current_min] the first element of the current_page
* @param {int} [limit] the number of elements per page
* @param {boolean} [options.can_edit] editable feature of the pager
* @param {boolean} [options.single_page_hidden] (not) to display the pager if only one page
*/
init: function (parent, size, current_min, limit, options) {
this.state = {
size: size,
@@ -30,39 +40,142 @@ var Pager = Widget.extend({
return Math.min(this.current_min + this.limit - 1, this.size);
}
});
this.options = options || {};
this.options = _.defaults({}, options, {
can_edit: true, // editable
single_page_hidden: false, // displayed even if there is a single page
});
this._super(parent);
},
/**
* Renders the pager
* @returns {jQuery.Deferred}
*/
start: function () {
this.$content = this.$('.o-pager-value');
this.$value = this.$('.o_pager_value');
this.$limit = this.$('.o_pager_limit');
this._render();
return this._super();
},
set_state: function (options) {
_.extend(this.state, options);
/**
* Sets the state of the pager and renders it
* @param {Object} [state] the values to update (size, current_min and limit)
*/
update_state: function (state) {
_.extend(this.state, state);
this._render();
},
previous: function(e) {
/**
* Executes the previous action on the pager
*/
previous: function() {
this._change_selection(direction.previous);
},
/**
* Executes the next action on the pager
*/
next: function() {
this._change_selection(direction.next);
},
/**
* Disables the pager's arrows
*/
disable: function() {
this.$('button').prop("disabled", true);
},
/**
* Enables the pager's arrows
*/
enable: function() {
this.$('button').prop("disabled", false);
},
/**
* Private function that displays an input to edit the pager's state
*/
_edit: function() {
if (this.options.can_edit) {
var self = this;
var $input = $('<input>').val(this.$value.html());
this.$value.html($input);
$input.focus();
// Event handlers
$input.click(function(ev) {
ev.stopPropagation(); // ignore clicks on the input
});
$input.blur(function(ev) {
self._save($(ev.target)); // save the state when leaving the input
});
$input.on('keydown', function (ev) {
ev.stopPropagation();
if (ev.which === $.ui.keyCode.ENTER) {
self._save($(ev.target)); // save on enter
} else if (ev.which === $.ui.keyCode.ESCAPE) {
self._render(); // leave on escape
}
});
}
},
/**
* Private function that saves the state from the content of the input
* @param {jQuery} [$input] the jQuery element containing the new state
*/
_save: function($input) {
var value = $input.val().split("-");
var min = utils.confine(parseInt(value[0], 10), 1, this.state.size);
var max = utils.confine(parseInt(value[1], 10), 1, this.state.size);
if (!isNaN(min)) {
this.state.current_min = min;
if (!isNaN(max)) {
this.state.limit = utils.confine(max-min+1, 1, this.state.size);
} else {
// The state has been given as a single value -> set the limit to 1
this.state.limit = 1;
}
this.trigger('pager_changed', _.clone(this.state));
}
// Render the pager's new state (removes the input)
this._render();
},
/**
* Private function that updates the pager's state according to a pager action
* @param {int} [direction] the action (previous or next) on the pager
*/
_change_selection: function (direction) {
var size = this.state.size;
var current_min = this.state.current_min;
var limit = this.state.limit;
// Compute the new current_min
current_min = (current_min + limit*direction);
if (current_min > size) {
current_min = 1;
} else if ((current_min < 1) && (limit === 1)) {
current_min = size;
} else if ((current_min < 1) && (limit > 1)) {
current_min = size - ((size % limit) || limit) + 1;
}
this.state.current_min = current_min;
this.trigger('pager_changed', _.clone(this.state));
this._render();
},
/**
* Private function that renders the pager's state
*/
_render: function () {
var state;
var size = this.state.size;
var current_min = this.state.current_min;
var current_max = this.state.current_max;
@@ -79,33 +192,16 @@ var Pager = Widget.extend({
this.enable();
}
if (this.state.limit === 1) {
state = "" + current_min + " / " + size;
} else {
state = "" + current_min + "-" + current_max + " / " + size;
var value = "" + current_min;
if (this.state.limit > 1) {
value += "-" + current_max;
}
this.$content.html(state);
this.$value.html(value);
this.$limit.html(size);
}
},
_change_selection: function (direction) {
var size = this.state.size;
var current_min = this.state.current_min;
var limit = this.state.limit;
current_min = (current_min + limit*direction);
if (current_min > size) {
current_min = 1;
} else if ((current_min < 1) && (limit === 1)) {
current_min = size;
} else if ((current_min < 1) && (limit > 1)) {
current_min = size - ((size % limit) || limit) + 1;
}
this.state.current_min = current_min;
this.trigger('pager_changed', _.clone(this.state));
this._render();
},
});
return Pager;
});
});
+3 -3
View File
@@ -1907,10 +1907,10 @@
</button>
<div t-name="Pager">
<span class="o-pager-value"></span>
<span class="o_pager_value"></span> / <span class="o_pager_limit"></span>
<span class="btn-group btn-group-sm">
<button type="button" class="fa fa-chevron-left btn btn-icon o-pager-previous" accesskey="O"/>
<button type="button" class="fa fa-chevron-right btn btn-icon o-pager-next" accesskey="P"/>
<button type="button" class="fa fa-chevron-left btn btn-icon o_pager_previous" accesskey="O"/>
<button type="button" class="fa fa-chevron-right btn btn-icon o_pager_next" accesskey="P"/>
</span>
</div>