/* global Lang,app */
'use strict';
define('list', ['jquery', 'ko'], function($, ko) {
/**
* This class describe the client behavior of the item lists.
* Lists are available in window by `app.lists[id]`
*
* @param {Object} data The list initial parameters. this object must contain :
* - id : The list id
* - action : The URL to load to refresh the list
* - target (optionnal) : Where the list must be refreshed (default, it will be replace itself)
* - userParam : The filters, orders and navigation parameters previously set by the user
* @class List
*/
function List(data) {
this.id = data.id;
this.action = data.action;
this.target = data.target;
this.maxPages = ko.observable();
this.recordNumber = ko.observable(0);
this.node = $('#' + this.id);
this.wrapper = this.node.parent();
this.navigationSection = this.wrapper.find('.list-navigation');
this.titleLine = this.node.find('.list-title-line');
this.refreshContainer = this.node.find('.list > tbody');
// Get the list display parameters (number of lines, page number, searches and sorts)
var params = data.userParam || {};
this.searches = params.searches || {};
this.sorts = params.sorts || {};
this.page = ko.observable(params.page || List.DEFAULT_PAGE_NUMBER);
this.lines = ko.observable(params.lines || List.DEFAULT_LINES_NUMBER);
this.fields = {};
for (var j = 0; j < data.fields.length; j++) {
var field = data.fields[j];
this.fields[field] = {
name : field,
search : ko.observable(this.searches[field]),
sort : ko.observable(this.sorts[field])
};
}
// The label displaying the number of the list results
this.recordNumberLabel = ko.computed(function() {
return Lang.get('main.list-results-number', {number : this.recordNumber()}, this.recordNumber());
}.bind(this));
this.initControls();
}
/**
* The default delay before refreshing on search
*
* @var {int}
*/
List.DEFAULT_SEARCH_DELAY = 400;
/**
* The default lines number to display
*
* @var {int}
*/
List.DEFAULT_LINES_NUMBER = 20;
/**
* The default page number to display
*
* @var {int}
*/
List.DEFAULT_PAGE_NUMBER = 1;
/**
* Refresh the list
*
* @param {Object} options - Additionnal options to set to the request
* @returns {boolean} False
* @memberOf List
*/
List.prototype.refresh = function(options) {
// Set the user filters
var data = {
lines : this.lines(),
page : this.page(),
searches : this.searches,
sorts : this.sorts
};
var headers = options && options.headers || {};
headers['X-List-Filter-' + this.id] = JSON.stringify(data);
// Send the list is refreshing to the server
var get = {
refresh : 1
};
if (this.selected) {
get.selected = this.selected;
}
// Load the new data from the server
$.ajax({
url: this.action,
method : 'GET',
headers : headers,
data : get,
cache : false
})
.done(function(response) {
this.refreshContainer.html(response);
}.bind(this))
.fail(function() {
app.notify('error', Lang.get('main.refresh-list-error'));
});
return false;
};
/**
* Listen for list parameters changements to refresh the list
*
* @memberOf List
*/
List.prototype.initControls = function() {
if (this.navigationSection.length) {
ko.applyBindings(this, this.navigationSection[0]);
}
if (this.titleLine.length) {
ko.applyBindings(this, this.titleLine[0]);
}
var self = this;
/**
* Select all the lines
*/
this.node.find('.list-checkbox-all').change(function() {
self.node.find('.list-checkbox').prop('checked', $(this).is(':checked')).trigger('change');
});
/**
* Select a line
*/
this.node.find('.list-checkbox').change(function() {
self.node.find('.list-checkbox-all').prop({
checked : self.node.find('.list-checkbox:not(:checked)').length === 0
});
});
/**
* Change the number of lines per page
*/
this.lines.subscribe(function() {
this.refresh();
}.bind(this));
/**
* Go to the page xx
*
* @param {int} value The page number to go on
*/
this.page.subscribe(function(value) {
if (isNaN(value)) {
this.page(1);
return;
}
if (value < 1) {
this.page(1);
return;
}
if (value > this.maxPages()) {
this.page(this.maxPages());
return;
}
this.refresh();
}.bind(this));
/**
* Detect, when the max page number changed, to keep the page number lower than it
*
* @param {int} value The max page number
*/
this.maxPages.subscribe(function(value) {
if (this.page() > value) {
this.page(value);
}
}.bind(this));
$.each(this.fields, function(name, field) {
/**
* Sort the list
*
* @param {string} value The sort value : 'ASC' or 'DESC'
*/
field.sort.subscribe(function(value) {
if (!value) {
delete this.sorts[name];
}
else {
this.sorts[name] = value;
}
this.refresh();
}.bind(this));
/**
* Type a search
*
* @param {string} value The search value
*/
field.search.subscribe(function(value) {
if (value) {
this.searches[name] = value;
}
else {
delete this.searches[name];
}
// Wait for 400 ms to refresh the list, in case the user enter new characters in this interval
clearTimeout(this.searchTimeout);
this.searchTimeout = setTimeout(
function() {
this.refresh();
}.bind(this),
List.DEFAULT_SEARCH_DELAY
);
}.bind(this));
}.bind(this));
};
return List;
});