Implemented hirachical rows

This commit is contained in:
Andreas Stöckel 2012-03-30 11:43:39 +00:00
parent d7bd469ed9
commit 1d405d05ba
9 changed files with 189 additions and 33 deletions

View File

@ -437,7 +437,7 @@ var et2_dataview = Class.extend({
this.rowProvider = new et2_dataview_rowProvider(this.uniqueId, colIds); this.rowProvider = new et2_dataview_rowProvider(this.uniqueId, colIds);
// Create the grid class and pass "19" as the starting average row height // Create the grid class and pass "19" as the starting average row height
this.grid = new et2_dataview_grid(null, this.egw, this.rowProvider, 19); this.grid = new et2_dataview_grid(null, null, this.egw, this.rowProvider, 19);
// Insert the grid into the DOM-Tree // Insert the grid into the DOM-Tree
var tr = $j(this.grid._nodes[0]); var tr = $j(this.grid._nodes[0]);

View File

@ -446,7 +446,7 @@ var et2_dataview_controller = Class.extend({
this.self._rowCallback.call( this.self._rowCallback.call(
this.self._context, this.self._context,
_data, _data,
tr, this.entry.row,
this.entry.idx, this.entry.idx,
this.entry this.entry
); );

View File

@ -394,20 +394,24 @@ var et2_dataview_selectionManager = Class.extend({
this._indexMap[i].uid) this._indexMap[i].uid)
{ {
// Add the range to the "queryRanges" // Add the range to the "queryRanges"
if (naStart !== false) { if (naStart !== false)
{
queryRanges.push(et2_bounds(naStart, i - 1)); queryRanges.push(et2_bounds(naStart, i - 1));
naStart = false; naStart = false;
} }
// Select the element // Select the element
this.setSelected(this._indexMap[i].uid, true); this.setSelected(this._indexMap[i].uid, true);
} else if (naStart === false) { }
else if (naStart === false)
{
naStart = i; naStart = i;
} }
} }
// Add the last range to the "queryRanges" // Add the last range to the "queryRanges"
if (naStart !== false) { if (naStart !== false)
{
queryRanges.push(et2_bounds(naStart, i - 1)); queryRanges.push(et2_bounds(naStart, i - 1));
naStart = false; naStart = false;
} }

View File

@ -157,7 +157,7 @@ var et2_dataview_container = Class.extend(et2_dataview_IInvalidatable, {
// tree. // tree.
if (this._inTree) if (this._inTree)
{ {
if (_nodes.length === 1) if (this._nodes.length === 1)
{ {
if (this._attachData.prepend) if (this._attachData.prepend)
{ {
@ -170,7 +170,7 @@ var et2_dataview_container = Class.extend(et2_dataview_IInvalidatable, {
} }
else else
{ {
_node.after(this._nodes[this._nodes.length - 2]); this._nodes[this._nodes.length - 2].after(_node);
} }
this.invalidate(); this.invalidate();

View File

@ -53,17 +53,17 @@ var et2_dataview_grid = et2_dataview_container.extend(et2_dataview_IViewRange, {
* parameters are ignored and copied from the given grid instance. * parameters are ignored and copied from the given grid instance.
* @param _avgHeight is the starting average height of the column rows. * @param _avgHeight is the starting average height of the column rows.
*/ */
init: function (_parent, _egw, _rowProvider, _avgHeight) { init: function (_parent, _parentGrid, _egw, _rowProvider, _avgHeight) {
// Call the inherited constructor // Call the inherited constructor
this._super(_parent); this._super(_parent);
// If the parent is given, copy all other parameters from it // If the parent is given, copy all other parameters from it
if (_parent != null) if (_parentGrid != null)
{ {
this.egw = _parent.egw; this.egw = _parent.egw;
this._orgAvgHeight = false; this._orgAvgHeight = false;
this._rowProvider = _parent._rowProvider; this._rowProvider = _parentGrid._rowProvider;
} }
else else
{ {
@ -77,6 +77,8 @@ var et2_dataview_grid = et2_dataview_container.extend(et2_dataview_IViewRange, {
this._scrollTimeout = null; this._scrollTimeout = null;
} }
this._parentGrid = _parentGrid;
this._invalidateTimeout = null; this._invalidateTimeout = null;
this._invalidateCallback = null; this._invalidateCallback = null;
@ -483,17 +485,11 @@ var et2_dataview_grid = et2_dataview_container.extend(et2_dataview_IViewRange, {
} }
var self = this; var self = this;
var _super = this._super;
this._invalidateTimeout = window.setTimeout(function() { this._invalidateTimeout = window.setTimeout(function() {
self._invalidateTimeout = null; self._invalidateTimeout = null;
self._doInvalidate(); self._doInvalidate(_super);
}, ET2_GRID_INVALIDATE_TIMEOUT); }, ET2_GRID_INVALIDATE_TIMEOUT);
// Call the inherited invalidate function, broadcast the invalidation
// through the container tree.
if (this._parent !== null)
{
this._super();
}
}, },
/** /**
@ -805,7 +801,7 @@ var et2_dataview_grid = et2_dataview_container.extend(et2_dataview_IViewRange, {
* Invalidate iterates over the "mapping" array. It calculates which * Invalidate iterates over the "mapping" array. It calculates which
* containers have to be removed and where new containers should be added. * containers have to be removed and where new containers should be added.
*/ */
_doInvalidate: function() { _doInvalidate: function(_super) {
// Update the pixel positions // Update the pixel positions
this._recalculateElementPosition(); this._recalculateElementPosition();
@ -831,6 +827,13 @@ var et2_dataview_grid = et2_dataview_container.extend(et2_dataview_IViewRange, {
// Update the view range of all visible elements that implement the // Update the view range of all visible elements that implement the
// corresponding interface and request elements for all visible spacers // corresponding interface and request elements for all visible spacers
this._updateContainers(); this._updateContainers();
// Call the inherited invalidate function, broadcast the invalidation
// through the container tree.
if (this._parent && _super)
{
_super.call(this);
}
}, },
/** /**
@ -1294,12 +1297,12 @@ var et2_dataview_grid = et2_dataview_container.extend(et2_dataview_IViewRange, {
this.outerCell = $j(document.createElement("td")) this.outerCell = $j(document.createElement("td"))
.addClass("frame") .addClass("frame")
.attr("colspan", this._rowProvider.getColumnCount() .attr("colspan", this._rowProvider.getColumnCount()
+ (this._parent ? 0 : 1)) + (this._parentGrid ? 0 : 1))
.appendTo(this.tr); .appendTo(this.tr);
// Create the scrollarea div if this is the outer grid // Create the scrollarea div if this is the outer grid
this.scrollarea = null; this.scrollarea = null;
if (this._parent == null) if (this._parentGrid == null)
{ {
this.scrollarea = $j(document.createElement("div")) this.scrollarea = $j(document.createElement("div"))
.addClass("egwGridView_scrollarea") .addClass("egwGridView_scrollarea")
@ -1347,7 +1350,7 @@ var et2_dataview_grid = et2_dataview_container.extend(et2_dataview_IViewRange, {
.appendTo(table); .appendTo(table);
// Set the tr as container element // Set the tr as container element
this.appendNode(this.tr[0]); this.appendNode($j(this.tr[0]));
} }
}); });

View File

@ -18,7 +18,7 @@
et2_dataview_view_container; et2_dataview_view_container;
*/ */
var et2_dataview_row = et2_dataview_container.extend({ var et2_dataview_row = et2_dataview_container.extend(et2_dataview_IViewRange, {
/** /**
* Creates the row container. Use the "setRow" function to load the actual * Creates the row container. Use the "setRow" function to load the actual
@ -33,18 +33,148 @@ var et2_dataview_row = et2_dataview_container.extend({
// Create the outer "tr" tag and append it to the container // Create the outer "tr" tag and append it to the container
this.tr = $j(document.createElement("tr")); this.tr = $j(document.createElement("tr"));
this.appendNode(this.tr); this.appendNode(this.tr);
// Grid row which gets expanded when clicking on the corresponding
// button
this.expansionContainer = null;
this.expansionVisible = false;
// Toggle button which is used to show and hide the expansionContainer
this.expansionButton = null;
}, },
clear: function() { clear: function() {
this.tr.empty(); this.tr.empty();
}, },
getDOMNode: function() { makeExpandable: function (_expandable, _callback, _context) {
if (_expandable)
{
// Create the tr and the button if this has not been done yet
if (!this.expansionButton)
{
this.expansionButton = $j(document.createElement("span"));
this.expansionButton.addClass("arrow closed").text(">");
var self = this;
this.expansionButton.click(function () {
self._handleExpansionButtonClick(_callback, _context);
});
$j("td:first", this.tr).prepend(this.expansionButton);
}
}
else
{
// If the row is made non-expandable, remove the created DOM-Nodes
if (this.expansionButton)
{
this.expansionButton.remove();
}
if (this.expansionContainer)
{
this.expansionContainer.removeFromTree();
}
this.expansionButton = null;
this.expansionContainer = null;
}
},
removeFromTree: function () {
if (this.expansionContainer)
{
this.expansionContainer.removeFromTree();
}
this.expansionContainer = null;
this.expansionButton = null;
this._super();
},
getDOMNode: function () {
return this.tr[0]; return this.tr[0];
}, },
getJNode: function() { getJNode: function () {
return this.tr; return this.tr;
},
getHeight: function () {
var h = this._super();
if (this.expansionContainer && this.expansionVisible)
{
h += this.expansionContainer.getHeight();
}
return h;
},
getAvgHeightData: function() {
// Only take the height of the own tr into account
var oldVisible = this.expansionVisible;
this.expansionVisible = false;
var res = {
"avgHeight": this.getHeight(),
"avgCount": 1
}
this.expansionVisible = true;
return res;
},
/** -- PRIVATE FUNCTIONS -- **/
_handleExpansionButtonClick: function (_callback, _context) {
// Create the "expansionContainer" if it does not exist yet
if (!this.expansionContainer)
{
this.expansionContainer = _callback.call(_context);
this.expansionContainer.insertIntoTree(this.tr);
this.expansionVisible = false;
}
// Toggle the visibility of the expansion tr
this.expansionVisible = !this.expansionVisible;
$j(this.expansionContainer._nodes[0]).toggle(this.expansionVisible);
// Set the class of the arrow
if (this.expansionVisible)
{
this.expansionButton.addClass("opened");
this.expansionButton.removeClass("closed");
}
else
{
this.expansionButton.addClass("closed");
this.expansionButton.removeClass("opened");
}
this.invalidate();
},
/** -- Implementation of et2_dataview_IViewRange -- **/
setViewRange: function (_range) {
if (this.expansionContainer && this.expansionVisible
&& this.expansionContainer.implements(et2_dataview_IViewRange))
{
// Substract the height of the own row from the container
var oh = $j(this._nodes[0]).height()
_range.top -= oh;
// Proxy the setViewRange call to the expansion container
this.expansionContainer.setViewRange(_range);
}
} }
}); });

View File

@ -28,13 +28,19 @@ function nm_action(_action, _senders, _target, _ids)
// ---------------------- // ----------------------
// TODO: Parse the _ids.inverted flag! // TODO: Parse the _ids.inverted flag!
// ---------------------- // ----------------------
var idsArr = _ids.ids;
// Translate the internal uids back to server uids
var idsArr = _ids.ids;
for (var i = 0; i < idsArr.length; i++)
{
idsArr[i] = idsArr[i].split("::").pop();
}
// Calculate the ids parameters
var ids = ""; var ids = "";
for (var i = 0; i < idsArr.length; i++) for (var i = 0; i < idsArr.length; i++)
{ {
var app_id = idsArr[i].split('::', 2); var id = idsArr[i];
var id = app_id[1];
ids += (id.indexOf(',') >= 0 ? '"'+id.replace(/"/g,'""')+'"' : id) + ids += (id.indexOf(',') >= 0 ? '"'+id.replace(/"/g,'""')+'"' : id) +
((i < idsArr.length - 1) ? "," : ""); ((i < idsArr.length - 1) ? "," : "");
} }

View File

@ -86,7 +86,7 @@ var et2_nextmatch_rowProvider = Class.extend({
this._template = rowTemplate; this._template = rowTemplate;
}, },
getDataRow: function(_data, _tr, _idx) { getDataRow: function(_data, _row, _idx) {
// Clone the row template // Clone the row template
var row = this._dataRow.cloneNode(true); var row = this._dataRow.cloneNode(true);
@ -157,10 +157,11 @@ var et2_nextmatch_rowProvider = Class.extend({
} }
// Insert the row into the tr // Insert the row into the tr
_tr.appendChild(row); var tr = _row.getDOMNode();
tr.appendChild(row);
// Set the row data // Set the row data
this._setRowData(this._template.rowData, _tr, mgrs); this._setRowData(this._template.rowData, tr, mgrs);
return rowWidget; return rowWidget;
}, },

View File

@ -128,11 +128,23 @@
* the actual DOM-Nodes for a node with the given data have to be * the actual DOM-Nodes for a node with the given data have to be
* created. * created.
*/ */
function rowCallback(_data, _tr, _idx) function rowCallback(_data, _row, _idx)
{ {
var tr = _row.getDOMNode();
var row = dataview.rowProvider.getPrototype("default"); var row = dataview.rowProvider.getPrototype("default");
$j("div", row).each(function () { $j(this).text("#" + _idx + " " + _data.caption) }); $j("div", row).each(function () { $j(this).text("#" + _idx + " " + _data.caption) });
$j(_tr).append(row.children()); $j(tr).append(row.children());
_row.makeExpandable(true, function () {
var grid = new et2_dataview_grid(_row, dataview.grid);
var controller = new et2_dataview_controller(grid,
new dataprovider(), rowCallback, linkCallback, null,
objectManager);
controller.update();
return grid;
});
} }
function linkCallback() { function linkCallback() {