forked from extern/egroupware
Fixed problem with calculated values diverging from actual height values
This commit is contained in:
parent
8875c94c24
commit
7457315ea4
@ -20,7 +20,7 @@
|
|||||||
var et2_dataview_dataProvider = Class.extend({
|
var et2_dataview_dataProvider = Class.extend({
|
||||||
|
|
||||||
getCount: function() {
|
getCount: function() {
|
||||||
return 10;
|
return 10000;
|
||||||
},
|
},
|
||||||
|
|
||||||
registerDataRow: function(_idx, _dataRow) {
|
registerDataRow: function(_idx, _dataRow) {
|
||||||
|
@ -15,8 +15,8 @@
|
|||||||
/*egw:uses
|
/*egw:uses
|
||||||
jquery.jquery;
|
jquery.jquery;
|
||||||
et2_core_common;
|
et2_core_common;
|
||||||
|
|
||||||
et2_dataview_interfaces;
|
et2_dataview_interfaces;
|
||||||
et2_dataview_view_row;
|
|
||||||
et2_dataview_view_partitionTree;
|
et2_dataview_view_partitionTree;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -28,7 +28,9 @@ var ET2_GRID_VIEW_EXT = 25;
|
|||||||
/**
|
/**
|
||||||
* Determines the timeout after which the scroll-event is processed.
|
* Determines the timeout after which the scroll-event is processed.
|
||||||
*/
|
*/
|
||||||
var ET2_GRID_SCROLL_TIMEOUT = 25;
|
var ET2_GRID_SCROLL_TIMEOUT = 100;
|
||||||
|
|
||||||
|
var partitionTree = null;
|
||||||
|
|
||||||
var et2_dataview_grid = Class.extend(et2_dataview_IViewRange, {
|
var et2_dataview_grid = Class.extend(et2_dataview_IViewRange, {
|
||||||
|
|
||||||
@ -88,7 +90,7 @@ var et2_dataview_grid = Class.extend(et2_dataview_IViewRange, {
|
|||||||
|
|
||||||
// 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(this._dataProvider,
|
partitionTree = this._partitionTree = new et2_dataview_partitionTree(this._dataProvider,
|
||||||
this._rowProvider, this._avgHeight, this.innerTbody);
|
this._rowProvider, this._avgHeight, this.innerTbody);
|
||||||
|
|
||||||
// Setup the "rebuild" timer - it rebuilds the complete partition tree
|
// Setup the "rebuild" timer - it rebuilds the complete partition tree
|
||||||
@ -138,7 +140,7 @@ var et2_dataview_grid = Class.extend(et2_dataview_IViewRange, {
|
|||||||
// Deactivated the code below for testing purposes
|
// Deactivated the code below for testing purposes
|
||||||
|
|
||||||
// Calculate the range of the actually shown elements
|
// Calculate the range of the actually shown elements
|
||||||
/*var displayTop = _range.top;
|
var displayTop = _range.top;
|
||||||
var displayBottom = _range.bottom;
|
var displayBottom = _range.bottom;
|
||||||
|
|
||||||
if (nodes.length > 0)
|
if (nodes.length > 0)
|
||||||
@ -149,18 +151,21 @@ var et2_dataview_grid = Class.extend(et2_dataview_IViewRange, {
|
|||||||
|
|
||||||
// Hide everything except for _holdCount elements at the top and bottom
|
// Hide everything except for _holdCount elements at the top and bottom
|
||||||
// of the viewrange
|
// of the viewrange
|
||||||
var reduceHeight = this._partitionTree.getAverageHeight() * this._holdCount;
|
var ah = this._partitionTree.getAverageHeight();
|
||||||
|
var reduceHeight = ah * this._holdCount;
|
||||||
|
|
||||||
if (displayTop > reduceHeight)
|
if (displayTop > reduceHeight)
|
||||||
{
|
{
|
||||||
this._partitionTree.reduce(et2_bounds(0, displayTop - reduceHeight));
|
console.log("/\\");
|
||||||
|
this._partitionTree.reduceRange(et2_bounds(0, displayTop - reduceHeight));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (displayBottom + reduceHeight < this._partitionTree.getHeight())
|
if (displayBottom + reduceHeight < this._partitionTree.getHeight())
|
||||||
{
|
{
|
||||||
this._partitionTree.reduce(et2_bounds(displayBottom + reduceHeight,
|
console.log("\\/");
|
||||||
|
this._partitionTree.reduceRange(et2_bounds(displayBottom + reduceHeight,
|
||||||
this._partitionTree.getHeight()));
|
this._partitionTree.getHeight()));
|
||||||
}*/
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -202,7 +207,9 @@ var et2_dataview_grid = Class.extend(et2_dataview_IViewRange, {
|
|||||||
// regarding to the count of elements managed in it
|
// regarding to the count of elements managed in it
|
||||||
if (count < Math.pow(ET2_PARTITION_TREE_WIDTH, depth - 1))
|
if (count < Math.pow(ET2_PARTITION_TREE_WIDTH, depth - 1))
|
||||||
{
|
{
|
||||||
|
et2_debug("info", "Rebuilding dataview partition tree");
|
||||||
this._partitionTree.rebuild();
|
this._partitionTree.rebuild();
|
||||||
|
et2_debug("info", "Done.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset the "treeChanged" function.
|
// Reset the "treeChanged" function.
|
||||||
@ -235,6 +242,9 @@ var et2_dataview_grid = Class.extend(et2_dataview_IViewRange, {
|
|||||||
// Set a new timeout which calls the setViewArea
|
// Set a new timeout which calls the setViewArea
|
||||||
// function
|
// function
|
||||||
e.data._scrollTimeout = window.setTimeout(function() {
|
e.data._scrollTimeout = window.setTimeout(function() {
|
||||||
|
if (typeof ET2_GRID_PAUSE != "undefined")
|
||||||
|
return;
|
||||||
|
|
||||||
e.data.setViewRange(et2_range(
|
e.data.setViewRange(et2_range(
|
||||||
e.data.scrollarea.scrollTop() - ET2_GRID_VIEW_EXT,
|
e.data.scrollarea.scrollTop() - ET2_GRID_VIEW_EXT,
|
||||||
e.data._height + ET2_GRID_VIEW_EXT * 2
|
e.data._height + ET2_GRID_VIEW_EXT * 2
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
jquery.jquery;
|
jquery.jquery;
|
||||||
et2_core_common;
|
et2_core_common;
|
||||||
et2_core_stylesheet;
|
et2_core_stylesheet;
|
||||||
|
|
||||||
|
et2_dataview_view_grid;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
258
etemplate/js/et2_dataview_view_partitionContainerNodes.js
Normal file
258
etemplate/js/et2_dataview_view_partitionContainerNodes.js
Normal file
@ -0,0 +1,258 @@
|
|||||||
|
/**
|
||||||
|
* eGroupWare eTemplate2 - Class which contains an management tree for the grid rows
|
||||||
|
*
|
||||||
|
* @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_core_common; // for et2_range functions
|
||||||
|
et2_core_inheritance;
|
||||||
|
et2_dataview_interfaces;
|
||||||
|
et2_dataview_view_partitionNode;
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 spacer. Complete parts of the tree can be
|
||||||
|
* transformed into spacer nodes.
|
||||||
|
*/
|
||||||
|
var et2_dataview_partitionSpacerNode = et2_dataview_partitionContainerNode.extend({
|
||||||
|
|
||||||
|
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
|
||||||
|
this._super(_root, container);
|
||||||
|
|
||||||
|
// Copy the count and average height parameters - this updates the height
|
||||||
|
// of the outer container
|
||||||
|
this.setParameters(_count, _avgHeight);
|
||||||
|
},
|
||||||
|
|
||||||
|
getCount: function() {
|
||||||
|
return this._count;
|
||||||
|
},
|
||||||
|
|
||||||
|
getAvgHeight: function() {
|
||||||
|
return this._avgHeight;
|
||||||
|
},
|
||||||
|
|
||||||
|
setParameters: function(_count, _avgHeight) {
|
||||||
|
if (_count != this._count || _avgHeight != this._avgHeight)
|
||||||
|
{
|
||||||
|
|
||||||
|
// Copy the given parameters
|
||||||
|
this._count = _count;
|
||||||
|
this._avgHeight = _avgHeight;
|
||||||
|
|
||||||
|
// Invalidate this element
|
||||||
|
this.invalidate();
|
||||||
|
|
||||||
|
// Call the container function to set the total height
|
||||||
|
this.container.setHeight(this._count * this._avgHeight);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the nodes which fall in the given range and returns them
|
||||||
|
*/
|
||||||
|
getRangeNodes: function(_range, _create) {
|
||||||
|
|
||||||
|
// If no new nodes should be created, simply return this node
|
||||||
|
if (!_create)
|
||||||
|
{
|
||||||
|
return this._super(_range);
|
||||||
|
}
|
||||||
|
|
||||||
|
var insertNodes = [];
|
||||||
|
|
||||||
|
// Copy parent and pidx as we'll have to access those objects after this
|
||||||
|
// one gets freed
|
||||||
|
var parent = this._parent;
|
||||||
|
var pidx = this._pidx;
|
||||||
|
|
||||||
|
// Get the top and bottom of this node
|
||||||
|
var t = this.getPosTop();
|
||||||
|
var b = this.getPosBottom();
|
||||||
|
|
||||||
|
// Get the start and stop index of the elements which have to be
|
||||||
|
// created.
|
||||||
|
var ah = this._avgHeight;
|
||||||
|
var startIdx = Math.max(0, Math.floor((_range.top - t) / ah));
|
||||||
|
var stopIdx = Math.min(this._count, Math.ceil((_range.bottom - t) / ah));
|
||||||
|
|
||||||
|
if (startIdx > 0 && startIdx < this._count)
|
||||||
|
{
|
||||||
|
// Create a spacer which contains the elements until startIdx
|
||||||
|
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
|
||||||
|
for (var i = startIdx; i < stopIdx; i++)
|
||||||
|
{
|
||||||
|
var rowNode = new et2_dataview_partitionRowNode(this.getRoot(), ah);
|
||||||
|
insertNodes.push(rowNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stopIdx < this._count - 1 && stopIdx > 0)
|
||||||
|
{
|
||||||
|
// Create a spacer which contains the elements starting from
|
||||||
|
// stop index
|
||||||
|
var l = this._count - stopIdx;
|
||||||
|
insertNodes.push(new et2_dataview_partitionSpacerNode(this.getRoot(),
|
||||||
|
l, ah));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check whether insertNodes really has entrys - this is not the case
|
||||||
|
// if the given range is just outside the range of this element
|
||||||
|
if (insertNodes.length > 0)
|
||||||
|
{
|
||||||
|
// Free this element
|
||||||
|
this.free();
|
||||||
|
|
||||||
|
// Insert the newly created nodes at the original place of this node
|
||||||
|
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 [];
|
||||||
|
},
|
||||||
|
|
||||||
|
getAvgHeightData: function(_data) {
|
||||||
|
// Do nothing here, as the spacers should not be inside the average
|
||||||
|
// height statistic.
|
||||||
|
},
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
var et2_dataview_partitionRowNode = et2_dataview_partitionContainerNode.extend({
|
||||||
|
|
||||||
|
init: function(_root, _avgHeight) {
|
||||||
|
|
||||||
|
var container = new et2_dataview_row(_root.getDataProvider(),
|
||||||
|
_root.getRowProvider(), this);
|
||||||
|
|
||||||
|
this._super(_root, container);
|
||||||
|
|
||||||
|
this._avgHeight = _avgHeight;
|
||||||
|
},
|
||||||
|
|
||||||
|
initializeContainer: function() {
|
||||||
|
this._super();
|
||||||
|
|
||||||
|
this.container.setIdx(this.getStartIndex());
|
||||||
|
},
|
||||||
|
|
||||||
|
getIdxNode: function(_node, _create) {
|
||||||
|
return this.node;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
317
etemplate/js/et2_dataview_view_partitionNode.js
Normal file
317
etemplate/js/et2_dataview_view_partitionNode.js
Normal file
@ -0,0 +1,317 @@
|
|||||||
|
/**
|
||||||
|
* eGroupWare eTemplate2 - Class which contains an management tree for the grid rows
|
||||||
|
*
|
||||||
|
* @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_core_common; // for et2_range functions
|
||||||
|
et2_core_inheritance;
|
||||||
|
et2_dataview_interfaces;
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The partition node tree manages all rows in a dataview. As a dataview may have
|
||||||
|
* many thousands of lines, the rows are organized in an a tree. The leafs of the
|
||||||
|
* tree represent the single rows, upper layers represent groups of nodes.
|
||||||
|
* Each node has a "height" value and is capable of calculate the exact position
|
||||||
|
* of a row and its top and bottom value.
|
||||||
|
* Additionaly, a leaf can represent an unlimited number of rows. In this way
|
||||||
|
* the partition tree is built dynamically and is also capable of "forgetting"
|
||||||
|
* information about the rows by simply reducing the tree nodes at a certain
|
||||||
|
* position.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var et2_dataview_IPartitionHeight = new Interface({
|
||||||
|
|
||||||
|
calculateHeight: function() {}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract base class for partition nodes - contains the code for calculating
|
||||||
|
* the top, bottom, height and (start) index of the node
|
||||||
|
*/
|
||||||
|
var et2_dataview_partitionNode = Class.extend([et2_dataview_IPartitionHeight,
|
||||||
|
et2_dataview_IInvalidatable], {
|
||||||
|
|
||||||
|
init: function(_root) {
|
||||||
|
|
||||||
|
this._root = _root;
|
||||||
|
this._parent = null;
|
||||||
|
this._pidx = 0;
|
||||||
|
|
||||||
|
// Initialize the temporary storage elements
|
||||||
|
this.doInvalidate();
|
||||||
|
this._invalid = true;
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
destroy: function() {
|
||||||
|
|
||||||
|
// Remove this element from the parent children list
|
||||||
|
if (this._parent)
|
||||||
|
{
|
||||||
|
this._parent.removePIdxNode(this._pidx);
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
setParent: function(_parent) {
|
||||||
|
if (this._parent != _parent)
|
||||||
|
{
|
||||||
|
this._parent = _parent;
|
||||||
|
this.invalidate();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
setPIdx: function(_pidx) {
|
||||||
|
if (this._pidx != _pidx)
|
||||||
|
{
|
||||||
|
this._pidx = _pidx;
|
||||||
|
this.invalidate();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalidates cached values - override the "doInvalidate" function.
|
||||||
|
*
|
||||||
|
* @param _sender is the node wich originally triggerd the invalidation, can
|
||||||
|
* be ommited when calling this function.
|
||||||
|
*/
|
||||||
|
invalidate: function(_sender) {
|
||||||
|
|
||||||
|
// If the _sender parameter is not given, assume that this element is
|
||||||
|
// the one which triggered the invalidation
|
||||||
|
var origin = typeof _sender == "undefined";
|
||||||
|
|
||||||
|
if ((origin || _sender != this) && !this._invalid)
|
||||||
|
{
|
||||||
|
this.doInvalidate();
|
||||||
|
this._invalid = true;
|
||||||
|
|
||||||
|
// Invalidate the parent node
|
||||||
|
if (this._parent)
|
||||||
|
{
|
||||||
|
this._parent.invalidate(origin ? this : _sender);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs the actual invalidation.
|
||||||
|
*/
|
||||||
|
doInvalidate: function() {
|
||||||
|
this._height = false;
|
||||||
|
this._posTop = false;
|
||||||
|
this._posBottom = false;
|
||||||
|
this._startIdx = false;
|
||||||
|
this._stopIdx = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the root node of the partition tree
|
||||||
|
*/
|
||||||
|
getRoot: function() {
|
||||||
|
return this._root;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the height of this node
|
||||||
|
*/
|
||||||
|
getHeight: function() {
|
||||||
|
// Calculate the height value if it is currently invalid
|
||||||
|
if (this._height === false)
|
||||||
|
{
|
||||||
|
this._height = this.calculateHeight();
|
||||||
|
|
||||||
|
// Do a sanity check for the value - if the height wasn't a number
|
||||||
|
// it could easily destroy the posTop and posBottom values of the
|
||||||
|
// complete tree!
|
||||||
|
if (isNaN(this._height))
|
||||||
|
{
|
||||||
|
et2_debug("error", "calculateHeight returned a NaN value!");
|
||||||
|
this._height = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._invalid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._height;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the top position of the node in px
|
||||||
|
*/
|
||||||
|
getPosTop: function() {
|
||||||
|
if (this._posTop === false)
|
||||||
|
{
|
||||||
|
this._posTop = this._accumulateValue(this.getPosTop, this.getPosBottom);
|
||||||
|
|
||||||
|
this._invalid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._posTop;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the bottom position of the node in px
|
||||||
|
*/
|
||||||
|
getPosBottom: function() {
|
||||||
|
if (this._posBottom === false)
|
||||||
|
{
|
||||||
|
this._posBottom = this.getPosTop() + this.getHeight();
|
||||||
|
|
||||||
|
this._invalid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._posBottom;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an range object
|
||||||
|
*/
|
||||||
|
getRange: function() {
|
||||||
|
return {
|
||||||
|
"top": this.getPosTop(),
|
||||||
|
"bottom": this.getPosBottom()
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the node intersects with the given range
|
||||||
|
*/
|
||||||
|
inRange: function(_ar) {
|
||||||
|
return et2_rangeIntersect(this.getRange(), _ar);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the overall start index of the node
|
||||||
|
*/
|
||||||
|
getStartIndex: function() {
|
||||||
|
if (this._startIdx === false)
|
||||||
|
{
|
||||||
|
this._startIdx = this._accumulateValue(this.getStartIndex,
|
||||||
|
this.getStopIndex);
|
||||||
|
|
||||||
|
this._invalid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._startIdx;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the overall stop index of the node
|
||||||
|
*/
|
||||||
|
getStopIndex: function() {
|
||||||
|
if (this._stopIdx === false)
|
||||||
|
{
|
||||||
|
this._stopIdx = this.getStartIndex() + this.getCount();
|
||||||
|
|
||||||
|
this._invalid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._stopIdx;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the index range object
|
||||||
|
*/
|
||||||
|
getIdxRange: function() {
|
||||||
|
return {
|
||||||
|
"top": this.getStartIndex(),
|
||||||
|
"bottom": this.getStopIndex()
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether this element is inside the given index range
|
||||||
|
*/
|
||||||
|
inIdxRange: function(_idxRange) {
|
||||||
|
return et2_rangeIntersect(this.getIdxRange, _idxRange);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the count of leafs which are below this node
|
||||||
|
*/
|
||||||
|
getCount: function() {
|
||||||
|
return 1;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the nodes which reside in the given range
|
||||||
|
*/
|
||||||
|
getRangeNodes: function(_range, _create) {
|
||||||
|
if (this.inRange(_range))
|
||||||
|
{
|
||||||
|
return [this];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the nodes which are inside the given index range
|
||||||
|
*/
|
||||||
|
getIdxRangeNodes: function(_idxRange, _create) {
|
||||||
|
if (this.inIdxRange(_idxRange))
|
||||||
|
{
|
||||||
|
return [this];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the (maximum) depth of the tree
|
||||||
|
*/
|
||||||
|
getDepth: function() {
|
||||||
|
return 1;
|
||||||
|
},
|
||||||
|
|
||||||
|
getAvgHeightData: function(_data) {
|
||||||
|
_data.count++;
|
||||||
|
_data.height += this.getHeight();
|
||||||
|
},
|
||||||
|
|
||||||
|
getNodeIdx: function(_idx, _create) {
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
|
||||||
|
getRowProvider: function() {
|
||||||
|
return this.getRoot().getRowProvider();
|
||||||
|
},
|
||||||
|
|
||||||
|
getDataProvider: function() {
|
||||||
|
return this.getRoot().getDataProvider();
|
||||||
|
},
|
||||||
|
|
||||||
|
/* ---- PRIVATE FUNCTIONS ---- */
|
||||||
|
|
||||||
|
_accumulateValue: function(_f1, _f2) {
|
||||||
|
if (this._parent)
|
||||||
|
{
|
||||||
|
if (this._pidx == 0)
|
||||||
|
{
|
||||||
|
return _f1.call(this._parent);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return _f2.call(this._parent._children[this._pidx - 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
642
etemplate/js/et2_dataview_view_partitionOrganizationNode.js
Normal file
642
etemplate/js/et2_dataview_view_partitionOrganizationNode.js
Normal file
@ -0,0 +1,642 @@
|
|||||||
|
/**
|
||||||
|
* eGroupWare eTemplate2 - Class which implements the organization node
|
||||||
|
*
|
||||||
|
* @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_core_common; // for et2_range functions
|
||||||
|
et2_core_inheritance;
|
||||||
|
et2_dataview_interfaces;
|
||||||
|
et2_dataview_view_partitionNode;
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ET2_PARTITION_TREE_WIDTH defines the count of children a node will be
|
||||||
|
* created with.
|
||||||
|
*/
|
||||||
|
var ET2_PARTITION_TREE_WIDTH = 10;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An partition tree organization node can contain child nodes and organizes
|
||||||
|
* those.
|
||||||
|
*/
|
||||||
|
var et2_dataview_partitionOrganizationNode = et2_dataview_partitionNode.extend(
|
||||||
|
/*et2_dataview_IIndexOperations, */{
|
||||||
|
|
||||||
|
init: function(_root, _parent, _pidx) {
|
||||||
|
|
||||||
|
if (typeof _parent == "undefined")
|
||||||
|
{
|
||||||
|
_parent = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof _pidx == "undefined")
|
||||||
|
{
|
||||||
|
_pidx = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the parent constructor
|
||||||
|
this._super(_root);
|
||||||
|
|
||||||
|
this._children = [];
|
||||||
|
|
||||||
|
// Set the given parent and parent-index
|
||||||
|
this.setParent(_parent);
|
||||||
|
this.setPIdx(_pidx);
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
destroy: function() {
|
||||||
|
// Free all child nodes
|
||||||
|
for (var i = this._children.length - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
this._children[i].free();
|
||||||
|
}
|
||||||
|
|
||||||
|
this._super();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete the buffered element count
|
||||||
|
*/
|
||||||
|
doInvalidate: function() {
|
||||||
|
this._super();
|
||||||
|
|
||||||
|
this._count = false;
|
||||||
|
this._depth = false;
|
||||||
|
this._avgHeightData = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the count of elements by accumulating the counts of the child
|
||||||
|
* elements.
|
||||||
|
*/
|
||||||
|
getCount: function() {
|
||||||
|
if (this._count === false)
|
||||||
|
{
|
||||||
|
// Calculate the count of nodes
|
||||||
|
this._count = 0;
|
||||||
|
for (var i = 0; i < this._children.length; i++)
|
||||||
|
{
|
||||||
|
this._count += this._children[i].getCount();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._count;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the height of this node by accumulating the height of the
|
||||||
|
* child nodes.
|
||||||
|
*/
|
||||||
|
calculateHeight: function() {
|
||||||
|
var result = 0;
|
||||||
|
for (var i = 0; i < this._children.length; i++)
|
||||||
|
{
|
||||||
|
result += this._children[i].getHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the given node from the tree
|
||||||
|
*/
|
||||||
|
removeNode: function(_node) {
|
||||||
|
// Search the element on this level
|
||||||
|
for (var i = 0; i < this._children.length; i++)
|
||||||
|
{
|
||||||
|
if (this._children[i] == _node)
|
||||||
|
{
|
||||||
|
this.removePIdxNode(i);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search the element on a lower level
|
||||||
|
for (var i = 0; i < this._children.length; i++)
|
||||||
|
{
|
||||||
|
if (this._children[i] instanceof et2_dataview_partitionOrganizationNode &&
|
||||||
|
this._children[i].removeNode(_node))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the child with the given index in the _children list
|
||||||
|
*/
|
||||||
|
removePIdxNode: function(_pidx) {
|
||||||
|
// Invalidate this element
|
||||||
|
this.invalidate();
|
||||||
|
|
||||||
|
// Delete the element at the given pidx and remove the parent reference
|
||||||
|
this._children.splice(_pidx, 1)[0].setParent(null);
|
||||||
|
|
||||||
|
// Recalculate the pidx of the children behind the one removed
|
||||||
|
for (var i = _pidx; i < this._children.length; i++)
|
||||||
|
{
|
||||||
|
this._children[i]._pidx--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the child with the given overall index
|
||||||
|
*/
|
||||||
|
removeIdxNode: function(_idx) {
|
||||||
|
return this._iterateToIndex(_idx, function(ei, bi, child) {
|
||||||
|
if (child.implements(et2_dataview_IIndexOperations))
|
||||||
|
{
|
||||||
|
return child.removeIdxNode(_idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.removePIdxNode(i);
|
||||||
|
}, false);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the node with the given overall index and null if it is not found
|
||||||
|
*/
|
||||||
|
getIdxNode: function(_idx) {
|
||||||
|
return this._iterateToIndex(_idx, function(ei, bi, child) {
|
||||||
|
if (child.implements(et2_dataview_IIndexOperations))
|
||||||
|
{
|
||||||
|
return child.getIdxNode()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idx == bi)
|
||||||
|
{
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
}, 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
|
||||||
|
*/
|
||||||
|
getRangeNodes: function(_range, _create) {
|
||||||
|
|
||||||
|
if (typeof _create == "undefined")
|
||||||
|
{
|
||||||
|
_create = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = [];
|
||||||
|
|
||||||
|
// Create a copy of the children of this element, as the child list may
|
||||||
|
// change due to new children being inserted.
|
||||||
|
var children = this._copyChildren();
|
||||||
|
|
||||||
|
// We did not have a intersect in the range now
|
||||||
|
var hadIntersect = false;
|
||||||
|
for (var i = 0; i < children.length; i++)
|
||||||
|
{
|
||||||
|
if (children[i].inRange(_range))
|
||||||
|
{
|
||||||
|
hadIntersect = true;
|
||||||
|
|
||||||
|
var res = children[i].getRangeNodes(_range, _create);
|
||||||
|
|
||||||
|
if (res === false)
|
||||||
|
{
|
||||||
|
return this.getRangeNodes(_range, _create);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append the search results of the given element
|
||||||
|
result = result.concat(res);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Abort as we are out of the range where intersects can happen
|
||||||
|
if (hadIntersect)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the nodes which are inside the given range
|
||||||
|
*/
|
||||||
|
getIdxRangeNodes: function(_idxRange, _create) {
|
||||||
|
|
||||||
|
if (typeof _create == "undefined")
|
||||||
|
{
|
||||||
|
_create = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = [];
|
||||||
|
|
||||||
|
// Create a copy of the children of this element, as the child list may
|
||||||
|
// change due to new children being inserted.
|
||||||
|
var children = this._copyChildren();
|
||||||
|
|
||||||
|
// We did not have a intersect in the range now
|
||||||
|
var hadIntersect = false;
|
||||||
|
for (var i = 0; i < children.length; i++)
|
||||||
|
{
|
||||||
|
if (children[i].inIdxRange(_idxRange))
|
||||||
|
{
|
||||||
|
hadIntersect = true;
|
||||||
|
|
||||||
|
// Append the search results of the given element
|
||||||
|
var res = children[i].getIdxRangeNodes(_idxRange,
|
||||||
|
_create);
|
||||||
|
|
||||||
|
if (res === false)
|
||||||
|
{
|
||||||
|
return this.getIdxRangeNodes(_idxRange, _create);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = result.concat(res);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Abort as we are out of the range where intersects can happen
|
||||||
|
if (hadIntersect)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reduces the given range to a spacer
|
||||||
|
*/
|
||||||
|
reduceRange: function(_range) {
|
||||||
|
this._reduce(this.getRangeNodes(_range, false))
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reduces the given index range to a spacer
|
||||||
|
*/
|
||||||
|
reduceIdxRange: function(_range) {
|
||||||
|
this._reduce(this.getIdxRangeNodes(_range, false));
|
||||||
|
},
|
||||||
|
|
||||||
|
getDepth: function() {
|
||||||
|
if (this._depth === false)
|
||||||
|
{
|
||||||
|
this._depth = 0;
|
||||||
|
|
||||||
|
// Get the maximum depth and increase it by one
|
||||||
|
for (var i = 0; i < this._children.length; i++)
|
||||||
|
{
|
||||||
|
this._depth = Math.max(this._depth, this._children[i].getDepth());
|
||||||
|
}
|
||||||
|
this._depth++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._depth;
|
||||||
|
},
|
||||||
|
|
||||||
|
_insertLeft: function(_idx, _nodes) {
|
||||||
|
// Check whether the node left to the given index can still take some
|
||||||
|
// nodes - if yes, insert the maximum amount of nodes into this node
|
||||||
|
if (_idx > 0 && this._children[_idx - 1] instanceof et2_dataview_partitionOrganizationNode
|
||||||
|
&& this._children[_idx - 1]._children.length < ET2_PARTITION_TREE_WIDTH)
|
||||||
|
{
|
||||||
|
// Calculate how many children can be inserted into the left node
|
||||||
|
var child = this._children[_idx - 1];
|
||||||
|
var c = Math.min(ET2_PARTITION_TREE_WIDTH - child._children.length, _nodes.length);
|
||||||
|
|
||||||
|
// Insert the remaining children into the left node
|
||||||
|
if (c > 0)
|
||||||
|
{
|
||||||
|
var nodes = _nodes.splice(0, c);
|
||||||
|
child.insertNodes(child._children.length, nodes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_insertRight: function(_idx, _nodes) {
|
||||||
|
// Check whether the node right to the given index can still take some
|
||||||
|
// nodes - if yes, insert the nodes there
|
||||||
|
if (_idx < this._children.length &&
|
||||||
|
this._children[_idx] instanceof et2_dataview_partitionOrganizationNode &&
|
||||||
|
this._children[_idx]._children.length < ET2_PARTITION_TREE_WIDTH)
|
||||||
|
{
|
||||||
|
var child = this._children[_idx];
|
||||||
|
var c = Math.min(ET2_PARTITION_TREE_WIDTH - child._children.length, _nodes.length);
|
||||||
|
|
||||||
|
// Insert the remaining children into the left node
|
||||||
|
if (c > 0)
|
||||||
|
{
|
||||||
|
var nodes = _nodes.splice(_nodes.length - c, c);
|
||||||
|
child.insertNodes(0, nodes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Groups the nodes which should be inserted by packages of ten and insert
|
||||||
|
* those as children. If there are more than ET2_PARTITION_TREE_WIDTH
|
||||||
|
* children as a result of this action, this node gets destroyed and the
|
||||||
|
* children are given to the parent node.
|
||||||
|
*/
|
||||||
|
insertNodes: function(_idx, _nodes) {
|
||||||
|
// Break if no nodes are to be inserted
|
||||||
|
if (_nodes.length == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invalidate this node
|
||||||
|
this.invalidate();
|
||||||
|
|
||||||
|
// Try to insert the given objects into an organization node at the left
|
||||||
|
// or right side of the given index
|
||||||
|
this._insertLeft(_idx, _nodes);
|
||||||
|
this._insertRight(_idx, _nodes);
|
||||||
|
|
||||||
|
// Update the pidx of the nodes after _idx
|
||||||
|
for (var i = _idx; i < this._children.length; i++)
|
||||||
|
{
|
||||||
|
this._children[i].setPIdx(i + _nodes.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the parent and the pidx of the new nodes
|
||||||
|
for (var i = 0; i < _nodes.length; i++)
|
||||||
|
{
|
||||||
|
_nodes[i].setParent(this);
|
||||||
|
_nodes[i].setPIdx(_idx + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simply insert the nodes at the given position
|
||||||
|
this._children.splice.apply(this._children, [_idx, 0].concat(_nodes));
|
||||||
|
|
||||||
|
// Check whether the width of this element is greater than ET2_PARTITION_TREE_WIDTH
|
||||||
|
// If yes, split the children into groups of ET2_PARTITION_TREE_WIDTH and
|
||||||
|
// insert those into this node
|
||||||
|
/*if (this._children.length > ET2_PARTITION_TREE_WIDTH)
|
||||||
|
{
|
||||||
|
var insertNodes = [];
|
||||||
|
|
||||||
|
while (_nodes.length > 0)
|
||||||
|
{
|
||||||
|
var orgaNode = new et2_dataview_partitionOrganizationNode(this,
|
||||||
|
insertNodes.length);
|
||||||
|
|
||||||
|
// Get groups of ET2_PARTITION_TREE_WIDTH from the nodes while
|
||||||
|
// reading the first level of nodes from organization nodes
|
||||||
|
var newNodes = [];
|
||||||
|
var isPartial = false;
|
||||||
|
while (newNodes.length < ET2_PARTITION_TREE_WIDTH && _nodes.length > 0)
|
||||||
|
{
|
||||||
|
var node = _nodes[0];
|
||||||
|
|
||||||
|
if (!(node instanceof et2_dataview_partitionOrganizationNode))
|
||||||
|
{
|
||||||
|
newNodes.push(_nodes.shift());
|
||||||
|
isPartial = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (node._children.length == 0)
|
||||||
|
{
|
||||||
|
// Remove the node from the list and free it
|
||||||
|
_nodes.shift().free();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!isPartial && node._children.length == ET2_PARTITION_TREE_WIDTH)
|
||||||
|
{
|
||||||
|
newNodes.push(_nodes.shift());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newNodes = newNodes.concat(node._children.splice(0,
|
||||||
|
ET2_PARTITION_TREE_WIDTH - newNodes.length));
|
||||||
|
isPartial = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
orgaNode.insertNodes(0, newNodes);
|
||||||
|
|
||||||
|
insertNodes.push(orgaNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._children = [];
|
||||||
|
this.insertNodes(0, insertNodes);
|
||||||
|
}*/
|
||||||
|
},
|
||||||
|
|
||||||
|
rebuild: function() {
|
||||||
|
// Get all leafs
|
||||||
|
var children = [];
|
||||||
|
this._getFlatList(children);
|
||||||
|
|
||||||
|
// Free all organization nodes
|
||||||
|
this._clear();
|
||||||
|
|
||||||
|
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(this._avgHeightData);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._invalid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Increment the data object entries by the buffered avg height data
|
||||||
|
_data.count += this._avgHeightData.count;
|
||||||
|
_data.height += this._avgHeightData.height;
|
||||||
|
},
|
||||||
|
|
||||||
|
debug: function() {
|
||||||
|
var children = [];
|
||||||
|
var offs = false;
|
||||||
|
this._getFlatList(children);
|
||||||
|
|
||||||
|
for (var i = 0; i < children.length; i++)
|
||||||
|
{
|
||||||
|
var idx = children[i].getStartIndex();
|
||||||
|
var node = children[i].getNodeAt(idx);
|
||||||
|
|
||||||
|
if (node)
|
||||||
|
{
|
||||||
|
if (offs === false)
|
||||||
|
{
|
||||||
|
offs = node.offset().top;
|
||||||
|
}
|
||||||
|
|
||||||
|
var actualTop = node.offset().top - offs;
|
||||||
|
var calculatedTop = children[i].getPosTop();
|
||||||
|
|
||||||
|
if (Math.abs(actualTop - calculatedTop) > 1)
|
||||||
|
{
|
||||||
|
et2_debug("warn", i, "Position missmatch at idx ", idx,
|
||||||
|
actualTop, calculatedTop, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
var actualHeight = node.outerHeight(true);
|
||||||
|
var calculateHeight = children[i].getHeight();
|
||||||
|
|
||||||
|
if (Math.abs(actualHeight - calculateHeight) > 1)
|
||||||
|
{
|
||||||
|
et2_debug("warn", i, "Height missmatch at idx ", idx,
|
||||||
|
actualHeight, calculateHeight, node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/* ---- PRIVATE FUNCTIONS ---- */
|
||||||
|
|
||||||
|
_copyChildren: function() {
|
||||||
|
// Copy the child array as querying the child nodes may change the tree
|
||||||
|
var children = new Array(this._children.length);
|
||||||
|
for (var i = 0; i < this._children.length; i++)
|
||||||
|
{
|
||||||
|
children[i] = this._children[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return children;
|
||||||
|
},
|
||||||
|
|
||||||
|
_iterateToIndex: function(_idx, _func, _res) {
|
||||||
|
for (var i = 0; i < this._children.length; i++)
|
||||||
|
{
|
||||||
|
var child = this._children[i];
|
||||||
|
|
||||||
|
var bi = child.getStartIndex();
|
||||||
|
var ei = child.getStopIndex();
|
||||||
|
|
||||||
|
if (bi > _idx)
|
||||||
|
{
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bi <= _idx && ei > _idx)
|
||||||
|
{
|
||||||
|
return _func.call(this, bi, ei, child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reduces the given nodes to a single spacer
|
||||||
|
*/
|
||||||
|
_reduce: function(_nodes) {
|
||||||
|
/* if (_nodes.length == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check whether the first or last node is a spacer, if not create
|
||||||
|
// a new one
|
||||||
|
var ph;
|
||||||
|
if (_nodes[0] instanceof et2_dataview_partitionSpacerNode)
|
||||||
|
{
|
||||||
|
ph = _nodes[0]
|
||||||
|
}
|
||||||
|
else if (_nodes[_nodes.length - 1] instanceof et2_dataview_partitionSpacerNode)
|
||||||
|
{
|
||||||
|
ph = _nodes[_nodes.length - 1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Create a new spacer node and insert it at the place of the
|
||||||
|
// first node of the range
|
||||||
|
ph = new et2_dataview_partitionSpacerNode(this.getRoot(), 0, 0);
|
||||||
|
this.getRoot().insertNodes(_nodes[0].getStartIndex(), [ph]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the height of the resulting spacer
|
||||||
|
var height = _nodes[_nodes.length - 1].getPosBottom() - _nodes[0].getPosTop();
|
||||||
|
|
||||||
|
// Get the count of actual elements in the nodes
|
||||||
|
var count = 0;
|
||||||
|
for (var i = 0; i < _nodes.length; i++)
|
||||||
|
{
|
||||||
|
count += _nodes[i].getCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the spacer parameters
|
||||||
|
et2_debug("log", "Spacer new height, count: ", height, count);
|
||||||
|
ph.setAvgHeight(height / count);
|
||||||
|
ph.setCount(count);
|
||||||
|
|
||||||
|
// Free all elements (except for the spacer)
|
||||||
|
for (var i = _nodes.length - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
if (_nodes[i] != ph)
|
||||||
|
{
|
||||||
|
_nodes[i].free();
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used when rebuilding the tree
|
||||||
|
*/
|
||||||
|
_getFlatList: function(_res) {
|
||||||
|
for (var i = 0; i < this._children.length; i++)
|
||||||
|
{
|
||||||
|
if (this._children[i] instanceof et2_dataview_partitionOrganizationNode)
|
||||||
|
{
|
||||||
|
this._children[i]._getFlatList(_res);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_res.push(this._children[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_clear: function() {
|
||||||
|
for (var i = this._children.length - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
if (this._children[i] instanceof et2_dataview_partitionOrganizationNode)
|
||||||
|
{
|
||||||
|
this._children[i].free();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this._children = [];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -16,37 +16,22 @@
|
|||||||
et2_dataview_interfaces;
|
et2_dataview_interfaces;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var __cc = 0;
|
|
||||||
|
|
||||||
var et2_dataview_row = et2_dataview_container.extend(et2_dataview_IDataRow, {
|
var et2_dataview_row = et2_dataview_container.extend(et2_dataview_IDataRow, {
|
||||||
|
|
||||||
init: function(_dataProvider, _rowProvider, _invalidationElem, _idx) {
|
init: function(_dataProvider, _rowProvider, _invalidationElem, _avgHeight) {
|
||||||
|
|
||||||
this._super(_dataProvider, _rowProvider, _invalidationElem);
|
this._super(_dataProvider, _rowProvider, _invalidationElem);
|
||||||
|
|
||||||
__cc += 5;
|
this._avgHeight = _avgHeight;
|
||||||
|
|
||||||
this.tr = this.rowProvider.getPrototype("default");
|
this.tr = this.rowProvider.getPrototype("default");
|
||||||
$j("div", this.tr).text("Blub" + (__cc / 5))
|
|
||||||
.height(20 + Math.round(Math.random() * 100))
|
|
||||||
.css("background-color", "rgb(" +
|
|
||||||
(255 - __cc % 255) + "," +
|
|
||||||
(__cc % 255) + "," +
|
|
||||||
((__cc * 2) % 255) +
|
|
||||||
")");
|
|
||||||
this.appendNode(this.tr);
|
this.appendNode(this.tr);
|
||||||
|
|
||||||
// Register this row in the dataprovider - if data is available for this
|
|
||||||
// row the "updateData" function will be called immediately.
|
|
||||||
//this.dataProvider.registerDataRow(_idx, this);
|
|
||||||
|
|
||||||
// if (this.tr == null)
|
|
||||||
// {
|
|
||||||
// }
|
|
||||||
},
|
},
|
||||||
|
|
||||||
destroy: function() {
|
setIdx: function(_idx) {
|
||||||
//this.dataProvider.unregisterDataRow(_idx);
|
this._idx = _idx;
|
||||||
|
|
||||||
|
$j("div:first", this.tr).text(_idx + ":");
|
||||||
},
|
},
|
||||||
|
|
||||||
updateData: function(_data) {
|
updateData: function(_data) {
|
||||||
|
@ -21,8 +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_view_gridContainer;
|
||||||
et2_dataview_dataProvider;
|
et2_dataview_model_dataProvider;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -40,12 +40,15 @@
|
|||||||
<script src="../et2_dataview_model_dataProvider.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_rowProvider.js"></script>
|
||||||
|
<script src="../et2_dataview_view_partitionNode.js"></script>
|
||||||
|
<script src="../et2_dataview_view_partitionOrganizationNode.js"></script>
|
||||||
|
<script src="../et2_dataview_view_partitionContainerNodes.js"></script>
|
||||||
<script src="../et2_dataview_view_partitionTree.js"></script>
|
<script src="../et2_dataview_view_partitionTree.js"></script>
|
||||||
<script src="../et2_dataview_view_grid.js"></script>
|
<script src="../et2_dataview_view_grid.js"></script>
|
||||||
<script src="../et2_dataview_view_container.js"></script>
|
<script src="../et2_dataview_view_container.js"></script>
|
||||||
<script src="../et2_dataview_view_row.js"></script>
|
<script src="../et2_dataview_view_row.js"></script>
|
||||||
<script src="../et2_dataview_view_spacer.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>
|
||||||
<script src="../lib/tooltip.js"></script>
|
<script src="../lib/tooltip.js"></script>
|
||||||
|
Loading…
Reference in New Issue
Block a user