mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-12-23 07:09:20 +01:00
First version of the dataview which does... well... 'something' at least (currently shows dummy rows with non-etemplate content) Need to cleanup code and test auto hiding of rows (code is actually there)
This commit is contained in:
parent
4088300b57
commit
035a4d369f
@ -10,14 +10,26 @@
|
|||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
"use strict"
|
||||||
|
|
||||||
|
/*egw:uses
|
||||||
|
et2_core_inheritance;
|
||||||
|
*/
|
||||||
|
|
||||||
var et2_dataview_IInvalidatable = new Interface({
|
var et2_dataview_IInvalidatable = new Interface({
|
||||||
|
|
||||||
invalidate: function();
|
invalidate: function() {}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
var et2_dataview_IDataRow = new Interface({
|
var et2_dataview_IDataRow = new Interface({
|
||||||
|
|
||||||
updateData: function(_data);
|
updateData: function(_data) {}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
var et2_dataview_IViewRange = new Interface({
|
||||||
|
|
||||||
|
setViewRange: function(_range) {}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -1,14 +1,17 @@
|
|||||||
/**
|
/**
|
||||||
* eGroupWare egw_action framework - egw action framework
|
* eGroupWare eTemplate2 - Class which contains a the columns model
|
||||||
*
|
*
|
||||||
* @link http://www.egroupware.org
|
|
||||||
* @author Andreas Stöckel <as@stylite.de>
|
|
||||||
* @copyright 2011 by Andreas Stöckel
|
|
||||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||||
* @package egw_action
|
* @package etemplate
|
||||||
|
* @subpackage dataview
|
||||||
|
* @link http://www.egroupware.org
|
||||||
|
* @author Andreas Stöckel
|
||||||
|
* @copyright Stylite 2011
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
"use strict"
|
||||||
|
|
||||||
/*egw:uses
|
/*egw:uses
|
||||||
et2_inheritance;
|
et2_inheritance;
|
||||||
*/
|
*/
|
||||||
|
53
etemplate/js/et2_dataview_model_dataProvider.js
Normal file
53
etemplate/js/et2_dataview_model_dataProvider.js
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/**
|
||||||
|
* eGroupWare eTemplate2 - Class which contains a the data model
|
||||||
|
*
|
||||||
|
* @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$
|
||||||
|
*/
|
||||||
|
|
||||||
|
"use strict"
|
||||||
|
|
||||||
|
/*egw:uses
|
||||||
|
et2_inheritance;
|
||||||
|
et2_dataview_interfaces;
|
||||||
|
*/
|
||||||
|
|
||||||
|
var et2_dataview_dataProvider = Class.extend({
|
||||||
|
|
||||||
|
getCount: function() {
|
||||||
|
return 1000;
|
||||||
|
},
|
||||||
|
|
||||||
|
registerDataRow: function(_idx, _dataRow) {
|
||||||
|
var row = {
|
||||||
|
"type": "dataRow",
|
||||||
|
"data": {
|
||||||
|
"ts_title": "Row " + _idx
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get a random value which is used to simulate network latency and time
|
||||||
|
// it needs to load the data.
|
||||||
|
var rnd = Math.round(Math.random() * 1000);
|
||||||
|
|
||||||
|
if (rnd < 200)
|
||||||
|
{
|
||||||
|
_dataRow.updateData(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.setTimeout(function() {_dataRow.updateData(row); },
|
||||||
|
Math.round(rnd / 2));
|
||||||
|
},
|
||||||
|
|
||||||
|
unregisterDataRow: function(_dataRow) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
@ -13,32 +13,189 @@
|
|||||||
"use strict"
|
"use strict"
|
||||||
|
|
||||||
/*egw:uses
|
/*egw:uses
|
||||||
|
jquery.jquery;
|
||||||
et2_dataview_interfaces;
|
et2_dataview_interfaces;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var et2_dataview_container = Class.extend({
|
var et2_dataview_container = Class.extend(et2_dataview_IInvalidatable, {
|
||||||
|
|
||||||
init: function(_data, _invalidationElem) {
|
/**
|
||||||
this._dataProvider = _data;
|
* Initializes the container object.
|
||||||
|
*
|
||||||
|
* @param _dataProvider is the data provider for the element
|
||||||
|
* @param _rowProvider is the "rowProvider" of the element
|
||||||
|
* @param _invalidationElem is the element of which the "invalidate" method
|
||||||
|
* will be called if the height of the elements changes. It has to
|
||||||
|
* implement the et2_dataview_IInvalidatable interface.
|
||||||
|
*/
|
||||||
|
init: function(_dataProvider, _rowProvider, _invalidationElem) {
|
||||||
|
this.dataProvider = _dataProvider;
|
||||||
|
this.rowProvider = _rowProvider;
|
||||||
this._invalidationElem = _invalidationElem;
|
this._invalidationElem = _invalidationElem;
|
||||||
|
|
||||||
this._node = null;
|
this._nodes = [];
|
||||||
|
this._inTree = false;
|
||||||
|
this._attachData = {"node": null, "prepend": false};
|
||||||
},
|
},
|
||||||
|
|
||||||
setJNode: function(_node) {
|
destroy: function() {
|
||||||
// Replace the old node with the new one
|
// Remove the nodes from the tree
|
||||||
if (this._node[0].parent)
|
this.removeFromTree();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter function which can be used to update the invalidation element.
|
||||||
|
*
|
||||||
|
* @param _invalidationElem is the element of which the "invalidate" method
|
||||||
|
* will be called if the height of the elements changes. It has to
|
||||||
|
* implement the et2_dataview_IInvalidatable interface.
|
||||||
|
*/
|
||||||
|
setInvalidationElement: function(_invalidationElem) {
|
||||||
|
this._invalidationElem = _invalidationElem;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts all container nodes into the DOM tree after the given element
|
||||||
|
*/
|
||||||
|
insertIntoTree: function(_afterNode, _prepend) {
|
||||||
|
if (!this._inTree && _afterNode != null)
|
||||||
{
|
{
|
||||||
this._node.replaceWith(_node);
|
for (var i = 0; i < this._nodes.length; i++)
|
||||||
|
{
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
if (_prepend)
|
||||||
|
{
|
||||||
|
_afterNode.prepend(this._nodes[i]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_afterNode.after(this._nodes[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Insert all following nodes after the previous node
|
||||||
|
this._nodes[i - 1].after(this._nodes[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the "attachData"
|
||||||
|
this._inTree = true;
|
||||||
|
this._attachData = {"node": _afterNode, "prepend": _prepend};
|
||||||
|
|
||||||
|
this.invalidate();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes all container nodes from the tree.
|
||||||
|
*/
|
||||||
|
removeFromTree: function() {
|
||||||
|
if (this._inTree)
|
||||||
|
{
|
||||||
|
// Call the jQuery remove function to remove all nodes from the tree
|
||||||
|
// again.
|
||||||
|
for (var 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 jQuery node to the container
|
||||||
|
*/
|
||||||
|
appendNode: function(_node) {
|
||||||
|
// 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 (_prepend)
|
||||||
|
{
|
||||||
|
this._attachData.node.prepend(this._nodes[0]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this._attachData.node.after(this._nodes[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this._nodes[_nodes.length - 2].after(_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.invalidate();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a jQuery node from the container
|
||||||
|
*/
|
||||||
|
removeNode: function(_node) {
|
||||||
|
// Get the index of the node in the nodes array
|
||||||
|
var idx = this._nodes.indexOf(_node);
|
||||||
|
|
||||||
|
if (idx >= 0)
|
||||||
|
{
|
||||||
|
// Remove the node if the container is currently attached
|
||||||
|
if (this._inTree)
|
||||||
|
{
|
||||||
|
_node.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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: function() {
|
||||||
|
|
||||||
|
if (this._nodes.length > 0)
|
||||||
|
{
|
||||||
|
return this._nodes[this._nodes.length - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
this._node = _node;
|
return null;
|
||||||
},
|
},
|
||||||
|
|
||||||
getJNode: function() {
|
/**
|
||||||
return this._node;
|
* Returns the accumulated height of all container nodes. Only visible nodes
|
||||||
|
* (without "display: none") are taken into account.
|
||||||
|
*/
|
||||||
|
getHeight: function() {
|
||||||
|
var height = 0;
|
||||||
|
|
||||||
|
if (this._inTree)
|
||||||
|
{
|
||||||
|
// Increment the height value for each visible container node
|
||||||
|
var self = this;
|
||||||
|
$j(this._nodes, ":visible").each(function() {
|
||||||
|
height += self._nodeHeight(this);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(height);
|
||||||
|
|
||||||
|
return height;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls the "invalidate" function of the connected invalidation element.
|
||||||
|
*/
|
||||||
invalidate: function() {
|
invalidate: function() {
|
||||||
this._invalidationElem.invalidate();
|
this._invalidationElem.invalidate();
|
||||||
}
|
}
|
||||||
@ -54,41 +211,33 @@ var et2_dataview_container = Class.extend({
|
|||||||
*/
|
*/
|
||||||
if ($j.browser.mozilla)
|
if ($j.browser.mozilla)
|
||||||
{
|
{
|
||||||
et2_dataview_container.prototype.getHeight = function()
|
et2_dataview_container.prototype._nodeHeight = function(_node)
|
||||||
{
|
{
|
||||||
if (this.node)
|
var height = 0;
|
||||||
|
// Firefox sometimes provides fractional pixel values - we are
|
||||||
|
// forced to use those - we can obtain the fractional pixel height
|
||||||
|
// by using the window.getComputedStyle function
|
||||||
|
var compStyle = getComputedStyle(_node, null);
|
||||||
|
if (compStyle)
|
||||||
{
|
{
|
||||||
// Firefox sometimes provides fractional pixel values - we are
|
var styleHeightStr = compStyle.getPropertyValue("height");
|
||||||
// forced to use those - we can obtain the fractional pixel height
|
height = parseFloat(styleHeightStr.substr(0,
|
||||||
// by using the window.getComputedStyle function
|
styleHeightStr.length - 2));
|
||||||
var compStyle = getComputedStyle(this._node, null);
|
|
||||||
if (compStyle)
|
if (isNaN(height) || height < 1)
|
||||||
{
|
{
|
||||||
var styleHeightStr = compStyle.getPropertyValue("height");
|
height = 0;
|
||||||
var height = parseFloat(styleHeightStr.substr(0, styleHeightStr.length - 2));
|
|
||||||
|
|
||||||
if (isNaN(height) || height < 1)
|
|
||||||
{
|
|
||||||
height = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return height;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
et2_dataview_container.prototype.getHeight = function()
|
et2_dataview_container.prototype._nodeHeight = function(_node)
|
||||||
{
|
{
|
||||||
if (this.node)
|
return $j(_node).outerHeight(true);
|
||||||
{
|
|
||||||
return this._node.offsetHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,24 +13,236 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
/*egw:uses
|
/*egw:uses
|
||||||
|
jquery.jquery;
|
||||||
|
et2_core_common;
|
||||||
|
et2_dataview_interfaces;
|
||||||
et2_dataview_view_row;
|
et2_dataview_view_row;
|
||||||
et2_dataview_view_partitionTree;
|
et2_dataview_view_partitionTree;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var et2_dataview_grid = Class.extend({
|
var et2_dataview_grid = Class.extend(et2_dataview_IViewRange, {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the grid.
|
||||||
|
*
|
||||||
|
* @param _parent is the parent grid class - if null, this means that this
|
||||||
|
* is the outer grid which manages the scrollarea. If not null, all other
|
||||||
|
* parameters are ignored and copied from the given grid instance.
|
||||||
|
* @param _outerId is the id of the grid container it uses for the css
|
||||||
|
* classes.
|
||||||
|
* @param _columnIds is the id of the individual columns used for the css
|
||||||
|
* classes.
|
||||||
|
* @param _avgHeight is the starting average height of the column rows.
|
||||||
|
*/
|
||||||
|
init: function(_parent, _outerId, _columnIds, _dataProvider, _avgHeight) {
|
||||||
|
|
||||||
|
// If the parent is given, copy all other parameters from it
|
||||||
|
if (_parent != null)
|
||||||
|
{
|
||||||
|
this._outerId = _parent._outerId;
|
||||||
|
this._columnIds = _parent._columnIds;
|
||||||
|
this._dataProvider = _parent._dataProvider;
|
||||||
|
this._avgHeight = _parent._partitionTree.getAverageHeight();
|
||||||
|
this._rowProvider = _parent._rowProvider;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Otherwise copy the given parameters
|
||||||
|
this._outerId = _outerId;
|
||||||
|
this._columnIds = _columnIds;
|
||||||
|
this._dataProvider = _dataProvider;
|
||||||
|
this._avgHeight = _avgHeight;
|
||||||
|
|
||||||
|
// Create the row provider
|
||||||
|
this._rowProvider = new et2_dataview_rowProvider(_outerId,
|
||||||
|
_columnIds);
|
||||||
|
|
||||||
|
this._scrollHeight = 0;
|
||||||
|
this._scrollTimeout = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The "treeChanged" variable is called whenever the viewrange has been
|
||||||
|
// set - changing the viewrange is the function which causes new elements
|
||||||
|
// to be generated and thus the partition tree to degenerate
|
||||||
|
this._treeChanged = false;
|
||||||
|
|
||||||
|
// Count of elements which are buffered at top and bottom of the viewrange
|
||||||
|
// before they get replaced with placeholders
|
||||||
|
this._holdCount = 50;
|
||||||
|
|
||||||
|
// The current range holds the currently visible nodes
|
||||||
|
this._currentRange = et2_range(0, 0);
|
||||||
|
|
||||||
|
// Build the grid outer nodes
|
||||||
|
this._createNodes();
|
||||||
|
|
||||||
init: function(_dataProvider, _count, _avgHeight) {
|
|
||||||
// Create the partition tree object which is used to organize the tree
|
// Create the partition tree object which is used to organize the tree
|
||||||
// items.
|
// items.
|
||||||
this._partitionTree = new et2_dataview_partitionTree(_dataProvider,
|
this._partitionTree = new et2_dataview_partitionTree(this._dataProvider,
|
||||||
_count, _avgHeight);
|
this._rowProvider, this._avgHeight, this.innerTbody);
|
||||||
|
|
||||||
|
// Setup the "rebuild" timer - it rebuilds the complete partition tree
|
||||||
|
// if any change has been done to it. Rebuilding the partition tree is
|
||||||
|
// necessary as the tree structure happens to degenerate.
|
||||||
|
var self = this;
|
||||||
|
this._rebuildTimer = window.setInterval(function() {
|
||||||
|
self._checkTreeRebuild();
|
||||||
|
}, 10 * 1000);
|
||||||
},
|
},
|
||||||
|
|
||||||
destroy: function() {
|
destroy: function() {
|
||||||
// Free the partition tree
|
// Stop the scroll timeout
|
||||||
|
if (this._scrollTimeout)
|
||||||
|
{
|
||||||
|
window.clearTimeout(this._scrollTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop the rebuild timer
|
||||||
|
window.clearInterval(this._rebuildTimer);
|
||||||
|
|
||||||
|
// Free the partition tree and the row provider
|
||||||
this._partitionTree.free();
|
this._partitionTree.free();
|
||||||
|
this._rowProvider.free();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The setViewRange function updates the range in which columns are shown.
|
||||||
|
*/
|
||||||
|
setViewRange: function(_range) {
|
||||||
|
this._treeChanged = true;
|
||||||
|
|
||||||
|
// Copy the given range
|
||||||
|
this._currentRange = et2_bounds(_range.top, _range.bottom);
|
||||||
|
|
||||||
|
// Display all elements in the given range
|
||||||
|
var nodes = this._partitionTree.getRangeNodes(_range);
|
||||||
|
|
||||||
|
for (var i = 0; i < nodes.length; i++)
|
||||||
|
{
|
||||||
|
if (nodes[i].implements(et2_dataview_IViewRange))
|
||||||
|
{
|
||||||
|
nodes[i].setViewRange(_range);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deactivated the code below for testing purposes
|
||||||
|
|
||||||
|
// Calculate the range of the actually shown elements
|
||||||
|
/*var displayTop = _range.top;
|
||||||
|
var displayBottom = _range.bottom;
|
||||||
|
|
||||||
|
if (nodes.length > 0)
|
||||||
|
{
|
||||||
|
displayTop = nodes[0].getPosTop();
|
||||||
|
displayBottom = nodes[nodes.length - 1].getPosBottom();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hide everything except for _holdCount elements at the top and bottom
|
||||||
|
// of the viewrange
|
||||||
|
var reduceHeight = this._partitionTree.getAverageHeight() * this._holdCount;
|
||||||
|
|
||||||
|
if (displayTop > reduceHeight)
|
||||||
|
{
|
||||||
|
this._partitionTree.reduce(et2_bounds(0, displayTop - reduceHeight));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (displayBottom + reduceHeight < this._partitionTree.getHeight())
|
||||||
|
{
|
||||||
|
this._partitionTree.reduce(et2_bounds(displayBottom + reduceHeight,
|
||||||
|
this._partitionTree.getHeight()));
|
||||||
|
}*/
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the scrollheight
|
||||||
|
*/
|
||||||
|
setScrollHeight: function(_height) {
|
||||||
|
this._height = _height;
|
||||||
|
|
||||||
|
// Update the height of the outer container
|
||||||
|
if (this.scrollarea)
|
||||||
|
{
|
||||||
|
this.scrollarea.height(_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the viewing range
|
||||||
|
this.setViewRange(et2_range(this._currentRange.top, this._height));
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the JQuery outer DOM-Node
|
||||||
|
*/
|
||||||
|
getJNode: function() {
|
||||||
|
return this.outerCell;
|
||||||
|
},
|
||||||
|
|
||||||
|
/* ---- PRIVATE FUNCTIONS ---- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the partition tree has to be rebuilt and if yes, does
|
||||||
|
* that.
|
||||||
|
*/
|
||||||
|
_checkTreeRebuild: function() {
|
||||||
|
if (this._treeChanged)
|
||||||
|
{
|
||||||
|
var depth = this._partitionTree.getDepth();
|
||||||
|
var count = this._partitionTree.getManagedCount();
|
||||||
|
|
||||||
|
// Check whether the depth of the tree is very unproportional
|
||||||
|
// regarding to the count of elements managed in it
|
||||||
|
if (count < Math.pow(ET2_PARTITION_TREE_WIDTH, depth - 1))
|
||||||
|
{
|
||||||
|
this._partitionTree.rebuild();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset the "treeChanged" function.
|
||||||
|
this._treeChanged = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the grid DOM-Nodes
|
||||||
|
*/
|
||||||
|
_createNodes: function() {
|
||||||
|
this.outerCell = $j(document.createElement("td"))
|
||||||
|
.addClass("frame")
|
||||||
|
.attr("colspan", this._columnIds.length + (this._parent ? 0 : 1));
|
||||||
|
|
||||||
|
// Create the scrollarea div if this is the outer grid
|
||||||
|
this.scrollarea = null;
|
||||||
|
if (this._parent == null)
|
||||||
|
{
|
||||||
|
this.scrollarea = $j(document.createElement("div"))
|
||||||
|
.addClass("egwGridView_scrollarea")
|
||||||
|
.scroll(this, function(e) {
|
||||||
|
|
||||||
|
// Clear any older scroll timeout
|
||||||
|
if (e.data._scrollTimeout)
|
||||||
|
{
|
||||||
|
window.clearTimeout(e.data._scrollTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set a new timeout which calls the setViewArea
|
||||||
|
// function
|
||||||
|
e.data._scrollTimeout = window.setTimeout(function() {
|
||||||
|
e.data.setViewRange(et2_range(
|
||||||
|
e.data.scrollarea.scrollTop(),
|
||||||
|
e.data._height
|
||||||
|
));
|
||||||
|
}, 25);
|
||||||
|
})
|
||||||
|
.height(this._scrollHeight)
|
||||||
|
.appendTo(this.outerCell);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the inner table
|
||||||
|
var table = $j(document.createElement("table"))
|
||||||
|
.addClass("egwGridView_grid")
|
||||||
|
.appendTo(this.scrollarea ? this.scrollarea : this.outerCell);
|
||||||
|
|
||||||
|
this.innerTbody = $j(document.createElement("tbody"))
|
||||||
|
.appendTo(table);
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -40,16 +40,19 @@ var et2_dataview_gridContainer = Class.extend({
|
|||||||
* Constructor for the grid container
|
* Constructor for the grid container
|
||||||
* @param object _parentNode is the DOM-Node into which the grid view will be inserted
|
* @param object _parentNode is the DOM-Node into which the grid view will be inserted
|
||||||
*/
|
*/
|
||||||
init: function(_parentNode) {
|
init: function(_parentNode, _dataProvider) {
|
||||||
|
|
||||||
// Copy the parent node parameter
|
// Copy the arguments
|
||||||
this.parentNode = $j(_parentNode);
|
this.parentNode = $j(_parentNode);
|
||||||
|
this.dataProvider = _dataProvider;
|
||||||
|
|
||||||
// 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.grid = null;
|
||||||
|
|
||||||
this.width = 0;
|
this.width = 0;
|
||||||
this.height = 0;
|
this.height = 0;
|
||||||
|
|
||||||
@ -69,6 +72,12 @@ var et2_dataview_gridContainer = Class.extend({
|
|||||||
// Clear the columns
|
// Clear the columns
|
||||||
this._clearHeader();
|
this._clearHeader();
|
||||||
|
|
||||||
|
// Free the grid
|
||||||
|
if (this.grid)
|
||||||
|
{
|
||||||
|
this.grid.free();
|
||||||
|
}
|
||||||
|
|
||||||
// Detatch the outer element
|
// Detatch the outer element
|
||||||
this.table.remove();
|
this.table.remove();
|
||||||
},
|
},
|
||||||
@ -99,10 +108,13 @@ var et2_dataview_gridContainer = Class.extend({
|
|||||||
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
|
||||||
|
this._buildGrid();
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -115,14 +127,20 @@ var et2_dataview_gridContainer = Class.extend({
|
|||||||
|
|
||||||
// Rebuild the column stylesheets
|
// Rebuild the column stylesheets
|
||||||
this.columnMgr.setTotalWidth(_w - this.scrollbarWidth);
|
this.columnMgr.setTotalWidth(_w - this.scrollbarWidth);
|
||||||
|
et2_debug("log", _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.
|
||||||
// TODO
|
if (this.grid)
|
||||||
|
{
|
||||||
|
this.grid.setScrollHeight(this.height -
|
||||||
|
this.headTr.outerHeight(true));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -236,14 +254,12 @@ var et2_dataview_gridContainer = Class.extend({
|
|||||||
vis_col++;
|
vis_col++;
|
||||||
this.visibleColumnCount++;
|
this.visibleColumnCount++;
|
||||||
|
|
||||||
|
// Update the visibility of the column
|
||||||
styleSheet.updateRule("." + col.tdClass,
|
styleSheet.updateRule("." + col.tdClass,
|
||||||
"display: " + (col.visible ? "table-cell" : "none") + "; " +
|
"display: table-cell; " +
|
||||||
((vis_col == total_cnt) ? "border-right-width: 0 " : "border-right-width: 1px ") +
|
((vis_col == total_cnt) ? "border-right-width: 0 " : "border-right-width: 1px ") +
|
||||||
"!important;");
|
"!important;");
|
||||||
|
|
||||||
styleSheet.updateRule(".egwGridView_outer ." + col.divClass,
|
|
||||||
"width: " + (col.width - this.headerBorderWidth) + "px;");
|
|
||||||
|
|
||||||
// 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 addBorder = 0;
|
var addBorder = 0;
|
||||||
@ -270,10 +286,15 @@ var et2_dataview_gridContainer = Class.extend({
|
|||||||
addBorder += 1;
|
addBorder += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
var width = Math.max(0, (col.width - this.columnBorderWidth - addBorder));
|
// Write the width of the body-columns
|
||||||
|
var columnWidth = Math.max(0, (col.width - this.columnBorderWidth - addBorder));
|
||||||
styleSheet.updateRule(".egwGridView_grid ." + col.divClass,
|
styleSheet.updateRule(".egwGridView_grid ." + col.divClass,
|
||||||
"width: " + width + "px;");
|
"width: " + columnWidth + "px;");
|
||||||
|
|
||||||
|
// Write the width of the header columns
|
||||||
|
var headerWidth = Math.max(0, (col.width - this.headerBorderWidth));
|
||||||
|
styleSheet.updateRule(".egwGridView_outer ." + col.divClass,
|
||||||
|
"width: " + headerWidth + "px;");
|
||||||
|
|
||||||
totalWidth += col.width;
|
totalWidth += col.width;
|
||||||
|
|
||||||
@ -281,8 +302,7 @@ var et2_dataview_gridContainer = Class.extend({
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
styleSheet.updateRule("." + col.tdClass,
|
styleSheet.updateRule("." + col.tdClass, "display: none;");
|
||||||
"display: " + (col.visible ? "table-cell" : "none") + ";");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -338,6 +358,24 @@ var et2_dataview_gridContainer = Class.extend({
|
|||||||
+ this.selectCol.width() + 1);
|
+ this.selectCol.width() + 1);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the inner grid class
|
||||||
|
*/
|
||||||
|
_buildGrid: function() {
|
||||||
|
// 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 grid class and pass "19" as the starting average row height
|
||||||
|
this.grid = new et2_dataview_grid(null, this.uniqueId, colIds,
|
||||||
|
this.dataProvider, 19);
|
||||||
|
|
||||||
|
// Insert the grid into the DOM-Tree
|
||||||
|
this.containerTr.append(this.grid.getJNode());
|
||||||
|
},
|
||||||
|
|
||||||
/* --- Code for calculating the browser/css depending widths --- */
|
/* --- Code for calculating the browser/css depending widths --- */
|
||||||
|
|
||||||
|
@ -49,8 +49,9 @@ var et2_dataview_IPartitionHeight = new Interface({
|
|||||||
var et2_dataview_partitionNode = Class.extend([et2_dataview_IPartitionHeight,
|
var et2_dataview_partitionNode = Class.extend([et2_dataview_IPartitionHeight,
|
||||||
et2_dataview_IInvalidatable], {
|
et2_dataview_IInvalidatable], {
|
||||||
|
|
||||||
init: function() {
|
init: function(_root) {
|
||||||
|
|
||||||
|
this._root = _root;
|
||||||
this._parent = null;
|
this._parent = null;
|
||||||
this._pidx = 0;
|
this._pidx = 0;
|
||||||
|
|
||||||
@ -126,12 +127,7 @@ var et2_dataview_partitionNode = Class.extend([et2_dataview_IPartitionHeight,
|
|||||||
* Returns the root node of the partition tree
|
* Returns the root node of the partition tree
|
||||||
*/
|
*/
|
||||||
getRoot: function() {
|
getRoot: function() {
|
||||||
if (this.parent != null)
|
return this._root;
|
||||||
{
|
|
||||||
return this.parent.getRoot();
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -293,6 +289,18 @@ var et2_dataview_partitionNode = Class.extend([et2_dataview_IPartitionHeight,
|
|||||||
_data.height += this.getHeight();
|
_data.height += this.getHeight();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getNodeIdx: function(_idx, _create) {
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
|
||||||
|
getRowProvider: function() {
|
||||||
|
return this.getRoot().getRowProvider();
|
||||||
|
},
|
||||||
|
|
||||||
|
getDataProvider: function() {
|
||||||
|
return this.getRoot().getDataProvider();
|
||||||
|
},
|
||||||
|
|
||||||
/* ---- PRIVATE FUNCTIONS ---- */
|
/* ---- PRIVATE FUNCTIONS ---- */
|
||||||
|
|
||||||
_accumulateValue: function(_f1, _f2) {
|
_accumulateValue: function(_f1, _f2) {
|
||||||
@ -314,7 +322,7 @@ var et2_dataview_partitionNode = Class.extend([et2_dataview_IPartitionHeight,
|
|||||||
});
|
});
|
||||||
|
|
||||||
/*var et2_dataview_IIndexOperations = new Interface({
|
/*var et2_dataview_IIndexOperations = new Interface({
|
||||||
getIdxNode: function(_idx),
|
getIdxNode: function(_idx, _create),
|
||||||
removeIdxNode: function(_idx),
|
removeIdxNode: function(_idx),
|
||||||
insertNodes: function(_idx, _nodes)
|
insertNodes: function(_idx, _nodes)
|
||||||
});*/
|
});*/
|
||||||
@ -326,7 +334,7 @@ var et2_dataview_partitionNode = Class.extend([et2_dataview_IPartitionHeight,
|
|||||||
var et2_dataview_partitionOrganizationNode = et2_dataview_partitionNode.extend(
|
var et2_dataview_partitionOrganizationNode = et2_dataview_partitionNode.extend(
|
||||||
/*et2_dataview_IIndexOperations, */{
|
/*et2_dataview_IIndexOperations, */{
|
||||||
|
|
||||||
init: function(_parent, _pidx) {
|
init: function(_root, _parent, _pidx) {
|
||||||
|
|
||||||
if (typeof _parent == "undefined")
|
if (typeof _parent == "undefined")
|
||||||
{
|
{
|
||||||
@ -339,7 +347,7 @@ var et2_dataview_partitionOrganizationNode = et2_dataview_partitionNode.extend(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Call the parent constructor
|
// Call the parent constructor
|
||||||
this._super();
|
this._super(_root);
|
||||||
|
|
||||||
this._children = [];
|
this._children = [];
|
||||||
|
|
||||||
@ -351,7 +359,7 @@ var et2_dataview_partitionOrganizationNode = et2_dataview_partitionNode.extend(
|
|||||||
|
|
||||||
destroy: function() {
|
destroy: function() {
|
||||||
// Free all child nodes
|
// Free all child nodes
|
||||||
for (var i = this._children.length - 1; i >= 0; i++)
|
for (var i = this._children.length - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
this._children[i].free();
|
this._children[i].free();
|
||||||
}
|
}
|
||||||
@ -367,6 +375,7 @@ var et2_dataview_partitionOrganizationNode = et2_dataview_partitionNode.extend(
|
|||||||
|
|
||||||
this._count = false;
|
this._count = false;
|
||||||
this._depth = false;
|
this._depth = false;
|
||||||
|
this._avgHeightData = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -451,7 +460,7 @@ var et2_dataview_partitionOrganizationNode = et2_dataview_partitionNode.extend(
|
|||||||
* Removes the child with the given overall index
|
* Removes the child with the given overall index
|
||||||
*/
|
*/
|
||||||
removeIdxNode: function(_idx) {
|
removeIdxNode: function(_idx) {
|
||||||
this._iterateToIndx(_idx, function(ei, bi, child) {
|
return this._iterateToIndex(_idx, function(ei, bi, child) {
|
||||||
if (child.implements(et2_dataview_IIndexOperations))
|
if (child.implements(et2_dataview_IIndexOperations))
|
||||||
{
|
{
|
||||||
return child.removeIdxNode(_idx);
|
return child.removeIdxNode(_idx);
|
||||||
@ -465,7 +474,7 @@ var et2_dataview_partitionOrganizationNode = et2_dataview_partitionNode.extend(
|
|||||||
* Returns the node with the given overall index and null if it is not found
|
* Returns the node with the given overall index and null if it is not found
|
||||||
*/
|
*/
|
||||||
getIdxNode: function(_idx) {
|
getIdxNode: function(_idx) {
|
||||||
this._iterateToIndx(_idx, function(ei, bi, child) {
|
return this._iterateToIndex(_idx, function(ei, bi, child) {
|
||||||
if (child.implements(et2_dataview_IIndexOperations))
|
if (child.implements(et2_dataview_IIndexOperations))
|
||||||
{
|
{
|
||||||
return child.getIdxNode()
|
return child.getIdxNode()
|
||||||
@ -478,6 +487,15 @@ var et2_dataview_partitionOrganizationNode = et2_dataview_partitionNode.extend(
|
|||||||
}, null);
|
}, null);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getNodeAt returns the DOM node at the given index
|
||||||
|
*/
|
||||||
|
getNodeAt: function(_idx) {
|
||||||
|
return this._iterateToIndex(_idx, function(ei, bi, child) {
|
||||||
|
return child.getNodeAt(_idx);
|
||||||
|
}, null);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all nodes in the given range
|
* Returns all nodes in the given range
|
||||||
*/
|
*/
|
||||||
@ -574,14 +592,14 @@ var et2_dataview_partitionOrganizationNode = et2_dataview_partitionNode.extend(
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reduces the given range to a placeholder
|
* Reduces the given range to a spacer
|
||||||
*/
|
*/
|
||||||
reduceRange: function(_range) {
|
reduceRange: function(_range) {
|
||||||
this._reduce(this.getRangeNodes(_range, false))
|
this._reduce(this.getRangeNodes(_range, false))
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reduces the given index range to a placeholder
|
* Reduces the given index range to a spacer
|
||||||
*/
|
*/
|
||||||
reduceIdxRange: function(_range) {
|
reduceIdxRange: function(_range) {
|
||||||
this._reduce(this.getIdxRangeNodes(_range, false));
|
this._reduce(this.getIdxRangeNodes(_range, false));
|
||||||
@ -747,6 +765,25 @@ var et2_dataview_partitionOrganizationNode = et2_dataview_partitionNode.extend(
|
|||||||
this.insertNodes(0, children);
|
this.insertNodes(0, children);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accumulates the "average height" data
|
||||||
|
*/
|
||||||
|
getAvgHeightData: function(_data) {
|
||||||
|
if (this._avgHeightData == false)
|
||||||
|
{
|
||||||
|
this._avgHeightData = {"count": 0, "height": 0};
|
||||||
|
|
||||||
|
for (var i = 0; i < this._children.length; i++)
|
||||||
|
{
|
||||||
|
this._children[i].getAvgHeightData(_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Increment the data object entries by the buffered avg height data
|
||||||
|
_data.count += this._avgHeightData.count;
|
||||||
|
_data.height += this._avgHeightData.height;
|
||||||
|
},
|
||||||
|
|
||||||
/* ---- PRIVATE FUNCTIONS ---- */
|
/* ---- PRIVATE FUNCTIONS ---- */
|
||||||
|
|
||||||
_copyChildren: function() {
|
_copyChildren: function() {
|
||||||
@ -760,7 +797,7 @@ var et2_dataview_partitionOrganizationNode = et2_dataview_partitionNode.extend(
|
|||||||
return children;
|
return children;
|
||||||
},
|
},
|
||||||
|
|
||||||
_iterateToIndx: function(_idx, _func, _res) {
|
_iterateToIndex: function(_idx, _func, _res) {
|
||||||
for (var i = 0; i < this._children.length; i++)
|
for (var i = 0; i < this._children.length; i++)
|
||||||
{
|
{
|
||||||
var child = this._children[i];
|
var child = this._children[i];
|
||||||
@ -783,7 +820,7 @@ var et2_dataview_partitionOrganizationNode = et2_dataview_partitionNode.extend(
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reduces the given nodes to a single placeholder
|
* Reduces the given nodes to a single spacer
|
||||||
*/
|
*/
|
||||||
_reduce: function(_nodes) {
|
_reduce: function(_nodes) {
|
||||||
if (_nodes.length == 0)
|
if (_nodes.length == 0)
|
||||||
@ -791,26 +828,26 @@ var et2_dataview_partitionOrganizationNode = et2_dataview_partitionNode.extend(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check whether the first or last node is a placeholder, if not create
|
// Check whether the first or last node is a spacer, if not create
|
||||||
// a new one
|
// a new one
|
||||||
var ph;
|
var ph;
|
||||||
if (_nodes[0] instanceof et2_dataview_partitionPlaceholderNode)
|
if (_nodes[0] instanceof et2_dataview_partitionSpacerNode)
|
||||||
{
|
{
|
||||||
ph = _nodes[0]
|
ph = _nodes[0]
|
||||||
}
|
}
|
||||||
else if (_nodes[_nodes.length - 1] instanceof et2_dataview_partitionPlaceholderNode)
|
else if (_nodes[_nodes.length - 1] instanceof et2_dataview_partitionSpacerNode)
|
||||||
{
|
{
|
||||||
ph = _nodes[_nodes.length - 1];
|
ph = _nodes[_nodes.length - 1];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Create a new placeholder node an insert it at the place of the
|
// Create a new spacer node an insert it at the place of the
|
||||||
// first node of the range
|
// first node of the range
|
||||||
ph = new et2_dataview_partitionPlaceholderNode();
|
ph = new et2_dataview_partitionSpacerNode(this.getRoot());
|
||||||
this.getRoot().insertNodes(_nodes[0].getStartIndex(), [ph]);
|
this.getRoot().insertNodes(_nodes[0].getStartIndex(), [ph]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the height of the resulting placeholder
|
// Get the height of the resulting spacer
|
||||||
var height = _nodes[_nodes.length - 1].getBottom() - _nodes[0].getTop();
|
var height = _nodes[_nodes.length - 1].getBottom() - _nodes[0].getTop();
|
||||||
|
|
||||||
// Get the count of actual elements in the nodes
|
// Get the count of actual elements in the nodes
|
||||||
@ -820,11 +857,11 @@ var et2_dataview_partitionOrganizationNode = et2_dataview_partitionNode.extend(
|
|||||||
count += _nodes[i].getCount();
|
count += _nodes[i].getCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the placeholder parameters
|
// Update the spacer parameters
|
||||||
ph.setAvgHeight(height / count);
|
ph.setAvgHeight(height / count);
|
||||||
ph.setCount(count);
|
ph.setCount(count);
|
||||||
|
|
||||||
// Free all elements (except for the placeholder)
|
// Free all elements (except for the spacer)
|
||||||
for (var i = _nodes.length - 1; i >= 0; i--)
|
for (var i = _nodes.length - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
if (_nodes[i] != ph)
|
if (_nodes[i] != ph)
|
||||||
@ -862,22 +899,112 @@ var et2_dataview_partitionOrganizationNode = et2_dataview_partitionNode.extend(
|
|||||||
|
|
||||||
this._children = [];
|
this._children = [];
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The partition container node base class implements most functionality for
|
||||||
|
* nodes which have a container.
|
||||||
|
*/
|
||||||
|
var et2_dataview_partitionContainerNode = et2_dataview_partitionNode.extend({
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies the given container object and inserts the container into the tree
|
||||||
|
* - if it is not already in there.
|
||||||
|
*/
|
||||||
|
init: function(_root, _container, _args) {
|
||||||
|
this._super(_root);
|
||||||
|
|
||||||
|
// Copy the container parameter and set its "invalidationElement" to
|
||||||
|
// this node
|
||||||
|
this.container = _container;
|
||||||
|
this.container.setInvalidationElement(this);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts the container into the tree if it is not already inserted.
|
||||||
|
*/
|
||||||
|
initializeContainer: function() {
|
||||||
|
// Obtain the node index and insert the container nodes at the node
|
||||||
|
// returned by getNodeAt. If idx is zero, the returned node will be
|
||||||
|
// the outer container, so the container nodes have to be prepended
|
||||||
|
// to it.
|
||||||
|
var idx = this.getStartIndex();
|
||||||
|
this.container.insertIntoTree(this.getRoot().getNodeAt(idx - 1),
|
||||||
|
idx == 0);
|
||||||
|
|
||||||
|
this.invalidate();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroys the container if it is still set - e.g. the spacer node
|
||||||
|
* sets the container to null before "free" ist called in some cases, in
|
||||||
|
* order to pass the container object to another spacer node.
|
||||||
|
*/
|
||||||
|
destroy: function() {
|
||||||
|
if (this.container)
|
||||||
|
{
|
||||||
|
this.container.free();
|
||||||
|
}
|
||||||
|
|
||||||
|
this._super();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the height of the container
|
||||||
|
*/
|
||||||
|
calculateHeight: function() {
|
||||||
|
return this.container.getHeight();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls the "insertNodeAfter" function of the container to insert the node.
|
||||||
|
*/
|
||||||
|
insertNodeAfter: function(_node) {
|
||||||
|
this.container.insertNodeAfter(_node);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the "lastNode" of the container
|
||||||
|
*/
|
||||||
|
getNodeAt: function(_idx) {
|
||||||
|
if (_idx >= this.getStartIndex() && _idx < this.getStopIndex())
|
||||||
|
{
|
||||||
|
return this.container.getLastNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Node which represents a placeholder. Complete parts of the tree can be
|
* Node which represents a spacer. Complete parts of the tree can be
|
||||||
* transformed into placeholder nodes.
|
* transformed into spacer nodes.
|
||||||
*/
|
*/
|
||||||
var et2_dataview_partitionPlaceholderNode = et2_dataview_partitionNode.extend({
|
var et2_dataview_partitionSpacerNode = et2_dataview_partitionContainerNode.extend({
|
||||||
|
|
||||||
init: function(_count, _avgHeight) {
|
init: function(_root, _count, _avgHeight, _container) {
|
||||||
|
|
||||||
|
// Create the container if it has not been passed as a third parameter
|
||||||
|
var container;
|
||||||
|
if (typeof _container != "undefined")
|
||||||
|
{
|
||||||
|
container = _container;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
container = new et2_dataview_spacer(_root.getDataProvider(),
|
||||||
|
_root.getRowProvider(), this);
|
||||||
|
}
|
||||||
|
|
||||||
// Call the inherited constructor
|
// Call the inherited constructor
|
||||||
this._super();
|
this._super(_root, container);
|
||||||
|
|
||||||
|
// Copy the count and average height parameters and update the height
|
||||||
|
// of the container
|
||||||
this._count = _count;
|
this._count = _count;
|
||||||
this._avgHeight = _avgHeight;
|
this._avgHeight = _avgHeight;
|
||||||
|
this.container.setHeight(_count * _avgHeight);
|
||||||
},
|
},
|
||||||
|
|
||||||
getCount: function() {
|
getCount: function() {
|
||||||
@ -889,6 +1016,7 @@ var et2_dataview_partitionPlaceholderNode = et2_dataview_partitionNode.extend({
|
|||||||
{
|
{
|
||||||
this._count = _count;
|
this._count = _count;
|
||||||
this.invalidate();
|
this.invalidate();
|
||||||
|
this.container.setHeight(_count * _avgHeight);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -897,6 +1025,7 @@ var et2_dataview_partitionPlaceholderNode = et2_dataview_partitionNode.extend({
|
|||||||
{
|
{
|
||||||
this._avgHeight = _height;
|
this._avgHeight = _height;
|
||||||
this.invalidate();
|
this.invalidate();
|
||||||
|
this.container.setHeight(_count * _avgHeight);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -927,23 +1056,29 @@ var et2_dataview_partitionPlaceholderNode = et2_dataview_partitionNode.extend({
|
|||||||
|
|
||||||
if (startIdx > 0 && startIdx < this._count)
|
if (startIdx > 0 && startIdx < this._count)
|
||||||
{
|
{
|
||||||
// Create a placeholder which contains the elements until startIdx
|
// Create a spacer which contains the elements until startIdx
|
||||||
insertNodes.push(new et2_dataview_partitionPlaceholderNode(startIdx, ah));
|
insertNodes.push(new et2_dataview_partitionSpacerNode(this.getRoot(),
|
||||||
|
startIdx, ah, this.container));
|
||||||
|
this.container = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Calculate the current average height
|
||||||
|
ah = this.getRoot().getAverageHeight();
|
||||||
|
|
||||||
// Create the elements from start to stop index
|
// Create the elements from start to stop index
|
||||||
for (var i = startIdx; i < stopIdx; i++)
|
for (var i = startIdx; i < stopIdx; i++)
|
||||||
{
|
{
|
||||||
var rowNode = new et2_dataview_partitionRowNode(ah);
|
var rowNode = new et2_dataview_partitionRowNode(this.getRoot(), ah);
|
||||||
insertNodes.push(rowNode);
|
insertNodes.push(rowNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stopIdx < this._count - 1 && stopIdx > 0)
|
if (stopIdx < this._count - 1 && stopIdx > 0)
|
||||||
{
|
{
|
||||||
// Create a placeholder which contains the elements starting from
|
// Create a spacer which contains the elements starting from
|
||||||
// stop index
|
// stop index
|
||||||
var l = this._count - stopIdx;
|
var l = this._count - stopIdx;
|
||||||
insertNodes.push(new et2_dataview_partitionPlaceholderNode(l, ah));
|
insertNodes.push(new et2_dataview_partitionSpacerNode(this.getRoot(),
|
||||||
|
l, ah));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check whether insertNodes really has entrys - this is not the case
|
// Check whether insertNodes really has entrys - this is not the case
|
||||||
@ -956,6 +1091,12 @@ var et2_dataview_partitionPlaceholderNode = et2_dataview_partitionNode.extend({
|
|||||||
// Insert the newly created nodes at the original place of this node
|
// Insert the newly created nodes at the original place of this node
|
||||||
parent.insertNodes(pidx, insertNodes);
|
parent.insertNodes(pidx, insertNodes);
|
||||||
|
|
||||||
|
// Insert the newly created elements into the DOM-Tree
|
||||||
|
for (var i = 0; i < insertNodes.length; i++)
|
||||||
|
{
|
||||||
|
insertNodes[i].initializeContainer();
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -963,7 +1104,7 @@ var et2_dataview_partitionPlaceholderNode = et2_dataview_partitionNode.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
getAvgHeightData: function(_data) {
|
getAvgHeightData: function(_data) {
|
||||||
// Do nothing here, as the placeholders should not be inside the average
|
// Do nothing here, as the spacers should not be inside the average
|
||||||
// height statistic.
|
// height statistic.
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -974,33 +1115,95 @@ var et2_dataview_partitionPlaceholderNode = et2_dataview_partitionNode.extend({
|
|||||||
*/
|
*/
|
||||||
var et2_dataview_partitionTree = et2_dataview_partitionOrganizationNode.extend({
|
var et2_dataview_partitionTree = et2_dataview_partitionOrganizationNode.extend({
|
||||||
|
|
||||||
init: function(_count, _avgHeight) {
|
init: function(_dataProvider, _rowProvider, _avgHeight, _node) {
|
||||||
this._super();
|
this._super(this);
|
||||||
|
|
||||||
// Append a placeholder node to the children
|
this._avgHeight = _avgHeight;
|
||||||
var ph = new et2_dataview_partitionPlaceholderNode(_count, _avgHeight);
|
this._node = _node;
|
||||||
|
this._count = _dataProvider.getCount();
|
||||||
|
|
||||||
|
this._dataProvider = _dataProvider;
|
||||||
|
this._rowProvider = _rowProvider;
|
||||||
|
|
||||||
|
et2_debug("Creating partition tree with ", this._count,
|
||||||
|
" elements of avgHeight ", this._avgHeight);
|
||||||
|
|
||||||
|
// Append a spacer node to the children
|
||||||
|
var ph = new et2_dataview_partitionSpacerNode(this, this._count,
|
||||||
|
this._avgHeight);
|
||||||
ph.setParent(this);
|
ph.setParent(this);
|
||||||
|
ph.initializeContainer();
|
||||||
|
|
||||||
this._children = [ph];
|
this._children = [ph];
|
||||||
|
},
|
||||||
|
|
||||||
|
getAverageHeight: function() {
|
||||||
|
var data = {"count": 0, "height": 0};
|
||||||
|
|
||||||
|
this.getAvgHeightData(data);
|
||||||
|
|
||||||
|
if (data.count == 0)
|
||||||
|
{
|
||||||
|
return this._avgHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data.height / data.count;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the actual count of managed objects inside of the tree - getCount
|
||||||
|
* in contrast returns the count of "virtual" objects including the
|
||||||
|
* spacers.
|
||||||
|
*/
|
||||||
|
getManagedCount: function() {
|
||||||
|
var data = {"count": 0, "height": 0};
|
||||||
|
this.getAvgHeightData(data);
|
||||||
|
|
||||||
|
return data.count;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the node after which new nodes have to be inserted for the given
|
||||||
|
* index.
|
||||||
|
*/
|
||||||
|
getNodeAt: function(_idx) {
|
||||||
|
|
||||||
|
// Insert the given node to the top of the parent container
|
||||||
|
if (_idx < 0)
|
||||||
|
{
|
||||||
|
return this._node;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise search for the tree node with that index
|
||||||
|
return this._super(_idx);
|
||||||
|
},
|
||||||
|
|
||||||
|
getRowProvider: function() {
|
||||||
|
return this._rowProvider;
|
||||||
|
},
|
||||||
|
|
||||||
|
getDataProvider: function() {
|
||||||
|
return this._dataProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
var et2_dataview_partitionRowNode = et2_dataview_partitionNode.extend({
|
var et2_dataview_partitionRowNode = et2_dataview_partitionContainerNode.extend({
|
||||||
|
|
||||||
|
init: function(_root, _avgHeight) {
|
||||||
|
|
||||||
|
var container = new et2_dataview_row(_root.getDataProvider(),
|
||||||
|
_root.getRowProvider(), this, 0);
|
||||||
|
|
||||||
|
this._super(_root, container);
|
||||||
|
|
||||||
init: function(_avgHeight) {
|
|
||||||
this._avgHeight = _avgHeight;
|
this._avgHeight = _avgHeight;
|
||||||
},
|
},
|
||||||
|
|
||||||
calculateHeight: function() {
|
getIdxNode: function(_node, _create) {
|
||||||
return this._avgHeight;
|
return this.node;
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/*
|
|
||||||
var tree = new et2_dataview_partitionTree(1000, 20);
|
|
||||||
tree.getRangeNodes(et2_range(0, 100));
|
|
||||||
//tree.getRangeNodes(et2_range(0, 1000));
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
@ -16,29 +16,31 @@
|
|||||||
et2_dataview_interfaces;
|
et2_dataview_interfaces;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var et2_dataview_row = et2_dataview_container.extend({
|
var et2_dataview_row = et2_dataview_container.extend(et2_dataview_IDataRow, {
|
||||||
|
|
||||||
init: function(_dataProvider, _rowProvider, _idx) {
|
init: function(_dataProvider, _rowProvider, _invalidationElem, _idx) {
|
||||||
this._dataProvider = _dataProvider;
|
|
||||||
this._rowProvider = _rowProvider;
|
this._super(_dataProvider, _rowProvider, _invalidationElem);
|
||||||
this._idx = _idx;
|
|
||||||
this._node = null;
|
this.tr = this.rowProvider.getPrototype("default");
|
||||||
this._rowImpl = null;
|
$j("div", this.tr).text("Blub");
|
||||||
|
this.appendNode(this.tr);
|
||||||
|
|
||||||
// Register this row in the dataprovider - if data is available for this
|
// Register this row in the dataprovider - if data is available for this
|
||||||
// row the "updateData" function will be called immediately.
|
// row the "updateData" function will be called immediately.
|
||||||
this._dataProvider.registerDataRow(_idx, this);
|
//this.dataProvider.registerDataRow(_idx, this);
|
||||||
|
|
||||||
if (this._node == null)
|
// if (this.tr == null)
|
||||||
{
|
// {
|
||||||
}
|
// }
|
||||||
},
|
},
|
||||||
|
|
||||||
destroy: function() {
|
destroy: function() {
|
||||||
this._dataProvider.unregisterDataRow(_idx);
|
//this.dataProvider.unregisterDataRow(_idx);
|
||||||
},
|
},
|
||||||
|
|
||||||
updateData: function(_data) {
|
updateData: function(_data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -21,16 +21,16 @@
|
|||||||
*/
|
*/
|
||||||
var et2_dataview_rowProvider = Class.extend({
|
var et2_dataview_rowProvider = Class.extend({
|
||||||
|
|
||||||
init: function(_gridId, _columnIds) {
|
init: function(_outerId, _columnIds) {
|
||||||
// Copy the given parameters
|
// Copy the given parameters
|
||||||
this._dataProvider = _dataProvider;
|
this._outerId = _outerId;
|
||||||
this._gridId = _gridId;
|
|
||||||
this._columnIds = _columnIds;
|
this._columnIds = _columnIds;
|
||||||
this._prototypes = {};
|
this._prototypes = {};
|
||||||
|
|
||||||
// Create the default row "prototypes"
|
// Create the default row "prototypes"
|
||||||
this._createFullRowPrototype();
|
this._createFullRowPrototype();
|
||||||
this._createDefaultPrototype();
|
this._createDefaultPrototype();
|
||||||
|
this._createEmptyPrototype();
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -43,8 +43,8 @@ var et2_dataview_rowProvider = Class.extend({
|
|||||||
{
|
{
|
||||||
if (typeof _generator != "undefined")
|
if (typeof _generator != "undefined")
|
||||||
{
|
{
|
||||||
this._prototypes[_name] = _generator.call(_context, _gridId,
|
this._prototypes[_name] = _generator.call(_context, this._outerId,
|
||||||
_columnIds);
|
this._columnIds);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -63,7 +63,7 @@ var et2_dataview_rowProvider = Class.extend({
|
|||||||
.attr("span", this._columnIds.length)
|
.attr("span", this._columnIds.length)
|
||||||
.appendTo(tr);
|
.appendTo(tr);
|
||||||
var div = $j(document.createElement("div"))
|
var div = $j(document.createElement("div"))
|
||||||
.addClass(this._gridId + "_div_fullRow")
|
.addClass(this._outerId + "_div_fullRow")
|
||||||
.appendTo(td);
|
.appendTo(td);
|
||||||
|
|
||||||
this._prototypes["fullRow"] = tr;
|
this._prototypes["fullRow"] = tr;
|
||||||
@ -76,14 +76,18 @@ var et2_dataview_rowProvider = Class.extend({
|
|||||||
for (var i = 0; i < this._columnIds.length; i++)
|
for (var i = 0; i < this._columnIds.length; i++)
|
||||||
{
|
{
|
||||||
var td = $j(document.createElement("td"))
|
var td = $j(document.createElement("td"))
|
||||||
.addClass(this._gridId + "_td_" + this._columnIds[i])
|
.addClass(this._outerId + "_td_" + this._columnIds[i])
|
||||||
.appendTo(tr);
|
.appendTo(tr);
|
||||||
var div = $j(document.createElement("div"))
|
var div = $j(document.createElement("div"))
|
||||||
.addClass(this._gridId + "_div_" + this._columnIds[i])
|
.addClass(this._outerId + "_div_" + this._columnIds[i])
|
||||||
.appendTo(td);
|
.appendTo(td);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._prototypes["default"] = tr;
|
this._prototypes["default"] = tr;
|
||||||
|
},
|
||||||
|
|
||||||
|
_createEmptyPrototype: function() {
|
||||||
|
this._prototypes["empty"] = $j(document.createElement("tr"));
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
53
etemplate/js/et2_dataview_view_spacer.js
Normal file
53
etemplate/js/et2_dataview_view_spacer.js
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/**
|
||||||
|
* eGroupWare eTemplate2 - Class which contains the spacer container
|
||||||
|
*
|
||||||
|
* @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$
|
||||||
|
*/
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/*egw:uses
|
||||||
|
jquery.jquery;
|
||||||
|
et2_dataview_view_container;
|
||||||
|
*/
|
||||||
|
|
||||||
|
var et2_dataview_spacer = et2_dataview_container.extend({
|
||||||
|
|
||||||
|
init: function(_dataProvider, _rowProvider, _invalidationElem) {
|
||||||
|
|
||||||
|
// Call the inherited container constructor
|
||||||
|
this._super(_dataProvider, _rowProvider, _invalidationElem);
|
||||||
|
|
||||||
|
// Get the spacer row and append it to the container
|
||||||
|
this.spacerNode = this.rowProvider.getPrototype("spacer",
|
||||||
|
this._createSpacerPrototype, this);
|
||||||
|
this._phDiv = $j("td", this.spacerNode);
|
||||||
|
this.appendNode(this.spacerNode);
|
||||||
|
},
|
||||||
|
|
||||||
|
setHeight: function(_height) {
|
||||||
|
this._phDiv.height(_height);
|
||||||
|
},
|
||||||
|
|
||||||
|
/* ---- PRIVATE FUNCTIONS ---- */
|
||||||
|
|
||||||
|
_createSpacerPrototype: function(_outerId, _columnIds) {
|
||||||
|
var tr = $j(document.createElement("tr"));
|
||||||
|
|
||||||
|
var td = $j(document.createElement("td"))
|
||||||
|
.addClass("egwGridView_spacer")
|
||||||
|
.addClass(_outerId + "_spacer_fullRow")
|
||||||
|
.attr("colspan", _columnIds.length)
|
||||||
|
.appendTo(tr);
|
||||||
|
|
||||||
|
return tr;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
@ -21,6 +21,8 @@
|
|||||||
et2_widget_grid;
|
et2_widget_grid;
|
||||||
et2_widget_selectbox;
|
et2_widget_selectbox;
|
||||||
et2_extension_nextmatch_dynheight;
|
et2_extension_nextmatch_dynheight;
|
||||||
|
et2_dataview_gridContainer;
|
||||||
|
et2_dataview_dataProvider;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -67,8 +69,13 @@ var et2_nextmatch = et2_DOMWidget.extend(et2_IResizeable, {
|
|||||||
// container.
|
// container.
|
||||||
this.dynheight = new et2_dynheight(null, this.div, 150);
|
this.dynheight = new et2_dynheight(null, this.div, 150);
|
||||||
|
|
||||||
|
// Create the data provider which cares about streaming the row data
|
||||||
|
// efficiently to the rows
|
||||||
|
this.dataProvider = new et2_dataview_dataProvider();
|
||||||
|
|
||||||
// Create the outer grid container
|
// Create the outer grid container
|
||||||
this.dataviewContainer = new et2_dataview_gridContainer(this.div);
|
this.dataviewContainer = new et2_dataview_gridContainer(this.div,
|
||||||
|
this.dataProvider);
|
||||||
|
|
||||||
this.activeFilters = {};
|
this.activeFilters = {};
|
||||||
},
|
},
|
||||||
@ -78,6 +85,7 @@ var et2_nextmatch = et2_DOMWidget.extend(et2_IResizeable, {
|
|||||||
*/
|
*/
|
||||||
destroy: function() {
|
destroy: function() {
|
||||||
this.dataviewContainer.free();
|
this.dataviewContainer.free();
|
||||||
|
this.dataProvider.free();
|
||||||
this.dynheight.free();
|
this.dynheight.free();
|
||||||
|
|
||||||
this._super.apply(this, arguments);
|
this._super.apply(this, arguments);
|
||||||
|
@ -32,6 +32,8 @@
|
|||||||
.egwGridView_scrollarea {
|
.egwGridView_scrollarea {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
|
||||||
|
background-color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.egwGridView_spacer {
|
.egwGridView_spacer {
|
||||||
|
@ -35,7 +35,16 @@
|
|||||||
|
|
||||||
<script src="../et2_extension_nextmatch.js"></script>
|
<script src="../et2_extension_nextmatch.js"></script>
|
||||||
<script src="../et2_extension_nextmatch_dynheight.js"></script>
|
<script src="../et2_extension_nextmatch_dynheight.js"></script>
|
||||||
|
|
||||||
|
<script src="../et2_dataview_interfaces.js"></script>
|
||||||
|
<script src="../et2_dataview_model_dataProvider.js"></script>
|
||||||
<script src="../et2_dataview_model_columns.js"></script>
|
<script src="../et2_dataview_model_columns.js"></script>
|
||||||
|
<script src="../et2_dataview_view_rowProvider.js"></script>
|
||||||
|
<script src="../et2_dataview_view_partitionTree.js"></script>
|
||||||
|
<script src="../et2_dataview_view_grid.js"></script>
|
||||||
|
<script src="../et2_dataview_view_container.js"></script>
|
||||||
|
<script src="../et2_dataview_view_row.js"></script>
|
||||||
|
<script src="../et2_dataview_view_spacer.js"></script>
|
||||||
<script src="../et2_dataview_view_gridcontainer.js"></script>
|
<script src="../et2_dataview_view_gridcontainer.js"></script>
|
||||||
|
|
||||||
<script src="../etemplate2.js"></script>
|
<script src="../etemplate2.js"></script>
|
||||||
|
Loading…
Reference in New Issue
Block a user