/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Table.js -- Contains functions to dynamically create and sort a table.
TODO :
Complete decorator functions.

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

var ie5 = ( document.all && document.getElementById );
var moz = ( ! document.all && document.getElementById );
var tables =
{
}
;
var includes =
{
}
;

//////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////

// Move to main ? Or wait for eelib ?
function includes( scriptFilename )
{
    if( isNull( includes.scriptFilename ) )
    {
        var html_doc = document.getElementsByTagName( 'head' ).item( 0 );
        var js = document.createElement( 'script' );
        js.setAttribute( 'language', 'javascript' );
        js.setAttribute( 'type', 'text/javascript' );
        js.setAttribute( 'src', script_filename );
        html_doc.appendChild( js );
        includes.scriptFilename = scriptFilename;
    }
    return false;
}

function eSymbol(id, url, type, alt)
{
    this.id = id;
    this.url = url;
    this.type = type;
    this.alt = alt;
}

function eTableMetaItem( cname, val, group, type, index, display, decorator )
{
    this.colName = cname;
    this.value = val;
    this.groupNumber = group;
    this.colIndex = index;
    this.display = true;
    this.type = type;
    if( ! isNull( display ) )
    {
        this.display = display;
    }
    this.decorator = null;
    if( ! isNull( decorator ) )
    {
        this.decorator = decorator;
    }
    switch( this.value )
    {
        case "NAMED_TEXT.TEXT_ID" :
        //      case "NAMED_TEXT.VALUE" :
        case "CLASS.SYMBOL_ID" : // Hides CLASS.SYMBOL_ID used in a couple of places where
                                 // symbol handling is not completed.
        case "DISCUSSION.DISCUSSION_ID" :
        case "NAMED_TEXT.TYPE_ID" :
        case "STATUS.STATUS_ID" :
            {
                this.display = false;
                break;
            }
    }

    this.sortOrder = eTableModel.ASCENDING;
}

eTableMetaItem.prototype.dump = function()
{
    return this.value + ", " + this.groupNumber + ", " + this.colIndex + ", " + this.display+", "+this.colName;
}


/////////////////////////////////////////////////////////////////////////////
// Model NOTES :
// deprecate some unused fields -- types, names, hidden... moved to meta data.
// create a URL map to replace xxxUrl fields. Fill with default, and override by param
// Add decorator override to meta item.
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
// eTableModel
///////////////////////////////////////////////////////////////////////////////
var tableModelIndex = 0;

function eTableModel( name )
{
    this.name = name;
    this.data = [];
    this.meta = [];
    this.names = [];
    this.types = [];
    this.selectionList = [];
    this.singleSelect = false;
    this.selectorLabelMetaColumn = "";
    this.sortIndex = null;
    this.currentRow = -1;
    this.currentColumn = 0;
    this.size = 0;
    this.sortOrder = eTableModel.ASCENDING;
    this.defaultPageSize = null;
    this.maxHeight = - 1;
    this.diagramLayout = 1;
    this.urlMap =
    {
    }
    ;
    this.symbols =
    {
    }
    ;
    this.elementDetailUrl = "../request/elementForm?id=";
    this.elementEditUrl = "../request/elementForm?id=";
    this.elementNewUrl = "../request/elementForm?id=";
    this.classDetailUrl = "../request/classAction?id";
    this.filterUrl = "../request/filter?id=";
    this.folderUrl = "../request/folder?id=";
    this.filterEditUrl = "../request/filterEdit?qid="
    this.chartUrl = "../request/chart?sa=true&id=";
    this.reportUrl = "../request/page?id=";
    
    this.filterProperties = {
        "enabled":false,
        "term":"",
        "q":"",
        "column":0
    };
}

eTableModel.createFromSqlStatement = function( statement, id )
{
    var model = new eTableModel( id );
    model.data = statement.dataSet.data;
    model.meta = statement.dataSet.meta;
    model.names = statement.dataSet.names;
    model.types = statement.dataSet.types;
    model.size = model.data.length;
    return model;
}

eTableModel.jsonLoad = function( obj )
{
    var rval = new eTableModel( obj.id );
    rval.data = obj.data;
    rval.size = obj.data.length;
    rval.meta = obj.meta;
    rval.symbols = obj.symbols;
    rval.currentRow = obj.currentRow == 0 ? -1 : obj.currentRow;
    rval.defaultPageSize = obj.defaultPageSize;
    rval.maxHeight = obj.maxHeight;
    rval.urlMap = obj.urlMap;
    
    rval.elementDetailUrl = loadUrlHelper(rval.elementDetailUrl, obj.urlMap, "elementDetailUrl");
    rval.elementEditUrl = loadUrlHelper(rval.elementEditUrl, obj.urlMap, "elementEditUrl");
    rval.elementNewUrl = loadUrlHelper(rval.elementNewUrl, obj.urlMap, "elementNewUrl");
    rval.classDetailUrl = loadUrlHelper(rval.classDetailUrl, obj.urlMap, "classDetailUrl");
    rval.filterUrl = loadUrlHelper(rval.filterUrl, obj.urlMap, "filterUrl");
    rval.filterEditUrl = loadUrlHelper(rval.filterEditUrl, obj.urlMap, "filtereditUrl");        
    rval.folderUrl = loadUrlHelper(rval.folderUrl, obj.urlMap, "folderUrl");
    rval.chartUrl = loadUrlHelper(rval.chartUrl, obj.urlMap, "chartUrl");
    rval.reportUrl = loadUrlHelper(rval.reportUrl, obj.urlMap, "reportUrl");

    return rval;
}

function loadUrlHelper(modelUrl, urlMap, key)
{
    if( ! isNull( urlMap[key] ) )
    {
        modelUrl = urlMap[key];
    }
    return modelUrl;
}

// Better way to do this? Using with to intropspect?
eTableModel.prototype.clone = function()
{
    var m = new eTableModel( this.name );
    m.data = this.data;
    m.meta = this.meta;
    m.names = this.names;
    m.types = this.types;
    m.symbols = this.symbols;
    m.sortIndex = this.sortIndex;
    m.currentRow = this.currentRow;
    m.currentColumn = this.currentColumn;
    m.sortOrder = this.sortOrder;
    m.defaultPageSize = this.defaultPageSize;
    m.urlMap = this.urlMap;
    m.filter = this.filter;
    m.size = this.size;
    return m;
}

eTableModel.prototype.getSize = function()
{
    return this.data.length;
}

eTableModel.prototype.hasRow = function()
{
    return ( this.currentRow < this.data.length-1  ) ? true : false;
}

eTableModel.prototype.nextRow = function()
{
    ++this.currentRow;
    this.currentColumn = 0;
}

eTableModel.prototype.hasColumn = function()
{
    var me = this;
    while( ( me.currentColumn < me.meta.length ) && ( me.meta[me.currentColumn].display == false ) )
    {
        me.nextColumn();
    }
    if( isNull( me.data[0] ) )
    {
        return false;
    }
    if( me.currentColumn > me.data[0].length - 1 )
    {
        return false;
    }
    return true;
}

eTableModel.prototype.getColumnName = function( index )
{
    if( index >= 0 && index < this.meta.length )
    {
        return this.meta[index].colName;
    }
}

eTableModel.prototype.nextColumn = function()
{
    ++ this.currentColumn;
}


eTableModel.prototype.setDiagramLayout = function( val )
{
    if( ( val >= 0 ) && ( val <= 3 ) )
    {
        this.diagramLayout = val;
    }
}

eTableModel.prototype.addMeta = function( cname, value, group, type, index, display )
{
    if( isNull( group ) )
    {
        this.meta[this.meta.length] = new eTableMetaItem( cname, value, 0, type, this.meta.length, true );
    }
    else
    {
        var m = new eTableMetaItem( value, group, type, index, display );
        this.meta[this.meta.length] = m;
    }
}

eTableModel.prototype.addRow = function( row )
{
    this.data[this.data.length] = row;
}

eTableModel.prototype.getData = function( )
{
    if( this.currentRow > - 1 && this.currentRow < this.data.length )
    {
        var d = this.data[this.currentRow][this.currentColumn];
        if( this.meta[this.currentColumn].type == 91 )
        {
            // return d.getFullYear() + '/' + d.getMonth() + '/' + d.getDate() + ' - ' + d.getHours() + ':' + d.getMinutes();
            if( isNull(d) || d == "")
            {
                return "";
            }
            else
            {
                return d.toDateString() + " - " + d.toTimeString();
            }
        }
        if( ! isNull( d ) )
        {
            return d.toString();
        }
        else
        {
            return "";
        }
    }
    else
    {
        return "";
    }
}

eTableModel.prototype.getValueByPosition = function( pos )
{
    if( pos > 0  && pos < this.currentRow.length )
    {
        return this.data[this.currentRow][pos];
    }
}

eTableModel.prototype.getColumnIndexByMetaName = function( colName )
{
    var index = 0;
    Array.forEach(this.meta, function(item)
    {
        if(item.value == colName){ index = item.colIndex; }
    });
    return index - 1 ;
 }

eTableModel.prototype.lookupByMetaAndValue = function( knownValue, knownMeta, targetMeta )
{
    var knownIndex = this.getColumnIndexByMetaName(knownMeta);
    var targetIndex = this.getColumnIndexByMetaName(targetMeta);
    
    if( isNull(knownValue) || isNull(knownMeta) )
    {
        return{ "key":null, "value":null, "row":0 };
    }
    else
    {
        var targetRow;
        for( var i = 0; i < this.data.length; i++ )
        {
 //       console.log(i+", "+this.data[i][knownIndex]+", "+ knownValue);
            if( this.data[i][knownIndex] == knownValue ){ targetRow = this.data[i]; break; }
        }
            
        var val = "";
        if( !isNull(targetRow) && targetIndex < targetRow.length )
        {
            val = targetRow[targetIndex];
        }
        return{ "key":knownValue, "value":val, "row":i };
    }

} 

eTableModel.prototype.eidRegex =new RegExp( "(ELEMENT_ATTR_C[0-9]+|ELEMENT)\.ELEMENT_ID" );

eTableModel.prototype.getElementIdValueForGroup = function(metaItem)
{
    var me = this;
    var g = 0;
    try{g = metaItem.groupNumber;}catch( eat ){}
    
    for( var i = 0; i < me.meta.length; i ++ )
    {
        if( me.meta[i].groupNumber == g 
         && me.eidRegex.test(me.meta[i].value) 
         && ! isNull( me.data[me.currentRow] ) )
        {
            return me.data[me.currentRow][i];
        }
     }
}

eTableModel.prototype.getValueByMetaColumn = function( mval )
{
    var me = this;
    var g = 0;
    try{g = me.meta[me.currentColumn].groupNumber;}catch( eat ){}
    
    for( var i = 0; i < me.meta.length; i ++ )
    {
        if( me.meta[i].groupNumber == g && me.meta[i].value == mval && ! isNull( me.data[me.currentRow] ) )
        {
            return me.data[me.currentRow][i];
        }
    }
}

eTableModel.prototype.getMetaValue = function()
{
    return this.getCurrentMeta().value;
}

eTableModel.prototype.getCurrentMeta = function()
{
    return this.meta[this.currentColumn];
}

eTableModel.prototype.initialize = function()
{
    ee.dm( "entering eTableModel.initialize()" );
    var me = this;
    if( isNull(me.data) ){return;}
    if( me.size == "undefined" ){me.size = me.data.length;}
    if( me.getSize() == 0 ) {return;}
    if( me.currentRow < -1 )
    {
        me.resetCursor();
    }
    var hasClassName = false;
    var re = new RegExp( "ELEMENT_ATTR_C[0-9]+\.ELEMENT_ID" );
    var eidCount = 0;
    var hasElementDescription = false;
    Array.forEach( me.meta, function(item )
    {
        if( !isNull( item ) )
        {
            if( item.value == "CLASS.NAME" || item.value == "CLASS.PREFIX")
            { 
                me.hideColumn(item.groupNumber,"CLASS.CLASS_ID");    
            }
            
            if( item.value == "TYPE_DEFINITION.DISPLAY_NAME"){me.hideColumn(item.groupNumber,"NAMED_TEXT.TYPE_ID");}
            
            if( item.value == "ELEMENT.DESCRIPTION" )hasElementDescription = true;
        }
    });

    for( var k in me.meta )
    {
        var m = me.meta[k];
        if( !isNull( m ) )
        {
            if( ( m.value == "ELEMENT.ELEMENT_ID" ) && hasElementDescription && m.display == false )
            {
                for( var k2 in me.meta )
                {
                    var m2 = me.meta[k2];
                    if( m2.group == m.group && m2.value == "ELEMENT.DESCRIPTION" )
                    {
                        m2.combine = true;
                    }
                }
            }
            
        }
    }

    for( var i in me.meta )
    {
        var m = me.meta[i];
        if( !isNull( m ) )
        {
        	/*
            var cname = me.getColumnName( i );
            if( !isNull(cname) && cname.toUpperCase() == "ELEMENT_ID" )
            {
                ++ eidCount;
            }
            */
            var rep = new RegExp( "(ELEMENT_ATTR_C[0-9]+|ELEMENT)\.ELEMENT_ID" )
            var n = rep.exec(m.value);
            if( n != null )
            {
                ++eidCount;
            }
        }
    }
    
    if( eidCount == 1 )
    {
        var a = document.getElementById( me.name + "Graph" );
        if( a )
        {
            a.style.display = "inline";
        }
    }
    ee.dm( "leaving eTableModel.initialize()" );
}


eTableModel.prototype.hideColumn = function(group, metaName)
{
    Array.forEach(this.meta, function(item)
    {
        if( item && item.value == metaName &&
            item.groupNumber == group){ item.display = false; }
    });
}

eTableModel.prototype.sortOnColumn = function()
{
    var me = this;
    me.resetCursor();
    
    switch( me.meta[me.sortIndex].type )
    {
        case 12 :
        me.data.sort( function( a, b )
        {
            if( isNull( a[me.sortIndex] ) )
            {
                return - 1;
            }
            if( isNull( b[me.sortIndex] ) )
            {
                return 1;
            }
            var x = a[me.sortIndex].toLowerCase();
            var y = b[me.sortIndex].toLowerCase();
            return ( ( x < y ) ? - 1 : ( ( x > y ) ? 1 : 0 ) );
        }
        );
        break;
        case 2 :
        me.data.sort( function( a, b )
        {
            if( isNull( a[me.sortIndex] ) || a[me.sortIndex] == "")
            {
                return - 1;
            }
            if( isNull( b[me.sortIndex] ) || b[me.sortIndex] == "")
            {
                return 1;
            }
            var x = parseInt( a[me.sortIndex] );
            var y = parseInt( b[me.sortIndex] );
            return x - y;
        }
        );
        break;
        case 91 :
        me.data.sort( function( a, b )
        {
            if( isNull( a[me.sortIndex] ) || a[me.sortIndex] == "") 
            {
                return - 1;
            }
            if( isNull( b[me.sortIndex] ) || b[me.sortIndex] == "") 
            {
                return 1;
            }
            var x = a[me.sortIndex].getTime();
            var y = b[me.sortIndex].getTime();
            return x - y;
        }
        );
        break;
        default :
        me.data.sort( function( a, b )
        {
            if( isNull( a[me.sortIndex] ) )
            {
                return - 1;
            }
            if( isNull( b[me.sortIndex] ) )
            {
                return 1;
            }
            var x = a[me.sortIndex].toLowerCase();
            var y = b[me.sortIndex].toLowerCase();
            return ( ( x < y ) ? - 1 : ( ( x > y ) ? 1 : 0 ) );
        }
        );
    }
    var metaItem = me.meta[me.sortIndex];
    if( metaItem.sortOrder == eTableModel.DESCENDING )
    {
        me.data.reverse();
        metaItem.sortOrder = eTableModel.ASCENDING;
    }
    else
    {
        metaItem.sortOrder = eTableModel.DESCENDING;
    }
    
}

eTableModel.prototype.filter = function(column,value)
{
    var me = this;
    
    me.filterProperties.term = new RegExp(value, "i");
    me.filterProperties.column = column;
    me.filterProperties.enabled = true;
    me.filterProperties.q = value;

    me.resetCursor();
    var fp = me.filterProperties;
    if( fp.originalData )
    { 
        me.data = fp.originalData; 
    }
    else
    {
        fp.originalData = me.data;
    }
    
    var temp = [];
    var count = 0;
    for( var i = 0; i < me.data.length; i++ )
    {
        if(fp.term.test(me.data[i][fp.column]))
        {
            temp[temp.length] = me.data[i];
            ++count;
        }
    }
    me.data = temp;
    me.size = temp.length;
    
//ee.dm("matched = "+count);
}

eTableModel.prototype.clearFilter = function(column,value)
{
    this.filterProperties.term = null;
    this.filterProperties.column = 0;
    this.filterProperties.enabled = false;
    
    if( this.filterProperties.originalData )
    {
        this.data = this.filterProperties.originalData;
        this.filterProperties.originalData = null;
    }
    
    this.size = this.data.length;
    
    this.resetCursor();
    
}


eTableModel.prototype.setCursor = function( a )
{
    if( a > - 1 && a < this.getSize() )
    {
        this.currentRow = a;
        this.currentColumn = 0;
    }
}

eTableModel.prototype.incrementCursor = function( a )
{
    if( this.currentRow + a >= this.getSize() )
    {
        if( this.getSize() - a < 0 )
        {
            this.resetCursor();
        }
        else
        {
            this.currentRow = this.getSize() - a;
        }
    }
    else
    {
        this.currentRow += a;
    }
}

eTableModel.prototype.decrementCursor = function( a )
{
    if( this.currentRow - a < -1 )
    {
        this.currentRow = -1;
    }
    else
    {
        this.currentRow = this.currentRow - a;
    }
}

eTableModel.prototype.resetCursor = function( )
{
    var me = this;
    me.currentRow = -1;
    me.currentColumn = 0;
}

eTableModel.create = function( name )
{
    if( name == null )
    {
        return new eTableModel( 'tm_' + ( ++ tableModelIndex ) );
    }
    else
    {
        return new eTableModel( name );
    }
}

eTableModel.prototype.getSelectedValue  = function(index)
{
    if(isNull(index)){ index = 0; }
    return this.selectionList[index];
}


eTableModel.ASCENDING = 0;
eTableModel.DESCENDING = 1;

///////////////////////////////////////////////////////////////////////////////
// eTable
///////////////////////////////////////////////////////////////////////////////

function eTable( id, tableModel )
{
    this.id = id;
    this.model = tableModel;
    this.selectorColumn = null;
    this.displayMode = eTable.DETAIL_MODE;
    if( tableModel.defaultPageSize == null || tableModel.defaultPageSize == - 1 )
    {
        tableModel.defaultPageSize = tableModel.getSize();
    }

    this.decorator = new eDecorator();
    this.renderingCallbacks = [];
    this.model.initialize();
    this.decorator.updateFromModel( this.model );
}

eTable.DETAIL_MODE = 0;
eTable.DIAGRAM_MODE = 1;
eTable.ICON_MODE = 2;

eTable.prototype.renderTable = function()
{
    var me = this;
    
    if( this.model.maxHeight > 0 )
    {
        me.adjustTableHeight( );
    }
    me.createTableHead();
    me.createTableBody();
    callbacks( me );
}

eTable.prototype.getFilterId = function()
{
    var fparts = this.id.split( "_" );
    var filterId = fparts[fparts.length - 1];
    return filterId;
}

eTable.prototype.addRenderingCallback = function( callback )
{
    this.renderingCallbacks.push( callback );
}

eTable.prototype.setDecorator = function( meta, func )
{
    this.decorator.decoratorMa[meta] = func;
}

eTable.prototype.setPageSize = function( size )
{
    this.model.defaultPageSize = size;
}

eTable.prototype.getPageSize = function( )
{
    return this.model.defaultPageSize;
}

eTable.prototype.getPageCount = function()
{
    return this.model.length / this.model.defaultPageSize;
}

eTable.prototype.getRowCount = function()
{
    return this.model.getSize();
}
// ? ? ? ? ?
eTable.prototype.getCurrentPage = function()
{
    if( ( this.model.currentRow - this.model.defaultPageSize ) < 0 )
    {
        return 0;
    }
    else
    {
        return Math.ceil(( this.model.currentRow  ) / this.model.defaultPageSize);
    }
}

eTable.prototype.setCurrentPage = function( val )
{
    this.model.setCursor( ( val * this.model.defaultPageSize ) - this.model.defaultPageSize );
}

/* *
* showPageXXX functions depend on the current page being set first,
* then the renderTable function is called.
*/
eTable.prototype.showPage = function( val )
{
    var me = this;
    me.setCurrentPage( val );
    me.renderTable();
}

eTable.prototype.showFirstPage = function()
{
    var me = this;
    me.model.resetCursor();
    me.renderTable();
}

eTable.prototype.showLastPage = function()
{
    var me = this;
    me.model.setCursor( me.getRowCount() - me.model.defaultPageSize );
    me.renderTable();
}

eTable.prototype.showPreviousPage = function()
{
    var me = this;
    me.model.decrementCursor( Number(me.model.defaultPageSize) + Number(me.getHtmlRowCount()) );
    if( me.model.hasRow() )
    {
        me.renderTable();
    }
}

eTable.prototype.showNextPage = function()
{
    var me = this;
    if( me.model.hasRow() )
    {
        me.renderTable();
    }
}


// TODO: Check. This may be off by one when filtering.
eTable.prototype.getHtmlRowCount = function()
{
    if( ie5 )
    {
        // don't count the header row.
        return ee.ge( this.id ).rows.length - 1;
    }
    else
    {
        var tbody = document.getElementById( this.id + 'Body' );
        return tbody.getElementsByTagName( "tr" ).length;
    }
}

eTable.prototype.sort = function()
{
    var me = this;
    me.model.sortOnColumn();
    me.renderTable();
}



eTable.prototype.setSortColumn = function( index )
{
    this.model.sortIndex = index;
}

eTable.prototype.setDisplayMode = function( mode )
{
    if( mode == eTable.DETAIL_MODE || mode == eTable.ICON_MODE )
    {
        this.displayMode = mode
    }
}

eTable.editFilter = function( id )
{
    //ee.popAndRefresh( 'filterEditUrl' + id, 850, 600 )
    window.location.href = '../request/filterEdit?qid=' + id;
}

// executeSort exists solely to allow the actual table
// sorting and rendering to occur asynchronously.
function executeSort( id )
{
    var table = tables[id];
    table.sort();
    updateDisplay( table );
}
// Global event handler that kicks off the sort procedure.
function sortTableByColumn( col, id )
{
    var t = tables[id];
    t.setSortColumn( col );
    var sa = document.getElementById( id + 'message' );
    if( sa )
    {
        sa.innerHTML = "<span style=\"color : red; \">Sorting on " + t.model.names[col].toUpperCase() + " this may take some time.</span>";
    }
    setTimeout( 'executeSort("'+id+'")', 100 );
}

eTable.prototype.adjustTableHeight = function()
{
    var me = this;
    if( ie5 )
    {
        var tc = document.getElementById( me.id + 'tableDiv' );
        tc.style.height = me.model.maxHeight + "px";
        tc.style.overflow = "auto";
        tc.style.clear = "both";
        // Part one of two to move the scrollbar.
        tc.style.paddingRight = "17px";
    }
    else
    {
        var tb = document.getElementById( me.id + 'tableDiv'  );
        tb.style.maxHeight = me.model.maxHeight + "px";
        tb.style.overflow = "auto";
    }
}

eTable.prototype.adjustTableHeadHeight = function()
{
    if( ie5 )
    {
        var me = this;
        var thead = document.getElementById( me.id + 'Head' );
        var row = thead.rows[0];
        row.style.position = "relative";
        row.style.backgroundColor = "#f0e5e0";
        row.style.color = "#ffffff";
        row.style.width = "100%";
        var t = document.getElementById( me.id );
        if( t )
        {
            t.style.marginRight = "-18px";
        }
    }
}

eTable.prototype.clearTableHead = function()
{
    var thead = document.getElementById( this.id + 'Head' );
    // Remove any existing nodes.
    while( thead.childNodes.length > 0 )
    {
        thead.removeChild( thead.lastChild );
    }
}

eTable.prototype.createTableHead = function( )
{
    var me = this;
    var thead = document.getElementById( me.id + 'Head' );
//    me.createColumnGroups();
    // Remove any existing nodes.
    me.clearTableHead();
    // Icon mode does not use a header.
    if( me.displayMode == eTable.ICON_MODE ) return;
    
    var row = ee.ceAsChild( "tr", thead );
    row.id = me.id + "-th";
    if( me.model.maxHeight > 0 )
    {
        me.adjustTableHeadHeight();
    }
    if( ! isNull( me.selectorColumn ) )
    {
        var th = ee.ceAsChild( "th", row );
        th.scope = "col";
        th.innerHTML = "Select";
    }
    // Is this a valid data point for this?
    var mt = me.model.meta;
    for( var i = 0; i < mt.length; i ++ )
    {
        if( mt[i].display == false ) continue;

        var td = ee.ceAsChild( "th", row );
        td.scope = "col";
		/*if (i>0) {
			td.style.backgroundImage = 'url(../images/Data_Row_Header_Not_Top_Left_Corner.gif)';
		}*/
		var an = ee.ceAsChild( "a", td );
        an.setAttribute( "href", "javascript:sortTableByColumn(" + i + ",'"+me.id+"');" );
        an.innerHTML = mt[i].colName;
    }
    if(me.model.filterProperties.enabled == true)
    {
        me.showFilterBar();
    }
    me.setCountInControlBar(); 
	
	$("#"+row.id+" th:first").css("background-image", "url(../images/Data_Row_Header_Top_Left_Corner.gif)");
}

function getFilterIdFromTableId(tableid)
{
    var parts = tableid.split("_");
    return parts[parts.length-1];
}

eTable.prototype.createColumnGroups = function()
{

    var me = this;
    var table = document.getElementById( me.id );
    table.rules = "groups";
    Array.forEach( table.getElementsByTagName('COLGROUP'), function(item)
    {
        table.removeChild(item);
    });

    var max = 0;
    Array.forEach( me.model.meta, function(item)
    {
        if( item.groupNumber > max ){ max = item.groupNumber;}
    });
    var groups = new Array(max);
    Array.forEach( me.model.meta, function(item)
    {
        if(isNull(groups[item.groupNumber])){groups[item.groupNumber]=0;}
        if(item.display == true){groups[item.groupNumber] = groups[item.groupNumber] + 1;}
    });

    for( var i = 0; i < groups.length; i++ )
    {
        var cg = ee.ceAsChild("colgroup",table);
        if( groups[i] > 1 ){ cg.span = groups[i]; }
        cg.className = "colgroup"+i;
        if( i % 2 == 0 )
        {
            cg.className = "cgeven";
            }
            else{
            cg.className = "cgodd";
            }
    }
}

eTable.prototype.setCountInControlBar = function()
{
    var span = document.getElementById( "ts" + this.id );
    if( ! isNull( span ) )
    {
        while( span.childNodes.length > 0 )
        {
            span.removeChild( span.firstChild );
        }
     
        span.appendChild( document.createTextNode(" ["+this.model.data.length+" items]") );
    }
}

eTable.prototype.clearTableBody = function()
{
    var tbody = ee.ge( this.id + 'Body' );
    while( tbody.childNodes.length > 0 )
    {
        tbody.removeChild( tbody.lastChild );
    }
}

eTable.prototype.createTableBody = function( )
{
    var me = this;
    if( me.displayMode == eTable.ICON_MODE )
    {
        me.createIconTableBody();
        return;
    }

    me.clearTableBody();
    // Set up the dom objects.
    var tr;
    var td;
    var tabParent = ( ( document.createDocumentFragment ) ? ee.ge( me.id + 'Body' ) : ee.ge( me.id )  );
    if( document.createDocumentFragment )
    {
        var frag = document.createDocumentFragment();
        frag.name="frag";
        for( var i = 0; ( i < me.model.defaultPageSize && me.model.hasRow() );  i++ )
        {
            me.model.nextRow();
            tr = document.createElement("tr");
            if( ( i % 2 ) == 0 )
            {
                ( moz ) ? tr.setAttribute( "class", "even" ) : tr.setAttribute( "className", "even" );
            }
            else
            {
                ( moz ) ? tr.setAttribute( "class", "odd" ) : tr.setAttribute( "className", "odd" );
            }
            if( !isNull(me.selectorColumn) )
            {
                me.addSelectorColumn( tr );
            }
    
            while( me.model.hasColumn() )
            {
                td = document.createElement("td");
                var meta = me.model.getCurrentMeta();
                if( (meta.groupNumber % 2 != 0) &&  ( i % 2 ) != 0)
                {
                    td.setAttribute("class", "even-meta-col");
                }
                me.decorateColumn( td, me, meta );
                tr.appendChild(td);
                me.model.nextColumn();
            }
            frag.appendChild(tr);
        }
        tabParent.appendChild(frag);
    }
    else
    {
        // For browsers that don't support document.createDocumentFragment.
        for( var i = 0; ( i < me.model.defaultPageSize && me.model.hasRow() );  i++ )
        {
            me.model.nextRow();
            tr = ee.addRow( tabParent );
            if( ( i % 2 ) == 0 )
            {
                ( moz ) ? tr.setAttribute( "class", "even" ) : tr.setAttribute( "className", "even" );
            }
            else
            {
                ( moz ) ? tr.setAttribute( "class", "odd" ) : tr.setAttribute( "className", "odd" );
            }

            if( ! isNull( me.selectorColumn ) )
            {
                me.addSelectorColumn( tr );
            }
    
            while( me.model.hasColumn() )
            {
                td = ee.addCell( tr );
                var meta = me.model.getCurrentMeta();
                if( (meta.groupNumber % 2 != 0) &&  ( i % 2 ) != 0)
                {
                    td.setAttribute("class", "even-meta-col");
                }
                me.decorateColumn( td, me, meta );
                me.model.nextColumn();
            }
        }
    }

}

eTable.prototype.addSelectorColumn = function( tr )
{
    var me = this;
    var val = this.model.getValueByMetaColumn( this.selectorColumn );
    var textVal = this.model.getValueByMetaColumn( this.model.selectorLabelMetaColumn );
    if( val )
    {
        var td = document.createElement("td");
        tr.appendChild(td);
        var newCheck = document.createElement( 'input' );
        newCheck.type = 'checkbox';
        newCheck.name = 'ck-'+val;
        newCheck.id = 'ck-'+val;
        newCheck.value = val;
        td.appendChild( newCheck );
        if( me.model.singleSelect )
        {
            var ht = document.createElement('input');
            ht.type = 'hidden';
            ht.id = 'txt-'+val;
            ht.value = textVal;
            td.appendChild(ht);
            if( val == me.model.selectionList[0] ){ newCheck.checked = true; window.tableSelect = val; window.tableSelectText = textVal}
        }
//console.log( "id = %s, val = %s, checked = %s, sl = %s ", newCheck.id, newCheck.value, newCheck.checked, me.model.selectionList[0] );
        
        EventUtils.addEventHandler( newCheck, "click", function()
        {
            var target = EventUtils.getTargetElement();
            
                me.model.selectionList[0] = target.value;
                window.tableSelect = target.value;
                var tid = target.id.split('-');
                var txtid = 'txt-'+tid[1];
//         console.log(txtid);
//         console.log(ee.ge(txtid));
                window.tableSelectText = ee.ge(txtid).value;
          
//console.log(window.tableSelectText+", "+txtid+", "+window.tableSelect);                
                Array.forEach(ee.ge(me.id+'Body').getElementsByTagName("input"), function(ck)
                {
                    if( !isNull(ck) && ck.type == 'checkbox' )
                    {
                        if(ck.value != target.value){ ck.checked = false; }
                    }
                });
            
            if( !me.model.singleSelect )
            {
                var list = me.model.selectionList;
                for( var i = 0; i < list.length; i ++ )
                {
                    if( list[i] == target.value )
                    {
                        list[i] = null;
                        return;
                    }
                }
                list.push( target.value );
            }
        }
        );
    }

}

eTable.prototype.getSelectedItems = function( )
{
    var list = this.model.selectionList;
    var rval = new Array();
    if( this.model.singleSelect )
    {
        Array.forEach(list,function(item)
        {
            if( item != null ){ rval[0] = item; }
        });
    }
    else
    {
        for( var i = 0; i < list.length; i ++ )
        {
            if( list[i] != null )
            {
                rval.push( list[i] );
            }
        }
    }
    return rval;
}

eTable.prototype.removeFilterBar = function()
{
    var me = this;
    if( ee.ge(me.id+"filterRow") )
    {
        var fr = ee.ge(me.id+"filterRow");
        while( fr.childNodes.length > 0 )
        {
            fr.removeChild( fr.firstChild );
        }
        fr.parentNode.removeChild(fr);
    }
    me.model.clearFilter();
    me.renderTable();
    updateDisplay(me);
}

eTable.prototype.showFilterBar = function()
{
    if( !document.createDocumentFragment )
    {
        alert("Your browser does not support this feature." );
        return;
    }
    var me = this;
    var df = document.createDocumentFragment();
    
    var filterRow = ee.ce("tr");
    filterRow.id = me.id+"filterRow";
    filterRow.className = "filter-row";
    df.appendChild(filterRow);
    
    if( !isNull( me.selectorColumn ) )
    {
        var td = ee.ceAsChild( "td", filterRow );
    }
      
    var mt = me.model.meta;
    Array.map(mt, function(item,i)
    {
        if( item.display )
        {
            var id = me.id+"-fr-"+i;
            var td = ee.ce("td");
            var ip = ee.ce("input");
            ip.id = id;
            ip.setAttribute("type","text" );
            ip.className = "filter-input";
            
            var lab = ee.ce("label");
            lab.setAttribute("for",ip.id);
            lab.appendChild(document.createTextNode(item.colName));
            lab.className = "filter-bar-label";
            
            
            td.appendChild(lab);
            td.appendChild( ip );
            filterRow.appendChild( td );
            
            EventUtils.addEventHandler( ip, "keydown",  function(evt)
            {
                var rval = true;
                evt = EventUtils.getEvent();
                if( evt.type == 'keydown' && evt.keyCode == KEY_ENTER  )
                {
                    var inpt = EventUtils.getTargetElement();
                    var temp = inpt.id.split('-');
                    var index = Number(temp[temp.length-1]);
                    var val = inpt.value;
                    if( val && val.length > 0 )
                    {
                        me.model.filter(index, val);
                        Array.forEach(ee.ge(filterRow.id).getElementsByTagName("input"), function(item)
                        {
                            item.value = "";
                        });
                        inpt.value = val;
                        me.renderTable();
                        updateDisplay(me);
                    }
                    rval = false;
                }
                return rval;
            });
            
            if(me.model.filterProperties.enabled == true &&
               i == me.model.filterProperties.column)
            {
               ip.value = me.model.filterProperties.q;
            }
               
        }
    }); 
    var thead = document.getElementById( me.id + 'Head' );
    thead.appendChild(df);
   
   // Find the first column with a filtering input.
   var k = 0;
   for( ; k < 5; k++ )
   {
       var e = ee.ge(me.id+'filterRow').getElementsByTagName('td')[k];
       if( !isNull(e.getElementsByTagName('input')[0]) ){ break; }
   }
   
    setTimeout("ee.ge('"+me.id+"filterRow').getElementsByTagName('td')["+k+"].getElementsByTagName('input')[0].focus();",10);

}


eTable.prototype.createIconTableBody = function()
{
    var me = this;
    var tr;
    var td;
    // Set up the dom objects.
    me.clearTableBody();
    var tbody = document.getElementById( me.id + 'Body' );
    tr = ee.ceAsChild( "tr", tbody );
    for( var i = 0;  me.model.hasRow(); i ++ )
    {
        if( ( i % 4 ) == 0 )
        {
            tr = ee.ceAsChild( "tr", tbody );
        }
        td = ee.ceAsChild( "td", tr );
        me.getIconValue( td );
        me.model.nextRow();
    }

}

eTable.prototype.decorateColumn = function( parent, table, meta )
{
    // Add id.
    //var decorate = this.decorator.decoratorMap[this.model.getMetaValue()];
    if( meta && meta.type == 2 )
    {
        parent.className = "numeric-column";
    }
    var decorate = this.decorator.getDecoratorByMetaColumn( table.model.getMetaValue() );
    if( isNull( decorate ) )
    {
        parent.innerHTML = eDecorator.decorateURL( table.model.getData(), meta );
    }
    else
    {
        decorate.call(table,parent,table,meta);
        //decorate( parent, table, meta );
    }
}

eTable.prototype.getIconValue = function( parent )
{
    var me = this;
    while( me.model.hasColumn() )
    {
        var m = me.model.meta[me.model.currentColumn];
        switch( m )
        {
            case "NAMED_TEXT.LABEL" :
            {
                me.decorator.decorateNamedTextLabel( parent, me.model );
                return;
            }
            case "FORMATTED_DATASET.FORMATTED_DATASET_ID" :
            {
                me.decorator.decorateFdsId( parent, me.model );
                return;
            }
            case "CLASS.CLASS_ID" :
            {
                me.decorator.decorateClassId( parent, me.model );
                return;
            }
            case "ELEMENT.DESCRIPTION" :
            {
                me.decorator.decorateElementDescription( parent, me.model );
                return;
            }
            default :
            {
                break;
            }
        }
        me.model.nextColumn();
    }
}

eTable.prototype.displayDiagram = function( url )
{
    if( this.displayMode == eTable.DETAIL_MODE )
    {
        this.displayMode = eTable.DIAGRAM_MODE;
        this.clearTableHead();
        this.clearTableBody();
        // Create dom elements to hold the diagram.
        var tbody = ee.ge( this.id + 'Body' );
        var tr = ee.ceAsChild( 'tr', tbody );
        var td = ee.ceAsChild( 'td', tr );
        var div = ee.ceAsChild( 'div', td );
        url += "&layout=" + this.model.diagramLayout;
        var s = '<embed src="'+url+'" height="800px" width="900px" type="image/svg+xml" ></embed>';
        div.innerHTML = s;
    }
    else
    {
        this.displayMode = eTable.DETAIL_MODE;
        this.model.resetCursor();
        this.renderTable();
    }
    EventUtils.stopEventPropagation( EventUtils.getEvent() );
    return false;

}

eTable.prototype.setSelector = function( onoff, metaCol, singleSelect )
{
    if( onoff )
    {
        this.selectorColumn = metaCol;
    }
    else
    {
        this.selectorColumn = null;
    }
    if( !isNull(singleSelect) )
    {
        this.model.singleSelect = singleSelect;
    } 
}

eTable.prototype.setSelectorLabelMetaColumn = function( metaCol )
{
    this.model.selectorLabelMetaColumn = metaCol;
}

eTable.prototype.getSingleSelectionDetails = function()
{
    var val = this.model.lookupByMetaAndValue(this.model.getSelectedValue(), this.selectorColumn, this.model.selectorLabelMetaColumn );
    return { "id": val.key,
             "text" : val.value, 
             "row" : (val.row/this.model.defaultPageSize) < 1 ? 0 : val.row };
}


///////////////////////////////////////////////////////////////////////////////
// Window level event handlers.
///////////////////////////////////////////////////////////////////////////////

function loadClassView()
{
    // Don't ask.
}

function displayChange( id, sel )
{
    var t = tables[id];
    var mode = sel.options[sel.selectedIndex].value;
    if( mode == 3 )
    {
        displayDiagram( '../request/classDiagram', id );
        // displayDiagram( '../classList.html', id );
    }
    else
    {
        t.setDisplayMode( mode );
        t.model.resetCursor();
        t.renderTable();
    }
}

function displayDiagram( url, id )
{
    var table = tables[id];
    table.displayDiagram( url );
}


function filter( evt,id )
{
    if( evt.type == 'keydown' && !(evt.keyCode == KEY_ENTER || evt.keyCode == KEY_SPACE)  ){return;}
    var table = tables[id];
    if( isNull(table) || isNull(table.id) ){ return; }
    if( ee.ge(table.id+"filterRow") )
    {
        table.removeFilterBar();
    }
    else
    {
        table.showFilterBar();
    }
}

function load()
{
    if( self != top )
    {
        document.bgColor = "#fafafa";
        var b = document.getElementById( 'bannerT' );
        if( b != null ) b.style.display = "none";
        var s = document.getElementById( 'status' );
        if( s != null )s.style.background = "#fafafa";
        var t = document.getElementById( 'pinTop' );
        if( t != null )t.style.background = "#fafafa";
        var h = document.getElementById( 'header' );
        if( h != null )h.style.left = "10px";
    }
    setPage();
    //  loadTables();
}

function loadTables()
{
    var delay = 0;
    for( var p in tables )
    {
        loadTable( p );
    }
}

function loadTable( id )
{
    var t = null;
    t = tables[id];
    if( t != null )
    {
        t.renderTable();
        updateDisplay( t );
        EventUtils.addEventHandlerById( t.id+'page', "change", pageChangeX );
    }
    var caption = ge( id + "Caption" );
    if( ! isNull( caption ) )
    {
        caption.style.display = "none";
    }
    
    /*
    Array.forEach(t.model.meta,function(item)
    {
        console.log(item.dump());
    });
    */
}

function callbacks( t )
{
    var l = t.renderingCallbacks.length;
    for( var i = 0; i < l; i ++ )
    {
        t.renderingCallbacks[i]( t );
        // var cb = t.renderingCallbacks[i];
        // cb( t );
    }
}

function pageChangeX( evt )
{
// If the page box has a value and it does not match the models current page,
        // we want to use the box value, this can happen when the user hits the back button
        // and the page reloads from the browser cache.
        var p = document.getElementById( t.id + 'page' );
        if( !isNull( p.value ) )
        {
            var cp = t.getCurrentPage();
            if( (p.value-1) != cp )
            {
                t.setCurrentPage( p.value-1 );    
            }
        
        }
}


function pageChange( evt )
{
    evt = EventUtils.getEvent();
    if( isNull( evt ) )
    {
        return;
    }
    var pageBox = evt.target;
    if( 13 == ( evt.which || evt.charCode || evt.keyCode ) )
    {
        var id = pageBox.id;
        var tid = id.substr( 0, id.indexOf( "page" ) );
        var table = tables[tid];
        if( isNull(table) ){ return; }
        var pbv = pageBox.value;
        if( isNumeric( pbv ) && ( pbv > 0 ) && ( pbv < ( table.getRowCount() / table.getPageSize() ) + 1 ) )
        {
            table.showPage( pageBox.value );
        }
        else
        {
            setPageData( table );
        }
        updateDisplay( table );
        pageBox.focus();
    }
}


function tableKeypressHandler(evt, id)
{
    evt = EventUtils.getEvent();
    var character = EventUtils.getKeyCharacter(evt);
    if( evt.type == 'keypress' && isNull(ee.ge(id+"filterRow") ) )
    { 
      if (character == 'p' || character == 'k')
      {
          move(-1,id);
      } 
      else if (character == 'n' || character == 'j')
      {
          move(1,id);
      }
      else if (character == 'f')
      {
          var t = tables[id];
          if( isNull(t) ){return; }
          t.showFirstPage();
          updateDisplay( t );
      }
      else if(character == 'l') 
      { 
          var t = tables[id];
          if( isNull(t) ){return; }          
          t.showLastPage();
          updateDisplay( t );
      }
     // EventUtils.stopEventPropagation(evt);
    }

}


function nav(evt, dir, id )
{
    evt = EventUtils.getEvent();
    if( (evt.type == 'keypress') && (evt.keyCode != 13) ){ return false; }
    move(dir,id);
    evt.target.focus();
}

function move(dir,id)
{
    var t = tables[id];
    if( isNull(t) ){ return false; }
    ( dir > 0 ) ? t.showNextPage() : t.showPreviousPage();
    updateDisplay( t );
}

function first(evt, id )
{
    evt = EventUtils.getEvent();
    if( (evt.type == 'keypress') && (evt.keyCode != 13) ){ return false; }
    var t = tables[id];
    if( isNull(t) ){ return false; }
    t.showFirstPage();
    updateDisplay( t );
    evt.target.focus();
}

function last(evt, id )
{
    evt = EventUtils.getEvent();
    if( (evt.type == 'keypress') && (evt.keyCode != 13) ){ return false; }
    var t = tables[id];
    if( isNull(t) ){ return false; }    
    t.showLastPage();
    updateDisplay( t );
    evt.target.focus();
}

function find()
{
    alert( "Find is not implemented in this version." );
}

function updateDisplay( t )
{
    setPageData( t );
    //location.hash = "#"+t.id;
}

function setViewMessage( mess, id  )
{
    var sa = document.getElementById( id + 'message' );
    if( sa != null ) sa.innerHTML = mess;
}

function setPageData( t )
{
    var p = document.getElementById( t.id + 'page' );
    var po = document.getElementById( t.id + 'pageOf' );
    if( p == null || po == null ) return;
    var size = t.getRowCount();
    var count = ( t.model.defaultPageSize > size ) ? size : t.model.defaultPageSize;
    var current = ( t.model.currentRow < 0 ) ? count : t.model.currentRow;
    //  alert( "size = " + size + " count = " + count + " current = " + current );
    if( size == 0 )
    {
        p.value = "0";
        po.innerHTML = " 0";
    }
    else
    {
        //p.value = ( t.model.currentRow < 0 ) ? Math.ceil( size / ( ( count > 0 ) ? count : 1 ) ) : Math.ceil( current / ( ( count > 0 ) ? count : 1 ) );
        var tp = Math.ceil( current / ( ( count > 0 ) ? count : 1 ) );
        p.value = ( t.model.currentRow < 0 ) ? 1 : ( tp == 0 ? 1 :  tp );
        po.innerHTML = Math.ceil( size / ( ( count > 0 ) ? count : 1 ) );
    }

    persistCurrentPageIndex( t, p.value );
}

function persistCurrentPageIndex(t, page)
{
   /* var fid = t.getFilterId();
    if (!fid || fid < 0)
    {
        return;
    }

    var obj = DomFactory.createSoapDOM();
    var soapDom = obj.doc;
    var body = obj.body;

    var bNode = soapDom.createElement("ejs:filterState");
    bNode.setAttribute("xmlns:ejs", "http://www.enterprise-elements.com/js");
    bNode.setAttribute("id", t.getFilterId());
    bNode.setAttribute("page", page);
    body.appendChild(bNode);

    var req = DomFactory.createXmlHttp();
    var url = DomFactory.checkUrl("../ws");

    req.open("POST", url, true);
    req.onreadystatechange = function()
    {
        // no-op
    }
    req.setRequestHeader("Content-Type", "text/xml");
    req.send(soapDom);*/

}



///////////////////////////////////////////////////////////////////////////////
// eDecorator
///////////////////////////////////////////////////////////////////////////////

function eDecorator()
{
    this.decoratorMap = [];
    var lists = [];
    this.symbolList = [];
    this.typeList = [];
    this.classList = [];
    this.loadMap();
}

eDecorator.decorateURL = decorateUrl;

eDecorator.prototype.getDecoratorByMetaColumn = function(metaVal)
{
    var map = this.decoratorMap;
    for( var i = 0; i < map.length; i ++ )
    {
        if( map[i].re.test(metaVal) ){ return map[i].decorator; }
    }
}



eDecorator.prototype.loadMap = function()
{
    
    var dm = [ { "re":new RegExp( "(ELEMENT_ATTR_C[0-9]+|ELEMENT)\.ELEMENT_ID" ), "decorator":this.decorateElementId},
               { "re":new RegExp( "ELEMENT\.DESCRIPTION" ), "decorator":this.decorateElementDescription},
               { "re":new RegExp( "CLASS\.CLASS_ID" ), "decorator":this.decorateClassId},
               { "re":new RegExp( "CLASS\.NAME" ), "decorator":this.decorateClassName},
               { "re":new RegExp( "CLASS\.SYMBOL_ID" ), "decorator":this.decorateClassSymbolId},
               { "re":new RegExp( "CLASS\.PREFIX" ), "decorator":this.decorateClassPrefix},
               { "re":new RegExp( "COLOR\.NAME" ), "decorator":this.decorateColorName},
               { "re":new RegExp( "NAMED_TEXT\.LABEL" ), "decorator":this.decorateNamedTextLabel},
               { "re":new RegExp( "SYMBOL\.SYMBOL_ID" ), "decorator":this.decorateSymbolId},
               { "re":new RegExp( "NAMED_TEXT\.TYPE_ID" ), "decorator":this.decorateNamedTextTypeId},
               { "re":new RegExp( "CLASS\.TYPE_ID" ), "decorator":this.decorateTypeId},
               { "re":new RegExp( "DISCUSSION\.TITLE" ), "decorator":this.decorateDiscussionTitle},
               { "re":new RegExp( "DISCUSSION\.DISCUSSION_ID" ), "decorator":this.decorateDiscussionId},
               { "re":new RegExp( "STATUS\.NAME" ), "decorator":this.decorateStatusName},
               { "re":new RegExp( "STATUS\.STATUS_ID" ), "decorator":this.decorateStatusId},
               { "re":new RegExp( "PSEUDO\.BAR_GRAPH" ), "decorator":this.decorateBarGraph},
               { "re":new RegExp( "PSEUDO\.PERCENT" ), "decorator":this.decorateBarGraph},
               { "re":new RegExp( "CLASS_ATTRIBUTE\.ATTRIBUTE_ID" ), "decorator":this.decorateAttributeId},
               { "re":new RegExp( "ATTRIBUTE\.ATTRIBUTE_ID" ), "decorator":this.decorateAttributeId},
               { "re":new RegExp( "FORMATTED_DATASET\.FORMATTED_DATASET_ID" ), "decorator":this.decorateFdsId} ];

    this.decoratorMap = dm;

}

eDecorator.prototype.test = function( parent, table, meta )
{
    parent.innerHTML = "<em>"+table.model.getData()+"</em>";
}

eDecorator.prototype.updateFromModel = function( model )
{
    var dm = [];
    var metaList = model.meta;
    for( var i = 0; i < metaList.length; i++ )
    {
        var meta = metaList[i];
        if( !isNull(meta) && !isNull( meta.decorator ) )
        {
            dm[dm.length] = {"re":new RegExp(meta.value),  "decorator":new Function("parent","table","meta",meta.decorator)};//eval( meta.decorator );
        }
    }
    
    Array.forEach(this.decoratorMap, function(item)
    {
        dm[dm.length] = item;                
    });
    this.decoratorMap = dm;
}

eDecorator.prototype.decorateElementId = function( parent,  table, meta )
{
    var model = table.model;
    var val = model.getValueByMetaColumn( meta.value );
    var cid = model.getValueByMetaColumn( 'CLASS.CLASS_ID' );
    
    // Add the edit element link.
    var tt;
    var cn = model.getValueByMetaColumn( 'CLASS.NAME' );
    if( isNull( cn ) || cn.length == 0 )
    {
        cn = model.getValueByMetaColumn( 'CLASS.PREFIX' );
        if( isNull( cn ) )
        {
            cn = "one of these.";
            tt = "Edit[this element: " + val + "]";
        }
        else
        {
            tt = "Edit[" + cn + " " + val + "]";
        }
    }
    if( isNull(tt) )
    {
        tt = "Edit[" + cn + " " + val + "]";
    } 
    
    // Add the new element link.    
    if( ! isNull( cid ) )
    {
        eDecorator.createCopyElementLink( cid, parent, model.elementNewUrl, cn, val );
        if( cid == 1 )
        {
            eDecorator.addUserEmailLink( val, parent );
        }
    }
    
    var eim = eDecorator.createImage( "images/icon_edit.gif", tt, null );
    var eda = eDecorator.createAnchor( "javascript:editElement('"+val+"', '"+model.elementEditUrl+"')", null, eim, "eida", null );
    parent.appendChild( eda );

    // Add the expansion diagram link.
    var dia = eDecorator.createImage( 'images/icon_graph.gif', "Expansion Diagram", null );
    var ad = eDecorator.createAnchor( "../request/classDiagram?sa=t&v=exp&eid=" + val, null, dia, "eida", null );
    parent.appendChild( ad );
    
    // hierarchy link.
    var hl = eDecorator.createImage( 'images/child_hierarchy.gif', "Children", null );
    var cl = eDecorator.createAnchor( "../request/filter?id=145&eid=" + val, null, hl, "eida", null );
    parent.appendChild( cl );
    var hl = eDecorator.createImage( 'images/parent_hierarchy.gif', "Parents", null );
    var pl = eDecorator.createAnchor( "../request/filter?id=144&eid=" + val, null, hl, "eida", null );
    parent.appendChild( pl );
    
    if( moz )parent.setAttribute( "class", "elementId" );
    else parent.setAttribute( "className", "elementId" );
}

eDecorator.createNewElementLink = function( cid, parent, url, cname )
{
    if( isNull(cname) )
    {
        cname = "element";
    }
    var im = eDecorator.createImage( "images/new_small.gif", "Create a new "+cname, null );
    var nw = eDecorator.createAnchor( "javascript:newElementWindow( '"+cid+"', '"+url+"' )", null, im, "eida", null );
    parent.appendChild( nw );
}

eDecorator.createCopyElementLink = function( cid, parent, url, cname, val )
{
    if( isNull(cname) )
    {
        cname = "element";
    }
    url += val;
    var im = eDecorator.createImage( "images/newascopy.gif", "Create a new "+cname, null );
    var nw = eDecorator.createAnchor( "javascript:newElementWindow( '"+cid+"', '"+url+"', null, 'Copy' )", null, im, "eida", null );
    parent.appendChild( nw );
}

eDecorator.prototype.decorateElementDescription = function( parent, table, meta )
{
    var d = document.createElement( 'div' );
    d.style.display = 'inline';
    d.style.marginRight = "4px";
    var model = table.model;
    var val = model.getData();
    var eid = model.getElementIdValueForGroup(meta); //model.getValueByMetaColumn( 'ELEMENT.ELEMENT_ID' );
    if( isNull( eid ) )
    {
        parent.innerHTML = val;
    }
    else
    {
        var a = eDecorator.createAnchor( model.elementDetailUrl + eid, val, null, null );
        if( ie5 )
        {
            a.attachEvent( 'ondragstart', dragStart );
        }
        d.appendChild( a );
        parent.appendChild( d );
    }
    if( moz )d.setAttribute( "class", "element" );
    else d.setAttribute( "className", "element" );
}

eDecorator.prototype.decorateClassId = function( parent, table, meta )
{
    var model = table.model;
    var val = model.getValueByMetaColumn( 'CLASS.CLASS_ID' );
    var nam = model.getValueByMetaColumn( 'CLASS.NAME' );
    var img = table.decorator.getClassImg( model, ( nam == null ) ? val : nam );

    var eid = model.getElementIdValueForGroup(meta); //model.getValueByMetaColumn( 'ELEMENT.ELEMENT_ID' );
    if( isNull( eid ) )
    {
        eDecorator.createNewElementLink( val, parent, model.elementNewUrl, nam );
    }
    
    var a = null;
    if( img!= null )
    {
        a = document.createElement("a");
        a.href = model.classDetailUrl+val;
        a.appendChild(img);
    }
    else
    {
        a = eDecorator.createAnchor( model.classDetailUrl + val, ( nam == null ) ? val : nam );
    }
    parent.appendChild( a );
}


eDecorator.prototype.decorateClassName = function( parent, table, meta )
{
    var model = table.model;
    var val = model.getData();
    var cid = model.getValueByMetaColumn( 'CLASS.CLASS_ID' );
    var img = table.decorator.getClassImg( model, cid );
    var a = null;
    if( img != null )
    {
        ( ie5 ) ? img.alt = "Class " + val : img.title = "Class " + val;
    }
    a = eDecorator.createAnchor( model.classDetailUrl + cid, ( val == null ) ? "" : val, img );
    a.style.zIndex = 2;

    eDecorator.classColumnDecoration(parent, model, val, cid, a);
    
}


eDecorator.classColumnDecoration = function(parent, model, val, cid, a)
{
    parent.style.padding = "0";
    parent.style.margin  = "0";
    
    var container = ee.ceAsChild("div",parent);
    container.style.position = "relative";
    container.className = "containercell";

    var buttons = ee.ce("div");
    container.appendChild(buttons);
    buttons.className = "ccell";
   
    var panel = ee.ce("div");
    container.appendChild(panel);
    panel.className = "dcell";
    
    panel.appendChild(a);
    eDecorator.createNewElementLink( cid, buttons, model.elementNewUrl, val );

    var b = eDecorator.createAnchor( "../request/elementGrid?active="+cid, "", eDecorator.createImage("images/table_edit.gif") );
    b.title = "Grid Edit";
    buttons.appendChild(b);
}

eDecorator.prototype.decorateClassPrefix = function( parent, table, meta )
{
    var model = table.model;
    var val = model.getData();
    if( isNull(model.getValueByMetaColumn("CLASS.NAME")) )
    {
        var cid = model.getValueByMetaColumn("CLASS.CLASS_ID");
        var a = eDecorator.createAnchor(model.classDetailUrl+cid,( val == null ) ? "" : val,null);
        
        eDecorator.classColumnDecoration(parent, model, val, cid, a);
    }
    else
    {
        parent.appendChild(document.createTextNode(val));
    }

}

eDecorator.prototype.decorateAttributeId = function( parent,table, meta )
{
    var model = table.model;
    var aid = model.getData();
    var cid = model.getValueByMetaColumn( 'CLASS.CLASS_ID' );
    if( isNull(cid) )
    {
        cid = getMetaTagMappedValue( "cid" );
        if( isNull( cid ) )
        {
            cid = getMetaTagMappedValue( "class.class_id" );
        }
    }
    if( !isNull(cid) )
    {
        var img = ee.ce("img");
        img.border = 0;
        img.alt = "Detailed attribute information.";
        img.src = "../images/field_info.png";
        parent.appendChild(img);
        a = eDecorator.createAnchor( "../request/attributeDetail?id="+aid+"&cid=" + cid, ( aid == null ) ? "" : aid, null );
        parent.appendChild( a );
    }
    else
    {
        parent.appendChild( ee.ct( aid ) );
    }

};

eDecorator.prototype.decorateStatusName = function( parent, table, meta )
{
    var model = table.model;
    var symid = model.getValueByMetaColumn( 'STATUS.STATUS_ID' );
    var val = model.getData();
    if( ! isNull( model.symbolTable  ) && ! isNull( symid ) )
    {
        var sym = model.symbolTable[symid];
        if( ! isNull( sym ) )
        {
            var im = eDecorator.createImgElement( sym, val, null );
            parent.appendChild( im );
        }
    }
    parent.appendChild( document.createTextNode( val ) );
}

eDecorator.prototype.decorateNamedTextLabel = function( parent, table, meta )
{
    var model = table.model;
    var id = model.getValueByMetaColumn( 'NAMED_TEXT.TEXT_ID' );
    var type = model.getValueByMetaColumn( 'NAMED_TEXT.TYPE_ID' );
    if( type == null )type = model.getValueByMetaColumn( 'TYPE.TYPE_ID' );
    var val = model.getData();
    // Add the display link;
    var div = document.createElement( "div" );
    var a = null;
    if( type == 20 )
    {
        a = eDecorator.createAnchor( model.filterUrl + id, val, null, "ntid" );
        div.appendChild( a );
    }
    else if( type == 22 )
    {
        a = eDecorator.createAnchor( "../request/filter?id="+id, val, null, "ntid" );
        div.appendChild( a );
    }
    else if( type == 21 || type == 23 )
    {
        a = eDecorator.createAnchor( model.chartUrl + id, val, null, "ntid" );
        div.appendChild( a );
    }
    else if ( type == 88 )
    {
        a = eDecorator.createAnchor( model.folderUrl + id, val, null, "ntid" );
        div.appendChild( a );
    }
    else if ( type == 49 )
    {
        a = eDecorator.createAnchor( "../request/namedText?name=" + val + "&loc=db", val, null, "ntid" )
        div.appendChild( a );
    }
    else
    {
        div = document.createTextNode( val );
    }
    if( ie5 )
    {
        if( a != null )
        {
            a.attachEvent( 'ondragstart', dragStart );
        }
    }
    parent.appendChild( div );
}

eDecorator.createFilterEditHyperlink = function( id, parent )
{
    var img = eDecorator.createImage( "images/icon_edit.gif", "Edit Filter " + id, "" );
    img.style.verticalAlign = "middle";
    img.height = 16;
    img.width = 16;
    if( model.filterEditUrl != '0' )
    {
        var ef = eDecorator.createAnchor( model.filterEditUrl + id, "", img );
        parent.appendChild( ef );
    }
}

eDecorator.prototype.decorateNamedTextId = function( parent, table, meta )
{
    var model = table.model;
    var id =  model.getData();
    var img = eDecorator.createImage( "images/filter.gif", "Edit Filter " + id, "" );
    img.style.border = 0;
    if( model.filterEditUrl != '0' )
    {
        var a = eDecorator.createAnchor( model.filterEditUrl + id, "", img );
        parent.appendChild( a );
    }
}

eDecorator.prototype.decorateNamedTextTypeId = function( parent, table, meta )
{
    var model = table.model;
    var val = ( model.getData( ) == null ) ? "" : model.getData();

    var type =
    {
    }
    ;
    if( val == 20 )
    {
        type.name = "Detail SQL";
    }
    else if( val == 21 )
    {
        type.name = "Summary SQL";
    }
    else if( val == 23 )
    {
        type.name = "Metric SQL";
    }
    else if( val == 22 )
    {
        type.name = "Parameterized SQL";
    }
    else if( val == 78 )
    {
        type.name = "User supplied HTML";
    }
    else if( val == 49 )
    {
        type.name = "XSLT";
    }
    else if( val == 88 )
    {
        type.name = "Folder";
    }
    else
    {
        type.name = "";
    }

    var id = model.getValueByMetaColumn( 'NAMED_TEXT.TEXT_ID' );
    if( val == 21 || val == 23 )
    {
        if( id )
        {
            var img2 = null;
            if( val == 21 )
            {
                img2 = eDecorator.createImage( "images/chart_new.gif", "Show Chart " + id, "" );
            }
            else if( val == 23 )
            {
                img2 = eDecorator.createImage( "images/gauge16.gif", "Show Gauge " + id, "" );
            }
            img2.style.border = 0;
            var ef2 = eDecorator.createAnchor( model.chartUrl + id, "", img2 );
            parent.appendChild( ef2 );
        }
    }
    else if( val == 20 )
    {
        var id = model.getValueByMetaColumn( 'NAMED_TEXT.TEXT_ID' );
        if( id )
        {
            var img2 = eDecorator.createImage( "images/filter.gif", "Open " + id, "" );
            img2.style.border = 0;
            var ef2 = eDecorator.createAnchor( model.folderUrl + id, "", img2 );
            parent.appendChild( ef2 );
        }
    }
    else if( val == 88 )
    {
        var img = eDecorator.createImage( "images/folder.gif", "Open Folder", "" );
        var a = eDecorator.createAnchor( model.folderUrl + id, "", img );
        parent.appendChild( a );
    }
    else if( val == 78 || val == 49 )
    {
        var img = eDecorator.createImage( "images/html.gif", "Markup", "" );
        img.style.height = "16px";
        img.style.width = "16px";
        parent.appendChild( img );
    }

    parent.appendChild( document.createTextNode( type.name ) );
}

eDecorator.prototype.decorateFdsId = function( parent, table, meta )
{
    var model = table.model;
    var cp = model.getValueByMetaColumn( 'FORMATTED_DATASET.FORMATTED_DATASET_ID' );
    var val = ( model.getData( ) == null ) ? "" : model.getData();
    var a = eDecorator.createAnchor( model.reportUrl + cp, val, null, "fdsid"  );
    parent.appendChild( a );
    // NOTE : Not enabled for dnd.
}

eDecorator.prototype.decorateStatusId = function( parent, table, meta )
{
    eDecorator.symbolIdHelper( parent, table, "STATUS.STATUS_ID" );
}

eDecorator.prototype.decorateSymbolId = function( parent, table, meta )
{
    eDecorator.symbolIdHelper( parent, table, "SYMBOL.SYMBOL_ID" );
}

eDecorator.prototype.decorateSymbolTypeName = function( parent, table, meta )
{
    eDecorator.symbolIdHelper( parent, table, "SYMBOL.SYMBOL_ID" );
}

eDecorator.prototype.decorateClassSymbolId = function( parent, table, meta )
{
    eDecorator.symbolIdHelper( parent, table, "CLASS.SYMBOL_ID" );
}

eDecorator.symbolIdHelper = function( parent, table, symKey )
{

    try
    {
        var model = table.model;
        if( isNull(model.getData()) || model.getData().length < 1 ){ return; }
        
        
        var val = ( model.getData( ) == null ) ? "" : model.getData();
        
     
        if( ! isNull( model.symbols ) && ! isNull( model.symbols[symKey] ) && (model.symbols[symKey] != '../null') )
        {
            var symList = model.symbols[symKey];
            var sym = symList[val];
            
         
            if( !isNull(sym) && !isNull(sym.url) )
            {
                var img = eDecorator.createImgElement(sym.url);
                if( !isNull( img ) )
                {
                    img.alt = sym.alt;
                    parent.appendChild( img );
                }
                else
                {
                    parent.innerHTML = symList[val].alt;
                }
            }
        }
    }
    catch(e)
    {
    }

}

eDecorator.prototype.decorateTypeId = function( parent, table, meta )
{
    var model = table.model;
    var val = ( model.getData( ) == null ) ? "" : model.getData();
    var type =
    {
    }
    ;
    type.name = val;
    var t = document.createTextNode( type.name );
    parent.appendChild( t );
}

eDecorator.prototype.decorateColorName = function( parent, table, meta )
{
    var val = table.model.getData();
    if( ! isNull( val )  && val.length > 2 )
    {
        parent.style.backgroundColor = '#' + val;
    }
}

eDecorator.prototype.decorateDiscussionTitle = function( parent, table, meta )
{
    var val = ( table.model.getData( ) == null ) ? "" : table.model.getData();
    var id = table.model.getValueByMetaColumn( 'DISCUSSION.DISCUSSION_ID' );
    var a = eDecorator.createAnchor( "../request/discussion?id=" + id, val, null );
    parent.appendChild( a );
}

eDecorator.prototype.decorateDiscussionId = function( parent, table, meta )
{

}

eDecorator.prototype.decorateTableName = function( parent, table, meta )
{
    var val = ( table.model.getData() == null ) ? "" : table.model.getData();
    var a = eDecorator.createAnchor( "javascript:eDecorator.renderTable('"+val+"', show );", val, null, null );
    parent.appendChild( a );
}

eDecorator.prototype.decorateBarGraph = function( parent, table, meta )
{
    var val = table.model.getData();
    parent.style.textAlign = "left";
    parent.style.padding = "0px";
    parent.style.margin = "0px";
    parent.innerHTML = eDecorator.getBarGraphCell( val, "../images/blueDot.gif" );
}

eDecorator.addUserEmailLink = function( val, parent )
{
    var im = eDecorator.createImage( "images/email_link.gif", "Envelope.", 'email-link', 16, 16 );
    im.style.verticalAlign = "middle";
    im.style.margin = "2px";
    im.title = "Email this user.";
    var a = eDecorator.createAnchor( "javascript:eDecorator.showEmailDialog('"+val+"' );", null, im, null );
    parent.appendChild( a );
}

eDecorator.showEmailDialog = function( val )
{
    var recip_list = [val];
    var em = new eElementsEmailTask();
    em.execute( recip_list );
}

/*
eDecorator.prototype.renderTable = function( table, callback )
{
    var where = prompt( 'Enter the WHERE clause (including the word "where")', "" );
    // if( ! where ) return;
    var sql = 'select * from ' + table;
    if( where.length > 0 )
    {
        sql += " " + where;
    }
    var es = new eSqlStatement( sql );
    var sel = new eSqlList( callback );
    sel.addStatement( es );
    sel.execute();
}
*/

/*
eDecorator.prototype.getClassImg = function( cid, table ){
var me = table.decorator;
var img = null;
if( me.classList.getById ){
var co = me.classList.getById( cid );
if( co != null ){
if( me.symbolList.getById ){
var symbol = me.symbolList.getById( co.symbol );
if( ( symbol != null ) && ( symbol.fileName != null ) ){
img = me.createImgElement( symbol );
}
}
}
}
if( ! isNull( table.model.symbolTable ) && ! isNull( table.model.symbolTable[cid] ) ){
img = eDecorator.createImgElement( table.model.symbolTable[cid] );
}
return img;
}
*/
eDecorator.prototype.getClassImg = function( model, val )
{
    var symbol = null;
    var symVal = model.getValueByMetaColumn( 'CLASS.SYMBOL_ID' );
    try
    {
	    if( !isNull(symVal) && model.symbols['CLASS.SYMBOL_ID'] )
	    {
	        symbol = model.symbols['CLASS.SYMBOL_ID'][symVal];
	    }
	    else if( isNull(symbol) &&
	            (model.symbols['CLASS.CLASS_ID'] || model.symbols['SYMBOL.SYMBOL_ID']) )
	    {
	        symVal = model.getValueByMetaColumn( 'CLASS.CLASS_ID' );
	        if( !isNull(symVal) )
	        {
	           if( model.symbols['CLASS.CLASS_ID'] )
	           {
	              symbol = model.symbols['CLASS.CLASS_ID'][symVal];
	           }
	           else if( model.symbols['SYMBOL.SYMBOL_ID'] )
	           {
	              symbol = model.symbols['SYMBOL.SYMBOL_ID'][symVal];
	           }
	        }
	        else
	        {
	            symVal = model.getValueByMetaColumn( 'SYMBOL.SYMBOL_ID' );
	            symbol = model.symbols['SYMBOL.SYMBOL_ID'][symVal];     
	        }
	    }
    }
    catch(er)
    {
    	
    }
    var img = null;
    if( !isNull(symbol) )
    {
        img = eDecorator.createImgElement( symbol.url );
        img.alt = symbol.alt;
    }
    return img;
}
eDecorator.createImgElement = function( src )
{
    var im = document.createElement( "img" );
    im.style.height = "20px";
    im.style.width = "20px";
    im.style.border = "0px";
    im.style.marginRight = "4px";
    if( ! isNull( src ) )
    {
        im.src = src;
    }
    return im;
}

var reLT = new RegExp( "&lt;" );
var reGT = new RegExp( "&gt;" );
eDecorator.createAnchor = function( href, text, image, clazz, fake )
{
    var a = document.createElement( "a" );
    a.setAttribute( "href", href );
    if( image != null )
    {
        a.appendChild( image );
    }
    if( text != null )
    {
        var t = document.createTextNode( text );
        a.appendChild( t );
    }
    if( clazz != null )
    {
        if( moz )a.setAttribute( "class", clazz );
        else a.setAttribute( "className", clazz );
    }
    return a;
}

/* Note the convention of naming images... images / myimg.gif
* The function prepends the .. / portion of the path. */
eDecorator.createImage = function( name, alt, clazz, h, w )
{
    var img = document.createElement( "img" );
    img.style.border = 0;
    img.style.margin = "1px 2px 1px 0px";
    img.style.verticalAlign = "baseline";
    if( !name )name = "images/element_page16.gif";
    // FIXME:, to properly use relative url, should be in eSymbol.
    img.setAttribute( "src", "../" + name );
    if( alt != null )
    {
        img.setAttribute( "alt", alt );
    }
    if( clazz != null )
    {
        if( moz )img.setAttribute( "class", clazz );
        else img.setAttribute( "className", clazz );
    }
    /*
    if( h != null ){
    img.height = h;
    }
    if( w != null ){
    img.width = w;
    }
    */
    return img;
}


/* *
* @param
*     pctValue -- percent value between 0.0 and 1.0.
* @return
*     An html string, normally used with .innerHTML for the table cell ( < td > ).
*     For example :
*       td.innerHTML = eDecorator.getBarGraphCell( pct, width );
*       Removed Math.ceil from pct value because it led to rounding errors.
*       replaced with toFixed( 1 ).
*/
eDecorator.getBarGraphCell = function( pctValue, src,value )
{
    var w   = ( isNull(value) ? 70 : 50 );
    var iw  = pctValue == 0 ? 0 : Math.ceil( pctValue * w );
    var pct = pctValue == 0 ? 0 : 100 * pctValue;
    pct = pct.toFixed(1);

    var sb = new StringBuilder();
    
    // wrapper.
    sb.append("<div style='margin-left:5px;position:relative;width:165px'>");
    
    // bar graph.
    sb.append("<div style='width:100px; height:15px; border: 2px solid #d0d0d0;'>");
    var imgw = pctValue * 100;
    imgw = imgw.toFixed(0);
      sb.append("<img src='").append(src);
      sb.append("' style='height:15px;margin:0;padding:0;text-align:left;width:").append(imgw).append("px;' />");
    sb.append("</div>");
    
    // text for percentage.
    sb.append("<div style='position:absolute;left:110px;top:2px;font-size:90%;font-weight:bold;'>").append(pct).append("%</div>");
    
    // end wrapper.
    sb.append("</div>");
    
    return sb.toString();
}


/*
eDecorator.getBarGraphCell = function( pctValue, src,value )
{
    var w   = ( isNull(value) ? 70 : 50 );
    var iw  = pctValue == 0 ? 0 : Math.ceil( pctValue * w );
    var pct = pctValue == 0 ? 0 : 100 * pctValue;
    pct = pct.toFixed(1);

    var sb = new StringBuilder();
    sb.append( "<table style='width:100%;padding:0;margin:0;border:none;' ><tr>" );
    sb.append( "<td style='width:" ).append( w ).append( "%;border:none;padding:0px;margin:0px;'>" );
    sb.append( "<img src='"+src+"' height='10' width='" ).append( pct ).append( "%;' style='margin:0px;padding:0px;text-align:left;' />" );
    sb.append( "</td><td style='text-align:right;'>").append(pct).append("%</td>");

    if( !isNull(value) )
    {
        sb.append("<td style='text-align:right;' >(").append(value).append(")</td>" );
    }
    
    sb.append("</tr></table>" );

    return sb.toString();
}
*/






/////////////////////////////////////////////////////////////////////
// Misc. Functions and Utilities
/////////////////////////////////////////////////////////////////////

/* Options Window */
var optionsWindow = null;
function pageOptions( tid )
{
    var tab = tables[tid];
    if( isNull(tab)){ return; }
    createOptionsWindow( tab );
}
function createOptionsWindow( tab )
{
    var screenY = getWindowX();
    var screenX = getWindowY();
    optionsWindow = window.open( "", "options", "height=270,width=290,menubar=no,toolbar=no,locationbar=no,left=" + screenX + ",top=" + screenY );
    var fstr = "showOptionsWindow('"+tab.id+"')";
    setTimeout( fstr, 100 );
}

function showOptionsWindow( tid )
{
    if( optionsWindow != null )
    {
        var tab = tables[tid];
        var all;
        if( !isNull(tab.model) && !isNull(tab.model.data) )
        {
          all = (tab.model.getSize() == tab.model.defaultPageSize);
        }
        else
        {
          all = false;
        }
        var size = all == true ? 'ALL' : tab.model.defaultPageSize;

        var out = new StringBuilder();
        out.append( "<html><head><style>body{font-family:arial,helvetica;font-size:9pt;width:265px;} " );
        out.append( "select{ width:100px;display:block;float:left;margin-bottom:10px; } .checkbox{width:1em;} ");
        out.append( "label{font-size:90%;display: block;text-align: left; float:left;width:130px;padding-right:10px;} ");
        out.append( "input{display:block;width:80px;float:left;margin-bottom:10px;text-align:right;}</style></head><body>" );
        out.append( "<div style='width:100%;text-align:right;'><a href='javascript:window.close();'>Close Window</a></div>" );
        out.append( "<h1>Options</h1><form><fieldset><legend>Table Display</legend><label for='pgSz'>Rows per page</label>" );
        out.append( "<input type='text' id='pgSz' name='pgSz' value='" ).append(size).append("'/>" );
        out.append( "<label for='ckAll'>Or, check to show all</label><input id='ckAll' type='checkbox' class='checkbox' name='ckAll'" );
        if( all )
        {
            out.append( "checked='checked'" );
        }
        out.append( " /></fieldset>" );

        out.append( "<fieldset><legend>Diagram Mode</legend><label for='layout'>Layout</label><select name='layout' id='layout'><option value='0'>Symmetrical</option>" );
        out.append( "<option value='1'>Hierarchical</option><option value='2'>Orthogonal</option><option value='3'>Circular</option></select></fieldset>" );

        out.append( "<input type='button' value='Ok' onclick='window.opener.acceptOptions();'" );
        out.append( "        style='float:right;margin-top:5px;width:55px;text-align: center;'/>" );
        out.append( "<input type='hidden' value='").append(tab.id).append("' name='tid' />" );
        out.append( "</form></body></html>" );
        optionsWindow.document.write( out.toString() );
        optionsWindow.document.close();
    }
    else
    {
        optionsWindow.focus();
    }
}

function acceptOptions()
{
    if( optionsWindow && ! optionsWindow.closed )
    {
        var tc = null;
        var layout = null;
        if( optionsWindow.document.forms[0].ckAll.checked == true )
        {
            tc = - 1;
        }
        else
        {
            tc = optionsWindow.document.forms[0].pgSz.value;
        }
        if( ! isNull( optionsWindow.document.forms[0].layout ) )
        {
            layout = FormUtils.getSelectedValues( optionsWindow.document.forms[0].layout )[0];
        }
        var id =  optionsWindow.document.forms[0].tid.value;
        // var so = 0; // optionsWindow.document.forms[0].sortOrder.options[optionsWindow.document.forms[0].sortOrder.selectedIndex];
        // var so = optionsWindow.document.forms[0].maxH.value;
        so = 0;
        for( var t in tables )
        {
            var table = tables[t];
            if( id == table.id )
            {
                processTableOption( table, tc, so );
                if( ! isNull( layout ) )
                {
                    table.model.diagramLayout = layout;
                }
                saveOptionToDb( table.getFilterId(), tc );
                break;
            }
        }
        optionsWindow.close();
        optionsWindow = null;
    }
}

function saveOptionToDb( filterid, num )
{
    var sql = new eSqlStatement( "begin ee_set_filter_page_size_pref( ?, ? ); end; " );
    sql.addParameter( new eParameter( 'number', filterid ) );
    sql.addParameter( new eParameter( 'varchar', num ) );
    sqlList = new eSqlList( function()
    {
    }
    );
    sqlList.addStatement( sql );
    sqlList.execute();
    window.status = "Option Saved ";
}

function processTableOption( table, tc, so )
{
    if( isNumeric( tc ) && tc > 0 )
    {
        table.model.defaultPageSize = Number(tc);
    }
    else
    {
        table.model.defaultPageSize = table.model.getSize();
    }
    //      table.model.maxHeight = so;
    //    table.model.sortOrder = so.value;
    table.showPreviousPage();
    updateDisplay( table );
}



/* End Options Window */

/* Drag and Drop functionality */
function dragStart()
{
    event.dataTransfer.effectAllowed = "copy";
}

function editElement( id, url )
{
    url = ee.validateElementFormUrl( url );
    ee.popAndRefresh( url + id, 800, 600 );
}

function newElementWindow( id, url, linkCid, verb   )
{
    url = ee.validateElementFormUrl( url );
    // in main.js
    newElement( id, url, true, linkCid, verb );
}


function classDiagramClick( id )
{
    // window.open( "../request/page?id=25&eid=" + id );
    window.location.href = "../request/classAction?id=" + id;
}

window.classDiagramClick = classDiagramClick;


function getObject( evt, level )
{
    var elem = ( evt.target ) ? evt.target : ( ( evt.srcElement ) ? evt.srcElement : null );
    if( elem.nodeType == 3 )
    {
        elem = elem.parentNode;
    }
    for( var i = 0; i < level; i ++ )
    {
        elem = elem.parentNode;
    }
    return elem;
}

function normalizeEvent( evt )
{
    return ( evt ) ? evt : ( ( window.event ) ? event : null );
}

function getWindowWidth()
{
    var windowWidth = 0;
    if( typeof( window.innerWidth ) == 'number' )
    {
        windowWidth = window.innerWidth;
    }
    else
    {
        if( document.documentElement && document.documentElement.clientWidth )
        {
            windowWidth = document.documentElement.clientWidth;
        }
        else
        {
            if( document.body && document.body.clientWidth )
            {
                windowWidth = document.body.clientWidth;
            }
        }
    }
    return windowWidth;
}

function getWindowHeight()
{
    var windowHeight = 0;
    if( typeof( window.innerHeight ) == 'number' )
    {
        windowHeight = window.innerHeight;
    }
    else
    {
        if( document.documentElement && document.documentElement.clientHeight )
        {
            windowHeight = document.documentElement.clientHeight;
        }
        else
        {
            if( document.body && document.body.clientHeight )
            {
                windowHeight = document.body.clientHeight;
            }
        }
    }
    return windowHeight;
}

function getWindowX()
{
    return  ( getWindowHeight() * .3 ) + window.screenTop;
}

function getWindowY()
{
    return ( getWindowWidth() * .3 ) + window.screenLeft;
}

function isNumeric( str )
{
    var validChars = "0123456789.";
    var isNumber = true;
    var c;

    for( i = 0; i < str.length && isNumber == true;
    i ++ )
    {
        c = str.charAt( i );
        if( validChars.indexOf( c ) == - 1 )
        {
            isNumber = false;
        }
    }
    return isNumber;
}




function countRows( tableId )
{
    var t = document.getElementById( tableId );
    if( isNull( t ) ) return;
    var tbd = t.getElementsByTagName( 'tbody' );
    if( isNull( tbd ) ) return;
    var trlist = tbd[0].getElementsByTagName( 'tr' );
    var message;
    if( arguments.length == 1 )
    {
        message = document.getElementById( tableId + 'msg' );
    }
    else
    {
        message = document.getElementById( arguments[1] );
    }
    if( ! isNull( message ) )
    {
        if( trlist.length > 1 )
        {
            message.innerHTML += "<em> [" + trlist.length + " - items]</em>";
        }
        else
        {
            message.innerHTML += "<em> [" + trlist.length + " - item]</em>";
        }
    }
}

function init()
{
    setPage();
    checkFrame();
}

