// ++=========================================================================++
// || DTO Core v2.0.1 - 213
// || Copyright © 2008-2010 Drive Thru Online, Inc. All Rights Reserved.
// || This file may not be redistributed in whole or significant part, or
// || used on web site without licensing of the enclosed code,
// || and software features.
// || http://www.drivethruonline.com | info@drivethruonline.com
// || Downloaded 15:34, Sun Jul 18th 2010
// || 623790213_604952770317
// ++ ========================================================================++

function DTO_View()                         {}

function DTO_View_new(viewIDP)
{
    var obj = new DTO_View();
    DTO_View_init(obj, viewIDP);
    return obj;
}

function DTO_View_init(obj, viewIDP)
{
    obj.viewID = viewIDP;
    obj.view = null;                   //element in dom
    obj.subviews = [];
    obj.style = null;
    
    obj.drawSelfPre = function(frag)                        {}
    obj.drawSelfPost = function(frag)                       {}
    
    obj.drawSubviewPre = function(frag, subview)            {}
    obj.drawSubviewPost = function(frag, subview)           {}
    
    obj.draw = function()
    {
        //debug('top draw '+this.viewID);
        var frag = this.domNode();
        if(frag)
        {
            this.drawSelfPre(frag);
            for(var i=0; i<this.subviews.length; i++) 
            {
                var subview = this.subviews[i];
                this.drawSubviewPre(frag, subview);
                //debug('subview draw '+ subview.getViewID());
                subview.draw();
                this.drawSubviewPost(frag, subview);
            }
            this.drawSelfPost(frag);
        }
        else
            debug(this.viewID + " can't find viewID in the document");
    }
     
    obj.createSubviews = function()                         {}
    obj.addSubview = function(subview)                      {this.subviews.push(subview);}
    obj.countSubviews = function()                          {return this.subviews.length;}
    obj.clearSubviews = function()                          {this.subviews = [];}
    obj.clear = function(subview)                           {clearChildNodes(this.domNode()); this.view = null;}
    
    obj.removeSubview = function(viewID)
    {
        var view, newArray = [];
        for(key in this.subviews)
        {
            view = this.subviews[key];
            if (typeof view == 'object' && view.getViewID() != viewID)
                newArray.push(view);
        }
        this.subviews = newArray;
    }
    
    obj.domNode = function()
    {
        if(!this.view)
            this.view = document.getElementById(this.viewID);
        return this.view;
    }
    
    obj.getViewID = function()                              {return this.viewID;}
    obj.getStyle = function()                               {return this.style;}
    obj.setStyle = function(newStyle)                       {this.style = newStyle;}
}

View_eventDict = {};

function View_createViewEvent(target)
{
    var viewID = target.getViewID();
    View_eventDict[viewID] = target;
    return function() {View_performViewEvent(this, viewID); return false;};
}

function View_performViewEvent(domView, viewID)
{
    var target = View_eventDict[viewID];
    target.performAction(domView);
    return false;
}

View_eventIDDict = {};

function View_createTagIDEvent(target, tag, id)
{
    View_eventIDDict[tag+'_'+id] = target;
    return function() {View_performTagIDEvent(this, tag, id); return false;};
}

function View_performTagIDEvent(domView, tag, id)
{
    var target = View_eventIDDict[tag+'_'+id];
    target.performTagIDAction(domView, tag, id);
    return false;
}

/*--------------------------------------------------------------*/

function DTO_TabView()                          {}

function DTO_TabView_new(viewIDP)
{
    var obj = new DTO_TabView();
    DTO_View_init(obj, viewIDP);
    DTO_TabView_init(obj);
    return obj;
}

function DTO_TabView_init(obj)
{
    obj.selectedTab = null;
    obj.onClickCB = null;
    obj.onCloseCB = null;
    obj.vertical = false;
    obj.width = 0;
    obj.bgColor1 = null;
    obj.bgColor2 = null;
    
    obj.drawSelfPre = function(frag)
    {
        var table, tbody, tr;
        this.clear();
        
        table = document.createElement("table");
        table.border = 1;
        table.className = 'tborder';
        tbody = document.createElement("tbody");
        
        if(!this.vertical)
        {
            tr = document.createElement("tr");
            tr.id = this.getViewID()+'_buttons';
            tbody.appendChild(tr);
        }
        table.appendChild(tbody);
        frag.appendChild(table);
    }
    
    obj.drawSubviewPre = function(frag, subview) 
    {
        var td, frag_tr;
        
        if(this.vertical)
        {
            frag_tr = document.createElement("tr");
            frag_tr.id = this.getViewID()+'_buttons';
            frag.appendChild(frag_tr);
        }
        else
            frag_tr = document.getElementById(this.getViewID()+'_buttons');
        
        td = document.createElement("td");
        td.align = 'center';
        td.vAlign = 'middle';
        td.id = subview.getViewID();
        
        if(subview.getIsOn())
            td.style.backgroundColor = (this.bgColor1 ? this.bgColor1 : '#ff0000');
        else
            td.style.backgroundColor = (this.bgColor2 ? this.bgColor2 : '#00ff00');
        
        frag_tr.appendChild(td);
    }
    
    obj.performAction = function(domView)
    {
        this.doTabClick(domView.value);
    }
    
    obj.setOnClick = function(cb)
    {
        this.onClickCB = cb;
    }
    
    obj.setOnClose = function(cb)
    {
        this.onCloseCB = cb;
    }
    
    obj.view_addSubview = obj.addSubview; 
    obj.addSubview = function(subview)
    {
        this.view_addSubview(subview);
        subview.setGroupOwner(this);
    }
    
    obj.doTabClick = function(tabID)
    {
        this.setSelectedTab(tabID);
        this.onClickCB(tabID);
    }
    
    obj.doTabClose = function(tabID)
    {
        this.onCloseCB(tabID);
    }
    
    obj.setSelectedTab = function(tabID)
    {
        this.selectedTab = null;
        for (var i=0; i<this.subviews.length; i++) 
        {
            var tab = this.subviews[i];
            tab.setIsOn(false);
            if(tab.getViewID() == tabID)
                this.selectedTab = tab;
        }
        if(this.selectedTab)
            this.selectedTab.setIsOn(true);

        this.draw();
    }
    
    obj.selectedTabID = function()
    {   
        if(this.selectedTab)
            return this.selectedTab.getViewID();
        else
            return '';
    }
    
    obj.addTabButton = function(title, buttonURL, viewID)
    {
        var button = DTO_ToggleButton_new(this.viewID + '_' + viewID, title, buttonURL, this.countSubviews());
        this.addSubview(button);
        if(this.countSubviews() == 1)
            this.setSelectedTab(this.viewID + '_' + viewID);
    }
    
    obj.setVertical = function()            {this.vertical = true;}
    obj.setWidth = function(newW)           {this.width = newW;}
    
    obj.setBgColor1 = function(color)       {this.bgColor1 = color;}
    obj.setBgColor2 = function(color)       {this.bgColor2 = color;}
}

/*--------------------------------------------------------------*/

function DTO_ToggleButton()                     {}

function DTO_ToggleButton_new(viewID, title, buttonURL, buttonID)
{
    var obj = new DTO_ToggleButton();
    DTO_View_init(obj, viewID);
    DTO_ToggleButton_init(obj, title, buttonURL, buttonID);
    return obj;
}

function DTO_ToggleButton_init(obj, title, buttonURL, buttonID)
{
    obj.title = title;
    obj.buttonURL = buttonURL;
    obj.buttonID = buttonID;
    obj.isOn = false; 
    obj.onClickCB = null;
    obj.onClickButtonCB = null;
    obj.groupOwner = null;          //controls tabs or radios,forward performAction to it
    
    obj.drawSelfPre = function(frag)
    {
        var a2 = null;
        var a, img, txt, br;
        this.clear();
        
        a = document.createElement("a");
        a.onclick = View_createTagIDEvent(this, 'title', this.buttonID);
        
        if(this.title && this.title.length > 0)
        {
            txt = document.createTextNode(this.title);
            a.appendChild(txt);
        }
        
        if(this.buttonURL && this.buttonURL.length > 0)
        {
            var groupWidth = (this.groupOwner ? this.groupOwner.width : 0);
                
            img = document.createElement("img");
            img.border = 0;
            img.src = this.buttonURL;
            if(groupWidth > 0)
                img.width = groupWidth;
            if(this.onClickButtonCB || this.groupOwner)
            {
                a2 = document.createElement("a");
                a2.onclick = View_createTagIDEvent(this, 'close', this.buttonID);
                a2.appendChild(img);
            }
        }
        
        if(a2)
        {
            frag.appendChild(a);
            frag.appendChild(a2);
        } 
        else
        {
            if(img)
                a.appendChild(img);
            frag.appendChild(a);
        }
    }
    
    obj.performTagIDAction = function(domView, tag, id)
    {   
        if(tag == 'title')
        {
            if(this.groupOwner)
                this.groupOwner.doTabClick(this.getViewID());
            else
                this.onClickCB(domView.value);
        }
        else if(tag == 'close')
        {
            if(this.groupOwner)
                this.groupOwner.doTabClose(this.getViewID());
            else
                this.onClickButtonCB(domView.value);
        }
    }
    
    obj.setOnClick = function(cb)
    {
        this.onClickCB = cb;
    }
    
    obj.setOnButtonClick = function(cb)
    {
        this.onClickButtonCB = cb;
    }
    
    obj.setGroupOwner = function(owner)             {this.groupOwner = owner;}
    obj.setIsOn = function(newOn)                   {this.isOn = newOn;}
    obj.getIsOn = function()                        {return this.isOn;}
}

/*--------------------------------------------------------------*/

function DTO_Table2FieldView()                        {}

function DTO_Table2FieldView_new(viewIDP, prompt)
{
    var obj = new DTO_Table2FieldView();
    DTO_View_init(obj, viewIDP);
    DTO_Table2FieldView_init(obj, prompt);
    return obj;
}

function DTO_Table2FieldView_init(obj, prompt)
{
    obj.prompt = prompt;
    obj.onChangeCB = null;
    obj.suppressCR = true;
    obj.value = '';
    
    obj.drawSelfPre = function(frag)
    {
        var label, txt, input;
        this.clear();
                
        label = document.createElement("label");
        txt = document.createTextNode(this.prompt);
        label.appendChild(txt);
        frag.appendChild(label);
        
        input = document.createElement('input');
        input.type = 'text';
        input.size = 20;
        input.style.width = "140px";
        input.value = ''; //this.value;
        input.name = this.getViewID();
        input.onchange = View_createViewEvent(this);
        input.className = "primary textbox";
        if(this.suppressCR)
            input.onkeypress = function        (keyPress)    {return (keyPress == 13 ? false : true);};
        frag.appendChild(input);
    }
    
    obj.performAction = function(domView)
    {
        this.selected = domView.value;
        this.onChangeCB(domView.value);
    }
    
    obj.setOnChange = function(cb)
    {
        this.onChangeCB = cb;
    }
    
    obj.setValue = function(newVal)         {this.value = newVal;}
}

/*--------------------------------------------------------------*/

function DTO_Table2CheckboxView()                        {}

function DTO_Table2CheckboxView_new(viewIDP, prompt)
{
    var obj = new DTO_Table2CheckboxView();
    DTO_View_init(obj, viewIDP);
    DTO_Table2CheckboxView_init(obj, prompt);
    return obj;
}

function DTO_Table2CheckboxView_init(obj, prompt)
{
    obj.prompt = prompt;
    obj.onChangeCB = null;
    
    obj.drawSelfPre = function(frag)
    {
        var label, txt, input;
        this.clear();
                
        label = document.createElement("label");
        txt = document.createTextNode(this.prompt);
        label.appendChild(txt);
        frag.appendChild(label);
        
        input = document.createElement('input');
        input.type = 'radio';
        input.name = this.getViewID();
        input.value = 'yes';
        input.onchange = View_createViewEvent(this);
        if(this.value == 'yes')
            input.checked = 'checked';
        frag.appendChild(input);
        txt = document.createTextNode('  ' + DTO_Phrase_cachedWithID('yes').phrase + '  ');
        frag.appendChild(txt);
        
        input = document.createElement('input');
        input.type = 'radio';
        input.name = this.getViewID();
        input.value = 'no';
        input.onchange = View_createViewEvent(this);
        if(this.value == 'no')
            input.checked = 'checked';
        frag.appendChild(input);
        txt = document.createTextNode('  ' + DTO_Phrase_cachedWithID('no').phrase + '  ');
        frag.appendChild(txt);
        input = document.createElement('input');
        input.type = 'radio';
        input.name = this.getViewID();
        input.value = 'either';
        input.onchange = View_createViewEvent(this);
        if(this.value == 'either')
            input.checked = 'checked';
        frag.appendChild(input);
        txt = document.createTextNode('  ' + DTO_Phrase_cachedWithID('either').phrase + '  ');
        frag.appendChild(txt);
    }
    
    obj.performAction = function(domView)
    {
        this.selected = domView.value;
        this.onChangeCB(domView.value);
    }
    
    obj.setOnChange = function(cb)
    {
        this.onChangeCB = cb;
    }
    
    obj.setSelected = function(newVal)         {this.value = newVal;}
}

/*--------------------------------------------------------------*/

function DTO_RadioOptionView()                        {}

function DTO_RadioOptionView_new(viewIDP, prompt)
{
    var obj = new DTO_RadioOptionView();
    DTO_RadioOptionView_init(obj, prompt);
    return obj;
}

function DTO_RadioOptionView_init(obj, prompt, owner)
{
    obj.enumID = enumID;
    obj.prompt = prompt;
    obj.owner = owner;
    
    obj.drawSelf = function(frag)
    {
        var txt, input;
        
        input = document.createElement('input');
        input.type = 'radio';
        input.name = this.getViewID();
        input.value = this.enumID;
        input.onchange = View_createViewEvent(this);
        if(this.owner.getValue() == this.enumID)
            input.checked = 'checked';
        frag.appendChild(input);
            
        txt = document.createTextNode(DTO_Phrase_cachedWithID('yes').phrase);
        frag.appendChild(txt);
    }
    
    obj.performAction = function(domView)
    {
        this.selected = domView.value;
        this.onChangeCB(domView.value);
    }
    
    obj.getOwner = function()              {return this.owner;}
    obj.getPrompt = function()             {return this.prompt;}
    obj.getEnumID = function()             {return this.enumID;}
}

/*--------------------------------------------------------------*/

function DTO_Table2RadioGroupView()                        {}

function DTO_Table2RadioGroupView_new(viewIDP, prompt)
{
    var obj = new DTO_Table2RadioGroupView();
    DTO_View_init(obj, viewIDP);
    DTO_Table2RadioGroupView_init(obj, prompt);
    return obj;
}

//bobhack - this code was never completed
//verify drawing, impl callbacks, refactor DTO_Table2CheckboxView
function DTO_Table2RadioGroupView_init(obj, prompt)
{
    obj.prompt = prompt;
    obj.onChangeCB = null;
    obj.options = null;
    
    obj.drawSelfPre = function(frag)
    {
        var td, txt;
        this.clear();
        
        td = document.createElement("td");
        td.align = 'left';
        if(this.style && this.style.length)
            td.className = this.style;
        txt = document.createTextNode(this.prompt);
        td.appendChild(txt);
        frag.appendChild(td);
        
        td = document.createElement("td");
        td.align = 'left';
        if(this.style && this.style.length)
            td.className = this.style;
        for(var i=0; i<this.options.length; i++) 
        {
            var option = this.options[i];
            option.drawSelf(td);
        }
        frag.appendChild(td); 
    }
    
    obj.addRadioOption = function(enumID, prompt)
    {
        this.radios.push
    }
    
    obj.performAction = function(domView)
    {
        this.selected = domView.value;
        this.onChangeCB(domView.value);
    }
    
    obj.setOnChange = function(cb)
    {
        this.onChangeCB = cb;
    }
    
    obj.setSelected = function(newVal)         {this.value = newVal;}
}

/*--------------------------------------------------------------*/

function DTO_Table2LabelView()                        {}

function DTO_Table2LabelView_new(viewIDP, prompt)
{
    var obj = new DTO_Table2LabelView();
    DTO_View_init(obj, viewIDP);
    DTO_Table2LabelView_init(obj, prompt);
    return obj;
}

function DTO_Table2LabelView_init(obj, prompt)
{
    obj.prompt = prompt;
    
    obj.drawSelfPre = function(frag)
    {
        var div, txt
        this.clear();
                
        b = document.createElement("b");
        txt = document.createTextNode(this.prompt);
        
        b.appendChild(txt);

        frag.appendChild(b);

    }
}

/*--------------------------------------------------------------*/

function DTO_Table2PopupView()                        {}

//popupFormatter is a formatter that responds to
//  count()
//  getID(i)
//  getTitle(i)

function DTO_Table2PopupView_new(viewIDP, prompt)
{
    var obj = new DTO_Table2PopupView();
    DTO_View_init(obj, viewIDP);
    DTO_Table2PopupView_init(obj, prompt);
    return obj;
}

function DTO_Table2PopupView_init(obj, prompt)
{
    obj.prompt = prompt;
    obj.formatter = null;
    obj.onChangeCB = null;
    obj.selected = null;
    
    obj.drawSelfPre = function(frag)
    {
        var label, txt;
        var formatter = this.formatter;
        var count = (formatter ? formatter.count(): 0);
        this.clear();
                
        label = document.createElement("label");

        txt = document.createTextNode(this.prompt);
        label.appendChild(txt);
        frag.appendChild(label);
        
        if(count > 0)
        {
            select = document.createElement("select");
            select.onchange = View_createViewEvent(this);
            for (var i=0; i<count; i++)
            {
                var id = formatter.getID(i);
                option = document.createElement("option");
                option.value = id;
                if(id == this.selected)
                    option.selected = 'selected';
                txt = document.createTextNode(formatter.getTitle(i));
                option.appendChild(txt);
                select.appendChild(option);
            }
            
            frag.appendChild(select);
        }
    }
    
    obj.setFormatter = function(newFormatter)               {this.formatter = newFormatter;}
    
    obj.performAction = function(domView)
    {
        this.selected = domView.value;
        this.onChangeCB(domView.value);
    }
    
    obj.setOnChange = function(cb)
    {
        this.onChangeCB = cb;
    }
    
    obj.setSelected = function(newVal)                      {this.selected = newVal;}
}

/*--------------------------------------------------------------*/

function DTO_Table2RangePopupView()                        {}

//popupFormatter is a formatter that responds to
//  count()
//  getID(i)
//  getTitle(i)

function DTO_Table2RangePopupView_new(viewIDP, prompt)
{
    var obj = new DTO_Table2RangePopupView();
    DTO_View_init(obj, viewIDP);
    DTO_Table2RangePopupView_init(obj, prompt);
    return obj;
}

function DTO_Table2RangePopupView_init(obj, prompt)
{
    obj.prompt = prompt;
    obj.lowFormatter = null;
    obj.highFormatter = null;
    obj.onChangeCB = null;
    obj.selectedLow = null;
    obj.selectedHigh = null;
    
    obj.drawSelfPre = function(frag)
    {
        var label, txt, div;
        this.clear();
                
        label = document.createElement("label");
        txt = document.createTextNode(this.prompt);
        label.appendChild(txt);
        frag.appendChild(label);
        
        div = document.createElement("div");
        this.drawPopup(this.lowFormatter, 'low', div, this.selectedLow);
        
        txt = document.createTextNode(' - ');
        div.appendChild(txt);
        
        this.drawPopup(this.lowFormatter, 'high', div, this.selectedHigh);
        
        frag.appendChild(div);
    }
    
    obj.drawPopup = function(formatter, tag, frag, selected)
    {
        var td, txt;
        var count = (formatter ? formatter.count(): 0);
                
        if(count > 0)
        {
            select = document.createElement("select");
            select.onchange = View_createTagIDEvent(this, tag, this.getViewID()); 
            for (var i=0; i<count; i++)
            {
                var id = formatter.getID(i);
                option = document.createElement("option");
                option.value = id;
                if(id == selected)
                    option.selected = 'selected';
                txt = document.createTextNode(formatter.getTitle(i));
                option.appendChild(txt);
                select.appendChild(option);
            }
            
            frag.appendChild(select);
        }
    }
    
    obj.setLowFormatter = function(newFormatter)                    {this.lowFormatter = newFormatter;}
    obj.setHighFormatter = function(newFormatter)                   {this.highFormatter = newFormatter;}
    
    obj.performTagIDAction = function(domView, tag, id)
    {   
        if(tag == 'low')
            this.selectedLow = domView.value;
        else if(tag == 'high')
            this.selectedHigh = domView.value;
        this.onChangeCB(this, tag);
    }
    
    obj.setOnChange = function(cb)                      {this.onChangeCB = cb;}
    obj.getLowValue = function()                        {return this.selectedLow;}
    obj.getHighValue = function()                       {return this.selectedHigh;}
    obj.setLowValue = function(newVal)                  {this.selectedLow = newVal;}
    obj.setHighValue = function(newVal)                 {this.selectedHigh = newVal;}
}

/*--------------------------------------------------------------*/

function DTO_Table2RangeView()                        {}

function DTO_Table2RangeView_new(viewIDP, prompt)
{
    var obj = new DTO_Table2RangeView();
    DTO_View_init(obj, viewIDP);
    DTO_Table2RangeView_init(obj, prompt);
    return obj;
}

function DTO_Table2RangeView_init(obj, prompt)
{
    obj.prompt = prompt;
    obj.onChangeCB = null;
    obj.lowValue = 0;
    obj.highValue = 0;
    
    obj.drawSelfPre = function(frag)
    {
        var label, txt, input;
        this.clear();
                
        label = document.createElement("label");
        txt = document.createTextNode(this.prompt);
        label.appendChild(txt);
        frag.appendChild(label);
        
        input = document.createElement("input");
        input.className = "primary textbox";
        input.type = 'text';
        input.value =  ''; //obj.lowValue;
        input.size = 8;
        input.onchange = View_createTagIDEvent(this, 'low', this.getViewID());
        frag.appendChild(input);
        
        txt = document.createTextNode(' - ');
        frag.appendChild(txt);
        
        input = document.createElement("input");
        input.type = 'text';
        input.value = ''; //obj.highValue;
        input.size = 8;
        input.onchange = View_createTagIDEvent(this, 'high', this.getViewID());
        input.className = "primary textbox";
        frag.appendChild(input);
    }
    
    obj.setOnChange = function(cb)                      {this.onChangeCB = cb;}
    obj.getLowValue = function()                        {return this.lowValue;}
    obj.getHighValue = function()                       {return this.highValue;}
    obj.setLowValue = function(newVal)                  {this.lowValue = newVal;}
    obj.setHighValue = function(newVal)                 {this.highValue = newVal;}
    
    obj.performTagIDAction = function(domView, tag, id)
    {
        if(tag == 'low')
            this.lowValue = domView.value;
        else if(tag == 'high')
            this.highValue = domView.value;
        this.onChangeCB(this);
    }
}

/*--------------------------------------------------------------*/

function DTO_Table2ButtonView()                        {}

function DTO_Table2ButtonView_new(viewIDP, prompt)
{
    var obj = new DTO_Table2ButtonView();
    DTO_View_init(obj, viewIDP);
    DTO_Table2ButtonView_init(obj, prompt);
    return obj;
}

function DTO_Table2ButtonView_init(obj, prompt)
{
    obj.prompt = prompt;
    obj.onClickCB = null;
    
    obj.drawSelfPre = function(frag)
    {
        var td, input;
        this.clear();
                
        input = document.createElement("input");
        input.type = 'submit';
        input.name = obj.viewID;
        input.value = "    " + obj.prompt + "    ";
        input.className = "button";
        input.onclick = View_createViewEvent(this);

        frag.appendChild(input);
    }
    
    obj.performAction = function(domView)               {this.onClickCB(domView.value);}
    obj.setOnClick = function(cb)                       {this.onClickCB = cb;}
}

/*--------------------------------------------------------------*/

function DTO_TableBodyColView()                              {}

function DTO_TableBodyColView_new(viewIDP)
{
    var obj = new DTO_TableBodyColView();
    DTO_View_init(obj, viewIDP);
    DTO_TableBodyColView_init(obj);
    return obj;
}

function DTO_TableBodyColView_init(obj)
{
    obj.columns = [];
    obj.rowData = null;
    obj.altStyle = null;
    obj.selectedRowIndex = -1;
    obj.selectedRowFormatter = null;
    obj.emptyMsg = "Nothing to display.";
    
    obj.addColumn = function(colView)               {this.columns.push(colView);}
    obj.setRowData = function(a)                    {this.rowData = a;}
    
    obj.draw = function()
    {
        this.clear();
        if(this.rowData)
        {
            //debug('top draw '+this.viewID+ ' '+this.columns.length + 'x' + this.rowData.length);
            var frag = this.domNode();
            if(frag)
            {
                this.drawSelfPre(frag);
                var countRow = this.rowData.length;
                var countCol = this.columns.length;
                
                var tr = document.createElement("tr");
                for (var ii=0; ii<countCol; ii++) 
                {
                    var column = this.columns[ii];
                    column.drawTitle(tr);
                }
                frag.appendChild(tr);

                if(countRow > 0)
                {                
                    for (var i=0; i<countRow; i++) 
                    {
                        var row = this.rowData[i];    
                        var tr = document.createElement("tr");
                        if(i % 2 == 0)
                        {
                            if(this.style)
                                tr.className = this.style;   
                        }
                        else
                        {   
                            if(this.altStyle)
                                tr.className = this.altStyle;
                        }
                        if(this.selectedRowIndex == i)
                        {
                            tr.id = this.getViewID() + '_selectedRow';
                            this.selectedRowFormatter.drawFormatted(tr, row);
                        }
                        else
                        {
                            for (var ii=0; ii<countCol; ii++) 
                            {
                                var column = this.columns[ii];
                                column.draw(tr, row);
                            }
                        }
                        frag.appendChild(tr);
                    }
                }
                else
                {
                    var td, txt;
                    tr = document.createElement("tr");
                    td = document.createElement("td");
        
                    td.align = 'center';
                    td.vAlign = 'middle';
                    td.colSpan = countCol;
        
                    txt = document.createTextNode(this.emptyMsg);
        
                    td.appendChild(txt);
                    tr.appendChild(td);
                    frag.appendChild(tr);
                }                   
                
                this.drawSelfPost(frag);
            }
            else
                debug(this.viewID + " can't find viewID in the document");
        }
        else
            debug('top draw '+this.viewID+ ' no rowData');
    }
    
    obj.setAltStyle = function(style)                   {this.altStyle = style;}
    obj.setEmptyMessage = function(str)                 {this.emptyMsg = str;}
    
    obj.setSelectedRowIndex = function(index)           {this.selectedRowIndex = index;}
    obj.setSelectedRowFormatter = function(formatter)   {this.selectedRowFormatter = formatter;}
}

/*--------------------------------------------------------------*/

function DTO_ColumnView()                              {}

//columnFormatter is a formatter that responds to
//  getValue(i)

function DTO_ColumnView_new(viewIDP, title, columnFormatter, style)
{
    var obj = new DTO_ColumnView();
    DTO_View_init(obj, viewIDP);
    DTO_ColumnView_init(obj, title, columnFormatter, style);
    return obj;
}

function DTO_ColumnView_init(obj, title, columnFormatter)
{
    obj.columns = [];
    obj.title = title;
    obj.columnFormatter = columnFormatter;
    obj.align = null;
    obj.sortJS = null;
    
    obj.addColumn = function(colView)                   {this.columns.push(colView);}
    obj.setSortMethod = function(sortJS)                {this.sortJS = sortJS;}
    
    obj.draw = function(frag, row)
    {
        var td = document.createElement("td");
        var value = this.columnFormatter.getValue(row);
        if(this.align)
            td.align = this.align;
        if(this.style && this.style.length)
            td.className = this.style;
        var txt = document.createTextNode(value);
        td.appendChild(txt);
        frag.appendChild(td);
    }
    
    obj.drawTitle = function(frag)
    {
        var td = document.createElement("td");
        td.align = 'center';
        
        if(this.style && this.style.length)
            td.className = this.style;
        
        b = document.createElement("b");
        var txt = document.createTextNode(this.title);
        if(this.sortJS)
        {
            var a = document.createElement("a");
            a.onclick = this.sortJS;
            a.appendChild(b);
            b.appendChild(txt);
            td.appendChild(a);
        }
        else
        {
            b.appendChild(txt);
            td.appendChild(b);
        }
        frag.appendChild(td);
    }
    
    obj.setAlign = function(newAlign)                   {this.align=newAlign;}
}

/*--------------------------------------------------------------*/

function DTO_ColumnDrawView()                              {}

//columnFormatter is a formatter that responds to
//  draw(domFrag, row)

function DTO_ColumnDrawView_new(viewIDP, title, columnFormatter)
{
    var obj = new DTO_ColumnDrawView();
    DTO_View_init(obj, viewIDP);
    DTO_ColumnDrawView_init(obj, title, columnFormatter);
    return obj;
}

function DTO_ColumnDrawView_init(obj, title, columnFormatter)
{
    obj.columns = [];
    obj.title = title;
    obj.columnFormatter = columnFormatter;
    obj.align = null;
    obj.sortJS = null;
    
    obj.addColumn = function(colView)                   {this.columns.push(colView);}
    obj.setSortMethod = function(sortJS)                {this.sortJS = sortJS;}
    
    obj.draw = function(frag, row)
    {
        var td = document.createElement("td");
        if(this.align)
            td.align = this.align;
        if(this.style && this.style.length)
            td.className = this.style;
        this.columnFormatter.draw(td, row);
        frag.appendChild(td);
    }
    
    obj.drawTitle = function(frag)
    {
        var td = document.createElement("td");
        td.align = 'center';
        if(this.style && this.style.length)
            td.className = this.style;
        b = document.createElement("b");
        var txt = document.createTextNode(this.title);
        if(this.sortJS)
        {
            var a = document.createElement("a");
            a.onclick = this.sortJS;
            a.appendChild(b);
            b.appendChild(txt);
            td.appendChild(a);
        }
        else
        {
            b.appendChild(txt);
            td.appendChild(b);
        }
        frag.appendChild(td);
    }
    
    obj.setAlign = function(newAlign)                   {this.align=newAlign;}
}

/*--------------------------------------------------------------*/

function DTO_TableBodyRowView()                              {}

//rowFormatter builds out complex rows
//  draw(frag, row)

function DTO_TableBodyRowView_new(viewIDP, rowFormatter)
{
    var obj = new DTO_TableBodyRowView();
    DTO_View_init(obj, viewIDP);
    DTO_TableBodyRowView_init(obj, rowFormatter);
    return obj;        
}

function DTO_TableBodyRowView_init(obj, rowFormatter)
{
    obj.rowFormatter = rowFormatter;
    obj.rowData = null;
    obj.altStyle = null;
    
    obj.setRowData = function(a)                    {this.rowData =  a;}
    
    obj.draw = function()
    {
        this.clear();
        if(this.rowData)
        {
            //debug('top draw '+this.viewID+ ' '+ this.rowData.length);
            var frag = this.domNode();
            if(frag)
            {
                this.drawSelfPre(frag);
                var countRow = this.rowData.length;
                
                for (var i=0; i<countRow; i++) 
                {
                    var row = this.rowData[i];    
                    var tr = document.createElement("tr");
                    if(i % 2 == 0)
                    {
                        if(this.style)
                            tr.className = this.style;   
                    }
                    else
                    {   
                        if(this.altStyle)
                            tr.className = this.altStyle;
                    }
                    rowFormatter.draw(tr, row);
                    
                    frag.appendChild(tr);
                }
                this.drawSelfPost(frag);
            }
            else
                debug(this.viewID + " can't find viewID in the document");
        }
        else
            debug('top draw '+this.viewID+ ' no rowData');
    }
    
    obj.setAltStyle = function(style)               {this.altStyle = style;}
}


/*--------------------------------------------------------------*/

function DTO_TableBodyRowFormatterAbstract()                              {}

function DTO_TableBodyRowFormatterAbstract_new()
{
    var obj = new DTO_TableBodyRowFormatterAbstract();
    DTO_TableBodyRowFormatterAbstract_init(obj);
    return obj;
}

function DTO_TableBodyRowFormatterAbstract_init(obj)
{
    obj.style = null;
    
    obj.getStyle = function()                               {return this.style;}
    obj.setStyle = function(newStyle)                       {this.style = newStyle;}
    
    obj.drawRow = function(frag, title, value, alignValue)
    {
        var tr, td1, td2, txt1, txt2;
        
        tr = document.createElement("tr");
       
        td1 = document.createElement('td');
        td2 = document.createElement('td');
        td1.align = 'left';
        td2.align = 'left';        
        if(alignValue && alignValue.length)
            td2.align = alignValue;
        if(this.style && this.style.length)
        {
            td1.className = this.style;
            td2.className = this.style;
        }
        txt1 = document.createTextNode(title);
        txt2 = document.createTextNode(value);
        
        td1.appendChild(txt1);
        td2.appendChild(txt2);
        
        tr.appendChild(td1);
        tr.appendChild(td2);
        
        frag.appendChild(tr);
    }
    
    obj.drawCell = function(frag, title, value, alignValue)
    {
        var td1, td2, txt1, txt2;
        
        td1 = document.createElement('td');
        td2 = document.createElement('td');
        td1.align = 'left';
        td2.align = 'left';
        if(alignValue && alignValue.length)
            td2.align = alignValue;
        if(this.style && this.style.length)
        {
            td1.className = this.style;
            td2.className = this.style;
        }
        
        txt1 = document.createTextNode(title);
        txt2 = document.createTextNode(value);
        
        td1.appendChild(txt1);
        td2.appendChild(txt2);
        
        frag.appendChild(td1);
        frag.appendChild(td2);
    }
}

/*--------------------------------------------------------------*/

function DTO_TableBodyGridView()                              {}

//cellFormatter builds out complex table cells, frag is a tr
//  drawCell(frag, obj)

function DTO_TableBodyGridView_new(viewIDP, cellFormatter, rowWidth)
{
    var obj = new DTO_TableBodyGridView();
    DTO_View_init(obj, viewIDP);
    DTO_TableBodyGridView_init(obj, cellFormatter, rowWidth);
    return obj;
}

function DTO_TableBodyGridView_init(obj, cellFormatter, rowWidth)
{
    obj.cellFormatter = cellFormatter;
    obj.rowWidth = rowWidth;
    obj.rowData = null;
    obj.altStyle = null;
    obj.emptyMsg = "Nothing to display.";
    
    obj.setRowData = function(a)                    {this.rowData =  a;}
    
    obj.draw = function()
    {
        this.clear();
        if(this.rowData)
        {
            //debug('top draw '+this.viewID+ ' '+ this.rowData.length);
            var frag = this.domNode();
            if(frag)
            {
                this.drawSelfPre(frag);
                var countRow = this.rowData.length;
                var tr = null;
                
                if(countRow > 0)
                {
                    for (var i=0; i<countRow; i++) 
                    {
                        var obj = this.rowData[i];    
                        if(i % this.rowWidth == 0)
                        {
                            if(i > 0)
                                frag.appendChild(tr);
                            tr = document.createElement("tr");                    
                            /* doesn't seem to be needed for grids                        
                            if(i / this.rowWidth % 2 == 0)
                            {                 
                                if(this.style)
                                    tr.className = this.style;
                            }
                            else
                            {   
                                if(this.altStyle)
                                    tr.className = this.altStyle;
                            }   
                            */
                        }
                        this.cellFormatter.drawCell(tr, obj);
                    }
                    if(countRow)
                    {
                        var padCells = this.rowWidth - countRow % this.rowWidth ; 
                        if(padCells > 0)
                        {            
                            var td = document.createElement("td");
                            td.align = 'left';
                            td.colSpan = padCells;
                            tr.appendChild(td);    
                        }
                        frag.appendChild(tr);
                        this.drawSelfPost(frag);
                    }            
                }
                else
                {
                    var td, txt;
                    tr = document.createElement("tr");
                    td = document.createElement("td");
        
                    td.align = 'center';
                    td.vAlign = 'middle';
        
                    txt = document.createTextNode(this.emptyMsg);
        
                    td.appendChild(txt);
                    tr.appendChild(td);
                    frag.appendChild(tr);
                }            
            }
            else
                debug(this.viewID + " can't find viewID in the document");
        }
        else
            debug('top draw '+this.viewID+ ' no rowData');
    }
    
    obj.setAltStyle = function(style)               {this.altStyle = style;}
    
    obj.setEmptyMessage = function(str)             {this.emptyMsg = str;}
}

/*--------------------------------------------------------------*/

function DTO_TableBodyGridFormatterAbstract()                  {}

function DTO_TableBodyGridFormatterAbstract_new()
{
    var obj = new DTO_TableBodyGridFormatterAbstract();
    DTO_TableBodyGridFormatterAbstract_init(obj);
    return obj;
}

function DTO_TableBodyGridFormatterAbstract_init(obj)
{
    obj.drawCell = function(frag, obj)
    {
        //placeholder class for util methods
    }
}

/*--------------------------------------------------------------*/

function DTO_ImageView()                        {}

function DTO_ImageView_new(viewIDP, url)
{
    var obj = new DTO_ImageView();
    DTO_View_init(obj, viewIDP);
    DTO_ImageView_init(obj, url);
    return obj;
}

function DTO_ImageView_init(obj, url)
{
    obj.url = url;
    
    obj.drawSelfPre = function(frag)
    {
        this.clear();
        
        if(this.url && this.url.length > 0)
        {
            var img;
            img = document.createElement("img");
            img.border = 0;
            img.src = this.url;
            frag.appendChild(img);
        }    
    }
    
    obj.setURL = function(newStr)             {this.url = newStr;}
    
}

/*--------------------------------------------------------------*/

function DTO_LightboxView()                        {}

function DTO_LightboxView_new(viewIDP, group, width, height)
{
    var obj = new DTO_LightboxView();
    DTO_View_init(obj, viewIDP);
    DTO_LightboxView_init(obj, group, width, height);
    return obj;
}

function DTO_LightboxView_init(obj, group, width, height)
{
    obj.group = group;
    obj.width = width;
    obj.height = height;
    obj.images = [];
    
    //initLytebox();
    
    obj.drawSelfPre = function(frag)
    {
        var i, count = this.images.length;
        
        this.clear();
        
        if(count)
        {
            var table, tbody, tr, td, a, img, image;
            
            table = document.createElement('table');
            table.border = 0;
            tbody = document.createElement('tbody');
            
            for(i=0; i<count; i++)
            {
                image = this.images[i];
                
                tr = document.createElement('tr');
                td = document.createElement('td');
                td.align = 'left';
                a = document.createElement('a');
                img = document.createElement('img');
                
                a.href = image.url;
                a.rel = 'lytebox['+ this.group+']';
                a.title = image.title;
                
                img.border = 0;
                img.src = image.url;
                img.width = this.width;
                img.height = this.height;
            
                a.appendChild(img);
                td.appendChild(a);
                tr.appendChild(td);
                tbody.appendChild(tr);
            }
            
            table.appendChild(tbody);
            frag.appendChild(table);
        }
        
        myLytebox.updateLyteboxItems();
    }
    
    obj.addImage = function(url, title)
    {
        var i = new Object();
        i.url = url;
        i.title = title;
        this.images.push(i);
    }
    
    obj.clearImages = function()
    {
        Array_clear(this.images);
    }
}


/*--------------------------------------------------------------*/

function DTO_BodyFloatView()                              {}

//cellFormatter builds out complex table cells, frag is a tr
//  drawCell(frag, obj)

function DTO_BodyFloatView_new(viewIDP, cellFormatter)
{
    var obj = new DTO_BodyFloatView();
    DTO_View_init(obj, viewIDP);
    DTO_BodyFloatView_init(obj, cellFormatter);
    return obj;
}

function DTO_BodyFloatView_init(obj, cellFormatter)
{
    obj.cellFormatter = cellFormatter;
    obj.rowData = null;
    obj.emptyMsg = "Nothing to display.";
    
    obj.setRowData = function(a)                    {this.rowData =  a;}
    
    obj.draw = function()
    {
        this.clear();
        if(this.rowData)
        {
            //debug('top draw '+this.viewID+ ' '+ this.rowData.length);
            var frag = this.domNode();
            if(frag)
            {
                this.drawSelfPre(frag);
                var countRow = this.rowData.length;
                var li = null;
                var container;
                var title;
                var username;
                
                if(countRow > 0)
                {
                    for (var i=0; i<countRow; i++) 
                    {
                        var obj = this.rowData[i];    
                        li = document.createElement("li");  
                        
                        this.cellFormatter.draw(li, obj)
            
                        frag.appendChild(li);
                    }           
                }
                else
                {
                    //li = document.createElement("li");
        
                    div = document.createElement("div");
                    div.style.padding="20px";
                    txt = document.createTextNode(this.emptyMsg);
                    div.appendChild(txt);
                    frag.appendChild(div);
                }  
            }
            else
                debug(this.viewID + " can't find viewID in the document");
        }
        else
            debug('top draw '+this.viewID+ ' no rowData');
    }
    
    obj.setEmptyMessage = function(str)             {this.emptyMsg = str;}
}

