diff --git a/etemplate/js/et2_dataview.js b/etemplate/js/et2_dataview.js index 5474925b7f..97bbb40d8c 100644 --- a/etemplate/js/et2_dataview.js +++ b/etemplate/js/et2_dataview.js @@ -437,7 +437,7 @@ var et2_dataview = Class.extend({ 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.egw, this.rowProvider, 19); + this.grid = new et2_dataview_grid(null, null, this.egw, this.rowProvider, 19); // Insert the grid into the DOM-Tree var tr = $j(this.grid._nodes[0]); diff --git a/etemplate/js/et2_dataview_controller.js b/etemplate/js/et2_dataview_controller.js index ea97f39802..72cd960b27 100644 --- a/etemplate/js/et2_dataview_controller.js +++ b/etemplate/js/et2_dataview_controller.js @@ -446,7 +446,7 @@ var et2_dataview_controller = Class.extend({ this.self._rowCallback.call( this.self._context, _data, - tr, + this.entry.row, this.entry.idx, this.entry ); diff --git a/etemplate/js/et2_dataview_controller_selection.js b/etemplate/js/et2_dataview_controller_selection.js index 98fe5623cb..58c1922600 100644 --- a/etemplate/js/et2_dataview_controller_selection.js +++ b/etemplate/js/et2_dataview_controller_selection.js @@ -394,20 +394,24 @@ var et2_dataview_selectionManager = Class.extend({ this._indexMap[i].uid) { // Add the range to the "queryRanges" - if (naStart !== false) { + if (naStart !== false) + { queryRanges.push(et2_bounds(naStart, i - 1)); naStart = false; } // Select the element this.setSelected(this._indexMap[i].uid, true); - } else if (naStart === false) { + } + else if (naStart === false) + { naStart = i; } } // Add the last range to the "queryRanges" - if (naStart !== false) { + if (naStart !== false) + { queryRanges.push(et2_bounds(naStart, i - 1)); naStart = false; } diff --git a/etemplate/js/et2_dataview_view_container.js b/etemplate/js/et2_dataview_view_container.js index 925f29d2a0..aeedaa0ad8 100644 --- a/etemplate/js/et2_dataview_view_container.js +++ b/etemplate/js/et2_dataview_view_container.js @@ -157,7 +157,7 @@ var et2_dataview_container = Class.extend(et2_dataview_IInvalidatable, { // tree. if (this._inTree) { - if (_nodes.length === 1) + if (this._nodes.length === 1) { if (this._attachData.prepend) { @@ -170,7 +170,7 @@ var et2_dataview_container = Class.extend(et2_dataview_IInvalidatable, { } else { - _node.after(this._nodes[this._nodes.length - 2]); + this._nodes[this._nodes.length - 2].after(_node); } this.invalidate(); diff --git a/etemplate/js/et2_dataview_view_grid.js b/etemplate/js/et2_dataview_view_grid.js index 0ed70aeed2..b66869a20b 100644 --- a/etemplate/js/et2_dataview_view_grid.js +++ b/etemplate/js/et2_dataview_view_grid.js @@ -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. * @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 this._super(_parent); // If the parent is given, copy all other parameters from it - if (_parent != null) + if (_parentGrid != null) { this.egw = _parent.egw; this._orgAvgHeight = false; - this._rowProvider = _parent._rowProvider; + this._rowProvider = _parentGrid._rowProvider; } else { @@ -77,6 +77,8 @@ var et2_dataview_grid = et2_dataview_container.extend(et2_dataview_IViewRange, { this._scrollTimeout = null; } + this._parentGrid = _parentGrid; + this._invalidateTimeout = null; this._invalidateCallback = null; @@ -483,17 +485,11 @@ var et2_dataview_grid = et2_dataview_container.extend(et2_dataview_IViewRange, { } var self = this; + var _super = this._super; this._invalidateTimeout = window.setTimeout(function() { self._invalidateTimeout = null; - self._doInvalidate(); + self._doInvalidate(_super); }, 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 * containers have to be removed and where new containers should be added. */ - _doInvalidate: function() { + _doInvalidate: function(_super) { // Update the pixel positions 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 // corresponding interface and request elements for all visible spacers 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")) .addClass("frame") .attr("colspan", this._rowProvider.getColumnCount() - + (this._parent ? 0 : 1)) + + (this._parentGrid ? 0 : 1)) .appendTo(this.tr); // Create the scrollarea div if this is the outer grid this.scrollarea = null; - if (this._parent == null) + if (this._parentGrid == null) { this.scrollarea = $j(document.createElement("div")) .addClass("egwGridView_scrollarea") @@ -1347,7 +1350,7 @@ var et2_dataview_grid = et2_dataview_container.extend(et2_dataview_IViewRange, { .appendTo(table); // Set the tr as container element - this.appendNode(this.tr[0]); + this.appendNode($j(this.tr[0])); } }); diff --git a/etemplate/js/et2_dataview_view_row.js b/etemplate/js/et2_dataview_view_row.js index ed0f6838aa..e1b0960894 100644 --- a/etemplate/js/et2_dataview_view_row.js +++ b/etemplate/js/et2_dataview_view_row.js @@ -18,7 +18,7 @@ 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 @@ -33,18 +33,148 @@ var et2_dataview_row = et2_dataview_container.extend({ // Create the outer "tr" tag and append it to the container this.tr = $j(document.createElement("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() { 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]; }, - getJNode: function() { + getJNode: function () { 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); + } } }); diff --git a/etemplate/js/et2_extension_nextmatch_actions.js b/etemplate/js/et2_extension_nextmatch_actions.js index 3d6886b11d..7c4fcbb44b 100644 --- a/etemplate/js/et2_extension_nextmatch_actions.js +++ b/etemplate/js/et2_extension_nextmatch_actions.js @@ -28,13 +28,19 @@ function nm_action(_action, _senders, _target, _ids) // ---------------------- // 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 = ""; for (var i = 0; i < idsArr.length; i++) { - var app_id = idsArr[i].split('::', 2); - var id = app_id[1]; + var id = idsArr[i]; ids += (id.indexOf(',') >= 0 ? '"'+id.replace(/"/g,'""')+'"' : id) + ((i < idsArr.length - 1) ? "," : ""); } diff --git a/etemplate/js/et2_extension_nextmatch_rowProvider.js b/etemplate/js/et2_extension_nextmatch_rowProvider.js index 0a3aa1527e..3f3c977ac3 100644 --- a/etemplate/js/et2_extension_nextmatch_rowProvider.js +++ b/etemplate/js/et2_extension_nextmatch_rowProvider.js @@ -86,7 +86,7 @@ var et2_nextmatch_rowProvider = Class.extend({ this._template = rowTemplate; }, - getDataRow: function(_data, _tr, _idx) { + getDataRow: function(_data, _row, _idx) { // Clone the row template var row = this._dataRow.cloneNode(true); @@ -157,10 +157,11 @@ var et2_nextmatch_rowProvider = Class.extend({ } // Insert the row into the tr - _tr.appendChild(row); + var tr = _row.getDOMNode(); + tr.appendChild(row); // Set the row data - this._setRowData(this._template.rowData, _tr, mgrs); + this._setRowData(this._template.rowData, tr, mgrs); return rowWidget; }, diff --git a/etemplate/js/test/test_dataview.html b/etemplate/js/test/test_dataview.html index 99122119e7..329e424416 100644 --- a/etemplate/js/test/test_dataview.html +++ b/etemplate/js/test/test_dataview.html @@ -128,11 +128,23 @@ * the actual DOM-Nodes for a node with the given data have to be * created. */ - function rowCallback(_data, _tr, _idx) + function rowCallback(_data, _row, _idx) { + var tr = _row.getDOMNode(); + var row = dataview.rowProvider.getPrototype("default"); $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() {