Added code for creating widget-rows in the dataview

This commit is contained in:
Andreas Stöckel 2011-09-05 14:35:28 +00:00
parent 366bad914d
commit d037187234
11 changed files with 312 additions and 28 deletions

View File

@ -151,7 +151,7 @@ var et2_DOMWidget = et2_widget.extend(et2_IDOMNode, {
}
// Append this node at its index
var idx = this._parent ? this._parent.getChildren().indexOf(this) : -1;
var idx = this.getDOMIndex();
if (idx < 0 || idx >= this.parentNode.childNodes.length - 1)
{
this.parentNode.appendChild(node);
@ -210,6 +210,31 @@ var et2_DOMWidget = et2_widget.extend(et2_IDOMNode, {
return this.parentNode;
},
/**
* Returns the index of this element in the DOM tree
*/
getDOMIndex: function() {
if (this._parent)
{
var idx = 0;
var children = this._parent.getChildren();
for (var i = 0; i < children.length; i++)
{
if (children[i] == this)
{
return idx;
}
else if (children[i].isInTree())
{
idx++;
}
}
}
return -1;
},
/**
* Sets the id of the DOM-Node.
*/

View File

@ -43,7 +43,6 @@ var et2_arrayMgr = Class.extend({
this.perspectiveData = {
"owner": null,
"key": null,
"col": 0,
"row": 0
}
},
@ -217,7 +216,7 @@ var et2_arrayMgr = Class.extend({
return et2_evalBool(val);
},
openPerspective: function(_owner, _root, _col, _row)
openPerspective: function(_owner, _root, _row)
{
// Get the root node
var root = typeof _root == "string" ? this.data[_root] :
@ -235,10 +234,9 @@ var et2_arrayMgr = Class.extend({
mgr.perspectiveData.key = _root;
}
// Set the _col and _row parameter
if (typeof _col != "undefined" && typeof _row != "undefined")
// Set _row parameter
if (typeof _row != "undefined")
{
mgr.perspectiveData.col = _col;
mgr.perspectiveData.row = _row;
}
@ -283,4 +281,26 @@ var et2_readonlysArrayMgr = et2_arrayMgr.extend({
});
/**
* Creates a new set of array managers
*/
function et2_arrayMgrs_expand(_owner, _mgrs, _data, _row)
{
// Create a copy of the given _mgrs associative array
var result = {};
// Merge the given data associative array into the existing array managers
for (var key in _data)
{
if (typeof _mgrs[key] != "undefined")
{
// Open a perspective for the given data row
result[key] = _mgrs[key].openPerspective(_owner,
_data[key], _row);
}
}
// Return the resulting managers object
return result;
}

View File

@ -229,10 +229,14 @@ var et2_widget = Class.extend({
this._parent.removeChild(this);
}
// Delete all references to other objects
this._children = [];
this._parent = null;
this._mgrs = {};
// Free the array managers if they belong to this widget
for (var key in this._mgrs)
{
if (this._mgrs[key] && this._mgrs[key].owner == this)
{
this._mgrs[key].free();
}
}
},
/**

View File

@ -19,12 +19,16 @@
var et2_dataview_dataProvider = Class.extend({
init: function() {
this.updateQueue = 0;
},
getCount: function() {
return 10000;
},
registerDataRow: function(_idx, _dataRow) {
var row = {
registerDataRow: function(_dataRow, _idx) {
/* var row = {
"type": "dataRow",
"data": {
"ts_title": "Row " + _idx
@ -41,7 +45,12 @@ var et2_dataview_dataProvider = Class.extend({
}
window.setTimeout(function() {_dataRow.updateData(row); },
Math.round(rnd / 2));
Math.round(rnd / 2));*/
// All data rows are updated independently of all others - this allows
// user input between generation of the widgets.
window.setTimeout(function() {_dataRow.updateData({"readonlys": {"__ALL__": true}});}, 0);
},
unregisterDataRow: function(_dataRow) {

View File

@ -28,7 +28,7 @@ var ET2_GRID_VIEW_EXT = 25;
/**
* 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;
@ -46,7 +46,8 @@ var et2_dataview_grid = Class.extend(et2_dataview_IViewRange, {
* classes.
* @param _avgHeight is the starting average height of the column rows.
*/
init: function(_parent, _outerId, _columnIds, _dataProvider, _avgHeight) {
init: function(_parent, _outerId, _columnIds, _dataProvider, _rowProvider,
_avgHeight) {
// If the parent is given, copy all other parameters from it
if (_parent != null)
@ -63,12 +64,9 @@ var et2_dataview_grid = Class.extend(et2_dataview_IViewRange, {
this._outerId = _outerId;
this._columnIds = _columnIds;
this._dataProvider = _dataProvider;
this._rowProvider = _rowProvider;
this._avgHeight = _avgHeight;
// Create the row provider
this._rowProvider = new et2_dataview_rowProvider(_outerId,
_columnIds);
this._scrollHeight = 0;
this._scrollTimeout = null;
}
@ -112,9 +110,8 @@ var et2_dataview_grid = Class.extend(et2_dataview_IViewRange, {
// Stop the rebuild timer
window.clearInterval(this._rebuildTimer);
// Free the partition tree and the row provider
// Free the partition tree
this._partitionTree.free();
this._rowProvider.free();
},
/**

View File

@ -52,6 +52,7 @@ var et2_dataview_gridContainer = Class.extend({
this.columnNodes = []; // Array with the header containers
this.columns = [];
this.columnMgr = null;
this.rowProvider = null;
this.grid = null;
@ -80,6 +81,12 @@ var et2_dataview_gridContainer = Class.extend({
this.grid.free();
}
// Free the row provider
if (this.rowProvider)
{
this.rowProvider.free();
}
// Detatch the outer element
this.table.remove();
},
@ -375,9 +382,17 @@ var et2_dataview_gridContainer = Class.extend({
colIds[i] = this.columns[i].id;
}
// Create the row provider
if (this.rowProvider)
{
this.rowProvider.free();
}
this.rowProvider = new et2_dataview_rowProvider(this.uniqueId, colIds);
// Create the grid class and pass "19" as the starting average row height
this.grid = new et2_dataview_grid(null, this.uniqueId, colIds,
this.dataProvider, 19);
this.dataProvider, this.rowProvider, 19);
// Insert the grid into the DOM-Tree
this.containerTr.append(this.grid.getJNode());

View File

@ -236,11 +236,9 @@ var et2_dataview_partitionRowNode = et2_dataview_partitionContainerNode.extend({
init: function(_root, _avgHeight) {
var container = new et2_dataview_row(_root.getDataProvider(),
_root.getRowProvider(), this);
_root.getRowProvider(), this, _avgHeight);
this._super(_root, container);
this._avgHeight = _avgHeight;
},
initializeContainer: function() {

View File

@ -24,19 +24,66 @@ var et2_dataview_row = et2_dataview_container.extend(et2_dataview_IDataRow, {
this._avgHeight = _avgHeight;
this.rowWidget = null;
this.hasAvgHeight = false;
// Get the default row object and scale the row to the average height
this.tr = this.rowProvider.getPrototype("default");
// Append the row
this.appendNode(this.tr);
},
destroy: function() {
// Unregister the row from the data provider
this.dataProvider.unregisterDataRow(this);
// Free the row widget first, if it has been set
if (this.rowWidget)
{
this.rowWidget.free();
}
this._super();
},
setIdx: function(_idx) {
this._idx = _idx;
$j("div:first", this.tr)
.text(_idx + ":")
.height((_idx % 10) * 10 + 20);
// Register the row in the data provider
this.dataProvider.registerDataRow(this, _idx);
// Set the default height of the rowWidget has not been immediately
// created
if (!this.rowWidget)
{
$j("td:first", this.tr).height(this._avgHeight);
this.hasAvgHeight = true;
}
},
updateData: function(_data) {
// Reset the height
if (this.hasAvgHeight)
{
$j("td:first", this.tr).height("auto");
this.hasAvgHeight = false;
}
// Free the row widget if it already existed
if (this.rowWidget != null)
{
this.rowWidget.free();
}
// Create the row widget - it automatically generates the widgets and
// attaches the given data to them
this.rowWidget = this.rowProvider.getDataRow(_data, this.tr, this._idx);
// Invalidate this element
this.invalidate();
}
});

View File

@ -13,6 +13,9 @@
/*egw:uses
jquery.jquery;
et2_core_inheritance;
et2_core_interfaces;
et2_core_arrayMgr;
et2_core_widget;
*/
/**
@ -27,6 +30,10 @@ var et2_dataview_rowProvider = Class.extend({
this._columnIds = _columnIds;
this._prototypes = {};
this._dataRowTemplate = null;
this._mgrs = null;
this._rootWidget = null;
// Create the default row "prototypes"
this._createFullRowPrototype();
this._createDefaultPrototype();
@ -55,6 +62,25 @@ var et2_dataview_rowProvider = Class.extend({
return this._prototypes[_name].clone();
},
setDataRowTemplate: function(_template, _rootWidget) {
this._dataRowTemplate = _template;
this._rootWidget = _rootWidget;
},
getDataRow: function(_data, _row, _idx) {
// Create the row widget
var rowWidget = new et2_dataview_rowWidget(this._rootWidget, _row[0]);
// Create array managers with the given data merged in
var mgrs = et2_arrayMgrs_expand(rowWidget, this._rootWidget.getArrayMgrs(),
_data, _idx);
// Let the row widget create the widgets
rowWidget.createWidgets(mgrs, this._dataRowTemplate);
return rowWidget;
},
/* ---- PRIVATE FUNCTIONS ---- */
_createFullRowPrototype: function() {
@ -93,3 +119,56 @@ var et2_dataview_rowProvider = Class.extend({
});
var et2_dataview_rowWidget = et2_widget.extend(et2_IDOMNode, {
init: function(_parent, _row) {
// Call the parent constructor with some dummy attributes
this._super(_parent, {"id": "", "type": "rowWidget"});
// Initialize some variables
this._widgets = [];
// Copy the given DOM node
this._row = _row;
},
/**
* Copies the given array manager and clones the given widgets and inserts
* them into the row which has been passed in the constructor.
*/
createWidgets: function(_mgrs, _widgets) {
// Set the array managers - don't use setArrayMgrs here as this creates
// an unnecessary copy of the object
this._mgrs = _mgrs;
// Clone the given the widgets with this element as parent
this._widgets = new Array(_widgets.length);
for (var i = 0; i < _widgets.length; i++)
{
this._widgets[i] = _widgets[i].clone(this);
this._widgets[i].loadingFinished();
}
},
/**
* Returns the column node for the given sender
*/
getDOMNode: function(_sender) {
if (typeof _sender == "undefined" || !_sender)
{
return this.row;
}
for (var i = 0; i < this._widgets.length; i++)
{
if (this._widgets[i] == _sender)
{
return this._row.childNodes[i]; // Return the i-th td tag
}
}
}
});

View File

@ -214,6 +214,27 @@ var et2_nextmatch = et2_DOMWidget.extend(et2_IResizeable, {
},
_parseDataRow: function(_row, _colData) {
var columnWidgets = new Array(this.columns.length);
for (var x = 0; x < columnWidgets.length; x++)
{
if (typeof _row[x] != "undefined" && _row[x].widget)
{
columnWidgets[x] = _row[x].widget;
// Append the widget to this container
this.addChild(_row[x].widget);
}
else
{
columnWidgets[x] = _row[x].widget;
}
}
this.dataviewContainer.rowProvider.setDataRowTemplate(columnWidgets, this);
},
_parseGrid: function(_grid) {
// Search the rows for a header-row - if one is found, parse it
for (var y = 0; y < _grid.rowData.length; y++)
@ -222,6 +243,10 @@ var et2_nextmatch = et2_DOMWidget.extend(et2_IResizeable, {
{
this._parseHeaderRow(_grid.cells[y], _grid.colData);
}
else
{
this._parseDataRow(_grid.cells[y], _grid.colData);
}
}
},

View File

@ -62,6 +62,71 @@
</vbox>
<nextmatch-sortheader label="last changed" id="info_datemodified" options="DESC"/>
</row>
<row class="$row_cont[info_cat] $row_cont[class]" valign="top">
<hbox align="center" options="5">
<image label="$row_cont[info_type]" src="${row}[info_type]"/>
<button statustext="Change the status of an entry, eg. close it" label="$row_cont[info_status_label]" id="edit_status[$row_cont[info_id]]" onclick="window.open(egw::link('/index.php','menuaction=infolog.infolog_ui.edit&amp;info_id=$row_cont[info_id]'),'_blank','dependent=yes,width=750,height=600,scrollbars=yes,status=yes'); return false;" image="$row_cont[info_status_label]" ro_image="$row_cont[info_status_label]"/>
<button statustext="Change the status of an entry, eg. close it" label="$row_cont[info_percent]" id="edit_percent[$row_cont[info_id]]" onclick="window.open(egw::link('/index.php','menuaction=infolog.infolog_ui.edit&amp;info_id=$row_cont[info_id]'),'_blank','dependent=yes,width=750,height=600,scrollbars=yes,status=yes'); return false;" image="$row_cont[info_percent]"/>
<image label="$row_cont[info_percent2]" src="{$row}[info_percent2]" onclick="window.open(egw::link('/index.php','menuaction=infolog.infolog_ui.edit&amp;info_id=$row_cont[info_id]'),'_blank','dependent=yes,width=750,height=600,scrollbars=yes,status=yes'); return false;"/>
</hbox>
<vbox options="0,0" class="fullWidth">
<link label="%s $row_cont[info_addr]" id="${row}[info_link]" options="b"/>
<hbox options="0,0">
<description id="${row}[info_subject]" no_lang="1" class="$row_cont[sub_class]"/>
<description align="right" id="{$row}[info_number]" no_lang="1" class="infoId"/>
</hbox>
<box class="infoDes">
<description id="${row}[info_des]" no_lang="1" options=",,1"/>
</box>
<link-string id="${row}[filelinks]"/>
</vbox>
<customfields-list id="$row" class="customfields"/>
<menulist>
<menupopup type="select-cat" id="${row}[info_cat]" readonly="true"/>
</menulist>
<vbox cols="1" rows="3" options="0,0,1">
<date-time id="${row}[info_startdate]" readonly="true" options=",8" class="fixedHeight"/>
<date id="${row}[info_enddate]" readonly="true" class="$row_cont[end_class] fixedHeight"/>
<date-time id="${row}[info_datecompleted]" readonly="true" class="fixedHeight"/>
</vbox>
<vbox cols="1" rows="3" options="0,0">
<hbox readonly="true">
<hbox readonly="true" options="1,0">
<date-duration id="${row}[info_used_time]" readonly="true" options="@duration_format"/>
<date-duration id="${row}[info_sum_timesheets]" readonly="true" options="@duration_format" class="timesheet"/>
</hbox>
<description/>
</hbox>
<date-duration id="${row}[info_planned_time]" readonly="true" options="@duration_format" span="all" class="planned"/>
</vbox>
<vbox cols="1" rows="3" options="0,0">
<hbox id="r_used_time" options="1,0">
<image label="Times" src="timesheet"/>
<date-duration id="${row}[info_used_time]" readonly="true" options="@duration_format"/>
<date-duration id="${row}[info_sum_timesheets]" readonly="true" options="@duration_format" class="timesheet"/>
</hbox>
<hbox id="planified" options="1,0">
<image label="planned time" src="k_alarm.png"/>
<date-duration id="${row}[info_planned_time]" readonly="true" options="@duration_format" span="all" class="planned"/>
</hbox>
<hbox id="replanified" options="1,0">
<image label="Re-planned time" src="agt_reload.png"/>
<date-duration id="${row}[info_replanned_time]" readonly="true" options="@duration_format" span="all" class="replanned"/>
</hbox>
</vbox>
<vbox options="0,0">
<menulist>
<menupopup type="select-account" id="${row}[info_owner]" readonly="true"/>
</menulist>
<listbox type="select-account" id="${row}[info_responsible]" readonly="true" rows="5"/>
</vbox>
<vbox options="0" orient="0">
<date-time id="${row}[info_datemodified]" readonly="true"/>
<menulist>
<menupopup type="select-account" id="${row}[info_modifier]" readonly="true"/>
</menulist>
</vbox>
</row>
</rows>
</grid>
</template>