jsm

net/sf/jsm/table/jsmTable.js

Summary

No overview generated for 'net/sf/jsm/table/jsmTable.js'


Class Summary
JsmTable Represents a table

/**
 * Creates a new JsmTable object
 * @extends JsmObject
 * @class Represents a table
 * @constructor
 * @param {String} containerId Optional: The id of the element holding the table; If not specified the default value is 'myTableContainer'
 * @param {String} variableName Optional: The name of the variable holding this JsmTable object; If not specified the default value is 'myTable'
 * @param {boolean} resizable Optional: Indicates if the table should be resizable; default is false 
 */ 
  function JsmTable(containerId, variableName, resizable) { 
  	/** @ignore */
  	this.id=new Date().getTime() + "" + Math.random();
  	logger.info("Created JsmTable with id: " + this.id);
  	/** @ignore */  	
  	this._attributes=new Array(); 
  	/** The id of the element holding the table; Defaults to 'myTableContainer' 
  	* @type String
  	*/ 	 	
  	this.containerId = (jsm.noud(containerId))?"myTableContainer":containerId;
  	/** The name of the variable holding this JsmTable object; Defaults to 'myTable' 
  	* @type String
  	*/ 	   		 	
  	this.variableName = (jsm.noud(variableName))?"myTable":variableName;
  	/** Is the table resizable; defaults to false 
  	* @private
  	* @type boolean
  	*/ 	   	
  	this._resizable = (jsm.noud(resizable))?false:resizable;  	
  	/** Array holding {@link JsmTh} objects; can be null 
  	* @private
  	* @type Array
  	*/   	 	 	  	  	
  	this._headerRow = null;
  	/** Array holding the data rows ({@link JsmTr} objects); 
  	* @private
  	* @type Array
  	*/  	 	  	  	
  	this._rows = new Array();
  	/** Array holding the footer rows ({@link JsmTr} objects); 
  	* @private
  	* @type Array
  	*/  	 	  	  	
  	this._footer = new Array(); 
  	/** Defines if the actions cells should be displayed on the left or right side of the table; Default is 'right'
  	* @private
  	* @type String
  	*/   	
	this._actionCellSide='right';
  	/** Array holding {@link JsmActionCell} objects to display in the header row; 
  	* @private
  	* @type Array
  	*/   	
  	this._headerActionCells = new Array(); 
  	/** Array holding {@link JsmActionCell} objects to display in the footer row; 
  	* @private
  	* @type Array
  	*/   	
  	this._footerActionCells = new Array();   	
  	/** Array holding {@link JsmActionCell} objects to display in the data rows 
  	* @private
  	* @type Array
  	*/    	 	
  	this._rowActionCells = new Array();
  	/** Array holding Filter, eg. {@link JsmRegExFilter}, {@link JsmExactFilter}; 
  	* @private
  	* @type Array
  	*/    	  	  	
  	this._filters = new Array();
  	/** Array holding FilterGenerationConfigurations for filters generated by {@link #generateFilter} 
  	* The value of the array is again an array with the 0th element being the widget and the 1st element being the filter
  	* @private
  	* @type Array
  	*/     	
  	this._columnIdx2FilterGenerationConfig = new Array();
  	/** Mapping column name to column idx
  	* @private
  	* @type Hash
  	*/      	
  	this._columnName2ColumnIdx = new Array();
  	/** Mapping column idx to column name
  	* @private
  	* @type Hash
  	*/     	
  	this._columnIdx2ColumnName = new Array();
  	/** Mapping column idx to widget
  	* @private
  	* @type Hash
  	*/     	
  	this._columnIdx2Widget = new Array();
	/** Mapping column idx to property paths to store cell values back into JavaBeans  	
  	* @private
  	* @type Hash
  	*/      	
  	this._columnIdx2PropertyPath = new Array();  	
	/** Mapping column idx to comparator functions	
  	* @private
  	* @type Hash
  	*/      	
  	this._columnIdx2Comparator = new Array();    	
  	this._attributes['border']=0; //default value for border
  	this._attributes['cellSpacing']=0; //default value for cellspacing
  	this._attributes['cellPadding']=0; //default value for cellpadding
  	/** the column idx by which the table is currently sorted; defaults to 0
  	* @private
  	* @type int
  	*/    	
  	this._sortColumn=0;
  	/** The tables sorting order: ascending or descending;
  	* Values are 'asc' or 'desc'
  	* @private 
  	*/    	 	
  	this._sortOrder='desc';
  	/** counter used during the getNode()-Iteration
  	* @ignore 
  	*/    	
  	this._nodeIterationCounter = 0;
  	/** If set to true only the table header will be shown
  	* @private
  	* @type boolean
  	*/
  	this._showOnlyHeader=false;
  	/** The amount of rows to show when paging; defaults to -1
  	* @private
  	* @type int
  	*/
  	this._pageingMaxRows=-1;  	
  	/** The current start row when paging; defaults to 0
  	* @private
  	* @type int
  	*/
  	this._pageingCurrentStartRow=0; 	  	
  	/** The message to show if there are no rows to display; default: There are currently no rows to display
  	* @private
  	* @type String
  	*/
  	this._noRowsToDisplayMessage="There are currently no rows to display";
  	/** Indicates that at least one row of this table is dirty
  	* @type boolean
  	* @private
  	*/     	
  	this._dirty=false;  	
  }
  JsmTable.extendClass(JsmObject);
  /** @ignore */
  JsmTable.prototype.className="JsmTable";
  
  /** @ignore */
  JsmTable.prototype.toString = function() {
  	var retVal = "[JsmTable object: id=" + this.id + " rowCount=" + this._rows.length + "]\n";
  	if (!jsm.noud(this._headerRow)) {retVal=retVal+this._headerRow;}
  	for (var trIdx=0;trIdx<this._rows.length;trIdx++) {
  		retVal=retVal+this._rows[trIdx];	
  	}
  	return retVal;  	
  }
  
  /** Set the name of the variable holding this JsmTable object
  * @param {String} variableName
  * @return this
  */      
  JsmTable.prototype.setVariableName = function(variableName) {
  	this.variableName = variableName;
  	return this;  	
  }
  
  /** Set the name of the variable holding this JsmTable object
  * @return {String} variableName
  */      
  JsmTable.prototype.getVariableName = function() {
  	return this.variableName;
  }  

  	/** Set the id of the container displaying the table
  	* @param {String} containerId
  	* @return this
  	*/      
  JsmTable.prototype.setContainerId = function(containerId) {
  	this.containerId = containerId;
  	return this;  	
  } 
  
  	/** Get the id of the container displaying the table
  	* @return {String} containerId
  	*/      
  JsmTable.prototype.getContainerId = function() {
  	return this.containerId;
  }
  
  	/** The message to display if there are no rows to diplay
  	* @param {String} noRowsToDisplayMessage
  	* @return this
  	*/      
  JsmTable.prototype.setNoRowsToDisplayMessage = function(noRowsToDisplayMessage) {
  	this._noRowsToDisplayMessage = noRowsToDisplayMessage;
  	return this;  	
  }          
  
  	/** Determin if only the header should be shown
  	* @param {boolean} showOnlyHeader
  	* @return this
  	*/      
  JsmTable.prototype.setShowOnlyHeader = function(showOnlyHeader) {
  	this._showOnlyHeader = showOnlyHeader;
  	return this;  	
  }  
  
  	/** Should only the header be shown
  	* @return {boolean}
  	*/      
  JsmTable.prototype.isShowOnlyHeader = function() {
  	return this._showOnlyHeader;  	
  }  
      
  /** Set the sorting column
  * @param {String/int} sortColumn The column index (the index is zero based) or the column name
  * @return this
  */      
  JsmTable.prototype.setSortColumn = function(sortColumn) {
  	this._sortColumn = sortColumn;
  	return this;
  } 
  
  /**
  * @return {int} The index of the column currently sorted
  */      
  JsmTable.prototype.getSortColumn = function() {
  	return this._sortColumn;
  } 
  
  /** Set the sorting order
  * @param {String} sortOrder 'asc' or 'desc'
  * @return this
  */      
  JsmTable.prototype.setSortOrder = function(sortOrder) {
  	if (sortOrder != 'asc' && sortOrder !='desc') {sortOrder='asc';}
  	this._sortOrder = sortOrder;
  	return this;
  } 
  
  /**
  * @return {int} The tables sorting order
  */      
  JsmTable.prototype.getSortOrder = function() {
  	return this._sortOrder;
  }      
  
  /** Adds a filter; 
  * @param filter
  * @return this
  */        
  JsmTable.prototype.addFilter = function(filter) {
  	this.setPageingCurrentStartRow(0);
  	this._filters.push(filter);
  	return this;
  }
  
  /** Get all associated filters
  * @return {Array}
  */        
  JsmTable.prototype.getFilters = function() {
  	return this._filters;
  }  

  /** Remove all associated filters 
  * @return this
  */      
  JsmTable.prototype.removeFilters = function() {
	this.setPageingCurrentStartRow(0);  
  	this._filters = new Array();
  	return this;
  }
  
  /** Add the name for a column so that they do not have to be refered to be idx 
  * @param {String} columnName
  * @param {int} columnIdx  
  * @return this
  */        
  JsmTable.prototype.addColumnName = function(columnName, columnIdx) {
  	this._columnIdx2ColumnName[columnIdx]=columnName; 
  	this._columnName2ColumnIdx[columnName]=columnIdx;
  	return this;
  } 
  
  /** Get column name by column idx
  * @param {int} columnIdx  
  * @return {String} Name of the column or null if not specified
  */      
  JsmTable.prototype.getColumnName = function(columnIdx) {
	return this._columnIdx2ColumnName[columnIdx];
  } 
  
  /** Get column idx by column name
  * @param {String} columnName
  * @return {int} Index of column
  */    
  JsmTable.prototype.getColumnIdx = function(columnName) {
	return jsm.noud(this._columnName2ColumnIdx[columnName])?null:this._columnName2ColumnIdx[columnName];
  }      
  
  /** Add a widget to a column; This will be used for editing all cells of this column
  * @param {int || String} columnIdxOrName
  * @param widget  
  * @return this
  */    
  JsmTable.prototype.addWidget = function(columnIdxOrName, widget) { 
	var columnIdx = isNaN(columnIdxOrName)?this.getColumnIdx(columnIdxOrName):columnIdxOrName;
  	this._columnIdx2Widget[columnIdx]=widget; 	
  	return this;
  }  
  
  /** Get the widget of a column
  * @param {int || String} columnIdxOrName  
  * @return the widget or null if not specified
  */    
  JsmTable.prototype.getWidget = function(columnIdxOrName) {
	var columnIdx = isNaN(columnIdxOrName)?this.getColumnIdx(columnIdxOrName):columnIdxOrName;  
  	return this._columnIdx2Widget[columnIdx]; 	  	
  } 
  
  /** Add filter configuration for {@link #generateFilter} to a column; If already widgets for editing
  * are set it is optional to set them via this method. The ones set by {@link #addWidget} would be used 
  * together with a {@JsmRegExFilter}
  * @param {int / String} columnIdxOrName  
  * @param widget The widget to display as a filter 
  * @param filter 
  * @return this
  */    
  JsmTable.prototype.addFilterConfig = function(columnIdxOrName, widget, filter) {
  	var columnIdx = isNaN(columnIdxOrName)?this.getColumnIdx(columnIdxOrName):columnIdxOrName;
  	this._columnIdx2FilterGenerationConfig[columnIdx]=[widget, filter]; 	
  	return this;
  }  
  
  /** Get the filter configuration for a column
  * @param {int} columnIdx  
  * @return {Array} The filter configuration. 0th element is the widget object, 1st element is the filter object.
  * Will return a configuration based upon the widget specified via {@link addWidget} 
  * if no filter configuration was specified using {#addFilterConfig}
  */    
  JsmTable.prototype.getFilterConfig = function(columnIdx) {
  	var filterConfig = this._columnIdx2FilterGenerationConfig[columnIdx];
  	if (jsm.noud(filterConfig)) {filterConfig = [this.getWidget(columnIdx)];}
  	if (jsm.noud(filterConfig[1])) {filterConfig[1]=new JsmRegExFilter().setIgnoreCase(true);}
  	return filterConfig; 	
  } 
  
  /** Set the property path for this column to set a cells value back on the JavaBean
  * @param {int / String} columnIdxOrName  
  * @param propertyPath {String} The propertyPath to set the cell value back on the JavaBean 
  * @return this
  */    
  JsmTable.prototype.addPropertyPath = function(columnIdxOrName, propertyPath) {
  	var columnIdx = isNaN(columnIdxOrName)?this.getColumnIdx(columnIdxOrName):columnIdxOrName;
  	this._columnIdx2PropertyPath[columnIdx]=propertyPath; 	
  	return this;
  }  
  
  /** Get the property path for this column to set a cells value back on the JavaBean
  * @param {int} columnIdx  
  * @return {String} The propertyPath to set the cell value back on the JavaBean
  */    
  JsmTable.prototype.getPropertyPath = function(columnIdx) {
  	return this._columnIdx2PropertyPath[columnIdx];
  }
 
  /** Set the comparator function for this column
  * @param {int / String} columnIdxOrName  
  * @param comparator {Function} A comparator function
  * @return this
  */    
  JsmTable.prototype.addComparator = function(columnIdxOrName, comparator) {
  	var columnIdx = isNaN(columnIdxOrName)?this.getColumnIdx(columnIdxOrName):columnIdxOrName;
  	this._columnIdx2Comparator[columnIdx]=comparator; 	
  	return this;
  }  
  
  /** Get the comparator function for this column
  * @param {int} columnIdx  
  * @return {Function} A comparator function; The default is JsmAlphaComparator if no comparator was specified
  */    
  JsmTable.prototype.getComparator = function(columnIdx) {
  	var retVal = this._columnIdx2Comparator[columnIdx];
  	return (jsm.noud(retVal)?JsmAlphaComparator:retVal);
  }  
  
  /** Get the value for the specified cell
  * @param {int} trIdx The row index  
  * @param {int} tdIdx The column index  
  * @return The value or null if not defined
  */    
  JsmTable.prototype.getValue = function(trIdx, tdIdx) {
   	try { 
	  	return this._rows[trIdx]._cells[tdIdx].value;
  	} catch (e) {logger.error("Can not getValue: " + trIdx + " - " + tdIdx + " - " + value); return "";}  	
  }  
  
  /** Set the value for the specified cell
  * @param {int} trIdx The row index  
  * @param {int} tdIdx The column index  
  * @param {String} value Can contain HTML tags
  * @return this
  */    
  JsmTable.prototype.setValue = function(trIdx, tdIdx, value) {
	try { 
  		this._rows[trIdx]._cells[tdIdx].value = value;
  	} catch (e) {logger.error("Can not setValue: " + trIdx + " - " + tdIdx + " - " + value);}
  	return this;
  } 
  
  /** Get the {@link JsmTr} object
  * @param {int} trIdx The row index  
  * @return {JsmTr}
  */    
  JsmTable.prototype.getTr = function(trIdx) {
  	return this._rows[trIdx];
  }     
  
  /** Get the {@link JsmTd} object
  * @param {int} trIdx The row index  
  * @param {int} tdIdx The column index    
  * @return {JsmTd} null if not found
  */    
  JsmTable.prototype.getTd = function(trIdx, tdIdx) {
	try {
	  	return this._rows[trIdx]._cells[tdIdx];
  	} catch (e) {logger.error("Can not getTd: " + trIdx + " - " + tdIdx); return null;}	  	
  } 
  
  /** Get the {@link JsmTd} objects of this row
  * @param {int} trIdx The row index  
  * @return {Array} null if not found
  */   
  JsmTable.prototype.getTds = function(trIdx) {
  	try {
	  	return this._rows[trIdx]._cells;
  	} catch (e) {logger.error("Can not getTds: " + trIdx); return null;}	  	
  }  
  
  /** Get the {@link JsmTr} object; same as getTr
  * @param {int} trIdx The row index  
  * @return {JsmTr}
  */ 
  JsmTable.prototype.getRow = function(trIdx) {
  	return this.getTr(trIdx);
  }       
  
  /** Get the data {@link JsmTr} rows;
  * @return {Array}
  */ 
  JsmTable.prototype.getRows = function() {
  	return this._rows;
  } 
  
  /** Get the number of data {@link JsmTr} rows;
  * @return {int}
  */ 
  JsmTable.prototype.getRowCount = function() {
  	return this._rows.length;
  }   
  
  /** Get the filtered data {@link JsmTr} rows;
  * @return {Array}
  */ 
  JsmTable.prototype.getFilteredRows = function() {
  		var retVal = [];
  		for (var trIdx=0;trIdx<this._rows.length;trIdx++) {
			var passedFilter = true;
	 		var row = this._rows[trIdx];
	  		for (var filter=0;filter<this.getFilters().length;filter++) {  
	  			passedFilter = this.getFilters()[filter].isValidRow(row);
	  			if (!passedFilter) break;
	  		}  		
			if (passedFilter) {
				retVal.push(row);			
			}  
		}
		return retVal;
  }     
  
  /** Get the footer {@link JsmTr} objects;
  * @return {Array}
  */ 
  JsmTable.prototype.getFooter = function() {
  	return this._footer;
  }   
  
  /** Get the  header row
  * @return {JsmTr} null if not set
  */ 
  JsmTable.prototype.getHeaderRow = function() {
  	return this._headerRow;
  }              
    
  /** Set the header row; Sets the rows meta data 'jsmRowType' to 'header'.
  * Will also set the value of the {@link JsmTh} objects as column names if not already specified by {@link #addColumnName}
  * @param {JsmTr} tr The row holding the {@link JsmTh} objects  
  * @return this
  */     
  JsmTable.prototype.setHeaderRow = function(tr) {
  	logger.debug("Add header row. Cell count: " + tr.getCells().length);
  	this._headerRow = tr;
  	tr.table = this;
  	tr.setMetaData('jsmRowType', 'header');
  	//add th-values as cell column names if not already set
  	for(var i = 0; i < tr.getCells().length; i++) {
  		if (jsm.noud(this.getColumnName(i)) && !jsm.noud(tr.getCells()[i].getValue())) {
  			logger.debug("Add column name: " + tr.getCells()[i].getValue() + " to column: " + i);
  			this.addColumnName(tr.getCells()[i].getValue(), i);
  		}
  	}  	
  	return this;
  }  
  
  /** Add a row to this table 
  * @param {JsmTr} tr The row holding the {@link JsmTd} objects  
  * @param {boolean} renderImmediately True if the added row should be rendered immediately
  * @return this
  */    
  JsmTable.prototype.addRow = function(tr, renderImmediately) {
  	this._rows.push(tr);
  	tr.table = this;
  	tr.idx=this._rows.length-1;
  	if (renderImmediately) {
//TODO problem wenn footer vorhanden ist
		var theTable = $(this.id);
		if (!jsm.noud(theTable)) {
			var tbody = theTable.getElementsByTagName('tbody')[0];
			var specialClassName='jsmEven';
			if(!jsm.noud(tbody.lastChild) && !jsm.noud(tbody.lastChild.className)) {
				if (tbody.lastChild.className.indexOf('jsmEven')!=-1) {specialClassName='jsmOdd';}
			}
			tbody.appendChild(tr.getNode(specialClassName));
		}
  	}
  	return this;
  }
  
  /** Add rows to this table 
  * @param {Array } trs Array of {@link JsmTd} objects  
  * @param {boolean} renderImmediately True if the added rows should be rendered immediately  
  * @return this
  */    
  JsmTable.prototype.addRows = function(trs, renderImmediately) {
  	for (var rowIdx=0;rowIdx<trs.length;rowIdx++) {
  		this.addRow(trs[rowIdx], renderImmediately);
  	}
  	return this;
  }  
  
  /** Remove a row from this table 
  * @param {int} idx The row index
  * @return this
  */     
  JsmTable.prototype.removeRow = function(idx) {
  	logger.debug("JsmTable: removeRow: at " + idx);  	  	
  	this._rows.splice(idx, 1);
  	this._updateRowIndex();		 	
  }
  
  /** Add a footer row to this table; Sets the rows meta data 'jsmRowType' to 'footer'.
  * @param {JsmTr} tr The row holding the {@link JsmTd} objects  
  * @return this
  */    
  JsmTable.prototype.addFooter = function(tr) {    
  	this._footer.push(tr);
  	tr.table = this;
  	tr.setMetaData('jsmRowType', 'footer');	
  	return this;
  }  
  
  /** Defines if the actions cells should be displayed on the left or right side of the table
  * @param {String} leftOrRight Set to 'left' or 'right'
  * @return this
  */    
  JsmTable.prototype.setActionCellSide = function(leftOrRight) {
    this._actionCellSide=leftOrRight;  
  	return this;  
  } 
  
  /** Returns the side on which the action cells should be displayed
  * @return {String} 
  */    
  JsmTable.prototype.getActionCellSide = function() {
    return this._actionCellSide;  
  }   
  
  /** Add a global action Td; will be displayed in the header row
  * @param {JsmActionCell} theActionCell
  * @return this
  */    
  JsmTable.prototype.addHeaderActionCell = function(theActionCell) {
    this._headerActionCells.push(theActionCell);  
  	return this;  
  }
  
  /** Add a global action Td; will be displayed in the footer row
  * @param {JsmActionCell} theActionCell
  * @return this
  */    
  JsmTable.prototype.addFooterActionCell = function(theActionCell) {
    this._footerActionCells.push(theActionCell);  
  	return this;  
  }  

  /** Add a row action Td; will be displayed on side of each row
  * @param {JsmActionCell} theActionCell
  * @return this
  */    
  JsmTable.prototype.addRowActionCell = function(theActionCell) {
  	this._rowActionCells.push(theActionCell);  	 
  	return this;  
  }   	  	    
  
  /** Sets the max number of rows to show
  * @param {int} pageingMaxRows
  * @return this
  */
  JsmTable.prototype.setPageingMaxRows = function(pageingMaxRows) {
  	this._pageingMaxRows=pageingMaxRows;  
	return this;
  }   
  
  /** Gets the max number of rows to show
  * @return {int}
  */
  JsmTable.prototype.getPageingMaxRows = function() {
	return this._pageingMaxRows;
  }    
   
  /** Sets the current start row for paging
  * @param {int} pageingCurrentStartRow Zero based
  * @return this
  */
  JsmTable.prototype.setPageingCurrentStartRow = function(pageingCurrentStartRow) {
  	this._pageingCurrentStartRow=pageingCurrentStartRow;  
	return this;
  }   
  
  /** Gets the current start row for paging
  * @return {int}
  */
  JsmTable.prototype.getPageingCurrentStartRow = function() {
	return this._pageingCurrentStartRow;
  }  	  	

  /** Render this table into the container
  * @return this
  */  
  JsmTable.prototype.render = function() {
  	var theContainer = document.getElementById(this.containerId)
 	if (jsm.noud(theContainer)) {
		alert("Can not find container to hold table with id: " + this.containerId + " - make sure to define an html element with the appropriate id before calling the render() method.");
	  	return;
	}  	 		
	theContainer.innerHTML='';	 
	theContainer.appendChild(this.getNode()); 
	window.setTimeout("jsmSelectWidgetNodes()", 10);//for IE: make sure all selected widgets are selected	
  }  
  
  /** Sort the rows
  * @param columnIdxOrName (Optional) Column index or name of the colum to sort;
  * if not specified will sort on the currently set {@see #_sortColumn}
  * @return this
  */ 
  JsmTable.prototype.sort = function(columnIdxOrName) {
	//determin the sort column idx 
  	var columnIdx;
  	if (isNaN(columnIdxOrName)) {
  		columnIdx = this.getColumnIdx(columnIdxOrName);
  	} else {
  		columnIdx = columnIdxOrName;
  	}  	
  	//if parameter columnIdxOrName was not specified - use last sort column
  	if (jsm.noud(columnIdx)) { 		
  		if (isNaN(this._sortColumn)) {
		  	this._sortColumn=this.getColumnIdx(this._sortColumn);		
  		}	
  		columnIdx=this._sortColumn;  		 		  	
  	}
  	//start sorting depending of the sorting order
  	if (this._sortColumn == columnIdx && this._sortOrder == 'asc') {		 	
  		this._rows.reverse(this.getComparator(this._sortColumn));
  		this._sortOrder = 'desc';
  	} else {
		this._sortColumn = columnIdx; //set the current sort column  	
  		this._rows.sort(this.getComparator(this._sortColumn));
  		this._sortOrder = 'asc';
  	}  	  	
  	
  	this._updateRowIndex();
	return this;
  } 
    
  /** Get the node object; the model (this) will be attached to the node as property 'model'
  * @return The created node object
  */  
  JsmTable.prototype.getNode = function() {
	  	var table = document.createElement("table");
	  	table.setAttribute("id", this.id);
	  	table.model=this;	
		this.addAttributesToViewComponent(table); 
	  	//add default class 'jsmTable'
	  	if (jsm.noud(this.getAttribute('className'))) {
			table.className='jsmTable';
	  	} else {
			table.className=this.getAttribute('className') + ' jsmTable';  	
	  	}  		  
	  	if (!jsm.noud(this._headerRow)) {
		  	var thead = document.createElement("thead");
		  	table.appendChild(thead);  	  	  		  	
	  		thead.appendChild(this._headerRow.getNode());
	  	}
	  	var tbody = document.createElement("tbody");
	  	table.appendChild(tbody); 
	  	if (!this.isShowOnlyHeader()) { 
		  	this._nodeIterationCounter=0;
		  	var passedFilterCounter=-1;	
		  	
		  	//data rows
		  	var filteredRows = this.getFilteredRows();
		  	jsmFilteredRowsCount = filteredRows.length;
		  	logger.debug("JsmTable.getNode: filteredRows# :" + jsmFilteredRowsCount);
		  	
		  	//show message noRowsToDisplayMessage
		  	if (jsmFilteredRowsCount == 0) {
		  		var messageTd = new JsmTd(this._noRowsToDisplayMessage).setAttribute('align', 'center');
		  		if (!jsm.noud(this.getHeaderRow()) && !jsm.noud(this.getHeaderRow().getCells())) {messageTd.setAttribute('colspan', this.getHeaderRow().getCells().length);}
		  		var messageTr = new JsmTr(messageTd);		  		
		  		messageTr.table = this;
		  		tbody.appendChild(messageTr.getNode());
		  	}		  	
		  	
		  	//add data rows
		  	for (var idx=0;idx<filteredRows.length;idx++) {		  		
		  		var row = filteredRows[idx];
				//if pageing is activated	
				if (this.getPageingMaxRows()) {
				  	logger.debug("JsmTable.getNode: pageing is activated: maxRows: " + this.getPageingMaxRows() + " current start row: " + this.getPageingCurrentStartRow());				
					//show only rows from the current start row onwards
					if (idx >= this.getPageingCurrentStartRow()) {
					  	logger.trace("JsmTable.getNode: add row from filteredRows: " + idx);									
			  			tbody.appendChild(row.getNode((this._nodeIterationCounter%2==0)?'jsmEven':'jsmOdd'));  														
						this._nodeIterationCounter++;			  			
					}
				} else {
		  			tbody.appendChild(row.getNode());  			
					this._nodeIterationCounter++;		  			
				} 	 	 			
				//restrict number of rows to show for pageing 
				if (this.getPageingMaxRows() != -1 && this.getPageingMaxRows()==this._nodeIterationCounter) {
					break;
				}	  		
		  	}
		  	//footer rows
			for (var trIdx=0;trIdx<this._footer.length;trIdx++) {
		  		tbody.appendChild(this._footer[trIdx].getNode());  			
		  	}		  	
		}
	  	//resize
	  	if (this._resizable) {
		  	table.onmousemove=_jsmOnMouseMoveEventDelegate;
		}  
	  	return table;
  }    

  /** Update the idx of the {@link JsmTr} objects
  * @private
  * @return this
  */ 
  JsmTable.prototype._updateRowIndex = function() {
    for (var trIdx=0;trIdx<this._rows.length;trIdx++) {
  		this._rows[trIdx].idx = trIdx;  		
  	}
  	return this;
  } 
  
  /** Determins if this column only hold numbers
  * @param {int} columnIdx The column index
  * @private
  * @return {boolean} True if the column holds only number values
  */   
  JsmTable.prototype._isNumberColumn = function(columnIdx) {  
	//todo optimize
	logger.debug("JsmTable: isNumberColumn: columnIdx: " + columnIdx);
  	for (var trIdx=0;trIdx<this._rows.length;trIdx++) {
		logger.debug("JsmTable: isNumberColumn: trIdx: " + trIdx + this._rows[trIdx] + this._rows[trIdx]._cells[columnIdx]);  	
		var row = this._rows[trIdx];
		if (jsm.noud(row)) {
			logger.error("JsmTable: isNumberColumn: row is null");
			return false;
		}
		var cell = row._cells[columnIdx];
		if (jsm.noud(cell)) {
			logger.error("JsmTable: isNumberColumn: cell is null");
			return false;
		}		
  		var cellValue = this._rows[trIdx]._cells[columnIdx].value;
  		if (cellValue != '' && isNaN(cellValue)) {return false;}  		
  	}
  	return true;
  }  
  
  /** Clean up after a save, eg. remove edit mode from rows, remove JsmDoubleSelectFieldDiv
  * @return this
  */   
  JsmTable.prototype.cleanUpAfterSave = function() {
  	//if exists remove the JsmDoubleSelectFieldDiv 
  	var theDiv = $('JsmDoubleSelectFieldDiv');
  	if (!jsm.noud(theDiv)) {theDiv.parentNode.removeChild(theDiv);} 
  	this.unSetEditModeForAllRows();
  	return this;
  }   
  
  /** Calles _jsmOnSaveRow for each row in edit mode
  * @return this
  */   
  JsmTable.prototype.saveAllRowsInEditMode = function() {
  	//if exists remove the JsmDoubleSelectFieldDiv 
  	var theDiv = $('JsmDoubleSelectFieldDiv');
  	if (!jsm.noud(theDiv)) {theDiv.parentNode.removeChild(theDiv);} 
  	//save all rows   
  	for (var rowIndex=0;rowIndex<this.getRows().length;rowIndex++) {
  		if (this.getRow(rowIndex).isEditMode()) {
  			_jsmOnSaveRow(this, rowIndex, -1);
  		}
  	} 
  	return this;
  }    
  
  /** Sets the edit mode of every row to false
  * @return this
  */    
  JsmTable.prototype.unSetEditModeForAllRows = function() {  
  	for (var rowIndex=0;rowIndex<this.getRows().length;rowIndex++) {
  		this.getRow(rowIndex).setEditMode(false);
  	}
  	return this;
  }   
  
  /** Sets the focus on the first widget found
  * @return this
  */    
  JsmTable.prototype.focusOnFirstWidget = function() { 
  	if (this.getRow(1) && this.getRow(1).getCells()) {
  		var cellcount = this.getRow(1).getCells().length;
  	} 
  	for (i=0;i<cellcount;i++) {
  		var theWidget = this.getWidget(i);  		
  		if (!jsm.noud(theWidget)) {
  			//found a widget  		
  			var theElement = document.getElementById(theWidget.getId());    					
  			if (!jsm.noud(theElement)) {theElement.focus();} //found the node
  			break;
  		}
  	}  
  	return this;
  } 
  
  /** Generates filter
  * @param {String} filterContainerId The id of the HTML element holding the filter
  * @param {Array} filterColumnIdxs Array of column indices; For these columns a filter widget will be generated
  * @param {int} horizontalSize Optional: The number of filter widgets to display beside each other; defaults to 2
  * @return this
  */    
  JsmTable.prototype.generateFilter = function(filterContainerId, filterColumnIdxs, horizontalSize) { 
  	if (jsm.noud(horizontalSize)) {horizontalSize=2;}
  	logger.debug("generateFilter: filterContainerId: " + filterContainerId + " filterColumnIdxs: " + filterColumnIdxs + " horizontalSize: " + horizontalSize);
  	var myFilterTable = new JsmTable(filterContainerId, this.getVariableName() + "Filter").setAttribute("width", "100%");
  	//add widget rows
	var myFilterTr = null;
	var widgetCount = 0;  	
  	for (var i=0;i<filterColumnIdxs.length;i++) {
   		columnIdx=filterColumnIdxs[i]; 
   		var filterConfig = this.getFilterConfig(columnIdx);
  		var widget = filterConfig[0];
  		if (!jsm.noud(widget)) {			  
	  		if (widgetCount%horizontalSize == 0) {
			  	logger.debug("generateFilter: Add new Tr: widgetCount: " + widgetCount);	  		
		  		myFilterTr = new JsmTr();
				myFilterTable.addRow(myFilterTr);		  		
	  		}
  		    widget = widget.clone();
  			widget.setId("jsmFilter@" + this.getVariableName() + "@" + columnIdx);
  			widget.setAttribute('onkeyup', "if (!e) e=window.event; if(e.keyCode == 13) try {document.getElementById('jsmApplyFilterButton@" + this.getVariableName() + "').click();}catch(e){}");
  			widget.setAttribute('onchange', "try {document.getElementById('jsmApplyFilterButton@" + this.getVariableName() + "').click();}catch(e){}");  			 			  			
  			//label	  			  	
	  	  	myFilterTr.addCell(new JsmTd(this.getColumnName(columnIdx) + ":").setTitle(this.getColumnName(columnIdx)).setAttribute('class', 'jsmLabel'));
	  	  	//widget
			myFilterTr.addCell(new JsmTd(widget).setTitle(this.getColumnName(columnIdx)));
			widgetCount++;			
  		}  	  	
  	}
  	//fill up with empty tds
  	while (widgetCount%horizontalSize != 0) {
		logger.debug("generateFilter: Add empty tds to fill up filter widget row");	  		  	
	  	widgetCount++;
  		myFilterTr.addCell(new JsmTd(" "));
  		myFilterTr.addCell(new JsmTd(" "));  		
  	}
  	//add buttons
  	widgetCount = 1;
	myFilterTr = new JsmTr();   	
	myFilterTr.addCell(new JsmTd("<button class='jsmButton' onclick='jsm.jsmResetTableFilter(\"" + this.getVariableName() + "\")'>" + jsmButtonResetFilter + "</button> <button id='jsmApplyFilterButton@" + this.getVariableName() + "' class='jsmButton' onclick='jsm.jsmApplyTableFilter(\"" + this.getVariableName() + "\")'>" + jsmButtonApplyFilter + "</button>").setAttribute("colspan", horizontalSize*2).setAttribute('align', 'right').setTitle(" "));
	myFilterTable.addRow(myFilterTr);
  	myFilterTable.render();
  	return this;
  }  
  
  
  /** Sets the dirty flag; if set to false will propagate this to the child rows
  * @param {boolean} dirty
  * @return this
  */   
  JsmTable.prototype.setDirty = function(dirty) {
    logger.debug("Reset the dirty flag for table: " + this);  
  	this._dirty = dirty;
  	//propagate cleanness of table to rows
  	if (!dirty) { 
	  var rows = this.getRows();
	  for (var rowIdx=0;rowIdx<rows.length;rowIdx++) {
	  	var row = rows[rowIdx];
	  	row.setDirty(dirty, false);
	  } 
	}  
	return this; 
  }
  
  /** 
  * @return {boolean} Value of the dirty flag
  */      
  JsmTable.prototype.isDirty = function() {
  	return this._dirty;
  }         
  

  

  

jsm

Documentation generated by JSDoc on Tue Sep 26 08:42:57 2006