From c5523c649cfc4b32db83527c312729acdb9c5ad5 Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Sun, 13 Mar 2016 14:18:22 +0000 Subject: [PATCH] remove 11.1 felamimail grid, unused since 14.1 --- phpgwapi/inc/class.egw_grid_columns.inc.php | 335 --- phpgwapi/js/egw_action/egw_grid.js | 293 --- phpgwapi/js/egw_action/egw_grid_columns.js | 589 ----- phpgwapi/js/egw_action/egw_grid_data.js | 1471 ----------- phpgwapi/js/egw_action/egw_grid_view.js | 2170 ----------------- phpgwapi/js/egw_action/test/grid.css | 229 -- phpgwapi/js/egw_action/test/test_grid.html | 199 -- .../js/egw_action/test/test_grid_view.html | 322 --- 8 files changed, 5608 deletions(-) delete mode 100644 phpgwapi/inc/class.egw_grid_columns.inc.php delete mode 100644 phpgwapi/js/egw_action/egw_grid.js delete mode 100644 phpgwapi/js/egw_action/egw_grid_columns.js delete mode 100644 phpgwapi/js/egw_action/egw_grid_data.js delete mode 100644 phpgwapi/js/egw_action/egw_grid_view.js delete mode 100644 phpgwapi/js/egw_action/test/grid.css delete mode 100644 phpgwapi/js/egw_action/test/test_grid.html delete mode 100644 phpgwapi/js/egw_action/test/test_grid_view.html diff --git a/phpgwapi/inc/class.egw_grid_columns.inc.php b/phpgwapi/inc/class.egw_grid_columns.inc.php deleted file mode 100644 index 9a1f0345db..0000000000 --- a/phpgwapi/inc/class.egw_grid_columns.inc.php +++ /dev/null @@ -1,335 +0,0 @@ - array( - "types" => "string", - "default" => "" - ) - ); - - protected $data = array(); - - /** - * Merges the given properties into the supported properties array. - * - * @param array $props are the supported properties which will be added to the - * object. - */ - protected function add_supported_properties($props) - { - $this->supported_properties = array_merge($this->supported_properties, $props); - } - - /** - * Reads the object data from the - */ - public function load_assoc(array $assoc) - { - /** - * Calls the magic setter for each data element - */ - foreach ($assoc as $key => $data) - { - $this->$key = $data; - } - } - - /** - * Returns an associative array with the object data - */ - public function store_assoc($include_defaults = false) - { - $result = array(); - - foreach ($this->supported_properties as $key => $opt) - { - if (!array_key_exists("store", $opt) || $opt[$store]) - { - $val = $this->$key; - - if ($val != $opt["default"] || $include_defaults ) - { - $result[$key] = $val; - } - } - } - - return $result; - } - - /** - * Magic setter function - checks whether the specified key is supported by the - * the object and the given value is of the supported type. - */ - public function __set($key,$val) - { - if (array_key_exists($key, $this->supported_properties)) - { - $sup_entry = $this->supported_properties[$key]; - - // Test for the type (PHP-Docu says not to use gettype here) - $correct_type = true; - - if (array_key_exists("types", $sup_entry)) - { - $types = explode(",", $sup_entry["types"]); - - foreach ($types as $type) - { - switch ($type) - { - case "bool": - $correct_type = $correct_type || is_bool($val); - break; - case "string": - $correct_type = $correct_type || is_string($val); - break; - case "int": - $correct_type = $correct_type || is_int($val); - break; - case "float": - $correct_type = $correct_type || is_float($val); - break; - } - } - } - - // Set the value in the data array or call a setter function an inherited - // class might have specified - if ($correct_type) - { - if (method_exists($this, "set_".$key)) - { - call_user_func(array($this, "set_".$key), $val); - } - else - { - $this->data[$key] = $val; - } - } - } - } - - /** - * Magic getter function - returns the default value if the data key has not - * been set yet, returns null if the property does not exists. - */ - public function __get($key) { - if (array_key_exists($key, $this->supported_properties)) - { - // Check whether the inherited class has a special getter implemented - if (method_exists($this, "get_".$key)) - { - return call_user_func(array($this, "get_".$key), $val); - } - else - { - if (array_key_exists($key, $this->data)) - { - return $this->data[$key]; - } - else - { - return $this->supported_properties[$key]["default"]; - } - } - } - return null; - } -} - - -/** - * Define some constants as they occur in egw_grid_columns.js - */ -define("EGW_COL_TYPE_DEFAULT", 0); -define("EGW_COL_TYPE_NAME_ICON_FIXED", 1); -define("EGW_COL_TYPE_CHECKBOX", 2); - -define("EGW_COL_VISIBILITY_ALWAYS", 0); -define("EGW_COL_VISIBILITY_VISIBLE", 1); -define("EGW_COL_VISIBILITY_INVISIBLE", 2); -define("EGW_COL_VISIBILITY_ALWAYS_NOSELECT", 3); - -define("EGW_COL_SORTABLE_NONE", 0); -define("EGW_COL_SORTABLE_ALPHABETIC", 1); -define("EGW_COL_SORTABLE_NUMERICAL", 2); -define("EGW_COL_SORTABLE_NATURAL", 3); -define("EGW_COL_SORTABLE_EXTERNAL", 4); - -define("EGW_COL_SORTMODE_NONE", 0); -define("EGW_COL_SORTMODE_ASC", 1); -define("EGW_COL_SORTMODE_DESC", 2); - -define("EGW_COL_DEFAULT_FETCH", -10000); - -/** - * Object which represents a single column - */ -class egw_grid_column extends egw_json_object -{ - public function __construct($id = "") - { - // Add the supported properties - $this->add_supported_properties(array( - "width" => array("types" => "bool,int,string", "default" => false), - "maxWidth" => array("types" => "int,bool", "default" => false), - "caption" => array("types" => "string", "default" => ""), - "visibility" => array("types" => "int", "default" => EGW_COL_VISIBILITY_VISIBLE), - "visible" => array("types" => "bool", "default" => true, "store" => false), - "sortable" => array("types" => "int", "default" => EGW_COL_SORTABLE_NONE), - "sortmode" => array("types" => "int", "default" => EGW_COL_SORTMODE_NONE), - "default" => array("types" => "string,int", "default" => EGW_COL_DEFAULT_FETCH), - "type" => array("types" => "int", "default" => EGW_COL_TYPE_DEFAULT) - )); - - // Set the column id - $this->id = $id; - } - - public function get_visible() - { - return $this->visibility != EGW_COL_VISIBILITY_INVISIBLE; - } - - public function set_visible($val) - { - if ($this->visibility != EGW_COL_VISIBILITY_ALWAYS && - $this->visibility != EGW_COL_VISIBILITY_ALWAYS_NOSELECT) - { - $this->visibility = $val ? EGW_COL_VISIBILITY_VISIBLE : EGW_COL_VISIBILITY_INVISIBLE; - } - } -} - -class egw_grid_columns -{ - private $app_name; - private $grid_name; - - private $grid_data = array(); - - public function __construct($app_name, $grid_name = "main") - { - $this->app_name = $app_name; - $this->grid_name = $grid_name; - } - - public function load_grid_data($data) - { - foreach ($data as $col) - { - $colobj = new egw_grid_column(); - $colobj->load_assoc($col); - - $this->grid_data[] = $colobj; - } - } - - private function get_col($id) - { - foreach ($this->grid_data as $col) - { - if ($col->id == $id) - { - return $col; - } - } - - return null; - } - - /** - * Loads the given column data in the user preferences for this grid - */ - private function get_userdata() - { - if ($GLOBALS['egw_info']['user']['preferences'][$this->app_name][$this->grid_name.'_column_data']) - { - return unserialize($GLOBALS['egw_info']['user']['preferences'][$this->app_name][$this->grid_name.'_column_data']); - } - return array(); - } - - /** - * Stores the given column data in the user preferences for this grid - */ - private function set_userdata($data) - { - $GLOBALS['egw']->preferences->read_repository(); - - $GLOBALS['egw']->preferences->change($this->app_name, $this->grid_name.'_column_data', - serialize($data)); - - $GLOBALS['egw']->preferences->save_repository(true); - } - - public function load_userdata() - { - // Read the userdata from the user preferences - $data = $this->get_userdata(); - - // Merge the userdata into the column data - foreach ($data as $col_id => $col_data) - { - $col = $this->get_col($col_id); - if ($col && is_array($col_data)) - { - $col->load_assoc($col_data); - } - } - } - - public function store_userdata($data) - { - $store_data = array(); - - // Check whether the specified columns exists - foreach ($data as $col_id => $col_data) - { - $col = $this->get_col($col_id); - if ($col) - { - $store_data[$col_id] = $col_data; - } - } - - // Store the verified data columns - $this->set_userdata($store_data); - } - - /** - * Returns the associative array containing the column data which can be - * JSON-encoded and sent to the client - */ - public function get_assoc() - { - $result = array(); - foreach ($this->grid_data as $col) - { - $result[] = $col->store_assoc(); - } - - return $result; - } -} - diff --git a/phpgwapi/js/egw_action/egw_grid.js b/phpgwapi/js/egw_action/egw_grid.js deleted file mode 100644 index 72bf1c4c25..0000000000 --- a/phpgwapi/js/egw_action/egw_grid.js +++ /dev/null @@ -1,293 +0,0 @@ -/** - * 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 - jquery.jquery; - egw_action; - egw_grid_columns; - egw_grid_data; - egw_grid_view; -*/ - -function egwGrid(_parentNode, _columns, _objectManager, _fetchCallback, - _columnChangeCallback, _context) -{ - this.parentNode = _parentNode; - this.objectManager = _objectManager; - - this.columnChangeCallback = _columnChangeCallback; - this.context = _context; - - this.width = 0; - this.height = 0; - - // Create the column handler and connect its update event to this object - this.columns = new egwGridColumns(_columns, this.columnsUpdate, this); - - // Create the read queue - this.readQueue = new egwGridDataQueue(_fetchCallback, _context); - - this.selectedChangeCallback = null; - this.sortColsCallback = null; - - // Create the root data element - this.dataRoot = new egwGridDataElement("", null, this.columns, this.readQueue, - _objectManager); - var self = this; - this.dataRoot.actionObject.setSelectedCallback = function() { - if (self.gridOuter.checkbox || self.selectedChangeCallback) - { - var allSelected = this.getAllSelected(); - if (self.gridOuter.checkbox) - { - self.gridOuter.checkbox.attr("checked", allSelected) - } - - if (self.selectedChangeCallback) - { - self.selectedChangeCallback.call(self.context, allSelected); - } - } - }; - - // Create the outer view component and pass the dataRoot element so that - // the grid outer element will be capable of fetching the root data and - // can create a spacer for that. - this.gridOuter = new egwGridViewOuter(_parentNode, this.dataRoot, - this.selectcolsClick, this.toggleAllClick, this.sortColsClick, this); - this.gridOuter.updateColumns(this.columns.getColumnData()); -} - -var EGW_SELECTMODE_DEFAULT = 0; -var EGW_SELECTMODE_TOGGLE = 1; - -egwGrid.prototype.setSelectmode = function(_mode) -{ - this.gridOuter.grid.selectmode = _mode; -} - -egwGrid.prototype.setActionLinkGroup = function(_group, _links) -{ - this.dataRoot.actionLinkGroups[_group] = _links; -} - -/** - * Updates the action link groups. - * - * @param object _groups is an object used as associative array, which will be - * merged into the existing actionLinkGroups - * @param boolean _replace specifies whether existing action link groups will - * be deleted. Defaults to false. - */ -egwGrid.prototype.setActionLinkGroups = function(_groups, _replace) -{ - if (typeof _replace == "undefined") - { - _replace = false; - } - - if (_replace) - { - this.dataRoot.actionLinkGroups = {}; - } - - for (var k in _groups) - { - this.dataRoot.actionLinkGroups[k] = _groups[k]; - } -} - -egwGrid.prototype.resize = function(_w, _h) -{ -// if (_w != this.width) - { - this.columns.setTotalWidth(_w - this.gridOuter.scrollbarWidth - 2); - this.gridOuter.updateColumns(this.columns.getColumnData()); - this.height = -1; - } - -// if (_h != this.height) - { - this.gridOuter.setHeight(_h); - } - - this.height = _h; - this.width = _w; -} - -/** - * If the columns have changed, call the gridOuter "updateColumns" function, - * which will rebuild the view. - */ -egwGrid.prototype.columnsUpdate = function(_column) -{ - if (this.gridOuter) - { - this.gridOuter.updateColumns(this.columns.getColumnData()); - } -} - -/** - * Handle the selectcols callback - */ -egwGrid.prototype.selectcolsClick = function(_at) -{ - var column_data = this.columns.getColumnVisibilitySet(); - - // Create a menu which contains these elements and show it - var menu_data = []; - for (var k in column_data) - { - var col = column_data[k]; - // strip html from caption - var strippedCaption = col.caption.replace(/&(lt|gt);/g, function (strMatch, p1) { - return (p1 == "lt")? "<" : ">";}); - strippedCaption = strippedCaption.replace(/<\/?[^>]+(>|$)/g,""); - menu_data.push( - { - "id": k, - "caption": strippedCaption, - "enabled": col.enabled, - "checkbox": true, - "checked": col.visible - } - ); - } - - var menu = new egwMenu(); - menu.loadStructure(menu_data); - - var self = this; - menu.setGlobalOnClick(function(_elem) { - column_data[_elem.id].visible = _elem.checked; - - if (self.columnChangeCallback) - { - // Create the user data column visibility set - var set = {}; - for (var k in column_data) - { - set[k] = { - "visible": column_data[k].visible - }; - } - - // Call the column change callback with the user data - if (self.columnChangeCallback) - { - self.columnChangeCallback.call(self.context, set); - } - } - - self.columns.setColumnVisibilitySet(column_data); - }); - - menu.showAt(_at.offset().left, _at.offset().top); -} - -/** - * Handles the toggle all click - */ -egwGrid.prototype.toggleAllClick = function(_checked) -{ - this.dataRoot.actionObject.toggleAllSelected(_checked); -} - -/** - * Handles clicking on a sortable column header - */ -egwGrid.prototype.sortColsClick = function(_columnIdx) -{ - var col = this.columns.columns[_columnIdx]; - if (col.sortable == EGW_COL_SORTABLE_EXTERNAL) - { - if (this.sortColsCallback) - { - this.sortColsCallback.call(this.context, col.id); - } - } - else - { - var dir = EGW_COL_SORTMODE_ASC; - - if (col.sortmode == EGW_COL_SORTMODE_ASC) - { - dir = EGW_COL_SORTMODE_DESC - } - - this.sortData(col.id, dir); - } -} - -egwGrid.prototype.sortData = function(_columnId, _dir) -{ - var col = this.columns.getColumnById(_columnId); - - if (col && col.sortable != EGW_COL_SORTABLE_NONE && col.sortable != EGW_COL_SORTABLE_EXTERNAL) - { - this.dataRoot.sortChildren(col.id, _dir, col.sortable, function() { - // Set the new sort direction - col.set_sortmode(_dir); - - this.displaySortMode(); - - // Rebuild the inner grid - this.reload(); - }, this); - } -} - -egwGrid.prototype.displaySortMode = function() -{ - // Update the column data of the grid - this.gridOuter.updateColumns(this.columns.getColumnData()); - - // Update the column header - for (var i = 0; i < this.columns.columns.length; i++) - { - this.gridOuter.updateColSortmode(i); - } -} - -egwGrid.prototype.resetSort = function() -{ - for (var i = 0; i < this.columns.columns.length; i++) - { - fileGrid.columns.columns[i].set_sortmode(EGW_COL_SORTMODE_NONE); - } - - this.displaySortMode(); -} - -/** - * Emptys the grid - */ -egwGrid.prototype.empty = function() -{ - this.dataRoot.empty(); - - this.gridOuter.grid.empty(); -} - -egwGrid.prototype.reload = function() -{ - this.gridOuter.empty(); -} - -/** - * Returns the height of the data inserted into the grid - */ -egwGrid.prototype.getDataHeight = function() -{ - return this.gridOuter.grid.getHeight(); -} - - diff --git a/phpgwapi/js/egw_action/egw_grid_columns.js b/phpgwapi/js/egw_action/egw_grid_columns.js deleted file mode 100644 index 42da49e197..0000000000 --- a/phpgwapi/js/egw_action/egw_grid_columns.js +++ /dev/null @@ -1,589 +0,0 @@ -/** - * 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 - egw_action_common; -*/ - -/** - * Contains logic for the column class. The column class represents the unique set - * of columns a grid view owns. The parameters of the columns (except for visibility) - * di normaly not change. - */ - -var EGW_COL_TYPE_DEFAULT = 0; -var EGW_COL_TYPE_NAME_ICON_FIXED = 1; -var EGW_COL_TYPE_CHECKBOX = 2; - -var EGW_COL_VISIBILITY_ALWAYS = 0; -var EGW_COL_VISIBILITY_VISIBLE = 1; -var EGW_COL_VISIBILITY_INVISIBLE = 2; -var EGW_COL_VISIBILITY_ALWAYS_NOSELECT = 3; - -var EGW_COL_SORTABLE_NONE = 0; -var EGW_COL_SORTABLE_ALPHABETIC = 1; -var EGW_COL_SORTABLE_NUMERICAL = 2; -var EGW_COL_SORTABLE_NATURAL = 3; -var EGW_COL_SORTABLE_EXTERNAL = 4; - - -var EGW_COL_SORTMODE_NONE = 0; -var EGW_COL_SORTMODE_ASC = 1; -var EGW_COL_SORTMODE_DESC = 2; - -var EGW_COL_DEFAULT_FETCH = -10000; - - -/** - * Class representing a single grid column. - */ -function egwGridColumn(_context, _visiblityChangeCallback, _sortmodeChangeCallback) -{ - if (typeof _context == "undefined") - { - _context = null; - } - - if (typeof _visiblityChangeCallback == "undefined") - { - _visiblityChangeCallback == null; - } - - this.id = ""; - this.fixedWidth = false; - this.relativeWidth = false; - this.maxWidth = false; - this.caption = ""; - this.type = EGW_COL_TYPE_DEFAULT; - this.visibility = EGW_COL_VISIBILITY_VISIBLE; - this.sortable = EGW_COL_SORTABLE_NONE; - this.sortmode = EGW_COL_SORTMODE_NONE; - this["default"] = EGW_COL_DEFAULT_FETCH; - - this.context = _context; - this.visibilityChangeCallback = _visiblityChangeCallback; - this.sortmodeChangeCallback = _sortmodeChangeCallback; -} - -egwGridColumn.prototype.loadData = function(_data) -{ - egwActionStoreJSON(_data, this, true); -} - -egwGridColumn.prototype.set_width = function(_value) -{ - // Parse the width parameter. Posible values are: - // 1. "100" => fixedWidth 100px - // 2. "100px" => fixedWidth 100px - // 3. "50%" => relativeWidth 50% - if (_value) - { - if (typeof _value == "string") - { - 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)); - } - else if (!isNaN(w)) - { - this.fixedWidth = parseInt(w); - } - } - } -} - -egwGridColumn.prototype.set_maxWidth = function(_value) -{ - if (!isNaN(_value) && _value > 0) - { - this.maxWidth = _value; - } -} - -egwGridColumn.prototype.set_default = function(_value) -{ - if (typeof _value == "string") - { - this["default"] = _value; - } - else if (typeof _value == "number" && (_value == EGW_COL_DEFAULT_FETCH)) - { - this["default"] = _value; - } -} - -egwGridColumn.prototype.set_id = function(_value) -{ - this.id = _value; -} - -/** - * Setter for the column type. - */ -egwGridColumn.prototype.set_type = function(_value) -{ - if (typeof _value == "number" && (_value == EGW_COL_TYPE_DEFAULT || - _value == EGW_COL_TYPE_NAME_ICON_FIXED || _value == EGW_COL_TYPE_CHECKBOX)) - { - this.type = _value; - - if (this.type == EGW_COL_TYPE_CHECKBOX) - { - this.set_width("23px"); - } - } -} - -/** - * Setter for the visibility of the column. Checks whether the given value is in - * the allowed range and calls the visibilityChangeCallback. - */ -egwGridColumn.prototype.set_visibility = function(_value) -{ - if (typeof _value == "number" && (_value == EGW_COL_VISIBILITY_ALWAYS || - _value == EGW_COL_VISIBILITY_INVISIBLE || _value == EGW_COL_VISIBILITY_VISIBLE || - _value == EGW_COL_VISIBILITY_ALWAYS_NOSELECT)) - { - if (_value != this.visibility) - { - this.visibility = _value; - - if (this.visibilityChangeCallback) - { - this.visibilityChangeCallback.call(this.context, this); - } - } - } -} - -/** - * Sets the sortmode of the column and informs the parent about it. - */ -egwGridColumn.prototype.set_sortmode = function(_value) -{ - if (typeof _value == "number" && (_value == EGW_COL_SORTMODE_NONE || - _value == EGW_COL_SORTMODE_ASC || _value == EGW_COL_SORTMODE_DESC)) - { - if (this.sortable == EGW_COL_SORTABLE_NONE) - { - this.sortmode = EGW_COL_SORTMODE_NONE; - } - else - { - if (_value != this.sortmode) - { - if (this.sortmodeChangeCallback) - { - this.sortmodeChangeCallback.call(this.context, this); - } - this.sortmode = _value; - } - } - } -} - -egwGridColumn.prototype.set_sortable = function(_value) -{ - if (typeof _value == "number" && (_value == EGW_COL_SORTABLE_ALPHABETIC || - _value == EGW_COL_SORTABLE_NONE || _value == EGW_COL_SORTABLE_NATURAL || - _value == EGW_COL_SORTABLE_NUMERICAL || _value == EGW_COL_SORTABLE_EXTERNAL)) - { - if (_value == EGW_COL_SORTABLE_NONE) - { - this.sortmode = EGW_COL_SORTABLE_NONE; - } - - this.sortable = _value; - } -} - - -egwGridColumn.prototype.set_caption = function(_value) -{ - this.caption = _value; -} - - -/** - * Object which is used inside egwGrid to manage the grid columns. - */ -function egwGridColumns(_columns, _updateCallback, _context, _columnSpace) -{ - // Default the coulumn padding value to two - if (typeof _columnSpace == "undefined") - { - this.columnSpace = 2; - } - else - { - this.columnSpace = _columnSpace; - } - - this.totalWidth = false; - this.inUpdate = false; - this.sortChanged = null; - this.visibilityChanged = false; - this.columnWidths = []; - - this.context = _context; - this.updateCallback = _updateCallback; - - this._beginUpdate(); - - this.columns = []; - for (var i = 0; i < _columns.length; i++) - { - var column = new egwGridColumn(this, this._visibilityCallback, this._sortCallback); - column.loadData(_columns[i]); - - this.columns.push(column); - } - - this._endUpdate(); -} - -egwGridColumns.prototype._beginUpdate = function() -{ - this.inUpdate = true; - this.sortChanged = null; - this.visibilityChanged = false; -} - -egwGridColumns.prototype._endUpdate = function() -{ - this.inUpdate = false; - - // Call the sort update again in order to update the other columns - if (this.sortChanged) - { - this._sortCallback(this.sortCallback); - } - - if (this.visibilityChanged || this.sortChanged) - { - this.updateCallback.call(this.context, this); - } - - this.sortChanged = null; - this.visibilityChanged = false; -} - -egwGridColumns.prototype._visibilityCallback = function(_elem) -{ - if (this.inUpdate) - { - this.visibilityChanged = true; - } - else - { - this.updateCallback.call(this.context, this); - } -} - -egwGridColumns.prototype._sortCallback = function(_elem) -{ - if (this.inUpdate) - { - this.sortChanged = _elem; - } - else - { - // Reset the sortmode of all other elements. - for (var i = 0; i < this.columns.length; i++) - { - if (this.columns[i] != _elem) - { - this.columns[i].sortmode = EGW_COL_SORTMODE_NONE; - } - } - } -} - -egwGridColumns.prototype._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;// - (Math.max(this.getVisibleCount() - 1, 0)) * this.columnSpace; - - // 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 != EGW_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 = true; - do - { - done = true; - - var noWidth = remRelWidth / noWidthCount; - - for (var i = 0; i < this.columns.length; i++) - { - var col = this.columns[i]; - - if (col.visibility != EGW_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 != EGW_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 != EGW_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); - } -} - -egwGridColumns.prototype.setTotalWidth = function(_value) -{ - if (_value < 100) - { - _value = 100; - } - - this.totalWidth = _value; - this._calculateWidths(); -} - -egwGridColumns.prototype.getColumnIndexById = function(_id) -{ - for (var i = 0; i < this.columns.length; i++) - { - if (this.columns[i].id == _id) - { - return i; - } - } - return -1; -} - -egwGridColumns.prototype.getColumnById = function(_id) -{ - var idx = this.getColumnIndexById(_id); - return (idx == -1) ? null : this.columns[idx]; -} - -egwGridColumns.prototype.getVisibleCount = function() -{ - var cnt = 0; - for (var i = 0; i < this.columns.length; i++) - { - if (this.columns[i].visibility != EGW_COL_VISIBILITY_INVISIBLE) - { - cnt++; - } - } - return cnt; -} - -egwGridColumns.prototype.getColumnVisibilitySet = function() -{ - var result = {}; - - for (var i = 0; i < this.columns.length; i++) - { - if (this.columns[i].visibility != EGW_COL_VISIBILITY_ALWAYS_NOSELECT) - { - result[this.columns[i].id] = { - "caption": this.columns[i].caption, - "enabled": (this.columns[i].visibility != EGW_COL_VISIBILITY_ALWAYS) && - (this.columns[i].type != EGW_COL_TYPE_NAME_ICON_FIXED), - "visible": this.columns[i].visibility != EGW_COL_VISIBILITY_INVISIBLE - }; - } - } - - return result; -} - -egwGridColumns.prototype.setColumnVisibilitySet = function(_set) -{ - this._beginUpdate(); - - for (var k in _set) - { - var col = this.getColumnById(k); - if (col) - { - col.set_visibility(_set[k].visible ? EGW_COL_VISIBILITY_VISIBLE : - EGW_COL_VISIBILITY_INVISIBLE); - } - } - - if (this.visibilityChanged) - { - this._calculateWidths(); - } - - this._endUpdate(); -} - -egwGridColumns.prototype.getColumnData = function() -{ - var result = []; - - for (var i = 0; i < this.columns.length; i++) - { - result.push( - { - "id": this.columns[i].id, - "caption": this.columns[i].caption, - "sortable": this.columns[i].sortable, - "sortmode": this.columns[i].sortmode, - "default": this.columns[i]["default"], - "width": this.columnWidths[i], - "type": this.columns[i].type, - "visible": this.columns[i].visibility != EGW_COL_VISIBILITY_INVISIBLE, - "element": this.columns[i] - } - ); - } - - return result; -} - -egwGridColumns.prototype.sortBy = function(_id, _mode) -{ - // Fetch the column and set its sortmode. If the column supports sorting, - // it will call the callback function. - var col = this.getColumnById(_id); - if (col) - { - col.set_sortmode(_mode); - } -} - - diff --git a/phpgwapi/js/egw_action/egw_grid_data.js b/phpgwapi/js/egw_action/egw_grid_data.js deleted file mode 100644 index 4ded6facc5..0000000000 --- a/phpgwapi/js/egw_action/egw_grid_data.js +++ /dev/null @@ -1,1471 +0,0 @@ -/** - * 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 - egw_action; - egw_action_common; - egw_grid_columns; -*/ - -/** -- egwGridDataElement Class -- **/ - -var EGW_DATA_TYPE_RANGE = 0; -var EGW_DATA_TYPE_ELEMENT = 1; - -/** - * Contains the data (model) objects which retrieve data from the given source and - * pass it to. - * - * @param object _parent the parent data element in which the new element is contained - * @param object _columns the columns object which contains information about the data columns - * @param object _readQueue is the queue object which queues data-fetching calls and executes these - * asynchronously. - * @param object _objectManager if this element is the root element (_parent is null), - * specify the _objectManager in order to supply a parent object manager for that - * element. - */ -function egwGridDataElement(_id, _parent, _columns, _readQueue, _objectManager) -{ - // Copy the passed arguments - this.id = _id; - this.parent = _parent; - this.columns = _columns; - this.readQueue = _readQueue; - - // Generate the action object associated to this element - this.parentActionObject = _parent ? _parent.actionObject : _objectManager; - this.actionObject = null; - - // If this is the root object, add the an root action object to the objectManager - if (!_parent) - { - this.actionObject = this.parentActionObject.addObject(_id, null, - EGW_AO_FLAG_IS_CONTAINER | EGW_AO_FLAG_DEFAULT_FOCUS); - this.readQueue.setDataRoot(this); - } - - // Preset some parameters - this.children = []; - - this.data = {}; - this.caption = false; - this.iconUrl = false; - this.iconSize = false; - this.iconOverlay = []; - this.opened = _parent == null; - this.index = 0; - this.canHaveChildren = false; - this.type = egwGridViewRow; - this.userData = null; - this.updatedGrid = null; - this.actionLinkGroups = {}; - this.group = false; - this.capColTime = 0; - this.rowClass = ""; - - this.gridViewObj = null; -} - -var EGW_GRID_DATA_UPDATE_TIME = 0; - -egwGridDataElement.prototype.free = function() -{ - //TODO -} - -egwGridDataElement.prototype.set_rowClass = function(_value) -{ - if (_value != this.rowClass) - { - this.rowClass = _value; - } -} - -egwGridDataElement.prototype.set_caption = function(_value) -{ - if (_value != this.caption) - { - this.capColTime = EGW_GRID_DATA_UPDATE_TIME; - this.caption = _value; - } -} - -egwGridDataElement.prototype.set_iconUrl = function(_value) -{ - if (_value != this.iconUrl) - { - this.capColTime = EGW_GRID_DATA_UPDATE_TIME; - this.iconUrl = _value; - } -} - -egwGridDataElement.prototype.set_iconOverlay = function(_value) -{ - if (!egwArraysEqual(_value, this.iconOverlay)) - { - this.capColTime = EGW_GRID_DATA_UPDATE_TIME; - this.iconOverlay = _value; - } -} - -egwGridDataElement.prototype.set_iconSize = function(_value) -{ - if (_value != this.iconSize) - { - this.capColTime = EGW_GRID_DATA_UPDATE_TIME; - this.iconSize = _value; - } -} - -egwGridDataElement.prototype.set_opened = function(_value) -{ - this.opened = _value; -} - -egwGridDataElement.prototype.set_canHaveChildren = function(_value) -{ - // Calculate the canHaveChildren value which would really be set - var rv = _value && (this.children.length == 0); - - if (rv != this.canHaveChildren) - { - this.canHaveChildren = _value; - this.capColTime = EGW_GRID_DATA_UPDATE_TIME; - } -} - -egwGridDataElement.prototype.set_group = function(_value) -{ - this.group = _value; - - var root = this.getRootElement(); - - var groups = _value.split(","); - for (var key in groups) - { - var val = groups[key]; - if (typeof root.actionLinkGroups[val] != "undefined") - { - this.actionObject.updateActionLinks(root.actionLinkGroups[val]); - } - } -} - -/** - * Updates the column data. The column data is an object (used as associative array) - * which may be of the following outline: - * - * { - * "[col1_id]": "[data]", - * "[col2_id]": - * { - * "data": "[data]", - * "sortData": "[sortData]" - * } - * } - * - * "sortData" is data which is used for sorting instead of "data" when set. - */ -egwGridDataElement.prototype.set_data = function(_value) -{ - if (typeof _value == "object" && _value.constructor == Object) - { - // Update the column data specified in the value - for (col_id in _value) - { - var val = _value[col_id]; - - var data = ""; - var sortData = null; - - if (typeof val == "object") - { - data = typeof val.data != "undefined" ? val.data : ""; - sortData = typeof val.sortData != "undefined" ? val.sortData : null; - } - else - { - data = val; - } - - // Set the data column timestamp - this is used inside the grid_view - // row unit in order to only update data which has really changed - var ts = 0; - var newData = true; - - if (typeof this.data[col_id] != "undefined" && this.data[col_id].data == data) - { - ts = this.data[col_id].ts; - newData = false; - } - - if (newData) - { - ts = EGW_GRID_DATA_UPDATE_TIME; - } - - this.data[col_id] = { - "data": data, - "sortData": sortData, - "queued": false, - "time": ts - } - } - } -} - -egwGridDataElement.prototype.addClass = function(_value) { - // Split the string into individual classes - classes = this.rowClass.split(' '); - - // Add the given class if it is not already set - if (classes.indexOf(_value) == -1) - { - classes.push(_value); - - // Write the new value - this.rowClass = classes.join(' '); - - // Update the grid element - this.callGridViewObjectUpdate(); - } -} - -egwGridDataElement.prototype.removeClass = function(_value) { - // Split the string into individual classes - classes = this.rowClass.split(' '); - - // Remove the given value if it exists - var idx = classes.indexOf(_value); - if (idx > -1) - { - classes.splice(idx, 1); - - // Write the new value - this.rowClass = classes.join(' '); - - // Update the grid element - this.callGridViewObjectUpdate(); - } -} - - -/** - * Loads data into the GridData element. This function has two basic operating modes: - * - * 1. If an array of objects is passed, the specified objects are added as children. - * If a child node with the given ID already exists, it is updated. - * The given data array must have the following form: - * [ - * { - * ["entryType": (EGW_DATA_TYPE_ELEMENT | EGW_DATA_TYPE_RANGE)] // Defaults to EGW_DATA_TYPE_ELEMENT - * "type": "[Typeclass]" // Typeclass of the view-container: specifies the chars after the egwGridView-prefix. Defaults to "Row" which becomes "egwGridViewRow", - * IF EGW_DATA_TYPE_ELEMENT: - * "id": [ Name of the element ] - * "children": [ Objects which will be added to the children of the element ] - * ELEMENT DATA // See below - IF EGW_DATA_TYPE_RANGE: - "count": [Count of Elements], | "ids": [ Array with element ids ], - "group": [ Action Link Group to which the generated objects should be added ] - "prefix": "[String prefix which will be added to each element including their index in the list]" - * } - * ] - * - * 2. If a string or number is passed, inside an array, it is encapsulated into - * an empty entry with that id - * - * 3. If an object with element dara is passed, the properties of the element will - * be updated to the given values. - * - * { - * "data": { COLUMN DATA OBJECT } // See "set_data" function - * "caption": "[Caption]" // Used in the EGW_COL_TYPE_NAME_ICON_FIXED column - * "iconUrl": "[IconUrl]" // Used in the EGW_COL_TYPE_NAME_ICON_FIXED column - * "opened": [true|false] // Specifies whether the row is "opened" or "closed" (in trees) - * "canHaveChildren": [true|false] // Specifies whether the row "open/close" button is displayed - * } - */ -egwGridDataElement.prototype.loadData = function(_data, _doCallUpdate) -{ - // Store the current timestamp - EGW_GRID_DATA_UPDATE_TIME = (new Date).getTime(); - - if (typeof _doCallUpdate == "undefined") - { - _doCallUpdate = false; - } - - if (_data.constructor == Array) - { - var virgin = this.children.length == 0; - var last_element = null; - - for (var i = 0; i < _data.length; i++) - { - var entry = _data[i]; - - // Single string entries are automatically converted to an entry - // with that id - if (typeof entry == String || typeof entry == Number) - { - entry = { - "id": (entry + '') // The "+ ''" converts the entry to a string - } - } - - if (entry.constructor != Object) - { - continue; - } - - var element = null; - - // Read the entry type and the element type (if they are set) - var entryType = typeof entry.entryType == "number" ? entry.entryType : - EGW_DATA_TYPE_ELEMENT; - var type = (typeof entry.type == "string") && (typeof window["egwGridView" + entry.type] == "function") ? - window["egwGridView" + entry.type] : egwGridViewRow; - - // Inserts a range of given dummy elements into the data tree - if (entryType == EGW_DATA_TYPE_RANGE) - { - var prefix = typeof entry.prefix == "string" ? entry.prefix : "elem_"; - var canHaveChildren = typeof entry.canHaveChildren == "boolean" ? entry.canHaveChildren : false; - var index = last_element ? last_element.index + 1 : 0; - var group = typeof entry.group == "string" ? entry.group : false; - var ids = []; - - if (typeof entry.ids != "undefined") - { - ids = entry.ids; - } - else if (typeof entry.count != "undefined") - { - var count = typeof entry.count == "number" && entry.count >= 0 ? entry.count : 1; - - for (var j = 0; j < count; j++) - { - ids.push(prefix + (index + j)); - } - } - - for (var j = 0; j < ids.length; j++) - { - element = this.insertElement(index + j, ids[j]); - element.type = type; // Type can only be set directly after creation - element.canHaveChildren = canHaveChildren; - if (group !== false) - { - element.set_group(group); - } - } - } - else if (entryType == EGW_DATA_TYPE_ELEMENT) - { - var id = typeof entry.id == "string" ? entry.id : ""; - element = null; - - if (!virgin && id) - { - element = this.getElementById(id, 1); - } - - if (!element) - { - element = this.insertElement(false, id); - element.type = type; // Type can only be set directly after creation - } - - - element.loadData(entry); - } - - last_element = element; - } - } - else - { - // Load all the data element for which a setter function exists - egwActionStoreJSON(_data, this, true); - - // Load the child data - if (typeof _data.children != "undefined" && _data.children.constructor == Array) - { - this.loadData(_data.children); - } - - if (_doCallUpdate) - { - this.callBeginUpdate(); - } - - this.callGridViewObjectUpdate(); - } -} - -/** - * Resets all relevant data (the column data, icon and icon size) of the element - * and triggers a gridViewObj update. - */ -egwGridDataElement.prototype.clearData = function() -{ - this.data = {}; - this.caption = false; - this.iconUrl = false; - this.iconSize = false; - this.capColTime = 0; - - this.callGridViewObjectUpdate(); -} - -/** - * Inserts a new element as child at the given position - * - * @param integer _index is the index at which the element will be inserted. If - * false, the element will be added to the end of the list. - * @param string _id is the id of the newly created element - * @returns the newly created element - */ -egwGridDataElement.prototype.insertElement = function(_index, _id) -{ - if (!_index) - { - _index = this.children.length; - } - else - { - _index = Math.max(0, Math.min(this.children.length, _index)); - } - - // Create the data element - var element = new egwGridDataElement(_id, this, this.columns, this.readQueue, - null); - element.index = _index; - - // Create the action object with a temporary AOI which can be used to make - // the object visible - var object = this.actionObject.insertObject(_index, _id, - new egwGridTmpAOI(this.getRootElement().gridObject, _index), 0); - object.data = element; - - // Link the two together - element.actionObject = object; - - // As this element now at least has one child, "canHaveChildren" must be true - this.canHaveChildren = true; - - // Insert the element at the given index - this.children.splice(_index, 0, element); - - // Increment the index of all following elements - for (var i = _index + 1; i < this.children.length; i++) - { - this.children[i].index++; - } - - return element; -} - -/** - * Adds a new data element as child to the end of the list. - * - * @param string _id is the object identifier - * @returns the newly created element - */ -egwGridDataElement.prototype.addElement = function(_id) -{ - return this.insertElement(false, _id); -} - -egwGridDataElement.prototype.removeElement = function() -{ - //TODO -} - -/** - * Searches for the element with the given id and returns it. _depth specifies - * the maximum recursion depth. May be omited. - */ -egwGridDataElement.prototype.getElementById = function(_id, _depth) -{ - if (typeof _depth == "undefined") - { - _depth = -1; - } - - // Check whether this element is the searched one, if yes return it - if (_id == this.id) - { - return this; - } - - // Only continue searching in deeper levels, if the given depth is greater than - // zero, or hasn't been defined and is therefore smaller than zero - if (_depth < 0 || _depth > 0) - { - for (var i = 0; i < this.children.length; i++) - { - var elem = this.children[i].getElementById(_id, _depth - 1); - - if (elem) - { - return elem; - } - } - } - - return null; -} - -/** - * Returns all children as array - this list will be used to set the item list - * of the egwGridViewSpacer containers. - */ -egwGridDataElement.prototype.getChildren = function(_callback, _context) -{ - if (this.children.length > 0) - { - _callback.call(_context, this.children, true); - } - else if (this.canHaveChildren) - { - // If the children havn't been loaded yet, request them via queue call. - this.readQueue.queueCall(this, EGW_DATA_QUEUE_CHILDREN, function() { - _callback.call(_context, this.children, false); - }, this); - } -} - -egwGridDataElement.prototype.hasColumn = function(_columnId, _returnData) -{ - // Get the column - var col = this.columns.getColumnById(_columnId); - var res = null; - - if (col) - { - res = false; - - // Check whether the queried column is the "EGW_COL_TYPE_NAME_ICON_FIXED" column - if (col.type == EGW_COL_TYPE_NAME_ICON_FIXED) - { - if (this.caption !== false) - { - if (_returnData) - { - res = { - "caption": this.caption, - "iconUrl": this.iconUrl, - "time": this.capColTime, - "queued": false - } - } - else - { - res = true; - } - } - - if (!_returnData && typeof (this.data[_columnId]) != "undefined" && this.data[_columnId].queued) - { - res = true; - } - } - else if (col.type == EGW_COL_TYPE_CHECKBOX) - { - if (!_returnData) - { - res = true; // Tell the loader that the checkbox data is always available - } - else - { - var dataSet = (typeof this.data[_columnId] != "undefined"); - res = { - "data": dataSet ? this.data[_columnId].data : 0, - "time": dataSet ? this.data[_columnId].time : this.capColTime, - "queued": false - } - } - } - else - { - // Check whether the column data of this column has been read, - // if yes, return it. - if (typeof this.data[_columnId] != "undefined") - { - if (_returnData) - { - // If the data should be returned, simply return it - if (typeof this.data[_columnId].data != "undefined") - { - res = this.data[_columnId]; - } - } - else - { - // Otherwise check whether the data has been loaded - if this - // is the case, return true - if (typeof this.data[_columnId].data != "undefined") - { - res = true; - } - else - { - // Otherwise return the "queued" state - res = this.data[_columnId].queued; - } - } - } - // Probably there is a default value specified for this column... - else if (col["default"] !== EGW_COL_DEFAULT_FETCH) - { - if (_returnData) - { - res = col["default"]; - } - else - { - res = true; - } - } - } - } - - return res; -} - -/** - * Returns the data for the given columns or incomplete data if those columns - * are not available now. Those columns are loaded asynchronously in the background - * and the GridViewObject is informed about this as soon as the new data has been - * loaded. - * - * @param _columnIds is an array of column ids for which the data should be returned - */ -egwGridDataElement.prototype.getData = function(_columnIds) -{ - var queryList = []; - var result = {}; - - for (var i = 0; i < _columnIds.length; i++) - { - var res = this.hasColumn(_columnIds[i], true); - - // Either add the result to the result list (if the column data was available) - // or add it to the query list. - if (res !== null) - { - if (res !== false) - { - if (typeof res.queued != "undefined" && res.queued != false) - { - result[_columnIds[i]] = false; - } - else - { - result[_columnIds[i]] = res; - } - } - else - { - queryList.push(_columnIds[i]); - } - } - } - - // If one data entry hasn't been available, queue the request for this data - // in the readQueue - if (queryList.length > 0) - { - this.readQueue.queueCall(this, queryList); - } - - return result; -} - - -/** - * Calls the row object update function - checks whether the row object implements - * this interface and whether it is set. - */ -egwGridDataElement.prototype.callGridViewObjectUpdate = function(_immediate) -{ - if (typeof _immediate == "undefined") - { - _immediate = false; - } - - if (this.gridViewObj && typeof this.gridViewObj.doUpdateData == "function") - { - this.gridViewObj.doUpdateData(_immediate); - } -} - -egwGridDataElement.prototype.getDeepestOpened = function() -{ - if (this.opened && this.children.length > 0) - { - return this.children[this.children.length - 1].getDeepestOpened(); - } - else - { - return this; - } -} - -/** - * Returns whether this data element is a odd or even one - */ -egwGridDataElement.prototype.isOdd = function() -{ - return (this.index % 2) == 0; // Improve - old exact version needed way too much performance -} - -/** - * Function which is called by the grid view container in order to update the - * action object aoi. - */ -egwGridDataElement.prototype.setGridViewObj = function(_obj) -{ - this.gridViewObj = _obj; - - if (_obj && typeof _obj.getAOI == "function") - { - var aoi = _obj.getAOI(); - this.actionObject.setAOI(aoi); - aoi.reconnectActions(); - } - else - { - this.actionObject.setAOI(null); - } -} - -/** - * Returns the root element - */ -egwGridDataElement.prototype.getRootElement = function() -{ - if (!this.parent) - { - return this; - } - else - { - return this.parent.getRootElement(); - } -} - -/** - * Returns the depth of this element in the document tree - */ -egwGridDataElement.prototype.getDepth = function() -{ - return (this.parent) ? (this.parent.getDepth() + 1) : 0; -} - -/** - * Calls the beginUpdate function of the grid associated to the grid view object - */ -egwGridDataElement.prototype.callBeginUpdate = function() -{ - if (this.gridViewObj) - { - var root = this.getRootElement(); - - if (root.updatedGrid != this.gridViewObj.grid) - { - if (root.updatedGrid) - { - root.updatedGrid.endUpdate(); - } - root.updatedGrid = this.gridViewObj.grid; - root.updatedGrid.beginUpdate(); - } - } -} - -/** - * Calls the end update function of the currently active updated grid - */ -egwGridDataElement.prototype.callEndUpdate = function() -{ - var root = this.getRootElement(); - - if (root.updatedGrid) - { - root.updatedGrid.endUpdate(); - root.updatedGrid = null; - } -} - -/** - * Deletes all child elements - */ -egwGridDataElement.prototype.empty = function() -{ - this.actionObject.clear(); - this.children = []; - - // Prevent all event handlers which are associated to elements in the read - // queue from being called - those elements might no longer exist - this.readQueue.flushEventQueue(); -} - -/** - * Returns all parents in a list - */ -egwGridDataElement.prototype.getParentList = function(_lst) -{ - if (typeof _lst == "undefined") - { - _lst = []; - } - - _lst.push(this); - - if (this.parent) - { - this.parent.getParentList(_lst); - } - - return _lst; -} - -/** - * Requires a certain column to have all data localy - if this isn't the case, - * the data is fetched from the server. - * - * @param string _colId specifies the column which should be loaded - * @param function _callback is the function which should be called once all data - * has been fetched. - * @param object _context is the context in which the callback should be executed - * @param object _loadIds is used internally to accumulate the object ids which - * should be loaded. - */ -egwGridDataElement.prototype.requireColumn = function(_colId, _callback, _context, - _loadElems) -{ - var outerCall = false; - if (typeof _loadElems == "undefined") - { - _loadElems = { - "elems": [] - } - outerCall = true; - } - - if (!outerCall && !this.hasColumn(_colId, false)) - { - _loadElems.elems.push(this); - } - - for (var i = 0; i < this.children.length; i++) - { - this.children[i].requireColumn(_colId, null, null, _loadElems); - } - - // TODO: In which cases has this to be aborted? - if (outerCall) - { - if (_loadElems.elems.length > 0) - { - this.readQueue.queueCall(_loadElems.elems, [_colId], function() { - _callback.call(_context); - }, null); - } - else - { - // If all elements had been loaded, postpone calling the callback function - window.setTimeout(function() { - _callback.call(_context); - }, 0); - } - } -} - - -/** - * Sorts the data element by the given column, the given sort direction and the - * given sort mode - if the tree doesn't have all the column data loaded which is - * needed for sorting, it first queries it from the server. - * - * @param string _colId is the id of the column - * @param int _dir is one of EGW_COL_SORTMODE_* - * @param int _mode is one of EGW_COL_SORTABLE_* - * @param function _callback is a callback function which is called once the - * sorting is done - * @param - * @param boolean _outerCall is used internally, do not specify it - */ -egwGridDataElement.prototype.sortChildren = function(_colId, _dir, _mode, _callback, - _context, _outerCall) -{ - if (typeof _outerCall == "undefined") - { - _outerCall = true; - } - - // If this is the outer call of the function, we first have to make sure - // that all data for the given column id is available - if (_outerCall) - { - this.requireColumn(_colId, function() { - // Call the actual sort part of this function by explicitly passing "false" - // to the _outerCall parameter - this.sortChildren(_colId, _dir, _mode, _callback, _context, false); - - _callback.call(_context); - }, this); - } - else - { - // Select the sort function - var sortFunc = null; - switch (_mode) { - case EGW_COL_SORTABLE_ALPHABETIC: - sortFunc = egwGridData_sortAlphabetic; - break; - - case EGW_COL_SORTABLE_NATURAL: - sortFunc = egwGridData_sortNatural; - break; - - case EGW_COL_SORTABLE_NUMERICAL: - sortFunc = egwGridData_sortNumerical; - break; - } - - var col = this.columns.getColumnById(_colId); - - // Determine the mode multiplier which is used to sort the list in the - // given direction. - var dirMul = (_dir == EGW_COL_SORTMODE_ASC) ? 1 : -1; - this.children.sort(function (a, b) { - // Fetch the sortData or the regular data from the a and b element - // and pass it to the sort function - var aData = ""; - var bData = ""; - - switch (col.type) - { - case EGW_COL_TYPE_DEFAULT: - aData = a.data[_colId].sortData === null ? a.data[_colId].data : - a.data[_colId].sortData; - bData = b.data[_colId].sortData === null ? b.data[_colId].data : - b.data[_colId].sortData; - break; - - case EGW_COL_TYPE_NAME_ICON_FIXED: - aData = a.caption; - bData = b.caption; - break; - - case EGW_COL_TYPE_CHECKBOX: - aData = a.actionObject.getSelected() ? 1 : 0; - bData = b.actionObject.getSelected() ? 1 : 0; - break; - } - - return sortFunc(aData, bData) * dirMul; - }); - - // Sort all children - for (var i = 0; i < this.children.length; i++) - { - this.children[i].sortChildren(_colId, _dir, _mode, null, null, false); - } - - // Sorting is done - call the callback function - if (_callback) - { - _callback.call(_context); - } - } -} - -function egwGridData_sortAlphabetic(a, b) -{ - return (a > b) ? 1 : -1; -} - -function egwGridData_sortNumerical(a, b) -{ - aa = parseFloat(a); - bb = parseFloat(b); - - return (aa > bb) ? 1 : -1; -} - -/** - * See http://my.opera.com/GreyWyvern/blog/show.dml/1671288 - */ -function egwGridData_sortNatural(a, b) -{ - function chunkify(t) - { - var tz = [], x = 0, y = -1, n = 0, i, j; - - while (i = (j = t.charAt(x++)).charCodeAt(0)) - { - var m = (i == 46 || (i >=48 && i <= 57)); - if (m !== n) - { - tz[++y] = ""; - n = m; - } - tz[y] += j; - } - - return tz; - } - - var aa = chunkify(a); - var bb = chunkify(b); - - for (x = 0; aa[x] && bb[x]; x++) - { - if (aa[x] !== bb[x]) - { - var c = Number(aa[x]), d = Number(bb[x]); - if (c == aa[x] && d == bb[x]) - { - return c - d; - } - else - { - return (aa[x] > bb[x]) ? 1 : -1; - } - } - } - return aa.length - bb.length; -} - - -/** - * Returns the outermost parent of a set of elements - assume the following tree - * where the elements marked with "x" are passed as array to this function: - * - * ROOT - * |- CHILD 1 - * |- SUB_CHILD 1 - * |- SUB_CHILD 2 (x) - * |- CHILD 2 - * |- SUB_CHILD 1 - * |- SUB_SUB_CHILD 1 (x) - * The function should now return the "ROOT" elements as this is the outermost - * parent the elements have in common. - * - * TODO: If I think about this, the function actually doesn't work like I'd like - * it to behave... - */ -function egwGridData_getOutermostParent(_elements) -{ - var minElem = null; - var minCnt = 0; - - for (var i = 0; i < _elements.length; i++) - { - var parents = _elements[i].getParentList(); - - if (i == 0 || parents.length < minCnt) - { - minCnt = parents.length; - minElem = _elements[i]; - } - } - - return minElem ? (minElem.parent ? minElem.parent : minElem) : null; -} - - -/** - egwGridDataReadQueue -- **/ - -// Some internally used constants -var EGW_DATA_QUEUE_ELEM = 0; -var EGW_DATA_QUEUE_CHILDREN = 1; - -// Count of elements which are dynamically added to the update list. -var EGW_DATA_QUEUE_PREFETCH_COUNT = 50; - -// Timeout after which the queue events are no longer queued but the actual -// callback function is called. -var EGW_DATA_QUEUE_FLUSH_TIMEOUT = 200; - -// Maximum count of elements in the queue after which the queue is flushed -var EGW_DATA_QUEUE_MAX_ELEM_COUNT = 100; - -function egwGridDataQueue(_fetchCallback, _context) -{ - this.fetchCallback = _fetchCallback; - this.context = _context; - this.dataRoot = null; - - this.queue = []; - this.queueColumns = []; - this.timeoutId = 0; - - this.eventQueue = new egwEventQueue(); -} - -/** - * Prevents handling the response function - e.g. if the data elements got emptied. - */ -egwGridDataQueue.prototype.flushEventQueue = function() -{ - this.eventQueue.flush(); -} - -egwGridDataQueue.prototype.setDataRoot = function(_dataRoot) -{ - this.dataRoot = _dataRoot; -} - -/** - * Adds an element to the queue and checks whether its element count is larger - * than the one specified in EGW_DATA_QUEUE_MAX_ELEM_COUNT. If this is the case, - * the queue is flushed and false is returned, otherwise true. - */ -egwGridDataQueue.prototype._queue = function(_obj, _last) -{ - this.timeoutId++; - - // Push the queue object onto the queue - this.queue.push(_obj); - - if (_last && this.queue.length > EGW_DATA_QUEUE_MAX_ELEM_COUNT) - { - this.flushQueue(false); - return false; - } - else - { - // Specify that the element data is queued - if (_obj.type != EGW_DATA_QUEUE_CHILDREN) - { - for (var i = 0; i < this.queueColumns.length; i++) - { - if (typeof _obj.elem.data[this.queueColumns[i]] == "undefined") - { - _obj.elem.data[this.queueColumns[i]] = { - "queued": true - } - } - } - } - - // Set the flush queue timeout - if (_last) - { - var tid = this.timeoutId; - var self = this; - this.eventQueue.queueTimeout(this.flushQueue, this, [true], - "dataQueueTimeout", EGW_DATA_QUEUE_FLUSH_TIMEOUT); - } - } - - return true; -} - -egwGridDataQueue.prototype._accumulateQueueColumns = function(_columns) -{ - if (this.dataRoot.columns.columns.length > this.queueColumns.length) - { - // Merge the specified columns into the queueColumns variable - for (var i = 0; i < _columns.length; i++) - { - if (this.queueColumns.indexOf(_columns[i]) == -1) - { - this.queueColumns.push(_columns[i]); - } - } - } -} - -/** - * Queues the given element in the fetch-data queue. - * - * @param object/array _elems is a single element or an array of elements - - * their data will be fetched - * @param array _columns is an array of column ids which should be fetched. Those - * columns will be accumulated over the queue calls. _columns may also take - * the value EGW_DATA_QUEUE_CHILDREN in which case a request for the children - * of the given element is queued. - * @param function _callback is a callback function which will be called after - * the data has been sent from the server. - * @param object _context is the context in which the callback function will - * be executed. - */ -egwGridDataQueue.prototype.queueCall = function(_elems, _columns, _callback, _context) -{ - if (typeof _callback == "undefined") - { - _callback = null; - } - if (typeof _context == "undefined") - { - _context = null; - } - - if (!(_elems instanceof Array)) - { - _elems = [_elems]; - } - - for (var i = 0; i < _elems.length; i++) - { - var last = i == _elems.length - 1; - if (_columns === EGW_DATA_QUEUE_CHILDREN) - { - this._queue({ - "elem": _elems[i], - "type": EGW_DATA_QUEUE_CHILDREN, - "callback": last ? _callback : null, - "context": _context - }, last); - } - else - { - // Accumulate the queue columns ids - this._accumulateQueueColumns(_columns); - - // Queue the element and search in the elements around the given one for - // elements whose data isn't loaded yet. - this._queue({ - "elem": _elems[i], - "type": EGW_DATA_QUEUE_ELEM, - "callback": last ? _callback : null, - "context": _context - }, last); - } - } -} - -egwGridDataQueue.prototype._getQueuePlanes = function() -{ - var planes = []; - var curPlane = null; - - for (var i = 0; i < this.queue.length; i++) - { - var elem = this.queue[i].elem; - - if (!curPlane || elem.parent != curPlane.parent) - { - curPlane = null; - for (var j = 0; j < planes.length; j++) - { - if (planes[j].parent == elem.parent) - { - curPlane = planes[j]; - break; - } - } - - if (!curPlane) - { - curPlane = { - "parent": elem.parent, - "cnt": 0, - "min": 0, - "max": 0, - "idx": 0, - "done": false - }; - planes.push(curPlane); - } - } - - if (curPlane.cnt == 0 || elem.index < curPlane.min) - { - curPlane.min = elem.index; - } - if (curPlane.cnt == 0 || elem.index > curPlane.max) - { - curPlane.max = elem.index; - } - - curPlane.cnt++; - } - - return planes; -} - -egwGridDataQueue.prototype.prefetch = function(_cnt) -{ - var cnt = _cnt; - var planes = this._getQueuePlanes(); - - // Set the start indices - for (var i = 0; i < planes.length; i++) - { - planes[i].idx = Math.max(0, Math.ceil(planes[i].min - _cnt / (2 * planes.length))); - } - - // Add as many elements as specified to the prefetched elements - var done = 0; - var plane = 0; - while (cnt > 0 && done < planes.length) - { - if (!planes[plane].done) - { - var idx = planes[plane].idx; - - if (!planes[plane].parent || idx == planes[plane].parent.children.length) - { - planes[plane].done = true; - done++; - } - else - { - var hasData = true; - var elem = planes[plane].parent.children[idx]; - for (var j = 0; j < this.queueColumns.length; j++) - { - if (!elem.hasColumn(this.queueColumns[j], false)) - { - hasData = false; - break; - } - } - - if (!hasData) - { - this._queue({ - "elem": elem, - "type": EGW_DATA_QUEUE_ELEM, - "callback": null, - "context": null - }); - cnt--; - } - - planes[plane].idx++; - } - } - - // Go to the next plane - plane = (plane + 1) % planes.length; - } -} - -egwGridDataQueue.prototype.empty = function() -{ - this.queue = []; -} - -/** - * Empties the queue and calls the fetch callback which cares about retrieving - * the data from the server. - */ -egwGridDataQueue.prototype.flushQueue = function(_doPrefetch) -{ - var ids = []; - - if (_doPrefetch) - { - // Get the count of elements which will be dynamically added to the list, "prefetched" - var prefetch_cnt = Math.min(EGW_DATA_QUEUE_PREFETCH_COUNT, - Math.max(0, EGW_DATA_QUEUE_MAX_ELEM_COUNT - this.queue.length)); - - this.prefetch(prefetch_cnt); - } - - // Generate a list of element ids - for (var i = 0; i < this.queue.length; i++) - { - var id = this.queue[i].elem.id; - if (id == this.queue[i].elem.id) - { - if (this.queue[i].type == EGW_DATA_QUEUE_CHILDREN) - { - id = "[CHILDREN]" + id; - } - } - - ids.push(id); - } - - // Check whether there actually are elements queued... - if (ids.length > 0) - { - // Call the fetch callback and save a snapshot of the current queue - var queue = this.queue; - this.fetchCallback.call(this.context, ids, this.queueColumns, function(_data) { - this.dataCallback(_data, queue); - }, this); - - this.queue = []; - this.queueColumns = []; - this.timeoutId = 0; - } -} - -/** - * Internal function which is called when the data is received from the fetchCallback. - * - * @param _data contains the data which has been retrieved by the fetchCallback - * @param _queue is the list of elements which had been requested. - */ -egwGridDataQueue.prototype.dataCallback = function(_data, _queue) -{ - var rootData = []; - try - { - // Iterate over the given data and check whether the data coresponds to one - // of the queue elements - if yes, call their (probably) specified callback. - // All elements for which no queue element can be found are added to the - // "rootData" list, which is then loaded by the "dataRoot" data object. - var i = 0; - for (var i = 0; i < _data.length; i++) - { - var hasTarget = false; - - // Search for a queue element which belongs to the given data entry. - if (_queue.length > 0 && typeof _data[i].id != "undefined") - { - var id = _data[i].id; - - for (var j = 0; j < _queue.length; j++) - { - if (_queue[j].elem.id == id) - { - _queue[j].elem.loadData(_data[i], true); - - // Call the queue object callback (if specified) - if (_queue[j].callback) - { - _queue[j].callback.call(_queue[j].context); - } - - // Delete this queue element - _queue.splice(j, 1); - - hasTarget = true; - break; - } - } - } - - if (!hasTarget) - { - rootData.push(_data[i]); - } - } - - this.dataRoot.loadData(rootData, true); - } - finally - { - this.dataRoot.callEndUpdate(); - } -} - diff --git a/phpgwapi/js/egw_action/egw_grid_view.js b/phpgwapi/js/egw_action/egw_grid_view.js deleted file mode 100644 index 8b030baead..0000000000 --- a/phpgwapi/js/egw_action/egw_grid_view.js +++ /dev/null @@ -1,2170 +0,0 @@ -/** - * 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 - jquery.jquery; - egw_stylesheet; -*/ - -/** - * Common functions used in most view classes - */ - -/** - * Returns an "area" object with the given top position and height - */ -function egwArea(_top, _height) -{ - return { - "top": _top, - "bottom": _top + _height - } -} - -/** - * Returns whether two area objects intersect each other - */ -function egwAreaIntersect(_ar1, _ar2) -{ - return ! (_ar1.bottom < _ar2.top || _ar1.top > _ar2.bottom); -} - -/** - * Returns whether two areas intersect (result = 0) or their relative position - * to each other (used to do a binary search inside a list of sorted area objects). - */ -function egwAreaIntersectDir(_ar1, _ar2) -{ - if (_ar1.bottom < _ar2.top) - { - return -1; - } - if (_ar1.top > _ar2.bottom) - { - return 1; - } - return 0; -} - - -/** -- egwGridViewOuter Class -- **/ - -var EGW_GRID_COLUMN_PADDING = 2; -var EGW_GRID_SCROLLBAR_WIDTH = false; -var EGW_GRID_HEADER_BORDER_WIDTH = false; -var EGW_GRID_COLUMN_BORDER_WIDTH = false; -var EGW_UNIQUE_COUNTER = 0; - -/** - * Base view class which is responsible for displaying a grid view element. - * - * @param object _parentNode is the DOM-Node into which the grid view will be inserted - * @param object _data is the data-provider object which contains/loads the grid rows - * and contains their data. - */ -function egwGridViewOuter(_parentNode, _dataRoot, _selectColsCallback, _toggleAllCallback, - _sortColsCallback, _context) -{ - this.parentNode = $j(_parentNode); - this.dataRoot = _dataRoot; - - EGW_UNIQUE_COUNTER++; - - // Build the base nodes - this.outer_table = null; - this.outer_thead = null; - this.outer_head_tr = null; - this.outer_tbody = null; - this.outer_tr = null; - this.optcol = null; - this.selectcols = null; - - this.oldWidth = 0; - this.oldHeight = 0; - this.scrollbarWidth = 0; - - this.visibleColumnCount = 0; - - this.checkbox = null; - - this.uniqueId = 'grid_outer_' + EGW_UNIQUE_COUNTER; - - this.headerColumns = []; - this.selectColsCallback = _selectColsCallback; - this.sortColsCallback = _sortColsCallback; - this.toggleAllCallback = _toggleAllCallback; - this.context = _context; - - this.styleSheet = new egwDynStyleSheet(); - - this.buildBase(); - - // Now that the base grid has been build, we can perform a few tests, to - // determine some browser/CSS dependant width values - - // Read the scrollbar width - this.scrollbarWidth = Math.max(10, this.getScrollbarWidth()); - - // Read the th and td border width - this.headerBorderWidth = this.getHeaderBorderWidth(); - this.columnBorderWidth = this.getColumnBorderWidth(); - - // Start value for the average row height - this.avgRowHeight = 19.0; - this.avgRowCnt = 1; - - // Insert the base grid container into the DOM-Tree - this.grid = new egwGridViewGrid(null, null, true, this); // (No parent grid, no height change callback, scrollable) - this.grid.insertIntoDOM(this.outer_tr, []); - - this.dataRoot.gridObject = this.grid; -} - -/** - * Adds a new element to the average container height counter. - */ -egwGridViewOuter.prototype.addHeightToAvg = function(_value) -{ - this.avgRowCnt++; - - var frac = 1.0 / this.avgRowCnt; - this.avgRowHeight = this.avgRowHeight * (1 - frac) + _value * frac; -} - -/** - * Removes the height from the average container height - */ -egwGridViewOuter.prototype.remHeightFromAvg = function(_value) -{ - var sum = this.avgRowHeight * this.avgRowCnt - _value; - this.avgRowCnt--; - this.avgRowCount = sum / this.avgRowCnt; -} - -/** - * Removes all containers from the base grid and replaces it with spacers again. - * As only partial data is displayed, this method is faster than updating every - * displayed data row. Please note that this may also reset/change the scrollbar - * position. - */ -egwGridViewOuter.prototype.empty = function() -{ - this.grid.empty(this.columns); - - // Create a new spacer container and set the item list to the root level children - var spacer = this.grid.insertContainer(-1, egwGridViewSpacer, this.avgRowHeight); - this.dataRoot.getChildren(function(_children) { - spacer.setItemList(_children); - }, null); -} - -/** - * 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.buildBase = function() -{ - /* - Structure: - - - [HEAD] - - - [GRID CONTAINER] - -
- */ - - this.outer_table = $j(document.createElement("table")); - this.outer_table.addClass("egwGridView_outer"); - this.outer_thead = $j(document.createElement("thead")); - this.outer_tbody = $j(document.createElement("tbody")); - this.outer_tr = $j(document.createElement("tr")); - this.outer_head_tr = $j(document.createElement("tr")); - - this.outer_table.append(this.outer_thead, this.outer_tbody); - this.outer_tbody.append(this.outer_tr); - this.outer_thead.append(this.outer_head_tr); - - this.parentNode.append(this.outer_table); -} - -egwGridViewOuter.prototype.updateColSortmode = function(_colIdx, _sortArrow) -{ - if (typeof _sortArrow == "undefined") - { - _sortArrow = $j("span.sort", this.headerColumns[_colIdx]); - } - - var col = this.columns[_colIdx]; - if (_sortArrow) - { - _sortArrow.removeClass("asc"); - _sortArrow.removeClass("desc"); - - switch (col.sortmode) - { - case EGW_COL_SORTMODE_ASC: - _sortArrow.addClass("asc"); - break; - case EGW_COL_SORTMODE_DESC: - _sortArrow.addClass("desc"); - break; - } - } -} - -egwGridViewOuter.prototype.buildBaseHeader = function() -{ - // Build the "option-column", if this hasn't been done yet - if (this.headerColumns.length == 0) - { - // Create the head columns - this.headerColumns = []; - - for (var i = 0; i < this.columns.length; i++) - { - var col = this.columns[i]; - - // Create the column element and insert it into the DOM-Tree - var column = $j(document.createElement("th")); - column.addClass(col.tdClass); - this.headerColumns.push(column); - - var cont = $j(document.createElement("div")); - cont.addClass("innerContainer"); - cont.addClass(col.divClass); - - if (col.type == EGW_COL_TYPE_CHECKBOX) - { - this.checkbox = $j(document.createElement("input")); - this.checkbox.attr("type", "checkbox"); - this.checkbox.change(this, function(e) { - // Call the toggle all callback - if (e.data.toggleAllCallback) - { - e.data.toggleAllCallback.call(e.data.context, $j(this).is(":checked")); - } - }); - - cont.append(this.checkbox); - } else { - var caption = $j(document.createElement("span")); - caption.html(col.caption); - - cont.append(caption); - } - - if (col.type != EGW_COL_TYPE_CHECKBOX && col.sortable != EGW_COL_SORTABLE_NONE) - { - var sortArrow = $j(document.createElement("span")); - sortArrow.addClass("sort"); - cont.append(sortArrow); - - this.updateColSortmode(i, sortArrow); - - column.click({"self": this, "idx": i}, function(e) { - var idx = e.data.idx; - var self = e.data.self; - if (self.sortColsCallback) - { - self.sortColsCallback.call(self.context, idx); - } - }); - } - - column.append(cont); - this.outer_head_tr.append(column); - } - - // Build the "select columns" icon - this.selectcols = $j(document.createElement("span")); - this.selectcols.addClass("selectcols"); - - // Build the option column - this.optcol = $j(document.createElement("th")); - this.optcol.addClass("optcol"); - this.optcol.append(this.selectcols); - - // Append the option column and set its width of the last column - this.outer_head_tr.append(this.optcol); - - this.optcol.css("width", this.scrollbarWidth - this.optcol.outerWidth() - + this.optcol.width() + 1); - this.optcol.click(this, function(e) { - e.data.selectColsCallback.call(e.data.context, e.data.selectcols); - - return false; - }); - } -} - -/** - * Calculates the width of the browser scrollbar - */ -egwGridViewOuter.prototype.getScrollbarWidth = function() -{ - if (EGW_GRID_SCROLLBAR_WIDTH === false) - { - // Create a temporary td and two div, which are inserted into the dom-tree - var td = $j(document.createElement("td")); - var div_outer = $j(document.createElement("div")); - var div_inner = $j(document.createElement("div")); - - // The outer div has a fixed size and "overflow" set to auto. When the second - // div is inserted, it will be forced to display a scrollbar. - div_outer.css("height", "100px"); - div_outer.css("width", "100px"); - div_outer.css("overflow", "auto"); - - div_inner.css("height", "1000px"); - - // Clone the outer table and insert it into the top window (which should) - // always be visible. - var clone = this.outer_table.clone(); - var top_body = $j(window.top.document.getElementsByTagName("body")[0]); - top_body.append(clone); - - $j("tbody tr", clone).append(td); - td.append(div_outer); - div_outer.append(div_inner); - - // Store the scrollbar width statically. - EGW_GRID_SCROLLBAR_WIDTH = div_outer.outerWidth() - div_inner.outerWidth(); - - // Remove the temporary elements again. - clone.remove(); - } - - return EGW_GRID_SCROLLBAR_WIDTH; -} - -/** - * Calculates the total width of the header column border - */ - egwGridViewOuter.prototype.getHeaderBorderWidth = function() -{ - if (EGW_GRID_HEADER_BORDER_WIDTH === false) - { - // Create a temporary th which is appended to the outer thead row - var cont = $j(document.createElement("div")); - cont.addClass("innerContainer"); - - var th = $j(document.createElement("th")); - th.append(cont); - - // Clone the outer table and insert it into the top window (which should) - // always be visible. - var clone = this.outer_table.clone(); - var top_body = $j(window.top.document.getElementsByTagName("body")[0]); - top_body.append(clone); - - // Insert the th into the document tree - $j("thead tr", clone).append(th); - - // Calculate the total border width - EGW_GRID_HEADER_BORDER_WIDTH = th.outerWidth(true) - cont.width(); - - // Remove the clone again - clone.remove(); - } - - return EGW_GRID_HEADER_BORDER_WIDTH; -} - -/** - * Calculates the total width of the column border - */ -egwGridViewOuter.prototype.getColumnBorderWidth = function() -{ - if (EGW_GRID_COLUMN_BORDER_WIDTH === false) - { - // Create a temporary td which is appended to the outer tbody row - var cont = $j(document.createElement("div")); - cont.addClass("innerContainer"); - - var td = $j(document.createElement("td")); - td.append(cont); - - // Insert the th into the document tree - var clone = this.outer_table.clone(); - var top_body = $j(window.top.document.getElementsByTagName("body")[0]); - top_body.append(clone); - - clone.addClass("egwGridView_grid"); - $j("tbody tr", clone).append(td); - - // Calculate the total border width - EGW_GRID_COLUMN_BORDER_WIDTH = td.outerWidth(true) - cont.width(); - - // Remove the clone again - clone.remove(); - } - - return EGW_GRID_COLUMN_BORDER_WIDTH; -} - -egwGridViewOuter.prototype.setHeight = function(_h) -{ - this.grid.setScrollHeight(_h - this.outer_thead.outerHeight()); -} - - -/** -- egwGridViewContainer Interface -- **/ - -/** - * Constructor for the abstract egwGridViewContainer class. A grid view container - * represents a chunk of data which is inserted into a grid. As the grid itself - * is a container, hirachical structures can be realised. All containers are inserted - * into the DOM tree directly after creation. - * - * @param object _grid is the parent grid this container is inserted into. - */ -function egwGridViewContainer(_grid, _heightChangeProc) -{ - this.grid = _grid; - this.visible = true; - this.position = 0; - this.heightChangeProc = _heightChangeProc; - this.parentNode = null; - this.columns = []; - this.height = false; - this.assumedHeight = false; - this.index = 0; - this.viewArea = false; - this.containerClass = ""; - this.heightInAvg = false; - this.updated = true; - - this.doInsertIntoDOM = null; - this.doSetViewArea = null; -} - -/** - * Calls the heightChangeProc (if set) in the context of the parent grid (if set) - */ -egwGridViewContainer.prototype.callHeightChangeProc = function() -{ - if (this.heightChangeProc && this.grid) - { - // Pass this element as parameter - this.heightChangeProc.call(this.grid, this); - } -} - -/** - * Sets the visibility of the container. Setting the visibility only takes place - * if the parentNode is set and the visible state has changed or the _force - * parameter is set to true. - */ -egwGridViewContainer.prototype.setVisible = function(_visible, _force) -{ - // Default the _force parameter to force - if (typeof _force == "undefined") - { - _force = false; - } - - if ((_visible != this.visible || _force) && this.parentNode) - { - $j(this.parentNode).toggleClass("hidden", !_visible); - - if (_visible) - { - this.assumedHeight = 0; - this.height = false; - } - - // As the element is now (in)visible, its height has changed. Inform the - // parent about it. - this.callHeightChangeProc(); - } - - this.visible = _visible; -} - -/** - * Returns whether the container is visible. The element is not visible as long - * as it isn't implemented into the DOM-Tree. - */ -egwGridViewContainer.prototype.getVisible = function() -{ - return this.parentNode && this.visible; -} - -/** - * Inserts the container into the given _parentNode. This method may only be - * called once after the creation of the container. - * - * @param object _parentNode is the parentDOM-Node into which the container should - * be inserted. - * @param array _columns is an array of columns which will be generated - */ -egwGridViewContainer.prototype.insertIntoDOM = function(_parentNode, _columns) -{ - if (_parentNode && !this.parentNode) - { - // Copy the function arguments - this.columns = _columns; - this.parentNode = $j(_parentNode); - - // Call the interface function of the implementation which will insert its data - // into the parent node. - return egwCallAbstract(this, this.doInsertIntoDOM, arguments); - - this.setVisible(this.visible); - } - else - { - throw "egw_action Exception: egwGridViewContainer::insertIntoDOM called more than once for a container object or parent node not specified."; - } - - return false; -} - -egwGridViewContainer.prototype.setViewArea = function(_area, _force) -{ - // Calculate the relative coordinates and pass those to the implementation - if (_area) - { - var relArea = { - "top": _area.top - this.position, - "bottom": _area.bottom - this.position - }; - - this.viewArea = relArea; - - if (isNaN(this.viewArea.top)) - { - throw("View Area got NaN"); - } - - this.checkViewArea(_force); - } -} - -egwGridViewContainer.prototype.getViewArea = function() -{ - if (this.viewArea && this.visible) - { - return this.viewArea; - } - - return false; -} - -egwGridViewContainer.prototype.setPosition = function(_top) -{ - // Recalculate the relative view area - if (this.viewArea) - { - var at = this.position + this.viewArea.top; - this.viewArea = { - "top": at - _top, - "bottom": at - _top + (this.viewArea.bottom - this.viewArea.top) - }; - - this.checkViewArea(); - } - - this.position = _top; -} - -/** - * Returns the height of the container in pixels and zero if the element is not - * visible. The height is clamped to positive values. - * The browser switch is placed at this position as the getHeight function is one - * of the mostly called functions in the whole grid code and should stay - * quite fast. - */ -if (navigator.userAgent.match(/Mozilla /) && !navigator.userAgent.match(/WebKit /)) -{ - egwGridViewContainer.prototype.getHeight = function(_update) - { - if (typeof _update == "undefined") - _update = false; - - if (this.visible && this.parentNode) - { - if ((this.height === false && this.assumedHeight === false) || _update) - { - // Firefox sometimes provides fractional pixel values - we are - // forced to use those - we can obtain the fractional pixel height - // by using the window.getComputedStyle function - var compStyle = getComputedStyle(this.parentNode.context, null); - if (compStyle) - { - var styleHeightStr = compStyle.getPropertyValue("height"); - this.height = parseFloat(styleHeightStr.substr(0, styleHeightStr.length - 2)); - - if (isNaN(this.height) || this.height < 1) - { - this.height = false; - } - else - { - this.assumedHeight = false; - } - } - } - - return this.height !== false ? this.height : this.assumedHeight; - } - - return 0; - } -} -else -{ - egwGridViewContainer.prototype.getHeight = function(_update) - { - if (typeof _update == "undefined") - _update = false; - - if (this.visible && this.parentNode) - { - if ((this.height === false && this.assumedHeight === false) || _update) - { - this.height = this.parentNode.context.offsetHeight - - if (this.height < 1) { - this.height = false; - } - else - { - this.assumedHeight = false; - } - } - - return this.height !== false ? this.height : this.assumedHeight; - } - - return 0; - } -} - -egwGridViewContainer.prototype.invalidateHeightCache = function() -{ - this.assumedHeight = false; - this.height = false; -} - -egwGridViewContainer.prototype.offsetPosition = function(_offset) -{ - this.position += _offset; - - // Offset the view area in the oposite direction - if (this.viewArea) - { - this.viewArea.top -= _offset; - this.viewArea.bottom -= _offset; - - this.checkViewArea(); - } -} - -egwGridViewContainer.prototype.inArea = function(_area) -{ - return egwAreaIntersect(this.getArea(), _area); -} - -egwGridViewContainer.prototype.checkViewArea = function(_force) -{ - if (typeof _force == "undefined") - { - _force = false; - } - - if (this.visible && this.viewArea) - { - if (!this.grid || !this.grid.inUpdate || _force) - { - return egwCallAbstract(this, this.doSetViewArea, [this.viewArea]); - } - } - - return false; -} - -egwGridViewContainer.prototype.getArea = function() -{ - return egwArea(this.position, this.getHeight()); -} - -egwGridViewContainer.prototype.getAbsolutePosition = function() -{ - if (this.grid) - { - return this.grid.getAbsolutePosition() + this.position; - } - else - { - return this.position; - } -} - -egwGridViewContainer.prototype.getAbsoluteArea = function() -{ - return egwArea(this.getAbsolutePosition(), this.getHeight()); -} - -/** - * Function which is called whenever the column count or the data inside the columns - * has probably changed - the checkViewArea function of the grid element is called - * and the variable "updated" is set to true. Grid elements should check this - * flag and set it to false if they have successfully updated themselves. - */ -egwGridViewContainer.prototype.updateColumns = function(_columns) -{ - this.columns = _columns; - - this.updated = true; - this.checkViewArea(); -} - -/** -- egwGridViewGrid Class -- **/ - -var EGW_GRID_VIEW_EXT = 25; -var EGW_GRID_MAX_CYCLES = 10; -var EGW_GRID_SCROLL_TIMEOUT = 100; -var EGW_GRID_UPDATE_HEIGHTS_TIMEOUT = 50; - -/** - * egwGridViewGrid is the container for egwGridViewContainer objects, but itself - * implements the egwGridViewContainer interface. - */ -function egwGridViewGrid(_grid, _heightChangeProc, _scrollable, _outer) -{ - if (typeof _scrollable == "undefined") - { - _scrollable = false; - } - - EGW_UNIQUE_COUNTER++; - - var container = new egwGridViewContainer(_grid, _heightChangeProc); - - // Introduce new functions to the container interface - container.outerNode = null; - container.innerNode = null; - container.scrollarea = null; - container.scrollable = _scrollable; - container.scrollHeight = 100; - container.scrollEvents = 0; - container.inUpdate = 0; - container.didUpdate = false; - container.updateIndex = 0; - container.triggerID = 0; - container.setupContainer = egwGridViewGrid_setupContainer; - container.insertContainer = egwGridViewGrid_insertContainer; - container.removeContainer = egwGridViewGrid_removeContainer; - container.addContainer = egwGridViewGrid_addContainer; - container.heightChangeHandler = egwGridViewGrid_heightChangeHandler; - container.setScrollHeight = egwGridViewGrid_setScrollHeight; - container.scrollCallback = egwGridViewGrid_scrollCallback; - container.empty = egwGridViewGrid_empty; - container.getOuter = egwGridViewGrid_getOuter; - container.updateAssumedHeights = egwGridViewGrid_updateAssumedHeights; - container.beginUpdate = egwGridViewGrid_beginUpdate; - container.endUpdate = egwGridViewGrid_endUpdate; - container.triggerUpdateAssumedHeights = egwGridViewGrid_triggerUpdateAssumedHeights; - container.addIconHeightToAvg = egwGridViewGrid_addIconHeightToAvg; - container.setIconWidth = egwGridViewGrid_setIconWidth; - container.updateColumns = egwGridViewGrid_updateColumns; - container.children = []; - container.outer = _outer; - container.containerClass = "grid"; - container.avgIconHeight = 16; - container.avgIconCnt = 1; - container.uniqueId = "grid_" + EGW_UNIQUE_COUNTER; - container.maxIconWidth = 16; - container.styleSheet = new egwDynStyleSheet(); - - // Overwrite the abstract container interface functions - container.getHeight = egwGridViewGrid_getHeight; - container.doInsertIntoDOM = egwGridViewGrid_doInsertIntoDOM; - container.doSetViewArea = egwGridViewGrid_doSetviewArea; - - // Set the default selectmode - container.selectmode = EGW_SELECTMODE_DEFAULT; - - return container; -} - -function egwGridViewGrid_setIconWidth(_value) -{ - if (_value > this.maxIconWidth) - { - this.maxIconWidth = _value; - - this.styleSheet.updateRule(".iconContainer." + this.uniqueId, - "min-width: " + (this.maxIconWidth + 8) + "px;"); - } -} - -function egwGridViewGrid_beginUpdate() -{ - if (this.inUpdate == 0) - { - this.didUpdate = false; - - if (this.grid) - { - this.grid.beginUpdate(); - } - } - this.inUpdate++; -} - -function egwGridViewGrid_triggerUpdateAssumedHeights() -{ - this.triggerID++; - var self = this; - var id = this.triggerID; - window.setTimeout(function() { - if (id == self.triggerID) - { - self.triggerID = 0; - self.updateAssumedHeights(20); - } - }, - EGW_GRID_UPDATE_HEIGHTS_TIMEOUT - ); -} - -function egwGridViewGrid_endUpdate(_recPrev) -{ - if (typeof _recPrev == "undefined") - { - _recPrev = false; - } - - if (this.inUpdate > 0) - { - this.inUpdate--; - - if (this.inUpdate == 0 && this.grid) - { - this.grid.endUpdate(); - } - - if (this.inUpdate == 0 && this.didUpdate) - { - // If an update has been done, check whether any height assumptions have been - // done. This procedure is executed with some delay, as this gives the browser - // the time to insert the newly generated objects into the DOM-Tree and allows - // us to read their height at a very fast rate. - if (this.didUpdate && !_recPrev) - { - this.triggerUpdateAssumedHeights(); - } - - this.didUpdate = false; - } - } -} - -function egwGridViewGrid_updateColumns(_columns) -{ - try - { - this.beginUpdate(); - - this.didUpdate = true; - - // Set the colspan value of the grid - this.outerNode.attr("colspan", this.getOuter().visibleColumnCount - + (this.scrollable ? 1 : 0)); - - // Call the update function of all children - for (var i = 0; i < this.children.length; i++) - { - this.children[i].updateColumns(_columns); - } - - // Call the inherited function - egwGridViewContainer.prototype.updateColumns.call(this, _columns); - - this.updated = false; - } - finally - { - this.endUpdate(); - } -} - -function egwGridViewGrid_getOuter() -{ - if (this.outer) - { - return this.outer; - } - else if (this.grid) - { - return this.grid.getOuter(); - } - - return null; -} - -function egwGridViewGrid_setupContainer() -{ - /* - Structure: - - [
] - - - [Container 1] - [Container 2] - [...] - [Container n] - -
- [
] - - */ - - this.outerNode = $j(document.createElement("td")); - this.outerNode.addClass("frame"); - - if (this.scrollable) - { - this.scrollarea = $j(document.createElement("div")); - this.scrollarea.addClass("egwGridView_scrollarea"); - this.scrollarea.css("height", this.scrollHeight + "px"); - this.scrollarea.scroll(this, function(e) { - e.data.scrollEvents++; - var cnt = e.data.scrollEvents; - window.setTimeout(function() { - e.data.scrollCallback(cnt); - }, EGW_GRID_SCROLL_TIMEOUT); - }); - } - - var table = $j(document.createElement("table")); - table.addClass("egwGridView_grid"); - - this.innerNode = $j(document.createElement("tbody")); - - if (this.scrollable) - { - this.outerNode.append(this.scrollarea); - this.scrollarea.append(table); - } - else - { - this.outerNode.append(table); - } - - table.append(this.innerNode); -} - -function egwGridViewGrid_setScrollHeight(_value) -{ - this.scrollHeight = _value; - - if (this.scrollarea) - { - this.scrollarea.css("height", _value + "px"); - this.scrollCallback(); - } -} - -function egwGridViewGrid_scrollCallback(_event) -{ - if ((typeof _event == "undefined" || _event == this.scrollEvents) && this.scrollarea) - { - var cnt = 0; - var area = egwArea(this.scrollarea.scrollTop() - EGW_GRID_VIEW_EXT, - this.scrollHeight + EGW_GRID_VIEW_EXT * 2); - - this.setViewArea(area); - - this.scrollEvents = 0; - } -} - -function egwGridViewGrid_updateAssumedHeights(_maxCount) -{ - var traversed = 0; - var cnt = _maxCount; - var outer = this.getOuter(); - - try - { - this.beginUpdate(); - - while (traversed < this.children.length && cnt > 0) - { - // Clamp the update index - if (this.updateIndex >= this.children.length) - { - this.updateIndex = 0; - } - - // Get the child at the given position and check whether it used - // an assumed height - var child = this.children[this.updateIndex]; - if (child.assumedHeight !== false) - { - // Get the difference (delta) between the assumed and the real - // height - var oldHeight = child.assumedHeight; - - //XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX - // This is an ugly hack, but currently I don't have the time to - // provide a proper fix - problem is that with the "invalidateHeightCache" - // line wrong height values may be returned which causes all - // grid data to be loaded. The workaround for this causes - // the tree view not to work correctly. - var newHeight; - if (egw_getObjectManager("felamimail", false) != null) - { - newHeight = child.getHeight(true); - } - else - { - child.invalidateHeightCache(); - newHeight = child.getHeight(); - } - //XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX - - if (child.containerClass == "row") - { - if (child.heightInAvg) - { - outer.remHeightFromAvg(oldHeight); - } - outer.addHeightToAvg(newHeight); - child.heightInAvg = true; - } - - // Offset the position of all following elements by the delta. - var delta = newHeight - oldHeight; - - if (Math.abs(delta) > 0.001) - { - for (var j = this.updateIndex + 1; j < this.children.length; j++) - { - this.children[j].offsetPosition(delta); - } - } - - // We've now worked on one element with assumed height, decrease - // the counter - cnt--; - } - - // Increment the element index and the count of checked elements - this.updateIndex++; - traversed++; - } - } - finally - { - this.endUpdate(true); - } - - if (cnt == 0) - { - // If the maximum-update-count has been exhausted, retrigger this function - this.triggerUpdateAssumedHeights(); - } - else if (this.viewArea) - { - // Otherwise, all elements have been checked - we'll now call "setViewArea" - // which may check whether new objects are now in the currently visible range - var self = this; - window.setTimeout(function() { - self.setViewArea(self.viewArea); - }, EGW_GRID_UPDATE_HEIGHTS_TIMEOUT); - } -} - -function egwGridViewGrid_insertContainer(_after, _class, _params) -{ - var container = null; - - try - { - this.beginUpdate(); - this.didUpdate = true; - - container = new _class(this, this.heightChangeHandler, _params); - - var idx = this.children.length; - if (typeof _after == "number") - { - idx = Math.min(this.children.length, Math.max(-1, _after)) + 1; - } - else if (typeof _after == "object" && _after) - { - idx = _after.index + 1; - } - - // Insert the element at the given position - this.children.splice(idx, 0, container); - - // Create a table row for that element - var tr = $j(document.createElement("tr")); - - // Insert the table row after the container specified in the _after parameter - // and set the top position of the node - container.index = idx; - - if (idx == 0) - { - this.innerNode.prepend(tr); - container.setPosition(0); - } - else - { - tr.insertAfter(this.children[idx - 1].parentNode); - container.setPosition(this.children[idx - 1].getArea().bottom); - } - - // Insert the container into the table row - container.insertIntoDOM(tr, this.columns); - - // Offset the position of all following elements by the height of the container - // and move the index of those elements - var height = this.getOuter().avgRowHeight; - container.assumedHeight = height; - for (var i = idx + 1; i < this.children.length; i++) - { - this.children[i].offsetPosition(height); - this.children[i].index++; - } - } - finally - { - this.endUpdate(); - } - - return container; -} - -function egwGridViewGrid_removeContainer(_container) -{ - this.didUpdate = true; - - try - { - this.beginUpdate(); - - var idx = _container.index; - - // Offset the position of the folowing children back - var height = _container.getHeight(); - for (var i = idx + 1; i < this.children.length; i++) - { - this.children[i].offsetPosition(-height); - this.children[i].index--; - } - - // Delete the parent node of the container object - if (_container.parentNode) - { - _container.parentNode.remove(); - _container.parentNode = null; - } - - this.children.splice(idx, 1); - } - finally - { - this.endUpdate(); - } - - this.callHeightChangeProc(); -} - -function egwGridViewGrid_empty(_newColumns) -{ - if (typeof _newColumns != "undefined") - { - this.columns = _newColumns; - } - - this.innerNode.empty(); - this.children = []; - this.maxIconWidth = 16; -} - -function egwGridViewGrid_addContainer(_class) -{ - // Insert the container at the beginning of the list. - this.insertContainer(false, _class); - return container; -} - -function egwGridViewGrid_getHeight() -{ - if (this.visible && this.parentNode) - { - if (this.height === false) - { - this.height = this.innerNode.outerHeight(); - } - return this.height; - } - else - { - return 0; - } -} - -function egwGridViewGrid_heightChangeHandler(_elem) -{ - this.didUpdate = true; - - // The old height of the element is now only an assumed height - the next - // time the "updateAssumedHeights" functions is triggered, this will be - // updated. - var oldHeight = _elem.assumedHeight !== false ? _elem.assumedHeight : - (_elem.height === false ? 0 : _elem.height); - _elem.invalidateHeightCache(false); - _elem.assumedHeight = oldHeight; - - if ((_elem.containerClass == "grid" || _elem.containerClass == "spacer") && !this.inUpdate) - { - this.triggerUpdateAssumedHeights(); - } - - // As a result of the height of one of the children, the height of this element - // has changed too - inform the parent grid about it. - this.callHeightChangeProc(); -} - -function egwGridViewGrid_doInsertIntoDOM() -{ - // Generate the DOM Nodes and append the outer node to the parent node - this.setupContainer(); - this.parentNode.append(this.outerNode); - - this.outerNode.attr("colspan", this.columns.length + (this.scrollable ? 1 : 0)); -} - -function egwGridViewGrid_doSetviewArea(_area, _recPrev) -{ - if (typeof _recPrev == "undefined") - { - _recPrev == false; - } - - // Do a binary search for elements which are inside the given area - this.didUpdate = false; - var elem = null; - var elems = []; - - var bordertop = 0; - var borderbot = this.children.length - 1; - var idx = 0; - while ((borderbot - bordertop >= 0) && !elem) - { - idx = Math.round((borderbot + bordertop) / 2); - - var ar = this.children[idx].getArea(); - - var dir = egwAreaIntersectDir(_area, ar); - - if (dir == 0) - { - elem = this.children[idx]; - } - else if (dir == -1) - { - borderbot = idx - 1; - } - else - { - bordertop = idx + 1; - } - } - - if (elem) - { - elems.push(elem); - - // Search upwards for elements in the area from the matched element on - for (var i = idx - 1; i >= 0; i--) - { - if (this.children[i].inArea(_area)) - { - elems.unshift(this.children[i]); - } - else - { - break; - } - } - - // Search downwards for elemwnts in the area from the matched element on - for (var i = idx + 1; i < this.children.length; i++) - { - if (this.children[i].inArea(_area)) - { - elems.push(this.children[i]); - } - else - { - break; - } - } - } - - try - { - this.beginUpdate(); - - // Call the setViewArea function of visible child elements - // Imporant: The setViewArea function has to work on a copy of children, - // as the container may start to remove themselves or add new elements using - // the insertAfter function. - for (var i = 0; i < elems.length; i++) - { - elems[i].setViewArea(_area, true); - } - } - finally - { - this.endUpdate(_recPrev); - } -} - -function egwGridViewGrid_addIconHeightToAvg(_value) -{ - this.avgIconCnt++; - - var frac = 1.0 / this.avgIconCnt; - this.avgIconHeight = this.avgIconHeight * (1 - frac) + _value * frac; -} - -/** -- egwGridViewRow Class -- **/ - -function egwGridViewRow(_grid, _heightChangeProc, _item) -{ - var container = new egwGridViewContainer(_grid, _heightChangeProc); - - // Copy the item parameter, which is used when fetching data from the data - // source - container.item = _item; - - // Set a few new functions/properties - container.isOdd = 0; - container.aoiSetup = egwGridViewRow_aoiSetup; - container.getAOI = egwGridViewRow_getAOI; - container._columnClick = egwGridViewRow__columnClick; - container._checkboxClick = egwGridViewRow__checkboxClick; - container.setOpen = egwGridViewRow_setOpen; - container.reloadChildren = egwGridViewRow_reloadChildren; - container.tdObjects = []; - container.containerClass = "row"; - container.childGrid = null; - container.opened = false; - container.rowClass = ""; - container.checkbox = null; - - // Overwrite the inherited abstract functions - container.doInsertIntoDOM = egwGridViewRow_doInsertIntoDOM; - container.doSetViewArea = egwGridViewRow_doSetViewArea; - container.doUpdateData = egwGridViewRow_doUpdateData; - - return container; -} - -/** - * Creates AOI instance of the item and overwrites all necessary functions. - */ -function egwGridViewRow_aoiSetup() -{ - this.aoi = new egwActionObjectInterface(); - - // The default state of an aoi is EGW_AO_STATE_NORMAL || EGW_AO_STATE_VISIBLE - - // egwGridItems are not necessarily visible by default - this.aoi._state = EGW_AO_STATE_NORMAL; - this.aoi.row = this; - this.aoi.doSetState = egwGridViewRow_aoiSetState; - this.aoi.doTriggerEvent = egwGridViewRow_aoiTriggerEvent; - this.aoi.doMakeVisible = egwGridViewRow_aoiMakeVisible; - this.aoi.getDOMNode = egwGridViewRow_aoiGetDOMNode; -} - -function egwGridViewRow_aoiSetState(_state, _shiftState) -{ - if (this.row.parentNode) - { - var selected = egwBitIsSet(_state, EGW_AO_STATE_SELECTED); - this.row.parentNode.toggleClass("selected", selected); - this.row.parentNode.toggleClass("focused", egwBitIsSet(_state, - EGW_AO_STATE_FOCUSED)); - - // Set the checkbox checked-state with the selected state - if (this.row.checkbox) - { - this.row.checkbox.attr("checked", selected); - } - } -} - -function egwGridViewRow_aoiGetDOMNode() -{ - return this.row.parentNode ? this.row.parentNode.context : null; -} - -function egwGridViewRow_aoiTriggerEvent(_event, _data) -{ - if (_event == EGW_AI_DRAG_OVER) - { - this.row.parentNode.addClass("draggedOver"); - } - - if (_event == EGW_AI_DRAG_OUT) - { - this.row.parentNode.removeClass("draggedOver"); - } -} - -function egwGridViewRow_aoiMakeVisible() -{ - egwGridView_scrollToArea(this.row.grid.getOuter().grid.scrollarea, - this.row.getAbsoluteArea()); -} - -/** - * Returns the actionObjectInterface object of this grid item. - */ -function egwGridViewRow_getAOI() -{ - return this.aoi; -} - -function egwGridViewRow__columnClick(_shiftState, _column) -{ - var state = this.aoi.getState(); - var isSelected = egwBitIsSet(state, EGW_AO_STATE_SELECTED); - - switch (this.grid.selectmode) - { - case EGW_SELECTMODE_DEFAULT: - this.aoi.updateState(EGW_AO_STATE_SELECTED, - !egwBitIsSet(_shiftState, EGW_AO_SHIFT_STATE_MULTI) || !isSelected, - _shiftState); - break; - case EGW_SELECTMODE_TOGGLE: - this.aoi.updateState(EGW_AO_STATE_SELECTED, !isSelected, - egwSetBit(_shiftState, EGW_AO_SHIFT_STATE_MULTI, true)); - break; - } -} - -function egwGridViewRow__checkboxClick() -{ - this.aoi.updateState(EGW_AO_STATE_SELECTED, this.checkbox.is(":checked"), - EGW_AO_SHIFT_STATE_MULTI); - - return false; -} - -var - EGW_GRID_VIEW_ROW_BORDER = false; - -function egwGridViewRow_doInsertIntoDOM() -{ - this.parentNode.empty(); - this.parentNode.addClass("row"); - - // Setup the aoi and inform the item about it - if (!this.aoi) - { - this.aoiSetup(); - this.item.setGridViewObj(this); - } - - for (var i = 0; i < this.columns.length; i++) - { - var col = this.columns[i]; - - var td = $j(document.createElement("td")); - td.addClass(col.tdClass); - - var cont = $j(document.createElement("div")); - cont.addClass(col.divClass); - cont.addClass("innerContainer"); - - this.parentNode.append(td); - - // Assign the click event to the column - td.mousedown(egwPreventSelect); - if (col.type == EGW_COL_TYPE_CHECKBOX) - { - this.checkbox = $j(document.createElement("input")); - this.checkbox.attr("type", "checkbox"); - this.checkbox.attr("checked", egwBitIsSet(this.aoi.getState(), - EGW_AO_STATE_SELECTED)); - this.checkbox.change(this, function(e) { - e.data._checkboxClick(); - return false; - }); - - cont.append(this.checkbox); - } - else - { - td.click({"item": this, "col": col.id}, function(e) { - // Reset the browser focus, so that key navigation will work - // properly - egwUnfocus(); - this.onselectstart = null; - if (!e.data.item.checkbox || this != e.data.item.checkbox.context) - { - e.data.item._columnClick(egwGetShiftState(e), e.data.col); - } - }); - } - - td.append(cont); - - // Store the column in the td object array - this.tdObjects.push({ - "td": td, - "cont": cont, - "ts": 0 - }); - } - - this.doUpdateData(true); - - this.checkViewArea(); -} - -function egwGridViewRow_doUpdateData(_immediate) -{ - var ids = []; - var vis_cnt = 0; - for (var i = 0; i < this.columns.length; i++) - { - if (this.columns[i].visible) - { - ids.push(this.columns[i].id); - vis_cnt++; - } - } - - var data = this.item.getData(ids); - var vis_idx = 0; - - // Set the row class - if (this.rowClass != this.item.rowClass) - { - if (this.rowClass != "") - { - this.parentNode.removeClass(this.rowClass); - } - - this.parentNode.addClass(this.item.rowClass); - this.rowClass = this.item.rowClass; - } - - // Set the column data - for (var i = 0; i < this.tdObjects.length; i++) - { - var col = this.columns[i]; - - if (col.visible) - { - vis_idx++; - - var cont = this.tdObjects[i].cont; - if (typeof data[col.id] != "undefined") - { - // If the timestamp of the tdObject and the data is still the - // same we don't have to update - if (this.tdObjects[i].ts == data[col.id].time) - { - continue; - } - - // Update the timestamp - this.tdObjects[i].ts = data[col.id].time; - - if (col.type == EGW_COL_TYPE_NAME_ICON_FIXED) - { - cont.empty(); - // Insert the indentation spacer - var depth = this.item.getDepth() - 1; - if (depth > 0) - { - // Build the indentation object - var indentation = $j(document.createElement("span")); - indentation.addClass("indentation"); - indentation.css("width", (depth * 20) + "px"); - cont.append(indentation); - } - - // Insert the open/close arrow - var arrow = $j(document.createElement("span")); - arrow.addClass("arrow"); - if (this.item.canHaveChildren) - { - arrow.addClass(this.item.opened ? "opened" : "closed"); - arrow.click(this, function(e) { - $this = $j(this); - - if (!e.data.opened) - { - $this.addClass("opened"); - $this.removeClass("closed"); - } - else - { - $this.addClass("closed"); - $this.removeClass("opened"); - } - - e.data.setOpen(!e.data.opened); - - return false; // Don't bubble this event - }); - arrow.dblclick(function() {return false;}); - } - cont.append(arrow); - - // Insert the icon - if (data[col.id].iconUrl) - { - // Build the icon container - var iconContainer = $j(document.createElement("span")); - iconContainer.addClass("iconContainer " + this.grid.uniqueId); - - // Default the iconContainer height to the average height - this attribute - // is removed from the row as soon as the icon is loaded - iconContainer.css("min-height", this.grid.avgIconHeight + "px"); - - // Build the icon - var overlayCntr = $j(document.createElement("span")); - overlayCntr.addClass("iconOverlayContainer"); - - var icon = $j(document.createElement("img")); - if (this.item.iconSize) - { - icon.css("height", this.item.iconSize + "px"); - icon.css("width", this.item.iconSize + "px"); //has to be done because of IE :-( - } - icon.load({"item": this, "cntr": iconContainer}, function(e) { - e.data.cntr.css("min-height", ""); - var icon = $j(this); - window.setTimeout(function() { - e.data.item.grid.setIconWidth(icon.width()); - e.data.item.grid.addIconHeightToAvg(icon.height()); - }, 100); - e.data.item.callHeightChangeProc(); - }); - - icon.attr("src", data[col.id].iconUrl); - - overlayCntr.append(icon); - - if (this.item.iconOverlay.length > 0) - { - var overlayCntr2 = $j(document.createElement("span")); - overlayCntr2.addClass("overlayContainer"); - for (var i = 0; i < this.item.iconOverlay.length; i++) - { - var overlay = $j(document.createElement("img")); - overlay.addClass("overlay"); - overlay.attr("src", this.item.iconOverlay[i]); - overlayCntr2.append(overlay); - } - overlayCntr.append(overlayCntr2); - } - - icon.addClass("icon"); - iconContainer.append(overlayCntr); - cont.append(iconContainer); - } - - // Build the caption - if (data[col.id].caption) - { - var caption = $j(document.createElement("span")); - caption.addClass("caption"); - caption.html(data[col.id].caption); - cont.append(caption); - } - } - else if (col.type == EGW_COL_TYPE_CHECKBOX) - { - var checked = (data[col.id].data === 0) ? - egwBitIsSet(this.aoi.getState(), EGW_AO_STATE_SELECTED) : - data[col.id].data; - this.checkbox.attr("checked", checked); - this.item.actionObject.setSelected(checked); - } - else - { - cont.empty(); - cont.html(data[col.id].data); - } - cont.toggleClass("queued", false); - } - else - { - cont.empty(); - cont.toggleClass("queued", true); - } - } - } - - // Set the open state - this.setOpen(this.item.opened); - - // If the call is not from inside the doInsertIntoDOM function, we have to - // inform the parent about a possible height change - if (!_immediate && (this.height || this.assumedHeight)) - { - this.callHeightChangeProc(); - } -} - -function egwGridViewRow_doSetViewArea() -{ - if (this.updated) - { - this.updated = false; - this.doUpdateData(false); - } -} - -function egwGridViewRow_setOpen(_open, _force) -{ - if (typeof _force == "undefined") - { - _force = false; - } - - if (_open != this.opened || _force) - { - var inserted = false; - - if (_open) - { - if (!this.childGrid) - { - // Get the arrow and put it to "loading" state - var arrow = $j(".arrow", this.parentNode); - arrow.removeClass("closed"); - arrow.addClass("loading"); - - // Create the "child grid" - var childGrid = null; - this.childGrid = childGrid = this.grid.insertContainer(this.index, egwGridViewGrid, - false); - inserted = true; - this.childGrid.setVisible(false); - var spacer = this.childGrid.insertContainer(-1, egwGridViewSpacer, - this.grid.getOuter().avgRowHeight); - this.item.getChildren(function(_children) { - arrow.removeClass("loading"); - arrow.removeClass("closed"); - arrow.addClass("opened"); - spacer.setItemList(_children); - childGrid.setVisible(true); - }); - } - } - - if (this.childGrid && !inserted) - { - if (!_open) - { - // Deselect all childrens - for (var i = 0; i < this.item.children.length; i++) - { - this.item.children[i].actionObject.setAllSelected(false); - } - } - - this.childGrid.setVisible(_open); - } - - this.opened = _open; - this.item.opend = _open; - } -} - -function egwGridViewRow_reloadChildren() -{ - // Remove the child grid container - if (this.childGrid) - { - this.grid.removeContainer(this.childGrid); - this.childGrid = null; - - // Remove all the data from the data object - this.item.empty(); - - // Recreate the child grid - this.setOpen(this.opened, true); - } -} - - -/** -- egwGridViewSpacer Class -- **/ - -function egwGridViewSpacer(_grid, _heightChangeProc, _itemHeight) -{ - if (typeof _itemHeight == "undefined") - { - _itemHeight = 20; - } - - var container = new egwGridViewContainer(_grid, _heightChangeProc); - - // Add some new functions/properties to the container - container.itemHeight = _itemHeight; - container.domNode = null; - container.items = []; - container.setItemList = egwGridViewSpacer_setItemList; - container.containerClass = "spacer"; - - // Overwrite the inherited functions - container.doInsertIntoDOM = egwGridViewSpacer_doInsertIntoDOM; - container.doSetViewArea = egwGridViewSpacer_doSetViewArea; - - return container; -} - -function egwGridViewSpacer_setItemList(_items) -{ - this.items = _items; - - if (this.domNode) - { - this.domNode.css("height", (this.items.length * this.itemHeight) + "px"); - this.callHeightChangeProc(); - } -} - -/** - * Creates the spacer DOM-Node and inserts it into the DOM-Tree. - */ -function egwGridViewSpacer_doInsertIntoDOM() -{ - this.domNode = $j(document.createElement("td")); - this.domNode.addClass("egwGridView_spacer"); - this.domNode.addClass(this.grid.getOuter().uniqueId + "_spacer_fullRow"); - this.domNode.css("height", (this.items.length * this.itemHeight) + "px"); - this.domNode.attr("colspan", this.columns.length); - - this.parentNode.append(this.domNode); -} - -/** - * Checks which elements this spacer contains are inside the given area and - * creates those. - */ -function egwGridViewSpacer_doSetViewArea() -{ - if (this.items.length > 0) - { - var avgHeight = this.grid.getOuter().avgRowHeight; - - // Get all items which are in the view area - var top = Math.max(0, Math.floor(this.viewArea.top / this.itemHeight)); - var bot = Math.min(this.items.length, Math.ceil(this.viewArea.bottom / this.itemHeight)); - - // Split the item list into three parts - var it_top = this.items.slice(0, top); - var it_mid = this.items.slice(top, bot); - var it_bot = this.items.slice(bot, this.items.length); - - this.items = []; - var idx = this.index; - - // Insert the new rows in the parent grid in front of the spacer container - for (var i = it_mid.length - 1; i >= 0; i--) - { - this.grid.insertContainer(idx - 1, it_mid[i].type, it_mid[i]); - } - - // If top was greater than 0, insert a new spacer in front of the newly - // created elements. - if (it_top.length > 0) - { - // this.itemHeight has to be passed to the new top spacer - otherwise the - // scroll position might change and we'll go into a nasty setViewArea - // loop. - var spacer = this.grid.insertContainer(idx - 1, egwGridViewSpacer, this.itemHeight); - spacer.setItemList(it_top); - } - - // If there are items left at the bottom of the spacer, set theese as items of this spacer - if (it_bot.length > 0) - { - // The height of this (the bottom) spacer can be set to the average height - this.itemHeight = avgHeight; - this.setItemList(it_bot); - } - else - { - this.grid.removeContainer(this); - } - } -} - - - - -/** -- egwGridViewFullRow Class -- **/ - -/** - * The egwGridViewFullRow Class has only one td which contains a single caption - */ - -function egwGridViewFullRow(_grid, _heightChangeProc, _item) -{ - var container = new egwGridViewContainer(_grid, _heightChangeProc); - - // Copy the item parameter, which is used when fetching data from the data - // source - container.item = _item; - - // Set a few new functions/properties - use the row aoi functions - container.aoiSetup = egwGridViewRow_aoiSetup; - container.getAOI = egwGridViewRow_getAOI; - container.containerClass = "row"; - container._columnClick = egwGridViewRow__columnClick; - container.td = null; - container.cont = null; - - // Overwrite the inherited abstract functions - container.doInsertIntoDOM = egwGridViewFullRow_doInsertIntoDOM; - container.doSetViewArea = egwGridViewFullRow_doSetViewArea; - container.doUpdateData = egwGridViewFullRow_doUpdateData; - - return container; -} - -function egwGridViewFullRow_doInsertIntoDOM() -{ - this.parentNode.empty(); - this.parentNode.addClass("row"); - this.parentNode.addClass("fullRow"); - - // Setup the aoi and inform the item about it - if (!this.aoi) - { - this.aoiSetup(); - this.item.setGridViewObj(this); - } - - var td = this.td = $j(document.createElement("td")); - td.attr("colspan", this.columns.length); - - var cont = this.cont = $j(document.createElement("div")); - cont.addClass("innerContainer"); - cont.addClass(this.grid.getOuter().uniqueId + '_div_fullRow'); - - td.append(cont); - this.parentNode.append(td); - - this.doUpdateData(true); - - this.checkViewArea(); -} - -function egwGridViewFullRow_doUpdateData(_immediate) -{ - this.cont.empty(); - - if (this.item.caption) - { - // Insert the indentation spacer - var depth = this.item.getDepth(); - if (depth > 0) - { - // Build the indentation object - var indentation = $j(document.createElement("span")); - indentation.addClass("indentation"); - indentation.css("width", (depth * 20) + "px"); - this.cont.append(indentation); - } - - // Insert the caption - var caption = $j(document.createElement("span")); - caption.addClass("caption"); - caption.html(this.item.caption); - this.cont.append(caption); - } - - // If the call is not from inside the doInsertIntoDOM function, we have to - // inform the parent about a possible height change - if (!_immediate && (this.height || this.assumedHeight)) - { - this.callHeightChangeProc(); - } -} - -function egwGridViewFullRow_doSetViewArea() -{ - // -} - -/** - * Temporary AOI which has to be assigned to invisible grid objects in order - * to give them the possiblity to make them visible when using e.g. keyboard navigation - */ -function egwGridTmpAOI(_grid, _index) -{ - var aoi = new egwActionObjectDummyInterface(); - - // Assign the make visible function - aoi.grid = _grid; - aoi.index = _index; - aoi.doMakeVisible = egwGridTmpAOI_makeVisible; - - return aoi; -} - -function egwGridTmpAOI_makeVisible() -{ - // Assume an area for the element (this code is not optimal, but it should - // work in most cases - problem is that the elements in the grid may have equal - // sizes and the grid is scrolled to some area where the element is not) - var avgHeight = this.grid.getOuter().avgRowHeight; - var area = egwArea(this.grid.getAbsolutePosition() + this.index * avgHeight, - avgHeight); - - egwGridView_scrollToArea(this.grid.getOuter().grid.scrollarea, area); -} - -function egwGridView_scrollToArea(_scrollarea, _visarea) -{ - // Get the current view area - var va = egwArea(_scrollarea.scrollTop(), _scrollarea.height()); - - // Calculate the assumed position of this element - var pos = _visarea; - - // Check whether it is currently (completely) visible, if not scroll the - // scroll area to that position - if (!(pos.top >= va.top && pos.bottom <= va.bottom)) - { - if (pos.top < va.top) - { - _scrollarea.scrollTop(pos.top); - } - else - { - _scrollarea.scrollTop(va.top + pos.bottom - va.bottom); - } - } -} - diff --git a/phpgwapi/js/egw_action/test/grid.css b/phpgwapi/js/egw_action/test/grid.css deleted file mode 100644 index a3ef7a54b7..0000000000 --- a/phpgwapi/js/egw_action/test/grid.css +++ /dev/null @@ -1,229 +0,0 @@ -body { - margin: 0; - padding: 0; -} - -body, td, th { - font-family: Verdana,Arial,Helvetica,sans-serif; - font-size: 11px; -} - -.egwGridView_grid { - table-layout: fixed; - border-spacing: 0; - border-collapse: collapse; -} - -.egwGridView_outer div.innerContainer.queued { - background-image: url(imgs/ajax-loader.gif); - background-position: center; - background-repeat: no-repeat; - height: 19px; -} - -.egwGridView_grid tr.focused td { - background-image: url(imgs/focused_hatching.png); - background-repeat: repeat; -} - -.egwGridView_grid tr.selected td { - background-color: #b7c3ff; -} - -.egwGridView_grid tr.draggedOver td { - background-color: #ffd09c !important; -} - -/*.egwGridView_grid tr.selected.odd td { - background-color: #9dadff; -}*/ - -.egwGridView_scrollarea { - width: 100%; - overflow: auto; -} - -.egwGridView_spacer { - background-image: url(imgs/non_loaded_bg.png); - background-position: top left; -} - -.egwGridView_outer { - table-layout: fixed; - border-spacing: 0; - border-collapse: collapse; - padding: 0; - margin: 5px; -} - -.egwGridView_outer td, .egwGridView_outer tr { - padding: 0; - margin: 0; -} - -.egwGridView_grid td { - border-right: 1px solid silver; - border-bottom: 1px solid #e0e0e0; - padding: 2px 3px 2px 4px; - margin: 0; -} - -.egwGridView_outer th div.innerContainer, -.egwGridView_grid td div.innerContainer { - margin: 0; - padding: 0; - display: block; - overflow: hidden; -} - -.egwGridView_grid tr.fullRow { - font-style: italic; -} - -.egwGridView_grid tr.row:hover { - background-color: #f0f0ff; -} - -.egwGridView_grid tr { - padding: 2px 3px 2px 4px; - margin: 0; -} - -.egwGridView_grid tr.hidden { - display: none; -} - -/*.egwGridView_grid tr.odd { - background-color: #F1F1F1; -}*/ - -.egwGridView_grid span.indentation { - display: inline-block; -} - -.egwGridView_grid span { - vertical-align: middle; -} - -.egwGridView_grid img.icon { - vertical-align: middle; - margin: 2px 5px 2px 2px; - -moz-user-select: none; - -khtml-user-select: none; - user-select: none; -} - -.egwGridView_grid span.arrow { - display: inline-block; - vertical-align: middle; - width: 8px; - height: 8px; - background-repeat: no-repeat; - margin-right: 2px; - -moz-user-select: none; - -khtml-user-select: none; - user-select: none; -} - -.egwGridView_grid span.arrow.opened { - cursor: pointer; - background-image: url(imgs/arrows.png); - background-position: -8px 0; -} - -.egwGridView_grid span.arrow.closed { - cursor: pointer; - background-image: url(imgs/arrows.png); - background-position: 0 0; -} - -.egwGridView_grid span.arrow.loading { - cursor: pointer; - background-image: url(imgs/ajax-loader.gif); - background-position: 0 0; -} - -.egwGridView_grid span.iconContainer { - display: inline-block; - padding: 0; - margin: 0; - text-align: center; -} - -.egwGridView_grid span.caption { - cursor: default; - -moz-user-select: none; - -khtml-user-select: none; - user-select: none; -} - -.egwGridView_outer thead th { - background-color: #E0E0E0; - font-weight: normal; - padding: 5px; - text-align: left; - border-left: 1px solid silver; - border-top: 1px solid silver; - border-right: 1px solid gray; - border-bottom: 1px solid gray; - background-image: url(imgs/header_overlay.png); - background-position: center; - background-repeat: repeat-x; -} - -.egwGridView_outer thead th:hover { - background-color: #F0F0F0; -} - -.egwGridView_outer thead th:active { - background-color: #D0D0D0; - border-left: 1px solid gray; - border-top: 1px solid gray; - border-right: 1px solid silver; - border-bottom: 1px solid silver; -} - - -.egwGridView_outer thead th.optcol { - padding: 0; - text-align: center; -} - -.selectcols { - display: inline-block; - width: 10px; - height: 9px; - margin: 0; - padding: 0; - vertical-align: middle; - background-image: url(imgs/selectcols.png); - background-position: center; - background-repeat: no-repeat; -} - -.egwGridView_grid td.frame, -.egwGridView_outer td.frame, -.egwGridView_grid td.egwGridView_spacer { - padding: 0 !important; - border-right: 0 none silver !important; - 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(imgs/up.png); -} - -.egwGridView_outer span.sort.desc { - background-image: url(imgs/down.png); -} - diff --git a/phpgwapi/js/egw_action/test/test_grid.html b/phpgwapi/js/egw_action/test/test_grid.html deleted file mode 100644 index c5c185b725..0000000000 --- a/phpgwapi/js/egw_action/test/test_grid.html +++ /dev/null @@ -1,199 +0,0 @@ - - - Grid Test - - - - - - - - - - - - - - - - - - - - - -
- - - diff --git a/phpgwapi/js/egw_action/test/test_grid_view.html b/phpgwapi/js/egw_action/test/test_grid_view.html deleted file mode 100644 index 45fdc1d5d4..0000000000 --- a/phpgwapi/js/egw_action/test/test_grid_view.html +++ /dev/null @@ -1,322 +0,0 @@ - - - - Grid Test - - - - - - - - - - - - - - - - - - - - - - - - - - -

Test for dynamically displaying and loading grid lines

- Simulates network trafic by using window.setTimeout(), 100ms network latency - - -
- - -