diff --git a/etemplate/js/et2_core_interfaces.js b/etemplate/js/et2_core_interfaces.js index 106738ea9a..9bf340fb27 100644 --- a/etemplate/js/et2_core_interfaces.js +++ b/etemplate/js/et2_core_interfaces.js @@ -70,5 +70,19 @@ var et2_IResizeable = new Interface({ resize: function() {} }); +/** + * Interface for widgets which want to e.g. perform clientside validation before + * the form is submitted. + */ +var et2_ISubmitListener = new Interface({ + /** + * Called whenever the template gets submitted. Return false if you want to + * stop submission. + * + * @param _values contains the values which will be sent to the server. + * Listeners may change these values before they get submitted. + */ + submit: function(_values) {} +}); diff --git a/etemplate/js/et2_core_stylesheet.js b/etemplate/js/et2_core_stylesheet.js index 03c1da6ea2..6791af65e4 100644 --- a/etemplate/js/et2_core_stylesheet.js +++ b/etemplate/js/et2_core_stylesheet.js @@ -17,7 +17,7 @@ * rules - updating a single stylesheet rule is way more efficient than updating * the element style of many objects. */ -var EGW_DYNAMIC_STYLESHEET = null; +var ET2_DYNAMIC_STYLESHEET = null; /** * Main egwDynStyleSheet class - all egwDynStyleSheets share the same stylesheet @@ -26,8 +26,8 @@ var EGW_DYNAMIC_STYLESHEET = null; */ function et2_dynStyleSheet() { - // Check whether the EGW_DYNAMIC_STYLESHEET has already be created - if (!EGW_DYNAMIC_STYLESHEET) + // Check whether the ET2_DYNAMIC_STYLESHEET has already be created + if (!ET2_DYNAMIC_STYLESHEET) { var style = document.createElement("style"); document.getElementsByTagName("head")[0].appendChild(style); @@ -36,13 +36,13 @@ function et2_dynStyleSheet() this.selectors = {}; this.selectorCount = 0; - EGW_DYNAMIC_STYLESHEET = this; + ET2_DYNAMIC_STYLESHEET = this; return this; } else { - return EGW_DYNAMIC_STYLESHEET; + return ET2_DYNAMIC_STYLESHEET; } } diff --git a/etemplate/js/et2_dataview_model_columns.js b/etemplate/js/et2_dataview_model_columns.js new file mode 100755 index 0000000000..89203a40ba --- /dev/null +++ b/etemplate/js/et2_dataview_model_columns.js @@ -0,0 +1,405 @@ +/** + * eGroupWare egw_action framework - egw action framework + * + * @link http://www.egroupware.org + * @author Andreas Stöckel + * @copyright 2011 by Andreas Stöckel + * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License + * @package egw_action + * @version $Id$ + */ + +/*egw:uses + et2_inheritance; +*/ + +var ET2_COL_TYPE_DEFAULT = 0; +var ET2_COL_TYPE_NAME_ICON_FIXED = 1; + +var ET2_COL_VISIBILITY_ALWAYS = 0; +var ET2_COL_VISIBILITY_VISIBLE = 1; +var ET2_COL_VISIBILITY_INVISIBLE = 2; +var ET2_COL_VISIBILITY_ALWAYS_NOSELECT = 3; + +/** + * Class which stores the data of a single column. + */ +var et2_dataview_column = Class.extend({ + + attributes: { + "id": { + "name": "ID", + "type": "string", + "description": "Unique identifier for this column. It is used to " + + "store changed column widths or visibilities." + }, + "visibility": { + "name": "Visibility", + "type": "integer", + "default": ET2_COL_VISIBILITY_VISIBLE, + "description": "Defines the visibility state of this column." + }, + "caption": { + "name": "Caption", + "type": "string", + "description": "Caption of the column as it is displayed in the " + + "select columns popup." + }, + "type": { + "name": "Column type", + "type": "integer", + "default": ET2_COL_TYPE_DEFAULT, + "description": "Type of the column" + }, + "width": { + "name": "Width", + "type": "dimension", + "default": "auto", + "description": "Width of the column." + }, + "maxWidth": { + "name": "Maximum width", + "type": "integer", + "default": 0, + "description": "Maximum width of the column" + } + }, + + init: function(_attrs) { + this.fixedWidth = false; + this.relativeWidth = false; + + // Do the sanity check on the attributes and load them + this.generateAttributeSet(_attrs); + this.initAttributes(_attrs); + }, + + set_width: function(_value) { + // Parse the width parameter. Posible values are: + // 1. "100" => fixedWidth 100px + // 2. "100px" => fixedWidth 100px + // 3. "50%" => relativeWidth 50% + // 4. "auto" => fixedWidth false, relativeWidth false + this.relativeWidth = false; + this.fixedWidth = false; + var w = _value; + + if (w.charAt(w.length - 1) == "%" && !isNaN(w.substr(0, w.length - 1))) + { + this.relativeWidth = parseInt(w.substr(0, w.length - 1)) / 100; + + // Relative widths with more than 100% are not allowed! + if (this.relativeWidth > 1) + { + this.relativeWidth = false; + } + } + else if (w.substr(w.length - 2, 2) == "px" && !isNaN(w.substr(0, w.length - 2))) + { + this.fixedWidth = parseInt(w.substr(0, w.length - 2)); + } + } + +}); + +/** + * Contains logic for the columns class. The columns class represents the unique set + * of columns a grid view owns. The parameters of the columns (except for visibility) + * do normaly not change. + */ + +var et2_dataview_columns = Class.extend({ + + init: function(_columnData) { + // Initialize some variables + this.totalWidth = 0; + this.columnWidths = []; + + // Create the columns object + this.columns = new Array(_columnData.length); + for (var i = 0; i < _columnData.length; i++) + { + this.columns[i] = new et2_dataview_column(_columnData[i]); + } + + this.updated = true; + }, + + destroy: function() { + // Free all column objects + for (var i = 0; i < this.columns.length; i++) + { + this.columns[i].free(); + } + }, + + /** + * Set the total width of the header row + */ + setTotalWidth: function(_width) { + if (_width != this.totalWidth && _width > 0) + { + this.totalWidth = _width; + this.updated = true; + } + }, + + /** + * Returns the index of the colum with the given id + */ + getColumnIndexById: function(_id) { + for (var i = 0; i < this.columns.length; i++) + { + if (this.columns[i].id == _id) + { + return i; + } + } + return -1; + }, + + /** + * Returns the column with the given id + */ + getColumnById: function(_id) { + var idx = this.getColumnIndexById(_id); + return (idx == -1) ? null : this.columns[idx]; + }, + + /** + * Returns the width of the column with the given index + */ + getColumnWidth: function(_idx) { + if (this.totalWidth > 0 && _idx >= 0 && _idx < this.columns.length) + { + // Recalculate the column widths if something has changed. + if (this.updated) + { + this._calculateWidths(); + this.updated = false; + } + + // Return the calculated width for the column with the given index. + return this.columnWidths[_idx]; + } + + return 0; + }, + + /** + * Returns an array containing the width of the column and its visibility + * state. + */ + getColumnData: function() { + var result = []; + + for (var i = 0; i < this.columns.length; i++) + { + result.push({ + "id": this.columns[i].id, + "width": this.getColumnWidth(i), + "visible": this.columns[i].visibility != ET2_COL_VISIBILITY_INVISIBLE + }); + } + + return result; + }, + + /** + * Returns an associative array which contains data about the visibility + * state of the columns. + */ + getColumnVisibilitySet: function() { + var result = {}; + + for (var i = 0; i < this.columns.length; i++) + { + if (this.columns[i].visibility != ET2_COL_VISIBILITY_ALWAYS_NOSELECT) + { + result[this.columns[i].id] = { + "caption": this.columns[i].caption, + "enabled": (this.columns[i].visibility != ET2_COL_VISIBILITY_ALWAYS) && + (this.columns[i].type != ET2_COL_TYPE_NAME_ICON_FIXED), + "visible": this.columns[i].visibility != ET2_COL_VISIBILITY_INVISIBLE + }; + } + } + + return result; + }, + + /** + * Sets a column visiblity set + */ + setColumnVisibilitySet: function(_set) { + for (var k in _set) + { + var col = this.getColumnById(k); + if (col) + { + col.set_visibility(_set[k].visible ? ET2_COL_VISIBILITY_VISIBLE : + ET2_COL_VISIBILITY_INVISIBLE); + } + } + + this.updated = true; + }, + + /* ---- PRIVATE FUNCTIONS ---- */ + + /** + * Calculates the absolute column width depending on the previously set + * "totalWidth" value. The calculated values are stored in the columnWidths + * array. + */ + _calculateWidths: function() + { + // Reset some values which are used during the calculation + for (var i = 0; i < this.columns.length; i++) + { + this.columns[i]._larger = false; + this.columns[i]._newWidth = false; + } + + // Remove the spacing between the columns from the total width + var tw = this.totalWidth; + + // Calculate how many space is - relatively - not occupied with columns with + // relative or fixed width + var remRelWidth = 1; + var noWidthCount = 0 + + for (var i = 0; i < this.columns.length; i++) + { + var col = this.columns[i]; + if (col.visibility != ET2_COL_VISIBILITY_INVISIBLE) + { + if (col.relativeWidth) + { + remRelWidth -= col.relativeWidth; + } + else if (col.fixedWidth) + { + remRelWidth -= col.fixedWidth / tw; + } + else + { + noWidthCount++; + } + } + } + + // Check whether the width of columns with relative width is larger than their + // maxWidth + var done; + do + { + done = true; + + var noWidth = remRelWidth / noWidthCount; + + for (var i = 0; i < this.columns.length; i++) + { + var col = this.columns[i]; + + if (col.visibility != ET2_COL_VISIBILITY_INVISIBLE) + { + if (col.maxWidth && !col._larger) + { + if (col.relativeWidth) + { + var w = col.relativeWidth * tw; + col._larger = w > col.maxWidth; + if (col._larger) + { + // Recalculate the remaining relative width: + // col.maxWidth / w is the relative amount of space p which + // is remaining for the element. E.g. an element with + // w = 150px and maxWidth = 100px => p = 2/3 + // The space which got removed is 1 - p => 1/3 + // ==> we have to add 1/3 * oldRelWidth to the remRelWidth + // variable. + remRelWidth += col.relativeWidth * (1 - col.maxWidth / w); + done = false; + break; + } + } + else + { + col._larger = noWidth * tw > col.maxWidth; + if (col._larger) + { + remRelWidth -= col.maxWidth / tw; + noWidthCount--; + done = false; + break; + } + } + } + } + } + // As some columns take their max width, new space might come available, which + // requires other columns to take their maximum width. + } while (!done); + + + // Check whether the columns where a relative width is specified have more + // space than the remaining columns - if yes, make the relative ones larger + for (var i = 0; i < this.columns.length; i++) + { + var col = this.columns[i]; + + if (col.visibility != ET2_COL_VISIBILITY_INVISIBLE) + { + if (col.relativeWidth && !col._larger) + { + if (col.relativeWidth < noWidth) + { + noWidthCount++; + remRelWidth += col.relativeWidth; + col._newWidth = true; + } + else + { + col._newWidth = false; + } + } + } + } + + // Now calculate the absolute width of the columns in pixels + this.columnWidths = []; + for (var i = 0; i < this.columns.length; i++) + { + var w = 0; + var col = this.columns[i]; + if (col.visibility != ET2_COL_VISIBILITY_INVISIBLE) + { + if (col._larger) + { + w = col.maxWidth; + } + else if (col.fixedWidth) + { + w = col.fixedWidth; + } + else if (col.relativeWidth && !col._newWidth) + { + w = Math.round(tw * col.relativeWidth); + } + else + { + w = Math.round(tw * (remRelWidth / noWidthCount)); + } + + if (w < 0) + { + w = 0; + } + } + this.columnWidths.push(w); + } + } + +}); + diff --git a/etemplate/js/et2_dataview_view_gridcontainer.js b/etemplate/js/et2_dataview_view_gridcontainer.js index 3e4b7da65e..3e55f77f51 100644 --- a/etemplate/js/et2_dataview_view_gridcontainer.js +++ b/etemplate/js/et2_dataview_view_gridcontainer.js @@ -53,6 +53,8 @@ var et2_dataview_gridContainer = Class.extend({ this.width = 0; this.height = 0; + this.uniqueId = "gridCont_" + et2_uniqueId(); + // Build the base nodes this._createElements(); @@ -91,11 +93,13 @@ var et2_dataview_gridContainer = Class.extend({ */ setColumns: function(_columnData) { // Free all column objects which have been created till this moment - this.headTr.empty(); + this._clearHeader(); - // Create the column manager and pass the _columnData to it - this.columns = _columnData; //XXX - //this.columnMgr = new et2_dataview_columnsMgr(_columnData); + // Copy the given column data + this.columnMgr = new et2_dataview_columns(_columnData); + + // Create the stylesheets + this._updateColumns(); // Build the header row this._buildHeader(); @@ -110,16 +114,37 @@ var et2_dataview_gridContainer = Class.extend({ this.width = _w; // Rebuild the column stylesheets + this.columnMgr.setTotalWidth(_w - this.scrollbarWidth); this._updateColumns(); } if (this.height != _h) { + this.height = _h; // Set the height of the grid. // TODO } }, + /** + * Returns the column manager object. You can use it to set the visibility + * of columns etc. Call "updateHeader" if you did any changes. + */ + getColumnMgr: function() { + return this.columnMgr; + }, + + /** + * Recalculates the stylesheets which determine the column visibility and + * width. + */ + updateColumns: function() { + if (this.columnMgr) + { + this._updateColumns(); + } + }, + /* --- PRIVATE FUNCTIONS --- */ @@ -162,7 +187,6 @@ var et2_dataview_gridContainer = Class.extend({ * Clears the header row */ _clearHeader: function() { - // Destroy the column manager if it had been created if (this.columnMgr) { this.columnMgr.free(); @@ -171,9 +195,104 @@ var et2_dataview_gridContainer = Class.extend({ // Reset the headerColumns array and empty the table row this.columnNodes = []; + this.columns = []; this.headTr.empty(); }, + /** + * Sets the column data which is retrieved by calling egwGridColumns.getColumnData. + * The columns will be updated. + */ + _updateColumns: function() { + // Get the stylesheet singleton + var styleSheet = new et2_dynStyleSheet(); + + // Copy the columns data + this.columns = this.columnMgr.getColumnData(); + + // Count the visible rows + var total_cnt = 0; + for (var i = 0; i < this.columns.length; i++) + { + if (this.columns[i].visible) + { + total_cnt++; + } + } + + // Set the grid column styles + var first = true; + var vis_col = this.visibleColumnCount = 0; + var totalWidth = 0; + for (var i = 0; i < this.columns.length; i++) + { + var col = this.columns[i]; + + col.tdClass = this.uniqueId + "_td_" + col.id; + col.divClass = this.uniqueId + "_div_" + col.id; + + if (col.visible) + { + vis_col++; + this.visibleColumnCount++; + + styleSheet.updateRule("." + col.tdClass, + "display: " + (col.visible ? "table-cell" : "none") + "; " + + ((vis_col == total_cnt) ? "border-right-width: 0 " : "border-right-width: 1px ") + + "!important;"); + + styleSheet.updateRule(".egwGridView_outer ." + col.divClass, + "width: " + (col.width - this.headerBorderWidth) + "px;"); + + // Ugly browser dependant code - each browser seems to treat the + // right (collapsed) border of the row differently + var addBorder = 0; + if ($j.browser.mozilla) + { + var maj = $j.browser.version.split(".")[0]; + if (maj < 2) { + addBorder = 1; // Versions <= FF 3.6 + } + } + if ($j.browser.webkit && !first) + { + addBorder = 1; + } + if (($j.browser.msie || $j.browser.opera) && first) + { + addBorder = -1; + } + + // Make the last columns one pixel smaller, to prevent a horizontal + // scrollbar from showing up + if (vis_col == total_cnt) + { + addBorder += 1; + } + + var width = Math.max(0, (col.width - this.columnBorderWidth - addBorder)); + + styleSheet.updateRule(".egwGridView_grid ." + col.divClass, + "width: " + width + "px;"); + + totalWidth += col.width; + + first = false; + } + else + { + styleSheet.updateRule("." + col.tdClass, + "display: " + (col.visible ? "table-cell" : "none") + ";"); + } + } + + // Add the full row and spacer class + styleSheet.updateRule(".egwGridView_grid ." + this.uniqueId + "_div_fullRow", + "width: " + (totalWidth - this.columnBorderWidth - 1) + "px; border-right-width: 0 !important;"); + styleSheet.updateRule(".egwGridView_outer ." + this.uniqueId + "_spacer_fullRow", + "width: " + (totalWidth - 1) + "px; border-right-width: 0 !important;"); + }, + /** * Builds the containers for the header row */ @@ -327,113 +446,3 @@ var et2_dataview_gridContainer = Class.extend({ }); - - -/* - * Sets the column data which is retrieved by calling egwGridColumns.getColumnData. - * The columns will be updated. - */ -/*egwGridViewOuter.prototype.updateColumns = function(_columns) -{ - // Copy the columns data - this.columns = _columns; - - var first = true; - - // Count the visible rows - var total_cnt = 0; - for (var i = 0; i < this.columns.length; i++) - { - if (this.columns[i].visible) - { - total_cnt++; - } - } - - var vis_col = this.visibleColumnCount = 0; - var totalWidth = 0; - - // Set the grid column styles - for (var i = 0; i < this.columns.length; i++) - { - var col = this.columns[i]; - - col.tdClass = this.uniqueId + "_td_" + col.id; - col.divClass = this.uniqueId + "_div_" + col.id; - - if (col.visible) - { - vis_col++; - this.visibleColumnCount++; - - this.styleSheet.updateRule("." + col.tdClass, - "display: " + (col.visible ? "table-cell" : "none") + "; " + - ((vis_col == total_cnt) ? "border-right-width: 0 " : "border-right-width: 1px ") + - "!important;"); - - this.styleSheet.updateRule(".egwGridView_outer ." + col.divClass, - "width: " + (col.width - this.headerBorderWidth) + "px;"); - - // Ugly browser dependant code - each browser seems to treat the - // right (collapsed) border of the row differently - addBorder = 0; - if ($j.browser.mozilla) - { - var maj = $j.browser.version.split(".")[0]; - if (maj < 2) { - addBorder = 1; // Versions <= FF 3.6 - } - } - if ($j.browser.webkit && !first) - { - addBorder = 1; - } - if (($j.browser.msie || $j.browser.opera) && first) - { - addBorder = -1; - } - - // Make the last columns one pixel smaller, to prevent a horizontal - // scrollbar from showing up - if (vis_col == total_cnt) - { - addBorder += 1; - } - - var width = (col.width - this.columnBorderWidth - addBorder); - - this.styleSheet.updateRule(".egwGridView_grid ." + col.divClass, - "width: " + width + "px;"); - - totalWidth += col.width; - - first = false; - } - else - { - this.styleSheet.updateRule("." + col.tdClass, - "display: " + (col.visible ? "table-cell" : "none") + ";"); - } - } - - // Add the full row and spacer class - this.styleSheet.updateRule(".egwGridView_grid ." + this.uniqueId + "_div_fullRow", - "width: " + (totalWidth - this.columnBorderWidth - 1) + "px; border-right-width: 0 !important;"); - this.styleSheet.updateRule(".egwGridView_outer ." + this.uniqueId + "_spacer_fullRow", - "width: " + (totalWidth - 1) + "px; border-right-width: 0 !important;"); - - // Build the header if this hasn't been done yet - this.buildBaseHeader(); - - // Update the grid - this.grid.updateColumns(this.columns); -} - - - -egwGridViewOuter.prototype.setHeight = function(_h) -{ - this.grid.setScrollHeight(_h - this.outer_thead.outerHeight()); -} - -});*/ diff --git a/etemplate/js/et2_extension_nextmatch.js b/etemplate/js/et2_extension_nextmatch.js index 63a989ca39..e20d77d39a 100644 --- a/etemplate/js/et2_extension_nextmatch.js +++ b/etemplate/js/et2_extension_nextmatch.js @@ -70,10 +70,12 @@ var et2_nextmatch = et2_DOMWidget.extend(et2_IResizeable, { // Create the outer grid container this.dataviewContainer = new et2_dataview_gridContainer(this.div); - this.columns = []; this.activeFilters = {}; }, + /** + * Destroys all + */ destroy: function() { this.dataviewContainer.free(); this.dynheight.free(); @@ -81,8 +83,14 @@ var et2_nextmatch = et2_DOMWidget.extend(et2_IResizeable, { this._super.apply(this, arguments); }, + /** + * Implements the et2_IResizeable interface - lets the dynheight manager + * update the width and height and then update the dataview container. + */ resize: function() { - this.dynheight.update(); + this.dynheight.update(function(_w, _h) { + this.dataviewContainer.resize(_w, _h); + }, this); }, /** @@ -128,6 +136,10 @@ var et2_nextmatch = et2_DOMWidget.extend(et2_IResizeable, { (_asc ? "asc" : "desc") + "'"); }, + /** + * Removes the sort entry from the active filters object and thus returns to + * the natural sort order. + */ resetSort: function() { // Check whether the nextmatch widget is currently sorted if (typeof this.activeFilters["sort"] != "undefined") @@ -137,7 +149,7 @@ var et2_nextmatch = et2_DOMWidget.extend(et2_IResizeable, { _widget.setSortmode("none"); }, this, et2_INextmatchSortable); - // If yes, delete the "sort" filter + // Delete the "sort" filter entry delete(this.activeFilters["sort"]); this.applyFilters(); } @@ -150,7 +162,7 @@ var et2_nextmatch = et2_DOMWidget.extend(et2_IResizeable, { /** * Generates the column name for the given column widget */ - _genColumnName: function(_widget) { + _genColumnCaption: function(_widget) { var result = null; _widget.iterateOver(function(_widget) { @@ -167,24 +179,31 @@ var et2_nextmatch = et2_DOMWidget.extend(et2_IResizeable, { return result; }, - _parseHeaderRow: function(_row) { + _parseHeaderRow: function(_row, _colData) { // Go over the header row and create the column entries this.columns = new Array(_row.length); + var columnData = new Array(_row.length); for (var x = 0; x < _row.length; x++) { this.columns[x] = { - "widget": _row[x].widget, - "name": this._genColumnName(_row[x].widget), - "disabled": false, - "canDisable": true, - "width": "auto" - } + "widget": _row[x].widget + }; + + columnData[x] = { + "id": "col_" + x, + "caption": this._genColumnCaption(_row[x].widget), + "visibility": _colData[x].disabled ? + ET2_COL_VISIBILITY_INVISIBLE : ET2_COL_VISIBILITY_VISIBLE, + "width": _colData[x].width + }; // Append the widget to this container this.addChild(_row[x].widget); } - this.dataviewContainer.setColumns(this.columns); + // Create the column manager and update the grid container + this.dataviewContainer.setColumns(columnData); + }, _parseGrid: function(_grid) { @@ -193,7 +212,7 @@ var et2_nextmatch = et2_DOMWidget.extend(et2_IResizeable, { { if (_grid.rowData[y]["class"] == "th") { - this._parseHeaderRow(_grid.cells[y]); + this._parseHeaderRow(_grid.cells[y], _grid.colData); } } }, diff --git a/etemplate/js/et2_extension_nextmatch_dynheight.js b/etemplate/js/et2_extension_nextmatch_dynheight.js index a0a3e4b606..8f4db66c4c 100644 --- a/etemplate/js/et2_extension_nextmatch_dynheight.js +++ b/etemplate/js/et2_extension_nextmatch_dynheight.js @@ -97,7 +97,7 @@ var et2_dynheight = Class.extend({ // Call the callback function if (typeof _callback != "undefined") { - _callback.call(_context, _w, _h); + _callback.call(_context, w, h); } } }, diff --git a/etemplate/js/et2_widget_grid.js b/etemplate/js/et2_widget_grid.js index a51c88f69f..710da15210 100644 --- a/etemplate/js/et2_widget_grid.js +++ b/etemplate/js/et2_widget_grid.js @@ -40,6 +40,7 @@ var et2_grid = et2_DOMWidget.extend({ // 2D-Array which holds references to the DOM td tags this.cells = []; this.rowData = []; + this.colData = []; this.managementArray = []; }, @@ -72,6 +73,7 @@ var et2_grid = et2_DOMWidget.extend({ "autoColSpan": false, "rowSpan": 1, "autoRowSpan": false, + "width": _colData[x].width, "x": x, "y": y }; @@ -365,7 +367,7 @@ var et2_grid = et2_DOMWidget.extend({ this._expandLastCells(cells); // Create the table rows - this.createTableFromCells(cells, rowData); + this.createTableFromCells(cells, colData, rowData); } else { @@ -373,13 +375,14 @@ var et2_grid = et2_DOMWidget.extend({ } }, - createTableFromCells: function(_cells, _rowData) { + createTableFromCells: function(_cells, _colData, _rowData) { // Set the rowCount and columnCount variables var h = this.rowCount = _cells.length; var w = this.columnCount = (h > 0) ? _cells[0].length : 0; this.managementArray = []; this.cells = _cells; + this.colData = _colData; this.rowData = _rowData; // Create the table rows. @@ -394,6 +397,11 @@ var et2_grid = et2_DOMWidget.extend({ tr.hide(); } + if (this.rowData[y].height != "auto") + { + tr.height(this.rowData[y].height); + } + // Create the cells. x is incremented by the colSpan value of the // cell. for (var x = 0; x < w;) @@ -412,6 +420,11 @@ var et2_grid = et2_DOMWidget.extend({ td.hide(); } + if (cell.width != "auto") + { + td.width(cell.width); + } + // Add the entry for the widget to the management array this.managementArray.push({ "cell": td[0], @@ -461,13 +474,25 @@ var et2_grid = et2_DOMWidget.extend({ // Remember all widgets which have already been instanciated var instances = []; + // Copy some data from the colData array + var colData = new Array(_obj.colData.length); + for (var x = 0; x < _obj.colData.length; x++) + { + colData[x] = { + "disabled": _obj.colData[x].disabled, + "class": _obj.colData[x]["class"], + "width": _obj.colData[x].width + } + } + // Copy the some data from the rowData array var rowData = new Array(_obj.rowData.length); for (var y = 0; y < _obj.rowData.length; y++) { rowData[y] = { "disabled": _obj.rowData[y].disabled, - "class": _obj.rowData[y]["class"] + "class": _obj.rowData[y]["class"], + "height": _obj.rowData[y].height } } @@ -512,13 +537,14 @@ var et2_grid = et2_DOMWidget.extend({ "colSpan": srcCell.colSpan, "rowSpan": srcCell.rowSpan, "disabled": srcCell.disabled, - "class": srcCell["class"] + "class": srcCell["class"], + "width": srcCell.width } } } // Create the table - this.createTableFromCells(cells, rowData); + this.createTableFromCells(cells, colData, rowData); // Copy a reference to the content array manager if (_obj._mgr) diff --git a/etemplate/js/et2_widget_selectbox.js b/etemplate/js/et2_widget_selectbox.js index af0483959b..d8a27f6520 100644 --- a/etemplate/js/et2_widget_selectbox.js +++ b/etemplate/js/et2_widget_selectbox.js @@ -276,7 +276,7 @@ var et2_option = et2_baseWidget.extend({ loadContent: function(_data) { this.option.text(_data); - }, + } /* Doesn't work either with selectboxes set_statustext: function(_value) { diff --git a/etemplate/js/et2_widget_textbox.js b/etemplate/js/et2_widget_textbox.js index 0586d5daae..d1bf88752c 100644 --- a/etemplate/js/et2_widget_textbox.js +++ b/etemplate/js/et2_widget_textbox.js @@ -54,7 +54,7 @@ var et2_textbox = et2_inputWidget.extend({ "type": "integer", "default": -1, "description": "Multiline field width - better to use CSS" - }, + } }, init: function() { diff --git a/etemplate/js/etemplate2.js b/etemplate/js/etemplate2.js index 4b04ed0c8c..2554530fad 100644 --- a/etemplate/js/etemplate2.js +++ b/etemplate/js/etemplate2.js @@ -61,9 +61,6 @@ function etemplate2(_container, _menuaction) // Connect to the window resize event $j(window).resize(this, function(e) {e.data.resize()}); - - // Associative array with the event listeners - this.listeners = {}; } /** @@ -197,7 +194,15 @@ etemplate2.prototype.submit = function() var values = this.getValues(this.widgetContainer); // Trigger the submit event - if (this.fireEvent("submit", [values])) + var canSubmit = true; + this.widgetContainer.iterateOver(function(_widget) { + if (_widget.submit(values) === false) + { + canSubmit = false; + } + }, this, et2_ISubmitListener); + + if (canSubmit) { // Create the request object if (typeof egw_json_request != "undefined") @@ -284,72 +289,6 @@ etemplate2.prototype.getValues = function(_root) return result; } -/** - * Adds an callback function to the given event slot - * - * @param _event is the name of the event - * @param _callback is the function which should be called once the event gets - * fired. - * @param _context is the context in which the function should be executed. - */ -etemplate2.prototype.addListener = function(_event, _callback, _context) -{ - // Add the event slot if it does not exist yet - if (typeof this.listeners[_event] == "undefined") - { - this.listeners[_event] = []; - } - - this.listeners[_event].push({ - "callback": _callback, - "context": _context - }); -} - -/** - * Removes the given callback function from the given event slot. - */ -etemplate2.prototype.removeListener = function(_event, _callback) -{ - if (typeof this.listeners[_event] != "undefined") - { - var events = this.listeners[_event]; - - for (var i = events.length - 1; i >= 0; i--) - { - if (events[i].callback == _callback) - { - events.splice(i, 1); - } - } - } -} - -/** - * Fires the given event. The return values are conected via AND - */ -etemplate2.prototype.fireEvent = function(_event, _args) -{ - if (typeof _args == "undefined") - { - _args = []; - } - - var result = true; - - if (typeof this.listeners[_event] != "undefined") - { - var events = this.listeners[_event]; - - for (var i = 0; i < events.length; i++) - { - result = result && events[i].callback.apply(events[i].context, _args); - } - } - - return result; -} - /** * Function which handles the EGW JSON et2_load response */ diff --git a/etemplate/js/test/et2_test_nextmatch.xet b/etemplate/js/test/et2_test_nextmatch.xet index 26dd087b91..62fd8c63a9 100644 --- a/etemplate/js/test/et2_test_nextmatch.xet +++ b/etemplate/js/test/et2_test_nextmatch.xet @@ -12,8 +12,6 @@ - - @@ -63,8 +61,6 @@ - - diff --git a/etemplate/js/test/et2_test_text.json b/etemplate/js/test/et2_test_text.json index 7b5f394966..b94d5622e2 100644 --- a/etemplate/js/test/et2_test_text.json +++ b/etemplate/js/test/et2_test_text.json @@ -3,5 +3,5 @@ var text_data = { "url": "www.egroupware.org", "email": "", "phone": "(866) 789-RACE" - }, + } } diff --git a/etemplate/js/test/grid.css b/etemplate/js/test/grid.css index 829f59ad72..cf029db2f4 100644 --- a/etemplate/js/test/grid.css +++ b/etemplate/js/test/grid.css @@ -200,21 +200,3 @@ border-bottom: 0 none silver !important; } -.egwGridView_outer span.sort { - display: inline-block; - width: 7px; - height: 7px; - background-repeat: no-repeat; - background-position: center; - margin: 2px; - vertical-align: middle; -} - -.egwGridView_outer span.sort.asc { - background-image: url(gfx/up.png); -} - -.egwGridView_outer span.sort.desc { - background-image: url(gfx/down.png); -} - diff --git a/etemplate/js/test/test.css b/etemplate/js/test/test.css index 7148a39d22..79cdd693cf 100644 --- a/etemplate/js/test/test.css +++ b/etemplate/js/test/test.css @@ -9,7 +9,7 @@ body, table, td { font-family: Lucida Grande, sans-serif; font-size: 10pt; -/* overflow: hidden;*/ + overflow: hidden; } #linklist a { @@ -348,7 +348,7 @@ label input, label span, label div, label select, label textarea { .nextmatch_sortheader { color: #003075; cursor: pointer; - padding-right: 18px; + padding-right: 10px; margin-right: 10px; background-repeat: no-repeat; background-position: right center; diff --git a/etemplate/js/test/test_xml.html b/etemplate/js/test/test_xml.html index 6430291914..c003112f3b 100644 --- a/etemplate/js/test/test_xml.html +++ b/etemplate/js/test/test_xml.html @@ -34,6 +34,7 @@ +