diff --git a/etemplate/js/et2_dataview_controller.js b/etemplate/js/et2_dataview_controller.js index 72cd960b27..c2e434fed5 100644 --- a/etemplate/js/et2_dataview_controller.js +++ b/etemplate/js/et2_dataview_controller.js @@ -54,10 +54,11 @@ var et2_dataview_controller = Class.extend({ * @param _actionObjectManager is the object that manages the action * objects. */ - init: function (_grid, _dataProvider, _rowCallback, _linkCallback, _context, - _actionObjectManager) + init: function (_parentController, _grid, _dataProvider, _rowCallback, + _linkCallback, _context, _actionObjectManager) { // Copy the given arguments + this._parentController = _parentController; this._grid = _grid; this._dataProvider = _dataProvider; this._rowCallback = _rowCallback; @@ -79,9 +80,14 @@ var et2_dataview_controller = Class.extend({ this._grid.setDataCallback(this._gridCallback, this); // Create the selection manager - this._selectionMgr = new et2_dataview_selectionManager(this._indexMap, - _actionObjectManager, this._selectionFetchRange, - this._makeIndexVisible, this); + this._selectionMgr = new et2_dataview_selectionManager( + this._parentController ? this._parentController._selectionMgr : null, + this._indexMap, + _actionObjectManager, + this._selectionFetchRange, + this._makeIndexVisible, + this + ); }, destroy: function () { @@ -92,7 +98,6 @@ var et2_dataview_controller = Class.extend({ // Clear the selection timeout this._clearTimer(); - this._super(); }, /** @@ -161,6 +166,19 @@ var et2_dataview_controller = Class.extend({ } }, + /** + * Returns the depth of the controller instance. + */ + getDepth: function () { + + if (this._parentController) + { + return this._parentController.getDepth() + 1; + } + + return 0; + }, + /* -- PRIVATE FUNCTIONS -- */ @@ -442,7 +460,6 @@ var et2_dataview_controller = Class.extend({ this.entry.row.clear(); // Fill the row DOM Node with data - var tr = this.entry.row.getDOMNode(); this.self._rowCallback.call( this.self._context, _data, @@ -451,6 +468,15 @@ var et2_dataview_controller = Class.extend({ this.entry ); + // Attach the "subgrid" tag to the row, if the depth of this + // controller is larger than zero + var tr = this.entry.row.getDOMNode(); + var d = this.self.getDepth(); + if (d > 0) + { + $j(tr).addClass("subentry level_" + d); + } + var links = null; // Get the action links if the links callback is set diff --git a/etemplate/js/et2_dataview_controller_selection.js b/etemplate/js/et2_dataview_controller_selection.js index 58c1922600..bbb2cdb8c1 100644 --- a/etemplate/js/et2_dataview_controller_selection.js +++ b/etemplate/js/et2_dataview_controller_selection.js @@ -27,15 +27,23 @@ */ var et2_dataview_selectionManager = Class.extend({ - init: function (_indexMap, _actionObjectManager, _queryRangeCallback, - _makeVisibleCallback, _context) { + init: function (_parent, _indexMap, _actionObjectManager, + _queryRangeCallback, _makeVisibleCallback, _context) { + // Copy the arguments + this._parent = _parent; this._indexMap = _indexMap; this._actionObjectManager = _actionObjectManager; this._queryRangeCallback = _queryRangeCallback; this._makeVisibleCallback = _makeVisibleCallback; this._context = _context; + // Attach this manager to the parent manager if one is given + if (this._parent) + { + this._parent._children.push(this); + } + // Internal map which contains all curently selected uids and their // state this._registeredRows = {}; @@ -43,6 +51,29 @@ var et2_dataview_selectionManager = Class.extend({ this._invertSelection = false; this._inUpdate = false; this._total = 0; + this._children = []; + }, + + destroy: function () { + + // If we have a parent, unregister from that + if (this._parent) + { + var idx = this._parent._children.indexOf(this); + this._parent._children.splice(idx, 1); + } + + // Destroy all children + for (var i = this._children.length - 1; i >= 0; i--) + { + this._children[i].free(); + } + + // Delete all still registered rows + for (var key in this._registeredRows) + { + this.unregisterRow(key, this._registeredRows[key].tr); + } }, setIndexMap: function (_indexMap) { @@ -169,6 +200,12 @@ var et2_dataview_selectionManager = Class.extend({ } } + // Push all events of the child managers onto the list + for (var i = 0; i < this._children.length; i++) + { + ids = ids.concat(this._children[i].getSelected().ids); + } + // Return an array containing those ids return { "inverted": this._invertSelection, @@ -360,6 +397,7 @@ var et2_dataview_selectionManager = Class.extend({ if (!_ctrl) { this.resetSelection(); + this._actionObjectManager.setAllSelected(false); // needed for hirachical stuff } // Mark the element that was clicked as selected diff --git a/etemplate/js/et2_dataview_view_grid.js b/etemplate/js/et2_dataview_view_grid.js index b66869a20b..ddefc9825f 100644 --- a/etemplate/js/et2_dataview_view_grid.js +++ b/etemplate/js/et2_dataview_view_grid.js @@ -79,6 +79,8 @@ var et2_dataview_grid = et2_dataview_container.extend(et2_dataview_IViewRange, { this._parentGrid = _parentGrid; + this._scrollTimeout = null; + this._invalidateTimeout = null; this._invalidateCallback = null; @@ -106,6 +108,9 @@ var et2_dataview_grid = et2_dataview_container.extend(et2_dataview_IViewRange, { }, destroy: function () { + // Destroy all containers + this.setTotalCount(0); + // Stop the scroll timeout if (this._scrollTimeout) { @@ -118,9 +123,6 @@ var et2_dataview_grid = et2_dataview_container.extend(et2_dataview_IViewRange, { window.clearTimeout(this._invalidateTimeout); } - // Destroy all containers - this.setTotalCount(0); - this._super(); }, diff --git a/etemplate/js/et2_dataview_view_row.js b/etemplate/js/et2_dataview_view_row.js index e1b0960894..259c0374bf 100644 --- a/etemplate/js/et2_dataview_view_row.js +++ b/etemplate/js/et2_dataview_view_row.js @@ -43,6 +43,16 @@ var et2_dataview_row = et2_dataview_container.extend(et2_dataview_IViewRange, { this.expansionButton = null; }, + destroy: function () { + + if (this.expansionContainer != null) + { + this.expansionContainer.free(); + } + + this._super(); + }, + clear: function() { this.tr.empty(); }, @@ -54,7 +64,7 @@ var et2_dataview_row = et2_dataview_container.extend(et2_dataview_IViewRange, { if (!this.expansionButton) { this.expansionButton = $j(document.createElement("span")); - this.expansionButton.addClass("arrow closed").text(">"); + this.expansionButton.addClass("arrow closed"); var self = this; this.expansionButton.click(function () { @@ -74,7 +84,7 @@ var et2_dataview_row = et2_dataview_container.extend(et2_dataview_IViewRange, { if (this.expansionContainer) { - this.expansionContainer.removeFromTree(); + this.expansionContainer.free(); } this.expansionButton = null; diff --git a/etemplate/js/et2_extension_nextmatch.js b/etemplate/js/et2_extension_nextmatch.js index 083a06a589..e511024841 100644 --- a/etemplate/js/et2_extension_nextmatch.js +++ b/etemplate/js/et2_extension_nextmatch.js @@ -544,6 +544,7 @@ var et2_nextmatch = et2_DOMWidget.extend(et2_IResizeable, { // Create the grid controller this.controller = new et2_nextmatch_controller( + null, this.egw(), this.getInstanceManager().etemplate_exec_id, "nm", @@ -580,25 +581,34 @@ var et2_nextmatch = et2_DOMWidget.extend(et2_IResizeable, { } }, - _getSubgrid: function (_row, _parentId) { + _getSubgrid: function (_row, _data, _controller) { + // Fetch the id of the element described by _data, this will be the + // parent_id of the elements in the subgrid + var rowId = _data.content[this.options.settings.row_id]; + // Create a new grid with the row as parent and the dataview grid as // parent grid var grid = new et2_dataview_grid(_row, this.dataview.grid); // Create a new controller for the grid var controller = new et2_nextmatch_controller( + _controller, this.egw(), this.getInstanceManager().etemplate_exec_id, "nm", - _parentId, + rowId, grid, this.rowProvider, this.options.settings.action_links, - null, - this.options.settings.actions + _controller.getObjectManager() ); controller.update(); + // Register inside the destruction callback of the grid + grid.setDestroyCallback(function () { + controller.free(); + }); + return grid; }, diff --git a/etemplate/js/et2_extension_nextmatch_controller.js b/etemplate/js/et2_extension_nextmatch_controller.js index 7dd0ec6923..2f03dcc24b 100644 --- a/etemplate/js/et2_extension_nextmatch_controller.js +++ b/etemplate/js/et2_extension_nextmatch_controller.js @@ -31,6 +31,7 @@ var et2_nextmatch_controller = et2_dataview_controller.extend( /** * Initializes the nextmatch controller. * + * @param _parentController is the parent nextmatch controller instance * @param _egw is the api instance * @param _execId is the execId of the etemplate * @param _widgetId is the id of the nextmatch-widget we are fetching data @@ -43,8 +44,8 @@ var et2_nextmatch_controller = et2_dataview_controller.extend( * @param _actions contains the actions, may be null if an object manager * is given. */ - init: function (_egw, _execId, _widgetId, _parentId, _grid, _rowProvider, - _actionLinks, _objectManager, _actions) { + init: function (_parentController, _egw, _execId, _widgetId, _parentId, + _grid, _rowProvider, _actionLinks, _objectManager, _actions) { // Copy the egw reference this.egw = _egw; @@ -61,8 +62,8 @@ var et2_nextmatch_controller = et2_dataview_controller.extend( } // Call the parent et2_dataview_controller constructor - this._super(_grid, this, this._rowCallback, this._linkCallback, this, - this._objectManager); + this._super(_parentController, _grid, this, this._rowCallback, + this._linkCallback, this, this._objectManager); // Copy the given parameters this._actionLinks = _actionLinks @@ -100,6 +101,10 @@ var et2_nextmatch_controller = et2_dataview_controller.extend( this._lastModification = null; }, + getObjectManager: function () { + return this._objectManager; + }, + /** -- PRIVATE FUNCTIONS -- **/ @@ -163,7 +168,7 @@ var et2_nextmatch_controller = et2_dataview_controller.extend( // Let the row provider fill in the data row -- store the returned // rowWidget inside the _entry _entry.widget = this._rowProvider.getDataRow( - { "content": _data }, _tr, _idx); + { "content": _data }, _tr, _idx, this); }, /** @@ -184,7 +189,7 @@ var et2_nextmatch_controller = et2_dataview_controller.extend( // Merge the parent id into the _queriedRange if it is set if (this._parentId !== null) { - _queriedRange["parent_id"] = _queriedRange; + _queriedRange["parent_id"] = this._parentId; } // Pass the fetch call to the API, multiplex the data about the diff --git a/etemplate/js/et2_extension_nextmatch_rowProvider.js b/etemplate/js/et2_extension_nextmatch_rowProvider.js index 5f81913b13..ca7512f8ce 100644 --- a/etemplate/js/et2_extension_nextmatch_rowProvider.js +++ b/etemplate/js/et2_extension_nextmatch_rowProvider.js @@ -88,7 +88,7 @@ var et2_nextmatch_rowProvider = Class.extend({ this._template = rowTemplate; }, - getDataRow: function(_data, _row, _idx) { + getDataRow: function(_data, _row, _idx, _controller) { // Clone the row template var row = this._dataRow.cloneNode(true); @@ -168,7 +168,7 @@ var et2_nextmatch_rowProvider = Class.extend({ { _row.makeExpandable(true, function () { return this._subgridCallback.call(this._context, - _row, _data.content["parent_id"]); + _row, _data, _controller); }, this); }