mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-28 19:03:14 +01:00
Work on getting nextmatch going
This commit is contained in:
parent
3b2f3e50de
commit
22780e5629
@ -1,3 +1,4 @@
|
|||||||
|
"use strict";
|
||||||
/**
|
/**
|
||||||
* EGroupware eTemplate2 - dataview code
|
* EGroupware eTemplate2 - dataview code
|
||||||
*
|
*
|
||||||
@ -9,7 +10,7 @@
|
|||||||
* @copyright Stylite 2011-2012
|
* @copyright Stylite 2011-2012
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
/*egw:uses
|
/*egw:uses
|
||||||
/vendor/bower-asset/jquery/dist/jquery.js;
|
/vendor/bower-asset/jquery/dist/jquery.js;
|
||||||
et2_core_common;
|
et2_core_common;
|
||||||
@ -19,7 +20,6 @@
|
|||||||
et2_dataview_view_grid;
|
et2_dataview_view_grid;
|
||||||
et2_dataview_view_resizeable;
|
et2_dataview_view_resizeable;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The et2_dataview class is the main class for displaying a dataview. The
|
* The et2_dataview class is the main class for displaying a dataview. The
|
||||||
* dataview class manages the creation of the outer html nodes (like the table,
|
* dataview class manages the creation of the outer html nodes (like the table,
|
||||||
@ -29,28 +29,7 @@
|
|||||||
*
|
*
|
||||||
* @augments Class
|
* @augments Class
|
||||||
*/
|
*/
|
||||||
var et2_dataview = (function(){ "use strict"; return Class.extend({
|
var et2_dataview = /** @class */ (function () {
|
||||||
|
|
||||||
/**
|
|
||||||
* Constant which regulates the column padding.
|
|
||||||
*/
|
|
||||||
columnPadding: 2,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Some browser dependant variables which will be calculated on creation of
|
|
||||||
* the first gridContainer object.
|
|
||||||
*/
|
|
||||||
scrollbarWidth: false,
|
|
||||||
headerBorderWidth: false,
|
|
||||||
columnBorderWidth: false,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hooks to allow parent to keep up to date if things change
|
|
||||||
*/
|
|
||||||
onUpdateColumns: false,
|
|
||||||
selectColumnsClick: false,
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for the grid container
|
* Constructor for the grid container
|
||||||
*
|
*
|
||||||
@ -58,171 +37,130 @@ var et2_dataview = (function(){ "use strict"; return Class.extend({
|
|||||||
* @param {egw} _egw
|
* @param {egw} _egw
|
||||||
* @memberOf et2_dataview
|
* @memberOf et2_dataview
|
||||||
*/
|
*/
|
||||||
init: function(_parentNode, _egw) {
|
function et2_dataview(_parentNode, _egw) {
|
||||||
|
|
||||||
// Copy the arguments
|
// Copy the arguments
|
||||||
this.parentNode = jQuery(_parentNode);
|
this.parentNode = jQuery(_parentNode);
|
||||||
this.egw = _egw;
|
this.egw = _egw;
|
||||||
|
|
||||||
// Initialize some variables
|
// Initialize some variables
|
||||||
this.columnNodes = []; // Array with the header containers
|
this.columnNodes = []; // Array with the header containers
|
||||||
this.columns = [];
|
this.columns = [];
|
||||||
this.columnMgr = null;
|
this.columnMgr = null;
|
||||||
this.rowProvider = null;
|
this.rowProvider = null;
|
||||||
|
|
||||||
this.grid = null;
|
|
||||||
|
|
||||||
this.width = 0;
|
this.width = 0;
|
||||||
this.height = 0;
|
this.height = 0;
|
||||||
|
|
||||||
this.uniqueId = "gridCont_" + this.egw.uid();
|
this.uniqueId = "gridCont_" + this.egw.uid();
|
||||||
|
|
||||||
// Build the base nodes
|
// Build the base nodes
|
||||||
this._createElements();
|
this._createElements();
|
||||||
|
|
||||||
// Read the browser dependant variables
|
// Read the browser dependant variables
|
||||||
this._getDepVars();
|
this._getDepVars();
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroys the object, removes all dom nodes and clears all references.
|
* Destroys the object, removes all dom nodes and clears all references.
|
||||||
*/
|
*/
|
||||||
destroy: function() {
|
et2_dataview.prototype.destroy = function () {
|
||||||
// Clear the columns
|
// Clear the columns
|
||||||
this._clearHeader();
|
this._clearHeader();
|
||||||
|
|
||||||
// Free the grid
|
// Free the grid
|
||||||
if (this.grid)
|
if (this.grid) {
|
||||||
{
|
|
||||||
this.grid.free();
|
this.grid.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free the row provider
|
// Free the row provider
|
||||||
if (this.rowProvider)
|
if (this.rowProvider) {
|
||||||
{
|
|
||||||
this.rowProvider.free();
|
this.rowProvider.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Detatch the outer element
|
// Detatch the outer element
|
||||||
this.table.remove();
|
this.table.remove();
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears all data rows and reloads them
|
* Clears all data rows and reloads them
|
||||||
*/
|
*/
|
||||||
clear: function() {
|
et2_dataview.prototype.clear = function () {
|
||||||
if (this.grid)
|
if (this.grid) {
|
||||||
{
|
|
||||||
this.grid.clear();
|
this.grid.clear();
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the column container node for the given column index
|
* Returns the column container node for the given column index
|
||||||
*
|
*
|
||||||
* @param _columnIdx the integer column index
|
* @param _columnIdx the integer column index
|
||||||
*/
|
*/
|
||||||
getHeaderContainerNode: function(_columnIdx) {
|
et2_dataview.prototype.getHeaderContainerNode = function (_columnIdx) {
|
||||||
if (typeof this.columnNodes[_columnIdx] != "undefined")
|
if (typeof this.columnNodes[_columnIdx] != "undefined") {
|
||||||
{
|
|
||||||
return this.columnNodes[_columnIdx].container[0];
|
return this.columnNodes[_columnIdx].container[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the column descriptors and creates the column header according to it.
|
* Sets the column descriptors and creates the column header according to it.
|
||||||
* The inner grid will be emptied if it has already been built.
|
* The inner grid will be emptied if it has already been built.
|
||||||
*/
|
*/
|
||||||
setColumns: function(_columnData) {
|
et2_dataview.prototype.setColumns = function (_columnData) {
|
||||||
// Free all column objects which have been created till this moment
|
// Free all column objects which have been created till this moment
|
||||||
this._clearHeader();
|
this._clearHeader();
|
||||||
|
|
||||||
// Copy the given column data
|
// Copy the given column data
|
||||||
this.columnMgr = new et2_dataview_columns(_columnData);
|
this.columnMgr = new et2_dataview_columns(_columnData);
|
||||||
|
|
||||||
// Create the stylesheets
|
// Create the stylesheets
|
||||||
this.updateColumns();
|
this.updateColumns();
|
||||||
|
|
||||||
// Build the header row
|
// Build the header row
|
||||||
this._buildHeader();
|
this._buildHeader();
|
||||||
|
|
||||||
// Build the grid
|
// Build the grid
|
||||||
this._buildGrid();
|
this._buildGrid();
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resizes the grid
|
* Resizes the grid
|
||||||
*/
|
*/
|
||||||
resize: function(_w, _h) {
|
et2_dataview.prototype.resize = function (_w, _h) {
|
||||||
// Not fully initialized yet...
|
// Not fully initialized yet...
|
||||||
if (!this.columnMgr) return;
|
if (!this.columnMgr)
|
||||||
|
return;
|
||||||
if (this.width != _w)
|
if (this.width != _w) {
|
||||||
{
|
|
||||||
this.width = _w;
|
this.width = _w;
|
||||||
|
|
||||||
// Take grid border width into account
|
// Take grid border width into account
|
||||||
_w -= (this.table.outerWidth(true) - this.table.innerWidth());
|
_w -= (this.table.outerWidth(true) - this.table.innerWidth());
|
||||||
|
|
||||||
// Take grid header border's width into account. eg. category colors may add extra pixel into width
|
// Take grid header border's width into account. eg. category colors may add extra pixel into width
|
||||||
_w = _w - (this.thead.find('tr').outerWidth() - this.thead.find('tr').innerWidth());
|
_w = _w - (this.thead.find('tr').outerWidth() - this.thead.find('tr').innerWidth());
|
||||||
|
|
||||||
// Rebuild the column stylesheets
|
// Rebuild the column stylesheets
|
||||||
this.columnMgr.setTotalWidth(_w - this.scrollbarWidth);
|
this.columnMgr.setTotalWidth(_w - this.scrollbarWidth);
|
||||||
this._updateColumns();
|
this._updateColumns();
|
||||||
}
|
}
|
||||||
|
if (this.height != _h) {
|
||||||
if (this.height != _h)
|
|
||||||
{
|
|
||||||
this.height = _h;
|
this.height = _h;
|
||||||
|
|
||||||
// Set the height of the grid.
|
// Set the height of the grid.
|
||||||
if (this.grid)
|
if (this.grid) {
|
||||||
{
|
|
||||||
this.grid.setScrollHeight(this.height -
|
this.grid.setScrollHeight(this.height -
|
||||||
this.headTr.outerHeight(true));
|
this.headTr.outerHeight(true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the column manager object. You can use it to set the visibility
|
* Returns the column manager object. You can use it to set the visibility
|
||||||
* of columns etc. Call "updateHeader" if you did any changes.
|
* of columns etc. Call "updateHeader" if you did any changes.
|
||||||
*/
|
*/
|
||||||
getColumnMgr: function() {
|
et2_dataview.prototype.getColumnMgr = function () {
|
||||||
return this.columnMgr;
|
return this.columnMgr;
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recalculates the stylesheets which determine the column visibility and
|
* Recalculates the stylesheets which determine the column visibility and
|
||||||
* width.
|
* width.
|
||||||
*
|
*
|
||||||
* @param setDefault boolean Allow admins to save current settings as default for all users
|
* @param setDefault boolean Allow admins to save current settings as default for all users
|
||||||
*/
|
*/
|
||||||
updateColumns: function(setDefault) {
|
et2_dataview.prototype.updateColumns = function (setDefault) {
|
||||||
if (this.columnMgr)
|
if (setDefault === void 0) { setDefault = false; }
|
||||||
{
|
if (this.columnMgr) {
|
||||||
this._updateColumns();
|
this._updateColumns();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ability to notify parent / someone else
|
// Ability to notify parent / someone else
|
||||||
if (this.onUpdateColumns)
|
if (this.onUpdateColumns) {
|
||||||
{
|
|
||||||
this.onUpdateColumns(setDefault);
|
this.onUpdateColumns(setDefault);
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
|
|
||||||
|
|
||||||
/* --- PRIVATE FUNCTIONS --- */
|
/* --- PRIVATE FUNCTIONS --- */
|
||||||
|
|
||||||
/* --- Code for building the grid container DOM-Tree elements ---- */
|
/* --- Code for building the grid container DOM-Tree elements ---- */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds the base DOM-Tree elements
|
* Builds the base DOM-Tree elements
|
||||||
*/
|
*/
|
||||||
_createElements: function() {
|
et2_dataview.prototype._createElements = function () {
|
||||||
/*
|
/*
|
||||||
Structure:
|
Structure:
|
||||||
<table class="egwGridView_outer">
|
<table class="egwGridView_outer">
|
||||||
@ -234,43 +172,32 @@ var et2_dataview = (function(){ "use strict"; return Class.extend({
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
this.containerTr = jQuery(document.createElement("tr"));
|
this.containerTr = jQuery(document.createElement("tr"));
|
||||||
this.headTr = jQuery(document.createElement("tr"));
|
this.headTr = jQuery(document.createElement("tr"));
|
||||||
|
|
||||||
this.thead = jQuery(document.createElement("thead"))
|
this.thead = jQuery(document.createElement("thead"))
|
||||||
.append(this.headTr);
|
.append(this.headTr);
|
||||||
this.tbody = jQuery(document.createElement("tbody"))
|
this.tbody = jQuery(document.createElement("tbody"))
|
||||||
.append(this.containerTr);
|
.append(this.containerTr);
|
||||||
|
|
||||||
this.table = jQuery(document.createElement("table"))
|
this.table = jQuery(document.createElement("table"))
|
||||||
.addClass("egwGridView_outer")
|
.addClass("egwGridView_outer")
|
||||||
.append(this.thead, this.tbody)
|
.append(this.thead, this.tbody)
|
||||||
.appendTo(this.parentNode);
|
.appendTo(this.parentNode);
|
||||||
},
|
};
|
||||||
|
|
||||||
|
|
||||||
/* --- Code for building the header row --- */
|
/* --- Code for building the header row --- */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears the header row
|
* Clears the header row
|
||||||
*/
|
*/
|
||||||
_clearHeader: function() {
|
et2_dataview.prototype._clearHeader = function () {
|
||||||
if (this.columnMgr)
|
if (this.columnMgr) {
|
||||||
{
|
|
||||||
this.columnMgr.free();
|
this.columnMgr.free();
|
||||||
this.columnMgr = null;
|
this.columnMgr = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove dynamic CSS,
|
// Remove dynamic CSS,
|
||||||
for (var i = 0; i < this.columns.length; i++)
|
for (var i = 0; i < this.columns.length; i++) {
|
||||||
{
|
if (this.columns[i].tdClass) {
|
||||||
if(this.columns[i].tdClass)
|
|
||||||
{
|
|
||||||
this.egw.css('.' + this.columns[i].tdClass);
|
this.egw.css('.' + this.columns[i].tdClass);
|
||||||
}
|
}
|
||||||
if(this.columns[i].divClass)
|
if (this.columns[i].divClass) {
|
||||||
{
|
|
||||||
this.egw.css('.' + this.columns[i].divClass);
|
this.egw.css('.' + this.columns[i].divClass);
|
||||||
this.egw.css(".egwGridView_outer ." + this.columns[i].divClass);
|
this.egw.css(".egwGridView_outer ." + this.columns[i].divClass);
|
||||||
this.egw.css(".egwGridView_grid ." + this.columns[i].divClass);
|
this.egw.css(".egwGridView_grid ." + this.columns[i].divClass);
|
||||||
@ -279,52 +206,39 @@ var et2_dataview = (function(){ "use strict"; return Class.extend({
|
|||||||
this.egw.css(".egwGridView_grid ." + this.uniqueId + "_div_fullRow");
|
this.egw.css(".egwGridView_grid ." + this.uniqueId + "_div_fullRow");
|
||||||
this.egw.css(".egwGridView_outer ." + this.uniqueId + "_td_fullRow");
|
this.egw.css(".egwGridView_outer ." + this.uniqueId + "_td_fullRow");
|
||||||
this.egw.css(".egwGridView_outer ." + this.uniqueId + "_spacer_fullRow");
|
this.egw.css(".egwGridView_outer ." + this.uniqueId + "_spacer_fullRow");
|
||||||
|
|
||||||
// Reset the headerColumns array and empty the table row
|
// Reset the headerColumns array and empty the table row
|
||||||
this.columnNodes = [];
|
this.columnNodes = [];
|
||||||
this.columns = [];
|
this.columns = [];
|
||||||
this.headTr.empty();
|
this.headTr.empty();
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the column data which is retrieved by calling egwGridColumns.getColumnData.
|
* Sets the column data which is retrieved by calling egwGridColumns.getColumnData.
|
||||||
* The columns will be updated.
|
* The columns will be updated.
|
||||||
*/
|
*/
|
||||||
_updateColumns: function() {
|
et2_dataview.prototype._updateColumns = function () {
|
||||||
// Copy the columns data
|
// Copy the columns data
|
||||||
this.columns = this.columnMgr.getColumnData();
|
this.columns = this.columnMgr.getColumnData();
|
||||||
|
|
||||||
// Count the visible rows
|
// Count the visible rows
|
||||||
var total_cnt = 0;
|
var total_cnt = 0;
|
||||||
for (var i = 0; i < this.columns.length; i++)
|
for (var i = 0; i < this.columns.length; i++) {
|
||||||
{
|
if (this.columns[i].visible) {
|
||||||
if (this.columns[i].visible)
|
|
||||||
{
|
|
||||||
total_cnt++;
|
total_cnt++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the grid column styles
|
// Set the grid column styles
|
||||||
var first = true;
|
var first = true;
|
||||||
var vis_col = this.visibleColumnCount = 0;
|
var vis_col = this.visibleColumnCount = 0;
|
||||||
var totalWidth = 0;
|
var totalWidth = 0;
|
||||||
for (var i = 0; i < this.columns.length; i++)
|
for (var i = 0; i < this.columns.length; i++) {
|
||||||
{
|
|
||||||
var col = this.columns[i];
|
var col = this.columns[i];
|
||||||
|
|
||||||
col.tdClass = this.uniqueId + "_td_" + col.id;
|
col.tdClass = this.uniqueId + "_td_" + col.id;
|
||||||
col.divClass = this.uniqueId + "_div_" + col.id;
|
col.divClass = this.uniqueId + "_div_" + col.id;
|
||||||
|
if (col.visible) {
|
||||||
if (col.visible)
|
|
||||||
{
|
|
||||||
vis_col++;
|
vis_col++;
|
||||||
this.visibleColumnCount++;
|
this.visibleColumnCount++;
|
||||||
|
|
||||||
// Update the visibility of the column
|
// Update the visibility of the column
|
||||||
this.egw.css("." + col.tdClass,
|
this.egw.css("." + col.tdClass, "display: table-cell; " +
|
||||||
"display: table-cell; " +
|
|
||||||
"!important;");
|
"!important;");
|
||||||
|
|
||||||
// Ugly browser dependant code - each browser seems to treat the
|
// Ugly browser dependant code - each browser seems to treat the
|
||||||
// right (collapsed) border of the row differently
|
// right (collapsed) border of the row differently
|
||||||
var subBorder = 0;
|
var subBorder = 0;
|
||||||
@ -350,206 +264,160 @@ var et2_dataview = (function(){ "use strict"; return Class.extend({
|
|||||||
subBorder = -1;
|
subBorder = -1;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Make the last columns one pixel smaller, to prevent a horizontal
|
// Make the last columns one pixel smaller, to prevent a horizontal
|
||||||
// scrollbar from showing up
|
// scrollbar from showing up
|
||||||
if (vis_col == total_cnt)
|
if (vis_col == total_cnt) {
|
||||||
{
|
|
||||||
subBorder += 1;
|
subBorder += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the width of the header columns
|
// Write the width of the header columns
|
||||||
var headerWidth = Math.max(0, (col.width - this.headerBorderWidth - subHBorder));
|
var headerWidth = Math.max(0, (col.width - this.headerBorderWidth - subHBorder));
|
||||||
this.egw.css(".egwGridView_outer ." + col.divClass,
|
this.egw.css(".egwGridView_outer ." + col.divClass, "width: " + headerWidth + "px;");
|
||||||
"width: " + headerWidth + "px;");
|
|
||||||
|
|
||||||
// Write the width of the body-columns
|
// Write the width of the body-columns
|
||||||
var columnWidth = Math.max(0, (col.width - this.columnBorderWidth - subBorder));
|
var columnWidth = Math.max(0, (col.width - this.columnBorderWidth - subBorder));
|
||||||
this.egw.css(".egwGridView_grid ." + col.divClass,
|
this.egw.css(".egwGridView_grid ." + col.divClass, "width: " + columnWidth + "px;");
|
||||||
"width: " + columnWidth + "px;");
|
|
||||||
|
|
||||||
totalWidth += col.width;
|
totalWidth += col.width;
|
||||||
|
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
this.egw.css("." + col.tdClass, "display: none;");
|
this.egw.css("." + col.tdClass, "display: none;");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the full row and spacer class
|
// Add the full row and spacer class
|
||||||
this.egw.css(".egwGridView_grid ." + this.uniqueId + "_div_fullRow",
|
this.egw.css(".egwGridView_grid ." + this.uniqueId + "_div_fullRow", "width: " + (totalWidth - this.columnBorderWidth - 2) + "px; border-right-width: 0 !important;");
|
||||||
"width: " + (totalWidth - this.columnBorderWidth - 2) + "px; border-right-width: 0 !important;");
|
this.egw.css(".egwGridView_outer ." + this.uniqueId + "_td_fullRow", "border-right-width: 0 !important;");
|
||||||
this.egw.css(".egwGridView_outer ." + this.uniqueId + "_td_fullRow",
|
this.egw.css(".egwGridView_outer ." + this.uniqueId + "_spacer_fullRow", "width: " + (totalWidth - 1) + "px; border-right-width: 0 !important;");
|
||||||
"border-right-width: 0 !important;");
|
};
|
||||||
this.egw.css(".egwGridView_outer ." + this.uniqueId + "_spacer_fullRow",
|
|
||||||
"width: " + (totalWidth - 1) + "px; border-right-width: 0 !important;");
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds the containers for the header row
|
* Builds the containers for the header row
|
||||||
*/
|
*/
|
||||||
_buildHeader: function() {
|
et2_dataview.prototype._buildHeader = function () {
|
||||||
var self = this;
|
var self = this;
|
||||||
var handler = function (event) {
|
var handler = function (event) {
|
||||||
};
|
};
|
||||||
for (var i = 0; i < this.columns.length; i++)
|
for (var i = 0; i < this.columns.length; i++) {
|
||||||
{
|
|
||||||
var col = this.columns[i];
|
var col = this.columns[i];
|
||||||
|
|
||||||
// Create the column header and the container element
|
// Create the column header and the container element
|
||||||
var cont = jQuery(document.createElement("div"))
|
var cont = jQuery(document.createElement("div"))
|
||||||
.addClass("innerContainer")
|
.addClass("innerContainer")
|
||||||
.addClass(col.divClass);
|
.addClass(col.divClass);
|
||||||
|
|
||||||
var column = jQuery(document.createElement("th"))
|
var column = jQuery(document.createElement("th"))
|
||||||
.addClass(col.tdClass)
|
.addClass(col.tdClass)
|
||||||
.attr("align", "left")
|
.attr("align", "left")
|
||||||
.append(cont)
|
.append(cont)
|
||||||
.appendTo(this.headTr);
|
.appendTo(this.headTr);
|
||||||
|
if (this.columnMgr && this.columnMgr.columns[i]) {
|
||||||
if(this.columnMgr && this.columnMgr.columns[i])
|
|
||||||
{
|
|
||||||
column.addClass(this.columnMgr.columns[i].fixedWidth ? 'fixedWidth' : 'relativeWidth');
|
column.addClass(this.columnMgr.columns[i].fixedWidth ? 'fixedWidth' : 'relativeWidth');
|
||||||
if(this.columnMgr.columns[i].visibility === ET2_COL_VISIBILITY_ALWAYS_NOSELECT)
|
if (this.columnMgr.columns[i].visibility === et2_dataview_column.ET2_COL_VISIBILITY_ALWAYS_NOSELECT) {
|
||||||
{
|
|
||||||
column.addClass('noResize');
|
column.addClass('noResize');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// make column resizable
|
// make column resizable
|
||||||
var enc_column = self.columnMgr.getColumnById(col.id);
|
var enc_column = self.columnMgr.getColumnById(col.id);
|
||||||
if(enc_column.visibility !== ET2_COL_VISIBILITY_ALWAYS_NOSELECT)
|
if (enc_column.visibility !== et2_dataview_column.ET2_COL_VISIBILITY_ALWAYS_NOSELECT) {
|
||||||
{
|
et2_dataview_view_resizable.makeResizeable(column, function (_w) {
|
||||||
et2_dataview_makeResizeable(column, function(_w) {
|
|
||||||
|
|
||||||
// User wants the column to stay where they put it, even for relative
|
// User wants the column to stay where they put it, even for relative
|
||||||
// width columns, so set it explicitly first and adjust other relative
|
// width columns, so set it explicitly first and adjust other relative
|
||||||
// columns to match.
|
// columns to match.
|
||||||
if(this.relativeWidth)
|
if (this.relativeWidth) {
|
||||||
{
|
|
||||||
// Set to selected width
|
// Set to selected width
|
||||||
this.set_width(_w + "px");
|
this.set_width(_w + "px");
|
||||||
self.columnMgr.updated = true;
|
self.columnMgr.updated = true;
|
||||||
// Just triggers recalculation
|
// Just triggers recalculation
|
||||||
self.columnMgr.getColumnWidth(0);
|
self.columnMgr.getColumnWidth(0);
|
||||||
|
|
||||||
// Set relative widths to match
|
// Set relative widths to match
|
||||||
var relative = self.columnMgr.totalWidth - self.columnMgr.totalFixed + _w;
|
var relative = self.columnMgr.totalWidth - self.columnMgr.totalFixed + _w;
|
||||||
this.set_width(_w / relative);
|
this.set_width(_w / relative);
|
||||||
for(var i = 0; i < self.columnMgr.columns.length; i++)
|
for (var i = 0; i < self.columnMgr.columns.length; i++) {
|
||||||
{
|
|
||||||
var col = self.columnMgr.columns[i];
|
var col = self.columnMgr.columns[i];
|
||||||
if(col == this || col.fixedWidth) continue;
|
if (col == this || col.fixedWidth)
|
||||||
|
continue;
|
||||||
col.set_width(self.columnMgr.columnWidths[i] / relative);
|
col.set_width(self.columnMgr.columnWidths[i] / relative);
|
||||||
}
|
}
|
||||||
// Triggers column change callback, which saves
|
// Triggers column change callback, which saves
|
||||||
self.updateColumns();
|
self.updateColumns();
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
this.set_width(this.relativeWidth ? (_w / self.columnMgr.totalWidth) : _w + "px");
|
this.set_width(this.relativeWidth ? (_w / self.columnMgr.totalWidth) : _w + "px");
|
||||||
self.columnMgr.updated = true;
|
self.columnMgr.updated = true;
|
||||||
self.updateColumns();
|
self.updateColumns();
|
||||||
}
|
}
|
||||||
|
|
||||||
}, enc_column);
|
}, enc_column);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store both nodes in the columnNodes array
|
// Store both nodes in the columnNodes array
|
||||||
this.columnNodes.push({
|
this.columnNodes.push({
|
||||||
"column": column,
|
"column": column,
|
||||||
"container": cont
|
"container": cont
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this._buildSelectCol();
|
this._buildSelectCol();
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds the select cols column
|
* Builds the select cols column
|
||||||
*/
|
*/
|
||||||
_buildSelectCol: function() {
|
et2_dataview.prototype._buildSelectCol = function () {
|
||||||
// Build the "select columns" icon
|
// Build the "select columns" icon
|
||||||
this.selectColIcon = jQuery(document.createElement("span"))
|
this.selectColIcon = jQuery(document.createElement("span"))
|
||||||
.addClass("selectcols")
|
.addClass("selectcols")
|
||||||
.css('display', 'inline-block'); // otherwise jQuery('span.selectcols',this.dataview.headTr).show() set it to "inline" causing it to not show up because 0 height
|
.css('display', 'inline-block'); // otherwise jQuery('span.selectcols',this.dataview.headTr).show() set it to "inline" causing it to not show up because 0 height
|
||||||
|
|
||||||
// Build the option column
|
// Build the option column
|
||||||
this.selectCol = jQuery(document.createElement("th"))
|
this.selectCol = jQuery(document.createElement("th"))
|
||||||
.addClass("optcol")
|
.addClass("optcol")
|
||||||
.append(this.selectColIcon)
|
.append(this.selectColIcon)
|
||||||
// Toggle display of option popup
|
// Toggle display of option popup
|
||||||
.click(this, function(e) {if(e.data.selectColumnsClick) e.data.selectColumnsClick(e);})
|
.click(this, function (e) { if (e.data.selectColumnsClick)
|
||||||
|
e.data.selectColumnsClick(e); })
|
||||||
.appendTo(this.headTr);
|
.appendTo(this.headTr);
|
||||||
|
|
||||||
this.selectCol.css("width", this.scrollbarWidth - this.selectCol.outerWidth()
|
this.selectCol.css("width", this.scrollbarWidth - this.selectCol.outerWidth()
|
||||||
+ this.selectCol.width() + 1);
|
+ this.selectCol.width() + 1);
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds the inner grid class
|
* Builds the inner grid class
|
||||||
*/
|
*/
|
||||||
_buildGrid: function() {
|
et2_dataview.prototype._buildGrid = function () {
|
||||||
// Create the collection of column ids
|
// Create the collection of column ids
|
||||||
var colIds = new Array(this.columns.length);
|
var colIds = new Array(this.columns.length);
|
||||||
for (var i = 0; i < this.columns.length; i++)
|
for (var i = 0; i < this.columns.length; i++) {
|
||||||
{
|
|
||||||
colIds[i] = this.columns[i].id;
|
colIds[i] = this.columns[i].id;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the row provider
|
// Create the row provider
|
||||||
if (this.rowProvider)
|
if (this.rowProvider) {
|
||||||
{
|
|
||||||
this.rowProvider.free();
|
this.rowProvider.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.rowProvider = new et2_dataview_rowProvider(this.uniqueId, colIds);
|
this.rowProvider = new et2_dataview_rowProvider(this.uniqueId, colIds);
|
||||||
|
|
||||||
// Create the grid class and pass "19" as the starting average row height
|
// Create the grid class and pass "19" as the starting average row height
|
||||||
this.grid = new et2_dataview_grid(null, null, this.egw, this.rowProvider, 19);
|
this.grid = new et2_dataview_grid(null, null, this.egw, this.rowProvider, 19);
|
||||||
|
|
||||||
// Insert the grid into the DOM-Tree
|
// Insert the grid into the DOM-Tree
|
||||||
var tr = jQuery(this.grid._nodes[0]);
|
var tr = jQuery(this.grid._nodes[0]);
|
||||||
this.containerTr.replaceWith(tr);
|
this.containerTr.replaceWith(tr);
|
||||||
this.containerTr = tr;
|
this.containerTr = tr;
|
||||||
},
|
};
|
||||||
|
|
||||||
/* --- Code for calculating the browser/css depending widths --- */
|
/* --- Code for calculating the browser/css depending widths --- */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads the browser dependant variables
|
* Reads the browser dependant variables
|
||||||
*/
|
*/
|
||||||
_getDepVars: function() {
|
et2_dataview.prototype._getDepVars = function () {
|
||||||
if (this.scrollbarWidth === false)
|
if (typeof this.scrollbarWidth === 'undefined') {
|
||||||
{
|
|
||||||
// Clone the table and attach it to the outer body tag
|
// Clone the table and attach it to the outer body tag
|
||||||
var clone = this.table.clone();
|
var clone = this.table.clone();
|
||||||
jQuery(window.top.document.getElementsByTagName("body")[0])
|
jQuery(window.top.document.getElementsByTagName("body")[0])
|
||||||
.append(clone);
|
.append(clone);
|
||||||
|
|
||||||
// Read the scrollbar width
|
// Read the scrollbar width
|
||||||
this.scrollbarWidth = this.constructor.prototype.scrollbarWidth =
|
this.scrollbarWidth = this.constructor.prototype.scrollbarWidth =
|
||||||
this._getScrollbarWidth(clone);
|
this._getScrollbarWidth(clone);
|
||||||
|
|
||||||
// Read the header border width
|
// Read the header border width
|
||||||
this.headerBorderWidth = this.constructor.prototype.headerBorderWidth =
|
this.headerBorderWidth = this.constructor.prototype.headerBorderWidth =
|
||||||
this._getHeaderBorderWidth(clone);
|
this._getHeaderBorderWidth(clone);
|
||||||
|
|
||||||
// Read the column border width
|
// Read the column border width
|
||||||
this.columnBorderWidth = this.constructor.prototype.columnBorderWidth =
|
this.columnBorderWidth = this.constructor.prototype.columnBorderWidth =
|
||||||
this._getColumnBorderWidth(clone);
|
this._getColumnBorderWidth(clone);
|
||||||
|
|
||||||
// Remove the cloned DOM-Node again from the outer body
|
// Remove the cloned DOM-Node again from the outer body
|
||||||
clone.remove();
|
clone.remove();
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads the scrollbar width
|
* Reads the scrollbar width
|
||||||
*/
|
*/
|
||||||
_getScrollbarWidth: function(_table) {
|
et2_dataview.prototype._getScrollbarWidth = function (_table) {
|
||||||
// Create a temporary td and two divs, which are inserted into the
|
// Create a temporary td and two divs, which are inserted into the
|
||||||
// DOM-Tree. The outer div has a fixed size and "overflow" set to auto.
|
// DOM-Tree. The outer div has a fixed size and "overflow" set to auto.
|
||||||
// When the second div is inserted, it will be forced to display a scrollbar.
|
// When the second div is inserted, it will be forced to display a scrollbar.
|
||||||
@ -562,64 +430,49 @@ var et2_dataview = (function(){ "use strict"; return Class.extend({
|
|||||||
.append(div_inner);
|
.append(div_inner);
|
||||||
var td = jQuery(document.createElement("td"))
|
var td = jQuery(document.createElement("td"))
|
||||||
.append(div_outer);
|
.append(div_outer);
|
||||||
|
|
||||||
// Store the scrollbar width statically.
|
// Store the scrollbar width statically.
|
||||||
jQuery("tbody tr", _table).append(td);
|
jQuery("tbody tr", _table).append(td);
|
||||||
var width = Math.max(10, div_outer.outerWidth() - div_inner.outerWidth());
|
var width = Math.max(10, div_outer.outerWidth() - div_inner.outerWidth());
|
||||||
|
|
||||||
// Remove the elements again
|
// Remove the elements again
|
||||||
div_outer.remove();
|
div_outer.remove();
|
||||||
|
|
||||||
return width;
|
return width;
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the total width of the header column border
|
* Calculates the total width of the header column border
|
||||||
*/
|
*/
|
||||||
_getHeaderBorderWidth: function(_table) {
|
et2_dataview.prototype._getHeaderBorderWidth = function (_table) {
|
||||||
// Create a temporary th which is appended to the outer thead row
|
// Create a temporary th which is appended to the outer thead row
|
||||||
var cont = jQuery(document.createElement("div"))
|
var cont = jQuery(document.createElement("div"))
|
||||||
.addClass("innerContainer");
|
.addClass("innerContainer");
|
||||||
|
|
||||||
var th = jQuery(document.createElement("th"))
|
var th = jQuery(document.createElement("th"))
|
||||||
.append(cont);
|
.append(cont);
|
||||||
|
|
||||||
// Insert the th into the document tree
|
// Insert the th into the document tree
|
||||||
jQuery("thead tr", _table).append(th);
|
jQuery("thead tr", _table).append(th);
|
||||||
|
|
||||||
// Calculate the total border width
|
// Calculate the total border width
|
||||||
var width = th.outerWidth(true) - cont.width();
|
var width = th.outerWidth(true) - cont.width();
|
||||||
|
|
||||||
// Remove the appended element again
|
// Remove the appended element again
|
||||||
th.remove();
|
th.remove();
|
||||||
|
|
||||||
return width;
|
return width;
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the total width of the column border
|
* Calculates the total width of the column border
|
||||||
*/
|
*/
|
||||||
_getColumnBorderWidth : function(_table) {
|
et2_dataview.prototype._getColumnBorderWidth = function (_table) {
|
||||||
// Create a temporary th which is appended to the outer thead row
|
// Create a temporary th which is appended to the outer thead row
|
||||||
var cont = jQuery(document.createElement("div"))
|
var cont = jQuery(document.createElement("div"))
|
||||||
.addClass("innerContainer");
|
.addClass("innerContainer");
|
||||||
|
|
||||||
var td = jQuery(document.createElement("td"))
|
var td = jQuery(document.createElement("td"))
|
||||||
.append(cont);
|
.append(cont);
|
||||||
|
|
||||||
// Insert the th into the document tree
|
// Insert the th into the document tree
|
||||||
jQuery("tbody tr", _table).append(td);
|
jQuery("tbody tr", _table).append(td);
|
||||||
|
|
||||||
// Calculate the total border width
|
// Calculate the total border width
|
||||||
_table.addClass("egwGridView_grid");
|
_table.addClass("egwGridView_grid");
|
||||||
var width = td.outerWidth(true) - cont.width();
|
var width = td.outerWidth(true) - cont.width();
|
||||||
|
|
||||||
// Remove the appended element again
|
// Remove the appended element again
|
||||||
td.remove();
|
td.remove();
|
||||||
|
|
||||||
return width;
|
return width;
|
||||||
}
|
};
|
||||||
|
return et2_dataview;
|
||||||
});}).call(this);
|
}());
|
||||||
|
exports.et2_dataview = et2_dataview;
|
||||||
|
//# sourceMappingURL=et2_dataview.js.map
|
664
api/js/etemplate/et2_dataview.ts
Normal file
664
api/js/etemplate/et2_dataview.ts
Normal file
@ -0,0 +1,664 @@
|
|||||||
|
/**
|
||||||
|
* EGroupware eTemplate2 - dataview code
|
||||||
|
*
|
||||||
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||||
|
* @package etemplate
|
||||||
|
* @subpackage dataview
|
||||||
|
* @link http://www.egroupware.org
|
||||||
|
* @author Andreas Stöckel
|
||||||
|
* @copyright Stylite 2011-2012
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*egw:uses
|
||||||
|
/vendor/bower-asset/jquery/dist/jquery.js;
|
||||||
|
et2_core_common;
|
||||||
|
|
||||||
|
et2_dataview_model_columns;
|
||||||
|
et2_dataview_view_rowProvider;
|
||||||
|
et2_dataview_view_grid;
|
||||||
|
et2_dataview_view_resizeable;
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The et2_dataview class is the main class for displaying a dataview. The
|
||||||
|
* dataview class manages the creation of the outer html nodes (like the table,
|
||||||
|
* header, etc.) and contains the root container: an instance of
|
||||||
|
* et2_dataview_view_grid, which can be accessed using the "grid" property of
|
||||||
|
* this object.
|
||||||
|
*
|
||||||
|
* @augments Class
|
||||||
|
*/
|
||||||
|
export class et2_dataview
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constant which regulates the column padding.
|
||||||
|
*/
|
||||||
|
columnPadding: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Some browser dependant variables which will be calculated on creation of
|
||||||
|
* the first gridContainer object.
|
||||||
|
*/
|
||||||
|
scrollbarWidth: number;
|
||||||
|
headerBorderWidth: number;
|
||||||
|
columnBorderWidth: number;
|
||||||
|
|
||||||
|
private width: number;
|
||||||
|
private height: number;
|
||||||
|
|
||||||
|
private uniqueId: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hooks to allow parent to keep up to date if things change
|
||||||
|
*/
|
||||||
|
onUpdateColumns: Function;
|
||||||
|
selectColumnsClick: Function;
|
||||||
|
|
||||||
|
private parentNode: JQuery;
|
||||||
|
egw: any;
|
||||||
|
|
||||||
|
private columnNodes: any[];
|
||||||
|
private columns: any[];
|
||||||
|
private columnMgr: et2_dataview_columns;
|
||||||
|
private rowProvider: et2_dataview_rowProvider;
|
||||||
|
|
||||||
|
private grid: et2_dataview_grid;
|
||||||
|
|
||||||
|
// DOM stuff
|
||||||
|
private selectColIcon: JQuery;
|
||||||
|
private headTr: any;
|
||||||
|
private containerTr: JQuery;
|
||||||
|
private selectCol: JQuery;
|
||||||
|
private thead: JQuery;
|
||||||
|
private tbody: JQuery;
|
||||||
|
private table: JQuery;
|
||||||
|
private visibleColumnCount: number;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for the grid container
|
||||||
|
*
|
||||||
|
* @param {DOMElement} _parentNode is the DOM-Node into which the grid view will be inserted
|
||||||
|
* @param {egw} _egw
|
||||||
|
* @memberOf et2_dataview
|
||||||
|
*/
|
||||||
|
constructor(_parentNode, _egw) {
|
||||||
|
|
||||||
|
// Copy the arguments
|
||||||
|
this.parentNode = jQuery(_parentNode);
|
||||||
|
this.egw = _egw;
|
||||||
|
|
||||||
|
// Initialize some variables
|
||||||
|
this.columnNodes = []; // Array with the header containers
|
||||||
|
this.columns = [];
|
||||||
|
this.columnMgr = null;
|
||||||
|
this.rowProvider = null;
|
||||||
|
|
||||||
|
this.width = 0;
|
||||||
|
this.height = 0;
|
||||||
|
|
||||||
|
this.uniqueId = "gridCont_" + this.egw.uid();
|
||||||
|
|
||||||
|
// Build the base nodes
|
||||||
|
this._createElements();
|
||||||
|
|
||||||
|
// Read the browser dependant variables
|
||||||
|
this._getDepVars();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroys the object, removes all dom nodes and clears all references.
|
||||||
|
*/
|
||||||
|
destroy()
|
||||||
|
{
|
||||||
|
// Clear the columns
|
||||||
|
this._clearHeader();
|
||||||
|
|
||||||
|
// Free the grid
|
||||||
|
if (this.grid)
|
||||||
|
{
|
||||||
|
this.grid.free();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free the row provider
|
||||||
|
if (this.rowProvider)
|
||||||
|
{
|
||||||
|
this.rowProvider.free();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detatch the outer element
|
||||||
|
this.table.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears all data rows and reloads them
|
||||||
|
*/
|
||||||
|
clear()
|
||||||
|
{
|
||||||
|
if (this.grid)
|
||||||
|
{
|
||||||
|
this.grid.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the column container node for the given column index
|
||||||
|
*
|
||||||
|
* @param _columnIdx the integer column index
|
||||||
|
*/
|
||||||
|
getHeaderContainerNode(_columnIdx)
|
||||||
|
{
|
||||||
|
if (typeof this.columnNodes[_columnIdx] != "undefined")
|
||||||
|
{
|
||||||
|
return this.columnNodes[_columnIdx].container[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the column descriptors and creates the column header according to it.
|
||||||
|
* The inner grid will be emptied if it has already been built.
|
||||||
|
*/
|
||||||
|
setColumns(_columnData)
|
||||||
|
{
|
||||||
|
// Free all column objects which have been created till this moment
|
||||||
|
this._clearHeader();
|
||||||
|
|
||||||
|
// Copy the given column data
|
||||||
|
this.columnMgr = new et2_dataview_columns(_columnData);
|
||||||
|
|
||||||
|
// Create the stylesheets
|
||||||
|
this.updateColumns();
|
||||||
|
|
||||||
|
// Build the header row
|
||||||
|
this._buildHeader();
|
||||||
|
|
||||||
|
// Build the grid
|
||||||
|
this._buildGrid();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resizes the grid
|
||||||
|
*/
|
||||||
|
resize(_w: number, _h: number)
|
||||||
|
{
|
||||||
|
// Not fully initialized yet...
|
||||||
|
if (!this.columnMgr) return;
|
||||||
|
|
||||||
|
if (this.width != _w)
|
||||||
|
{
|
||||||
|
this.width = _w;
|
||||||
|
|
||||||
|
// Take grid border width into account
|
||||||
|
_w -= (this.table.outerWidth(true) - this.table.innerWidth());
|
||||||
|
|
||||||
|
// Take grid header border's width into account. eg. category colors may add extra pixel into width
|
||||||
|
_w = _w - (this.thead.find('tr').outerWidth() - this.thead.find('tr').innerWidth());
|
||||||
|
|
||||||
|
// Rebuild the column stylesheets
|
||||||
|
this.columnMgr.setTotalWidth(_w - this.scrollbarWidth);
|
||||||
|
this._updateColumns();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.height != _h)
|
||||||
|
{
|
||||||
|
this.height = _h;
|
||||||
|
|
||||||
|
// Set the height of the grid.
|
||||||
|
if (this.grid)
|
||||||
|
{
|
||||||
|
this.grid.setScrollHeight(this.height -
|
||||||
|
this.headTr.outerHeight(true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the column manager object. You can use it to set the visibility
|
||||||
|
* of columns etc. Call "updateHeader" if you did any changes.
|
||||||
|
*/
|
||||||
|
getColumnMgr() {
|
||||||
|
return this.columnMgr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recalculates the stylesheets which determine the column visibility and
|
||||||
|
* width.
|
||||||
|
*
|
||||||
|
* @param setDefault boolean Allow admins to save current settings as default for all users
|
||||||
|
*/
|
||||||
|
updateColumns(setDefault : boolean = false)
|
||||||
|
{
|
||||||
|
if (this.columnMgr)
|
||||||
|
{
|
||||||
|
this._updateColumns();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ability to notify parent / someone else
|
||||||
|
if (this.onUpdateColumns)
|
||||||
|
{
|
||||||
|
this.onUpdateColumns(setDefault);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* --- PRIVATE FUNCTIONS --- */
|
||||||
|
|
||||||
|
/* --- Code for building the grid container DOM-Tree elements ---- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the base DOM-Tree elements
|
||||||
|
*/
|
||||||
|
private _createElements()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Structure:
|
||||||
|
<table class="egwGridView_outer">
|
||||||
|
<thead>
|
||||||
|
<tr> [HEAD] </tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr> [GRID CONTAINER] </tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
*/
|
||||||
|
|
||||||
|
this.containerTr = jQuery(document.createElement("tr"));
|
||||||
|
this.headTr = jQuery(document.createElement("tr"));
|
||||||
|
|
||||||
|
this.thead = jQuery(document.createElement("thead"))
|
||||||
|
.append(this.headTr);
|
||||||
|
this.tbody = jQuery(document.createElement("tbody"))
|
||||||
|
.append(this.containerTr);
|
||||||
|
|
||||||
|
this.table = jQuery(document.createElement("table"))
|
||||||
|
.addClass("egwGridView_outer")
|
||||||
|
.append(this.thead, this.tbody)
|
||||||
|
.appendTo(this.parentNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* --- Code for building the header row --- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the header row
|
||||||
|
*/
|
||||||
|
private _clearHeader ()
|
||||||
|
{
|
||||||
|
if (this.columnMgr)
|
||||||
|
{
|
||||||
|
this.columnMgr.free();
|
||||||
|
this.columnMgr = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove dynamic CSS,
|
||||||
|
for (var i = 0; i < this.columns.length; i++)
|
||||||
|
{
|
||||||
|
if(this.columns[i].tdClass)
|
||||||
|
{
|
||||||
|
this.egw.css('.'+this.columns[i].tdClass);
|
||||||
|
}
|
||||||
|
if(this.columns[i].divClass)
|
||||||
|
{
|
||||||
|
this.egw.css('.'+this.columns[i].divClass);
|
||||||
|
this.egw.css(".egwGridView_outer ." + this.columns[i].divClass);
|
||||||
|
this.egw.css(".egwGridView_grid ." + this.columns[i].divClass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.egw.css(".egwGridView_grid ." + this.uniqueId + "_div_fullRow");
|
||||||
|
this.egw.css(".egwGridView_outer ." + this.uniqueId + "_td_fullRow");
|
||||||
|
this.egw.css(".egwGridView_outer ." + this.uniqueId + "_spacer_fullRow");
|
||||||
|
|
||||||
|
// Reset the headerColumns array and empty the table row
|
||||||
|
this.columnNodes = [];
|
||||||
|
this.columns = [];
|
||||||
|
this.headTr.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the column data which is retrieved by calling egwGridColumns.getColumnData.
|
||||||
|
* The columns will be updated.
|
||||||
|
*/
|
||||||
|
private _updateColumns()
|
||||||
|
{
|
||||||
|
// Copy the columns data
|
||||||
|
this.columns = this.columnMgr.getColumnData();
|
||||||
|
|
||||||
|
// Count the visible rows
|
||||||
|
var total_cnt = 0;
|
||||||
|
for (var i = 0; i < this.columns.length; i++)
|
||||||
|
{
|
||||||
|
if (this.columns[i].visible)
|
||||||
|
{
|
||||||
|
total_cnt++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the grid column styles
|
||||||
|
var first = true;
|
||||||
|
var vis_col = this.visibleColumnCount = 0;
|
||||||
|
var totalWidth = 0;
|
||||||
|
for (var i = 0; i < this.columns.length; i++)
|
||||||
|
{
|
||||||
|
var col = this.columns[i];
|
||||||
|
|
||||||
|
col.tdClass = this.uniqueId + "_td_" + col.id;
|
||||||
|
col.divClass = this.uniqueId + "_div_" + col.id;
|
||||||
|
|
||||||
|
if (col.visible)
|
||||||
|
{
|
||||||
|
vis_col++;
|
||||||
|
this.visibleColumnCount++;
|
||||||
|
|
||||||
|
// Update the visibility of the column
|
||||||
|
this.egw.css("." + col.tdClass,
|
||||||
|
"display: table-cell; " +
|
||||||
|
"!important;");
|
||||||
|
|
||||||
|
// Ugly browser dependant code - each browser seems to treat the
|
||||||
|
// right (collapsed) border of the row differently
|
||||||
|
var subBorder = 0;
|
||||||
|
var subHBorder = 0;
|
||||||
|
/*
|
||||||
|
if (jQuery.browser.mozilla)
|
||||||
|
{
|
||||||
|
var maj = jQuery.browser.version.split(".")[0];
|
||||||
|
if (maj < 2) {
|
||||||
|
subBorder = 1; // Versions <= FF 3.6
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (jQuery.browser.webkit)
|
||||||
|
{
|
||||||
|
if (!first)
|
||||||
|
{
|
||||||
|
subBorder = 1;
|
||||||
|
}
|
||||||
|
subHBorder = 1;
|
||||||
|
}
|
||||||
|
if ((jQuery.browser.msie || jQuery.browser.opera) && first)
|
||||||
|
{
|
||||||
|
subBorder = -1;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Make the last columns one pixel smaller, to prevent a horizontal
|
||||||
|
// scrollbar from showing up
|
||||||
|
if (vis_col == total_cnt)
|
||||||
|
{
|
||||||
|
subBorder += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the width of the header columns
|
||||||
|
var headerWidth = Math.max(0, (col.width - this.headerBorderWidth - subHBorder));
|
||||||
|
this.egw.css(".egwGridView_outer ." + col.divClass,
|
||||||
|
"width: " + headerWidth + "px;");
|
||||||
|
|
||||||
|
// Write the width of the body-columns
|
||||||
|
var columnWidth = Math.max(0, (col.width - this.columnBorderWidth - subBorder));
|
||||||
|
this.egw.css(".egwGridView_grid ." + col.divClass,
|
||||||
|
"width: " + columnWidth + "px;");
|
||||||
|
|
||||||
|
totalWidth += col.width;
|
||||||
|
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.egw.css("." + col.tdClass, "display: none;");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the full row and spacer class
|
||||||
|
this.egw.css(".egwGridView_grid ." + this.uniqueId + "_div_fullRow",
|
||||||
|
"width: " + (totalWidth - this.columnBorderWidth - 2) + "px; border-right-width: 0 !important;");
|
||||||
|
this.egw.css(".egwGridView_outer ." + this.uniqueId + "_td_fullRow",
|
||||||
|
"border-right-width: 0 !important;");
|
||||||
|
this.egw.css(".egwGridView_outer ." + this.uniqueId + "_spacer_fullRow",
|
||||||
|
"width: " + (totalWidth - 1) + "px; border-right-width: 0 !important;");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the containers for the header row
|
||||||
|
*/
|
||||||
|
private _buildHeader()
|
||||||
|
{
|
||||||
|
var self = this;
|
||||||
|
var handler = function(event) {
|
||||||
|
};
|
||||||
|
for (var i = 0; i < this.columns.length; i++)
|
||||||
|
{
|
||||||
|
var col = this.columns[i];
|
||||||
|
|
||||||
|
// Create the column header and the container element
|
||||||
|
var cont = jQuery(document.createElement("div"))
|
||||||
|
.addClass("innerContainer")
|
||||||
|
.addClass(col.divClass);
|
||||||
|
|
||||||
|
var column = jQuery(document.createElement("th"))
|
||||||
|
.addClass(col.tdClass)
|
||||||
|
.attr("align", "left")
|
||||||
|
.append(cont)
|
||||||
|
.appendTo(this.headTr);
|
||||||
|
|
||||||
|
if(this.columnMgr && this.columnMgr.columns[i])
|
||||||
|
{
|
||||||
|
column.addClass(this.columnMgr.columns[i].fixedWidth ? 'fixedWidth' : 'relativeWidth');
|
||||||
|
if(this.columnMgr.columns[i].visibility === et2_dataview_column.ET2_COL_VISIBILITY_ALWAYS_NOSELECT)
|
||||||
|
{
|
||||||
|
column.addClass('noResize');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// make column resizable
|
||||||
|
var enc_column = self.columnMgr.getColumnById(col.id);
|
||||||
|
if(enc_column.visibility !== et2_dataview_column.ET2_COL_VISIBILITY_ALWAYS_NOSELECT)
|
||||||
|
{
|
||||||
|
et2_dataview_view_resizable.makeResizeable(column, function(_w) {
|
||||||
|
|
||||||
|
// User wants the column to stay where they put it, even for relative
|
||||||
|
// width columns, so set it explicitly first and adjust other relative
|
||||||
|
// columns to match.
|
||||||
|
if(this.relativeWidth)
|
||||||
|
{
|
||||||
|
// Set to selected width
|
||||||
|
this.set_width(_w + "px");
|
||||||
|
self.columnMgr.updated = true;
|
||||||
|
// Just triggers recalculation
|
||||||
|
self.columnMgr.getColumnWidth(0);
|
||||||
|
|
||||||
|
// Set relative widths to match
|
||||||
|
var relative = self.columnMgr.totalWidth - self.columnMgr.totalFixed + _w;
|
||||||
|
this.set_width(_w / relative);
|
||||||
|
for(var i = 0; i < self.columnMgr.columns.length; i++)
|
||||||
|
{
|
||||||
|
var col = self.columnMgr.columns[i];
|
||||||
|
if(col == this || col.fixedWidth) continue;
|
||||||
|
col.set_width(self.columnMgr.columnWidths[i] / relative);
|
||||||
|
}
|
||||||
|
// Triggers column change callback, which saves
|
||||||
|
self.updateColumns();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.set_width(this.relativeWidth ? (_w / self.columnMgr.totalWidth) : _w + "px");
|
||||||
|
self.columnMgr.updated = true;
|
||||||
|
self.updateColumns();
|
||||||
|
}
|
||||||
|
|
||||||
|
}, enc_column);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store both nodes in the columnNodes array
|
||||||
|
this.columnNodes.push({
|
||||||
|
"column": column,
|
||||||
|
"container": cont
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this._buildSelectCol();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the select cols column
|
||||||
|
*/
|
||||||
|
private _buildSelectCol()
|
||||||
|
{
|
||||||
|
// Build the "select columns" icon
|
||||||
|
this.selectColIcon = jQuery(document.createElement("span"))
|
||||||
|
.addClass("selectcols")
|
||||||
|
.css('display', 'inline-block'); // otherwise jQuery('span.selectcols',this.dataview.headTr).show() set it to "inline" causing it to not show up because 0 height
|
||||||
|
|
||||||
|
// Build the option column
|
||||||
|
this.selectCol = jQuery(document.createElement("th"))
|
||||||
|
.addClass("optcol")
|
||||||
|
.append(this.selectColIcon)
|
||||||
|
// Toggle display of option popup
|
||||||
|
.click(this, function(e) {if(e.data.selectColumnsClick) e.data.selectColumnsClick(e);})
|
||||||
|
.appendTo(this.headTr);
|
||||||
|
|
||||||
|
this.selectCol.css("width", this.scrollbarWidth - this.selectCol.outerWidth()
|
||||||
|
+ this.selectCol.width() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the inner grid class
|
||||||
|
*/
|
||||||
|
private _buildGrid()
|
||||||
|
{
|
||||||
|
// Create the collection of column ids
|
||||||
|
var colIds = new Array(this.columns.length);
|
||||||
|
for (var i = 0; i < this.columns.length; i++)
|
||||||
|
{
|
||||||
|
colIds[i] = this.columns[i].id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the row provider
|
||||||
|
if (this.rowProvider)
|
||||||
|
{
|
||||||
|
this.rowProvider.free();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.rowProvider = new et2_dataview_rowProvider(this.uniqueId, colIds);
|
||||||
|
|
||||||
|
// Create the grid class and pass "19" as the starting average row height
|
||||||
|
this.grid = new et2_dataview_grid(null, null, this.egw, this.rowProvider, 19);
|
||||||
|
|
||||||
|
// Insert the grid into the DOM-Tree
|
||||||
|
var tr = jQuery(this.grid._nodes[0]);
|
||||||
|
this.containerTr.replaceWith(tr);
|
||||||
|
this.containerTr = tr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Code for calculating the browser/css depending widths --- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the browser dependant variables
|
||||||
|
*/
|
||||||
|
private _getDepVars()
|
||||||
|
{
|
||||||
|
if (typeof this.scrollbarWidth === 'undefined')
|
||||||
|
{
|
||||||
|
// Clone the table and attach it to the outer body tag
|
||||||
|
var clone = this.table.clone();
|
||||||
|
jQuery(window.top.document.getElementsByTagName("body")[0])
|
||||||
|
.append(clone);
|
||||||
|
|
||||||
|
// Read the scrollbar width
|
||||||
|
this.scrollbarWidth = this.constructor.prototype.scrollbarWidth =
|
||||||
|
this._getScrollbarWidth(clone);
|
||||||
|
|
||||||
|
// Read the header border width
|
||||||
|
this.headerBorderWidth = this.constructor.prototype.headerBorderWidth =
|
||||||
|
this._getHeaderBorderWidth(clone);
|
||||||
|
|
||||||
|
// Read the column border width
|
||||||
|
this.columnBorderWidth = this.constructor.prototype.columnBorderWidth =
|
||||||
|
this._getColumnBorderWidth(clone);
|
||||||
|
|
||||||
|
// Remove the cloned DOM-Node again from the outer body
|
||||||
|
clone.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the scrollbar width
|
||||||
|
*/
|
||||||
|
private _getScrollbarWidth(_table: JQuery)
|
||||||
|
{
|
||||||
|
// Create a temporary td and two divs, which are inserted into the
|
||||||
|
// DOM-Tree. The outer div has a fixed size and "overflow" set to auto.
|
||||||
|
// When the second div is inserted, it will be forced to display a scrollbar.
|
||||||
|
var div_inner = jQuery(document.createElement("div"))
|
||||||
|
.css("height", "1000px");
|
||||||
|
var div_outer = jQuery(document.createElement("div"))
|
||||||
|
.css("height", "100px")
|
||||||
|
.css("width", "100px")
|
||||||
|
.css("overflow", "auto")
|
||||||
|
.append(div_inner);
|
||||||
|
var td = jQuery(document.createElement("td"))
|
||||||
|
.append(div_outer);
|
||||||
|
|
||||||
|
// Store the scrollbar width statically.
|
||||||
|
jQuery("tbody tr", _table).append(td);
|
||||||
|
var width = Math.max(10, div_outer.outerWidth() - div_inner.outerWidth());
|
||||||
|
|
||||||
|
// Remove the elements again
|
||||||
|
div_outer.remove();
|
||||||
|
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the total width of the header column border
|
||||||
|
*/
|
||||||
|
private _getHeaderBorderWidth(_table: JQuery)
|
||||||
|
{
|
||||||
|
// Create a temporary th which is appended to the outer thead row
|
||||||
|
var cont = jQuery(document.createElement("div"))
|
||||||
|
.addClass("innerContainer");
|
||||||
|
|
||||||
|
var th = jQuery(document.createElement("th"))
|
||||||
|
.append(cont);
|
||||||
|
|
||||||
|
// Insert the th into the document tree
|
||||||
|
jQuery("thead tr", _table).append(th);
|
||||||
|
|
||||||
|
// Calculate the total border width
|
||||||
|
var width = th.outerWidth(true) - cont.width();
|
||||||
|
|
||||||
|
// Remove the appended element again
|
||||||
|
th.remove();
|
||||||
|
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the total width of the column border
|
||||||
|
*/
|
||||||
|
private _getColumnBorderWidth(_table: JQuery)
|
||||||
|
{
|
||||||
|
// Create a temporary th which is appended to the outer thead row
|
||||||
|
var cont = jQuery(document.createElement("div"))
|
||||||
|
.addClass("innerContainer");
|
||||||
|
|
||||||
|
var td = jQuery(document.createElement("td"))
|
||||||
|
.append(cont);
|
||||||
|
|
||||||
|
// Insert the th into the document tree
|
||||||
|
jQuery("tbody tr", _table).append(td);
|
||||||
|
|
||||||
|
// Calculate the total border width
|
||||||
|
_table.addClass("egwGridView_grid");
|
||||||
|
var width = td.outerWidth(true) - cont.width();
|
||||||
|
|
||||||
|
// Remove the appended element again
|
||||||
|
td.remove();
|
||||||
|
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,3 +1,4 @@
|
|||||||
|
"use strict";
|
||||||
/**
|
/**
|
||||||
* EGroupware eTemplate2 - Contains interfaces used inside the dataview
|
* EGroupware eTemplate2 - Contains interfaces used inside the dataview
|
||||||
*
|
*
|
||||||
@ -9,89 +10,5 @@
|
|||||||
* @copyright Stylite 2011
|
* @copyright Stylite 2011
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
/*egw:uses
|
//# sourceMappingURL=et2_dataview_interfaces.js.map
|
||||||
et2_core_inheritance;
|
|
||||||
*/
|
|
||||||
|
|
||||||
var et2_dataview_IInvalidatable = new Interface({
|
|
||||||
|
|
||||||
invalidate: function() {}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
var et2_dataview_IViewRange = new Interface({
|
|
||||||
|
|
||||||
setViewRange: function(_range) {}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface a data provider has to implement. The data provider functions are
|
|
||||||
* called by the et2_dataview_controller class. The data provider basically acts
|
|
||||||
* like the egw api egw_data extension, but some etemplate specific stuff has
|
|
||||||
* been stripped away -- the implementation (for the nextmatch widget that is
|
|
||||||
* et2_extension_nextmatch_dataprovider) has to take care of that.
|
|
||||||
*/
|
|
||||||
var et2_IDataProvider = new Interface({
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function is used by the et2_dataview_controller to fetch data for
|
|
||||||
* a certain range. The et2_dataview_controller provides data which allows
|
|
||||||
* to only update elements which really have changed.
|
|
||||||
*
|
|
||||||
* @param queriedRange is an object of the following form:
|
|
||||||
* {
|
|
||||||
* start: <START INDEX>,
|
|
||||||
* num_rows: <COUNT OF ENTRIES>
|
|
||||||
* }
|
|
||||||
* @param knownRange is an array of the above form and informs the
|
|
||||||
* implementation which range is already known to the client. This parameter
|
|
||||||
* may be null in order to indicate that the client currently has no valid
|
|
||||||
* data.
|
|
||||||
* @param lastModification is the last timestamp that was returned from the
|
|
||||||
* data provider and for which the client has data. It may be null in order
|
|
||||||
* to indicate, that the client currently has no data or needs a complete
|
|
||||||
* refresh.
|
|
||||||
* @param callback is the function that should get called, once the data
|
|
||||||
* is available. The data passed to the callback function has the
|
|
||||||
* following form:
|
|
||||||
* {
|
|
||||||
* order: [uid, ...],
|
|
||||||
* total: <TOTAL COUNT>,
|
|
||||||
* lastModification: <LAST MODIFICATION TIMESTAMP>
|
|
||||||
* }
|
|
||||||
* @param context is the context in which the callback function will get
|
|
||||||
* called.
|
|
||||||
*/
|
|
||||||
dataFetch: function (_queriedRange, _lastModification, _callback, _context) {},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers the intrest in a certain uid for a callback function. If
|
|
||||||
* the data for that uid changes or gets loaded, the given callback
|
|
||||||
* function is called. If the data for the given uid is available at the
|
|
||||||
* time of registering the callback, the callback is called immediately.
|
|
||||||
*
|
|
||||||
* @param _uid is the uid for which the callback should be registered.
|
|
||||||
* @param _callback is the callback which should get called.
|
|
||||||
* @param _context is an optional parameter which can
|
|
||||||
*/
|
|
||||||
dataRegisterUID: function (_uid, _callback, _context) {},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unregisters the intrest of updates for a certain data uid.
|
|
||||||
*
|
|
||||||
* @param _uid is the data uid for which the callbacks should be
|
|
||||||
* unregistered.
|
|
||||||
* @param _callback specifies the specific callback that should be
|
|
||||||
* unregistered. If it evaluates to false, all callbacks (or those
|
|
||||||
* matching the optionally given context) are removed.
|
|
||||||
* @param _context specifies the callback context that should be
|
|
||||||
* unregistered. If it evaluates to false, all callbacks (or those
|
|
||||||
* matching the optionally given callback function) are removed.
|
|
||||||
*/
|
|
||||||
dataUnregisterUID: function (_uid, _callback, _context) {}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
100
api/js/etemplate/et2_dataview_interfaces.ts
Normal file
100
api/js/etemplate/et2_dataview_interfaces.ts
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
/**
|
||||||
|
* EGroupware eTemplate2 - Contains interfaces used inside the dataview
|
||||||
|
*
|
||||||
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||||
|
* @package etemplate
|
||||||
|
* @subpackage dataview
|
||||||
|
* @link http://www.egroupware.org
|
||||||
|
* @author Andreas Stöckel
|
||||||
|
* @copyright Stylite 2011
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*egw:uses
|
||||||
|
et2_core_inheritance;
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface et2_dataview_IInvalidatable
|
||||||
|
{
|
||||||
|
|
||||||
|
invalidate()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface et2_dataview_IViewRange
|
||||||
|
{
|
||||||
|
|
||||||
|
setViewRange(_range)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface a data provider has to implement. The data provider functions are
|
||||||
|
* called by the et2_dataview_controller class. The data provider basically acts
|
||||||
|
* like the egw api egw_data extension, but some etemplate specific stuff has
|
||||||
|
* been stripped away -- the implementation (for the nextmatch widget that is
|
||||||
|
* et2_extension_nextmatch_dataprovider) has to take care of that.
|
||||||
|
*/
|
||||||
|
export interface et2_IDataProvider
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function is used by the et2_dataview_controller to fetch data for
|
||||||
|
* a certain range. The et2_dataview_controller provides data which allows
|
||||||
|
* to only update elements which really have changed.
|
||||||
|
*
|
||||||
|
* @param _queriedRange is an object of the following form:
|
||||||
|
* {
|
||||||
|
* start: <START INDEX>,
|
||||||
|
* num_rows: <COUNT OF ENTRIES>
|
||||||
|
* }
|
||||||
|
* @param _knownRange is an array of the above form and informs the
|
||||||
|
* implementation which range is already known to the client. This parameter
|
||||||
|
* may be null in order to indicate that the client currently has no valid
|
||||||
|
* data.
|
||||||
|
* @param _lastModification is the last timestamp that was returned from the
|
||||||
|
* data provider and for which the client has data. It may be null in order
|
||||||
|
* to indicate, that the client currently has no data or needs a complete
|
||||||
|
* refresh.
|
||||||
|
* @param _callback is the function that should get called, once the data
|
||||||
|
* is available. The data passed to the callback function has the
|
||||||
|
* following form:
|
||||||
|
* {
|
||||||
|
* order: [uid, ...],
|
||||||
|
* total: <TOTAL COUNT>,
|
||||||
|
* lastModification: <LAST MODIFICATION TIMESTAMP>
|
||||||
|
* }
|
||||||
|
* @param _context is the context in which the callback function will get
|
||||||
|
* called.
|
||||||
|
*/
|
||||||
|
dataFetch (_queriedRange : {start: number, num_rows:number}, _lastModification, _callback : Function, _context : object)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers the intrest in a certain uid for a callback function. If
|
||||||
|
* the data for that uid changes or gets loaded, the given callback
|
||||||
|
* function is called. If the data for the given uid is available at the
|
||||||
|
* time of registering the callback, the callback is called immediately.
|
||||||
|
*
|
||||||
|
* @param _uid is the uid for which the callback should be registered.
|
||||||
|
* @param _callback is the callback which should get called.
|
||||||
|
* @param _context is an optional parameter which can
|
||||||
|
*/
|
||||||
|
dataRegisterUID (_uid : string, _callback : Function, _context : object)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregisters the intrest of updates for a certain data uid.
|
||||||
|
*
|
||||||
|
* @param _uid is the data uid for which the callbacks should be
|
||||||
|
* unregistered.
|
||||||
|
* @param _callback specifies the specific callback that should be
|
||||||
|
* unregistered. If it evaluates to false, all callbacks (or those
|
||||||
|
* matching the optionally given context) are removed.
|
||||||
|
* @param _context specifies the callback context that should be
|
||||||
|
* unregistered. If it evaluates to false, all callbacks (or those
|
||||||
|
* matching the optionally given callback function) are removed.
|
||||||
|
*/
|
||||||
|
dataUnregisterUID (_uid : string, _callback : Function, _context : object)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
|||||||
|
"use strict";
|
||||||
/**
|
/**
|
||||||
* EGroupware eTemplate2 - dataview code
|
* EGroupware eTemplate2 - dataview code
|
||||||
*
|
*
|
||||||
@ -9,12 +10,7 @@
|
|||||||
* @copyright Stylite 2012
|
* @copyright Stylite 2012
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
/*egw:uses
|
|
||||||
/vendor/bower-asset/jquery/dist/jquery.js;
|
|
||||||
et2_dataview_interfaces;
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The et2_dataview_container class is the main object each dataview consits of.
|
* The et2_dataview_container class is the main object each dataview consits of.
|
||||||
* Each row, spacer as well as the grid itself are containers. A container is
|
* Each row, spacer as well as the grid itself are containers. A container is
|
||||||
@ -31,8 +27,7 @@
|
|||||||
*
|
*
|
||||||
* @augments Class
|
* @augments Class
|
||||||
*/
|
*/
|
||||||
var et2_dataview_container = (function(){ "use strict"; return Class.extend(et2_dataview_IInvalidatable,
|
var et2_dataview_container = /** @class */ (function () {
|
||||||
{
|
|
||||||
/**
|
/**
|
||||||
* Initializes the container object.
|
* Initializes the container object.
|
||||||
*
|
*
|
||||||
@ -40,37 +35,31 @@ var et2_dataview_container = (function(){ "use strict"; return Class.extend(et2_
|
|||||||
* interface. _parent may not be null.
|
* interface. _parent may not be null.
|
||||||
* @memberOf et2_dataview_container
|
* @memberOf et2_dataview_container
|
||||||
*/
|
*/
|
||||||
init: function(_parent) {
|
function et2_dataview_container(_parent) {
|
||||||
// Copy the given invalidation element
|
// Copy the given invalidation element
|
||||||
this._parent = _parent;
|
this._parent = _parent;
|
||||||
|
this._nodes = [];
|
||||||
this._nodes = []; // contains all DOM-Nodes this container exists of
|
this._inTree = false;
|
||||||
this._inTree = false; //
|
|
||||||
this._attachData = { "node": null, "prepend": false };
|
this._attachData = { "node": null, "prepend": false };
|
||||||
this._destroyCallback = null;
|
this._destroyCallback = null;
|
||||||
this._destroyContext = null;
|
this._destroyContext = null;
|
||||||
|
this._height = -1;
|
||||||
this._height = false;
|
|
||||||
this._index = 0;
|
this._index = 0;
|
||||||
this._top = 0;
|
this._top = 0;
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroys this container. Classes deriving from et2_dataview_container
|
* Destroys this container. Classes deriving from et2_dataview_container
|
||||||
* should override this method and take care of unregistering all event
|
* should override this method and take care of unregistering all event
|
||||||
* handlers etc.
|
* handlers etc.
|
||||||
*/
|
*/
|
||||||
destroy: function() {
|
et2_dataview_container.prototype.destroy = function () {
|
||||||
// Remove the nodes from the tree
|
// Remove the nodes from the tree
|
||||||
this.removeFromTree();
|
this.removeFromTree();
|
||||||
|
|
||||||
// Call the callback function (if one is registered)
|
// Call the callback function (if one is registered)
|
||||||
if (this._destroyCallback)
|
if (this._destroyCallback) {
|
||||||
{
|
|
||||||
this._destroyCallback.call(this._destroyContext, this);
|
this._destroyCallback.call(this._destroyContext, this);
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the "destroyCallback" -- the given function gets called whenever
|
* Sets the "destroyCallback" -- the given function gets called whenever
|
||||||
* the container is destroyed. This instance is passed as an parameter to
|
* the container is destroyed. This instance is passed as an parameter to
|
||||||
@ -79,11 +68,10 @@ var et2_dataview_container = (function(){ "use strict"; return Class.extend(et2_
|
|||||||
* @param {function} _callback
|
* @param {function} _callback
|
||||||
* @param {object} _context
|
* @param {object} _context
|
||||||
*/
|
*/
|
||||||
setDestroyCallback: function(_callback, _context) {
|
et2_dataview_container.prototype.setDestroyCallback = function (_callback, _context) {
|
||||||
this._destroyCallback = _callback;
|
this._destroyCallback = _callback;
|
||||||
this._destroyContext = _context;
|
this._destroyContext = _context;
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inserts all container nodes into the DOM tree after or before the given
|
* Inserts all container nodes into the DOM tree after or before the given
|
||||||
* element.
|
* element.
|
||||||
@ -94,163 +82,124 @@ var et2_dataview_container = (function(){ "use strict"; return Class.extend(et2_
|
|||||||
* or after the given node. Inserting before is needed for inserting the
|
* or after the given node. Inserting before is needed for inserting the
|
||||||
* first element in front of an spacer.
|
* first element in front of an spacer.
|
||||||
*/
|
*/
|
||||||
insertIntoTree: function(_node, _prepend) {
|
et2_dataview_container.prototype.insertIntoTree = function (_node, _prepend) {
|
||||||
|
if (!this._inTree && _node != null && this._nodes.length > 0) {
|
||||||
if (!this._inTree && _node != null && this._nodes.length > 0)
|
|
||||||
{
|
|
||||||
// Store the parent node and indicate that this element is now in
|
// Store the parent node and indicate that this element is now in
|
||||||
// the tree.
|
// the tree.
|
||||||
this._attachData = {"node": _node, "prepend": _prepend};
|
this._attachData = { node: _node, prepend: _prepend };
|
||||||
this._inTree = true;
|
this._inTree = true;
|
||||||
|
for (var i = 0; i < this._nodes.length; i++) {
|
||||||
for (var i = 0; i < this._nodes.length; i++)
|
if (i == 0) {
|
||||||
{
|
if (_prepend) {
|
||||||
if (i == 0)
|
|
||||||
{
|
|
||||||
if (_prepend)
|
|
||||||
{
|
|
||||||
_node.before(this._nodes[0]);
|
_node.before(this._nodes[0]);
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
_node.after(this._nodes[0]);
|
_node.after(this._nodes[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
// Insert all following nodes after the previous node
|
// Insert all following nodes after the previous node
|
||||||
this._nodes[i - 1].after(this._nodes[i]);
|
this._nodes[i - 1].after(this._nodes[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invalidate this element in order to update the height of the
|
// Invalidate this element in order to update the height of the
|
||||||
// parent
|
// parent
|
||||||
this.invalidate();
|
this.invalidate();
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes all container nodes from the tree.
|
* Removes all container nodes from the tree.
|
||||||
*/
|
*/
|
||||||
removeFromTree: function() {
|
et2_dataview_container.prototype.removeFromTree = function () {
|
||||||
if (this._inTree)
|
if (this._inTree) {
|
||||||
{
|
|
||||||
// Call the jQuery remove function to remove all nodes from the tree
|
// Call the jQuery remove function to remove all nodes from the tree
|
||||||
// again.
|
// again.
|
||||||
for (var i = 0; i < this._nodes.length; i++)
|
for (var i = 0; i < this._nodes.length; i++) {
|
||||||
{
|
|
||||||
this._nodes[i].remove();
|
this._nodes[i].remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset the "attachData"
|
// Reset the "attachData"
|
||||||
this._inTree = false;
|
this._inTree = false;
|
||||||
this._attachData = { "node": null, "prepend": false };
|
this._attachData = { "node": null, "prepend": false };
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Appends a node to the container.
|
* Appends a node to the container.
|
||||||
*
|
*
|
||||||
* @param _node is the DOM-Node which should be appended.
|
* @param _node is the DOM-Node which should be appended.
|
||||||
*/
|
*/
|
||||||
appendNode: function(_node) {
|
et2_dataview_container.prototype.appendNode = function (_node) {
|
||||||
// Add the given node to the "nodes" array
|
// Add the given node to the "nodes" array
|
||||||
this._nodes.push(_node);
|
this._nodes.push(_node);
|
||||||
|
|
||||||
// If the container is already in the tree, attach the given node to the
|
// If the container is already in the tree, attach the given node to the
|
||||||
// tree.
|
// tree.
|
||||||
if (this._inTree)
|
if (this._inTree) {
|
||||||
{
|
if (this._nodes.length === 1) {
|
||||||
if (this._nodes.length === 1)
|
if (this._attachData.prepend) {
|
||||||
{
|
|
||||||
if (this._attachData.prepend)
|
|
||||||
{
|
|
||||||
this._attachData.node.before(_node);
|
this._attachData.node.before(_node);
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
this._attachData.node.after(_node);
|
this._attachData.node.after(_node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
this._nodes[this._nodes.length - 2].after(_node);
|
this._nodes[this._nodes.length - 2].after(_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.invalidate();
|
this.invalidate();
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a certain node from the container
|
* Removes a certain node from the container
|
||||||
*
|
*
|
||||||
* @param {DOMElement} _node
|
* @param {HTMLElement} _node
|
||||||
*/
|
*/
|
||||||
removeNode: function(_node) {
|
et2_dataview_container.prototype.removeNode = function (_node) {
|
||||||
// Get the index of the node in the nodes array
|
// Get the index of the node in the nodes array
|
||||||
var idx = this._nodes.indexOf(_node);
|
var idx = this._nodes.indexOf(_node);
|
||||||
|
if (idx >= 0) {
|
||||||
if (idx >= 0)
|
|
||||||
{
|
|
||||||
// Remove the node if the container is currently attached
|
// Remove the node if the container is currently attached
|
||||||
if (this._inTree)
|
if (this._inTree) {
|
||||||
{
|
|
||||||
_node.parentNode.removeChild(_node);
|
_node.parentNode.removeChild(_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the node from the nodes array
|
// Remove the node from the nodes array
|
||||||
this._nodes.splice(idx, 1);
|
this._nodes.splice(idx, 1);
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the last node of the container - new nodes have to be appended
|
* Returns the last node of the container - new nodes have to be appended
|
||||||
* after it.
|
* after it.
|
||||||
*/
|
*/
|
||||||
getLastNode: function() {
|
et2_dataview_container.prototype.getLastNode = function () {
|
||||||
|
if (this._nodes.length > 0) {
|
||||||
if (this._nodes.length > 0)
|
|
||||||
{
|
|
||||||
return this._nodes[this._nodes.length - 1];
|
return this._nodes[this._nodes.length - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the first node of the container.
|
* Returns the first node of the container.
|
||||||
*/
|
*/
|
||||||
getFirstNode: function() {
|
et2_dataview_container.prototype.getFirstNode = function () {
|
||||||
return this._nodes.length > 0 ? this._nodes[0] : null;
|
return this._nodes.length > 0 ? this._nodes[0] : null;
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the accumulated height of all container nodes. Only visible nodes
|
* Returns the accumulated height of all container nodes. Only visible nodes
|
||||||
* (without "display: none" etc.) are taken into account.
|
* (without "display: none" etc.) are taken into account.
|
||||||
*/
|
*/
|
||||||
getHeight: function() {
|
et2_dataview_container.prototype.getHeight = function () {
|
||||||
if (this._height === false && this._inTree)
|
if (this._height === -1 && this._inTree) {
|
||||||
{
|
|
||||||
this._height = 0;
|
this._height = 0;
|
||||||
|
|
||||||
// Setting this before measuring height helps with issues getting the
|
// Setting this before measuring height helps with issues getting the
|
||||||
// wrong height due to margins & collapsed borders
|
// wrong height due to margins & collapsed borders
|
||||||
this.tr.css('display', 'block');
|
this.tr.css('display', 'block');
|
||||||
|
|
||||||
// Increment the height value for each visible container node
|
// Increment the height value for each visible container node
|
||||||
for (var i = 0; i < this._nodes.length; i++)
|
for (var i = 0; i < this._nodes.length; i++) {
|
||||||
{
|
if (et2_dataview_container._isVisible(this._nodes[i][0])) {
|
||||||
if (this._isVisible(this._nodes[i][0]))
|
this._height += et2_dataview_container._nodeHeight(this._nodes[i][0]);
|
||||||
{
|
|
||||||
this._height += this._nodeHeight(this._nodes[i][0]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.tr.css('display', '');
|
this.tr.css('display', '');
|
||||||
}
|
}
|
||||||
|
return (this._height === -1) ? 0 : this._height;
|
||||||
return this._height === false ? 0 : this._height;
|
};
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a datastructure containing information used for calculating the
|
* Returns a datastructure containing information used for calculating the
|
||||||
* average row height of a grid.
|
* average row height of a grid.
|
||||||
@ -260,88 +209,73 @@ var et2_dataview_container = (function(){ "use strict"; return Class.extend(et2_
|
|||||||
* avgCount: <the element count this calculation was based on>
|
* avgCount: <the element count this calculation was based on>
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
getAvgHeightData: function() {
|
et2_dataview_container.prototype.getAvgHeightData = function () {
|
||||||
return {
|
return {
|
||||||
"avgHeight": this.getHeight(),
|
"avgHeight": this.getHeight(),
|
||||||
"avgCount": 1
|
"avgCount": 1
|
||||||
};
|
};
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the previously set "pixel top" of the container.
|
* Returns the previously set "pixel top" of the container.
|
||||||
*/
|
*/
|
||||||
getTop: function() {
|
et2_dataview_container.prototype.getTop = function () {
|
||||||
return this._top;
|
return this._top;
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the "pixel bottom" of the container.
|
* Returns the "pixel bottom" of the container.
|
||||||
*/
|
*/
|
||||||
getBottom: function() {
|
et2_dataview_container.prototype.getBottom = function () {
|
||||||
return this._top + this.getHeight();
|
return this._top + this.getHeight();
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the range of the element.
|
* Returns the range of the element.
|
||||||
*/
|
*/
|
||||||
getRange: function() {
|
et2_dataview_container.prototype.getRange = function () {
|
||||||
return et2_bounds(this.getTop(), this.getBottom());
|
return et2_bounds(this.getTop(), this.getBottom());
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the index of the element.
|
* Returns the index of the element.
|
||||||
*/
|
*/
|
||||||
getIndex: function() {
|
et2_dataview_container.prototype.getIndex = function () {
|
||||||
return this._index;
|
return this._index;
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns how many elements this container represents.
|
* Returns how many elements this container represents.
|
||||||
*/
|
*/
|
||||||
getCount: function() {
|
et2_dataview_container.prototype.getCount = function () {
|
||||||
return 1;
|
return 1;
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the top of the element.
|
* Sets the top of the element.
|
||||||
*
|
*
|
||||||
* @param {number} _value
|
* @param {number} _value
|
||||||
*/
|
*/
|
||||||
setTop: function(_value) {
|
et2_dataview_container.prototype.setTop = function (_value) {
|
||||||
this._top = _value;
|
this._top = _value;
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the index of the element.
|
* Sets the index of the element.
|
||||||
*
|
*
|
||||||
* @param {number} _value
|
* @param {number} _value
|
||||||
*/
|
*/
|
||||||
setIndex: function(_value) {
|
et2_dataview_container.prototype.setIndex = function (_value) {
|
||||||
this._index = _value;
|
this._index = _value;
|
||||||
},
|
};
|
||||||
|
|
||||||
/* -- et2_dataview_IInvalidatable -- */
|
/* -- et2_dataview_IInvalidatable -- */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Broadcasts an invalidation through the container tree. Marks the own
|
* Broadcasts an invalidation through the container tree. Marks the own
|
||||||
* height as invalid.
|
* height as invalid.
|
||||||
*/
|
*/
|
||||||
invalidate: function() {
|
et2_dataview_container.prototype.invalidate = function () {
|
||||||
// Abort if this element is already marked as invalid.
|
// Abort if this element is already marked as invalid.
|
||||||
if (this._height !== false)
|
if (this._height !== -1) {
|
||||||
{
|
|
||||||
// Delete the own, probably computed height
|
// Delete the own, probably computed height
|
||||||
this._height = false;
|
this._height = -1;
|
||||||
|
|
||||||
// Broadcast the invalidation to the parent element
|
// Broadcast the invalidation to the parent element
|
||||||
this._parent.invalidate();
|
this._parent.invalidate();
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
|
|
||||||
|
|
||||||
/* -- PRIVATE FUNCTIONS -- */
|
/* -- PRIVATE FUNCTIONS -- */
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to check whether an element is visible or not (non recursive).
|
* Used to check whether an element is visible or not (non recursive).
|
||||||
*
|
*
|
||||||
@ -349,34 +283,31 @@ var et2_dataview_container = (function(){ "use strict"; return Class.extend(et2_
|
|||||||
* only checked whether some stylesheet makes the element invisible, not if
|
* only checked whether some stylesheet makes the element invisible, not if
|
||||||
* the given object is actually inside the DOM.
|
* the given object is actually inside the DOM.
|
||||||
*/
|
*/
|
||||||
_isVisible: function(_obj) {
|
et2_dataview_container._isVisible = function (_obj) {
|
||||||
|
|
||||||
// Check whether the element is localy invisible
|
// Check whether the element is localy invisible
|
||||||
if (_obj.style && (_obj.style.display === "none"
|
if (_obj.style && (_obj.style.display === "none"
|
||||||
|| _obj.style.visiblity === "none"))
|
|| _obj.style.visibility === "none")) {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the computed style of the element
|
// Get the computed style of the element
|
||||||
var style = window.getComputedStyle ? window.getComputedStyle(_obj, null)
|
var style = window.getComputedStyle ? window.getComputedStyle(_obj, null)
|
||||||
|
// @ts-ignore
|
||||||
: _obj.currentStyle;
|
: _obj.currentStyle;
|
||||||
if (style.display === "none" || style.visibility === "none")
|
if (style.display === "none" || style.visibility === "none") {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the height of a node in pixels and zero if the element is not
|
* Returns the height of a node in pixels and zero if the element is not
|
||||||
* visible. The height is clamped to positive values.
|
* visible. The height is clamped to positive values.
|
||||||
*
|
*
|
||||||
* @param {DOMElement} _node
|
* @param {HTMLElement} _node
|
||||||
*/
|
*/
|
||||||
_nodeHeight: function(_node)
|
et2_dataview_container._nodeHeight = function (_node) {
|
||||||
{
|
|
||||||
return _node.offsetHeight;
|
return _node.offsetHeight;
|
||||||
}
|
};
|
||||||
});}).call(this);
|
return et2_dataview_container;
|
||||||
|
}());
|
||||||
|
exports.et2_dataview_container = et2_dataview_container;
|
||||||
|
//# sourceMappingURL=et2_dataview_view_container.js.map
|
421
api/js/etemplate/et2_dataview_view_container.ts
Normal file
421
api/js/etemplate/et2_dataview_view_container.ts
Normal file
@ -0,0 +1,421 @@
|
|||||||
|
/**
|
||||||
|
* EGroupware eTemplate2 - dataview code
|
||||||
|
*
|
||||||
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||||
|
* @package etemplate
|
||||||
|
* @subpackage dataview
|
||||||
|
* @link http://www.egroupware.org
|
||||||
|
* @author Andreas Stöckel
|
||||||
|
* @copyright Stylite 2012
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*egw:uses
|
||||||
|
/vendor/bower-asset/jquery/dist/jquery.js;
|
||||||
|
et2_dataview_interfaces;
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {et2_dataview_IInvalidatable} from "./et2_dataview_interfaces";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The et2_dataview_container class is the main object each dataview consits of.
|
||||||
|
* Each row, spacer as well as the grid itself are containers. A container is
|
||||||
|
* described by its parent element and a certain height. On the DOM-Level a
|
||||||
|
* container may consist of multiple "tr" nodes, which are treated as a unit.
|
||||||
|
* Some containers (like grid containers) are capable of managing a set of child
|
||||||
|
* containers. Each container can indicate, that it thinks that it's height
|
||||||
|
* might have changed. In that case it informs its parent element about that.
|
||||||
|
* The only requirement for the parent element is, that it implements the
|
||||||
|
* et2_dataview_IInvalidatable interface.
|
||||||
|
* A container does not know where it resides inside the grid, or whether it is
|
||||||
|
* currently visible or not -- this information is efficiently managed by the
|
||||||
|
* et2_dataview_grid container.
|
||||||
|
*
|
||||||
|
* @augments Class
|
||||||
|
*/
|
||||||
|
export class et2_dataview_container implements et2_dataview_IInvalidatable
|
||||||
|
{
|
||||||
|
protected _parent: any;
|
||||||
|
|
||||||
|
// contains all DOM-Nodes this container exists of
|
||||||
|
private _nodes: any[];
|
||||||
|
private _inTree: boolean;
|
||||||
|
|
||||||
|
private _attachData: { node: JQuery; prepend: boolean };
|
||||||
|
|
||||||
|
private _destroyCallback: Function;
|
||||||
|
_destroyContext: any;
|
||||||
|
|
||||||
|
private _height: number;
|
||||||
|
private _index: number;
|
||||||
|
private _top: number;
|
||||||
|
|
||||||
|
protected tr: any;
|
||||||
|
/**
|
||||||
|
* Initializes the container object.
|
||||||
|
*
|
||||||
|
* @param _parent is an object which implements the IInvalidatable
|
||||||
|
* interface. _parent may not be null.
|
||||||
|
* @memberOf et2_dataview_container
|
||||||
|
*/
|
||||||
|
constructor(_parent)
|
||||||
|
{
|
||||||
|
// Copy the given invalidation element
|
||||||
|
this._parent = _parent;
|
||||||
|
|
||||||
|
this._nodes = [];
|
||||||
|
this._inTree = false;
|
||||||
|
this._attachData = {"node": null, "prepend": false};
|
||||||
|
this._destroyCallback = null;
|
||||||
|
this._destroyContext = null;
|
||||||
|
|
||||||
|
this._height = -1;
|
||||||
|
this._index = 0;
|
||||||
|
this._top = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroys this container. Classes deriving from et2_dataview_container
|
||||||
|
* should override this method and take care of unregistering all event
|
||||||
|
* handlers etc.
|
||||||
|
*/
|
||||||
|
destroy()
|
||||||
|
{
|
||||||
|
// Remove the nodes from the tree
|
||||||
|
this.removeFromTree();
|
||||||
|
|
||||||
|
// Call the callback function (if one is registered)
|
||||||
|
if (this._destroyCallback)
|
||||||
|
{
|
||||||
|
this._destroyCallback.call(this._destroyContext, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the "destroyCallback" -- the given function gets called whenever
|
||||||
|
* the container is destroyed. This instance is passed as an parameter to
|
||||||
|
* the callback.
|
||||||
|
*
|
||||||
|
* @param {function} _callback
|
||||||
|
* @param {object} _context
|
||||||
|
*/
|
||||||
|
setDestroyCallback(_callback : Function, _context : object) {
|
||||||
|
this._destroyCallback = _callback;
|
||||||
|
this._destroyContext = _context;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts all container nodes into the DOM tree after or before the given
|
||||||
|
* element.
|
||||||
|
*
|
||||||
|
* @param _node is the node after/before which the container "tr"s should
|
||||||
|
* get inserted. _node should be a simple DOM node, not a jQuery object.
|
||||||
|
* @param _prepend specifies whether the container should be inserted before
|
||||||
|
* or after the given node. Inserting before is needed for inserting the
|
||||||
|
* first element in front of an spacer.
|
||||||
|
*/
|
||||||
|
insertIntoTree(_node: JQuery, _prepend: boolean)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!this._inTree && _node != null && this._nodes.length > 0)
|
||||||
|
{
|
||||||
|
// Store the parent node and indicate that this element is now in
|
||||||
|
// the tree.
|
||||||
|
this._attachData = {node: _node, prepend: _prepend};
|
||||||
|
this._inTree = true;
|
||||||
|
|
||||||
|
for (let i = 0; i < this._nodes.length; i++)
|
||||||
|
{
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
if (_prepend)
|
||||||
|
{
|
||||||
|
_node.before(this._nodes[0]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_node.after(this._nodes[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Insert all following nodes after the previous node
|
||||||
|
this._nodes[i - 1].after(this._nodes[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invalidate this element in order to update the height of the
|
||||||
|
// parent
|
||||||
|
this.invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes all container nodes from the tree.
|
||||||
|
*/
|
||||||
|
removeFromTree()
|
||||||
|
{
|
||||||
|
if (this._inTree)
|
||||||
|
{
|
||||||
|
// Call the jQuery remove function to remove all nodes from the tree
|
||||||
|
// again.
|
||||||
|
for (let i = 0; i < this._nodes.length; i++)
|
||||||
|
{
|
||||||
|
this._nodes[i].remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset the "attachData"
|
||||||
|
this._inTree = false;
|
||||||
|
this._attachData = {"node": null, "prepend": false};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends a node to the container.
|
||||||
|
*
|
||||||
|
* @param _node is the DOM-Node which should be appended.
|
||||||
|
*/
|
||||||
|
appendNode(_node : JQuery | HTMLElement)
|
||||||
|
{
|
||||||
|
// Add the given node to the "nodes" array
|
||||||
|
this._nodes.push(_node);
|
||||||
|
|
||||||
|
// If the container is already in the tree, attach the given node to the
|
||||||
|
// tree.
|
||||||
|
if (this._inTree)
|
||||||
|
{
|
||||||
|
if (this._nodes.length === 1)
|
||||||
|
{
|
||||||
|
if (this._attachData.prepend)
|
||||||
|
{
|
||||||
|
this._attachData.node.before(_node);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this._attachData.node.after(_node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this._nodes[this._nodes.length - 2].after(_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a certain node from the container
|
||||||
|
*
|
||||||
|
* @param {HTMLElement} _node
|
||||||
|
*/
|
||||||
|
removeNode(_node: HTMLElement)
|
||||||
|
{
|
||||||
|
// Get the index of the node in the nodes array
|
||||||
|
const idx = this._nodes.indexOf(_node);
|
||||||
|
|
||||||
|
if (idx >= 0)
|
||||||
|
{
|
||||||
|
// Remove the node if the container is currently attached
|
||||||
|
if (this._inTree)
|
||||||
|
{
|
||||||
|
_node.parentNode.removeChild(_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the node from the nodes array
|
||||||
|
this._nodes.splice(idx, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the last node of the container - new nodes have to be appended
|
||||||
|
* after it.
|
||||||
|
*/
|
||||||
|
getLastNode()
|
||||||
|
{
|
||||||
|
|
||||||
|
if (this._nodes.length > 0)
|
||||||
|
{
|
||||||
|
return this._nodes[this._nodes.length - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the first node of the container.
|
||||||
|
*/
|
||||||
|
getFirstNode()
|
||||||
|
{
|
||||||
|
return this._nodes.length > 0 ? this._nodes[0] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the accumulated height of all container nodes. Only visible nodes
|
||||||
|
* (without "display: none" etc.) are taken into account.
|
||||||
|
*/
|
||||||
|
getHeight()
|
||||||
|
{
|
||||||
|
if (this._height === -1 && this._inTree)
|
||||||
|
{
|
||||||
|
this._height = 0;
|
||||||
|
|
||||||
|
// Setting this before measuring height helps with issues getting the
|
||||||
|
// wrong height due to margins & collapsed borders
|
||||||
|
this.tr.css('display','block');
|
||||||
|
|
||||||
|
// Increment the height value for each visible container node
|
||||||
|
for (let i = 0; i < this._nodes.length; i++)
|
||||||
|
{
|
||||||
|
if (et2_dataview_container._isVisible(this._nodes[i][0]))
|
||||||
|
{
|
||||||
|
this._height += et2_dataview_container._nodeHeight(this._nodes[i][0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.tr.css('display','');
|
||||||
|
}
|
||||||
|
|
||||||
|
return ( this._height === -1 ) ? 0 : this._height;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a datastructure containing information used for calculating the
|
||||||
|
* average row height of a grid.
|
||||||
|
* The datastructure has the
|
||||||
|
* {
|
||||||
|
* avgHeight: <the calculated average height of this element>,
|
||||||
|
* avgCount: <the element count this calculation was based on>
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
getAvgHeightData()
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
"avgHeight": this.getHeight(),
|
||||||
|
"avgCount": 1
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the previously set "pixel top" of the container.
|
||||||
|
*/
|
||||||
|
getTop()
|
||||||
|
{
|
||||||
|
return this._top;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the "pixel bottom" of the container.
|
||||||
|
*/
|
||||||
|
getBottom()
|
||||||
|
{
|
||||||
|
return this._top + this.getHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the range of the element.
|
||||||
|
*/
|
||||||
|
getRange()
|
||||||
|
{
|
||||||
|
return et2_bounds(this.getTop(), this.getBottom());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the index of the element.
|
||||||
|
*/
|
||||||
|
getIndex()
|
||||||
|
{
|
||||||
|
return this._index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns how many elements this container represents.
|
||||||
|
*/
|
||||||
|
getCount()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the top of the element.
|
||||||
|
*
|
||||||
|
* @param {number} _value
|
||||||
|
*/
|
||||||
|
setTop(_value)
|
||||||
|
{
|
||||||
|
this._top = _value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the index of the element.
|
||||||
|
*
|
||||||
|
* @param {number} _value
|
||||||
|
*/
|
||||||
|
setIndex(_value)
|
||||||
|
{
|
||||||
|
this._index = _value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- et2_dataview_IInvalidatable -- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Broadcasts an invalidation through the container tree. Marks the own
|
||||||
|
* height as invalid.
|
||||||
|
*/
|
||||||
|
invalidate()
|
||||||
|
{
|
||||||
|
// Abort if this element is already marked as invalid.
|
||||||
|
if ( this._height !== -1)
|
||||||
|
{
|
||||||
|
// Delete the own, probably computed height
|
||||||
|
this._height = -1;
|
||||||
|
|
||||||
|
// Broadcast the invalidation to the parent element
|
||||||
|
this._parent.invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -- PRIVATE FUNCTIONS -- */
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to check whether an element is visible or not (non recursive).
|
||||||
|
*
|
||||||
|
* @param _obj is the element which should be checked for visibility, it is
|
||||||
|
* only checked whether some stylesheet makes the element invisible, not if
|
||||||
|
* the given object is actually inside the DOM.
|
||||||
|
*/
|
||||||
|
private static _isVisible(_obj : HTMLElement)
|
||||||
|
{
|
||||||
|
|
||||||
|
// Check whether the element is localy invisible
|
||||||
|
if (_obj.style && (_obj.style.display === "none"
|
||||||
|
|| _obj.style.visibility === "none"))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the computed style of the element
|
||||||
|
const style = window.getComputedStyle ? window.getComputedStyle(_obj, null)
|
||||||
|
// @ts-ignore
|
||||||
|
: _obj.currentStyle;
|
||||||
|
|
||||||
|
if (style.display === "none" || style.visibility === "none")
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the height of a node in pixels and zero if the element is not
|
||||||
|
* visible. The height is clamped to positive values.
|
||||||
|
*
|
||||||
|
* @param {HTMLElement} _node
|
||||||
|
*/
|
||||||
|
private static _nodeHeight(_node : HTMLElement)
|
||||||
|
{
|
||||||
|
return _node.offsetHeight;
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
1456
api/js/etemplate/et2_dataview_view_grid.ts
Normal file
1456
api/js/etemplate/et2_dataview_view_grid.ts
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
4058
api/js/etemplate/et2_extension_nextmatch.ts
Normal file
4058
api/js/etemplate/et2_extension_nextmatch.ts
Normal file
File diff suppressed because it is too large
Load Diff
18
api/js/etemplate/et2_types.d.ts
vendored
18
api/js/etemplate/et2_types.d.ts
vendored
@ -8,7 +8,9 @@ declare class et2_DOMWidget extends et2_widget{}
|
|||||||
declare class et2_baseWidget extends et2_DOMWidget{}
|
declare class et2_baseWidget extends et2_DOMWidget{}
|
||||||
declare class et2_valueWidget extends et2_baseWidget{}
|
declare class et2_valueWidget extends et2_baseWidget{}
|
||||||
declare class et2_inputWidget extends et2_valueWidget{
|
declare class et2_inputWidget extends et2_valueWidget{
|
||||||
getInputNode() : HTMLElement
|
getInputNode() : HTMLElement;
|
||||||
|
public set_value(value: string | object | number);
|
||||||
|
public getValue() : any;
|
||||||
}
|
}
|
||||||
declare class et2_tabbox extends et2_valueWidget {
|
declare class et2_tabbox extends et2_valueWidget {
|
||||||
tabData : any;
|
tabData : any;
|
||||||
@ -49,7 +51,13 @@ declare var et2_dataview_row : any;
|
|||||||
declare var et2_dataview_rowProvider : any;
|
declare var et2_dataview_rowProvider : any;
|
||||||
declare var et2_dataview_spacer : any;
|
declare var et2_dataview_spacer : any;
|
||||||
declare var et2_dataview_tile : any;
|
declare var et2_dataview_tile : any;
|
||||||
declare var et2_customfields_list : any;
|
declare class et2_customfields_list extends et2_valueWidget {
|
||||||
|
constructor(_parent: any, _attrs: WidgetConfig, object: object);
|
||||||
|
|
||||||
|
public static readonly prefix : string;
|
||||||
|
public customfields : any;
|
||||||
|
set_visible(visible : boolean);
|
||||||
|
}
|
||||||
declare var et2_INextmatchHeader : any;
|
declare var et2_INextmatchHeader : any;
|
||||||
declare var et2_INextmatchSortable : any;
|
declare var et2_INextmatchSortable : any;
|
||||||
declare var et2_nextmatch : any;
|
declare var et2_nextmatch : any;
|
||||||
@ -116,12 +124,16 @@ declare var et2_selectAccount_ro : any;
|
|||||||
declare class et2_selectbox extends et2_inputWidget {
|
declare class et2_selectbox extends et2_inputWidget {
|
||||||
protected options : any;
|
protected options : any;
|
||||||
public createInputWidget();
|
public createInputWidget();
|
||||||
|
public set_multiple(boolean);
|
||||||
|
public set_select_options(options: any);
|
||||||
}
|
}
|
||||||
declare var et2_selectbox_ro : any;
|
declare var et2_selectbox_ro : any;
|
||||||
declare var et2_menulist : any;
|
declare var et2_menulist : any;
|
||||||
declare var et2_split : any;
|
declare var et2_split : any;
|
||||||
declare var et2_styles : any;
|
declare var et2_styles : any;
|
||||||
declare class et2_taglist extends et2_selectbox {}
|
declare class et2_taglist extends et2_selectbox {
|
||||||
|
protected div : JQuery;
|
||||||
|
}
|
||||||
declare var et2_taglist_account : any;
|
declare var et2_taglist_account : any;
|
||||||
declare var et2_taglist_email : any;
|
declare var et2_taglist_email : any;
|
||||||
declare var et2_taglist_category : any;
|
declare var et2_taglist_category : any;
|
||||||
|
Loading…
Reference in New Issue
Block a user