/*
Copyright (c) 2006 Author
Author: Anil Sharma for the book "Real-World AJAX: Secrets of the Masters"

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions
of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

function SimpleTable() {
   // list of columns
   this.columns = null;
   // the body element where data is shown
   this.tbody = null;
   // the actual table element
   this.tableElement = null;
   
   this.currentRow = -1;
   this.savedColor = new Array();
   this.dlist = null;
   this.cellSelectedListeners = new Array();
}

SimpleTable.prototype.setHtmlElement = function(e) {
    this.tableElement = e;
    var collection = new ElementCollection(e);
    var thead = collection.getFirstElement('THEAD');
    this.tbody = collection.getFirstElement('TBODY');
    if (thead == null) {
        alert("SimpleTable requires THEAD element inside TABLE element");
        return;
    }
    if (this.tbody == null) {
        alert("SimpleTable requires TBODY element inside TABLE element");
        return;
    }
    // makes a list of columns
    this.columns = new ElementCollection(thead).getElements('TH');
}

SimpleTable.prototype.setData = function(dlist) {
    this.dlist = dlist;
    // removes all nodes user the body element, cleans it up
    removeAll(this.tbody);
    
    this.currentRow = -1;
    
    // click handler is added to each cell
    var self = this;
    self.clickHandler = function(event) {self.cellClicked(event);};
    
    // for each object is the list creates a TR element
    for (var i=0; i<dlist.length; i++) {
        var row = dlist[i];
        // creates a TR element
        var tr = document.createElement('tr');
        // for each column, creates TD element
        for (j=0; j<this.columns.length; j++) {
        var col = this.columns[j];
        var td = document.createElement('td');
        // assign id that can give row, column of the cell
        td.id = "Cell_" + i + "_" + j;
        // set onclick handler for the cell
        td.onclick = self.clickHandler;
        // looks up value of the attribute with the same
        // name as the column id
        var v = row[col.id];
        if (v == null) {
            v = ' ';
        }
        var className = 'tdContent';
        // check if it is a special column, sets it style using
        // className 'tableCellRowHeader'
        if (col.id == '_rowHeader') {
            className = 'tableCellRowHeader';
            } else {
            if (j==0) {
                className = 'tdContent1st';
            }
        }
        // sets style of TD element
        td.className = className;
        // set the value of TD element
        td.appendChild(document.createTextNode(v));
        // add the TD to TR element
        tr.appendChild(td);
        }
        // add TR to body element
        this.tbody.appendChild(tr);
    }
}

// returns the data set used to set the value of
// table
SimpleTable.prototype.getData = function() {
    return this.dlist;
}

// returns the object corresponding to a
// given row
SimpleTable.prototype.getRowData = function(r) {
    if (this.dlist == null) {
        return null;
    }
    if (r < 0 && r>= dlist.length) {
        return null;
    }
    return this.dlist[r];
}

// cell clicked event handler
SimpleTable.prototype.cellClicked = function(event) {
    var ev = event ? event : window.event;
    var e = ev.srcElement ? ev.srcElement : ev.target;
    // retrieve cell id
    var cellId = e.id;
    // retrieve row and column
    var idx = cellId.indexOf("_");
    var idx2 = cellId.lastIndexOf("_");
    var row = parseInt(cellId.substring(idx+1, idx2));
    var col = parseInt(cellId.substring(idx2+1));
    // select the clicked row
    this.selectRow(row);
    // send message to its cell selected listener
    for (var i=0; i<this.cellSelectedListeners.length; i++) {
        this.cellSelectedListeners[i].cellSelected(row, col);
    }
}

// highlights the given row
SimpleTable.prototype.selectRow = function(row) {
    var tr;
    // reset the background of currently selected row
    if (this.currentRow != -1) {
        tr = this.tbody.rows[this.currentRow];
        for (var i=0; i<tr.cells.length; i++) {
			tr.cells[i].style.backgroundColor = this.savedColor[i];
        }
    }
    this.currentRow = row;
    this.savedColor.length = 0;
    // highlight the newly selected row
    // save the current background color before highlighting
    if (this.currentRow != -1) {
        tr = this.tbody.rows[this.currentRow];
        for (var i=0; i<tr.cells.length; i++) {
			this.savedColor.push(tr.cells[i].style.backgroundColor);
			tr.cells[i].style.backgroundColor = __selectionColor;
        }
    }
}

// adds a cell selected listener
// assumes that the passed listener defines cell selected method
SimpleTable.prototype.addCellSelectedListener = function(l) {
    if (l.cellSelected == null) {
        alert("The given listener should implement cellSelected(r, c) method");
        return;
    }
    this.cellSelectedListeners.push(l);
}

// this method is called when the value of an object's
// attribute changes.
// If the given, object is found in this table's dataset
// then the value of the cell corresponding to the
// changed attribute is updated.
SimpleTable.prototype.processValueChange = function(data, name, value) {
    if (this.dlist == null) {
        return;
    }
    
    for (var i=0; i<this.dlist.length; i++) {
        if (this.dlist[i] == data) {
			// given object is present in my dataset
			for (j=0; j<this.columns.length; j++) {
				var col = this.columns[j];
				if (col.id == name) {
					// column matches the given attribute name
					var tr = this.tbody.rows[i];
					var td = tr.cells[j];
					removeAll(td);
					// update value of the cell.
					td.appendChild(document.createTextNode(value));
					break;
				}
			}
			break;
        }
    }
}
