Files
PetitTeton/public/admin/js/linkedTable.js

167 lines
6.7 KiB
JavaScript

"use strict";
var LinkedTable;
+function($) {
LinkedTable = function(element, options) {
var _this = this;
this.$element = $(element);
this.options = $.extend({}, LinkedTable.DEFAULTS, options);
this.$selectedRow = null;
this.selectionHandler = function(event) {
$(this).addClass(_this.options.selectionCSS).siblings().removeClass(_this.options.selectionCSS);
_this.$selectedRow = $(this);
};
};
LinkedTable.DEFAULTS = {
url: '', //The absolute or relative path to use to query the data. Server is expected to respond with a JSON array of objects.
attr: 'data-key-name',
selectionCSS: 'selected',
selection: 'row', //Currently only row is supported.
supportingData: [], //An array of objects, one for each collection of supporting data. Each object must have a 'name', 'url', and optional 'parameters'. The url and parameters are used the same as for the primary query. The name is used to store the results for use in rendering the data. Optional 'postProcess' attribute can be a function that takes the data and returns a modified set of data.
cellDataHandlers: {}, //An object containing a function for each attribute, where the attribute is the table header object key, and the function is called to convert the primary data object into a cell value. The function will be passed the jquery table data wrapper object for the cell, the primary data object for the row, and the object containing the supporting data returned from running the supporting data queries.
postAddRowHandler: null, //Optional function that is passed the jquery table row and the data object sent by the server for that row. Allows post processing of the row prior to display.
parameters: null //Optional function that returns an object, or an object whose attributes are passed to the URL as parameters.
};
LinkedTable.prototype.getSelectedRow = function() {
return this.$selectedRow;
};
//A function that will clean and rebuild the table displaying all the users.
//Note that each row of the table will have a data element attached to the table row. The key will be "model" and the value will be the object sent by the server.
LinkedTable.prototype.refresh = function() {
var _this = this;
var table = this.$element;
var thead = table.find("thead tr");
var tbody = table.find("tbody");
var selection = this.options.selection;
var attr = this.options.attr;
var selectionHandler = this.selectionHandler;
var params;
var deferreds = [];
var supportingData = {};
if(thead.length == 0) {
return;
}
//Empty or Create the table body.
if(tbody.length != 0) {
//Remove the row selection handler.
if(selection == 'row') this.$element.off('click', 'tbody tr', selectionHandler);
//Empty the table of data.
tbody.empty();
}
else {
tbody = $("<tbody></tbody>");
tbody.appendTo(table);
}
//Build the parameters for the query for the primary set of data.
if(typeof this.options.parameters == 'function') {
params = this.options.parameters();
//Must be an object.
if(typeof params != 'object') {
params = {};
}
}
else if(typeof this.options.parameters == 'object') {
params = this.options.parameters;
}
else {params = {};}
//Load the primary set of data.
deferreds.push($.getJSON(this.options.url, params));
//Load all supporting data.
for(var supportingDataIndex = 0; supportingDataIndex < this.options.supportingData.length; supportingDataIndex++) {
var nextSupportingData = this.options.supportingData[supportingDataIndex];
//Build the parameters for each supporting set of data.
if(typeof nextSupportingData.parameters == 'function') {
params = nextSupportingData.parameters();
//Must be an object.
if(typeof params != 'object') {
params = {};
}
}
else if(typeof nextSupportingData.parameters == 'object') {
params = nextSupportingData.parameters;
}
else {params = {};}
//Load the supporting data.
deferreds.push($.getJSON(nextSupportingData.url, params));
}
//Use apply to convert an array of parameters to individual parameters for the $.when(..) function. The success function will receive the results in order passed to when().
$.when.apply($, deferreds).then(function() {
var data = arguments[0][0]; //Note: The result of the first query returns an array of three values: the data (array in this case), the message, and XHR object. We only care about the data.
var headers = thead.children();
var attributes = [];
//Save each supporting set of data by name into the supportingData object.
for(var argumentIndex = 1; argumentIndex < arguments.length; argumentIndex++) {
var supportingResult = arguments[argumentIndex][0]; //We only care about the data. The other two array elements are the status and the XHR object.
if(_this.options.supportingData[argumentIndex - 1].postProcess) {
supportingResult = _this.options.supportingData[argumentIndex - 1].postProcess(supportingResult);
}
supportingData[_this.options.supportingData[argumentIndex - 1].name] = supportingResult;
}
//Read the table headers to get the data object keys.
for(var headerIndex = 0; headerIndex < headers.length; headerIndex++) {
var nextHeader = headers[headerIndex];
attributes[headerIndex] = $(nextHeader).attr(attr);
//Replace the attribute name with the handler function if there is one in the mapping.
if(_this.options.cellDataHandlers[attributes[headerIndex]]) {
attributes[headerIndex] = _this.options.cellDataHandlers[attributes[headerIndex]];
}
}
//Add the table data.
for(var dataIndex = 0; dataIndex < data.length; dataIndex++) {
var rowData = data[dataIndex];
var row = $("<tr></tr>");
row.appendTo(tbody);
//Save the model attached to the table row. Can be retrieved later to get the model sent by the server.
row.data("model", rowData);
for(var attributeIndex = 0; attributeIndex < attributes.length; attributeIndex++) {
var attribute = attributes[attributeIndex];
if($.isFunction(attribute)) {
var cell = $("<td></td>");
cell.appendTo(row);
attribute(cell, rowData, supportingData);
}
else {
var cellData = rowData[attribute];
row.append("<td>" + cellData + "</td>");
}
}
if(_this.options.postAddRowHandler) {
//Call the optional handler after adding the row, passing the jquery row object, and the row data object sent by the server. Allows post processing on the row (adding classes to the row for example).
_this.options.postAddRowHandler(row, rowData);
}
}
//Setup the row selection handler.
if(selection == 'row') table.on('click', 'tbody tr', selectionHandler);
}).fail(function(err) {
console.error("Unexpected error loading the table data?!?");
});
}
}(jQuery);