forked from extern/egroupware
362 lines
8.0 KiB
JavaScript
362 lines
8.0 KiB
JavaScript
/**
|
|
* eGroupWare eTemplate2 - JS Nextmatch object
|
|
*
|
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
|
* @package etemplate
|
|
* @subpackage api
|
|
* @link http://www.egroupware.org
|
|
* @author Andreas Stöckel
|
|
* @copyright Stylite 2011
|
|
* @version $Id$
|
|
*/
|
|
|
|
"use strict";
|
|
|
|
/*egw:uses
|
|
jquery.jquery;
|
|
et2_widget;
|
|
et2_core_interfaces;
|
|
et2_core_DOMWidget;
|
|
et2_widget_template;
|
|
et2_widget_grid;
|
|
et2_widget_selectbox;
|
|
et2_extension_nextmatch_dynheight;
|
|
*/
|
|
|
|
/**
|
|
* Interface all special nextmatch header elements have to implement.
|
|
*/
|
|
var et2_INextmatchHeader = new Interface({
|
|
|
|
/**
|
|
* The 'setNextmatch' function is called by the parent nextmatch widget
|
|
* and tells the nextmatch header widgets which widget they should direct
|
|
* their 'sort', 'search' or 'filter' calls to.
|
|
*/
|
|
setNextmatch: function(_nextmatch) {}
|
|
});
|
|
|
|
var et2_INextmatchSortable = new Interface({
|
|
|
|
setSortmode: function(_mode) {}
|
|
|
|
});
|
|
|
|
/**
|
|
* Class which implements the "nextmatch" XET-Tag
|
|
*/
|
|
var et2_nextmatch = et2_DOMWidget.extend(et2_IResizeable, {
|
|
|
|
attributes: {
|
|
"template": {
|
|
"name": "Template",
|
|
"type": "string",
|
|
"description": "The id of the template which contains the grid layout."
|
|
}
|
|
},
|
|
|
|
legacyOptions: ["template"],
|
|
|
|
init: function() {
|
|
this._super.apply(this, arguments);
|
|
|
|
this.div = $j(document.createElement("div"))
|
|
.addClass("et2_nextmatch");
|
|
|
|
// Create the dynheight component which dynamically scales the inner
|
|
// container.
|
|
this.dynheight = new et2_dynheight(null, this.div, 150);
|
|
|
|
// Create the outer grid container
|
|
this.dataviewContainer = new et2_dataview_gridContainer(this.div);
|
|
|
|
this.columns = [];
|
|
this.activeFilters = {};
|
|
},
|
|
|
|
destroy: function() {
|
|
this.dataviewContainer.free();
|
|
this.dynheight.free();
|
|
|
|
this._super.apply(this, arguments);
|
|
},
|
|
|
|
resize: function() {
|
|
this.dynheight.update();
|
|
},
|
|
|
|
/**
|
|
* Sorts the nextmatch widget by the given ID.
|
|
*
|
|
* @param _id is the id of the data entry which should be sorted.
|
|
* @param _asc if true, the elements are sorted ascending, otherwise
|
|
* descending. If not set, the sort direction will be determined
|
|
* automatically.
|
|
*/
|
|
sortBy: function(_id, _asc) {
|
|
// Create the "sort" entry in the active filters if it did not exist
|
|
// yet.
|
|
if (typeof this.activeFilters["sort"] == "undefined")
|
|
{
|
|
this.activeFilters["sort"] = {
|
|
"id": null,
|
|
"asc": true
|
|
};
|
|
}
|
|
|
|
// Determine the sort direction automatically if it is not set
|
|
if (typeof _asc == "undefined")
|
|
{
|
|
if (this.activeFilters["sort"].id == _id)
|
|
{
|
|
_asc = !this.activeFilters["sort"].asc;
|
|
}
|
|
}
|
|
|
|
// Update the entry in the activeFilters object
|
|
this.activeFilters["sort"] = {
|
|
"id": _id,
|
|
"asc": _asc
|
|
}
|
|
|
|
// Set the sortmode display
|
|
this.iterateOver(function(_widget) {
|
|
_widget.setSortmode((_widget.id == _id) ? (_asc ? "asc": "desc") : "none");
|
|
}, this, et2_INextmatchSortable);
|
|
|
|
et2_debug("info", "Sorting nextmatch by '" + _id + "' in direction '" +
|
|
(_asc ? "asc" : "desc") + "'");
|
|
},
|
|
|
|
resetSort: function() {
|
|
// Check whether the nextmatch widget is currently sorted
|
|
if (typeof this.activeFilters["sort"] != "undefined")
|
|
{
|
|
// Reset the sortmode
|
|
this.iterateOver(function(_widget) {
|
|
_widget.setSortmode("none");
|
|
}, this, et2_INextmatchSortable);
|
|
|
|
// If yes, delete the "sort" filter
|
|
delete(this.activeFilters["sort"]);
|
|
this.applyFilters();
|
|
}
|
|
},
|
|
|
|
applyFilters: function() {
|
|
et2_debug("info", "Changing nextmatch filters to ", this.activeFilters);
|
|
},
|
|
|
|
/**
|
|
* Generates the column name for the given column widget
|
|
*/
|
|
_genColumnName: function(_widget) {
|
|
var result = null;
|
|
|
|
_widget.iterateOver(function(_widget) {
|
|
if (!result)
|
|
{
|
|
result = _widget.options.label;
|
|
}
|
|
else
|
|
{
|
|
result += ", " + _widget.options.label;
|
|
}
|
|
}, this, et2_INextmatchHeader);
|
|
|
|
return result;
|
|
},
|
|
|
|
_parseHeaderRow: function(_row) {
|
|
// Go over the header row and create the column entries
|
|
this.columns = new Array(_row.length);
|
|
for (var x = 0; x < _row.length; x++)
|
|
{
|
|
this.columns[x] = {
|
|
"widget": _row[x].widget,
|
|
"name": this._genColumnName(_row[x].widget),
|
|
"disabled": false,
|
|
"canDisable": true,
|
|
"width": "auto"
|
|
}
|
|
|
|
// Append the widget to this container
|
|
this.addChild(_row[x].widget);
|
|
}
|
|
|
|
this.dataviewContainer.setColumns(this.columns);
|
|
},
|
|
|
|
_parseGrid: function(_grid) {
|
|
// Search the rows for a header-row - if one is found, parse it
|
|
for (var y = 0; y < _grid.rowData.length; y++)
|
|
{
|
|
if (_grid.rowData[y]["class"] == "th")
|
|
{
|
|
this._parseHeaderRow(_grid.cells[y]);
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* When the template attribute is set, the nextmatch widget tries to load
|
|
* that template and to fetch the grid which is inside of it. It then calls
|
|
* _parseGrid in order to get the information for the column headers etc.
|
|
*/
|
|
set_template: function(_value) {
|
|
if (!this.template)
|
|
{
|
|
// Load the template
|
|
var template = et2_createWidget("template", {"id": _value}, this);
|
|
|
|
if (!template.proxiedTemplate)
|
|
{
|
|
et2_debug("error", "Error while loading definition template for" +
|
|
"nextmatch widget.");
|
|
return;
|
|
}
|
|
|
|
// Fetch the grid element and parse it
|
|
var definitionGrid = template.proxiedTemplate.getChildren()[0];
|
|
if (definitionGrid && definitionGrid instanceof et2_grid)
|
|
{
|
|
this._parseGrid(definitionGrid);
|
|
}
|
|
else
|
|
{
|
|
et2_debug("error", "Nextmatch widget expects a grid to be the " +
|
|
"first child of the defined template.");
|
|
return;
|
|
}
|
|
|
|
// Free the template again
|
|
template.free();
|
|
|
|
// Call the "setNextmatch" function of all registered
|
|
// INextmatchHeader widgets.
|
|
this.iterateOver(function (_node) {
|
|
_node.setNextmatch(this);
|
|
}, this, et2_INextmatchHeader);
|
|
}
|
|
},
|
|
|
|
getDOMNode: function(_sender) {
|
|
if (_sender == this)
|
|
{
|
|
return this.div[0];
|
|
}
|
|
|
|
for (var i = 0; i < this.columns.length; i++)
|
|
{
|
|
if (_sender == this.columns[i].widget)
|
|
{
|
|
return this.dataviewContainer.getHeaderContainerNode(i);
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
});
|
|
|
|
et2_register_widget(et2_nextmatch, ["nextmatch"]);
|
|
|
|
|
|
/**
|
|
* Classes for the nextmatch sortheaders etc.
|
|
*/
|
|
var et2_nextmatch_header = et2_baseWidget.extend(et2_INextmatchHeader, {
|
|
|
|
attributes: {
|
|
"label": {
|
|
"name": "Caption",
|
|
"type": "string",
|
|
"description": "Caption for the nextmatch header",
|
|
"translate": true
|
|
}
|
|
},
|
|
|
|
init: function() {
|
|
this._super.apply(this, arguments);
|
|
|
|
this.labelNode = $j(document.createElement("span"));
|
|
this.nextmatch = null;
|
|
|
|
this.setDOMNode(this.labelNode[0]);
|
|
},
|
|
|
|
destroy: function() {
|
|
this._super.apply(this, arguments);
|
|
},
|
|
|
|
/**
|
|
* Set nextmatch is the function which has to be implemented for the
|
|
* et2_INextmatchHeader interface.
|
|
*/
|
|
setNextmatch: function(_nextmatch) {
|
|
this.nextmatch = _nextmatch;
|
|
},
|
|
|
|
set_label: function(_value) {
|
|
this.label = _value;
|
|
|
|
this.labelNode.text(_value);
|
|
}
|
|
|
|
});
|
|
|
|
et2_register_widget(et2_nextmatch_header, ['nextmatch-header',
|
|
'nextmatch-customfilter', 'nextmatch-customfields']);
|
|
|
|
var et2_nextmatch_sortheader = et2_nextmatch_header.extend(et2_INextmatchSortable, {
|
|
|
|
init: function() {
|
|
this._super.apply(this, arguments);
|
|
|
|
this.sortmode = "none";
|
|
|
|
this.labelNode.addClass("nextmatch_sortheader none");
|
|
},
|
|
|
|
click: function() {
|
|
if (this.nextmatch && this._super.apply(this, arguments))
|
|
{
|
|
this.nextmatch.sortBy(this.id);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
},
|
|
|
|
/**
|
|
* Function which implements the et2_INextmatchSortable function.
|
|
*/
|
|
setSortmode: function(_mode) {
|
|
// Remove the last sortmode class and add the new one
|
|
this.labelNode.removeClass(this.sortmode)
|
|
.addClass(_mode);
|
|
|
|
this.sortmode = _mode;
|
|
}
|
|
|
|
});
|
|
|
|
et2_register_widget(et2_nextmatch_sortheader, ['nextmatch-sortheader']);
|
|
|
|
|
|
var et2_nextmatch_filterheader = et2_selectbox.extend(et2_INextmatchHeader, {
|
|
|
|
/**
|
|
* Set nextmatch is the function which has to be implemented for the
|
|
* et2_INextmatchHeader interface.
|
|
*/
|
|
setNextmatch: function(_nextmatch) {
|
|
this.nextmatch = _nextmatch;
|
|
}
|
|
|
|
});
|
|
|
|
et2_register_widget(et2_nextmatch_filterheader, ['nextmatch-filterheader',
|
|
'nextmatch-accountfilter']);
|
|
|