openerp.base.list = function (openerp) { openerp.base.views.add('list', 'openerp.base.ListView'); openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListView# */ { defaults: { // records can be selected one by one 'selectable': true, // list rows can be deleted 'deletable': true, // whether the column headers should be displayed 'header': true, // display addition button, with that label 'addable': "New", // whether the list view can be sorted, note that once a view has been // sorted it can not be reordered anymore 'sortable': true, // whether the view rows can be reordered (via vertical drag & drop) 'reorderable': true }, /** * Core class for list-type displays. * * As a view, needs a number of view-related parameters to be correctly * instantiated, provides options and overridable methods for behavioral * customization. * * See constructor parameters and method documentations for information on * the default behaviors and possible options for the list view. * * @constructs * @param parent parent object * @param element_id the id of the DOM elements this view should link itself to * @param {openerp.base.DataSet} dataset the dataset the view should work with * @param {String} view_id the listview's identifier, if any * @param {Object} options A set of options used to configure the view * @param {Boolean} [options.selectable=true] determines whether view rows are selectable (e.g. via a checkbox) * @param {Boolean} [options.header=true] should the list's header be displayed * @param {Boolean} [options.deletable=true] are the list rows deletable * @param {void|String} [options.addable="New"] should the new-record button be displayed, and what should its label be. Use ``null`` to hide the button. * @param {Boolean} [options.sortable=true] is it possible to sort the table by clicking on column headers * @param {Boolean} [options.reorderable=true] is it possible to reorder list rows * * @borrows openerp.base.ActionExecutor#execute_action as #execute_action */ init: function(parent, element_id, dataset, view_id, options) { this._super(parent, element_id); this.set_default_options(_.extend({}, this.defaults, options || {})); this.dataset = dataset; this.model = dataset.model; this.view_id = view_id; this.columns = []; this.records = new Collection(); this.set_groups(new openerp.base.ListView.Groups(this)); if (this.dataset instanceof openerp.base.DataSetStatic) { this.groups.datagroup = new openerp.base.StaticDataGroup(this.dataset); } this.page = 0; }, /** * Retrieves the view's number of records per page (|| section) * * options > defaults > parent.action.limit > indefinite * * @returns {Number|null} */ limit: function () { if (this._limit === undefined) { this._limit = (this.options.limit || this.defaults.limit || (this.widget_parent.action || {}).limit || null); } return this._limit; }, /** * Set a custom Group construct as the root of the List View. * * @param {openerp.base.ListView.Groups} groups */ set_groups: function (groups) { var self = this; if (this.groups) { $(this.groups).unbind("selected deleted action row_link"); delete this.groups; } this.groups = groups; $(this.groups).bind({ 'selected': function (e, ids, records) { self.do_select(ids, records); }, 'deleted': function (e, ids) { self.do_delete(ids); }, 'action': function (e, action_name, id, callback) { self.do_button_action(action_name, id, callback); }, 'row_link': function (e, id, dataset) { self.do_activate_record(dataset.index, id, dataset); } }); }, /** * View startup method, the default behavior is to set the ``oe-listview`` * class on its root element and to perform an RPC load call. * * @returns {$.Deferred} loading promise */ start: function() { this.$element.addClass('oe-listview'); return this.reload_view(); }, /** * Called after loading the list view's description, sets up such things * as the view table's columns, renders the table itself and hooks up the * various table-level and row-level DOM events (action buttons, deletion * buttons, selection of records, [New] button, selection of a given * record, ...) * * Sets up the following: * * * Processes arch and fields to generate a complete field descriptor for each field * * Create the table itself and allocate visible columns * * Hook in the top-level (header) [New|Add] and [Delete] button * * Sets up showing/hiding the top-level [Delete] button based on records being selected or not * * Sets up event handlers for action buttons and per-row deletion button * * Hooks global callback for clicking on a row * * Sets up its sidebar, if any * * @param {Object} data wrapped fields_view_get result * @param {Object} data.fields_view fields_view_get result (processed) * @param {Object} data.fields_view.fields mapping of fields for the current model * @param {Object} data.fields_view.arch current list view descriptor * @param {Boolean} grouped Is the list view grouped */ on_loaded: function(data, grouped) { var self = this; this.fields_view = data.fields_view; //this.log(this.fields_view); this.name = "" + this.fields_view.arch.attrs.string; this.setup_columns(this.fields_view.fields, grouped); this.$element.html(QWeb.render("ListView", this)); // Head hook this.$element.find('.oe-list-add') .click(this.do_add_record) .attr('disabled', grouped && this.options.editable); this.$element.find('.oe-list-delete') .attr('disabled', true) .click(this.do_delete_selected); this.$element.find('thead').delegate('th.oe-sortable[data-id]', 'click', function (e) { e.stopPropagation(); var $this = $(this); self.dataset.sort($this.data('id')); if ($this.find('span').length) { $this.find('span').toggleClass( 'ui-icon-triangle-1-s ui-icon-triangle-1-n'); } else { $this.append('') .siblings('.oe-sortable').find('span').remove(); } self.reload_content(); }); this.$element.find('.oe-list-pager') .delegate('button', 'click', function () { var $this = $(this); switch ($this.data('pager-action')) { case 'first': self.page = 0; break; case 'last': self.page = Math.floor( self.dataset.ids.length / self.limit()); break; case 'next': self.page += 1; break; case 'previous': self.page -= 1; break; } self.reload_content(); }).find('.oe-pager-state') .click(function (e) { e.stopPropagation(); var $this = $(this); var $select = $('