////////////////////////////////////////////////////////////////////////////
// Globals
////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////
// Resources
////////////////////////////////////////////////////////////////////////////
// common
var _vlHomePage = "WEB_CONSOLE_URL";
var INPUT_ACTION = "action";
var INPUT_ENCODEDSTRING = "_in_";
var _encodedKey = "SETTINGS_SECURITY_KEY";
var INPUT_IE_NOCACHE = "nc";

// registration
var INPUT_TLID = "tlid";
var INPUT_NAME = "name";
var INPUT_COMPANY = "company";
var INPUT_TITLE = "title";
var INPUT_DEPARTMENT = "dept";
var INPUT_DIVISION = "dvsn";
var INPUT_EMAIL = "email";
var INPUT_PHONE = "phn";
var INPUT_PASSWORD = "pwd";

// search
var INPUT_SEARCH_FOR = "searchfor";
var INPUT_ENVIRONMENT_ID = "eid";
var _sfOneFolder = "SEARCH_ONE_FOLDER";
var INPUT_FOLDERID = "folderId";
var INPUT_FOLDER_NAME = "folderName";
var INPUT_VIRTUAL_LIBRARY = "VirtualLibrary";
var INPUT_OLD_VIRTUAL_LIBRARY = "VirtualLibraryOldName";
var INPUT_CONTENTS = "contents";
var INPUT_SORT_FIELD = "sort_by";
var _sortByUnsorted = "VALUE_SORT_UNSORTED";
var INPUT_SORT_DIRECTION = "sort_dir";
var INPUT_SEARCHALLFIELDS = "search_in_all_fields";
var INPUT_SEARCHINABSTRACT = "search_also_in_abstract"


var INPUT_TIMEZONE_OFFSET = "timezone_offset";
var INPUT_USER_TIME = "user_time";


// paging
var INPUT_PAGENUM = "pagenum";
var INPUT_PERPAGE = "perpage";

// VLSettings
    // Settings - Store Value
var _settingsKeyName = "INPUT_SETTINGS_KEY";
var _settingsValueName = "INPUT_SETTINGS_VALUE";
    // Library Settings
var INPUT_VL_ADDR = "vl_addr";
var INPUT_VL_DOMAIN = "vl_domain";
var INPUT_CHANGE_VL_ADDR = "to_vl_addr";
var INPUT_CHANGE_VL_DOMAIN = "to_vl_domain";
    // Dispplay Settings
var INPUT_VIEW_ORGANIZER = "view_organizer";
var INPUT_VIEW_RESINNEW = "view_resinnew";
    // Console Settings
var INPUT_UPDATE_ORGTIMEOUT = "org_timeout";

// VL Configure
var INPUT_ADMIN_PERMISSIONS = "admin_perm";
var INPUT_VL_PERMISSIONS = "vl_perm";
var VLU_PTOP_AUTOREGISTERUSER = "QUOSAServer_AutoRegisterUsers";
var VLU_PROP_DEFAULTPERMISSIONS = "QUOSAServer_DefaultPermissions";
var INPUT_ADMIN_USE_AS_DEFAULT = "use_as_deafult";
var PUBLISH_PROP_METHOD = "QUOSAServer_PublishMethod";
var PUBLISH_PROP_ALLOWPUBLISH = "QUOSAServer_AllowPublish";
var INPUT_UPLOADED_FILENAME = "uploadedfile";
var INPUT_STORE_BACKUP_TIME = "vl_store_backup_time";
var INPUT_STORE_BACKUP_DIR = "vl_store_backup_dir";
var INPUT_STORE_BACKUP_USE_REMOTE = "vl_store_backup_use_remote";
var INPUT_STORE_BACKUP_UPN = "vl_store_backup_upn";
var INPUT_STORE_BACKUP_PWD = "vl_store_backup_pwd";
var INPUT_STORE_BACKUP_ZIP = "vl_store_backup_zip";

// Fodler Management
var _vlFolderName = "INPUT_FOLDER_NAME";
var _vlFolderOwnerName = "INPUT_FOLDER_OWNERNAME";
var _vlFolderOwnerEMail = "INPUT_FOLDER_OWNEREMAIL";

////////////////////////////////////////////////////////////////////////////
// Notification
////////////////////////////////////////////////////////////////////////////
var VL_NOTIFY_FIRST                  = 20000;

// VLConfServerAddr
var VLCONFN_FIRST                    = VL_NOTIFY_FIRST + 100;
var VLCONFN_ONTESTBTN_CLICK          = VLCONFN_FIRST + 1;
var VLCONFN_ONRESETBTN_CLICK         = VLCONFN_FIRST + 2;

// Organizer
var VLN_ORGANIZER_FIRST              = VL_NOTIFY_FIRST + 200;
var VLN_ORGANIZER_VL_ROOT_CLICK      = VLN_ORGANIZER_FIRST + 1;
var VLN_ORGANIZER_VL_ITEM_CLICK      = VLN_ORGANIZER_FIRST + 2;
var VLN_ORGANIZER_FOLDER_ITEM_CLICK  = VLN_ORGANIZER_FIRST + 3;
var VLN_ORGANIZER_ALERT_ITEM_CLICK   = VLN_ORGANIZER_FIRST + 4;
var VLN_ORGANIZER_FILTER_ITEM_CLICK  = VLN_ORGANIZER_FIRST + 5;
var VLN_ORGANIZER_ON_INSERT_FOLDER   = VLN_ORGANIZER_FIRST + 10;
var VLN_ORGANIZER_ON_MODIFY_FOLDER   = VLN_ORGANIZER_FIRST + 11;
var VLN_ORGANIZER_ON_DELETE_FOLDER   = VLN_ORGANIZER_FIRST + 12;

// VL Control
var VLCTRLLIBN_FIRST                 = VL_NOTIFY_FIRST + 300;
var VLCTRLLIBN_CHANGED               = VLCTRLLIBN_FIRST + 1;
var VLCTRLLIBN_INSERTED              = VLCTRLLIBN_FIRST + 2;
var VLCTRLLIBN_DELETED               = VLCTRLLIBN_FIRST + 3;

// Sort Control
var VLCTRLSORTN_FIRST                 = VL_NOTIFY_FIRST + 400;
var VLCTRLSORTN_ITEM_ISERTED          = VLCTRLSORTN_FIRST + 1;
var VLCTRLSORTN_ITEM_DELETING         = VLCTRLSORTN_FIRST + 2;
var VLCTRLSORTN_ITEM_DELETED          = VLCTRLSORTN_FIRST + 3;
var VLCTRLSORTN_ITEM_STATE_CHANGED    = VLCTRLSORTN_FIRST + 4;
var VLCTRLSORTN_ITEM_CLICKED          = VLCTRLSORTN_FIRST + 5;
var VLCTRLSORTN_CHANGED               = VLCTRLSORTN_FIRST + 6;

// Search
var VLN_SEARCH                       = VL_NOTIFY_FIRST + 500;
var VLN_SEARCH_SUBMIT                = VLN_SEARCH + 1;
var VLN_SEARCH_ACTION_CLICK          = VLN_SEARCH + 2;

// Register
var VLN_REGISTER_FIRST               = VL_NOTIFY_FIRST + 600;
var VLN_REGISTER_LOGON               = VLN_REGISTER_FIRST + 1;
var VLN_REGISTER_REGISTER            = VLN_REGISTER_FIRST + 2;

// Search Results
var VLN_SEARCH_RESULTS_FIRST           = VL_NOTIFY_FIRST + 700;
var VLN_SEARCH_RESULTS_ONFOLDERCLICK   = VLN_SEARCH_RESULTS_FIRST + 1;
var VLN_SEARCH_RESULTS_PAGING_SUBMIT   = VLN_SEARCH_RESULTS_FIRST + 2;
var VLN_SEARCH_RESULTS_SORT_CHANGED    = VLN_SEARCH_RESULTS_FIRST + 3;
var VLN_SEARCH_RESULTS_EXPORTEN_SUBMIT = VLN_SEARCH_RESULTS_FIRST + 4;
var VLN_SEARCH_RESULTS_PERPAGE_CHANGED = VLN_SEARCH_RESULTS_FIRST + 5;

// Ask Server Message Box
var VLN_ASKSRVMSG_FIRST              = VL_NOTIFY_FIRST + 800;
var VLN_ASKSRVMSG_BUTTON_CLICK       = VLN_ASKSRVMSG_FIRST + 1;

// VLOtherFields
var VLN_OTHERFIELDS_FIRST            = VL_NOTIFY_FIRST + 900;
var VLN_OTHERFIELDS_HEIGHT_CHANGED   = VLN_OTHERFIELDS_FIRST + 1;

// VLSearchForm
var VLN_SEARCHFORM_FIRST             = VL_NOTIFY_FIRST + 950;
var VLN_SEARCHFORM_SUBMIT            = VLN_SEARCHFORM_FIRST + 1;

// VL Permissions
var VL_PERMISSONS_FULLCONTROL       = 0xFF;
var VL_PERMISSONS_VIEW              = 0x01;
var VL_PERMISSONS_CREATE            = (VL_PERMISSONS_VIEW | 0x02);
var VL_PERMISSONS_MODIFY            = (VL_PERMISSONS_VIEW | 0x04);
var VL_PERMISSONS_DELETE            = (VL_PERMISSONS_VIEW | 0x08);

////////////////////////////////////////////////////////////////////////////
// Common Functions
////////////////////////////////////////////////////////////////////////////
VLCommon = function()
{
}

////////////////////////////////////////////////////////////////////////////
// vlPermToString
////////////////////////////////////////////////////////////////////////////
VLCommon.vlPermToString = function(perm)
{
    var retVal = perm;
    
    if ( typeof perm == "string" )
    {
        perm = parseInt(perm);
        if ( isNaN(perm) )
        {
            return retVal;
        }
    }
    
    switch ( perm )
    {
    case 0:
        retVal = "member";
        break;
    case 1:
        retVal = "reviewer";
        break;
    case 2:
        retVal = "none";
        break;
    case 3:
        retVal = "curator";
        break;
    }
    
    return retVal;
}

////////////////////////////////////////////////////////////////////////////
// vlIsDenied
////////////////////////////////////////////////////////////////////////////
VLCommon.vlIsDenied = function(perm)
{
    return (perm == 2);
}

////////////////////////////////////////////////////////////////////////////
// validVLName
////////////////////////////////////////////////////////////////////////////
VLCommon.validVLName = function(str)
{
    str = AP.trim(str);
    if ( !str.length )
    {
        return false;
    }
    var reg = /[\\/:*?<>|]/;
    if ( reg.test(str) == true )
    {
        return false;
    }
    return str;
}

////////////////////////////////////////////////////////////////////////////
// validVLFolderName
////////////////////////////////////////////////////////////////////////////
VLCommon.validVLFolderName = function(folderName)
{
    return VLCommon.validVLName(folderName);
}

////////////////////////////////////////////////////////////////////////////
// fullSrvAddr
////////////////////////////////////////////////////////////////////////////
VLCommon.fullSrvAddr = function(addr)
{
    if ( !addr.length )
    {
        return "";
    }
    
    var retVal = addr.toLowerCase();
    retVal = AP.trim(retVal);
    
    if ( retVal.indexOf("http://") != 0 && retVal.indexOf("https://") != 0 )
    {
        retVal = "http://" + retVal;
    }
    if ( retVal.charAt(retVal.length - 1) != "/" )
    {
        retVal += "/";
    }
    
    return retVal;
}

////////////////////////////////////////////////////////////////////////////
// tvGetCheckedOrSelected
////////////////////////////////////////////////////////////////////////////
VLCommon.tvGetCheckedOrSelected = function(tv)
{
    var ret = [];
    var ret = tv.checked();
    if ( !ret.length )
    {
        ret = tv.selected();
        if ( !ret.length )
        {
            var focused = tv.focused();
            if ( focused != TV_ROOT_ITEM_ID )
            {
                ret = [focused];
            }
        }
    }
    return ret;
}

////////////////////////////////////////////////////////////////////////////
// guestName
////////////////////////////////////////////////////////////////////////////
VLCommon.guestName = function(str)
{
    if ( AP.is_set(str) )
    {
        return (str.toLowerCase() == "guest");
    }
    return "guest";
}

////////////////////////////////////////////////////////////////////////////
// guestId
////////////////////////////////////////////////////////////////////////////
VLCommon.guestId = function(str)
{
    if ( AP.is_set(str) )
    {
        return (str.toLowerCase() == "built-in account for guest access");
    }
    
    return "built-in account for guest access";
}

////////////////////////////////////////////////////////////////////////////
// guestEMail
////////////////////////////////////////////////////////////////////////////
VLCommon.guestEMail = function(str)
{
    return VLCommon.guestId(str);
}

////////////////////////////////////////////////////////////////////////////
// isBuiltInUser
////////////////////////////////////////////////////////////////////////////
VLCommon.isBuiltInUser = function(email)
{
    if ( !AP.is_set(email) )
    {
        return false;
    }
    
    return (email.toLowerCase().indexOf("built-in account") != -1 ? true : false);
}

////////////////////////////////////////////////////////////////////////////
// rssId
////////////////////////////////////////////////////////////////////////////
VLCommon.rssId = function(str)
{
    if ( AP.is_set(str) )
    {
        return (str.toLowerCase() == "built-in account for rss links");
    }
    
    return "built-in account for rss links";
}

////////////////////////////////////////////////////////////////////////////
// rssEMail
////////////////////////////////////////////////////////////////////////////
VLCommon.rssEMail = function(str)
{
    return VLCommon.rssId(str);
}

////////////////////////////////////////////////////////////////////////////
// dlinkId
////////////////////////////////////////////////////////////////////////////
VLCommon.dlinkId = function(str)
{
    if ( AP.is_set(str) )
    {
        return (str.toLowerCase() == "built-in account for dynamic links");
    }
    
    return "built-in account for dynamic links";
}

////////////////////////////////////////////////////////////////////////////
// dlinkEMail
////////////////////////////////////////////////////////////////////////////
VLCommon.dlinkEMail = function(str)
{
    return VLCommon.dlinkId(str);
}

////////////////////////////////////////////////////////////////////////////
// class VLCtrlSort extends AP
////////////////////////////////////////////////////////////////////////////
// VLCtrlSort DOM
////////////////////////////////////////////////////////////////////////////
/*
<div class="vl_ctrl_sort">
    <table>
        <tr>
            <td align="right" valign="middle">
                Sort By:
            </td>
        </tr>
        <tr>
            <td align="left" valign="middle">
                <span><img class="vl_ctrl_sort_img"></span>
            </td>
        </tr>
    </table>
</div>
WndBorder {
        <table class="vlsort_items_container" cellpadding="0" cellspacing="0">
            <tbody>
                <tr class="vlsort_item">
                    <td class="vlsort_sub_item_check" align="center" valign="middle">
                        <div><img src="img/sort/check_item.gif"></div>
                    </td>
                    <td class="vlsort_sub_item_value" valign="middle" nowrap>
                        <span>kakoy-to tekst</span>
                    </td>
                </tr>
                .......
                <tr class="vlsort_separator_item">
                    <td class="vlsort_sub_item_sep" align="center" valign="middle" colspan="2">
                        <hr>
                    </td>
                </tr>
                <tr class="vlsort_item">
                    <td class="vlsort_sub_item_check" align="center" valign="middle">
                        <div><img src="img/sort/check_dir.gif"></div>
                    </td>
                    <td class="vlsort_sub_item_value" valign="middle" nowrap>
                        <span>forward</span>
                    </td>
                </tr>
                <tr class="vlsort_item">
                    <td class="vlsort_sub_item_check" align="center" valign="middle">
                        <div><img src="img/sort/check_dir.gif"></div>
                    </td>
                    <td class="vlsort_sub_item_value" valign="middle" nowrap>
                        <span>backward</span>
                    </td>
                </tr>
            </tbody>
        </table>
}
*/
// states
var VLCTRLSORTS_OVER                    = 0x01;
var VLCTRLSORTS_DROPDOWN                = 0x02;
// item states
var VLCTRLSORTIS_OVER                   = 0x01;
var VLCTRLSORTIS_DISABLED               = 0x02;
////////////////////////////////////////////////////////////////////////////
// constructor
////////////////////////////////////////////////////////////////////////////
VLCtrlSort = function()
{
    this.subclass = AP;
    this.subclass();
    
    this.popup = new WndBorder();
    this.items_container = null;
    this.items_bd = null;
    
    this.indexForward = -1;
    this.indexBackward = -1;
    
    this.sortValue = {
        field: "",
        direction: 0
    };

    this.className = "VLCtrlSort";  
}
VLCtrlSort.prototype = new AP;

////////////////////////////////////////////////////////////////////////////
// create
////////////////////////////////////////////////////////////////////////////
VLCtrlSort.prototype.create = function(parent)
{
    this.subclass = AP.prototype.create;
    this.subclass(parent, "vl_ctrl_sort");   
    AP.addEvent(this.element, "mouseover", VLCtrlSort.onMouseEvent);
    AP.addEvent(this.element, "mouseout", VLCtrlSort.onMouseEvent);
    AP.addEvent(this.element, "mousedown", VLCtrlSort.onPressDropDown);
    
    var cells = [[[
        null,
        [
            [null, null, null, "right", "middle"],
            [null, null, null, "left", "middle"]
        ]
    ]]];
    this.tbl = AP.createTable(2, 0, cells, this.element);
    this.tbl.tBodies[0].rows[0].cells[0].innerHTML = "Sort By:";
    
    this.spanImg = AP.createElement("span", this.tbl.tBodies[0].rows[0].cells[1]);
    this.img = AP.createElement("img", this.spanImg, "vl_ctrl_sort_img");
    this.img.src = ROOT_PATH + "img/sort/btn.gif";
    AP.width(this.img, 15);
    AP.height(this.img, 16);
    
    this.popup.create(document.body, null, WND_FLAGS_MODAL | WND_FLAGS_HIDDEN | WND_FLAGS_POPUP | WND_FLAGS_BORDER | WND_FLAGS_VRESIZE | WND_FLAGS_HRESIZE);
    this.popup.element.className += " ctrl_sort_wnd";
    this.popup.ctrlSort = this;
    AP.addEvent(this.popup.element, "mousedown", VLCtrlSort.onPopUpMouseAction);
    
    var cells = [[  ]];
    this.items_container = AP.createTable(0, 2, cells, null, "vlsort_items_container");
    this.items_bd = this.items_container.tBodies[0];
    this.popup.assignChild(this.items_container);

    this.setPosition({flags: POS_FLAGS_RECALCULATE});
    this.tabIndex(0);
}

////////////////////////////////////////////////////////////////////////////
// setPosition
////////////////////////////////////////////////////////////////////////////
VLCtrlSort.prototype.setPosition = function(pos)
{
    this.subclass = AP.prototype.setPosition;
    this.subclass(pos);
}

////////////////////////////////////////////////////////////////////////////
// value
////////////////////////////////////////////////////////////////////////////
/*
var newValue = {
    field: string,
    direction: bool,
    do_not_notify: bool
}
*/
VLCtrlSort.prototype.value = function(newValue)
{
    if ( AP.is_set(newValue) )
    {
        var changed = false;
        
        if ( AP.is_set(newValue.field) )
        {
            if ( this.sortValue.field != newValue.field )
            {
                this.sortValue.field = newValue.field;
                changed = true;
            }
        }
        if ( AP.is_set(newValue.direction) )
        {
            if ( this.sortValue.direction != newValue.direction )
            {
                this.sortValue.direction = newValue.direction;
                changed = true;
            }
        }
        
        if ( changed && !AP.is_set(newValue.do_not_notify, false) )
        {
            this.fireNotify(VLCTRLSORTN_CHANGED, this.sortValue);
        }
        
        // Check Items
        // Field
        for ( var loop = 0; loop < this.indexSeparator; loop++ )
        {
            var trItem = this._getItem(loop);
            var check = (trItem.value == this.sortValue.field);
            this._checkItem(loop, check);
        }
        // Direction
        this._checkItem(this.indexForward, (this.sortValue.direction == 0));
        this._checkItem(this.indexBackward, (this.sortValue.direction != 0));
    }
    
    return this.sortValue;
}

////////////////////////////////////////////////////////////////////////////
// tabIndex
////////////////////////////////////////////////////////////////////////////
VLCtrlSort.prototype.tabIndex = function(tabIndex)
{
    if ( AP.is_set(tabIndex) )
    {
        this.img.tabIndex = tabIndex;
    }
    return AP.is_set(tabIndex, -1);
}

////////////////////////////////////////////////////////////////////////////
// dropdown
////////////////////////////////////////////////////////////////////////////
VLCtrlSort.prototype.dropdown = function(visible)
{
    if ( visible )
    {
        this.popup.dropdown(this.element, 0);
        this.state( this.state() | VLCTRLSORTS_DROPDOWN );
        
        var divPopUpClientWidth = AP.clientWidth( this.popup.childArea() );
        if ( AP.offsetWidth(this.items_container) < divPopUpClientWidth )
        {
            AP.width(this.items_container, divPopUpClientWidth);
            if ( this.getItemCount() )
            {
                this.items_bd.rows[0].cells[1].style.width = "99%";
            }
        }
    }
    else
    {
        this.popup.hide();
        this.state( this.state() & ~VLCTRLSORTS_DROPDOWN );
        
        AP.width(this.items_container, "auto");
        if ( this.getItemCount() )
        {
            this.items_bd.rows[0].cells[1].style.width = "auto";
        }
    }
}

////////////////////////////////////////////////////////////////////////////
// updateItems
////////////////////////////////////////////////////////////////////////////
/*
var items = [
    {
       text: Display text,
       value: internal value for lucene
    },
    ................
];
*/
VLCtrlSort.prototype.updateItems = function(items)
{
    this.deleteAll();

    this.appendItem({img: ROOT_PATH + "img/sort/check_sort.gif", text: "Unsorted", value: _sortByUnsorted});
    
    for ( var loop = 0; loop < items.length; loop++ )
    {
        this.appendItem({
            img: ROOT_PATH + "img/sort/check_sort.gif",
            text: items[loop].text,
            value: items[loop].value
        });
    }
    
    this.indexSeparator = this.appendItem({separator: true});
    
    this.indexForward = this.appendItem({img: ROOT_PATH + "img/sort/check_dir.gif", text: "Ascending", value: "forward"});
    this.indexBackward = this.appendItem({img: ROOT_PATH + "img/sort/check_dir.gif", text: "Descending", value: "backward"});
    
    this.value(this.value);
}

////////////////////////////////////////////////////////////////////////////
// getItemCount
////////////////////////////////////////////////////////////////////////////
VLCtrlSort.prototype.getItemCount = function()
{
    return this.items_bd.rows.length;
}

////////////////////////////////////////////////////////////////////////////
// appendItem
////////////////////////////////////////////////////////////////////////////
/*
var itemParam = {
    value: "PMID",
    text: "PubMed Id",
    separator: bool
}
*/
VLCtrlSort.prototype.appendItem = function(itemParam)
{
    itemParam.index = this.getItemCount();
    return this.insertItem(itemParam);
}

////////////////////////////////////////////////////////////////////////////
// insertItem
////////////////////////////////////////////////////////////////////////////
/*
var itemParam = {
    index: -1,
    img: img src check,
    value: "PMID",
    text: "PubMed Id",
    separator: bool
}
*/
VLCtrlSort.prototype.insertItem = function(itemParam)
{
    itemParam.img = AP.is_set(itemParam.img, ROOT_PATH + "img/sort/check_sort.gif");

    // DOM
    // make table row
    var trItem = this.items_bd.insertRow(itemParam.index);
    trItem.className = "ap vlsort_item ";
    if ( itemParam.separator )
    {
        trItem.className += "vlsort_separator_item";
    }
    trItem.instance = this;
    trItem._state = 0;
    
    if ( itemParam.separator )
    {
        var tdSep = trItem.insertCell(trItem.cells.length);
        tdSep.className = "ap vlsort_sub_item_sep";
        tdSep.colSpan = 2;
        tdSep.innerHTML = "<hr>";
    }
    else
    {
        var tdCheck = trItem.insertCell(trItem.cells.length);
        tdCheck.className = "ap vlsort_sub_item_check";
        var tdValue = trItem.insertCell(trItem.cells.length);
        tdValue.className = "ap vlsort_sub_item_value";
        tdValue.noWrap = true;
        
        // check
        trItem.divImgCheck = AP.createElement("div", tdCheck);
        AP.visible(trItem.divImgCheck, false);
        trItem.imgCheck = AP.createElement("img", trItem.divImgCheck);
        AP.width(trItem.imgCheck, 16);
        AP.width(trItem.imgCheck, 16);
        trItem.imgCheck.src = itemParam.img;
        
        // value
        trItem.spanText = AP.createElement("span", tdValue);
        
        // Fill Item
        this.setItem(itemParam);
    
        AP.addEvent(trItem, "mouseover", VLCtrlSort.onItemMouseAction);
        AP.addEvent(trItem, "mouseout", VLCtrlSort.onItemMouseAction);
        AP.addEvent(trItem, "click", VLCtrlSort.onItemMouseAction);
    
        this.tabIndex( this.tabIndex() );
    }
    
    this.fireNotify(VLCTRLSORTN_ITEM_ISERTED, itemParam.index);
    
    return itemParam.index;
}

////////////////////////////////////////////////////////////////////////////
// isSeparator
////////////////////////////////////////////////////////////////////////////
VLCtrlSort.prototype.isSeparator = function(index)
{
    return (index == this.indexSeparator);
}

////////////////////////////////////////////////////////////////////////////
// setItem
////////////////////////////////////////////////////////////////////////////
VLCtrlSort.prototype.setItem = function(itemParam)
{
    if ( AP.is_set(itemParam.index) === false )
    {
        return -1;
    }

    var trItem = this._getItem(itemParam.index);
    
    // Value
    if ( AP.is_set(itemParam.value) !== false )
    {
        trItem.value = itemParam.value;
    }
    
    // Text
    if ( AP.is_set(itemParam.text) !== false )
    {
        trItem.spanText.innerHTML = itemParam.text;
    }
}

////////////////////////////////////////////////////////////////////////////
// deleteAll
////////////////////////////////////////////////////////////////////////////
VLCtrlSort.prototype.deleteAll = function()
{
    while ( this.getItemCount() )
    {
        this.deleteItem( this.getItemCount() - 1 );
    }
}

////////////////////////////////////////////////////////////////////////////
// deleteItem
////////////////////////////////////////////////////////////////////////////
VLCtrlSort.prototype.deleteItem = function(index)
{
    if ( this.fireNotify(VLCTRLSORTN_ITEM_DELETING, index) == -1 )
        return;
    
    var trItem = this._getItem(index);

    if ( !this.isSeparator(index) )
    {
        AP.removeEvent(trItem, "mouseover", VLCtrlSort.onItemMouseAction);
        AP.removeEvent(trItem, "mouseout", VLCtrlSort.onItemMouseAction);
        AP.removeEvent(trItem, "click", VLCtrlSort.onItemMouseAction);
    
        // detrsoy DOM
        // left img
        trItem.divImgCheck.removeChild(trItem.imgCheck);
        trItem.imgCheck = null;
        trItem.divImgCheck.parentNode.removeChild(trItem.divImgCheck);
        trItem.divImgCheck = null;
        // text 
        trItem.spanText.parentNode.removeChild(trItem.spanText);
        trItem.spanText = null;
        // -- detrsoy DOM
    }

    trItem.instance = null;
    trItem._state = null;
    this.items_bd.deleteRow(index);
    
    this.fireNotify(VLCTRLSORTN_ITEM_DELETED, index);
}

////////////////////////////////////////////////////////////////////////////
// itemState
////////////////////////////////////////////////////////////////////////////
VLCtrlSort.prototype.itemState = function(index, state)
{
    var trItem = this._getItem(index);
    if ( !trItem )
        DebugLog.write("trItem == null");
    
    if ( AP.is_set(state) === false )
        return trItem._state;

    var stateOld = trItem._state;
    if ( stateOld == state )
        return null;
        
    trItem._state = state;
    VLCtrlSort._itemStateToClassName(trItem);
    this.fireNotify(VLCTRLSORTN_ITEM_STATE_CHANGED, index);

    return trItem._state;   
}

////////////////////////////////////////////////////////////////////////////
// _checkItem
////////////////////////////////////////////////////////////////////////////
VLCtrlSort.prototype._checkItem = function(index, check)
{
    var trItem = this._getItem(index);
    AP.visible(trItem.divImgCheck, check);
}

////////////////////////////////////////////////////////////////////////////
// _itemStateToClassName
////////////////////////////////////////////////////////////////////////////
VLCtrlSort._itemStateToClassName = function(trItem)
{
    var className = "ap vlsort_item";
    if ( trItem._state & VLCTRLSORTIS_OVER )
    {
        className += " vlsort_item_over";
    }
    else
    {
    }
    trItem.className = className;
}

////////////////////////////////////////////////////////////////////////////
// _getItem
////////////////////////////////////////////////////////////////////////////
VLCtrlSort.prototype._getItem = function(index)
{
    return this.items_bd.rows[index];
}

////////////////////////////////////////////////////////////////////////////
// _getItemIndex
////////////////////////////////////////////////////////////////////////////
VLCtrlSort.prototype._getItemIndex = function(item)
{
    var index = -1;
    
    for ( var loop = 0; loop < this.items_bd.rows.length; loop++ )
    {
        if ( this.items_bd.rows[loop] == item )
        {
            index = loop;
            break;
        }
    }
    
    return index;
}

////////////////////////////////////////////////////////////////////////////
// _stateToClassName
////////////////////////////////////////////////////////////////////////////
VLCtrlSort.prototype._stateToClassName = function()
{
    if ( this._state & VLCTRLSORTS_OVER )
    {
        this.img.src = ROOT_PATH + "img/sort/btn_over.gif";
    }
    else
    {
        this.img.src = ROOT_PATH + "img/sort/btn.gif";
    }
}

////////////////////////////////////////////////////////////////////////////
// onPressDropDown
////////////////////////////////////////////////////////////////////////////
VLCtrlSort.onPressDropDown = function(ev)
{
    ev || (ev = window.event);
    var obj = (AP.isIE() ? ev.srcElement : ev.currentTarget);
    var ctrl = VLCtrlSort.getInstance(obj);
    if ( !ctrl )
        return true;
    
    ctrl.dropdown(true);
   
    return true;
}

////////////////////////////////////////////////////////////////////////////
// onMouseEvent
////////////////////////////////////////////////////////////////////////////
VLCtrlSort.onMouseEvent = function(ev)
{
    ev || (ev = window.event);
    var obj = (AP.isIE() ? ev.srcElement : ev.currentTarget);
    var ctrl = VLCtrlSort.getInstance(obj);
    if ( !ctrl )
        return true;
    
    if ( ev.type == "mouseover" )
    {
        ctrl.state( ctrl.state() | VLCTRLSORTS_OVER );
    }
    else if ( ev.type == "mouseout" )
    {
        ctrl.state( ctrl.state() & ~VLCTRLSORTS_OVER );
    }
    
    return true;    
}

////////////////////////////////////////////////////////////////////////////
// onPopUpMouseAction
////////////////////////////////////////////////////////////////////////////
VLCtrlSort.onPopUpMouseAction = function(ev)
{
    ev || (ev = window.event);
    var obj = (AP.isIE() ? ev.srcElement : ev.target);
    if ( obj.instance && obj.instance.ctrlSort )
    {
        obj.instance.ctrlSort.dropdown(false);
    }

    return true;    
}

////////////////////////////////////////////////////////////////////////////
// onItemMouseAction
////////////////////////////////////////////////////////////////////////////
VLCtrlSort.onItemMouseAction = function(ev)
{
    ev || (ev = window.event);
    var obj = (AP.isIE() ? ev.srcElement : ev.currentTarget);
    var trItem = VLCtrlSort.getItemElement(obj);
    if ( !trItem )
    {
        return true;
    }

    var ctrl = trItem.instance;
    if ( !ctrl )
    {
        return true;
    }
    var index = ctrl._getItemIndex(trItem);

    if ( ev.type == "mouseover" )
    {
        ctrl.itemState( index, ctrl.itemState(index) | VLCTRLSORTIS_OVER );
    }
    else if ( ev.type == "mouseout" )
    {
        ctrl.itemState( index, ctrl.itemState(index) & ~VLCTRLSORTIS_OVER );
    }
    else if ( ev.type == "click" )
    {
        ctrl.fireNotify(VLCTRLSORTN_ITEM_CLICKED, index);
        var value = trItem.value;
        if ( value == "forward" )
        {
            ctrl.value({direction: 0});
        }
        else if ( value == "backward" )
        {
            ctrl.value({direction: 1});
        }
        else
        {
            ctrl.value({field: value});
        }
        ctrl.dropdown(false);
    }

    return true;    
}

////////////////////////////////////////////////////////////////////////////
// getItemElement
////////////////////////////////////////////////////////////////////////////
VLCtrlSort.getItemElement = function(obj)
{
    for ( var o = obj; o && !AP.isSetClassName(o, "vlsort_item"); o = o.parentNode );
    return o;
}

////////////////////////////////////////////////////////////////////////////
// getInstance
////////////////////////////////////////////////////////////////////////////
VLCtrlSort.getInstance = function(obj)
{
    for ( var o = obj; o && !(o.instance && VLCtrlSort.prototype.isPrototypeOf(o.instance)); o = o.parentNode );
    return (o ? o.instance : null);
}

////////////////////////////////////////////////////////////////////////////
// class VLTreeView extends TreeViewEx
////////////////////////////////////////////////////////////////////////////
VLTreeView = function(imgList)
{
    this.subclass = TreeViewEx;
    this.subclass(imgList);

    this.className = "VLTreeView";
}
VLTreeView.prototype = new TreeViewEx;

////////////////////////////////////////////////////////////////////////////
// _compareItems
////////////////////////////////////////////////////////////////////////////
VLTreeView._compareItems = function(itemLeft, itemRight)
{
    return VLTreeView._compareItemsData(itemLeft.data, itemRight.data);
}

////////////////////////////////////////////////////////////////////////////
// _compareItems_virt
////////////////////////////////////////////////////////////////////////////
VLTreeView.prototype._compareItems_virt = function(itemLeft, itemRight)
{
    return VLTreeView._compareItems(itemLeft, itemRight);
}

////////////////////////////////////////////////////////////////////////////
// _compareItemsData
////////////////////////////////////////////////////////////////////////////
VLTreeView._compareItemsData = function(dataLeft, dataRight)
{
    if ( typeof dataLeft != typeof dataRight )
    {
        return 1;
    }
    
    if ( typeof dataLeft == "object" )
    {
        if ( dataLeft.type != dataRight.type )
        {
            return 1;
        }
        
        if ( dataLeft.type == "vl_addr" )
        {
            var leftAddr = AP.is_set(dataLeft.vl_addr, "<not?*?set>").toLowerCase();
            var rightAddr = AP.is_set(dataRight.vl_addr, "<not?*?set>").toLowerCase();
            return (leftAddr == rightAddr ? 0 : 1);
        }
        else if ( dataLeft.type == "vl_domain" )
        {
            var leftDomain = AP.is_set(dataLeft.vl_domain, "<not?*?set>").toLowerCase();
            var rightDomain = AP.is_set(dataRight.vl_domain, "<not?*?set>").toLowerCase();
            return (leftDomain == rightDomain ? 0 : 1);
        }
        else if ( dataLeft.type == "vl_root" )
        {
            var leftAddr = AP.is_set(dataLeft.vl_addr, "<not?*?set>").toLowerCase();
            var rightAddr = AP.is_set(dataRight.vl_addr, "<not?*?set>").toLowerCase();
            var leftDomain = AP.is_set(dataLeft.vl_domain, "<not?*?set>").toLowerCase();
            var rightDomain = AP.is_set(dataRight.vl_domain, "<not?*?set>").toLowerCase();
            if ( leftAddr == rightAddr && leftDomain == rightDomain )
            {
                return 0;
            }
            else
            {
                return 1;
            }
        }
        else if ( dataLeft.type == "lib"
                  || dataLeft.type == "user" )
        {
            var leftId = AP.is_set(dataLeft.id, "<not?*?set>").toLowerCase();
            var rightId = AP.is_set(dataRight.id, "<not?*?set>").toLowerCase();
            return (leftId == rightId ? 0 : 1);
        }
//        else if ( dataLeft.type == "folder"
//                  || dataLeft.type == "alert"
//                  || dataLeft.type == "filter" )
        return (dataLeft.id == dataRight.id ? 0 : 1);
    }

    //DebugLog.write("WARNING: Invalid ItemData");
    return (dataLeft == dataRight ? 0 : 1);
}

////////////////////////////////////////////////////////////////////////////
// _compareItemsDataByName
////////////////////////////////////////////////////////////////////////////
// check for name equals only (example: alert with name == a2a = folder with name == a2a)
VLTreeView._compareItemsDataByName = function(dataLeft, dataRight)
{
    if ( typeof dataLeft != typeof dataRight )
    {
        return 1;
    }
    
    if ( typeof dataLeft == "object" )
    {
        if ( dataLeft.type != "lib"
             && dataLeft.type != "alert"
             && dataLeft.type != "folder"
             && dataLeft.type != "filter" )
        {
            return 1;
        }
        
        var leftName = AP.is_set(dataLeft.name, "<not?*?set>").toLowerCase();
        var rightName = AP.is_set(dataLeft.name, "<not?*?set>").toLowerCase();
        return (leftName == rightName ? 0 : 1);
    }
    
    return 1;
}

////////////////////////////////////////////////////////////////////////////
// _compareItemsDataByType
////////////////////////////////////////////////////////////////////////////
// check for type equals only
VLTreeView._compareItemsDataByType = function(dataLeft, dataRight)
{
    if ( typeof dataLeft != typeof dataRight )
    {
        return 1;
    }
    
    if ( typeof dataLeft == "object" )
    {
        return (dataLeft.type === dataRight.type) ? 0 : 1;
    }
    
    return 1;
}

////////////////////////////////////////////////////////////////////////////
// _compareFolderItemsData
////////////////////////////////////////////////////////////////////////////
// check for id equals only (example: alert with id == 5 = folder with id == 5)
VLTreeView._compareFolderItemsData = function(dataLeft, dataRight)
{
    if ( typeof dataLeft != typeof dataRight )
    {
        return 1;
    }
    
    if ( typeof dataLeft == "object" )
    {
        if ( dataLeft.type != "alert"
             && dataLeft.type != "folder"
             && dataLeft.type != "filter" )
        {
            return 1;
        }
        
        return (dataLeft.id == dataRight.id ? 0 : 1);
    }
    
    return (dataLeft == dataRight ? 0 : 1);
}

////////////////////////////////////////////////////////////////////////////
// _compareItemsData_virt
////////////////////////////////////////////////////////////////////////////
VLTreeView.prototype._compareItemsData_virt = function(dataLeft, dataRight)
{
    return VLTreeView._compareItemsData(dataLeft, dataRight);
}

////////////////////////////////////////////////////////////////////////////
// isType
////////////////////////////////////////////////////////////////////////////
VLTreeView.isType = function(itemData, type)
{
    if ( typeof itemData == "object"
         && AP.is_set(itemData.type)
         && itemData.type == type )
    {
        return true;
    }
    
    return false;
}

////////////////////////////////////////////////////////////////////////////
// isVLRoot
////////////////////////////////////////////////////////////////////////////
VLTreeView.prototype.isVLRoot = function(itemId)
{
    var itemData = this.itemData(itemId);
    return VLTreeView.isType(itemData, "vl_root");
}

////////////////////////////////////////////////////////////////////////////
// isLibrary
////////////////////////////////////////////////////////////////////////////
VLTreeView.prototype.isLibrary = function(itemId)
{
    var itemData = this.itemData(itemId);
    return VLTreeView.isType(itemData, "lib");
}

////////////////////////////////////////////////////////////////////////////
// isFolder
////////////////////////////////////////////////////////////////////////////
VLTreeView.prototype.isFolder = function(itemId)
{
    var itemData = this.itemData(itemId);
    return VLTreeView.isType(itemData, "folder");
}

////////////////////////////////////////////////////////////////////////////
// isFolderType
////////////////////////////////////////////////////////////////////////////
VLTreeView.prototype.isFolderType = function(itemId)
{
    var itemData = this.itemData(itemId);
    return VLTreeView.isType(itemData, "folder")
           || VLTreeView.isType(itemData, "alert")
           || VLTreeView.isType(itemData, "filter");
}

////////////////////////////////////////////////////////////////////////////
// isAlert
////////////////////////////////////////////////////////////////////////////
VLTreeView.prototype.isAlert = function(itemId)
{
    var itemData = this.itemData(itemId);
    return VLTreeView.isType(itemData, "alert");
}

////////////////////////////////////////////////////////////////////////////
// isFilter
////////////////////////////////////////////////////////////////////////////
VLTreeView.prototype.isFilter = function(itemId)
{
    var itemData = this.itemData(itemId);
    return VLTreeView.isType(itemData, "filter");
}

////////////////////////////////////////////////////////////////////////////
// getItemVLInfo
////////////////////////////////////////////////////////////////////////////
VLTreeView.prototype.getItemVLInfo = function(itemId)
{
    var rootItemId = null;
    
    for ( ; itemId && itemId != TV_ROOT_ITEM_ID; itemId = this.nextItem(itemId, TVI_FIND_PARENT) )
    {
        var itemData = this.itemData(itemId);
        if ( VLTreeView.isType(itemData, "vl_root") )
        {
            rootItemId = itemId;
            break;
        }
    }
    if ( rootItemId )
    {
        return this.itemData(rootItemId);
    }
    
    return null;
}

////////////////////////////////////////////////////////////////////////////
// getFullFolderName
////////////////////////////////////////////////////////////////////////////
VLTreeView.prototype.getFullFolderName = function(info)
{
    var retVal = {
        vl_name: null,
        folder_id: -1,
        full_name: null,
        result_item: null,
        found_all: false
    };
    
    info.vl_name = AP.is_set(info.vl_name, "*");
    info.folder_id = AP.is_set(info.folder_id, -1);
    
    // Root Item
    var vlRootId = this.findVLRoot(info);
    if ( !vlRootId )
    {
        return retVal;
    }
    retVal.result_item = vlRootId;
    
    // extract vl name & domain name
    var domainName = "";
    var vlName = info.vl_name;
    var split = info.vl_name.split("/", 2);
    if ( split.length > 1 )
    {
        domainName = split[0];
        vlName = split[1];
    }
    // --
    retVal.vl_name = "*";
    retVal.folder_id = -1;
    retVal.full_name = RES_ALL_LIBRARIES;
    if ( vlName == "*" )
    {
        retVal.found_all = true;
        return retVal;
    }

    // VL Item
    var vlItemId = this.findItemData(vlRootId, {type: "lib", id: vlName});
    if ( !vlItemId )
    {
        return retVal;
    }
    retVal.result_item = vlItemId;
    retVal.vl_name = vlName;
    retVal.full_name = vlName;
    if ( info.folder_id == -1 )
    {
        retVal.found_all = true;
        return retVal;
    }
    
    // Folder Item
    var folderItemId = this.findItemData(vlItemId, {id: info.folder_id}, VLTreeView._compareFolderItemsData);
    if ( !folderItemId )
    {
        return retVal;
    }
    retVal.result_item = folderItemId;
    retVal.folder_id = info.folder_id;
    retVal.found_all = true;
    
    var fullName = null;
    for ( var itemId = folderItemId; itemId && (itemId != TV_ROOT_ITEM_ID) && (itemId != vlRootId); itemId = this.nextItem(itemId, TVI_FIND_PARENT) )
    {
        var folderName = (this.itemText({itemId: itemId, columnId: 0}) || "");
        fullName = folderName + (fullName ? ("/" + fullName) : "");
    }
    retVal.full_name = fullName;
    
    return retVal;
}

////////////////////////////////////////////////////////////////////////////
// getFolderIdByFullName
////////////////////////////////////////////////////////////////////////////
VLTreeView.prototype.getFolderIdByFullName = function(info)
{
    var ret = {
        vl_name: null,
        folder_id: -1,
        found_all: false
    };
    
    var vlRootId = this.findVLRoot(info);
    if ( !vlRootId )
    {
        return ret;
    }
    
    var arrFullName = info.full_name.split("/");
    var itemId = this.nextItem(vlRootId, TVI_FIND_FIRST_CHILD);
    var loop = 0;
    while ( itemId && (loop < arrFullName.length) )
    {
        var itemData = this.itemData(itemId);
        if ( itemData.name == arrFullName[loop] )
        {
            if ( itemData.type == "lib" )
            {
                ret.vl_name = itemData.id;
            }
            else
            {
                ret.folder_id = itemData.id;
            }
            itemId = this.nextItem(itemId, TVI_FIND_FIRST_CHILD);
            loop++
        }
        else
        {
            itemId = this.nextItem(itemId, TVI_FIND_NEXT_SIBLING);
        }
    }
    
    if ( loop == arrFullName.length )
    {
        ret.found_all = true;
    }
    
    return ret;
}

////////////////////////////////////////////////////////////////////////////
// _getVLData
////////////////////////////////////////////////////////////////////////////
VLTreeView.prototype._getVLData = function(itemId)
{
    var ret = null;
    
    for ( var loopId = itemId;
          loopId && loopId != TV_ROOT_ITEM_ID;
          loopId = this.nextItem(loopId, TVI_FIND_PARENT) )
    {
        var itemData = this.itemData(loopId);
        if ( itemData
             && (typeof itemData == "object")
             && itemData.type
             && itemData.type == "lib" )
        {
            ret = itemData;
            break;
        }
    }
    
    return ret;
}

////////////////////////////////////////////////////////////////////////////
// _getVLName
////////////////////////////////////////////////////////////////////////////
VLTreeView.prototype._getVLName = function(itemId)
{
    var parentItemData = this._getVLData(itemId);
    var vl = null;
    if ( parentItemData )
    {
        vl = parentItemData.id;
    }
    
    return vl;
}

////////////////////////////////////////////////////////////////////////////
// findSrvAddressRoot
////////////////////////////////////////////////////////////////////////////
VLTreeView.prototype.findSrvAddressRoot = function(info)
{
    var vlRootId = this.findItemData(TV_ROOT_ITEM_ID, {
        type: "vl_addr",
        vl_addr: info.vl_addr
    });
    
    return vlRootId;
}

////////////////////////////////////////////////////////////////////////////
// findVLRoot
////////////////////////////////////////////////////////////////////////////
VLTreeView.prototype.findVLRoot = function(info)
{
    var vlRootId = this.findItemData(TV_ROOT_ITEM_ID, {
        type: "vl_root",
        vl_addr: info.vl_addr,
        vl_domain: info.vl_domain
    });
    
    return vlRootId;
}

////////////////////////////////////////////////////////////////////////////
// getInstance
////////////////////////////////////////////////////////////////////////////
VLTreeView.prototype.updateVLInfo = function(info)
{
    var vlRootId = this.findVLRoot(info.from);
    if ( vlRootId )
    {
        var itemData = this.itemData(vlRootId);
        itemData.vl_addr = info.to.vl_addr;
        itemData.vl_domain = info.to.vl_domain;
        this.itemData(vlRootId, itemData);
    }
    return null;
}

////////////////////////////////////////////////////////////////////////////
// getInstance
////////////////////////////////////////////////////////////////////////////
VLTreeView.getInstance = function(obj)
{
    for ( var o = obj; o && !(o.instance && VLTreeView.prototype.isPrototypeOf(o.instance)); o = o.parentNode );
    return (o ? o.instance : null);
}

////////////////////////////////////////////////////////////////////////////
// class VLOrganizer extends WndBorder
////////////////////////////////////////////////////////////////////////////
// VLOrganizer DOM
////////////////////////////////////////////////////////////////////////////
/*
WndBorder {
    VLTreeView
}
*/
////////////////////////////////////////////////////////////////////////////
// constructor
////////////////////////////////////////////////////////////////////////////
VLOrganizer = function()
{
    this.subclass = WndBorder;
    this.subclass();
    
    this.tv = new VLTreeView({
        base_dir: ROOT_PATH + "img_php/treeview/",
        img_ext: ".php",
        img_line: "line.php",
        img_check: TV_IMGLIST_CHECK,
        img_list: {
            base: "page.php",
            expanded: "folderopen.php",
            collapsed: "folder.php"
        }
    });
    
    this.vlRootItem = null;
    this.className = "VLOrganizer";
}
VLOrganizer.prototype = new WndBorder;

////////////////////////////////////////////////////////////////////////////
// create
////////////////////////////////////////////////////////////////////////////
var VL_ORGANIZER_FLAGS_LIBONLY         = 0x0100;
var VL_ORGANIZER_BTN_REFRESH           = 0x1000;
var VL_ORGANIZER_BTN_CLOSE             = 0x2000;
var VL_ORGANIZER_BTN_QUICKSEARCH       = 0x4000;
VLOrganizer.prototype.create = function(parent, flags, tvFlags)
{
    flags = AP.is_set(flags, 0);
    this.subclass = WndBorder.prototype.create;
    this.subclass(parent, "Organizer", flags | WND_FLAGS_BORDER );
    this.element.className += " vl_organizer_wnd";

    var btns = [];
    if ( flags & VL_ORGANIZER_BTN_REFRESH )
    {
        // see also setRefreshState function
        btns.push({
            text: "<img style=\"margin-top: 2px; cursor: pointer;\" src=\"" + ROOT_PATH + "img/refresh.gif\">",
            id: IDREFRESH
        });
    }
    if ( flags & VL_ORGANIZER_BTN_QUICKSEARCH )
    {
        btns.push({
            text: "<img style=\"margin-top: 2px; cursor: pointer;\" src=\"" + ROOT_PATH + "img/qsearch.gif\">",
            id: IDFIND
        });
    }
    if ( flags & VL_ORGANIZER_BTN_CLOSE )
    {
        btns.push({
            text: "<span style=\"cursor: pointer;\">X</span>",
            id: IDCLOSE
        });
    }

    this.appendButtons(btns);
    
    tvFlags = AP.is_set(tvFlags, TVS_MANAGEICON | TVS_ITEMICON | TVS_NO_LINES);
    if ( flags & VL_ORGANIZER_BTN_QUICKSEARCH )
    {
        tvFlags |= TVS_QUICKSEARCH;
    }
    this.tv.create(this.childArea(), tvFlags);
    this.tv.addNotifyHandler( [VLOrganizer.onTreeViewNotify, this] );

    if ( tvFlags & TVS_COLUMNHEADER )
    {
        this.tv.insertColumn({
            index: 0,
            text: "",
            width: 300
        });
    }
    if ( this.flags & VL_ORGANIZER_FLAGS_LIBONLY )
    {
        this.vlRootItem = TV_ROOT_ITEM_ID;
    }
    else
    {
        this.vlRootItem = this.tv.insertItem({
            img_list: {
                base: "quosa.php"
            },
            text: "QUOSA Browser",
            columns: {
                0: {
                    text: "QUOSA Browser",
                    data: null,
                    flags: 0
                }
            },
            data: {
                type: "quosa_root"
            },
            flags: TVI_INSERT_FIRST_CHILD
        });
    }
}

////////////////////////////////////////////////////////////////////////////
// setPosition
////////////////////////////////////////////////////////////////////////////
VLOrganizer.prototype.setPosition = function(pos)
{
    pos.flags = AP.is_set(pos.flags, 0);
    this.subclass = WndBorder.prototype.setPosition;
    this.subclass(pos);
    
    var childArea = this.childArea();
    var tvPos = {
        x: 1,
        y: 1,
        cx: AP.clientWidth(childArea) - 2,
        cy: AP.clientHeight(childArea) - 2
    }
    this.tv.setPosition(tvPos);
}

///////////////////////////////////////////////////////////////////////////
// restrict
// assignChild
VLOrganizer.prototype.assignChild = function(child) { return null; }
// restrict
////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////
// redirect
VLOrganizer.prototype.enable = function(doEnable) { return this.tv.enable(doEnable); }
VLOrganizer.prototype.tabIndex = function(tabIndex) { return this.tv.tabIndex(tabIndex); }
VLOrganizer.prototype.focus = function(itemId) { return this.tv.focus(itemId); }
VLOrganizer.prototype.select = function(itemId) { return this.tv.select(itemId); }
VLOrganizer.prototype.focused = function(itemId) { return this.tv.focused(itemId); }
VLOrganizer.prototype.selected = function(itemId) { return this.tv.selected(itemId); }
VLOrganizer.prototype.expand = function(itemId) { return this.tv.expand(itemId); }
VLOrganizer.prototype.smartSelect = function(itemId) { return this.tv.smartSelect(itemId); }
VLOrganizer.prototype.nextItem = function(itemId, flags) { return this.tv.nextItem(itemId, flags); }
VLOrganizer.prototype.itemData = function(itemId, itemData) { return this.tv.itemData(itemId, itemData); }
VLOrganizer.prototype.itemText = function(textInfo) { return this.tv.itemText(textInfo); }
VLOrganizer.prototype.findItem = function(itemFrom, findWhat, compare_function) { return this.tv.findItem(itemFrom, findWhat, compare_function); }
VLOrganizer.prototype.findItemData = function(itemFrom, itemData, compare_function) { return this.tv.findItemData(itemFrom, itemData, compare_function); }
VLOrganizer.prototype.qsShow = function(show, setFocus) { return this.tv.qsShow(show, setFocus); }
VLOrganizer.prototype.scrollItemIntoView = function(itemId) {return this.tv.scrollItemIntoView(itemId);}
VLOrganizer.prototype.setFocusOnTree = function() {return this.tv.setFocusOnTree();}
VLOrganizer.prototype.insertColumn = function(hdrItem) {return this.tv.insertColumn(hdrItem);}
VLOrganizer.prototype.setColumn = function(hdrItem) {return this.tv.setColumn(hdrItem);}
VLOrganizer.prototype.deleteColumn = function(itemId) {return this.tv.deleteColumn(itemId);}
VLOrganizer.prototype.updateTree = function(tree) {return this.tv.updateTree(tree);}
VLOrganizer.prototype._getVLData = function(itemId) {return this.tv._getVLData(itemId);}
VLOrganizer.prototype._getVLName = function(itemId) {return this.tv._getVLName(itemId);}
VLOrganizer.prototype.findSrvAddressRoot = function(info) {return this.tv.findSrvAddressRoot(info);}
VLOrganizer.prototype.findVLRoot = function(info) {return this.tv.findVLRoot(info);}
VLOrganizer.prototype.updateVLInfo = function(info) {return this.tv.updateVLInfo(info);}
VLOrganizer.prototype.getItemVLInfo = function(itemId) {return this.tv.getItemVLInfo(itemId);}
VLOrganizer.prototype.isVLRoot = function(itemId) {return this.tv.isVLRoot(itemId);}
VLOrganizer.prototype.isLibrary = function(itemId) {return this.tv.isLibrary(itemId);}
VLOrganizer.prototype.isFolder = function(itemId) {return this.tv.isFolder(itemId);}
VLOrganizer.prototype.isFolderType = function(itemId) {return this.tv.isFolderType(itemId);}
VLOrganizer.prototype.isAlert = function(itemId) {return this.tv.isAlert(itemId);}
VLOrganizer.prototype.isFilter = function(itemId) {return this.tv.isFilter(itemId);}
VLOrganizer.prototype.getFullFolderName = function(info) {return this.tv.getFullFolderName(info);}
VLOrganizer.prototype.getFolderIdByFullName = function(info) {return this.tv.getFolderIdByFullName(info);}
// -- redirect
////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////
// setRefreshState
////////////////////////////////////////////////////////////////////////////
VLOrganizer.prototype.setRefreshState = function(refreshing)
{
    var btnInfo = {};
    var id = null;
    if ( refreshing )
    {
        id = IDREFRESH;
        btnInfo.text = "<img style=\"margin-top: 2px; cursor: default;\" src=\"" + ROOT_PATH + "img/refreshing.gif\">";
        btnInfo.id = IDREFRESHING;
    }
    else
    {
        id = IDREFRESHING;
        btnInfo.text = "<img style=\"margin-top: 2px; cursor: pointer;\" src=\"" + ROOT_PATH + "img/refresh.gif\">";
        btnInfo.id = IDREFRESH;
    }
    
    this.setButton(id, btnInfo, true);
}

////////////////////////////////////////////////////////////////////////////
// getVLRoot
////////////////////////////////////////////////////////////////////////////
VLOrganizer.prototype.getVLRoot = function()
{
    return this.vlRootItem;
}

////////////////////////////////////////////////////////////////////////////
// updateVLTree
////////////////////////////////////////////////////////////////////////////
/*
var vlInfo = {
    vl_addr: ....,
    vl_domain: ....,
    tree: [
        tvItem,
        ......
    ] - see TreeViewMemory.updateTree method for more details
}
*/
VLOrganizer.prototype.updateVLTree = function(info)
{
    var vlRootId = this.findVLRoot(info);
    if ( !vlRootId )
    {
        vlRootId = this.tv.insertItem({
            parent: this.getVLRoot(),
            text: info.rootItem.text,
            data: info.rootItem.data,
            columns: info.rootItem.columns,
            img_list: info.rootItem.img_list,
            flags: TVI_INSERT_LAST_CHILD
        });
    }
    
    this.updateTree({
        parentId: vlRootId,
        parentItem: info.rootItem,
        tree: info.tree
    });
    
    return null;
}

////////////////////////////////////////////////////////////////////////////
// onTreeViewNotify
////////////////////////////////////////////////////////////////////////////
VLOrganizer.onTreeViewNotify = function(param)
{
//    var tv = param.producer;
//    var org = param.subscriber;
//    
//    // Folder Management
//    if ( param.code == TVN_ITEM_DO_TEXTMODIFY )
//    {
//        var itemId = param.param;
//        if ( org.isFolder(itemId) || org.isAlert(itemId) || org.isFilter(itemId) )
//        {
//            var vlData = org._getVLData(itemId);
//            if ( (vlData.access & VL_PERMISSONS_MODIFY) == VL_PERMISSONS_MODIFY )
//            {
//                return 0;
//            }
//        }
//        return -1;
//    }
//    else if ( param.code == TVN_ITEM_EDIT_ESCAPE )
//    {
//        if ( org._insert_folder )
//        {
//            org._insert_folder = false;
//            var itemId = param.param.item;
//            tv.endItemTextEditing(itemId, false);
//            tv.deleteItem(itemId);
//        }
//        else
//        {
//            return 0;
//        }
//        return -1;
//    }
//    else if ( param.code == TVN_ITEM_EDIT_CONFIRM )
//    {
//        var itemId = param.param.item;
//        var text = param.param.text;
//        
//        tv.endItemTextEditing(itemId, true, text);
//        if ( org.isFolder(itemId) || org.isAlert(itemId) || org.isFilter(itemId) )
//        {
//            text = VLCommon.validVLFolderName(text);
//            if ( text )
//            {
//                if ( org._insert_folder )
//                {
//                    org._insert_folder = false;
//                    
//                    var vlName = org._getVLName(itemId);
//                    var folderId = -1;
//                    var parentId = tv.nextItem(itemId, TVI_FIND_PARENT);
//                    if ( org.isFolder(parentId) )
//                    {   
//                        var itemData = tv.itemData(parentId);
//                        folderId = itemData.id;
//                    }
//                    
//                    var notifyParam = {
//                        vl: vlName,
//                        parentId: folderId,
//                        text: text
//                    }
//                    org.fireNotify(VLN_ORGANIZER_ON_INSERT_FOLDER, notifyParam);
//                }
//                else
//                {
//                    var vlName = org._getVLName(itemId);
//                    var itemData = tv.itemData(itemId);
//                    var folderId = itemData.id;
//                    
//                    var notifyParam = {
//                        vl: vlName,
//                        folderId: folderId,
//                        text: text
//                    }
//                    org.fireNotify(VLN_ORGANIZER_ON_MODIFY_FOLDER, notifyParam);
//                }
//            }
//        }
//        
//        return -1;
//    }
//    else if ( param.code == TVN_ITEM_DO_DELETE )
//    {
//        var itemId = param.param;
//        var isFolder = org.isFolder(itemId);
//        var isAlert = org.isAlert(itemId);
//        var isFilter = org.isFilter(itemId);
//        if ( isFolder || isAlert || isFilter )
//        {
//            var vlData = org._getVLData(itemId);
//            if ( (vlData.access & VL_PERMISSONS_DELETE) == VL_PERMISSONS_DELETE )
//            {
//                var itemData = tv.itemData(itemId);
//                var folderName = tv.itemText({itemId: itemId, columnId: 0});
//                var msgText = "Are you sure you want to remove the folder \"" + folderName + "\"\nand all its content?";
//                if ( confirm(msgText) )
//                {
//                    var vlName = org._getVLName(itemId);
//                    var folderId = itemData.id;
//                    
//                    var notifyParam = {
//                        vl: vlName,
//                        folderId: folderId
//                    }
//                    org.fireNotify(VLN_ORGANIZER_ON_DELETE_FOLDER, notifyParam);
//                }
//            }
//        }           
//        return -1;
//    }
//    else if ( param.code == TVN_ITEM_DO_INSERT )
//    {
//        var itemId = param.param;
//        var isLibrary = org.isLibrary(itemId);
//        var isFolder = org.isFolder(itemId);
//        var isFilter = org.isFilter(itemId);
//        if ( isLibrary || isFolder || isFilter )
//        {
//            var vlData = org._getVLData(itemId);
//            if ( (vlData.access & VL_PERMISSONS_CREATE) == VL_PERMISSONS_CREATE )
//            {
//                org._insert_folder = true;
//                
//                itemId = tv.insertItem({
//                    parent: itemId,
//                    text: "new Item",
//                    data: {
//                        type: "folder",
//                        id: 0
//                    },
//                    img_list: {
//                        base: "folder.php",
//                        focused: "folderopen.php"
//                    },
//                    flags: TVI_INSERT_FIRST_CHILD | TVI_INSERT_EXPANDED
//                });
//                
//                if ( !itemId )
//                {
//                    return -1;
//                }
//                
//                tv.focus(itemId);
//                
//                tv.startItemTextEditing(itemId);
//            }
//        }
//        
//        return -1;
//    }

    // redirect
    return param.subscriber.fireNotify(param.code, param.param);
}

////////////////////////////////////////////////////////////////////////////
// getInstance
////////////////////////////////////////////////////////////////////////////
VLOrganizer.getInstance = function(obj)
{
    for ( var o = obj; o && !(o.instance && VLOrganizer.prototype.isPrototypeOf(o.instance)); o = o.parentNode );
    return (o ? o.instance : null);
}

////////////////////////////////////////////////////////////////////////////
// class VLCtrlLibrary extends AP
////////////////////////////////////////////////////////////////////////////
// VLCtrlLibrary DOM
////////////////////////////////////////////////////////////////////////////
/*
ImgInput
VLOrganizer
*/
var VLCTRLLIB_FLAGS_DROPDOWNLIST        = 0x01;
////////////////////////////////////////////////////////////////////////////
// constructor
////////////////////////////////////////////////////////////////////////////
VLCtrlLibrary = function()
{
    this.subclass = AP;
    this.subclass();

    this.input = new ImgInput();
    this.vlOrganizer = new VLOrganizer();
    
    this._value = {
        vl_addr: null,
        vl_domain: null,
        vl_name: null,
        folder_id: -1,
        full_name: null
    };
    
    this.className = "VLCtrlLibrary";
}
VLCtrlLibrary.prototype = new AP;

////////////////////////////////////////////////////////////////////////////
// create
////////////////////////////////////////////////////////////////////////////
VLCtrlLibrary.prototype.create = function(parent, flags, tabIndex)
{
    this.flags = AP.is_set(flags, 0);
    this.subclass = AP.prototype.create;
    this.subclass(parent, "vl_ctrl_library");
   
    this.input.create(parent, "", IMGIN_FLAGS_TEXT | IMGIN_FLAGS_READONLY);
    this.input.image({
        src: ROOT_PATH + "img_php/treeview/vl.php",
        left: true,
        cx: "19px",
        cy: "16px"
    });
    this.input.image({
        src: ROOT_PATH + "img/cb/btn1.gif",
        left: false,
        cx: "15px",
        cy: "16px"
    });
    this.input.addNotifyHandler( [VLCtrlLibrary.onImgInputNotify, this] );
    
    this.vlOrganizer.create(document.body, VL_ORGANIZER_FLAGS_LIBONLY | VL_ORGANIZER_BTN_QUICKSEARCH | WND_FLAGS_MODAL | WND_FLAGS_BORDER | WND_FLAGS_HRESIZE | WND_FLAGS_VRESIZE);
    this.vlOrganizer.element.className += " vl_ctrl_library_popup";
    this.vlOrganizer.hide();
    this.vlOrganizer.setPosition( { cy: "150", cx: "300" } );
    this.vlOrganizer.addNotifyHandler( [VLCtrlLibrary.onOrganizerNotify, this] );
    AP.addEvent(this.vlOrganizer.element, "mousedown", VLCtrlLibrary.onPopUpMouseAction);
}

////////////////////////////////////////////////////////////////////////////
// enable
////////////////////////////////////////////////////////////////////////////
VLCtrlLibrary.prototype.enable = function(doEnable)
{
    if ( AP.is_set(doEnable) )
    {
        if ( doEnable )
        {
            
        }
        else
        {
            this.vlOrganizer.hide();
        }
    }
    this.vlOrganizer.enable(doEnable);
    this.input.enable(doEnable);
    
    this.subclass = AP.prototype.enable;
    return this.subclass(doEnable);
}

////////////////////////////////////////////////////////////////////////////
// dropdown
////////////////////////////////////////////////////////////////////////////
VLCtrlLibrary.prototype.dropdown = function()
{
    this.vlOrganizer.dropdown(this.input.element, 0);
    this.vlOrganizer.scrollItemIntoView(this.vlOrganizer.focused());
    this.vlOrganizer.setFocusOnTree();
}

////////////////////////////////////////////////////////////////////////////
// _value
////////////////////////////////////////////////////////////////////////////
/*
value = {
    vl_addr: value,
    vl_domain: value,
    vl_name: value,
    folder_id: value
    full_name: value
}
*/
VLCtrlLibrary.prototype.value = function(value)
{
    if ( AP.is_set(value) )
    {
        if ( AP.is_set(value.vl_addr) && this._value.vl_addr != value.vl_addr )
        {
            this._value.vl_addr = value.vl_addr;
            this._value.full_name = null;
        }
        if ( AP.is_set(value.vl_domain) && this._value.vl_domain != value.vl_domain )
        {
            this._value.vl_domain = value.vl_domain;
            this._value.full_name = null;
        }
        
        if ( AP.is_set(value.full_name) )
        {
            if ( this._value.full_name != value.full_name )
            {
                this._value.full_name = value.full_name;
                this._value.vl_name = null;
                this._value.folder_id = -1;
                
                var vlFolderID = this.vlOrganizer.getFolderIdByFullName(this._value);
                if ( vlFolderID.found_all != true )
                {
                    this._value.full_name = null;
                }
                this._value.vl_name = vlFolderID.vl_name;
                this._value.folder_id = vlFolderID.folder_id;
            }
        }
        else
        {
            if ( AP.is_set(value.vl_name) && this._value.vl_name != value.vl_name )
            {
                this._value.vl_name = value.vl_name;
                this._value.full_name = null;
            }
            
            if ( AP.is_set(value.folder_id) && this._value.folder_id != value.folder_id )
            {
                this._value.folder_id = value.folder_id;
                this._value.full_name = null;
            }
        }
        
        if ( this._value.full_name == null )
        {
            var fullNameInfo = this.vlOrganizer.getFullFolderName(this._value);
            
            if ( !fullNameInfo.full_name )
            {
                var firstRootId = this.vlOrganizer.findItemData(TV_ROOT_ITEM_ID, {type: "vl_root"}, VLTreeView._compareItemsDataByType);
                if ( firstRootId )
                {
                    var vlInfo = this.vlOrganizer.getItemVLInfo(firstRootId);
                    this._value.vl_addr = vlInfo.vl_addr;
                    this._value.vl_domain = vlInfo.vl_domain;
                    this._value.vl_name = null;
                    this._value.folder_id = -1;
                    fullNameInfo = this.vlOrganizer.getFullFolderName(this._value);
                }
            }
            
            this._value.vl_name = fullNameInfo.vl_name;
            this._value.folder_id = fullNameInfo.folder_id;
            this._value.full_name = fullNameInfo.full_name;
            
            //alert(this._value.full_name);
            this.input.value(this._value.full_name ? this._value.full_name : "");

            if ( this._value.vl_name == "*" )
            {
                this.input.image({
                    src: ROOT_PATH + "img_php/treeview/vl_root.php",
                    left: true,
                    cx: "19px",
                    cy: "16px"
                })
            }
            else if ( this._value.folder_id != -1 )
            {
                this.input.image({
                    src: ROOT_PATH + "img_php/treeview/folder.php",
                    left: true,
                    cx: "19px",
                    cy: "16px"
                })
            }
            else
            {
                this.input.image({
                    src: ROOT_PATH + "img_php/treeview/vl.php",
                    left: true,
                    cx: "19px",
                    cy: "16px"
                })
            }

            if ( fullNameInfo.result_item )
            {
                this.vlOrganizer.smartSelect(fullNameInfo.result_item);
            }
            
            this.fireNotify(VLCTRLLIBN_CHANGED, this._value);
        }
    }

    return this._value;
}

////////////////////////////////////////////////////////////////////////////
// findValue
////////////////////////////////////////////////////////////////////////////
var VLCTRLLIB_FIND_ANY        = 0x0F;
var VLCTRLLIB_FIND_VL         = 0x01;
var VLCTRLLIB_FIND_ROOT       = 0x02;
VLCtrlLibrary.prototype.findValue = function(flags, value)
{
    flags = AP.is_set(flags, 0);
    value = AP.is_set(value, this._value);
    
    var resId = null;
    
    // Search new value in organizer and select it
    var vlRootId = this.vlOrganizer.findVLRoot(value);
    var vlItemId = this.vlOrganizer.findItemData(vlRootId, {type: "lib", id: value.vl_name});
    var folderId = null;
    if ( vlItemId )
    {
        if ( value.folder_id != -1 )
        {
            folderId = this.vlOrganizer.findItemData(vlItemId, {id: value.folder_id}, VLTreeView._compareFolderItemsData);
        }
        else
        {
            folderId = vlItemId;
        }
    }
    
    resId = folderId;
    
    if ( !resId && flags & VLCTRLLIB_FIND_VL )
    {
        resId = vlItemId;
    }
    if ( !resId && flags & VLCTRLLIB_FIND_ROOT )
    {
        resId = vlRootId;
    }
    
    return resId;
}

////////////////////////////////////////////////////////////////////////////
// setPosition
////////////////////////////////////////////////////////////////////////////
VLCtrlLibrary.prototype.setPosition = function(pos)
{
    this.subclass = AP.prototype.setPosition;
    this.subclass(pos);

    this.input.setPosition(pos);
}

////////////////////////////////////////////////////////////////////////////
// onImgInputNotify
////////////////////////////////////////////////////////////////////////////
VLCtrlLibrary.onImgInputNotify = function(param)
{
    var ctrlLib = param.subscriber;
    var input = param.producer;
    
    if ( input == ctrlLib.input )
    {
        if ( param.code == APN_STATE_CHANGED
             && (param.param.diff_state & IMGINS_OVER) )
        {
            if ( param.param.new_state & IMGINS_OVER )
            {
                input.image({
                    src: ROOT_PATH + "img/cb/btn1_over.gif",
                    left: false,
                    cx: "15px",
                    cy: "16px"
                });
            }
            else
            {
                input.image({
                    src: ROOT_PATH + "img/cb/btn1.gif",
                    left: false,
                    cx: "15px",
                    cy: "16px"
                });
            }
        }
        else if ( param.code == IMGINN_ONBTNCLICKED && param.param == 1 )
        {
            ctrlLib.dropdown();
        }   
    }
    
    return 0;
}

////////////////////////////////////////////////////////////////////////////
// onPopUpMouseAction
////////////////////////////////////////////////////////////////////////////
VLCtrlLibrary.onPopUpMouseAction = function(ev)
{
    ev || (ev = window.event);
    var obj = (AP.isIE() ? ev.srcElement : ev.target);
    if ( obj.instance && AP.is_set(obj.instance.hide) )
    {
        obj.instance.hide();
    }
    return true;
}

////////////////////////////////////////////////////////////////////////////
// redirect
VLCtrlLibrary.prototype.updateVLTree = function(info) {return this.vlOrganizer.updateVLTree(info);}
// -- redirect
////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////
// onOrganizerNotify
////////////////////////////////////////////////////////////////////////////
VLCtrlLibrary.onOrganizerNotify = function(param)
{
    var pThis = param.subscriber;
    var org = param.producer;
    
    if ( param.code == TVN_AFTER_UPDATE_TREE )
    {
        pThis._value.full_name = null;
        pThis.value(pThis.value());
    }
    
    if ( pThis.fireNotify(param.code, param.param) == -1 )
    {
        return -1;
    }
    
    if ( param.code == TVN_ITEMTEXT_CLICKED
         || param.code == TVN_ITEMICON_CLICKED
         || (param.code == TVN_ITEM_KEYPRESS && param.param.key == KEY_CODE_ENTER) )
    {
        var itemId = param.param.item;
        var itemData = pThis.vlOrganizer.itemData(itemId);
        var vlInfo = pThis.vlOrganizer.getItemVLInfo(itemId);
        if ( pThis.vlOrganizer.isFolderType(itemId) )
        {
            pThis.value({
                vl_addr: vlInfo.vl_addr,
                vl_domain: vlInfo.vl_domain,
                vl_name: pThis.vlOrganizer._getVLName(itemId),
                folder_id: itemData.id,
                full_name: null
            });
        }
        else if ( pThis.vlOrganizer.isLibrary(itemId) )
        {
            pThis.value({
                vl_addr: vlInfo.vl_addr,
                vl_domain: vlInfo.vl_domain,
                vl_name: itemData.id,
                folder_id: -1,
                full_name: null
            });
        }
        else if ( pThis.vlOrganizer.isVLRoot(itemId) )
        {
            pThis.value({
                vl_addr: vlInfo.vl_addr,
                vl_domain: vlInfo.vl_domain,
                vl_name: "*",
                folder_id: -1,
                full_name: null
            });
        }

        pThis.vlOrganizer.hide();
    }
    
    return 0;
}

////////////////////////////////////////////////////////////////////////////
// class VLCtrlChoiceListPopUp extends WndBorder
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
// constructor
////////////////////////////////////////////////////////////////////////////
VLCtrlChoiceListPopUp = function()
{
    this.subclass = WndBorder;
    this.subclass();

    this.list = new TreeViewEx({
        base_dir: ROOT_PATH + "img_php/treeview/",
        img_ext: ".php",
        img_check: TV_IMGLIST_CHECK
    });
//    this.btnOK = new ImgButton();
    
    this.className = "VLCtrlChoiceListPopUp";
}
VLCtrlChoiceListPopUp.prototype = new WndBorder;

////////////////////////////////////////////////////////////////////////////
// create
////////////////////////////////////////////////////////////////////////////
VLCtrlChoiceListPopUp.prototype.create = function(parent, caption, flags, tvFlags)
{
    flags = AP.is_set(flags, 0);
    tvFlags = AP.is_set(tvFlags, 0);
    this.subclass = WndBorder.prototype.create;
    this.subclass(parent, caption, flags);
    this.element.className += " list_wnd";

    var childArea = this.childArea();
    this.list.create(childArea, tvFlags);
    this.list.addNotifyHandler( [VLCtrlChoiceListPopUp.onControlsNotify, this] );
    
//    this.btnOK.create(childArea, IMGBTN_FLAGS_DYNAMIC | IMGBTN_FLAGS_IMAGELINE);
//    this.btnOK.text("OK");
//    this.btnOK.addNotifyHandler( [VLCtrlChoiceListPopUp.onControlsNotify, this] );
}

////////////////////////////////////////////////////////////////////////////
// destroy
////////////////////////////////////////////////////////////////////////////
VLCtrlChoiceListPopUp.prototype.destroy = function()
{
    this.list.destroy();
    
    this.subclass = AP.prototype.destroy;
    this.subclass();
}

////////////////////////////////////////////////////////////////////////////
// setPosition
////////////////////////////////////////////////////////////////////////////
VLCtrlChoiceListPopUp.prototype.setPosition = function(pos)
{
    this.subclass = WndBorder.prototype.setPosition;
    this.subclass(pos);
    
    var childArea = this.childArea();
    var tvPos = {
        x: 1,
        y: 1,
        cx: AP.clientWidth(childArea) - 2,
        cy: AP.clientHeight(childArea) - 2//22
    }
    this.list.setPosition(tvPos);
    
//    var btnPos = {
//        x: tvPos.cx - 35,
//        y: tvPos.cy + 2,
//        cx: 30,
//        cy: 18
//    }
//    this.btnOK.setPosition(btnPos);
}

////////////////////////////////////////////////////////////////////////////
// redirect
VLCtrlChoiceListPopUp.onControlsNotify = function(param) { return param.subscriber.fireNotify(param.code, param.param); }
VLCtrlChoiceListPopUp.prototype.updateTree = function(tree) {return this.list.updateTree(tree);}
VLCtrlChoiceListPopUp.prototype.insertItem = function(item) {return this.list.insertItem(item);}
VLCtrlChoiceListPopUp.prototype.qsShow = function(show, setFocus) {return this.list.qsShow(show, setFocus);}
VLCtrlChoiceListPopUp.prototype.checked = function(itemId) {return this.list.checked(itemId);}
VLCtrlChoiceListPopUp.prototype.check = function(itemId, state) {return this.list.check(itemId, state);}
VLCtrlChoiceListPopUp.prototype.focused = function(itemId) {return this.list.focused(itemId);}
VLCtrlChoiceListPopUp.prototype.findItem = function(itemFrom, findWhat, compare_function) {return this.list.findItem(itemFrom, findWhat, compare_function);}
VLCtrlChoiceListPopUp.prototype.itemText = function(textInfo) {return this.list.itemText(textInfo);}
VLCtrlChoiceListPopUp.prototype.scrollItemIntoView = function(itemId) {return this.list.scrollItemIntoView(itemId);}
VLCtrlChoiceListPopUp.prototype.setFocusOnTree = function() {return this.list.setFocusOnTree();}
// -- redirect
////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////
// class VLCtrlChoiceList extends AP
////////////////////////////////////////////////////////////////////////////
// VLCtrlChoiceList DOM
////////////////////////////////////////////////////////////////////////////
/*
ImgInput
VLCtrlChoiceListPopUp
*/
var VLCTRLLIB_FLAGS_DROPDOWNLIST        = 0x01;
////////////////////////////////////////////////////////////////////////////
// constructor
////////////////////////////////////////////////////////////////////////////
VLCtrlChoiceList = function()
{
    this.subclass = AP;
    this.subclass();

    this.input = new ImgInput();
    this.popup = new VLCtrlChoiceListPopUp();
    this._separator = " ";
    
    this.className = "VLCtrlChoiceList";
}
VLCtrlChoiceList.prototype = new AP;

////////////////////////////////////////////////////////////////////////////
// create
////////////////////////////////////////////////////////////////////////////
VLCtrlChoiceList.prototype.create = function(parent, flags)
{
    this.flags = AP.is_set(flags, 0);
    this.subclass = AP.prototype.create;
    this.subclass(parent, "vl_ctrl_choice_list");
   
    this.input.create(this.element, "", IMGIN_FLAGS_TEXT);
    this.input.image({
        src: ROOT_PATH + "img/cb/btn1.gif",
        left: false,
        cx: "15px",
        cy: "16px"
    });
    this.input.addNotifyHandler( [VLCtrlChoiceList.onImgInputNotify, this] );
    
    var wndFlags = WND_FLAGS_MODAL | WND_FLAGS_HIDDEN
        | WND_FLAGS_POPUP | WND_FLAGS_BORDER | /*WND_FLAGS_CAPTION | */WND_FLAGS_MOVE
        | WND_FLAGS_VRESIZE | WND_FLAGS_HRESIZE;
    var tvFlags = TVS_NO_LINES | TVS_CHECKBOX | TVS_QUICKSEARCH | TVS_FULLROWSELECT;
    this.popup.create(document.body, "Check items", wndFlags, tvFlags);
    this.popup.setPosition( { cy: "150", cx: "300" } );
    this.popup.appendButtons([
        {
            text: "<img style=\"margin-top: 2px; cursor: pointer;\" src=\"" + ROOT_PATH + "img/qsearch.gif\">",
            id: IDFIND
        },
        {
            text: "<span style=\"cursor: pointer;\">X</span>",
            id: IDCLOSE
        }
    ]);
    this.popup.addNotifyHandler( [VLCtrlChoiceList.onPopUpNotify, this] );
    AP.addEvent(this.popup.element, "mousedown", VLCtrlChoiceList.onPopUpMouseAction);
}

////////////////////////////////////////////////////////////////////////////
// setPosition
////////////////////////////////////////////////////////////////////////////
VLCtrlChoiceList.prototype.setPosition = function(pos)
{
    this.subclass = AP.prototype.setPosition;
    this.subclass(pos);
    
    this.input.setPosition(pos);
}

////////////////////////////////////////////////////////////////////////////
// destroy
////////////////////////////////////////////////////////////////////////////
VLCtrlChoiceList.prototype.destroy = function()
{
    this.popup.destroy();
    this.input.destroy();

    this.subclass = AP.prototype.destroy;
    this.subclass();
}

////////////////////////////////////////////////////////////////////////////
// dropdown
////////////////////////////////////////////////////////////////////////////
VLCtrlChoiceList._tv_cmpTextFunc = function(itemLeft, itemRight)
{
    var textLeft = itemLeft.text;
    var textRight = itemRight.text;
    if ( textLeft && textRight && textLeft.toLowerCase() == textRight.toLowerCase() )
    {
        return 0;
    }
    
    return -1;
}

////////////////////////////////////////////////////////////////////////////
// _checkValues
////////////////////////////////////////////////////////////////////////////
VLCtrlChoiceList.prototype._checkValues = function()
{
    var value = this.input.value();
    
    // all uncheck
    var checkedList = this.popup.checked();
    for ( var loop = 0; loop < checkedList.length; loop++ )
    {
        this.popup.check(checkedList[loop], 0);
    }
    
    // 
    var tmpArr = value.split(this._separator);
    var arrValue = [];
    for ( var loop = 0; loop < tmpArr.length; loop++ )
    {
        var val = AP.trim(tmpArr[loop]);
        if ( !val.length )
        {
            continue;
        }
        if ( val.charAt(0) == "\"" )
        {
            val = val.substr(1);
        }
        if ( val.charAt(val.length - 1) == "\"" )
        {
            val = val.substring(0, val.length - 1);
        }
        var itemId = this.popup.findItem(TV_ROOT_ITEM_ID, {text: val}, VLCtrlChoiceList._tv_cmpTextFunc);
        if ( itemId && !this.popup.checked(itemId) )
        {
            this.popup.check(itemId, TVIS_CHECKED);
        }
    }
    
    this.input.value(value);
}

////////////////////////////////////////////////////////////////////////////
// dropdown
////////////////////////////////////////////////////////////////////////////
VLCtrlChoiceList.prototype.dropdown = function(visible)
{
    if ( visible )
    {
        this._checkValues();
        
        this.popup.dropdown(this.input.element, 0);
        this.popup.scrollItemIntoView(this.popup.focused());
        this.popup.setFocusOnTree();
    }
    else
    {
        this.popup.hide();
    }
}

////////////////////////////////////////////////////////////////////////////
// redirect
VLCtrlChoiceList.prototype.updateTree = function(tree) {return this.popup.updateTree(tree);}
VLCtrlChoiceList.prototype.insertItem = function(item) {return this.popup.insertItem(item);}
VLCtrlChoiceList.prototype.value = function(val) {return this.input.value(val);}
// -- redirect
////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////
// onImgInputNotify
////////////////////////////////////////////////////////////////////////////
VLCtrlChoiceList.onImgInputNotify = function(param)
{
    var pThis = param.subscriber;
    var pObj = param.producer;
    
    if ( param.code == APN_STATE_CHANGED
         && (param.param.diff_state & IMGINS_OVER) )
    {
        if ( param.param.new_state & IMGINS_OVER )
        {
            pObj.image({
                src: ROOT_PATH + "img/cb/btn1_over.gif",
                left: false,
                cx: "15px",
                cy: "16px"
            });
        }
        else
        {
            pObj.image({
                src: ROOT_PATH + "img/cb/btn1.gif",
                left: false,
                cx: "15px",
                cy: "16px"
            });
        }
    }
    else if ( param.code == IMGINN_ONBTNCLICKED && param.param == 1 )
    {
        pThis.dropdown(true);
    }   
    
    return 0;
}

////////////////////////////////////////////////////////////////////////////
// onPopUpNotify
////////////////////////////////////////////////////////////////////////////
VLCtrlChoiceList.onPopUpNotify = function(param)
{
    var pThis = param.subscriber;
    
    if ( param.code == DLGN_BTN_CLICKED )
    {
        if ( param.param == IDCLOSE )
        {
            pThis.dropdown(false);
        }
        else if ( param.param == IDFIND )
        {
            pThis.popup.qsShow(!pThis.popup.qsShow(), true);
        }
    }
//    else if ( param.code == BTN_CLICKED )
//    {
//        pThis.dropdown(false);
//    }
    else if ( param.code == TVN_ITEM_CHECKED )
    {
        var itemId = param.param;
        var itemText = pThis.popup.itemText({
            itemId: itemId,
            column: 0
        });
        var value = pThis.input.value();
        if ( pThis.popup.checked(itemId) )
        {
            value = AP.appendSubString(value, "\"" + itemText + "\"", this._separator, false);
        }
        else
        {
            value = AP.removeSubString(value, "\"" + itemText + "\"", this._separator, false);
        }
        pThis.input.value(value);
    }
    
    return 0;
}

////////////////////////////////////////////////////////////////////////////
// onPopUpMouseAction
////////////////////////////////////////////////////////////////////////////
VLCtrlChoiceList.onPopUpMouseAction = function(ev)
{
    ev || (ev = window.event);
    var obj = (AP.isIE() ? ev.srcElement : ev.target);
    if ( obj.instance && AP.is_set(obj.instance.hide) )
    {
        obj.instance.hide();
    }
    return true;
}

////////////////////////////////////////////////////////////////////////////
// class VLMainToolBar extends WndBorder
////////////////////////////////////////////////////////////////////////////
// VLMainToolBar DOM
////////////////////////////////////////////////////////////////////////////
/*
WndBorder {
    ToolBar
}
*/
////////////////////////////////////////////////////////////////////////////
// constructor
////////////////////////////////////////////////////////////////////////////
VLMainToolBar = function()
{
    this.subclass = WndBorder;
    this.subclass();
    
    this.tb = new ToolBar();
    
    this.className = "VLMainToolBar";
}
VLMainToolBar.prototype = new WndBorder;

////////////////////////////////////////////////////////////////////////////
// create
////////////////////////////////////////////////////////////////////////////
VLMainToolBar.prototype.create = function(parent, flags)
{
    flags = AP.is_set(flags, 0);
    this.subclass = WndBorder.prototype.create;
    this.subclass(parent, "Main ToolBar", flags | WND_FLAGS_BORDER /*| WND_FLAGS_CAPTION*/ );
    this.element.className += " vl_main_toolbar";
    
    this.tb.create(this.childArea(), /*TB_FLAGS_SCROLL | */TB_FLAGS_LINEBUTTONS);
    this.tb.addNotifyHandler( [VLMainToolBar.onToolBarNotify, this] );
}

////////////////////////////////////////////////////////////////////////////
// buttonParam
////////////////////////////////////////////////////////////////////////////
VLMainToolBar.prototype.buttonParam = function(index, param)
{
    var btn = this.tb.getButton(index);
    if ( !btn )
        return null;

    if ( AP.is_set(param) )
    {
        btn.usrParam = param;
    }
    
    return btn.usrParam;
}

////////////////////////////////////////////////////////////////////////////
// redirect
VLMainToolBar.prototype.appendButton = function(btn) { return this.tb.appendButton(btn); }
VLMainToolBar.prototype.deleteAllButtons = function() { return this.tb.deleteAllButtons(); }
VLMainToolBar.prototype.getButtonCount = function() { return this.tb.getButtonCount(); }
VLMainToolBar.prototype.getButton = function(index) { return this.tb.getButton(index); }
VLMainToolBar.onToolBarNotify = function(param) { return param.subscriber.fireNotify(param.code, param.param); }
// redirect
////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////
// setPosition
////////////////////////////////////////////////////////////////////////////
VLMainToolBar.prototype.setPosition = function(pos)
{
    pos.flags = AP.is_set(pos.flags, 0);
    this.subclass = WndBorder.prototype.setPosition;
    this.subclass(pos);
    
    var client_width = null;
    if ( AP.is_set(pos.cx) !== false || (pos.flags & POS_FLAGS_RECALCULATE) )
    {
        client_width = AP.clientWidth( this.childArea() );
        client_width -= 4;
    }

    var client_height = null;
    if ( AP.is_set(pos.cy) !== false || (pos.flags & POS_FLAGS_RECALCULATE) )
    {
        client_height = AP.clientHeight( this.childArea() );
        client_height -= 4;
    }

    if ( (AP.is_set(client_width) !== false) || (AP.is_set(client_height) !== false) )
    {
        this.tb.setPosition({ cx: client_width, cy: client_height });
    }
}

////////////////////////////////////////////////////////////////////////////
// restrict
// assignChild
VLMainToolBar.prototype.assignChild = function(child) { return null; }
// restrict
////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////
// getInstance
////////////////////////////////////////////////////////////////////////////
VLMainToolBar.getInstance = function(obj)
{
    for ( var o = obj; o && !(o.instance && VLMainToolBar.prototype.isPrototypeOf(o.instance)); o = o.parentNode );
    return (o ? o.instance : null);
}

////////////////////////////////////////////////////////////////////////////
// class VLRegister extends WndBorder
////////////////////////////////////////////////////////////////////////////
// VLRegister DOM
////////////////////////////////////////////////////////////////////////////
/*
WndBorder {
    <div class="vl_logon">
        <div class="vl_reg_logo">
        </div>
        <div class="vl_reg_caption">
            <table cellpadding="0" cellspacing="0"><tr><td valign="middle">
                Enter Your Logon<br>Information
            </td></tr></table>
        </div>
        <div class="vl_reg_inputs_container">
            <div class="vl_reg_input_pair">
                <div class="vl_reg_input_name">
                    E-Mail
                </div>
                <div class="vl_reg_input_value">
                    <input type="text" value="value">
                </div>
            </div>
            <div class="vl_reg_input_pair">
                <div class="vl_reg_input_name">
                    Password
                </div>
                <div class="vl_reg_input_value">
                    <input type="text" value="value">
                </div>
            </div>
        </div>
        <div class="vl_reg_actions_container">
            <div class="vl_reg_action_link">register...</div>
            <div class="vl_reg_action_button"><button>OK</button></div>
        </div>
    </div>
    <div class="vl_register">
        <div class="vl_reg_logo">
        </div>
        <div class="vl_reg_caption">
            <table cellpadding="0" cellspacing="0"><tr><td valign="middle">
                QUOSA<br>Registration Form
            </td></tr></table>
        </div>
        <div class="vl_reg_inputs_container">
            <div class="vl_reg_input_pair">
                <div class="vl_reg_input_name">
                    Name
                </div>
                <div class="vl_reg_input_req">*</div>
                <div class="vl_reg_input_value">
                    <input type="text" value="value">
                </div>
            </div>
            <div class="vl_reg_input_pair">
                <div class="vl_reg_input_name">
                    E-Mail
                </div>
                <div class="vl_reg_input_req">*</div>
                <div class="vl_reg_input_value">
                    <input type="text" value="value">
                </div>
            </div>
            <div class="vl_reg_input_pair">
                <div class="vl_reg_input_name">
                    Password
                </div>
                <div class="vl_reg_input_req">*</div>
                <div class="vl_reg_input_value">
                    <input type="text" value="value">
                </div>
            </div>
            <div class="vl_reg_input_pair">
                <div class="vl_reg_input_name">
                    Organisation
                </div>
                <div class="vl_reg_input_value">
                    <input type="text" value="value">
                </div>
            </div>
            <div class="vl_reg_input_pair">
                <div class="vl_reg_input_name">
                    Title
                </div>
                <div class="vl_reg_input_value">
                    <input type="text" value="value">
                </div>
            </div>
            <div class="vl_reg_input_pair">
                <div class="vl_reg_input_name">
                    Department
                </div>
                <div class="vl_reg_input_value">
                    <input type="text" value="value">
                </div>
            </div>
            <div class="vl_reg_input_pair">
                <div class="vl_reg_input_name">
                    Division
                </div>
                <div class="vl_reg_input_value">
                    <input type="text" value="value">
                </div>
            </div>
            <div class="vl_reg_input_pair">
                <div class="vl_reg_input_name">
                    Phone
                </div>
                <div class="vl_reg_input_value">
                    <input type="text" value="value">
                </div>
            </div>
        </div>
        <div class="vl_reg_actions_container">
            <div class="vl_reg_action_link">log on...</div>
            <div class="vl_reg_action_button"><button>OK</button></div>
        </div>
    </div>
    <div class="vl_reg_confirm">
        <div class="vl_reg_logo">
        </div>
        <div class="vl_reg_caption">
            <table cellpadding="0" cellspacing="0"><tr><td valign="middle">
                QUOSA<br>Registration Form
            </td></tr></table>
        </div>
        <div class="vl_reg_inputs_container">
            <div class="vl_reg_input_pair">
                <div class="vl_reg_input_name">
                    Confirm E-Mail
                </div>
                <div class="vl_reg_input_value">
                    <input type="text" value="value">
                </div>
            </div>
            <div class="vl_reg_input_pair">
                <div class="vl_reg_input_name">
                    Confirm Password
                </div>
                <div class="vl_reg_input_value">
                    <input type="text" value="value">
                </div>
            </div>
        </div>
        <div class="vl_reg_actions_container">
            <div class="vl_reg_action_link">back</div>
            <div class="vl_reg_action_button"><button>Register</button></div>
        </div>
    </div>
    <div class="vl_reg_err">
        <div class="vl_reg_logo">
        </div>
        <div class="vl_reg_caption">
            <table cellpadding="0" cellspacing="0"><tr><td valign="middle">
                Error Message
            </td></tr></table>
        </div>
        <div class="vl_reg_actions_container">
            <div class="vl_reg_action_link">log on...</div>
        </div>
    </div>
}
*/
////////////////////////////////////////////////////////////////////////////
// constructor
////////////////////////////////////////////////////////////////////////////
VLRegister = function()
{
    this.subclass = WndBorder;
    this.subclass();

    this.logon = {
        divView: null,
        caption: null,
        inputs: null,
        actions: null
    };
    this.register = {
        divView: null,
        caption: null,
        inputs: null,
        actions: null
    };
    this.confirm = {
        divView: null,
        caption: null,
        inputs: null,
        actions: null
    };
    this.errReg = {
        divView: null,
        caption: null,
        inputs: null,
        actions: null
    };
    
    this.currentView = -1;
    
    this.className = "VLRegister";
}
VLRegister.prototype = new WndBorder;

////////////////////////////////////////////////////////////////////////////
// create
////////////////////////////////////////////////////////////////////////////
VLRegister.prototype.create = function(parent, flags)
{
    flags = AP.is_set(flags, WND_FLAGS_CAPTION | WND_FLAGS_BORDER | WND_FLAGS_MOVE | WND_FLAGS_MODAL);
    this.subclass = WndBorder.prototype.create;
    this.subclass(parent, "", flags);
    this.element.className += " vl_register_wnd";
    
    this._createLogOn();
    this._createRegister();
    this._createConfirm();
    this._createErrorRegMsg();
    
    this.setPosition({ x: 20, y: 30 });
}

////////////////////////////////////////////////////////////////////////////
// clear
////////////////////////////////////////////////////////////////////////////
VLRegister.prototype.clear = function()
{
    VLRegister._clearInputs(this.logon.inputs);
    VLRegister._clearInputs(this.register.inputs);
    VLRegister._clearInputs(this.confirm.inputs);
}

////////////////////////////////////////////////////////////////////////////
// getViewValues
////////////////////////////////////////////////////////////////////////////
VLRegister.prototype.getViewValues = function(view)
{
    view = AP.is_set(view, this.currentView);

    var ret = [];
    
    if ( view == VLREG_VIEW_LOGON )
    {
        ret = VLRegister._getInputsPair(this.logon.inputs);
    }
    else if ( view == VLREG_VIEW_REGISTER )
    {
        ret = VLRegister._getInputsPair(this.register.inputs);
    }
    else if ( view == VLREG_VIEW_CONFIRM_REGISTER )
    {
        ret = VLRegister._getInputsPair(this.confirm.inputs);
    }
    
    return ret;
}

////////////////////////////////////////////////////////////////////////////
// showView
////////////////////////////////////////////////////////////////////////////
var VLREG_VIEW_LOGON              = 0;
var VLREG_VIEW_REGISTER           = 1;
var VLREG_VIEW_CONFIRM_REGISTER   = 2;
var VLREG_VIEW_ERROR_MSG          = 3;
VLRegister.prototype.showView = function(view, param)
{
    AP.visible(this.element, false);
    AP.show(this.element, true);
    
    var cyView = 0;

    AP.show(this.logon.divView,       (view == VLREG_VIEW_LOGON));
    AP.show(this.register.divView,    (view == VLREG_VIEW_REGISTER));
    AP.show(this.confirm.divView,     (view == VLREG_VIEW_CONFIRM_REGISTER));
    AP.show(this.errReg.divView,      (view == VLREG_VIEW_ERROR_MSG));

    if ( view == VLREG_VIEW_LOGON )
    {
        this.caption("Log on");
        
        cyView = AP.offsetHeight(this.logon.divView);
        
        if ( AP.is_set(param, true) !== false )
        {
            VLRegister._clearInputs(this.logon.inputs);
        }
    }
    else if ( view == VLREG_VIEW_REGISTER )
    {
        this.caption("Register");
        
        cyView = AP.offsetHeight(this.register.divView);

        if ( AP.is_set(param, true) !== false )
        {
            VLRegister._clearInputs(this.register.inputs);
        }
    }
    else if ( view == VLREG_VIEW_CONFIRM_REGISTER )
    {
        this.caption("Register");
        
        cyView = AP.offsetHeight(this.confirm.divView);

        if ( AP.is_set(param, true) !== false )
        {
            VLRegister._clearInputs(this.confirm.inputs);
        }
    }
    else if ( view == VLREG_VIEW_ERROR_MSG )
    {
        this.caption("Registration Error");
        this.errReg.caption.innerHTML = param;

        cyView = AP.offsetHeight(this.errReg.divView);
    }
    else
        throw ("VLRegister.showView: incorrect view [" + view + "]");

    if ( isNaN(cyView) || (cyView <= 100) )
    {
        DebugLog.write("VLRegister.showView: Invalid cyView[" + cyView + "]");
        throw ("VLRegister.showView: Invalid cyView[" + cyView + "]");
    }
    
    this.setClientSize({ cx: 350, cy: cyView });

    this.currentView = view;
    
    if ( this.state() & WND_STATE_MODAL )
    {
        this.showModal();
    }
    else
    {
        this.show();
    }
    AP.visible(this.element, true);
}

////////////////////////////////////////////////////////////////////////////
// restrict
// assignChild
VLRegister.prototype.assignChild = function(child) { return null; }
// restrict
////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////
// _createLogOn
////////////////////////////////////////////////////////////////////////////
VLRegister.prototype._createLogOn = function()
{
    var divView = AP.createElement("div", this.childArea(), "vl_logon");
    AP.show(divView, false);

    // HDR
    this._createWndHeader(divView, "Enter Your Logon<br>Information");
    
    // Inputs
    var inputsParam = [
        {
            displayName: "E-Mail",
            required: false,
            inputName: INPUT_EMAIL,
            handler: VLRegister.onControlsNotify
        },
        {
            displayName: "Password",
            required: false,
            inputName: INPUT_PASSWORD,
            inputFlags: IMGIN_FLAGS_PASSWORD,
            handler: VLRegister.onControlsNotify
        }
    ];
    var inputs = this._createInputs(divView, inputsParam);

    // Actions
    var actionsParam = {
        link: { text: "register...", handler: VLRegister.onActionLinkClick },
        button: { text: "OK", handler: VLRegister.onControlsNotify }
    };
    var actions = this._createActions(divView, actionsParam);

    // Summary
    this.logon = {
        divView: divView,
        inputs: inputs,
        actions: actions
    };
}

////////////////////////////////////////////////////////////////////////////
// _createRegister
////////////////////////////////////////////////////////////////////////////
VLRegister.prototype._createRegister = function()
{
    var divView = AP.createElement("div", this.childArea(), "vl_register");
    AP.show(divView, false);

    // HDR
    this._createWndHeader(divView, "QUOSA<br>Registration Form");
    
    // Inputs
    var inputsParam = [
        {
            displayName: "Name",
            required: true,
            inputName: INPUT_NAME,
            handler: VLRegister.onControlsNotify
        },
        {
            displayName: "E-Mail",
            required: true,
            inputName: INPUT_EMAIL,
            handler: VLRegister.onControlsNotify
        },
        {
            displayName: "Password",
            required: true,
            inputName: INPUT_PASSWORD,
            inputFlags: IMGIN_FLAGS_PASSWORD,
            handler: VLRegister.onControlsNotify
        },
        {
            displayName: "Organization",
            required: false,
            inputName: INPUT_COMPANY,
            handler: VLRegister.onControlsNotify
        },
        {
            displayName: "Title",
            required: false,
            inputName: INPUT_TITLE,
            handler: VLRegister.onControlsNotify
        },
        {
            displayName: "Department",
            required: false,
            inputName: INPUT_DEPARTMENT,
            handler: VLRegister.onControlsNotify
        },
        {
            displayName: "Division",
            required: false,
            inputName: INPUT_DIVISION,
            handler: VLRegister.onControlsNotify
        },
        {
            displayName: "Phone",
            required: false,
            inputName: INPUT_PHONE,
            handler: VLRegister.onControlsNotify
        }
    ];
    var inputs = this._createInputs(divView, inputsParam);
    
    // Actions
    var actionsParam = {
        link: { text: "log on...", handler: VLRegister.onActionLinkClick },
        button: { text: "OK", handler: VLRegister.onControlsNotify }
    };
    var actions = this._createActions(divView, actionsParam);

    // Summary
    this.register = {
        divView: divView,
        inputs: inputs,
        actions: actions
    };
}

////////////////////////////////////////////////////////////////////////////
// _createConfirm
////////////////////////////////////////////////////////////////////////////
VLRegister.prototype._createConfirm = function()
{
    var divView = AP.createElement("div", this.childArea(), "vl_reg_confirm");
    AP.show(divView, false);

    // HDR
    this._createWndHeader(divView, "QUOSA<br>Registration Form");
    
    // Inputs
    var inputsParam = [
        {
            displayName: "Confirm E-Mail",
            required: false,
            handler: VLRegister.onControlsNotify
        },
        {
            displayName: "Confirm Password",
            required: false,
            inputFlags: IMGIN_FLAGS_PASSWORD,
            handler: VLRegister.onControlsNotify
        }
    ];
    var inputs = this._createInputs(divView, inputsParam);
    
    // Actions
    var actionsParam = {
        link: { text: "back", handler: VLRegister.onActionLinkClick },
        button: { text: "Register", handler: VLRegister.onControlsNotify }
    };
    var actions = this._createActions(divView, actionsParam);

    // Summary
    this.confirm = {
        divView: divView,
        inputs: inputs,
        actions: actions
    };
}

////////////////////////////////////////////////////////////////////////////
// _createErrorRegMsg
////////////////////////////////////////////////////////////////////////////
VLRegister.prototype._createErrorRegMsg = function()
{
    var divView = AP.createElement("div", this.childArea(), "vl_reg_err");
    AP.show(divView, false);

    // HDR
    var caption = this._createWndHeader(divView, "");
    
    // Actions
    var actionsParam = {
        link: { text: "log on...", handler: VLRegister.onActionLinkClick }
    };
    var actions = this._createActions(divView, actionsParam);

    // Summary
    this.errReg = {
        divView: divView,
        caption: caption,
        actions: actions
    };
}

////////////////////////////////////////////////////////////////////////////
// _createWndHeader
////////////////////////////////////////////////////////////////////////////
VLRegister.prototype._createWndHeader = function(parent, text)
{
    var divLogo = AP.createElement("div", parent, "vl_reg_logo");
    
    var divCaption = AP.createElement("div", parent, "vl_reg_caption");
    var cells = [[
                    [
                        null,
                        [
                            [null, null, null, null, "middle"]
                        ]
                    ]
                ]];
    var tblCaptionText = AP.createTable(0, 0, cells, divCaption);
    
    var captionText = tblCaptionText.tBodies[0].rows[0].cells[0];
    captionText.innerHTML = text;
    
    return captionText;
}

////////////////////////////////////////////////////////////////////////////
// _createInputs
////////////////////////////////////////////////////////////////////////////
/*
var inputs = [
    {
        displayName: string,
        required: boolean;
        inputName: string;
        inputFlags: int; // see ImgInput Flags
    },
    ...................
];
*/
VLRegister.prototype._createInputs = function(parent, inputsParam)
{
    var inputs = new Array();
    
    var divInputsContainer = AP.createElement("div", parent, "vl_reg_inputs_container");
    var imgInWidth = 0;
    for ( var loop = 0; loop < inputsParam.length; loop++ )
    {
        var divPair = AP.createElement("div", divInputsContainer, "vl_reg_input_pair");
        // Name
        var divName = AP.createElement("div", divPair, "vl_reg_input_name");
        divName.innerHTML = inputsParam[loop].displayName;
        // Requierd
        if ( AP.is_set(inputsParam[loop].required) && inputsParam[loop].required )
        {
            var divReq = AP.createElement("div", divPair, "vl_reg_input_req");
            divReq.innerHTML = "*";
        }
        // Value
        var divValue = AP.createElement("div", divPair, "vl_reg_input_value");
        inputs.push( new ImgInput() );
        inputs[loop].create(divValue, inputsParam[loop].inputName, inputsParam[loop].inputFlags);
        if ( !loop )
        {
            imgInWidth = AP.clientWidth(divValue);
        }
        inputs[loop].setPosition({cx: imgInWidth});
        if ( inputsParam[loop].handler )
        {
            inputs[loop].addNotifyHandler( [inputsParam[loop].handler, this] );
        }
    }
    
    return inputs;
}


////////////////////////////////////////////////////////////////////////////
// _createActions
////////////////////////////////////////////////////////////////////////////
/*
var actionsParam = {
    link: { text: string, handler: func },
    button: { text: string, handler: func }
}
*/
VLRegister.prototype._createActions = function(parent, actionsParam)
{
    var actions = {
    };
    
    var divActions = AP.createElement("div", parent, "vl_reg_actions_container");
    if ( AP.is_set(actionsParam.button) )
    {
        var divBtn = AP.createElement("div", divActions, "vl_reg_action_button ap_xp1_buttons");
        actions.button = new ImgButton();
        actions.button.create(divBtn, IMGBTN_FLAGS_IMAGELINE | IMGBTN_FLAGS_DYNAMIC);
        
        actions.button.text(actionsParam.button.text);
        if ( actionsParam.button.handler )
        {
            actions.button.addNotifyHandler( [actionsParam.button.handler, this] );
        }
        
        var imgBtnWidth = AP.clientWidth(divBtn);
        actions.button.setPosition({cx: imgBtnWidth, cy: 23});
    }
    if ( AP.is_set(actionsParam.link) )
    {
        actions.link = AP.createElement("div", divActions, "vl_reg_action_link");
        actions.link.setAttribute("tabindex", 0);
        
        actions.link.innerHTML = actionsParam.link.text;
        if ( actionsParam.link.handler )
        {
            AP.addEvent(actions.link, "click", actionsParam.link.handler);
        }
    }
    
    return actions;
}

////////////////////////////////////////////////////////////////////////////
// _clearInputs
////////////////////////////////////////////////////////////////////////////
VLRegister._clearInputs = function(inputs)
{
    for ( var loop = 0; loop < inputs.length; loop++ )
    {
        inputs[loop].value("");
    }
}

////////////////////////////////////////////////////////////////////////////
// _getInputsPair
////////////////////////////////////////////////////////////////////////////
VLRegister._getInputsPair = function(inputs)
{
    var ret = new Array();
    for ( var loop = 0; loop < inputs.length; loop++ )
    {
        if ( inputs[loop].getName() )
        {
            ret.push( [inputs[loop].getName(), inputs[loop].value()] );
        }
    }
    return ret;
}

////////////////////////////////////////////////////////////////////////////
// onLogOnClick
////////////////////////////////////////////////////////////////////////////
VLRegister.onActionLinkClick = function(ev)
{   
    ev || (ev = window.event);
    var obj = (AP.isIE() ? ev.srcElement : ev.currentTarget);

    var reg = VLRegister.getInstance(obj);
    if ( !reg )
    {
        return true;
    }
    
    if ( reg.currentView == VLREG_VIEW_LOGON )
    {
        reg.showView(VLREG_VIEW_REGISTER, false);
    }
    else if ( reg.currentView == VLREG_VIEW_REGISTER )
    {
        reg.showView(VLREG_VIEW_LOGON, false);
    }
    else if ( reg.currentView == VLREG_VIEW_CONFIRM_REGISTER )
    {
        reg.showView(VLREG_VIEW_REGISTER, false);
    }
    else if ( reg.currentView == VLREG_VIEW_ERROR_MSG )
    {
        reg.showView(VLREG_VIEW_LOGON, true);
    }
    
    return true;
}

////////////////////////////////////////////////////////////////////////////
// onControlsNotify
////////////////////////////////////////////////////////////////////////////
VLRegister.onControlsNotify = function(param)
{
    if ( param.code == BTN_CLICKED
         || (param.code == BTN_KEYPRESSED && param.param.code == KEY_CODE_ENTER)
         || (param.code == IMGINN_ONKEYPRESSED && param.param.code == KEY_CODE_ENTER) )
    {
        var reg = param.subscriber;
        if ( reg.currentView == VLREG_VIEW_LOGON )
        {
            var email = reg.logon.inputs[0].value();
            var pwd = reg.logon.inputs[1].value();
            var guest = (VLCommon.guestName(email) || VLCommon.guestEMail(email));
            if ( !guest && !AP.validEMail(email) )
            {
                alert("The EMail you entered is invalid.");
            }
            else if ( !guest && !pwd.replace(/ /ig, "").length )
            {
                alert("The Password you entered is invalid.");
            }
            else
            {
                var values = reg.getViewValues(VLREG_VIEW_LOGON);
                reg.fireNotify(VLN_REGISTER_LOGON, values);
                reg.hide();
            }
        }
        else if ( reg.currentView == VLREG_VIEW_REGISTER )
        {
            var name = reg.register.inputs[0].value();
            var email = reg.register.inputs[1].value();
            var pwd = reg.register.inputs[2].value();
            var guest = (VLCommon.guestName(email) || VLCommon.guestEMail(email));
            if ( !name.replace(/ /ig, "").length )
            {
                alert("You must fill in the required fields.\nSorry, but this \"Name\" is invalid.");
            }
            else if ( guest || !AP.validEMail(email) )
            {
                alert("You must fill in the required fields.\nSorry, but this \"E-Mail\" is invalid.");
            }
            else if ( !pwd.replace(/ /ig, "").length )
            {
                alert("You must fill in the required fields.\nSorry, but this \"Password\" is invalid.");
            }
            else
            {
                reg.showView(VLREG_VIEW_CONFIRM_REGISTER, true);
            }
        }
        else if ( reg.currentView == VLREG_VIEW_CONFIRM_REGISTER )
        {
            var email1 = reg.register.inputs[1].value();
            var pwd1 = reg.register.inputs[2].value();
            
            var email2 = reg.confirm.inputs[0].value();
            var pwd2 = reg.confirm.inputs[1].value();
            
            if ( email1.toLowerCase() != email2.toLowerCase() )
            {
                alert("The E-Mails you entered did not match.");
            }
            else if ( pwd1 != pwd2 )
            {
                alert("The Passwords you entered did not match.");
            }
            else
            {
                var values = reg.getViewValues(VLREG_VIEW_REGISTER);
                reg.fireNotify(VLN_REGISTER_REGISTER, values);
                reg.hide();
            }
        }
        else if ( reg.currentView == VLREG_VIEW_ERROR_MSG )
        {
            throw ("VLRegister.onControlsNotify: pure virtual function call");
        }
    }

    return 0;
}

////////////////////////////////////////////////////////////////////////////
// getInstance
////////////////////////////////////////////////////////////////////////////
VLRegister.getInstance = function(obj)
{
    for ( var o = obj; o && !(o.instance && VLRegister.prototype.isPrototypeOf(o.instance)); o = o.parentNode );
    return (o ? o.instance : null);
}

////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
//
// VLSettings
//
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////
// class VLConfDisplay extends AP
////////////////////////////////////////////////////////////////////////////
// VLConfDisplay DOM
////////////////////////////////////////////////////////////////////////////
/*
<div class="vl_conf_display">
    <div class="section">
        Start Page
    </div>
    <div class="section_item">
        <div class="section_item_text">Show Organizer</div>
        <div class="section_item_input">
            <input type="checkbox">
        </div>
    </div>
    <div class="section_item">
        <div class="section_item_text">View Advanced Search</div>
        <div class="section_item_input">
            <input type="checkbox">
        </div>
    </div>
    <div class="section">
        Search Results
    </div>
    <div class="section_item">
        <div class="section_item_text">Per Page</div>
        <div class="section_item_input">
            ComboBox
        </div>
    </div>
    <div class="section_item">
        <div class="section_item_text">Open Result In New Window</div>
        <div class="section_item_input">
            <input type="checkbox">
        </div>
    </div>
</div>
*/
////////////////////////////////////////////////////////////////////////////
// constructor
////////////////////////////////////////////////////////////////////////////
VLConfDisplay = function()
{
    this.subclass = AP;
    this.subclass();
    
    this.className = "VLConfDisplay";
    
    this.inputViewOrg = null;
    this.inputViewOrgTimeout = new ImgInput();
    this.cbPerPage = new ComboBox();
    this.inputViewResInNew = null;
}
VLConfDisplay.prototype = new AP;

////////////////////////////////////////////////////////////////////////////
// create
////////////////////////////////////////////////////////////////////////////
VLConfDisplay.prototype.create = function(parent)
{
    this.subclass = AP.prototype.create;
    this.subclass(parent, "vl_conf_display");

    var childArea = this.element;   

        // Start Page
    var divSection = AP.createElement("div", childArea, "section");
    divSection.innerHTML = "Start Page";
    
    var divItem = AP.createElement("div", childArea, "section_item");
    var divText = AP.createElement("div", divItem, "section_item_text");
    divText.innerHTML = "Show Organizer";
    var divInput = AP.createElement("div", divItem, "section_item_input");
    this.inputViewOrg = AP.createNamedElement({
        tagName: "input",
        parent: divInput,
        type: "checkbox"
    });

    var divItem = AP.createElement("div", childArea, "section_item");
    AP.show(divItem, false);
    var divText = AP.createElement("div", divItem, "section_item_text");
    divText.innerHTML = "Refresh Organizer Timeout (sec)";
    var divInput = AP.createElement("div", divItem, "section_item_input");
    this.inputViewOrgTimeout.create(divInput, "", IMGIN_FLAGS_NUMBER);
    this.inputViewOrgTimeout.setPosition({ cx: 60 });

        // Search Result
    var divSection = AP.createElement("div", childArea, "section");
    divSection.innerHTML = "Search Results";

    var divItem = AP.createElement("div", childArea, "section_item");
    var divText = AP.createElement("div", divItem, "section_item_text");
    divText.innerHTML = "Per Page";
    var divInput = AP.createElement("div", divItem, "section_item_input");
    this.cbPerPage.create(divInput, "", CB_FLAGS_DROPDOWNLIST | CB_FLAGS_REPLACEIMAGE);
    this.cbPerPage.setPosition({ cx: 60 });
    this.cbPerPage.appendItem({text: "10", value: 10});
    this.cbPerPage.appendItem({text: "20", value: 20});
    this.cbPerPage.appendItem({text: "50", value: 50});
    this.cbPerPage.appendItem({text: "100", value: 100});

    var divItem = AP.createElement("div", childArea, "section_item");
    var divText = AP.createElement("div", divItem, "section_item_text");
    divText.innerHTML = "Open Result In New Window";
    var divInput = AP.createElement("div", divItem, "section_item_input");
    this.inputViewResInNew = AP.createNamedElement({
        tagName: "input",
        parent: divInput,
        type: "checkbox"
    });
}

////////////////////////////////////////////////////////////////////////////
// setPosition
////////////////////////////////////////////////////////////////////////////
VLConfDisplay.prototype.setPosition = function(pos)
{
    this.subclass = AP.prototype.setPosition;
    this.subclass(pos);
    
    var inParent = this.inputViewOrgTimeout.element.parentNode;
    this.inputViewOrgTimeout.setPosition({
        x: AP.offsetWidth(inParent) - AP.offsetWidth(this.inputViewOrgTimeout.element)
    });
    
    var cbParent = this.cbPerPage.element.parentNode;
    this.cbPerPage.setPosition({
        x: AP.offsetWidth(cbParent) - AP.offsetWidth(this.cbPerPage.element)
    });
}

////////////////////////////////////////////////////////////////////////////
// values
////////////////////////////////////////////////////////////////////////////
VLConfDisplay.prototype.values = function(values)
{
    if ( AP.is_set(values) )
    {
        if ( AP.is_set(values.view_org) )
        {
            this.inputViewOrg.checked = (values.view_org ? true : false);
        }
        if ( AP.is_set(values.view_org_periodic_timout) )
        {
            this.inputViewOrgTimeout.value(Math.round(values.view_org_periodic_timout/1000));
        }
        if ( AP.is_set(values.result_per_page) )
        {
            this.cbPerPage.value(values.result_per_page);
        }
        if ( AP.is_set(values.result_view_in_new) )
        {
            this.inputViewResInNew.checked = (values.result_view_in_new ? true : false);
        }
    }
    
    var timeout = this.inputViewOrgTimeout.value();
    if ( isNaN(parseInt(timeout)) )
    {
        timeout = 60;
    }
    else
    {
        timeout = timeout;
    }
    timeout = Math.max(10, timeout);
    timeout = Math.min(600, timeout);
    timeout = timeout*1000;
    
    var ret = {
        view_org: (this.inputViewOrg.checked ? true : false),
        view_org_periodic_timout: timeout,
        result_per_page: this.cbPerPage.value(),
        result_view_in_new: (this.inputViewResInNew.checked ? true : false)
    }
    
    return ret;
}

////////////////////////////////////////////////////////////////////////////
// class VLConfServerAddr extends AP
////////////////////////////////////////////////////////////////////////////
// VLConfServerAddr DOM
////////////////////////////////////////////////////////////////////////////
/*
<div class="vl_conf_server_addr">
    <div class="input_caption">
        Virtual Library Server Address:
    </div>
    <div class="input_control">
        ImgInput - Server Address
    </div>
    <div class="buttons ap_xp1_buttons">
        ImgButton - Test
        ImgButton - Reset
    </div>
    <div class="srvaddr_test_result">
    </div>
</div>
*/
////////////////////////////////////////////////////////////////////////////
// constructor
////////////////////////////////////////////////////////////////////////////
VLConfServerAddr = function()
{
    this.subclass = AP;
    this.subclass();
    
    this.className = "VLConfServerAddr";
    
    this._ext_flags = 0;
    
    this.inputVLAddr = new ImgInput();
    this.inputVLDomain = new ImgInput();
    
    this.divBtns = null;
    this.btnTest = new ImgButton();
    this.btnReset = new ImgButton();
    
    this.divTestResult = null;
}
VLConfServerAddr.prototype = new AP;

////////////////////////////////////////////////////////////////////////////
// create
////////////////////////////////////////////////////////////////////////////
VLConfServerAddr.prototype.create = function(parent)
{
    this.subclass = AP.prototype.create;
    this.subclass(parent, "vl_conf_server_addr");

    var childArea = this.element;
    
    // Virtual Library Server Address
    var divText = AP.createElement("div", childArea, "input_caption");
    divText.innerHTML = RES_VIRTUAL_LIBRARY + " Server Address:";
    var divInput = AP.createElement("div", childArea, "input_control");
    this.inputVLAddr.create(divInput, "", IMGIN_FLAGS_TEXT);
    this.inputVLAddr.setPosition({
        x: 0,
        y: 0
    });
    // Virtual Library Domain
    var divText = AP.createElement("div", childArea, "input_caption");
    divText.innerHTML = RES_VIRTUAL_LIBRARY + " Domain:";
    AP.show(divText, false);
    var divInput = AP.createElement("div", childArea, "input_control");
    AP.show(divInput, false);
    this.inputVLDomain.create(divInput, "", IMGIN_FLAGS_TEXT);
    this.inputVLDomain.setPosition({
        x: 0,
        y: 0
    });
    
    // Buttons
    this.divBtns = AP.createElement("div", childArea, "buttons ap_xp1_buttons");
    // Test
    this.btnTest.create(this.divBtns, IMGBTN_FLAGS_DYNAMIC | IMGBTN_FLAGS_IMAGELINE);
    this.btnTest.text("Test");
    this.btnTest.setPosition({
        x: 0,
        y: 0
    });
    this.btnTest.addNotifyHandler( [VLConfServerAddr.onButtonsNotify, this] );
    // Reset
    this.btnReset.create(this.divBtns, IMGBTN_FLAGS_DYNAMIC | IMGBTN_FLAGS_IMAGELINE);
    this.btnReset.text("Reset");
    this.btnReset.setPosition({
        x: 0,
        y: 0
    });
    this.btnReset.addNotifyHandler( [VLConfServerAddr.onButtonsNotify, this] );
    
    // Test Result Area
    this.divTestResult = AP.createElement("div", childArea, "test_result");
}

////////////////////////////////////////////////////////////////////////////
// extendedFlags
////////////////////////////////////////////////////////////////////////////
var VLCONF_SRVADDR_ADDR_READONLY = 0x01;
VLConfServerAddr.prototype.extendedFlags = function(flags)
{
    if ( AP.is_set(flags) )
    {
        this._ext_flags = flags;
        this.inputVLAddr.enable(!(this._ext_flags & VLCONF_SRVADDR_ADDR_READONLY));
        this.btnReset.enable(!(this._ext_flags & VLCONF_SRVADDR_ADDR_READONLY));
    }
    
    return this._ext_flags;
}

////////////////////////////////////////////////////////////////////////////
// setPosition
////////////////////////////////////////////////////////////////////////////
VLConfServerAddr.prototype.setPosition = function(pos)
{
    pos.flags = AP.is_set(pos.flags, 0);
    this.subclass = AP.prototype.setPosition;
    this.subclass(pos);
    
    var client_width = AP.clientWidth(this.element);
    var client_height = AP.clientHeight(this.element);
    
    this.inputVLAddr.setPosition({
        cx: client_width
    })
    this.inputVLDomain.setPosition({
        cx: client_width
    })
    var btnWidth = AP.offsetWidth(this.btnTest.element);
    this.btnTest.setPosition({
        x: client_width - btnWidth*2 -10
    })
    this.btnReset.setPosition({
        x: client_width - btnWidth
    })
}
    
////////////////////////////////////////////////////////////////////////////
// values
////////////////////////////////////////////////////////////////////////////
VLConfServerAddr.prototype.values = function(values)
{
    if ( AP.is_set(values) )
    {
        if ( AP.is_set(values.vl_addr) )
        {
            this.setSrvAddrTestResult("");
            this.inputVLAddr.value(values.vl_addr);
        }
        if ( AP.is_set(values.vl_domain) )
        {
            this.setSrvAddrTestResult("");
            this.inputVLDomain.value(values.vl_domain);
        }
    }
    
    var ret = {
        vl_addr: this.inputVLAddr.value(),
        vl_domain: this.inputVLDomain.value()
    };
    
    return ret;
}

////////////////////////////////////////////////////////////////////////////
// setSrvAddrTestResult
////////////////////////////////////////////////////////////////////////////
VLConfServerAddr.prototype.setSrvAddrTestResult = function(htmResult)
{
    this.divTestResult.innerHTML = htmResult;
}

////////////////////////////////////////////////////////////////////////////
// onButtonsNotify
////////////////////////////////////////////////////////////////////////////
VLConfServerAddr.onButtonsNotify = function(param)
{
    var pThis = param.subscriber;
    
    if ( param.code == BTN_CLICKED
         || (param.code == BTN_KEYPRESSED && param.param.code == KEY_CODE_ENTER) )
    {
        if ( param.producer == pThis.btnTest )
        {
            return pThis.fireNotify(VLCONFN_ONTESTBTN_CLICK, pThis.values());
        }
        else if ( param.producer == pThis.btnReset )
        {
            return pThis.fireNotify(VLCONFN_ONRESETBTN_CLICK, null);
        }
    }
    
    return 0;
}

////////////////////////////////////////////////////////////////////////////
// class VLSettingsEx extends WndBorder
////////////////////////////////////////////////////////////////////////////
// VLSettingsEx DOM
////////////////////////////////////////////////////////////////////////////
/*
WndBorder(" vl_settings_ex") {
    <div class="tb_buttons">
        ImgButton - Connection
    </div>
    <div class="client_area">
        <div class="display_settings">
            VLConfDisplay
        </div>
        <div class="connection_settings">
            VLConfServerAddr
        </div>
    </div>
    <div class="dlg_buttons ap_xp1_buttons">
        ImgButton - OK
        ImgButton - Cancel
    </div>
}
*/
var VLSETTINGS_DISPLAY_BTN     = 0x0001;
var VLSETTINGS_DISPLAY         = 0x0003;

var VLSETTINGS_CONNECTION_BTN  = 0x0100;
var VLSETTINGS_CONNECTION      = 0x0300;
var VLSETTINGS_VLADDR_READONLY = 0x0400;
////////////////////////////////////////////////////////////////////////////
// constructor
////////////////////////////////////////////////////////////////////////////
VLSettingsEx = function()
{
    this.subclass = WndBorder;
    this.subclass();
    
    this.className = "VLSettingsEx";

    this.values = {
        vl_info: {
            vl_addr: null,
            vl_domain: null
        },
        vl_addr: null,
        vl_domain: null,
        view_org: false,
        view_org_periodic_timout: 60*1000, // 60 sec
        result_per_page: 20,
        result_view_in_new: true,
        results_hide_empty_ann_tab: false
    };

    // ToolBar
    this.divToolBar = null;
    this.btnDisplay = new ImgButton();
    this.btnConnection = new ImgButton();
    
    // Client Area
    this.divClient = null;
    this.tabs = {
        views: 0,
        current: 0
    };
    
    // Display Tab
    this.divDisplay = null;
    // Display
    this.vlDisplay = new VLConfDisplay();
    
    // Connection Tab
    this.divConnection = null;
    // Connection - Server Address
    this.vlServerAddr = new VLConfServerAddr();

    // Dialog Buttons
    this.divDlgButtons = null;
    this.btnOK = new ImgButton();
    this.btnCancel = new ImgButton();
}
VLSettingsEx.prototype = new WndBorder;

////////////////////////////////////////////////////////////////////////////
// create
////////////////////////////////////////////////////////////////////////////
VLSettingsEx.prototype.create = function(parent, flags)
{
    flags = AP.is_set(flags, 0);
    this.subclass = WndBorder.prototype.create;
    this.subclass(parent, "Preferences", flags);
    this.element.className += " vl_settings_ex";
    
    var btns = [];
    btns.push({
        text: "<span style=\"cursor: pointer;\">X<span>",
        id: IDCLOSE
    });
    this.appendButtons(btns);
    
    var childArea = this.childArea();
    
    // ToolBar
    this.divToolBar = AP.createElement("div", childArea, "tb_buttons");
    // ToolBar Buttons
        // Display
    this.btnDisplay.create(this.divToolBar, IMGBTN_FLAGS_DYNAMIC);
    this.btnDisplay.setPosition({
        x: 0,
        y: 0,
        cx: 85,
        cy: 55
    });
    this.btnDisplay.text("Display");
    this.btnDisplay.image({
        base: ROOT_PATH + "img/display3_in.gif",
        checked: ROOT_PATH + "img/display3.gif",
        disabled: ROOT_PATH + "img/display3_d.gif"
    });
    this.btnDisplay.addNotifyHandler( [VLSettingsEx.onButtonsNotify, this] );
        // Connection
    this.btnConnection.create(this.divToolBar, IMGBTN_FLAGS_DYNAMIC);
    this.btnConnection.setPosition({
        x: 0,
        y: 0,
        cx: 85,
        cy: 55
    });
    this.btnConnection.text("Connection");
    this.btnConnection.image({
        base: ROOT_PATH + "img/connection1_in.gif",
        checked: ROOT_PATH + "img/connection1.gif",
        disabled: ROOT_PATH + "img/connection1_d.gif"
    });
    this.btnConnection.addNotifyHandler( [VLSettingsEx.onButtonsNotify, this] );

    ////////////////////////////////////    
    // Client Area
    this.divClient = AP.createElement("div", childArea, "client_area");
    // Display Settings
    this.divDisplay = AP.createElement("div", this.divClient, "display_settings");
    this.vlDisplay.create(this.divDisplay);
    // Connection
    this.divConnection = AP.createElement("div", this.divClient, "connection_settings");
    // Connection - Server Address
    this.vlServerAddr.create(this.divConnection);
    this.vlServerAddr.addNotifyHandler( [VLSettingsEx.onServerAddrNotify, this] );
    // Client Area
    ////////////////////////////////////    

    // Dialog Buttons
    this.divDlgButtons = AP.createElement("div", childArea, "dlg_buttons ap_xp1_buttons");
        // OK
    this.btnOK.create(this.divDlgButtons, IMGBTN_FLAGS_DYNAMIC | IMGBTN_FLAGS_IMAGELINE);
    this.btnOK.text("OK");
    this.btnOK.setPosition({y: 4});
    this.btnOK.addNotifyHandler( [VLSettingsEx.onButtonsNotify, this] );
        // Cancel
    this.btnCancel.create(this.divDlgButtons, IMGBTN_FLAGS_DYNAMIC | IMGBTN_FLAGS_IMAGELINE);
    this.btnCancel.text("Cancel");
    this.btnCancel.setPosition({y: 4});
    this.btnCancel.addNotifyHandler( [VLSettingsEx.onButtonsNotify, this] );
}

////////////////////////////////////////////////////////////////////////////
// setPosition
////////////////////////////////////////////////////////////////////////////
VLSettingsEx.prototype.setPosition = function(pos)
{
    pos.flags = AP.is_set(pos.flags, 0);
    this.subclass = WndBorder.prototype.setPosition;
    this.subclass(pos);

    var childArea = this.childArea();
    var client_height = AP.clientHeight(childArea);
    var client_width = AP.clientWidth(childArea);
    
    // ToolBar
    var tbWidth = client_width - AP.offsetLeft(this.divToolBar)*2;
    AP.width(this.divToolBar, tbWidth);
    var btnPos = {
        x: 0
    }
    if ( this.tabs.views & VLSETTINGS_DISPLAY_BTN )
    {
        btnPos.x += AP.offsetWidth(this.btnDisplay.element);
    }
    this.btnConnection.setPosition(btnPos);
    
    
    // Dialog Button
    var btnOffset = AP.offsetLeft(this.divDlgButtons);
    var posDlgBtn = {
        y: client_height - AP.offsetHeight(this.divDlgButtons) - btnOffset,
        cx: client_width - btnOffset*2
    };
    AP.setPosition(this.divDlgButtons, posDlgBtn);
    var btnWidth = AP.offsetWidth(this.btnOK.element);
    this.btnOK.setPosition({
        x: posDlgBtn.cx - btnWidth*2 - 10
    });
    this.btnCancel.setPosition({
        x: posDlgBtn.cx - btnWidth
    });

    ////////////////////////////////////    
    // Client Area
    var clientOffset = AP.offsetLeft(this.divClient);
    var posClient = {
        cx: client_width - clientOffset*2,
        cy: posDlgBtn.y // Dialog Buttons Height
            - AP.offsetTop(this.divClient) // Top Position
            - clientOffset // Bottom Padding
    };
    AP.setPosition(this.divClient, posClient)

    // Tabs    
    var tabPos = {
        x: 20,
        y: 0,
        cx: posClient.cx - 40,
        cy: posClient.cy
    };
    // Display
    this.vlDisplay.setPosition(tabPos);
    // Connection - Server Address
    var tabPos = {
        x: 20,
        y: 30,
        cx: posClient.cx - 40,
        cy: 160
    };
    this.vlServerAddr.setPosition(tabPos);
    // Client Area
    ////////////////////////////////////    
}

////////////////////////////////////////////////////////////////////////////
// setTabs
////////////////////////////////////////////////////////////////////////////
VLSettingsEx.prototype.setTabs = function(tabs)
{
    if ( AP.is_set(tabs.views) )
    {
        this.tabs.views = tabs.views;
        
        AP.visible(this.btnDisplay.element, this.tabs.views & VLSETTINGS_DISPLAY_BTN);
        this.btnDisplay.enable((this.tabs.views & VLSETTINGS_DISPLAY) == VLSETTINGS_DISPLAY);
        
        AP.visible(this.btnConnection.element, this.tabs.views & VLSETTINGS_CONNECTION_BTN);
        this.btnConnection.enable((this.tabs.views & VLSETTINGS_CONNECTION) == VLSETTINGS_CONNECTION);
        
        var srvAddrExtFlags = this.vlServerAddr.extendedFlags();
        if ( this.tabs.views & VLSETTINGS_VLADDR_READONLY )
        {
            srvAddrExtFlags |= VLCONF_SRVADDR_ADDR_READONLY;
        }
        else
        {
            srvAddrExtFlags &= ~VLCONF_SRVADDR_ADDR_READONLY;
        }
        this.vlServerAddr.extendedFlags(srvAddrExtFlags);
        
        this.setPosition({ flags: POS_FLAGS_RECALCULATE });
    }
    
    if ( AP.is_set(tabs.current) )
    {
        this.tabs.current = tabs.current;
        
        this.btnDisplay.check( (this.tabs.current == VLSETTINGS_DISPLAY) ? BTS_CHECKED : 0 );
        this.btnConnection.check( (this.tabs.current == VLSETTINGS_CONNECTION) ? BTS_CHECKED : 0 );
        
        AP.visible(this.divDisplay, this.tabs.current == VLSETTINGS_DISPLAY );
        AP.visible(this.divConnection, this.tabs.current == VLSETTINGS_CONNECTION );
    }
}

////////////////////////////////////////////////////////////////////////////
// getSettingsParams
////////////////////////////////////////////////////////////////////////////
VLSettingsEx.prototype.getSettingsParams = function()
{
    var values = [
        [INPUT_VL_ADDR, this.values.vl_info.vl_addr],
        [INPUT_VL_DOMAIN, this.values.vl_info.vl_domain]
    ];
    
    var changed = false;
    if ( (this.tabs.views & VLSETTINGS_DISPLAY) == VLSETTINGS_DISPLAY )
    {
        var dispSettings = this.vlDisplay.values();
        if ( dispSettings.view_org != this.values.view_org )
        {
            changed = true;
            values.push([
                INPUT_VIEW_ORGANIZER, dispSettings.view_org
            ]);
        }
        if ( dispSettings.view_org_periodic_timout != this.values.view_org_periodic_timout )
        {
            changed = true;
            values.push([
                INPUT_UPDATE_ORGTIMEOUT, dispSettings.view_org_periodic_timout
            ]);
        }
        if ( dispSettings.result_per_page != this.values.result_per_page )
        {
            changed = true;
            values.push([
                INPUT_PERPAGE, dispSettings.result_per_page
            ]);
        }
        if ( dispSettings.result_view_in_new != this.values.result_view_in_new )
        {
            changed = true;
            values.push([
                INPUT_VIEW_RESINNEW, dispSettings.result_view_in_new
            ]);
        }
    }
    
    if ( (this.tabs.views & VLSETTINGS_CONNECTION) == VLSETTINGS_CONNECTION )
    {
        var connSettings = this.vlServerAddr.values();
        if ( connSettings.vl_addr != this.values.vl_addr )
        {
            changed = true;
            values.push([
                INPUT_CHANGE_VL_ADDR, connSettings.vl_addr
            ]);
        }
        if ( connSettings.vl_domain != this.values.vl_domain )
        {
            changed = true;
            values.push([
                INPUT_CHANGE_VL_DOMAIN, connSettings.vl_domain
            ]);
        }
    }
    
    return changed ? values : null;
}

////////////////////////////////////////////////////////////////////////////
// setSrvAddrTestResult
////////////////////////////////////////////////////////////////////////////
VLSettingsEx.prototype.setSrvAddrTestResult = function(htmResult)
{
    this.vlServerAddr.setSrvAddrTestResult(htmResult);
}
    
////////////////////////////////////////////////////////////////////////////
// srvAddr
////////////////////////////////////////////////////////////////////////////
VLSettingsEx.prototype.srvAddr = function(addr)
{
    return this.vlServerAddr.values({
        vl_addr: addr
    }).vl_addr;
}

////////////////////////////////////////////////////////////////////////////
// updateUI
////////////////////////////////////////////////////////////////////////////
VLSettingsEx.prototype.updateUI = function()
{
    this.vlDisplay.values(this.values);
    this.vlServerAddr.values(this.values);
}

////////////////////////////////////////////////////////////////////////////
// getValues
////////////////////////////////////////////////////////////////////////////
VLSettingsEx.prototype.getValues = function()
{
    return this.values;
}

////////////////////////////////////////////////////////////////////////////
// setValues
////////////////////////////////////////////////////////////////////////////
VLSettingsEx.prototype.setValues = function(values, update)
{
    if ( AP.is_set(values) )
    {
        if ( AP.is_set(values.vl_info) )
        {
            if ( AP.is_set(values.vl_info.vl_addr) )
            {
                this.values.vl_info.vl_addr = values.vl_info.vl_addr;
            }
            if ( AP.is_set(values.vl_info.vl_domain) )
            {
                this.values.vl_info.vl_domain = values.vl_info.vl_domain;
            }
        }
    
        var changed = false;
        // Server Address
        if ( AP.is_set(values.vl_addr) )
        {
            if ( this.values.vl_addr != values.vl_addr )
            {
                this.values.vl_addr = values.vl_addr;
                changed = true;
            }
        }
        // VL Domain
        if ( AP.is_set(values.vl_domain) )
        {
            if ( this.values.vl_domain != values.vl_domain )
            {
                this.values.vl_domain = values.vl_domain;
                changed = true;
            }
        }
        
        // UI - View Organizer as Default
        if ( AP.is_set(values.view_org) )
        {
            if ( this.values.view_org != values.view_org )
            {
                this.values.view_org = values.view_org;
                changed = true;
            }
        }
        // UI - Organizer Periodic Update Timeout
        if ( AP.is_set(values.view_org_periodic_timout) )
        {
            if ( this.values.view_org_periodic_timout != values.view_org_periodic_timout )
            {
                this.values.view_org_periodic_timout = values.view_org_periodic_timout;
                changed = true;
            }
        }
        // Search - per Page
        if ( AP.is_set(values.result_per_page) )
        {
            if ( this.values.result_per_page != values.result_per_page )
            {
                this.values.result_per_page = values.result_per_page;
                changed = true;
            }
        }
        // Search - view results in new (_blank) window
        if ( AP.is_set(values.result_view_in_new) )
        {
            if ( this.values.result_view_in_new != values.result_view_in_new )
            {
                this.values.result_view_in_new = values.result_view_in_new;
                changed = true;
            }
        }
        // Hide Annotation Tab on Meta Property if no annotations
        if ( AP.is_set(values.results_hide_empty_ann_tab) )
        {
            if ( this.values.results_hide_empty_ann_tab != values.results_hide_empty_ann_tab )
            {
                this.values.results_hide_empty_ann_tab = values.results_hide_empty_ann_tab;
                changed = true;
            }
        }
    }
    
    // Update UI 
    update = AP.is_set(update, false);
    if ( update )
    {
        this.updateUI();
    }
    
    return changed;
}

////////////////////////////////////////////////////////////////////////////
// getInstance
////////////////////////////////////////////////////////////////////////////
VLSettingsEx.getInstance = function(obj)
{
    for ( var o = obj; o && !(o.instance && VLSettingsEx.prototype.isPrototypeOf(o.instance)); o = o.parentNode );
    return (o ? o.instance : null);
}

////////////////////////////////////////////////////////////////////////////
// onButtonsNotify
////////////////////////////////////////////////////////////////////////////
VLSettingsEx.onButtonsNotify = function(param)
{
    var pThis = param.subscriber;
    
    if ( param.code == BTN_CLICKED
         || (param.code == BTN_KEYPRESSED && param.param.code == KEY_CODE_ENTER) )
    {
        if ( param.producer == pThis.btnDisplay )
        {
            pThis.setTabs({current: VLSETTINGS_DISPLAY});
        }
        else if ( param.producer == pThis.btnConnection )
        {
            pThis.setTabs({current: VLSETTINGS_CONNECTION});
        }
        else if ( param.producer == pThis.btnOK )
        {
            return pThis.fireNotify(DLGN_BTN_CLICKED, IDOK);
        }
        else if ( param.producer == pThis.btnCancel )
        {
            return pThis.fireNotify(DLGN_BTN_CLICKED, IDCANCEL);
        }
    }
    
    return 0;
}

////////////////////////////////////////////////////////////////////////////
// onButtonsNotify
////////////////////////////////////////////////////////////////////////////
VLSettingsEx.onServerAddrNotify = function(param)
{
    var pThis = param.subscriber;

    if ( param.code == VLCONFN_ONTESTBTN_CLICK
         || param.code == VLCONFN_ONRESETBTN_CLICK )
    {
        return pThis.fireNotify(param.code, param.param);
    }
    
    return 0;
}

////////////////////////////////////////////////////////////////
// class  VLAnnotationItem
////////////////////////////////////////////////////////////////
////////////////////////
/* DOM MODEL

<!-- More/less link-->
<table class="vl_ann_item">
<tr>
    <td valign="top">
        <img src="img/ai/trClose.gif" width="14" height="14" vspace="0" onclick="changeAIStatus(this);" style="cursor:pointer;"> 
        <a onclick="changeAIStatus(this); return false;">More</a>
    </td>
    <td></td>
</tr>
<tr>
    <td></td>
    <td>
<!-- //More/less link-->
<table class="vl_ann_item" cellspacing="0" cellpadding="0">
    <!-- TODO delete this tbody-->
    <tbody class="vl_ann_header_container">
        <tr>
            <td colspan="5"></td>
        </tr>
    </tbody>
    <!-- //TODO delete this tbody-->
    <!-- Tabs Tbody-->
    <tbody style="display: none;">
        <tr>
            <td class="vl_ann_header" valign="top" nowrap onclick="onImgClickAI(this, 3);" style="cursor:pointer;">
                Citation Info
            </td>
            <td width="5" height="17" align="right">
                <img src="img/ai/tabR.gif" width="5" height="17" vspace="0">
            </td>
            <td class="vl_ann_header" valign="top" nowrap onclick="onImgClickAI(this, 2);" style="cursor:pointer;">
                User Annotation
            </td>
            <td width="5" height="17" align="right">
                <img src="img/ai/tabR1.gif" width="5" height="17" vspace="0">
            </td>
            <td class="vl_underline" width="50" height="1">&nbsp;</td>
        </tr>

    </tbody>    
    <!-- //Tabs Tbody-->    

    <!-- Annotations Tbody--> 
    <tbody style="display: none;">

    <!-- Annotation header-->            
        <tr>
            <td colspan="4" class="vl_ann_field_header" valign="top" nowrap>
                <img src="img/vl_plus.gif" height="14" width="14" onclick="showUserInfo(this);" style="cursor:pointer;">
                <a href="show info" onclick="showUserInfo(this); return false;">duff</a>
            </td>
            <td colspan="1" class="vl_ann_email" valign="top" colspan="2">
                <a href="mailto:duff@quosa.com">duff@quosa.com</a>
            </td>
        </tr>
    <!-- //Annotation header-->                
    <!-- Annotation body-->                
        <tr style="display: none" owner="duff">
            <td colspan="4" class="vl_ann_field" valign="top" nowrap>
                <div>Rating</div>
            </td>
            <td colspan="1" class="vl_ann_value" valign="top" colspan="2">
                <div>3</div>
            </td>
        </tr>
    <!-- //Annotation body-->                        
    </tbody>
    <!-- //Annotations Tbody-->        
    <!-- Citations Tbody--> 
    <tbody style="display: none;">
    <!-- Citation header-->            
        <tr>
            <td colspan="5" class="vl_ann_field_header" valign="top" nowrap>
                <img src="img/vl_plus.gif" height="14" width="14" onclick="showUserInfo(this);" style="cursor:pointer;"><a href="show info" onclick="showUserInfo(this); return false;">Article</a>
            </td>
        </tr>
    <!-- //Citation header-->                
    <!-- Citation body-->                
        <tr style="display: none" owner="Article">
            <td colspan="4" class="vl_ann_field" valign="top" nowrap>
                <div>Ctation info</div>
            </td>
            <td colspan="1" class="vl_ann_value" valign="top" colspan="2">
                <div>Value 2</div>
            </td>
        </tr>
    <!-- //Citation body-->                    
    </tbody>
    <!-- //Citations Tbody--> 
</table>
        </td>
    </tr>
</table>
*/

//////metainfo structure
/*
var metainfo = {
    gcit: [
        
            group: string,
            fieldvalues: [
                {
                    fiueld: string,
                    value: string
                },
                ...........
            ]
        ......
    ],
    gann: [
        {
            uname: string,
            user-email: string,
            fieldvalues: [
                {
                    fiueld: string,
                    value: string
                },
                ...........
            ]
        },
        ...............        
    ]
}
*/
////////////




VLAnnotationItem = function(parent, metainfo, modifiedFlag, hideEmptyAnnTab)
{
    hideEmptyAnnTab = AP.is_set(hideEmptyAnnTab, false);
    
    //modifiedFlag: 1 - is modifyed
    //modifiedFlag: "-" - no  Cit Info
    var cellsT = [[[
                    null,
                    [
                        ["vl_ann_header",null,null,null,"top"],
                        ["vl_ann_tab_right_img",null,null,null,"top"],
                        ["vl_ann_header",null,null,null,"top"],
                        ["vl_ann_tab_right_img",null,null,null,"top"],
                        ["vl_underline",null,null,null,null]
                    ]
                 ]]];

    var cells1 = [[
                       [
                          null,
                          [
                              ["",null,null,null,"top"],
                              ["",null,null,null,"top"]
                          ]
                       ],
                       [
                          null,
                          [
                              ["",null,null,null,"top"],
                              ["",null,null,null,"top"]
                          ]
                       ]                       
                  ]];

    var cells2 = [
                    [
                       [
                          null,
                          [
                              ["",2,null,null,null]
                          ]
                       ]

                    ], //tbody 0
                    [
                       [
                          null,
                          [
                              [null,2,null,null,"top"]
                          ]
                       ]
                    ],  //tbody 1 Tabs
                    [], //tbody 2 Ann Data
                    []  //tbody 3 CI Data
                ];                
                
    this.element = AP.createTable(0, 0, cells1, parent, "vl_ann_item");
    this.element.instance = this;
    this.className = "VLAnnotationItem";

    this.element.tBodies[0].rows[0].cells[0].noWrap = true;

    var img = AP.createElement("img", this.element.tBodies[0].rows[0].cells[0], null);
    img.style.cursor = "pointer";
    if (modifiedFlag == 1 || modifiedFlag == -1)
    {
        img.src = ROOT_PATH + "img/ai/tr1gClose.gif";
    }
    else
    {
        img.src = ROOT_PATH + "img/ai/tr1Close.gif";
    }
    AP.addEvent(img, "click", VLAnnotationItem.changeAIStatus);
    
    var a = AP.createElement("a", this.element.tBodies[0].rows[0].cells[0], null)
    a.innerHTML = "More";
    AP.addEvent(a, "click", VLAnnotationItem.changeAIStatus);


    var parent4dataTable = this.element.tBodies[0].rows[1].cells[1];
    var dataTable = AP.createTable(2, 2, cells2, parent4dataTable, "vl_ann_item");

    var parent4tabTable = dataTable.tBodies[1].rows[0].cells[0];
    var tabTable = AP.createTable(0, 0, cellsT, parent4tabTable, "vl_ann_item");


    AP.addEvent(tabTable.tBodies[0].rows[0].cells[0], "click", VLAnnotationItem.onImgClickAI);
    AP.addEvent(tabTable.tBodies[0].rows[0].cells[2], "click", VLAnnotationItem.onImgClickAI);

    var span = AP.createElement("span", tabTable.tBodies[0].rows[0].cells[0]);
    span.innerHTML = "Citation Info";
    var span = AP.createElement("span", tabTable.tBodies[0].rows[0].cells[2]);
    span.innerHTML = "User Annotation";
    var span = AP.createElement("span", tabTable.tBodies[0].rows[0].cells[4]);
    span.innerHTML = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";

    if ( hideEmptyAnnTab && !metainfo.gann.length )
    {
        AP.show(tabTable.tBodies[0].rows[0].cells[2], false);
        AP.show(tabTable.tBodies[0].rows[0].cells[3], false);
    }
    
    AP.addEvent(AP.firstChild(tabTable.tBodies[0].rows[0].cells[0]), "click", VLAnnotationItem.onImgClickAI);
    AP.addEvent(AP.firstChild(tabTable.tBodies[0].rows[0].cells[2]), "click", VLAnnotationItem.onImgClickAI);

    var img = AP.createElement("img", tabTable.tBodies[0].rows[0].cells[1]);
    img.src = ROOT_PATH + "img/ai/tabR.gif";
    var img = AP.createElement("img", tabTable.tBodies[0].rows[0].cells[3]);
    img.src = ROOT_PATH + "img/ai/tabR1.gif";
 
    var tbody1 = dataTable.tBodies[1];
    var tbody2 = dataTable.tBodies[2];
    var tbody3 = dataTable.tBodies[3];
    AP.show(tbody1, false);
    AP.show(tbody2, false);
    AP.show(tbody3, false);

    this.metainfo = metainfo;
    this.modifiedFlag = modifiedFlag;
    this.hideEmptyAnnTab = hideEmptyAnnTab;
}

VLAnnotationItem.loadAnnotationInfo = function(parent, metainfo)
{
    var dataTable = parent;
    var annCount = 0;

    for (loop = 0; loop < metainfo.gann.length; loop++)
    {
        var obj = metainfo.gann[loop];

        if (obj.fieldvalues.length > 0)
        {
            annCount++;
            var tr = dataTable.tBodies[2].insertRow(dataTable.tBodies[2].rows.length);
            tr.setAttribute("owner", obj.uname);
            var td1 = tr.insertCell(tr.cells.length);
            //td1.className = "ap vl_ann_field_header";
            td1.vAlign = "top";
            td1.noWrap = true;

            var img = AP.createElement("img", td1);
            img.src = ROOT_PATH + "img/vl_plus.gif";
            img.style.cursor = "pointer";
            AP.addEvent(img, "click", VLAnnotationItem.showUserInfo);

            var a = AP.createElement("a", td1, null);
            a.innerHTML = (obj.uname ? obj.uname : "&nbsp;");
            AP.addEvent(a, "click", VLAnnotationItem.showUserInfo);

            var td2 = tr.insertCell(tr.cells.length);
            td2.className = "ap vl_ann_email";
            td2.vAlign = "top";

            var a = AP.createElement("a", td2, null);
            a.href = "mailto:" + (obj.user_email ? obj.user_email : "&nbsp;");
            a.innerHTML = (obj.user_email ? obj.user_email : "&nbsp;");

            for (fv  = 0; fv < obj.fieldvalues.length; fv++)
            {
                var fvo = obj.fieldvalues[fv];
                var tr1 = dataTable.tBodies[2].insertRow(dataTable.tBodies[2].rows.length);
                tr1.setAttribute("owner", obj.uname);
                var td_1 = tr1.insertCell(tr1.cells.length);
                td_1.className = "ap vl_ann_field";
                td_1.vAlign = "top";
                td_1.setAttribute("owner", obj.uname);
                var div = AP.createElement("div", td_1);
                div.innerHTML = (fvo.field ? fvo.field : "&nbsp;");

                var td_2 = tr1.insertCell(tr1.cells.length);
                td_2.className = "ap vl_ann_field";
                td_2.vAlign = "top";
                var div = AP.createElement("div", td_2);
                div.innerHTML = (fvo.value ? fvo.value : "&nbsp;");

                AP.show(tr1, false);
            }
        }

    }

    for (loop = 0; loop < metainfo.gcit.length; loop++)
    {
        var obj = metainfo.gcit[loop];
        var tr = dataTable.tBodies[3].insertRow(dataTable.tBodies[3].rows.length);
        tr.setAttribute("owner", obj.group);
        var td1 = tr.insertCell(tr.cells.length);
        td1.colSpan = "2";
        //td1.className = "ap vl_ann_field_header";
        td1.vAlign = "top";
        td1.noWrap = true;

        var img = AP.createElement("img", td1);
        img.src = ROOT_PATH + "img/vl_plus.gif";
        img.style.cursor = "pointer";
        AP.addEvent(img, "click", VLAnnotationItem.showUserInfo);

        var a = AP.createElement("a", td1, null);
        a.innerHTML = (obj.group ? obj.group : "&nbsp;");
        AP.addEvent(a, "click", VLAnnotationItem.showUserInfo);

        for (fv  = 0; fv < obj.fieldvalues.length; fv++)
        {
            var fvo = obj.fieldvalues[fv];
            var tr1 = dataTable.tBodies[3].insertRow(dataTable.tBodies[3].rows.length);
            tr1.setAttribute("owner", obj.group);
            var td_1 = tr1.insertCell(tr1.cells.length);
            td_1.className = "ap vl_ann_field";
            td_1.vAlign = "top";
            td_1.noWrap = true;
            var div = AP.createElement("div", td_1);
            div.innerHTML = (fvo.field ? fvo.field : "&nbsp;");


            var td_2 = tr1.insertCell(tr1.cells.length);
            td_2.className = "ap vl_ann_value";
            td_2.vAlign = "top";
            var div = AP.createElement("div", td_2);
            div.innerHTML = (fvo.value ? fvo.value : "&nbsp;");

            AP.show(tr1, false);
        }

    }
}

VLAnnotationItem.changeAIStatus = function(ev)
{
    ev || (ev = window.event);
    var obj = (AP.isIE() ? ev.srcElement : ev.currentTarget);
    var tbl = VLAnnotationItem.getInstance(obj, "TABLE");
    var tbl = AP.firstChild(tbl.rows[1].cells[1]);
    var td = tbl.tBodies[0].rows[0].cells[0];
    var a = obj.parentNode.getElementsByTagName("a")[0];
    var ai = VLAnnotationItem.getInstanceEx(obj);

    if (a.innerHTML == "More")
    {
        a.innerHTML = "Less"
        var img = AP.firstChild(a.parentNode);
        img.src = img.src.replace("Close", "Open");
        var metainfo = ai.metainfo;
        if ( typeof tbl.getAttribute("annLoaded") == "object" )
        {
            tbl.setAttribute("annLoaded", true);
            VLAnnotationItem.loadAnnotationInfo(tbl, metainfo);
        }
        if ( ai.hideEmptyAnnTab && !metainfo.gann.length )
        {
            VLAnnotationItem.onImgClickAI1(tbl);
        }
        else
        {
            VLAnnotationItem.onImgClickAI(ev);
        }
    }
    else 
    {
        a.innerHTML = "More"    
        var img = AP.firstChild(a.parentNode);
        img.src = img.src.replace("Open", "Close");
        VLAnnotationItem.expand(tbl, td, 0);
        AP.show(tbl.tBodies[1], false);
        // HACK for IE 6, 7
        var sr = VLSearchResults.getInstance(ai.element);
        AP.show(sr.element, false);
        AP.show(sr.element, true);
        // -- HACK for IE 6, 7
    }
    //return AP.stopEvent(ev);
}

VLAnnotationItem.onImgClickAI1 = function(obj)
{
    var num2 = 3;

    var ai = obj;
    var obj = ai.tBodies[0].rows[0].cells[0];

    VLAnnotationItem.expand(ai, obj, num2);
    VLAnnotationItem.expand(ai, obj, num2);

    return true;
}

VLAnnotationItem.onImgClickAI = function(ev)
{
    var num2 = 2;
    ev || (ev = window.event);
    var obj = (AP.isIE() ? ev.srcElement : ev.currentTarget);
    var ai = VLAnnotationItem.getInstance(obj, "TABLE");

    if (ai.rows.length == 1)
    {
        if (obj.parentNode == ai.tBodies[0].rows[0].cells[0])
        {
            num2 = 3;
        }
        var ai = VLAnnotationItem.getInstance(ai.parentNode, "TABLE");
    }
    else
    {
        var ai = AP.firstChild(ai.rows[1].cells[1]);
        var obj = ai.tBodies[0].rows[0].cells[0];
    }
    if ( !ai )
        return true;
    if ( VLAnnotationItem.expanded(obj) )
    {
        VLAnnotationItem.collapse(ai, obj, num2);
    }
    else
    {
        VLAnnotationItem.expand(ai, obj, num2);
    }

    //var tbl1 = AP.firstChild(ai.tBodies[1].rows[0].cells[0]);
    //AP.show(tbl1.tBodies[0].rows[0].cells[2], false);
    //AP.show(tbl1.tBodies[0].rows[0].cells[3], false);

    return true;
}    

VLAnnotationItem.getInstanceEx = function(obj)
{
    for ( var o = obj; o && !(o.instance && (o.instance.className == "VLAnnotationItem")); o = o.parentNode );
    return (o ? o.instance : null);
}
VLAnnotationItem.getInstance = function(obj, tag)
{
    for ( var o = obj; o && (o.nodeName != tag); o = o.parentNode );
    return (o);
}


VLAnnotationItem.expand = function(tbl, el, num2)
{
    var vli = VLAnnotationItem.getInstanceEx(el);
    var modifiedFlag = vli.modifiedFlag;

    for (i=0;i<tbl.tBodies.length;i++)
    {
        AP.show(tbl.tBodies[i], false);
    }

    var tbl1 = AP.firstChild(tbl.tBodies[1].rows[0].cells[0]);
    var cell = tbl1.tBodies[0].rows[0].cells[0];
    var cell2 = tbl1.tBodies[0].rows[0].cells[2];

    var cellNum1 = "";
    var cellNum2 = "";
    var rNum1 = "";
    var rNum2 = "";

    if (num2 == 2)
    {
        cellNum1 = "2";
        rNum2 = "1";
    }
    else
    {
        cellNum2 = "2";
        rNum1 = "1";
    }

    eval("cell"+cellNum1+".className = \"ap vl_ann_header_active\";");
    eval("cell"+cellNum2+".className = \"ap vl_ann_header\";");

    if (modifiedFlag < 0)
    {
        AP.show(cell, false);
        AP.show(tbl1.tBodies[0].rows[0].cells[1], false);
    }

    var img = AP.firstChild(tbl1.tBodies[0].rows[0].cells[1]);
    img.src = img.src.replace("R"+rNum1+".", "R"+rNum2+".");
    var img = AP.firstChild(tbl1.tBodies[0].rows[0].cells[3]);
    img.src = img.src.replace("R"+rNum2+".", "R"+rNum1+".");

    AP.show(tbl.tBodies[1], true);
    AP.show(tbl.tBodies[num2], true);
}
VLAnnotationItem.collapse = function()
{
}
VLAnnotationItem.expanded = function(cell)
{
    return (cell.className.indexOf("active") != -1);
}


VLAnnotationItem.showUserInfo = function(ev)
{
    ev || (ev = window.event);
    var obj = (AP.isIE() ? ev.srcElement : ev.currentTarget);
    var o = VLAnnotationItem.getInstance(obj, "TBODY");
    var a = obj.parentNode.getElementsByTagName("a")[0];
    var img = obj.parentNode.getElementsByTagName("img")[0];
    if (a.getAttribute("status") == "hide")
    {
        VLAnnotationItem.hideUserInfo(a);
        a.setAttribute("status", "show");
        return false;
    }
    a.setAttribute("status", "hide");
    for (var i=0; i<o.rows.length; i++)
    {
        var tr = o.rows[i];
        if (tr.getAttribute('owner') == a.innerHTML)
        {
            if ( AP.show(tr) )
            {
                tr.setAttribute("info", "");
            } else
            {
                AP.show(tr, true);
                tr.setAttribute("info", "hidden");
                img.src = img.src.replace("plus.gif", "minus.gif");
            }
         }
    }
    return false;
}

VLAnnotationItem.hideUserInfo = function(obj)
{
    var o = VLAnnotationItem.getInstance(obj, "TBODY");
    var img = obj.parentNode.getElementsByTagName("img")[0];
    
    for (var i=0; i<o.rows.length; i++)
    {
        var tr = o.rows[i];
        if (tr.getAttribute("info") != ""  && tr.getAttribute('owner') == obj.innerHTML)
        {
            tr.style.display="none";
            img.src = img.src.replace("minus.gif", "plus.gif");
        }
    }
    
    // HACK for IE 6, 7
    var sr = VLSearchResults.getInstance(obj);
    AP.show(sr.element, false);
    AP.show(sr.element, true);
    // -- HACK for IE 6, 7
}

////////////////////////////////////////////////////////////////
// class VLDocResultItem
////////////////////////////////////////////////////////////////
/*
<table class="vl_doc_result_item">
    <tr>
        <td class="vl_dri_checkbox_container" align="right">
            #Checkbox Element#
        </td>
        <td class="vl_dri_number_container" valign="top">
            #Result Number#
        </td>
        <td class="vl_dri_text_container">
            <a class="vl_dri_url" href="#url#" target="#target#">#title#</a>
            <div class="vl_dri_text">#htmText#</div>
            <div class="vl_dri_folder">Folder:<a class="vl_dri_folder_url" vl=#VirtualLibrary# folderId=#FolderID">#FolderName#</a></div>
        </td>
    </tr>
</table>
*/
/*
var resInfo = {
    type: "doc",
    num: nResult,
    vl_addr: ...
    vl_domain: ...
    title: ...
    url: ...
    perm_url: ...
    url_target: window name
    htm_text: html content,
    vl: vl name,
    folder_id: ...
    folder_name: full folder name,
    meta_info: cit & ann,
    flags: ...
}
*/
VLDocResultItem = function(parent, resInfo, withCheckBox, hideEmptyAnnTab, noFolderUrl)
{
    this.vl_addr = resInfo.vl_addr;
    this.vl_domain = resInfo.vl_domain;
    this.vl_name = resInfo.vl;
    this.folder_id = resInfo.folder_id;
    this.url = resInfo.url;
    
    this.element = AP.createElement("table", parent, "vl_doc_result_item");
    this.element.cellSpacing = 0;
    this.element.cellPadding = 0;
    this.element.instance = this;
    this.className = "VLDocResultItem";
    
    this.bd = AP.createElement("tbody");
    this.element.appendChild(this.bd);
    this.tr = this.bd.insertRow(0);

    // 
    this.tdCheck = this.tr.insertCell(this.tr.cells.length);
    this.tdCheck.className = "vl_ri_checkbox_container";
    this.tdCheck.valign="top";
    this.checkBox = AP.createNamedElement({
        tagName: "input",
        name: "document_info",
        parent: this.tdCheck,
        className: "vl_ri_checkbox",
        type: withCheckBox ? "checkbox" : "hidden"
    });
    this.checkBox.id = AP.uniqueId();
    this.checkBox.setAttribute("vl_addr", resInfo.vl_addr);
    this.checkBox.setAttribute("vl_domain", resInfo.vl_domain);
    this.checkBox.setAttribute("vl_name", resInfo.vl);
    this.checkBox.setAttribute("title", resInfo.title);
    this.checkBox.setAttribute("guid", resInfo.guid);
    // -- 
    
    this.tdNum = this.tr.insertCell(this.tr.cells.length);
    this.tdNum.className = "ap vl_dri_number_container";
    this.tdNum.align = "right";
    this.tdNum.vAlign = "top";

    this.numSpan = AP.createElement("span", this.tdNum, "ap vl_dri_number_container");
    //this.tdNum.innerHTML = resInfo.num + ".";
    this.numSpan.innerHTML = resInfo.num + ".";

    this.tdTxt = this.tr.insertCell(this.tr.cells.length);
    this.tdTxt.className = "ap vl_dri_text_container";
    this.tdTxt.align = "left";
    this.tdTxt.vAlign = "top";
    
    if ( AP.is_set(resInfo.icon) && resInfo.icon )
    {
        this.numSpan.className = "ap vl_dri_number_container_icon";
        this.icon_span = AP.createElement("span", this.tdTxt, "vl_dri_icon_span");
        this.icon = AP.createElement("img", this.icon_span, "vl_dri_icon");
        this.icon.src = ROOT_PATH + "img/ctype/" + resInfo.icon;
    }

    if ( AP.is_set(resInfo.url) && resInfo.url.length )
    {
        this.urlEl = AP.createElement("a", this.tdTxt, "vl_dri_url");
        this.urlEl.href = resInfo.url;
        this.urlEl.innerHTML = resInfo.title;
        this.setResultTarget(resInfo.url_target);
    }
    else
    {
        this.urlEl = AP.createElement("span", this.tdTxt, "vl_dri_title");
        this.urlEl.innerHTML = resInfo.title;
    }
    
    this.txtEl = AP.createElement("div", this.tdTxt, "vl_dri_text");
    this.txtEl.innerHTML = resInfo.htm_text;

    if ( resInfo.folder_id != -1 )
    {   // Not "Folder Content" Query Type
        this.folderEl = AP.createElement("div", this.tdTxt, "vl_dri_folder");
        this.folderEl.innerHTML = "Folder: ";
    
        if ( noFolderUrl )
        {
            this.urlFolderEl = AP.createElement("span", this.folderEl, "vl_dri_folder_url");
        }
        else
        {
            this.urlFolderEl = AP.createElement("a", this.folderEl, "vl_dri_folder_url");
            this.urlFolderEl.setAttribute("urlFolder", "yes");
            this.urlFolderEl.setAttribute("vl", resInfo.vl);
            this.urlFolderEl.setAttribute("folderId", resInfo.folder_id);
        }
        this.urlFolderEl.innerHTML = ( resInfo.folder_name || "unresolved" );
    }
    
    // annotations
    this.annotations = new Array();
    this.annotations.push(new VLAnnotationItem(this.tdTxt, resInfo.meta_info[0], resInfo.flags[0], hideEmptyAnnTab));
}
VLDocResultItem.prototype.setResultTarget = function(newTarget)
{
    if ( !AP.is_set(this.url) || !this.url.length )
    {
        return false;
    }
    
    if ( AP.isIE() )
    {
        // IE HACK
        if (newTarget != "_blank")
        {
            this.urlEl.target = newTarget;
            this.urlEl.onclick = null;
        }
        else
        {
            this.urlEl.target = "_blank";
            this.urlEl.onclick = function(ev)
            {
                var win = window.open('');
                win.document.location = this.href;
                return AP.stopEvent(ev);
            }
        }
        //-- IE HACK
    }
    else
    {
        this.urlEl.target = newTarget;
    }
    
    return true;
}
VLDocResultItem.getInstance = function(obj)
{
    for ( var o = obj; o && !(o.instance && (o.instance.className == "VLDocResultItem")); o = o.parentNode );
    return (o ? o.instance : null);
}

////////////////////////////////////////////////////////////////////////////
// class VLSearchResults extends WndBorder
////////////////////////////////////////////////////////////////////////////
// VLSearchResults DOM
////////////////////////////////////////////////////////////////////////////
/*
<div class="vl_search_results">
    <div class="vl_sr_hdr">
        <div class="vl_sr_hdr_folder_cnt">
            <table cellpadding=0 cellspacing=0 class="vl_sr_hdr_folder_cnt_holder">
                <tr>
                    <td>Folder:</td>
                    <td></td>
                </tr>
                <tr>
                    <td>Library:</td>
                    <td></td>
                </tr>
            </table>
        </div>
        <div class="vl_sr_hdr_toolbar_container">
            <table cellpadding=0 cellspacing=0 class="vl_sr_hdr_toolbar">
                <tr>
                    <td class="vl_sr_hdr_tb_buttons" nowrap>
                        <div class="vl_sr_tbbtn_container">
                            <!-- ImgButton -->
                        </div>
                    </td>
                    <td class="vl_sr_hdr_paging_container" valign="top">
                        <div class="vl_sr_hdr_paging_bridge">
                            <table cellpadding=0 cellspacing=0 class="vl_sr_hdr_paging">
                                <tr>
                                    <td class="vl_sr_hdr_paging_text" align="center" valign="top">
                                        <table cellpadding=0 cellspacing=0>
                                            <tr>
                                                <td>Items 1-20 of 40</td>
                                                <td>Chain Icon</td>
                                                <td>RSS Icon</td>
                                            </tr>
                                        </table>
                                    </td>
                                    <td class="vl_sr_hdr_sortby_ctrl" valign="top">
                                        <div class="vl_sortby_control">
                                            <!--SortBy Control-->
                                        </div>
                                    </td>
                                    <td class="vl_sr_hdr_perpage_ctrl" valign="top">
                                        <div class="vl_perpage_control">
                                            <div class="vl_ppc_text_container">
                                                Display:
                                            </div>
                                            <!--ComboBox-->
                                        </div>
                                    </td>
                                    <td class="vl_sr_hdr_page_ctrl" valign="top" valign="top">
                                        <table class="vl_page_control">
                                            <tr>
                                                <td class="vl_pc_prev_container">
                                                    prev
                                                </td>
                                                <td class="vl_pc_btn_container">
                                                    ImgButton
                                                </td>
                                                <td class="vl_pc_input_container">
                                                    ImgInput
                                                </td>
                                                <td class="vl_pc_txt_container" nowrap>
                                                    of 7
                                                </td>
                                                <td class="vl_pc_next_container">
                                                    next
                                                </td>
                                            </tr>
                                        </table>
                                    </td>
                                </tr>
                            </table>
                        </div>
                        <!--<input type="hidden" name="action" value="do_paging">
                        <input type="hidden" name="search_for">
                        <input type="hidden" name="VirtualLibrary">
                        <input type="hidden" name="Content">-->
                    </td>
                </tr>
            </table>
        </div>
    </div>
    <div class="vl_sr_list_container">
        <table class="vl_sr_list">
            <tr>
                <td class="vl_sr_item_container">
                    VLDocResultItem / VLFolderResultItem
                </td>
            </tr>
            .......................
        </table>        
    </div>
</div>
*/
var VLSR_FLAGS_CHECKBOX         = 0x00010000;
VLSearchResults = function(parent)
{
    this.subclass = WndBorder;
    this.subclass();
    
    this.ctrlHdr = {
        element: null
    };
    this.queryInfo = {
        element: null,
        queryName: null,
        queryValue: null,
        locationName: null,
        locationValue: null
    }
    this.tbBtns = {
        exportEN: new ImgButton()
    };
    this.tbText = {
        viewRange: null,
        chainIcon: null,
        rssIcon: null
    };

    this.ctrlSort = new VLCtrlSort();
    this.cbPerPage = new ComboBox();
    this.pageCtrl = {
        btn: new ImgButton(),
        input: new ImgInput()
    };
    
    this.divLvResults = null;
    this.bdResults = null;
    this.results_hide_empty_ann_tab = false;
    this.results_nofolderurl = false;
    this.inputSearchResults = null;
    this.vlSearchResultPage = false;
    this.elementReprintDesk = null;
    
    this.className = "VLSearchResults";
}
VLSearchResults.prototype = new WndBorder;

////////////////////////////////////////////////////////////////////////////
// create
////////////////////////////////////////////////////////////////////////////
VLSearchResults.prototype.create = function(parent, flags)
{
    flags = AP.is_set(flags, 0);
    this.subclass = WndBorder.prototype.create;
    this.subclass(parent, "Search Results", flags | WND_FLAGS_BORDER );
    this.element.className += " vl_search_results";

    // Header - begin    
    this.ctrlHdr.element = AP.createElement("div", this.childArea(), "vl_sr_hdr");
    this.ctrlHdr.element.style.background = "url(" + ROOT_PATH + RES_RESULT_LOGO + ") no-repeat 3px 3px";
    
    // Folder Content
    var cells = [[
        [
            null,
            [
                [null, null, null, null, null], // td
                [null, null, null, null, null] // td
            ] // td collection
        ], // tr
        [
            null,
            [
                [null, null, null, null, null], // td
                [null, null, null, null, null] // td
            ] // td collection
        ]  // tr
    ]];
    this.queryInfo.element = AP.createTable(0, 0, cells, this.ctrlHdr.element, "vl_sr_hdr_quiery_info");
    this.queryInfo.queryName = this.queryInfo.element.tBodies[0].rows[0].cells[0];
    this.queryInfo.queryValue = AP.createElement("b", this.queryInfo.element.tBodies[0].rows[0].cells[1]);
    this.queryInfo.locationName = this.queryInfo.element.tBodies[0].rows[1].cells[0];
    this.queryInfo.locationValue = AP.createElement("b", this.queryInfo.element.tBodies[0].rows[1].cells[1]);
    
    // Toolbar and Paging
    // Toolbar
    this.divToolBarCont = AP.createElement("div", this.ctrlHdr.element, "vl_sr_hdr_toolbar_container");
    var cells = [[[
        null,
        [
            ["vl_sr_hdr_tb_buttons", null, null, null, "top"],
            ["vl_sr_hdr_paging_container", null, null, null, "top"]
        ] // td cols
    ]]];
    this.tblToolBarContainer = AP.createTable(0, 0, cells, this.divToolBarCont, "vl_sr_hdr_toolbar");
    this.toolBarCont = {
        tdToolBar: this.tblToolBarContainer.tBodies[0].rows[0].cells[0],
        tdPaging: this.tblToolBarContainer.tBodies[0].rows[0].cells[1]
    };
    // ToolBar Buttons

    // Export End Note
    //this.tbBtns.exportEN.create(this.toolBarCont.tdToolBar, IMGBTN_FLAGS_DYNAMIC | IMGBTN_FLAGS_IMAGELINE | IMGBTN_FLAGS_ALIGN_CENTER | IMGBTN_FLAGS_VALIGN_CENTER);
    //this.tbBtns.exportEN.element.style.position = "relative"; // !!!
    //this.tbBtns.exportEN.image(ROOT_PATH + "img/toCitation.jpg");
    //this.tbBtns.exportEN.text("Citations");
    //this.tbBtns.exportEN.setPosition({ cx: 100, cy: 20 });
    //this.tbBtns.exportEN.addNotifyHandler( [VLSearchResults.onExportEndNote, this] );


    // Paging
        // DOM Hack
    var divBridge = AP.createElement("div", this.toolBarCont.tdPaging, "vl_sr_hdr_paging_bridge");
    var cells = [[[
        null,
        [
            ["vl_sr_hdr_paging_text", null, null, "center", "top"],
            ["vl_sr_hdr_sortby_ctrl", null, null, null, "top"],
            ["vl_sr_hdr_perpage_ctrl", null, null, null, "top"],
            ["vl_sr_hdr_page_ctrl", null, null, null, "top"]
        ]
    ]]];
    var tblPagingCtrl = AP.createTable(0, 0, cells, divBridge, "vl_sr_hdr_paging");
    this.pagingCtrl = {
        tdText: tblPagingCtrl.tBodies[0].rows[0].cells[0],
        sortBy: tblPagingCtrl.tBodies[0].rows[0].cells[1],
        perPage: tblPagingCtrl.tBodies[0].rows[0].cells[2],
        pageCtrl: tblPagingCtrl.tBodies[0].rows[0].cells[3]
    };
        // ToolBarText
    var cells = [[[
        null,
        [
            [null, null, null, "center", "middle"], // viewRange
            [null, null, null, "center", "middle"], // ChainIcon
            [null, null, null, "center", "middle"] // RssIcon
        ]
    ]]];
    var tblPagingCtrl = AP.createTable(0, 2, cells, this.pagingCtrl.tdText);
    this.tbText.viewRange = tblPagingCtrl.tBodies[0].rows[0].cells[0];
        // ToolBarText - RSS
    this.tbText.rssIcon = AP.createElement("a", tblPagingCtrl.tBodies[0].rows[0].cells[1], "vl_sr_hdr_rss_url");
    this.tbText.rssIcon.target = "_blank";
    var img = AP.createElement("img", this.tbText.rssIcon);
    img.src = ROOT_PATH + "img/rss.gif";
    img.title = "RSS Feed";
        // ToolBarText - Chain
    this.tbText.chainIcon = AP.createElement("a", tblPagingCtrl.tBodies[0].rows[0].cells[2], "vl_sr_hdr_perm_url");
    this.tbText.chainIcon.target = "_blank";
    var img = AP.createElement("img", this.tbText.chainIcon);
    img.src = ROOT_PATH + "img/open_in_new.gif";
    img.title = "Dynamic link to results";
        // Sort By
    var divCtrlSort = AP.createElement("div", this.pagingCtrl.sortBy, "vl_sortby_control");
    this.ctrlSort.create(divCtrlSort);
    this.ctrlSort.setPosition({cx: AP.clientWidth(divCtrlSort), cy: AP.clientHeight(divCtrlSort)})
    this.ctrlSort.addNotifyHandler( [VLSearchResults.onPageCtrl, this] );
        
        // Per Page
    var divPerPage = AP.createElement("div", this.pagingCtrl.perPage, "vl_perpage_control");
    this.divPPText = AP.createElement("div", divPerPage, "vl_ppc_text_container");
    this.divPPText.innerHTML = "Display:";
    this.cbPerPage.create(divPerPage, INPUT_PERPAGE, CB_FLAGS_DROPDOWNLIST | CB_FLAGS_REPLACEIMAGE);
    this.cbPerPage.addNotifyHandler( [VLSearchResults.onPageCtrl, this] );
    var cxText = AP.clientWidth(this.divPPText);
    var cxPerPageCtrl = AP.clientWidth(divPerPage) - cxText;
    this.cbPerPage.setPosition({ x: cxText, cx: cxPerPageCtrl });
    this.cbPerPage.appendItem({text: "10", value: 10});
    this.cbPerPage.appendItem({text: "20", value: 20});
    this.cbPerPage.appendItem({text: "50", value: 50});
    this.cbPerPage.appendItem({text: "100", value: 100});
        // Page Control
    var cells = [[[
        null,
        [
            ["vl_pc_prev_container", null, null, null, "top"],
            ["vl_pc_btn_container", null, null, null, "top"],
            ["vl_pc_input_container", null, null, null, "top"],
            ["vl_pc_txt_container", null, null, null, "top"],
            ["vl_pc_next_container", null, null, null, "top"]
        ]
    ]]];
    var tblPageCtrl = AP.createTable(0, 0, cells, this.pagingCtrl.pageCtrl, "vl_page_control");
    this.pageCtrl.prev = AP.createElement("span", tblPageCtrl.tBodies[0].rows[0].cells[0]);
    this.pageCtrl.prev.innerHTML = "prev";
    AP.addEvent(this.pageCtrl.prev, "click", VLSearchResults.onPrevPageClick);
    this.pageCtrl.of = tblPageCtrl.tBodies[0].rows[0].cells[3];
    this.pageCtrl.next = AP.createElement("span", tblPageCtrl.tBodies[0].rows[0].cells[4]);
    this.pageCtrl.next.innerHTML = "next";
    AP.addEvent(this.pageCtrl.next, "click", VLSearchResults.onNextPageClick);
    this.pageCtrl.btn.create(tblPageCtrl.tBodies[0].rows[0].cells[1],
        IMGBTN_FLAGS_DYNAMIC | IMGBTN_FLAGS_IMAGELINE | IMGBTN_FLAGS_ALIGN_CENTER | IMGBTN_FLAGS_VALIGN_CENTER);
    this.pageCtrl.btn.text("page");
    this.pageCtrl.btn.setPosition({ cx: 45, cy: 20 });
    this.pageCtrl.btn.addNotifyHandler( [VLSearchResults.onPageCtrl, this] );
    this.pageCtrl.input.create(tblPageCtrl.tBodies[0].rows[0].cells[2], INPUT_PERPAGE, IMGIN_FLAGS_TEXT);
    this.pageCtrl.input.addNotifyHandler( [VLSearchResults.onPageCtrl, this] );
    this.pageCtrl.input.image({
        src: ROOT_PATH + "img/page_num.gif",
        left: true,
        cx: "16px",
        cy: "16px"
    });
    this.pageCtrl.input.setPosition({ cx: 45, cy: 20 });
    // Header - end
    
    this.divLvResults = AP.createElement("div", this.childArea(), "vl_sr_list_container");
    this.inputSearchResults = AP.createNamedElement({
            tagName: "input",
            name: "search_results",
            parent: this.divLvResults,
            type: "hidden"
    });
    var cells = [[
    ]];
    var tblResults = AP.createTable(0, 0, cells, this.divLvResults, "vl_sr_list");
    this.bdResults = tblResults.tBodies[0];
    AP.addEvent(tblResults, "click", VLSearchResults.onResultItemClick);


    //reprint button, will change code
    /**/
    this.elementReprintDesk = AP.createElement("center", this.divLvResults);

    var linkToReprint = AP.createElement("a", this.elementReprintDesk);
    linkToReprint.href = "http://www.reprintsdesk.com/main/home.aspx";
    linkToReprint.target = "_blank";

    var spanReprintDesk = AP.createElement("span", linkToReprint);
    var imgReprintDesk =  AP.createElement("img", spanReprintDesk, "vl_rp_reprint_desk_image");
    imgReprintDesk.src = ROOT_PATH + "img/reprintdesk.gif";
    imgReprintDesk.style.border = "0px";
    AP.width(imgReprintDesk, 77);
    AP.height(imgReprintDesk, 35);

    var txtSpan = AP.createElement("span", spanReprintDesk);
    txtSpan.innerHTML = "<br clear=all>Order from Reprints Desk";

    var nbspSpan = AP.createElement("span", this.elementReprintDesk);
    nbspSpan.innerHTML = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";

    AP.show(this.elementReprintDesk, false);
    /**/


    this.setPosition({ cx: 550, cy: 300 });
}

////////////////////////////////////////////////////////////////////////////
// showReprintDesk
////////////////////////////////////////////////////////////////////////////
VLSearchResults.prototype.showReprintDesk = function(isReprintDesk)
{
    AP.show(this.elementReprintDesk, isReprintDesk);
}

////////////////////////////////////////////////////////////////////////////
// getCurrentVLInfo
////////////////////////////////////////////////////////////////////////////
VLSearchResults.prototype.getCurrentVLInfo = function()
{
    var retVal = null;
    
    var vl_addr = this.inputSearchResults.getAttribute("vl_addr");
    var vl_domain = this.inputSearchResults.getAttribute("vl_domain");
    if ( AP.is_set(vl_addr)
         || AP.is_set(vl_domain) )
    {
        retVal = {};
        if ( AP.is_set(vl_addr) )
        {
            retVal.vl_addr = vl_addr;
        }
        if ( AP.is_set(vl_domain) )
        {
            retVal.vl_domain = vl_domain;
        }
    }
    
    return retVal;
}

////////////////////////////////////////////////////////////////////////////
// getPagingParams
////////////////////////////////////////////////////////////////////////////
VLSearchResults.prototype.getPagingParams = function(newSearch)
{
    var values = [];
    // VL Address
    var vl_addr = this.inputSearchResults.getAttribute("vl_addr");
    if ( AP.is_set(vl_addr) )
    {
        values.push([INPUT_VL_ADDR, vl_addr]);
    }
    // VL Domain
    var vl_domain = this.inputSearchResults.getAttribute("vl_domain");
    if ( AP.is_set(vl_domain) )
    {
        values.push([INPUT_VL_DOMAIN, vl_domain]);
    }
    // VL Name
    var vl_name = this.inputSearchResults.getAttribute("vl_name");
    if ( AP.is_set(vl_name) )
    {
        values.push([INPUT_VIRTUAL_LIBRARY, vl_name]);
    }
    // Folder ID
    var folder_id = this.inputSearchResults.getAttribute("folder_id");
    if ( AP.is_set(folder_id) )
    {
        values.push([INPUT_FOLDERID, folder_id]);
    }
    // Search For
    var sf = this.inputSearchResults.getAttribute("sf");
    if ( AP.is_set(sf) )
    {
        values.push([INPUT_SEARCH_FOR, sf]);
    }
    // Content
    var cnt = this.inputSearchResults.getAttribute("cnt");
    if ( AP.is_set(cnt) )
    {
        values.push([INPUT_CONTENTS, cnt]);
    }
    // Other Fields
    var other_fields = this.inputSearchResults.getAttribute("other_fields");
    if ( AP.is_set(other_fields) && other_fields > 0 )
    {
        for ( var loop = 0; loop < other_fields; loop++ )
        {
            var field = this.inputSearchResults.getAttribute("Field" + loop);
            var value = this.inputSearchResults.getAttribute("Value" + loop);
            values.push(["Field" + loop, field]);
            values.push(["Value" + loop, value]);
        }
    }
    // Search In All Fields
    var search_in_all = this.inputSearchResults.getAttribute("search_in_all");
    if ( AP.is_set(search_in_all) )
    {
        values.push([INPUT_SEARCHALLFIELDS, search_in_all]);
    }
    // Search Also In Abstract
    var search_in_abstract = this.inputSearchResults.getAttribute("search_in_abstract");
    if ( AP.is_set(search_in_abstract) )
    {
        values.push([INPUT_SEARCHINABSTRACT, search_in_abstract]);
    }
    // Sort By
    var sort_by = this.inputSearchResults.getAttribute("sort_by");
    if ( AP.is_set(sort_by) )
    {
        values.push([INPUT_SORT_FIELD, sort_by]);
    }
    // Sort Direction
    var sort_direction = this.inputSearchResults.getAttribute("sort_direction");
    if ( AP.is_set(sort_direction) )
    {
        values.push([INPUT_SORT_DIRECTION, sort_direction]);
    }
    // Page Num & Action
    if ( newSearch )
    {
        values.push([INPUT_ACTION, "search_results"]);
        values.push([INPUT_PAGENUM, 1]);
    }
    else
    {
        var page_num = this.inputSearchResults.getAttribute("page_num");
        values.push([INPUT_ACTION, "do_paging"]);
        values.push([INPUT_PAGENUM, page_num]);
    }
    // Per Page
    var per_page = this.inputSearchResults.getAttribute("per_page");
    if ( AP.is_set(per_page) )
    {
        values.push([INPUT_PERPAGE, per_page]);
    }    

    return values;
}

////////////////////////////////////////////////////////////////////////////
// updateHtmQueryInfo
////////////////////////////////////////////////////////////////////////////
/*
var queryInfo = {
    vl_name: ...,
    folder_name: ...,
    sf: ...,
    htm_query: ...
};
*/
VLSearchResults.prototype.updateHtmQueryInfo = function(queryInfo)
{
    if ( !AP.is_set(queryInfo) )
    {
        queryInfo = {
            vl_name: this.inputSearchResults.getAttribute("vl_name"),
            folder_id: this.inputSearchResults.getAttribute("folder_id"),
            folder_name: this.inputSearchResults.getAttribute("folder_name"),
            sf: this.inputSearchResults.getAttribute("sf"),
            htm_query: this.inputSearchResults.getAttribute("htm_query")
        };
    }
    
    var values = {};
    
    if ( queryInfo.sf == _sfOneFolder )
    {
        values.query_name = "&nbsp;";
        values.query_value = "&nbsp;";
        values.location_name = "Folder: ";
        values.location_value = queryInfo.folder_name;
    }
    else
    {
        values.query_name = "Query: ";
        values.query_value = queryInfo.htm_query;
        if ( queryInfo.folder_id != -1 )
        {
            values.location_name = "Folder: ";
            values.location_value = queryInfo.folder_name;
        }
        else
        {
            values.location_name = RES_LIBRARY + ": ";
            values.location_value = queryInfo.vl_name;
        }
    }
    
    if ( values.location_value == "*" )
    {
        values.location_value = RES_ALL_LIBRARIES;
    }
    
    this.queryInfo.queryName.innerHTML = values.query_name;
    this.queryInfo.queryValue.innerHTML = values.query_value;
    this.queryInfo.locationName.innerHTML = values.location_name;
    this.queryInfo.locationValue.innerHTML = values.location_value;
}

////////////////////////////////////////////////////////////////////////////
// setPagingInfo
////////////////////////////////////////////////////////////////////////////
/*
var info = {
    vl_addr: VL Server Address,
    vl_domain: VL Domain Name,
    vl: value,
    folder_id: value,
    sf: value,
    cnt: value,
    htm_query: value,
    server_query: value,
    other_fields: array of {
        Field: Field Name,
        Value: value
    },
    search_in_all: value,
    search_in_abstract: value,
    sort_by: sort field name,
    sort_direction: sort direction (0-forward),
    url_dlink: value,
    url_rss: value,
    page_num: value,
    per_page: value,
    total_results: value
}
*/
VLSearchResults.prototype.setPagingInfo = function(info)
{
    // VL Address
    if ( info && AP.is_set(info.vl_addr) )
    {
        this.inputSearchResults.setAttribute("vl_addr", info.vl_addr);
    }
    // VL Domain
    if ( info && AP.is_set(info.vl_domain) )
    {
        this.inputSearchResults.setAttribute("vl_domain", info.vl_domain);
    }
    // VL Name
    if ( info && AP.is_set(info.vl) )
    {
        this.inputSearchResults.setAttribute("vl_name", info.vl);
    }
    // Folder ID
    if ( info && AP.is_set(info.folder_id) )
    {
        this.inputSearchResults.setAttribute("folder_id", info.folder_id);
    }
    // Folder Name
    if ( info && AP.is_set(info.folder_name) )
    {
        this.inputSearchResults.setAttribute("folder_name", info.folder_name);
    }
    // Search For
    if ( info && AP.is_set(info.sf) )
    {
        this.inputSearchResults.setAttribute("sf", info.sf);
    }
    // Content
    if ( info && AP.is_set(info.cnt) )
    {
        this.inputSearchResults.setAttribute("cnt", info.cnt);
    }
    // Htm Query
    if ( info && AP.is_set(info.htm_query) )
    {
        this.inputSearchResults.setAttribute("htm_query", info.htm_query);
    }
    // Server Query
    if ( info && AP.is_set(info.server_query) )
    {
        this.inputSearchResults.setAttribute("server_query", info.server_query);
    }
    // Server Url
    if ( info && AP.is_set(info.server_url) )
    {
        this.inputSearchResults.setAttribute("server_url", info.server_url);
    }
    // Other Fileds
    if ( info && AP.is_set(info.other_fields) )
    {
        // Remove Old Other Fields
        for ( var loop = 0; AP.is_set(this.inputSearchResults.getAttribute("Field" + loop)); loop++ )
        {
            this.inputSearchResults.removeAttribute("Field" + loop);
            this.inputSearchResults.removeAttribute("Value" + loop);
        }
        // Add New Other Fields
        this.inputSearchResults.setAttribute("other_fields", info.other_fields.length);
        for ( var loop = 0; loop < info.other_fields.length; loop++ )
        {
            this.inputSearchResults.setAttribute("Field" + loop, info.other_fields[loop].Field);
            this.inputSearchResults.setAttribute("Value" + loop, info.other_fields[loop].Value);
        }
    }
    // Search In All Fields
    if ( info && AP.is_set(info.search_in_all) )
    {
        this.inputSearchResults.setAttribute("search_in_all", info.search_in_all);
    }
    // Search Also In Abstract
    if ( info && AP.is_set(info.search_in_abstract) )
    {
        this.inputSearchResults.setAttribute("search_in_abstract", info.search_in_abstract);
    }
    // Sort By
    if ( info && AP.is_set(info.sort_by) )
    {
        this.inputSearchResults.setAttribute("sort_by", info.sort_by);
        this.ctrlSort.value({
            field: info.sort_by,
            do_not_notify: true
        });
    }
    if ( false ) // TODO: // Sort Items Count > 0
    {
        AP.show(this.pagingCtrl.sortBy, false);
    }
    else
    {
        AP.show(this.pagingCtrl.sortBy, true);
    }
    // Sort Direction
    if ( info && AP.is_set(info.sort_direction) )
    {
        this.inputSearchResults.setAttribute("sort_direction", info.sort_direction);
        this.ctrlSort.value({
            direction: info.sort_direction,
            do_not_notify: true
        });
    }
    // Url For Dynamic Links
    if ( info && AP.is_set(info.url_dlink) )
    {
        this.inputSearchResults.setAttribute("url_dlink", info.url_dlink);
    }
    // Url RSS
    if ( info && AP.is_set(info.url_rss) )
    {
        this.inputSearchResults.setAttribute("url_rss", info.url_rss);
    }
    // TotalResults
    if ( info && AP.is_set(info.total_results) )
    {
        this.inputSearchResults.setAttribute("total_results", info.total_results);
    }
    // Per Page
    if ( info && AP.is_set(info.per_page) )
    {
        this.inputSearchResults.setAttribute("per_page", info.per_page);
        this.cbPerPage.value(info.per_page);
    }
    // Page Num
    if ( info && AP.is_set(info.page_num) )
    {
        this.inputSearchResults.setAttribute("page_num", info.page_num);
        this.pageCtrl.input.value(info.page_num);
    }
    // Search ID
    if ( info && AP.is_set(info.env_id) )
    {
        this.inputSearchResults.setAttribute("env_id", info.env_id);
    }
    // export to EN
//    AP.show(this.tbBtns.exportEN.element, false);

    this.updateHtmQueryInfo();

    var totalPages = this.totalPages();
    var pageNum = this.inputSearchResults.getAttribute("page_num");
    AP.show(this.pageCtrl.prev, (pageNum > 1));
    AP.show(this.pageCtrl.btn.element, (totalPages > 1));
    AP.show(this.pageCtrl.input.element, (totalPages > 1));
    AP.show(this.pageCtrl.of, (totalPages > 1));
    AP.show(this.pageCtrl.next, (pageNum < totalPages));
    if ( totalPages > 1 )
    {
        this.pageCtrl.of.innerHTML = "of&nbsp;" + totalPages;
    }
    AP.show(this.pagingCtrl.pageCtrl, (this.totalPages() > 1));
    
    var total_results = this.inputSearchResults.getAttribute("total_results");
    if ( eval(total_results) )
    {
        this.tbText.viewRange.innerHTML = "Items: " +
            this.firstResult() + " - " +
            this.lastResult() + " of " +
            total_results;
        
        var srUrlPart = 
            INPUT_ACTION + "=search_results" +
            (AP.is_set(this.inputSearchResults.getAttribute("vl_addr")) ? ("&" + INPUT_VL_ADDR + "=" + this.inputSearchResults.getAttribute("vl_addr")) : "") +
            (AP.is_set(this.inputSearchResults.getAttribute("vl_domain")) ? ("&" + INPUT_VL_DOMAIN + "=" + this.inputSearchResults.getAttribute("vl_domain")) : "") +
            (AP.is_set(this.inputSearchResults.getAttribute("vl_name")) ? ("&" + INPUT_VIRTUAL_LIBRARY + "=" + this.inputSearchResults.getAttribute("vl_name")) : "") +
            (AP.is_set(this.inputSearchResults.getAttribute("folder_id")) ? ("&" + INPUT_FOLDERID + "=" + this.inputSearchResults.getAttribute("folder_id")) : "") +
            (AP.is_set(this.inputSearchResults.getAttribute("sf")) ? ("&" + INPUT_SEARCH_FOR + "=" + this.inputSearchResults.getAttribute("sf")) : "") +
            (AP.is_set(this.inputSearchResults.getAttribute("cnt")) ? ("&" + INPUT_CONTENTS + "=" + this.inputSearchResults.getAttribute("cnt")) : "") +
            (AP.is_set(this.inputSearchResults.getAttribute("search_in_all")) ? ("&" + INPUT_SEARCHALLFIELDS + "=" + this.inputSearchResults.getAttribute("search_in_all")) : "") +
            (AP.is_set(this.inputSearchResults.getAttribute("search_in_abstract")) ? ("&" + INPUT_SEARCHINABSTRACT + "=" + this.inputSearchResults.getAttribute("search_in_abstract")) : "");
        var other_fields = this.inputSearchResults.getAttribute("other_fields");
        if ( AP.is_set(other_fields) && other_fields > 0 )
        {
            for ( var loop = 0; loop < other_fields; loop++ )
            {
                var field = this.inputSearchResults.getAttribute("Field" + loop);
                var value = this.inputSearchResults.getAttribute("Value" + loop);
                srUrlPart += "&Field" + loop + "=" + field;
                srUrlPart += "&Value" + loop + "=" + value;
            }
        }
        
        // RSS Link
        var url_rss = this.inputSearchResults.getAttribute("url_rss");
        if ( AP.is_set(url_rss) && url_rss.length ) 
        {
            var rssUrl = url_rss + "?";
            if ( AP.is_set(this.inputSearchResults.getAttribute("env_id")) )
            {
                rssUrl += INPUT_ENVIRONMENT_ID + "=" + this.inputSearchResults.getAttribute("env_id");
            }
            else if ( _encodedKey && _encodedKey.length )
            {
                rssUrl += INPUT_ENCODEDSTRING + "=" +
                    AP.encodeStr(srUrlPart, _encodedKey);
            }
            else
            {
                rssUrl += srUrlPart;
            }
            if ( window.navigator.userAgent.indexOf("MSIE 6.0") != -1 )
            {
                this.tbText.rssIcon.onclick = function () {
                    alert("This type of the Browser does not support RSS");
                };
            }
            else
            {
                this.tbText.rssIcon.href = rssUrl;
            }
            AP.show(this.tbText.rssIcon, true);
        }
        else
        {
            AP.show(this.tbText.rssIcon, false);
        }

        // Dynamic Link
        var url_dlink = this.inputSearchResults.getAttribute("url_dlink");
        if ( AP.is_set(url_dlink) && url_dlink.length )
        {
            var permSrUrlPart = srUrlPart +
                "&" + INPUT_PERPAGE + "=" + this.cbPerPage.value() +
                "&" + INPUT_PAGENUM + "=" + this.pageCtrl.input.value();
            if ( AP.is_set(this.inputSearchResults.getAttribute("sort_by")) )
            {
                permSrUrlPart = permSrUrlPart +
                    "&" + INPUT_SORT_FIELD + "=" + this.inputSearchResults.getAttribute("sort_by") +
                    "&" + INPUT_SORT_DIRECTION + "=" + this.inputSearchResults.getAttribute("sort_direction");
            }
            var permUrl = url_dlink + "?";
            if ( AP.is_set(this.inputSearchResults.getAttribute("env_id")) )
            {
                permUrl += INPUT_ENVIRONMENT_ID + "=" + this.inputSearchResults.getAttribute("env_id");
            }
            else if ( _encodedKey && _encodedKey.length )
            {
                permUrl += INPUT_ENCODEDSTRING + "=" +
                    AP.encodeStr(permSrUrlPart, _encodedKey);
            }
            else
            {
                permUrl += permSrUrlPart;
            }
            this.tbText.chainIcon.href = permUrl;
            AP.show(this.tbText.chainIcon, true);
        }
        else
        {
            AP.show(this.tbText.chainIcon, false);
        }
    }
    else
    {
        if ( this.inputSearchResults.getAttribute("sf") == _sfOneFolder )
        {
            this.tbText.viewRange.innerHTML = "Folder Is Empty";
        }
        else
        {
            this.tbText.viewRange.innerHTML = "No Items Found";
        }
        
        AP.show(this.tbText.rssIcon, false);

        AP.show(this.tbText.chainIcon, false);
    }
    // --
    
    this.showInterval(this.firstResult(), this.lastResult());
}

////////////////////////////////////////////////////////////////////////////
// firstResult
////////////////////////////////////////////////////////////////////////////
VLSearchResults.prototype.firstResult = function(pageNum, perPage)
{
    var p = null;
    if ( !pageNum )
    {
        p = this.pageCtrl.input.value();
    }
    else
    {
        p = pageNum;
    }
    var pp = null;
    if ( !perPage )
    {
        pp = this.cbPerPage.value();
    }
    else
    {
        pp = perPage;
    }
    return Math.max((p - 1)*pp + 1, 0);
}
////////////////////////////////////////////////////////////////////////////
// lastResult
////////////////////////////////////////////////////////////////////////////
VLSearchResults.prototype.lastResult = function(pageNum, perPage, totalResults)
{
    var p = null;
    if ( !pageNum )
    {
        p = this.pageCtrl.input.value();
    }
    else
    {
        p = pageNum;
    }
    var pp = null;
    if ( !perPage )
    {
        pp = this.cbPerPage.value();
    }
    else
    {
        pp = perPage;
    }
    var t = null;
    if ( !totalResults )
    {
        t = this.inputSearchResults.getAttribute("total_results");
    }
    else
    {
        t = totalResults;
    }
    return Math.min(Math.max(p*pp, 0), t);
}
////////////////////////////////////////////////////////////////////////////
// totalPages
////////////////////////////////////////////////////////////////////////////
VLSearchResults.prototype.totalPages = function(perPage, totalResults)
{
    if ( !perPage )
    {
        pp = this.cbPerPage.value();
    }
    else
    {
        pp = perPage;
    }
    var t = null;
    if ( !totalResults )
    {
        t = this.inputSearchResults.getAttribute("total_results");
    }
    else
    {
        t = totalResults;
    }
    return Math.max(Math.ceil(t/pp), 1);
}
////////////////////////////////////////////////////////////////////////////
// checkPageNum
////////////////////////////////////////////////////////////////////////////
VLSearchResults.prototype.checkPageNum = function(page)
{
    var pageNum = (page || this.pageCtrl.input.value());
    var perPage = this.cbPerPage.value();
    pageNum = Math.max(pageNum, 1);
    pageNum = Math.min(pageNum, this.totalPages());

    return pageNum;
}

////////////////////////////////////////////////////////////////////////////
// updateSortFields
////////////////////////////////////////////////////////////////////////////
/*
var sortFields = [
    {
        text: display string,
        value: internal value for lucene
    },
    ............
]
*/
VLSearchResults.prototype.updateSortFields = function(sortFields)
{
    this.ctrlSort.updateItems(sortFields);
    if ( this.ctrlSort.getItemCount() <= 4 /*unsort + separatot + forward + backward*/ )
    {
        AP.show(this.ctrlSort.element, false);
    }
    else
    {
        AP.show(this.ctrlSort.element, true);
    }
}

////////////////////////////////////////////////////////////////////////////
// insertUniqueItem
////////////////////////////////////////////////////////////////////////////
VLSearchResults.prototype.insertUniqueItem = function(resInfo)
{
    if ( !this.bdResults.rows.length )
    {
        return this._insertItem(0, resInfo);
    }
    
    var findRes = this._findResultItemIndexEx(0, this.bdResults.rows.length - 1, resInfo.num);
    if ( findRes[0] )
    {
        this.deleteItem(findRes[1]);
    }

    return this._insertItem(findRes[1], resInfo);
}

////////////////////////////////////////////////////////////////////////////
// _insertItem
////////////////////////////////////////////////////////////////////////////
VLSearchResults.prototype._insertItem = function(index, resInfo)
{
    var itemRow = this.bdResults.insertRow(index);
    var itemTd = itemRow.insertCell(0);
    itemTd.className = "ap vl_sr_item_container";
    if ( resInfo.type == "doc" )
    {
        itemTd.itemInstance = new VLDocResultItem(itemTd, resInfo, this.flags & VLSR_FLAGS_CHECKBOX ? true : false, this.results_hide_empty_ann_tab, this.results_nofolderurl);
    }
    else
    {
        throw("Unknown Type Of resInfo");
    }
    return index;
}

////////////////////////////////////////////////////////////////////////////
// getItemResultNum
////////////////////////////////////////////////////////////////////////////
VLSearchResults.prototype.getItemResultNum = function(index)
{
    var resItem = this.bdResults.rows[index].cells[0].itemInstance;
    //var num = parseInt(resItem.tdNum.innerHTML);
    var num = parseInt(resItem.numSpan.innerHTML);
    if ( isNaN(num) ) num = -1; 
    return num;
}

// - nResult Item routine
////////////////////////////////////////////////////////////////////////////
// findResultItemIndexEx
////////////////////////////////////////////////////////////////////////////
VLSearchResults.prototype.findResultItemIndexEx = function(nResult)
{
    if ( !this.bdResults.rows.length )
    {
        return -1;
    }
    var findRes = this._findResultItemIndexEx(0, this.bdResults.rows.length - 1, nResult);
    return ( findRes[0] ? findRes[1] : -1 );
}

////////////////////////////////////////////////////////////////////////////
// _findResultItemIndexEx
////////////////////////////////////////////////////////////////////////////
VLSearchResults.prototype._findResultItemIndexEx = function(first, last, nResult)
{
    var retVal = [false, last + 1];
    var diff = last - first;
    var current = first + Math.floor(diff / 2);
    var nCurrent = this.getItemResultNum(current);
    if ( nCurrent < nResult )
    {   // in right interval
        var numLast = this.getItemResultNum(last);
        if ( nResult < numLast )
        {
            retVal = this._findResultItemIndexEx(current + 1, last, nResult);
        }
        else if ( nResult == numLast )
        {
            retVal = [true, last];
        }
        else // if ( nResult > numLast )
        {
            retVal = [false, last + 1];
        }
    }
    else if ( nCurrent == nResult )
    {
        retVal = [true, current];
    }
    else //  if ( nCurrent > nResult )
    {   // in left interval
        var numFirst = this.getItemResultNum(first);
        if ( nResult > numFirst )
        {
            retVal = this._findResultItemIndexEx(first, current - 1, nResult);
        }
        else if ( nResult == numFirst )
        {
            retVal = [true, first];
        }
        else // if ( nResult < numFirst )
        {
            retVal = [false, first];
        }
    }
    return retVal;
}

////////////////////////////////////////////////////////////////////////////
// checkInterval
////////////////////////////////////////////////////////////////////////////
VLSearchResults.prototype.checkInterval = function(nFirst, nSecond)
{
    if ( !nSecond ) // it is possible if total Results == 0
    {
        return true;
    }
    
    if ( !this.bdResults.rows.length ) // if no results is cached
    {
        return false;
    }

    var findRes = this._findResultItemIndexEx(0, this.bdResults.rows.length - 1, nFirst);
    if ( !findRes[0] )
    {
        return false;
    }

    var first = findRes[1];
    for ( var second = first; (second < this.bdResults.rows.length) && ((second - first) < (nSecond - nFirst + 1)); second++ )
    {
        var num = this.getItemResultNum(second);
        if ( num != nFirst + (second - first) )
        {
            break;
        }
    }

    return ( (second - first) == (nSecond - nFirst + 1) );
}

////////////////////////////////////////////////////////////////////////////
// showInterval
////////////////////////////////////////////////////////////////////////////
VLSearchResults.prototype.showInterval = function(nFirst, nSecond)
{
    for ( var loop = 0; loop < this.bdResults.rows.length; loop++ )
    {
        var num = this.getItemResultNum(loop);
        AP.show( this.bdResults.rows[loop], ((num >= nFirst) && (num <= nSecond)) );
    }
}
// - nResult Item routine end

////////////////////////////////////////////////////////////////////////////
// updateResultsTarget
////////////////////////////////////////////////////////////////////////////
VLSearchResults.prototype.updateResultsTarget = function(newTarget)
{
    for ( var loop = 0; loop < this.bdResults.rows.length; loop++ )
    {
        var resItem = this.bdResults.rows[loop].cells[0].itemInstance;
        if ( typeof resItem.setResultTarget != "undefined" )
        {
            resItem.setResultTarget(newTarget);
        }
    }
}

////////////////////////////////////////////////////////////////////////////
// deleteAll
////////////////////////////////////////////////////////////////////////////
VLSearchResults.prototype.deleteAll = function()
{
    while ( this.bdResults.rows.length )
    {
        this.deleteItem(0);
    }
}

////////////////////////////////////////////////////////////////////////////
// deleteItem
////////////////////////////////////////////////////////////////////////////
VLSearchResults.prototype.deleteItem = function(index)
{
    var itemTd = this.bdResults.rows[index].cells[0];
    var itemInstance = itemTd.itemInstance;
    if ( itemInstance && itemInstance.annotations )
    {   // delete All AnnotationItems
        for ( var loop = 0; loop < itemInstance.annotations.length; loop++ )
        {
            //VLAnnotationItem.destroyInstance(itemInstance.annotations[loop]);
        }
    }
    //delete itemTd.itemInstance; // in IE wrote "Object doesn't support this action
    this.bdResults.rows[index].deleteCell(0);
    this.bdResults.deleteRow(index);
}

////////////////////////////////////////////////////////////////////////////
// setPosition
////////////////////////////////////////////////////////////////////////////
VLSearchResults.prototype.setPosition = function(pos)
{    
    pos.flags = AP.is_set(pos.flags, 0);
    this.subclass = WndBorder.prototype.setPosition;
    this.subclass(pos);
    
    if ( AP.is_set(pos.cx) !== false || (pos.flags & POS_FLAGS_RECALCULATE) )
    {
        var clientWidth = AP.clientWidth( this.childArea() );
        AP.width(this.ctrlHdr.element, clientWidth);
        var hdrWidth = AP.clientWidth( this.ctrlHdr.element );
        hdrWidth -= 20;
        
        AP.width(this.tblToolBarContainer, hdrWidth);
        AP.width(this.divLvResults, clientWidth);
    }
    
    if ( AP.is_set(pos.cy) !== false || (pos.flags & POS_FLAGS_RECALCULATE) )
    {
        var clientHeight = AP.clientHeight( this.childArea() );
        var lvResultHeight = clientHeight - AP.offsetTop(this.divLvResults);

        AP.height( this.divLvResults, lvResultHeight );
    }
}


////////////////////////////////////////////////////////////////////////////
// makeSubmitENData
////////////////////////////////////////////////////////////////////////////
VLSearchResults.prototype.makeSubmitENData = function(checkedDocs)
{
    var values = new Array();

    // action
    values.push([
        INPUT_ACTION,
        "export_endnote"
    ]);
    
    for (loop=0; loop < checkedDocs.length; loop++)
    {
        values.push([
            'doc_'+loop,
            checkedDocs[loop]
        ]);
    }
    return values;
}

////////////////////////////////////////////////////////////////////////////
// _getCheckedDocs
////////////////////////////////////////////////////////////////////////////

VLSearchResults.prototype._getCheckedDocs = function()
{
    var CheckedDocs = new Array();
    var anyDoc = false;
    for (loop=0; loop < this.bdResults.rows.length; loop++)
    {
        var a = this.bdResults.rows[loop].cells[0].getElementsByTagName("input")[0];
        CheckedDocs[a.value] = a.checked;
        anyDoc = (anyDoc || a.checked)?true:false;
    }
    if (anyDoc)
    {
        return CheckedDocs;
    }
    else
    {
        return Array();
    }
}

////////////////////////////////////////////////////////////////////////////
// _onExportEN
////////////////////////////////////////////////////////////////////////////
VLSearchResults.prototype._onExportEN = function(param)
{
    var sbs = param.subscriber;
    var checkedDocs = this._getCheckedDocs();
    if (checkedDocs.length > 0)
    {
        var values = sbs.makeSubmitENData(checkedDocs);
        sbs.fireNotify(VLN_SEARCH_RESULTS_EXPORTEN_SUBMIT, values);
    }
    else
    {
        alert('Please select any document.')
    }
}

////////////////////////////////////////////////////////////////////////////
// _onItemFolderClick
////////////////////////////////////////////////////////////////////////////
VLSearchResults.prototype._onItemFolderClick = function()
{
//            [INPUT_ACTION, "search_results"],
//            [INPUT_SEARCH_FOR, _sfOneFolder],
//            [INPUT_FOLDERID, folderId],
//            [INPUT_VIRTUAL_LIBRARY, vl]
}

////////////////////////////////////////////////////////////////////////////
// _onPaging
////////////////////////////////////////////////////////////////////////////
VLSearchResults.prototype._onPaging = function(newPage)
{
    this.inputSearchResults.setAttribute("page_num", this.checkPageNum(newPage));
    this.pageCtrl.input.value(this.inputSearchResults.getAttribute("page_num"));
    var allInCache = this.checkInterval(this.firstResult(), this.lastResult());
    if ( !allInCache )
    {
        var params = this.getPagingParams(false);
        this.fireNotify(VLN_SEARCH_RESULTS_PAGING_SUBMIT, params);
    }
    
    this.setPagingInfo();
}

////////////////////////////////////////////////////////////////////////////
// getInstance
////////////////////////////////////////////////////////////////////////////
VLSearchResults.getInstance = function(obj)
{
    for ( var o = obj; o && !(o.instance && VLSearchResults.prototype.isPrototypeOf(o.instance)); o = o.parentNode );
    return (o ? o.instance : null);
}

////////////////////////////////////////////////////////////////////////////
// onResultItemClick
////////////////////////////////////////////////////////////////////////////
VLSearchResults.onResultItemClick = function(ev)
{
    ev || (ev = window.event);
    var obj = (AP.isIE() ? ev.srcElement : ev.target);
    var pThis = VLSearchResults.getInstance(obj);
    if ( !pThis )
    {
        return true;
    }
    var item = VLDocResultItem.getInstance(obj);
    if ( !item )
    {
        return true;
    }
    
    if ( obj.getAttribute("urlFolder") == "yes" )
    {
        pThis.fireNotify(VLN_SEARCH_RESULTS_ONFOLDERCLICK, {
            vl_addr: item.vl_addr,
            vl_domain: item.vl_domain,
            vl_name: item.vl_name,
            folder_id: item.folder_id
        });
    }
    else if ( obj.name == "document_info" )
    {
        if ( obj.checked )
        {
            pThis.inputSearchResults.value = AP.appendSubString(pThis.inputSearchResults.value, obj.id, "|");
        }
        else
        {
            pThis.inputSearchResults.value = AP.removeSubString(pThis.inputSearchResults.value, obj.id, "|");
        }
    }
    
    return true;
}

////////////////////////////////////////////////////////////////////////////
// onPrevPageClick
////////////////////////////////////////////////////////////////////////////
VLSearchResults.onPrevPageClick = function(ev)
{
    ev || (ev = window.event);
    var obj = (AP.isIE() ? ev.srcElement : ev.target);
    var pThis = VLSearchResults.getInstance(obj);
    if ( !pThis )
    {
        return true;
    }
    
    var curPageNum = parseInt(pThis.inputSearchResults.getAttribute("page_num"));
    pThis._onPaging(curPageNum - 1);
    
    return true;
}

////////////////////////////////////////////////////////////////////////////
// onNextPageClick
////////////////////////////////////////////////////////////////////////////
VLSearchResults.onNextPageClick = function(ev)
{
    ev || (ev = window.event);
    var obj = (AP.isIE() ? ev.srcElement : ev.target);
    var pThis = VLSearchResults.getInstance(obj);
    if ( !pThis )
    {
        return true;
    }
    
    var curPageNum = parseInt(pThis.inputSearchResults.getAttribute("page_num"));
    pThis._onPaging(curPageNum + 1);
        
    return true;
}


////////////////////////////////////////////////////////////////////////////
// onExportEndNote
////////////////////////////////////////////////////////////////////////////
VLSearchResults.onExportEndNote = function(param)
{
    var sr = param.subscriber;
    if ( param.code == BTN_CLICKED )
    {
        sr._onExportEN(param);
    }
}

////////////////////////////////////////////////////////////////////////////
// onPageCtrl
////////////////////////////////////////////////////////////////////////////
VLSearchResults.onPageCtrl = function(param)
{
    var sr = param.subscriber;
    if ( param.code == IMGINN_ONCHANGED )
    {
        // 
    }
    else if ( param.code == CBN_ONCHANGED // PerPage Change
               || (param.code == IMGINN_ONKEYPRESSED && param.param.code == KEY_CODE_ENTER) // Enter On ImgInput
               || param.code == BTN_CLICKED ) // On Page Button Click
    {
        if ( param.code == CBN_ONCHANGED )
        {
            var cb = param.producer;
            var perPage = parseInt( cb.value() );
            sr.inputSearchResults.setAttribute("per_page", perPage);
            sr.fireNotify(VLN_SEARCH_RESULTS_PERPAGE_CHANGED, perPage);
        }

        // Check For Valid Input in Page Control
        var pageNum = sr.pageCtrl.input.value();
        if ( isNaN( parseInt(pageNum) ) )
        {
            sr.pageCtrl.input.value(sr.inputSearchResults.getAttribute("page_num"));
        }
        else
        {
            sr.inputSearchResults.setAttribute("page_num", pageNum);
            if ( sr.inputSearchResults.getAttribute("page_num") != pageNum )
            {
                sr.pageCtrl.input.value(sr.inputSearchResults.getAttribute("page_num"));
            }
        }

        // Submit        
        sr._onPaging(sr.inputSearchResults.getAttribute("page_num"));
    }
    else if ( param.code == VLCTRLSORTN_CHANGED )
    {
        var value = param.param;
        sr.inputSearchResults.setAttribute("sort_by", value.field);
        sr.inputSearchResults.setAttribute("sort_direction", value.direction);
        var params = sr.getPagingParams(true);
        
        sr.fireNotify(VLN_SEARCH_RESULTS_SORT_CHANGED, value);
        sr.fireNotify(VLN_SEARCH_RESULTS_PAGING_SUBMIT, params);
    }

    return 0;
}

////////////////////////////////////////////////////////////////////////////
// class VLOtherFields extends AP
////////////////////////////////////////////////////////////////////////////
// VLOtherFields DOM
////////////////////////////////////////////////////////////////////////////
/*
WndBorder {
    ???
}
*/
////////////////////////////////////////////////////////////////////////////
// constructor
////////////////////////////////////////////////////////////////////////////
VLOtherFields = function()
{
    this.subclass = AP;
    this.subclass();
    
    this.className = "VLOtherFields";
    
    this.tblItems = null;
    this.fields = [];
    
    this.cellIndexManage = 0;
    this.cellIndexField = 1;
    this.cellIndexValue = 2;
    
    this._doRecalculate = true;
}
VLOtherFields.prototype = new AP;

////////////////////////////////////////////////////////////////////////////
// create
////////////////////////////////////////////////////////////////////////////
VLOtherFields.prototype.create = function(parent)
{
    this.subclass = AP.prototype.create;
    this.subclass(parent, "vl_other_fields");
    
    this.tblItems = AP.createTable(2, 2, [[]], this.element, "tbl_fields_values");
    
    this.insertItem();

    AP.addEvent(this.tblItems, "click", VLOtherFields.onImgActionClick);
}

////////////////////////////////////////////////////////////////////////////
// setPosition
////////////////////////////////////////////////////////////////////////////
VLOtherFields.prototype.setPosition = function(pos)
{
    pos.flags = AP.is_set(pos.flags, 0);
    
    var notifyParent = false;
    if ( AP.is_set(pos.cy) || pos.flags & POS_FLAGS_RECALCULATE )
    {
        var needHeight = this.getNeedHeight();
        if ( AP.is_set(pos.cy) )
        {
            if ( pos.cy != needHeight )
            {
                pos.cy = needHeight;
                notifyParent = true;
            }
        }
        else if ( AP.offsetHeight(this.element) != needHeight )
        {
            pos.cy = needHeight;
        }
    }
    
    this.subclass = AP.prototype.setPosition;
    this.subclass(pos);
    
    if ( AP.is_set(pos.cx) || pos.flags & POS_FLAGS_RECALCULATE )
    {
        for ( var loop = 0; loop < this.getItemCount(); loop++ )
        {
            var item = this._getItem(loop);
            item.cbField.setPosition({ cx: AP.clientWidth(item.cbField.element.parentNode) });
            if ( item.ctrlValue )
            {
                item.ctrlValue.setPosition({ cx: AP.clientWidth(item.cbField.element.parentNode) });
            }
        }
    }
    
    if ( notifyParent )
    {
        this.fireNotify(VLN_OTHERFIELDS_HEIGHT_CHANGED, 0);
    }
}

////////////////////////////////////////////////////////////////////////////
// insertItem
////////////////////////////////////////////////////////////////////////////
VLOtherFields.prototype.insertItem = function(index, field_value)
{
    index = AP.is_set(index, 0);
    
    var item = this.tblItems.tBodies[0].insertRow(index);
    item.className = "item";
    item.insertCell(0);
    item.insertCell(0);
    item.insertCell(0);
    
    item.cells[this.cellIndexManage].className = "ap manage";
    item.cells[this.cellIndexManage].align = "right";
    item.cells[this.cellIndexManage].vAlign = "top";
    item.cells[this.cellIndexManage].innerHTML = ' \
        <table cellspacing="0" cellpadding="0"> \
            <tr><td style="padding: 0px 2px"><img class="img_insert" src="' + ROOT_PATH + 'img/db_insert.gif"></td> \
            <td><img class="img_delete" src="' + ROOT_PATH + 'img/db_delete.gif"></td></tr> \
        </table>';
    
    item.cells[this.cellIndexField].className = "ap field";
    item.cells[this.cellIndexManage].align = "left";
    item.cells[this.cellIndexField].vAlign = "top";
    item.cbField = new ComboBox();
    item.cbField.create(item.cells[this.cellIndexField], "", CB_FLAGS_DROPDOWNLIST | CB_FLAGS_REPLACEIMAGE);
    item.cbField.setPosition({ cx: AP.clientWidth(item.cbField.element.parentNode) });
    VLOtherFields._FillCombo(item.cbField, this.fields);
    item.cbField.addNotifyHandler( [VLOtherFields.onComboFieldNotify, this] );
    
    item.cells[this.cellIndexValue].className = "ap value";
    item.ctrlValue = null;
    
    if ( AP.is_set(field_value)
         && AP.is_set(field_value[0]) )
    {
        var index = item.cbField.findItem(0, field_value[0], CB_FIND_VALUE);
        if ( index != -1 )
        {
            item.cbField.selIndex(index);
        }
        if ( AP.is_set(field_value[1])
             && item.ctrlValue )
        {
            if ( this.fields[index].type == "text"
                 || this.fields[index].type == "list" )
            {
                item.ctrlValue.value(field_value[1]);
            }
            else if ( this.fields[index].type == "combo" )
            {
                var index = item.ctrlValue.findItem(0, field_value[1], CB_FIND_VALUE);
                if ( index != -1 )
                {
                    item.ctrlValue.selIndex(index);
                }
            }
            else if ( this.fields[index].type == "date_range" )
            {
                var validDateRange = false;
                var str_date_range = field_value[1];
                if ( str_date_range.charAt(0) == "[" )
                {
                    str_date_range = str_date_range.substring(1, str_date_range.length - 1);
                }
                var arr_date_range = str_date_range.split(" ");
                var date_range = {
                    value: "range",
                    from: "",
                    to: ""
                };
                if ( arr_date_range.length == 2 )
                {
                    DebugLog.write("TODO:// UTC to gmt to local");

                    var validate = RegExp(/^\d{8}/);
                    var y, m, d;
                    if (validate.test(arr_date_range[0])
                        && validate.test(arr_date_range[1]))
                    {
                        y = arr_date_range[0].substring(0,4);
                        m = arr_date_range[0].substring(4,6);
                        d = arr_date_range[0].substring(6,8);
                        h = arr_date_range[0].substring(8,10);
                        i = arr_date_range[0].substring(10,12);
                        s = arr_date_range[0].substring(12,14);
                        var dt = new Date();
                        dt.setFullYear(y);
                        dt.setMonth(m-1);
                        dt.setDate(d);
                        dt.setHours(h);
                        dt.setMinutes(i);
                        dt.setSeconds(s);
                        dt.setTime(dt.getTime() - dt.getTimezoneOffset()*60*1000);
                        date_range.from = dt.dateFormat('m/d/Y');//m + "/" + d + "/" + y;

                        var dt = new Date();
                        y = arr_date_range[1].substring(0,4);
                        m = arr_date_range[1].substring(4,6);
                        d = arr_date_range[1].substring(6,8);
                        h = arr_date_range[1].substring(8,10);
                        i = arr_date_range[1].substring(10,12);
                        s = arr_date_range[1].substring(12,14);

                        dt.setFullYear(y);
                        dt.setMonth(m-1);
                        dt.setDate(d);
                        dt.setHours(h);
                        dt.setMinutes(i);
                        dt.setSeconds(s);
                        dt.setTime(dt.getTime() - dt.getTimezoneOffset()*60*1000);
                        date_range.to = dt.dateFormat('m/d/Y');//m + "/" + d + "/" + y;

                        validDateRange = true;
                    }
                }

                if (! validDateRange)
                {
                    date_range.value = "any";
                }
                item.ctrlValue.value(date_range);
            }
        }
    }
    
    // Re-calc height
    if ( this.recalculateState() )
    {
        this.recalculateState(true);
    }
}

////////////////////////////////////////////////////////////////////////////
// deleteItem
////////////////////////////////////////////////////////////////////////////
VLOtherFields.prototype.deleteItem = function(index, createIfNull)
{
    var item = this._getItem(index);
    if ( !item )
    {
        return false;
    }
    
    AP.destroyInstance(item.cbField);
    item.cbField = null;
    
    this.tblItems.deleteRow(index);
    
    if ( createIfNull && !this.getItemCount() )
    {
        this.insertItem();
    }
    
    // Re-calc height
    if ( this.recalculateState() )
    {
        this.recalculateState(true);
    }
    
    return true;
}

////////////////////////////////////////////////////////////////////////////
// deleteAllItems
////////////////////////////////////////////////////////////////////////////
VLOtherFields.prototype.deleteAllItems = function(createFirst)
{
    while ( this.getItemCount() )
    {
        this.deleteItem(0, false);
    }
    if ( createFirst )
    {
        this.insertItem();
    }
}

////////////////////////////////////////////////////////////////////////////
// _FillCombo
////////////////////////////////////////////////////////////////////////////
VLOtherFields._FillCombo = function(cb, items)
{
    cb.deleteAll();
    for ( var loop = 0; loop < items.length; loop++ )
    {
        cb.appendItem({
            text: items[loop].text,
            value: items[loop].value,
            img: items[loop].img
        });
    }
}

////////////////////////////////////////////////////////////////////////////
// _FillList
////////////////////////////////////////////////////////////////////////////
VLOtherFields._FillList = function(list, items)
{
    list.updateTree({
        parent: TV_ROOT_ITEM_ID,
        tree: []
    });
    for ( var loop = 0; loop < items.length; loop++ )
    {
        list.insertItem({
            parent: TV_ROOT_ITEM_ID,
            text: items[loop].text,
            flags: TVI_INSERT_LAST_CHILD
        });
    }
}

////////////////////////////////////////////////////////////////////////////
// getItemCount
////////////////////////////////////////////////////////////////////////////
VLOtherFields.prototype.getItemCount = function()
{
    return this.tblItems.tBodies[0].rows.length;
}

////////////////////////////////////////////////////////////////////////////
// getItem
////////////////////////////////////////////////////////////////////////////
VLOtherFields.prototype._getItem = function(index)
{
    if ( index < this.getItemCount() )
    {
        return this.tblItems.tBodies[0].rows[index];
    }
    return null;
}

////////////////////////////////////////////////////////////////////////////
// getItemIndex
////////////////////////////////////////////////////////////////////////////
VLOtherFields.prototype._getItemIndex = function(item)
{
    if ( !AP.is_set(item) || !AP.is_set(item.rowIndex) )
    {
        return -1;
    }
    
    return item.rowIndex;
}

////////////////////////////////////////////////////////////////////////////
// recalculateState
////////////////////////////////////////////////////////////////////////////
VLOtherFields.prototype.recalculateState = function(value)
{
    if ( AP.is_set(value) )
    {
        this._doRecalculate = value;
        if ( this._doRecalculate )
        {
            this.setPosition({cy: 0});
        }
    }
    return this._doRecalculate;
}

////////////////////////////////////////////////////////////////////////////
// getNeedHeight
////////////////////////////////////////////////////////////////////////////
VLOtherFields.prototype.getNeedHeight = function()
{
    return AP.offsetHeight(this.tblItems);//this. element.scrollHeight;
}

////////////////////////////////////////////////////////////////////////////
// updateFields
////////////////////////////////////////////////////////////////////////////
VLOtherFields.prototype.updateFields = function(fields)
{
    this.fields = fields;
    this.recalculateState(false);
    this.deleteAllItems(true);
    this.recalculateState(true);
}

////////////////////////////////////////////////////////////////////////////
// updateCtrlValue
////////////////////////////////////////////////////////////////////////////
VLOtherFields.prototype.updateCtrlValue = function(index)
{
    var item = this._getItem(index);
    var selIndex = item.cbField.selIndex();
    if ( selIndex == -1 )
    {
        if ( item.ctrlValue )
        {
            AP.destroyInstance(item.ctrlValue);
            item.ctrlValue = null;
        }
    }
    else
    {
        var newType = this.fields[selIndex].type;
        if ( item.ctrlValue )
        {
            var oldType = "";
            if ( ComboBox.prototype.isPrototypeOf(item.ctrlValue) )
            {
                oldType = "combo";
            }
            else if ( VLCtrlChoiceList.prototype.isPrototypeOf(item.ctrlValue) )
            {
                oldType = "list";
            }
            else if ( ImgInput.prototype.isPrototypeOf(item.ctrlValue) )
            {
                oldType = "text";
            }
            
            if ( oldType != newType )
            {
                AP.destroyInstance(item.ctrlValue);
                item.ctrlValue = null;
            }
        }
        
        if ( !item.ctrlValue )
        {
            if ( newType == "combo" )
            {
                item.ctrlValue = new ComboBox();
                item.ctrlValue.create(item.cells[this.cellIndexValue], "", CB_FLAGS_DROPDOWNLIST | CB_FLAGS_REPLACEIMAGE);
            }
            else if ( newType == "text" )
            {
                item.ctrlValue = new ImgInput();
                item.ctrlValue.create(item.cells[this.cellIndexValue], "", IMGIN_FLAGS_TEXT);
            }
            else if ( newType == "list" )
            {
                item.ctrlValue = new VLCtrlChoiceList();
                item.ctrlValue.create(item.cells[this.cellIndexValue]);
            }
            else if ( newType == "date_range" )
            {
                item.ctrlValue = new DateRange();
                item.ctrlValue.create(item.cells[this.cellIndexValue]);
            }
            else
            {
                throw ("unknown field type");
            }
            item.ctrlValue.setPosition({ cx: AP.clientWidth(item.ctrlValue.element.parentNode) });
        }
        
        if ( newType == "combo" )
        {
            VLOtherFields._FillCombo(item.ctrlValue, this.fields[selIndex].cb_values);
        }
        else if ( newType == "list" )
        {
            VLOtherFields._FillList(item.ctrlValue, this.fields[selIndex].list_values);
        }
    }

    // Re-calc height
    if ( this.recalculateState() )
    {
        this.recalculateState(true);
    }
}

////////////////////////////////////////////////////////////////////////////
// values
////////////////////////////////////////////////////////////////////////////
VLOtherFields.prototype.values = function(fieldvalues)
{
    if ( AP.is_set(fieldvalues) )
    {
        //var tt0 = AP.getTickCount();
        this.recalculateState(false);
        this.deleteAllItems(fieldvalues.length ? false : true);
        for ( var loop = 0; loop < fieldvalues.length; loop++ )
        {
            this.insertItem(this.getItemCount(), fieldvalues[loop]);
        }
        this.recalculateState(true);
        //var tt1 = AP.getTickCount();
        //DebugLog.write(tt1 - tt0);
        
        return true;
    }
    
    var retVal = new Array();
    
    for ( var loop = 0; loop < this.getItemCount(); loop++ )
    {
        var item = this._getItem(loop);
        var selIndex = item.cbField.selIndex();
        if ( selIndex == -1 )
        {
            continue;
        }
        if ( !item.ctrlValue )
        {
            continue;
        }
        
        var pair = null;
        var field = item.cbField.value();
        var value = item.ctrlValue.value();
        
        if ( this.fields[selIndex].type == "date_range" )
        {
            DebugLog.write("TODO:// local to gmt to UTC");

            var m = value.from.substring(0,2);
            var d = value.from.substring(3,5);
            var y = value.from.substring(6,10);

            var df = new Date();
            var to = df.getTimezoneOffset()*60*1000;
            df.setFullYear(y);
            df.setMonth(m-1);
            df.setDate(d);
            df.setHours(0);
            df.setMinutes(0);
            df.setSeconds(0);
            df.setTime(df.getTime() + to);
            //alert(df.dateFormat("H:i:s"));
            //dfs = df.dateFormat("Ymd") + "000001";
            dfs = df.dateFormat("YmdHis");

            m = value.to.substring(0,2);
            d = value.to.substring(3,5);
            y = value.to.substring(6,10);

            var dt = new Date();
            dt.setFullYear(y);
            dt.setMonth(m-1);
            dt.setDate(d);
            dt.setHours(23);
            dt.setMinutes(59);
            dt.setSeconds(59);
            dt.setTime(dt.getTime() + to);
            //dts = dt.dateFormat("Ymd") + "235959";
            dts = dt.dateFormat("YmdHis");

            var date_range = "[" + dfs + " " + dts + "]";
            pair = [field, date_range];
        }
        else
        {
            pair = [field, value];
        }
        retVal.push(pair);
    }

    return retVal;
}

////////////////////////////////////////////////////////////////////////////
// getItemInstance
////////////////////////////////////////////////////////////////////////////
VLOtherFields.getItemInstance = function(obj)
{
    for ( var o = obj; o; o = o.parentNode )
    {
        if ( o.nodeName == "TR" && AP.isSetClassName(o, "item") )
        {
            return o;
        }
    }
    return null;
}

////////////////////////////////////////////////////////////////////////////
// getInstance
////////////////////////////////////////////////////////////////////////////
VLOtherFields.getInstance = function(obj)
{
    for ( var o = obj; o && !(o.instance && VLOtherFields.prototype.isPrototypeOf(o.instance)); o = o.parentNode );
    return (o ? o.instance : null);
}

////////////////////////////////////////////////////////////////////////////
// onImgActionClick
////////////////////////////////////////////////////////////////////////////
VLOtherFields.onImgActionClick = function(ev)
{
    var obj = (AP.isIE() ? window.event.srcElement : ev.target);
    if ( obj.nodeName != "IMG" )
    {
        return true;
    }
    var item = VLOtherFields.getItemInstance(obj);
    if ( !item )
    {
        return true;
    }
    var pThis = VLOtherFields.getInstance(item);
    if ( !pThis )
    {
        return true;
    }
    
    var index = pThis._getItemIndex(item);
    if ( AP.isSetClassName(obj, "img_insert") )
    {
        pThis.insertItem(index + 1);
    }
    else if ( AP.isSetClassName(obj, "img_delete") )
    {
        pThis.deleteItem(index, true);
    }

    return true;
}

////////////////////////////////////////////////////////////////////////////
// onComboFieldNotify
////////////////////////////////////////////////////////////////////////////
VLOtherFields.onComboFieldNotify = function(param)
{
    if ( param.code != CBN_ONCHANGED )
    {
        return 0;
    }
    
    
    var pThis = param.subscriber;
    var combo = param.producer;
    var item = VLOtherFields.getItemInstance(combo.element);
    pThis.updateCtrlValue(pThis._getItemIndex(item));

    return 0;
}

////////////////////////////////////////////////////////////////////////////
// class VLSearchForm extends WndBorder
////////////////////////////////////////////////////////////////////////////
// VLSearchForm DOM
////////////////////////////////////////////////////////////////////////////
/*
WndBorder {
    ???
}
*/
////////////////////////////////////////////////////////////////////////////
// constructor
////////////////////////////////////////////////////////////////////////////
VLSearchForm = function()
{
    this.subclass = WndBorder;
    this.subclass();
    
    this.className = "VLSearchForm";
    this.cookiePref = "VLSF";
    
    this.qs = {
        element: null,
        headerHeight: 120,
        parentOffset: 20,
        minWidth: 285,
        maxWidth: 550,
        minHeight: 285,
        // Search In
        fsSearch_in: new FieldSet(),
        ctrlLibrary: new VLCtrlLibrary(),
        // Search Fields
        fsSearch_fields: new FieldSet(),
        // Full Text
        divFullText: null,
        inputFullText: new ImgInput(),
        divSearchAllBtn: null,
        btnSearchAll: new ImgButton(),
        // Title
        divTitle: null,
        inputTitle: new ImgInput(),
        divSearchAbstractBtn: null,
        btnSearchAbstract: new ImgButton(),
        // Author
        inputAuthor: new ImgInput(),
        // Abstract
        inputJTitle: new ImgInput(),
        // More / Less
        ctrlMoreLess: null,
        mode: "less",
        // Dialog Buttons
        divDlgButtons: null,
        btnAdvancedForm: null,
        btnClear: new ImgButton(),
        btnOK: new ImgButton(),
        inputHiddenTimezoneOffset: null
        //,btnCancel: new ImgButton()
    }

    this.as = {
        element: null,
        headerHeight: 120,
        parentOffset: 20,
        minWidth: 285,
        maxWidth: 550,
        minHeight: 285,
        // Search In
        fsSearch_in: new FieldSet(),
        ctrlLibrary: new VLCtrlLibrary(),
        // Full Text
        fsSearch_ft: new FieldSet(),
        elFullText: null,
        // Other Fields
        fsSearch_of: new FieldSet(),
        ctrlOtherFields: new VLOtherFields(),
        // Dialog Buttons
        divDlgButtons: null,
        btnAdvancedForm: null,
        btnClear: new ImgButton(),
        btnOK: new ImgButton(),
        inputHiddenTimezoneOffset: null
        //,btnCancel: new ImgButton()
    }
    
    this.currentFormName = "quick";
}
VLSearchForm.prototype = new WndBorder;

////////////////////////////////////////////////////////////////////////////
// create
////////////////////////////////////////////////////////////////////////////
VLSearchForm.prototype.create = function(parent, caption, flags, btns)
{
    flags = AP.is_set(flags, 0);
    this.subclass = WndBorder.prototype.create;
    this.subclass(parent, caption, flags | WND_FLAGS_BORDER );
    this.element.className += " vl_search_form_wnd";

    btns = AP.is_set(btns, []);
    
    this.appendButtons(btns);
    
    var childArea = this.childArea();
    childArea.innerHTML = ' \
    <center class="header"> \
        <div><img src="' + ROOT_PATH + RES_MAIN_LOGO + '"></div> \
        <div>Enter your query and press "Search" to retrieve results.</div> \
    </center>';
    
    //////////////////////////////////////////////
    // Quick Search Form
    //////////////////////////////////////////////
    this.qs.element = AP.createElement("div", childArea, "quick_search");
    AP.setPosition(this.qs.element, {
        y: this.qs.headerHeight + this.qs.parentOffset,
        cy: 285
    });
    // Search In
    this.qs.fsSearch_in.create(this.qs.element, 0, "Search In");
    this.qs.fsSearch_in.setPosition({
        x: 0,
        y: 10,
        cy: 50
    });
    this.qs.ctrlLibrary.create(this.qs.fsSearch_in.getClientArea());
    this.qs.ctrlLibrary.setPosition({
        x: 15,
        y: 15
    });
    // Search Fields
    var pos_fsSearch_fields = {
        x: 0,
        y: AP.offsetTop(this.qs.fsSearch_in.element) + AP.offsetHeight(this.qs.fsSearch_in.element) + 20,
        cy: 67
    }
    this.qs.fsSearch_fields.create(this.qs.element, 0, "Search Query");
    this.qs.fsSearch_fields.setPosition(pos_fsSearch_fields);
    // More / Less
    var cells = [[[ null, [
        ["more", null, null, null, null],
        ["text", null, null, "left", "middle"]
    ]]]];
    this.qs.ctrlMoreLess = AP.createTable(0, 0, cells, this.qs.element, "morelessbtn");
    this.qs.ctrlMoreLess.tBodies[0].rows[0].cells[1].innerHTML = "More";
    AP.setPosition(this.qs.ctrlMoreLess, {
        x: 10,
        y: pos_fsSearch_fields.y + pos_fsSearch_fields.cy - 9
    });
    AP.addEvent(this.qs.ctrlMoreLess, "click", VLSearchForm.onEvent);
    AP.addEvent(this.qs.ctrlMoreLess, "mouseover", VLSearchForm.onEvent);
    AP.addEvent(this.qs.ctrlMoreLess, "mouseout", VLSearchForm.onEvent);
    // Full Text
    this.qs.divFullText = AP.createElement("div", this.qs.fsSearch_fields.getClientArea(), "label");
    this.qs.divFullText.innerHTML = "Full Text:";
    AP.setPosition(this.qs.divFullText, {y: 20});
    this.qs.inputFullText.create(this.qs.fsSearch_fields.getClientArea(), "", IMGIN_FLAGS_TEXT);
    this.qs.inputFullText.setPosition({
        y: 20
    });
    this.qs.inputFullText.addNotifyHandler( [VLSearchForm.onControlsNotify, this] );
    // Search All Fields
    this.qs.divSearchAllBtn = AP.createElement("div", this.qs.fsSearch_fields.getClientArea(), "dlg_buttons ap_check1_buttons");
    AP.setPosition(this.qs.divSearchAllBtn, {
        y: 41
    });
    
    this.qs.btnSearchAll.create(this.qs.divSearchAllBtn, IMGBTN_FLAGS_DYNAMIC | IMGBTN_FLAGS_IMAGELINE | IMGBTN_FLAGS_AUTOSTATE);
    this.qs.btnSearchAll.text("Search All Fields");
    this.qs.btnSearchAll.image(IMG_BTN_IMAGE_LIST_CHECK);
    this.qs.btnSearchAll.addNotifyHandler( [VLSearchForm.onControlsNotify, this] );
    // Title
    this.qs.divTitle = AP.createElement("div", this.qs.fsSearch_fields.getClientArea(), "label");
    this.qs.divTitle.innerHTML = "Title:";
    AP.setPosition(this.qs.divTitle, {y: 70});
    this.qs.inputTitle.create(this.qs.fsSearch_fields.getClientArea(), "", IMGIN_FLAGS_TEXT);
    this.qs.inputTitle.setPosition({
        y: 70
    });
    this.qs.inputTitle.addNotifyHandler( [VLSearchForm.onControlsNotify, this] );
        // Search in Abstract
    this.qs.divSearchAbstractBtn = AP.createElement("div", this.qs.fsSearch_fields.getClientArea(), "dlg_buttons ap_check1_buttons");
    AP.setPosition(this.qs.divSearchAbstractBtn, {
        y: 91
    });

    this.qs.btnSearchAbstract.create(this.qs.divSearchAbstractBtn, IMGBTN_FLAGS_DYNAMIC | IMGBTN_FLAGS_IMAGELINE | IMGBTN_FLAGS_AUTOSTATE);
    this.qs.btnSearchAbstract.text("Search Also in Abstract");
    this.qs.btnSearchAbstract.image(IMG_BTN_IMAGE_LIST_CHECK);
    this.qs.btnSearchAbstract.addNotifyHandler( [VLSearchForm.onControlsNotify, this] );
    // Author
    this.qs.divAuthor = AP.createElement("div", this.qs.fsSearch_fields.getClientArea(), "label");
    this.qs.divAuthor.innerHTML = "Author:";
    AP.setPosition(this.qs.divAuthor, {y: 120});
    this.qs.inputAuthor.create(this.qs.fsSearch_fields.getClientArea(), "", IMGIN_FLAGS_TEXT);
    this.qs.inputAuthor.setPosition({
        y: 120
    });
    this.qs.inputAuthor.addNotifyHandler( [VLSearchForm.onControlsNotify, this] );
    // JTitle
    this.qs.divJTitle = AP.createElement("div", this.qs.fsSearch_fields.getClientArea(), "label");
    this.qs.divJTitle.innerHTML = "Journal:";
    AP.setPosition(this.qs.divJTitle, {
        y: 120
    });
    this.qs.inputJTitle.create(this.qs.fsSearch_fields.getClientArea(), "", IMGIN_FLAGS_TEXT);
    this.qs.inputJTitle.setPosition({
        y: 120
    });
    this.qs.inputJTitle.addNotifyHandler( [VLSearchForm.onControlsNotify, this] );

    // Dialog Buttons
    this.qs.divDlgButtons = AP.createElement("div", this.qs.element, "dlg_buttons ap_xp1_buttons");
    AP.setPosition(this.qs.divDlgButtons, {
        y: AP.offsetTop(this.qs.fsSearch_fields.element) + AP.offsetHeight(this.qs.fsSearch_fields.element) + 10
    });
        // Switch To Advanced Search Form
    this.qs.btnSwitchForm = AP.createElement("a", this.qs.divDlgButtons, "link");
    this.qs.btnSwitchForm.innerHTML = "Advanced Search";
    AP.addEvent(this.qs.btnSwitchForm, "click", VLSearchForm.onEvent);
        // Clear
    this.qs.btnClear.create(this.qs.divDlgButtons, IMGBTN_FLAGS_DYNAMIC | IMGBTN_FLAGS_IMAGELINE);
    this.qs.btnClear.text("Clear");
    this.qs.btnClear.setPosition({y: 4});
    this.qs.btnClear.addNotifyHandler( [VLSearchForm.onControlsNotify, this] );
        // OK
    this.qs.btnOK.create(this.qs.divDlgButtons, IMGBTN_FLAGS_DYNAMIC | IMGBTN_FLAGS_IMAGELINE);
    this.qs.btnOK.text("Search");
    this.qs.btnOK.setPosition({y: 4});
    this.qs.btnOK.addNotifyHandler( [VLSearchForm.onControlsNotify, this] );
        // Cancel
//    this.qs.btnCancel.create(this.qs.divDlgButtons, IMGBTN_FLAGS_DYNAMIC | IMGBTN_FLAGS_IMAGELINE);
//    this.qs.btnCancel.text("Close");
//    this.qs.btnCancel.setPosition({y: 4});
//    this.qs.btnCancel.addNotifyHandler( [VLSearchForm.onControlsNotify, this] );

    this.qs.inputHiddenTimezoneOffset = AP.createNamedElement({
            tagName: "input",
            name: INPUT_TIMEZONE_OFFSET,
            parent: this.qs.element,
            type: "hidden"
    });
    this.qs.inputHiddenUserTime = AP.createNamedElement({
            tagName: "input",
            name: INPUT_USER_TIME,
            parent: this.qs.element,
            type: "hidden"
    });

    //////////////////////////////////////////////
    // Advanced Search Form
    //////////////////////////////////////////////
    this.as.element = AP.createElement("div", childArea, "advanced_search");
    // Search In
    this.as.fsSearch_in.create(this.as.element, 0, "Search In");
    this.as.fsSearch_in.setPosition({
        x: 0,
        y: 10,
        cy: 50
    });
    this.as.ctrlLibrary.create(this.as.fsSearch_in.getClientArea());
    this.as.ctrlLibrary.setPosition({
        x: 15,
        y: 15
    });
    // Full Text
    this.as.fsSearch_ft.create(this.as.element, 0, "Full Text");
    this.as.fsSearch_ft.setPosition({
        x: 0,
        y: AP.offsetTop(this.as.fsSearch_in.element) + AP.offsetHeight(this.as.fsSearch_in.element) + 20,
        cy: 90
    });
    this.as.elFullText = AP.createElement("textarea", this.as.fsSearch_ft.getClientArea(), "full_text");
    AP.setPosition(this.as.elFullText, {
        x: 15,
        y: 15,
        cy: 60
    });
    // Other Fields
    this.as.fsSearch_of.addNotifyHandler( [VLSettingsEx.onControlsNotify, this] );
    this.as.fsSearch_of.create(this.as.element, 0, "Other Fields");
    this.as.fsSearch_of.setPosition({
        x: 0,
        y: AP.offsetTop(this.as.fsSearch_ft.element) + AP.offsetHeight(this.as.fsSearch_ft.element) + 20,
        cy: 52
    });
    this.as.ctrlOtherFields.create(this.as.fsSearch_of.getClientArea());
    this.as.ctrlOtherFields.setPosition({
        x: 11, // 15-4 cellpadding + cellspacing - see OtherFields.create
        y: 11  // --"--
    });
    this.as.ctrlOtherFields.addNotifyHandler( [VLSearchForm.onControlsNotify, this] );
    
    // Dialog Buttons
    this.as.divDlgButtons = AP.createElement("div", this.as.element, "dlg_buttons ap_xp1_buttons");
    AP.setPosition(this.as.divDlgButtons, {
        y: AP.offsetTop(this.as.fsSearch_of.element) + AP.offsetHeight(this.as.fsSearch_of.element) + 10
    });
        // Switch To Advanced Search Form
    this.as.btnSwitchForm = AP.createElement("a", this.as.divDlgButtons, "link");
    this.as.btnSwitchForm.innerHTML = "Quick Search";
    AP.addEvent(this.as.btnSwitchForm, "click", VLSearchForm.onEvent);
        // Clear
    this.as.btnClear.create(this.as.divDlgButtons, IMGBTN_FLAGS_DYNAMIC | IMGBTN_FLAGS_IMAGELINE);
    this.as.btnClear.text("Clear");
    this.as.btnClear.setPosition({y: 4});
    this.as.btnClear.addNotifyHandler( [VLSearchForm.onControlsNotify, this] );
        // OK
    this.as.btnOK.create(this.as.divDlgButtons, IMGBTN_FLAGS_DYNAMIC | IMGBTN_FLAGS_IMAGELINE);
    this.as.btnOK.text("Search");
    this.as.btnOK.setPosition({y: 4});
    this.as.btnOK.addNotifyHandler( [VLSearchForm.onControlsNotify, this] );
        // Cancel
//    this.as.btnCancel.create(this.as.divDlgButtons, IMGBTN_FLAGS_DYNAMIC | IMGBTN_FLAGS_IMAGELINE);
//    this.as.btnCancel.text("Close");
//    this.as.btnCancel.setPosition({y: 4});
//    this.as.btnCancel.addNotifyHandler( [VLSearchForm.onControlsNotify, this] );

    this.as.inputHiddenTimezoneOffset = AP.createNamedElement({
            tagName: "input",
            name: INPUT_TIMEZONE_OFFSET,
            parent: this.qs.element,
            type: "hidden"
    });

    this.as.inputHiddenUserTime = AP.createNamedElement({
            tagName: "input",
            name: INPUT_USER_TIME,
            parent: this.qs.element,
            type: "hidden"
    });


    // Restore Default Form
    var formName = AP.getCookie(this.cookiePref + "formname", "quick");
    this.currentForm(formName);
    
    // Restore Default Quick Search Form Mode
    var qsFormMode = AP.getCookie(this.cookiePref + "qsmode", "more");
    this.qsFormMode(qsFormMode);
}

////////////////////////////////////////////////////////////////////////////
// create
////////////////////////////////////////////////////////////////////////////
VLSearchForm.prototype.setPosition = function(pos)
{
    pos.flags = AP.is_set(pos.flags, 0);
    this.subclass = WndBorder.prototype.setPosition;
    this.subclass(pos);
    
    var childArea = this.childArea();
    var client_height = AP.clientHeight(childArea);
    var client_width = AP.clientWidth(childArea);
    
    // Quick Search Form
    if ( this.currentForm() == "quick"
         && (AP.is_set(pos.cx) !== false
             || (pos.flags & POS_FLAGS_RECALCULATE)) )
    {
        var qsPos = {
        };
        qsPos.cy = (this.qs.mode == "more" ? 188 : 285);
        qsPos.cx = Math.max(client_width - this.qs.parentOffset*2, this.qs.minWidth);
        qsPos.cx = Math.min(qsPos.cx, this.qs.maxWidth);
        qsPos.x = Math.round( (client_width - qsPos.cx) / 2 );
        qsPos.x = Math.max(qsPos.x, this.qs.parentOffset);
        AP.setPosition(this.qs.element, qsPos);
        var qs_client_width = AP.clientWidth(this.qs.element);
        // Search In
        this.qs.fsSearch_in.setPosition({
            cx: qs_client_width
        });
        this.qs.ctrlLibrary.setPosition({
            cx: AP.clientWidth(this.qs.fsSearch_in.element) - 30
        });
        // Search Fields
        this.qs.fsSearch_fields.setPosition({
            cx: qs_client_width,
            cy: (this.qs.mode == "more" ? 65 : 162)
        });
        var clientWidth = AP.clientWidth(this.qs.fsSearch_in.getClientArea());
        // More / Less
        AP.setPosition(this.qs.ctrlMoreLess, {
            y: AP.offsetTop(this.qs.fsSearch_fields.element)
               + AP.offsetHeight(this.qs.fsSearch_fields.element) - 9
        });
        var inputPos = {
            x: 80,
            cx: clientWidth - 95
        };
        // Full Text
        this.qs.inputFullText.setPosition({
            x: inputPos.x,
            cx: inputPos.cx
        });
            // Search All Fields
        AP.setPosition(this.qs.divSearchAllBtn, {
            x: inputPos.x
        });
        // Title
        this.qs.inputTitle.setPosition({
            x: inputPos.x,
            cx: inputPos.cx
        });
            // Search in Abstract
        AP.setPosition(this.qs.divSearchAbstractBtn, {
            x: inputPos.x
        });
        inputPos.cx = Math.round( (inputPos.cx - 5 - 60) / 2 );
        this.qs.inputAuthor.setPosition({
            x: inputPos.x,
            cx: inputPos.cx
        });
        // JTitle
        AP.setPosition(this.qs.divJTitle, {
            x: inputPos.x + inputPos.cx
        });
        this.qs.inputJTitle.setPosition({
            x: inputPos.x + inputPos.cx + 65,
            cx: inputPos.cx
        });

        // Dialog Button
        AP.setPosition(this.qs.divDlgButtons, {
            y: AP.offsetTop(this.qs.fsSearch_fields.element) + AP.offsetHeight(this.qs.fsSearch_fields.element) + 10,
            cx: qs_client_width
        });
        var btnOffset = 5;
        var btnWidth = AP.offsetWidth(this.qs.btnOK.element);
        var btnLeft = qs_client_width - btnWidth;
//        if ( this._modalState() )
//        {
//            this.qs.btnCancel.setPosition({
//                x: btnLeft
//            });
//            btnLeft = btnLeft - btnWidth - btnOffset
//        }
        this.qs.btnOK.setPosition({
            x: btnLeft
        });
        btnLeft = btnLeft - btnWidth - btnOffset
        this.qs.btnClear.setPosition({
            x: btnLeft
        });
        btnLeft = btnLeft - btnWidth - btnOffset
    }

    // Advanced Search Form
    if ( this.currentForm() == "advanced"
         && (AP.is_set(pos.cx) !== false
             || AP.is_set(pos.cy) !== false
             || (pos.flags & POS_FLAGS_RECALCULATE)) )
    {
        if ( pos.flags & POS_FLAGS_RECALCULATE )
        {
            this.as.ctrlOtherFields.setPosition({
                flags: POS_FLAGS_RECALCULATE
            });
        }
        var otherFieldsHeight = AP.offsetHeight(this.as.ctrlOtherFields.element);
        this.as.minHeight = 260 + otherFieldsHeight;
        var asPos = {
        };
        asPos.cx = Math.max(client_width - this.as.parentOffset*2, this.as.minWidth);
        asPos.cx = Math.min(asPos.cx, this.as.maxWidth);
        asPos.x = Math.round( (client_width - asPos.cx) / 2 );
        asPos.x = Math.max(asPos.x, this.as.parentOffset);
        asPos.cy = this.as.minHeight;
        asPos.y = this.as.headerHeight + this.as.parentOffset,
        AP.setPosition(this.as.element, asPos);
        var as_client_width = AP.clientWidth(this.as.element);
        // Search In
        this.as.fsSearch_in.setPosition({
            cx: as_client_width
        });
        this.as.ctrlLibrary.setPosition({
            cx: AP.clientWidth(this.as.fsSearch_in.element) - 30
        });
        // Full Text
        this.as.fsSearch_ft.setPosition({
            cx: as_client_width
        });
        AP.setPosition(this.as.elFullText, {
            cx: AP.clientWidth(this.as.fsSearch_ft.element) - 30
        });
        // Other Fields
        this.as.fsSearch_of.setPosition({
            cx: as_client_width,
            cy: otherFieldsHeight + 22 // see this.as.ctrlOtherFields.create
        });
        this.as.ctrlOtherFields.setPosition({
            cx: AP.clientWidth(this.as.fsSearch_of.element) - 26 // see this.as.ctrlOtherFields.create
        });

        // Dialog Button
        AP.setPosition(this.as.divDlgButtons, {
            y: AP.offsetTop(this.as.fsSearch_of.element) + AP.offsetHeight(this.as.fsSearch_of.element) + 10,
            cx: as_client_width
        });
        var btnOffset = 5;
        var btnWidth = AP.offsetWidth(this.as.btnOK.element);
        var btnLeft = as_client_width - btnWidth;
//        if ( this._modalState() )
//        {
//            this.as.btnCancel.setPosition({
//                x: btnLeft
//            });
//            btnLeft = btnLeft - btnWidth - btnOffset
//        }
        this.as.btnOK.setPosition({
            x: btnLeft
        });
        btnLeft = btnLeft - btnWidth - btnOffset
        this.as.btnClear.setPosition({
            x: btnLeft
        });
        btnLeft = btnLeft - btnWidth - btnOffset
    }
}

////////////////////////////////////////////////////////////////////////////
// qsFormMode
////////////////////////////////////////////////////////////////////////////
VLSearchForm.prototype.qsFormMode = function(mode)
{
    if ( AP.is_set(mode) )
    {
        this.qs.ctrlMoreLess.tBodies[0].rows[0].cells[0].className = "ap " + mode;
        this.qs.ctrlMoreLess.tBodies[0].rows[0].cells[1].innerHTML = mode == "more" ? "More" : "Less";
        this.qs.mode = mode;

        this.setPosition({flags: POS_FLAGS_RECALCULATE});
        
        
        // Store Default Quick Search Form Mode
        AP.setCookie(this.cookiePref + "qsmode", mode, 365);

        //  !!!!!!!!!!!!!!!!
        //  ! Do not move this block above 
        //  ! this.setPosition function call - it is not working under IE6
        //  !!!!!!!!!!!!!!!!
        var show = (mode == "more" ? false : true);
        AP.show(this.qs.divTitle, show);
        AP.show(this.qs.inputTitle.element, show);
        AP.show(this.qs.btnSearchAbstract.element, show);
        AP.show(this.qs.divAuthor, show);
        AP.show(this.qs.inputAuthor.element, show);
        AP.show(this.qs.divJTitle, show);
        AP.show(this.qs.inputJTitle.element, show);
    }
    
    return this.qs.mode;
}

////////////////////////////////////////////////////////////////////////////
// currentForm
////////////////////////////////////////////////////////////////////////////
VLSearchForm.prototype.currentForm = function(formName)
{
    if ( AP.is_set(formName) )
    {
        this.currentFormName = formName;
        
        if ( formName == "quick" )
        {
            AP.visible(this.qs.element, false);
            AP.show(this.qs.element, true);
            this.setPosition({flags: POS_FLAGS_RECALCULATE});
            AP.visible(this.qs.element, true);
            
            AP.show(this.as.element, false);
        }
        else if ( formName == "advanced" )
        {
            AP.show(this.qs.element, false);
            
            AP.visible(this.as.element, false);
            AP.show(this.as.element, true);
            this.setPosition({flags: POS_FLAGS_RECALCULATE});
            AP.visible(this.as.element, true);
        }
        
        // Store Default Form
        AP.setCookie(this.cookiePref + "formname", formName, 365);
    }
    
    return this.currentFormName;
}

////////////////////////////////////////////////////////////////////////////
// updateSearchInTree
////////////////////////////////////////////////////////////////////////////
VLSearchForm.prototype.updateSearchInTree = function(info)
{
    this.qs.ctrlLibrary.updateVLTree(info);
    this.as.ctrlLibrary.updateVLTree(info);
}

////////////////////////////////////////////////////////////////////////////
// updateOtherFields
////////////////////////////////////////////////////////////////////////////
VLSearchForm.prototype.updateOtherFields = function(fields)
{
    this.as.ctrlOtherFields.updateFields(fields);
}

////////////////////////////////////////////////////////////////////////////
// getCurrentVLInfo
////////////////////////////////////////////////////////////////////////////
VLSearchForm.prototype.getCurrentVLInfo = function(formName)
{
    var retVal = null;
    
    if ( formName == "quick" )
    {
        retVal = this.qs.ctrlLibrary.value();
    }
    else if ( formName == "advanced" )
    {
        retVal = this.as.ctrlLibrary.value();
    }
    
    return retVal;
}

////////////////////////////////////////////////////////////////////////////
// values
////////////////////////////////////////////////////////////////////////////
VLSearchForm.prototype.values = function(formName, values)
{
    formName = AP.is_set(formName, this.currentFormName);
    if ( AP.is_set(values) )
    {
        if ( values == "from_cookie" )
        {
            values = this.cookieValues(formName);
        }
        if ( formName == "quick" )
        {
            var search_in = {
                vl_addr: null,
                vl_domain: null,
                vl_name: "*",
                folder_id: -1
            };
            var full_text = "";
            var search_all = true;
            var title = "";
            var search_abstract = false;
            var author = "";
            var j_title = "";
            var fieldValues = {};
            for ( var loop = 0; loop < values.length; loop++ )
            {
                var name = values[loop][0];
                var value = values[loop][1];
                if ( name == INPUT_VL_ADDR )
                {
                    search_in.vl_addr = value;
                }
                else if ( name == INPUT_VL_DOMAIN )
                {
                    search_in.vl_domain = value;
                }
                else if ( name == INPUT_VIRTUAL_LIBRARY )
                {
                    search_in.vl_name = value;
                }
                else if ( name == INPUT_FOLDERID )
                {
                    search_in.folder_id = value;
                }
                else if ( name == INPUT_CONTENTS )
                {
                    full_text = value;
                }
                else if ( name == INPUT_SEARCHALLFIELDS )
                {
                    search_all = value;
                }
                else if ( name == INPUT_SEARCHINABSTRACT )
                {
                    search_abstract = value;
                }
                else if ( name.indexOf("Field") == 0 )
                {
                    var num = parseInt(name.substr("Field".length));
                    if ( !isNaN(num) )
                    {
                        if ( !AP.is_set(fieldValues[num]) )
                        {
                            fieldValues[num] = {
                            };
                        }
                        fieldValues[num].field = value;
                    }
                }
                else if ( name.indexOf("Value") == 0 )
                {
                    var num = parseInt(name.substr("Value".length));
                    if ( !isNaN(num) )
                    {
                        if ( !AP.is_set(fieldValues[num]) )
                        {
                            fieldValues[num] = {
                            };
                        }
                        fieldValues[num].value = value;
                    }
                }
            }
            // Search In
            this.qs.ctrlLibrary.value(search_in);
            // Full Text
            this.qs.inputFullText.value(full_text);
            // Search All
            this.qs.btnSearchAll.check(search_all ? BTS_CHECKED : 0);
            // Search Abstract
            this.qs.btnSearchAbstract.check(search_abstract ? BTS_CHECKED : 0);
            
            // Other Fields
            var num = null;
            for ( num in fieldValues )
            {
                if ( fieldValues[num].field == "TI" )
                {
                    title = fieldValues[num].value;
                }
                else if ( fieldValues[num].field == "AU" )
                {
                    author = fieldValues[num].value;
                }
                else if ( fieldValues[num].field == "TA" )
                {
                    j_title = fieldValues[num].value;
                }
            }
            // Title
            this.qs.inputTitle.value(title);
            // Author
            this.qs.inputAuthor.value(author);
            // JTitle
            this.qs.inputJTitle.value(j_title);
        }
        else if ( formName == "advanced" )
        {
            var search_in = {
                vl_addr: null,
                vl_domain: null,
                vl_name: "*",
                folder_id: -1
            };
            var full_text = "";
            var fieldValues = {};
            for ( var loop = 0; loop < values.length; loop++ )
            {
                var name = values[loop][0];
                var value = values[loop][1];
                if ( name == INPUT_VL_ADDR )
                {
                    search_in.vl_addr = value;
                }
                else if ( name == INPUT_VL_DOMAIN )
                {
                    search_in.vl_domain = value;
                }
                else if ( name == INPUT_VIRTUAL_LIBRARY )
                {
                    search_in.vl_name = value;
                }
                else if ( name == INPUT_FOLDERID )
                {
                    search_in.folder_id = value;
                }
                else if ( name == INPUT_CONTENTS )
                {
                    full_text = value;
                }
                else if ( name.indexOf("Field") == 0 )
                {
                    var num = parseInt(name.substr("Field".length));
                    if ( !isNaN(num) )
                    {
                        if ( !AP.is_set(fieldValues[num]) )
                        {
                            fieldValues[num] = {
                            };
                        }
                        fieldValues[num].field = value;
                    }
                }
                else if ( name.indexOf("Value") == 0 )
                {
                    var num = parseInt(name.substr("Value".length));
                    if ( !isNaN(num) )
                    {
                        if ( !AP.is_set(fieldValues[num]) )
                        {
                            fieldValues[num] = {
                            };
                        }
                        fieldValues[num].value = value;
                    }
                }
            }
            
            // Search In
            this.as.ctrlLibrary.value(search_in);
            
            // Full Text
            this.as.elFullText.value = full_text;
            
            // Other Fields
            var other_fields_values = [];
            var num = null;
            for ( num in fieldValues )
            {
                other_fields_values.push([
                    fieldValues[num].field,
                    fieldValues[num].value,
                ]);
            }
            this.as.ctrlOtherFields.values(other_fields_values);
        }
        
        return true;
    }
    
    var retVal = [];
    
    // Search For - always "Docs"
    retVal.push([
        INPUT_SEARCH_FOR,
        "Docs"
    ]);

    var curDate = new Date();
    var timezoneOffset = curDate.getTimezoneOffset()/60;
    var curTime = curDate.dateFormat("H:i:s");
    
    if ( formName == "quick" )
    {
        // Search In
        var vl_folder = this.qs.ctrlLibrary.value();
        retVal.push([
            INPUT_VL_ADDR,
            vl_folder.vl_addr
        ]);
        retVal.push([
            INPUT_VL_DOMAIN,
            vl_folder.vl_domain
        ]);
        retVal.push([
            INPUT_VIRTUAL_LIBRARY,
            vl_folder.vl_name
        ]);
        retVal.push([
            INPUT_FOLDERID,
            vl_folder.folder_id
        ]);
        
        // Full Text
        retVal.push([
            INPUT_CONTENTS,
            AP.trim(this.qs.inputFullText.value())
        ]);

        // Timezone Offset
        retVal.push([
            INPUT_TIMEZONE_OFFSET,
            timezoneOffset
        ]);
        // UserDateTime
        retVal.push([
            INPUT_USER_TIME,
            curTime
        ]);

        if ( this.qs.btnSearchAll.checked() )
        {
            // All Fields
            retVal.push([
                INPUT_SEARCHALLFIELDS,
                1
            ]);
        }
        else if ( this.qs.mode != "more" )
        {
            var fieldIndex = 0;
            // Title
            var value = AP.trim(this.qs.inputTitle.value());
            if ( value.length )
            {
                retVal.push([
                    "Field" + fieldIndex,
                    "TI"
                ]);
                retVal.push([
                    "Value" + fieldIndex,
                    value
                ]);
                fieldIndex++;
            }
            // Search Also In Abstract
            if ( this.qs.btnSearchAbstract.checked() )
            {
                retVal.push([
                    INPUT_SEARCHINABSTRACT,
                    1
                ]);
            }
            // Author
            var value = AP.trim(this.qs.inputAuthor.value());
            if ( value.length )
            {
                retVal.push([
                    "Field" + fieldIndex,
                    "AU"
                ]);
                retVal.push([
                    "Value" + fieldIndex,
                    value
                ]);
                fieldIndex++;
            }
            // JTitle
            var value = AP.trim(this.qs.inputJTitle.value());
            if ( value.length )
            {
                retVal.push([
                    "Field" + fieldIndex,
                    "TA"
                ]);
                retVal.push([
                    "Value" + fieldIndex,
                    value
                ]);
                fieldIndex++;
            }
        }
    }
    else if ( formName == "advanced" )
    {
        // Search In
        var vl_folder = this.as.ctrlLibrary.value();
        retVal.push([
            INPUT_VL_ADDR,
            vl_folder.vl_addr
        ]);
        retVal.push([
            INPUT_VL_DOMAIN,
            vl_folder.vl_domain
        ]);
        retVal.push([
            INPUT_VIRTUAL_LIBRARY,
            vl_folder.vl_name
        ]);
        retVal.push([
            INPUT_FOLDERID,
            vl_folder.folder_id
        ]);

        // Full Text
        retVal.push([
            INPUT_CONTENTS,
            AP.trim(this.as.elFullText.value)
        ]);

        // Timezone Offset
        retVal.push([
            INPUT_TIMEZONE_OFFSET,
            timezoneOffset
        ]);
        // UserDateTime
        retVal.push([
            INPUT_USER_TIME,
            curTime
        ]);
        
        var otherfields = this.as.ctrlOtherFields.values();
        var fieldIndex = 0;
        for ( var loop = 0; loop < otherfields.length; loop++ )
        {
            var fieldName = otherfields[loop][0];
            var value = AP.trim(otherfields[loop][1]);
            
            retVal.push([
                "Field" + fieldIndex,
                fieldName
            ]);
            retVal.push([
                "Value" + fieldIndex,
                value
            ]);
            fieldIndex++;
        }        
    }
    
    return retVal;
}


////////////////////////////////////////////////////////////////////////////
// packValues
////////////////////////////////////////////////////////////////////////////
VLSearchForm.prototype.packValues = function(values)
{
    var retVal = "";
    for ( var loop = 0; loop < values.length; loop++ )
    {
        var name = values[loop][0];
        var value = encodeURIComponent(values[loop][1]);
        
        if ( retVal.length )
        {
            retVal += "&";
        }
        retVal += name + "=" + value;
    }
    return retVal;
}

////////////////////////////////////////////////////////////////////////////
// unpackValues
////////////////////////////////////////////////////////////////////////////
VLSearchForm.prototype.unpackValues = function(values)
{
    var retVal = [];

    if ( AP.is_set(values) && values.length )
    {
        var arrPair = values.split("&");
        for ( var loop = 0; loop < arrPair.length; loop++ )
        {
            var pair = arrPair[loop].split("=", 2);
            var name = pair[0];
            var value = decodeURIComponent(pair[1]);
            retVal.push([name, value]);
        }
    }
    
    return retVal;
}

////////////////////////////////////////////////////////////////////////////
// cookieValues
////////////////////////////////////////////////////////////////////////////
VLSearchForm.prototype.cookieValues = function(formName, values)
{
    formName = AP.is_set(formName, this.currentFormName);
    var cookieName = this.cookiePref;
    cookieName += (formName == "quick" ? "qs" : "as");
    
    if ( AP.is_set(values) )
    {
        var formValues = this.packValues(values);
        AP.setCookie(cookieName, formValues, 365);
    }
    else
    {
        var formValues = AP.getCookie(cookieName);
        return this.unpackValues(formValues);
    }
    
    return true;
}

////////////////////////////////////////////////////////////////////////////
// onEvent
////////////////////////////////////////////////////////////////////////////
VLSearchForm.onEvent = function(ev)
{
    ev || (ev = window.event);
    var obj = (AP.isIE() ? ev.srcElement : ev.target);
    var pThis = VLSearchForm.getInstance(obj);
    if ( !pThis )
    {
        return true;
    }

    if ( obj.nodeName == "TD" &&
         (AP.isSetClassName(obj, "more")
          || AP.isSetClassName(obj, "less")
          || AP.isSetClassName(obj, "text")) )
    {
        if ( ev.type == "click" )
        {
            pThis.qsFormMode(pThis.qsFormMode() == "more" ? "less" : "more");
        }
        else if ( ev.type == "mouseover" )
        {
            AP.appendClassName(pThis.qs.ctrlMoreLess, "morelessbtn_over");
        }
        else if ( ev.type == "mouseout" )
        {
            AP.removeClassName(pThis.qs.ctrlMoreLess, "morelessbtn_over");
        }
    }
    else if ( obj == pThis.qs.btnSwitchForm
              || obj == pThis.as.btnSwitchForm )
    {
        if ( ev.type == "click" )
        {
            pThis.currentForm(pThis.currentForm() == "quick" ? "advanced" : "quick");
        }
    }
    
    return true;
}

////////////////////////////////////////////////////////////////////////////
// onControlsNotify
////////////////////////////////////////////////////////////////////////////
VLSearchForm.onControlsNotify = function(param)
{
    var pThis = param.subscriber;
    var pObject = param.producer;
    
    if ( param.code == VLN_OTHERFIELDS_HEIGHT_CHANGED
         && pObject == pThis.as.ctrlOtherFields )
    {
        pThis.setPosition({flags: POS_FLAGS_RECALCULATE});
    }
    else if ( param.code == APN_STATE_CHANGED
         && pObject == pThis.qs.btnSearchAll
         && param.param.diff_state & BTS_CHECKED )
    {
        var checked = pObject.checked();
        if ( checked )
        {
            pThis.qs.divFullText.innerHTML = "Query:";
            AP.appendClassName(pThis.qs.divTitle, "label_disabled");
            AP.appendClassName(pThis.qs.divAuthor, "label_disabled");
            AP.appendClassName(pThis.qs.divJTitle, "label_disabled");
        }
        else
        {
            pThis.qs.divFullText.innerHTML = "Full Text:";
            AP.removeClassName(pThis.qs.divTitle, "label_disabled");
            AP.removeClassName(pThis.qs.divAuthor, "label_disabled");
            AP.removeClassName(pThis.qs.divJTitle, "label_disabled");
        }
        pThis.qs.inputTitle.enable( !checked );
        pThis.qs.btnSearchAbstract.enable( !checked );
        pThis.qs.inputAuthor.enable( !checked );
        pThis.qs.inputJTitle.enable( !checked );
    }
    else if ( param.code == BTN_CLICKED )
    {
        if ( pObject == pThis.qs.btnOK
             || pObject == pThis.as.btnOK )
        {
            var submit_params = pThis.values();
            pThis.cookieValues(null, submit_params);
            return pThis.fireNotify(VLN_SEARCHFORM_SUBMIT, submit_params);
        }
        else if ( pObject == pThis.qs.btnClear )
        {
            pThis.values("quick", []);
        }
        else if ( pObject == pThis.as.btnClear )
        {
            pThis.values("advanced", []);
        }
    }
    else if ( param.code == BTN_KEYPRESSED
              && param.param.code == KEY_CODE_ENTER )
    {
        if ( pObject == pThis.qs.btnOK
             || pObject == pThis.as.btnOK
             || pObject == pThis.qs.btnSearchAll
             || pObject == pThis.qs.btnSearchAbstract )
        {
            var submit_params = pThis.values();
            pThis.cookieValues(null, submit_params);
            return pThis.fireNotify(VLN_SEARCHFORM_SUBMIT, submit_params);
        }
    }
    else if ( param.code == IMGINN_ONKEYPRESSED
              && param.param.code == KEY_CODE_ENTER )
    {
        if ( pObject == pThis.qs.inputFullText
             || pObject == pThis.qs.inputTitle
             || pObject == pThis.qs.inputAuthor
             || pObject == pThis.qs.inputJTitle )
        {
            var submit_params = pThis.values();
            pThis.cookieValues(null, submit_params);
            return pThis.fireNotify(VLN_SEARCHFORM_SUBMIT, submit_params);
        }
    }
    
    return 0;
}

////////////////////////////////////////////////////////////////////////////
// getInstance
////////////////////////////////////////////////////////////////////////////
VLSearchForm.getInstance = function(obj)
{
    for ( var o = obj; o && !(o.instance && VLSearchForm.prototype.isPrototypeOf(o.instance)); o = o.parentNode );
    return (o ? o.instance : null);
}

////////////////////////////////////////////////////////////////////////////
// class VLAskServerMsg extends WndBorder
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
// VLAskServerMsg DOM
////////////////////////////////////////////////////////////////////////////
/*
WndBorder {
    <table cellpadding="2" cellspacing="0" class="vl_ask_server_msg">
        <tr class="msg_info">
            <td class="msg_icon_info">
                <img src="img/bar.gif">
            </td>
            <td class="msg_text">
                Please<br>
                Wait...
            </td>
        </tr>
        <tr class="msg_buttons">
            <td colspan="2" align="right" class="msg_button_container">
                <button class="msg_button">Cancel</button>
            </td>
        </tr>
    </table>
}
*/
////////////////////////////////////////////////////////////////////////////
// constructor
////////////////////////////////////////////////////////////////////////////
VLAskServerMsg = function()
{
    this.subclass = WndBorder;
    this.subclass();
    
    this.buttons = new Array();

    this.className = "VLAskServerMsg";
}
VLAskServerMsg.prototype = new WndBorder;

////////////////////////////////////////////////////////////////////////////
// create
////////////////////////////////////////////////////////////////////////////
VLAskServerMsg.prototype.create = function(parent, flags)
{
    flags = AP.is_set(flags, 0);
    this.subclass = WndBorder.prototype.create;
    this.subclass(parent, "Get Data From Server", flags | WND_FLAGS_MODAL | WND_FLAGS_BORDER );
    this.element.className += " vl_ask_server";
    // Table
    var cells = [[
        [
            "msg_info",
            [
                ["msg_info_icon", null, null, "left", "middle"], // td1
                ["msg_text", null, null, "left", "middle"] // td2
            ]
        ], // tr1
        [
            "msg_buttons",
            [
                ["msg_button_container", 2, null, "right", "middle"] // td1
            ]
        ] // tr2
    ]];
    this.tblMsg = AP.createTable(2, 0, cells, this.childArea(), "vl_ask_server_msg");
    // Icon
    this.tdIcon = this.tblMsg.tBodies[0].rows[0].cells[0];
    this.imgIcon = AP.createElement("img", this.tdIcon);
    this.imgIcon.src = ROOT_PATH + "img/bar.gif";
    // Text
    this.tdText = this.tblMsg.tBodies[0].rows[0].cells[1];
    this.tdText.innerHTML = "Please<br>Wait...";
    // Buttons
    this.tdButtons = this.tblMsg.tBodies[0].rows[1].cells[0];
    var btnCancel = AP.createElement("button", this.tdButtons);
    btnCancel.innerHTML = "Cancel";
    AP.addEvent(btnCancel, "click", VLAskServerMsg.onBtnClick);
    this.buttons.push({
        id: IDCANCEL,
        btn: btnCancel
    });
    /*var btnCancel = new ImgButton();
    btnCancel.create(this.tdButtons, IMGBTN_FLAGS_DYNAMIC | IMGBTN_FLAGS_IMAGELINE | IMGBTN_FLAGS_ALIGN_CENTER | IMGBTN_FLAGS_VALIGN_CENTER);
    this.btnCancel.addNotifyHandler( [VLAskServerMsg.onBtnClick, this] );
    this.buttons.push(btnCancel);*/
    
    this.setClientSize({ cx: AP.offsetWidth(this.tblMsg), cy: AP.offsetHeight(this.tblMsg) });
}

////////////////////////////////////////////////////////////////////////////
// addTask
////////////////////////////////////////////////////////////////////////////
VLAskServerMsg.prototype.addTask = function(taskId)
{
    return true;
}

////////////////////////////////////////////////////////////////////////////
// removeTask
////////////////////////////////////////////////////////////////////////////
VLAskServerMsg.prototype.removeTask = function(taskId)
{
    return true;
}

////////////////////////////////////////////////////////////////////////////
// clearTasks
////////////////////////////////////////////////////////////////////////////
VLAskServerMsg.prototype.clearTasks = function()
{
    return true;
}

////////////////////////////////////////////////////////////////////////////
// showModal
////////////////////////////////////////////////////////////////////////////
VLAskServerMsg.prototype.showModal = function(flags)
{
    flags = AP.is_set(flags, 0);
    if ( flags & BTN_CANCEL )
    {
        // TODO: 
    }
    
    this.subclass = WndBorder.prototype.showModal;
    return this.subclass();
}

////////////////////////////////////////////////////////////////////////////
// setPosition
////////////////////////////////////////////////////////////////////////////
VLAskServerMsg.prototype.setPosition = function(pos)
{
    pos.flags = AP.is_set(pos.flags, 0);
    this.subclass = WndBorder.prototype.setPosition;
    this.subclass(pos);
}

////////////////////////////////////////////////////////////////////////////
// getInstance
////////////////////////////////////////////////////////////////////////////
VLAskServerMsg.getInstance = function(obj)
{
    for ( var o = obj; o && !(o.instance && VLAskServerMsg.prototype.isPrototypeOf(o.instance)); o = o.parentNode );
    return (o ? o.instance : null);
}

////////////////////////////////////////////////////////////////////////////
// onBtnClick
////////////////////////////////////////////////////////////////////////////
VLAskServerMsg.onBtnClick = function(ev)
{
    ev || (ev = window.event);
    var obj = (AP.isIE() ? ev.srcElement : ev.currentTarget);
    var msg = VLAskServerMsg.getInstance(obj);
    if ( !msg )
        return true;
    
    for ( var loop = 0; loop < msg.buttons.length; loop++ )
    {
        if ( msg.buttons[loop].btn == obj )
        {
            msg.fireNotify(VLN_ASKSRVMSG_BUTTON_CLICK, msg.buttons[loop].id);
            break;
        }
    }

    return true;
}

////////////////////////////////////////////////////////////////////////////
// class VLInterface
////////////////////////////////////////////////////////////////////////////
VLInterface = function()
{
    this.parent = null;
    this.element = null;
    
    // Session Info
    this.session_info = {};

    // Server Depended Environment
    this.srv_env = [];
    
    // VL Ask Server Message Box
    this.vlAskServerMsg = new VLAskServerMsg();
}

////////////////////////////////////////////////////////////////////////////
// create
////////////////////////////////////////////////////////////////////////////
VLInterface.prototype.create = function(parent, className)
{
    this.parent = parent;
    this.element = AP.createElement("div", this.parent, className);
    
    // VL Ask Server Message Box
    this.vlAskServerMsg.create(this.element, WND_FLAGS_CAPTION | WND_FLAGS_HIDDEN);
    this.vlAskServerMsg.addNotifyHandler( [VLInterface.onAskServerDialog, this] );
}

////////////////////////////////////////////////////////////////////////////
// _onUpdateSrvEnvironment_virt
////////////////////////////////////////////////////////////////////////////
VLInterface.prototype._onUpdateSrvEnvironment_virt = function(vlInfo, envName, values)
{
    // no default implementation
}

////////////////////////////////////////////////////////////////////////////
// askServer
////////////////////////////////////////////////////////////////////////////
var WC_ASKSERVER_VIEWMSG            = 0x01;
var WC_ASKSERVER_CANCEL             = 0x02;
// serverBusy parameter - hack, see VLBrowserInterface.onPeriodicUpdateTimeOut function for details
/*
var ask_params = {
    url: url,
    target: windowName,
    method: "get"/"post",
    postData: array[name, value],
    func_onload: function(req, udata)
    flags: int
}
*/
VLInterface.prototype.askServer = function(askParams)
{
    askParams.target = AP.is_set(askParams.target, "vl_bi_action_frame");
    askParams.flags = AP.is_set(askParams.flags, 0);
    
    if ( askParams.target == "vl_bi_action_frame" )
    {
        DebugLog.write("[SENDREQUEST]: ",
                       askParams.postData ? askParams.postData.length : 0,
                       askParams.postData);

        var msgLoading = null;
        if ( askParams.flags & WC_ASKSERVER_VIEWMSG )
        {
            this.vlAskServerMsg.showModal(BTN_CANCEL);
            msgLoading = this.vlAskServerMsg;
        }
        
        var params = {
            action: askParams.url,
            method: askParams.method,
            data: askParams.postData,
            hdr: [["AJAX_REFERER", "true"]],
            func_onload: (askParams.func_onload ? askParams.func_onload : VLInterface.onSendRequestComplete),
            user_data: {
                bi: this,
                msg: msgLoading
            }
        };
        if ( !APHttpRequest.sendRequest(params) )
        {
            DebugLog.write("[SENDREQUEST]: FAIL");
        }
        
        // Store XMLHttRequest for Loading Bar/MessageBox
        if ( msgLoading )
        {
            msgLoading._request = params.req;
        }
    }
    else
    {
        AP.submit(askParams);
    }
}

////////////////////////////////////////////////////////////////////////////
// submit
////////////////////////////////////////////////////////////////////////////
VLInterface.prototype.submit = function(submit_params, flags)
{
    flags = AP.is_set(flags, WC_ASKSERVER_VIEWMSG | WC_ASKSERVER_CANCEL);
    
    var ask_server = {
        url: _vlHomePage,
        method: "POST",
        postData: submit_params,
        flags: flags
    };
    
    this.askServer(ask_server);
}

////////////////////////////////////////////////////////////////////////////
// redirect
////////////////////////////////////////////////////////////////////////////
VLInterface.prototype.redirect = function(url)
{
    this.element.ownerDocument.location = url;
}

////////////////////////////////////////////////////////////////////////////
// redirect
////////////////////////////////////////////////////////////////////////////
VLInterface.prototype.write = function(text)
{
    this.element.ownerDocument.write(text);
}

////////////////////////////////////////////////////////////////////////////
// _cb_logInfo
////////////////////////////////////////////////////////////////////////////
VLInterface.prototype._cb_logInfo = function()
{
    var resultString = "";
    for (var loop = 0; loop < arguments.length; loop++ )
    {
        if (loop)
        {
            resultString += " - ";
        }
        resultString += arguments[loop];
    }

    DebugLog.write("<font color=\"blue\">[INFO]:</font> " + resultString);
}

////////////////////////////////////////////////////////////////////////////
// _cb_logError
////////////////////////////////////////////////////////////////////////////
VLInterface.prototype._cb_logError = function()
{
    var resultString = "";
    for (var loop = 0; loop < arguments.length; loop++ )
    {
        if (loop)
        {
            resultString += " - ";
        }
        resultString += arguments[loop];
    }

    DebugLog.write("<font color=\"red\">[ERROR]:</font> " + resultString);
}

////////////////////////////////////////////////////////////////////////////
// _cb_error
////////////////////////////////////////////////////////////////////////////
var VLI_ERR_NOT_REGISTERED          = 1;
var VLI_ERR_INVALID_REGISTRATION    = 2;
var VLI_ERR_LICENSE_EXPIRED         = 3;
var VLI_ERR_SERVER_NOT_DEFINED      = 20;
var VLI_ERR_SERVER_NOT_REACHABLE    = 21;
var VLI_ERR_SERVER_TIMEOUT          = 22;
var VLI_ERR_SERVER_PROCESS_REQUEST  = 23;
var VLI_ERR_ACCESS_DENIED           = 30;
VLInterface.prototype._cb_error = function(err)
{
    DebugLog.write("<font color=\"red\">[ERROR]:</font>", err.code, err.msg);
}

////////////////////////////////////////////////////////////////////////////
// _cb_srvEnvValues
////////////////////////////////////////////////////////////////////////////
VLInterface.prototype._cb_srvEnvValues = function(vlInfo, envName, values)
{
    var retVal = null;
    
    var env = null;
    for ( var loop = 0; loop < this.srv_env.length; loop++ )
    {
        if ( this.srv_env[loop].vl_addr == vlInfo.vl_addr
             && this.srv_env[loop].vl_domain == vlInfo.vl_domain )
        {
            env = this.srv_env[loop].env;
            break;
        }
    }
    
    if ( AP.is_set(values) )
    {
        if ( !AP.is_set(env) )
        {
            this.srv_env.push({
                vl_addr: vlInfo.vl_addr,
                vl_domain: vlInfo.vl_domain,
                env: {
                }
            });
            env = this.srv_env[this.srv_env.length - 1].env;
        }
        
        env[envName] = values;
        
        this._onUpdateSrvEnvironment_virt(vlInfo, envName, values);
    }
    else
    {
        if ( AP.is_set(env) && AP.is_set(env[envName]) )
        {
            retVal = env[envName];
        }
    }
    
    return retVal;
}

////////////////////////////////////////////////////////////////////////////
// onSendRequestComplete
////////////////////////////////////////////////////////////////////////////
VLInterface.onSendRequestComplete = function(req, udata)
{
    //DebugLog.write("req", req.readyState());
    if ( req.readyState() != -1 // aborted
         && req.readyState() != 4 ) // completed
    {
        return false;
    }
    
    var bi = udata.bi;
    
    // Hide Loading Bar/MessageBox
    var msgLoading = udata.msg;
    if ( AP.is_set(msgLoading) )
    {
        if ( msgLoading._request )
        {
            msgLoading._request = null;
        }
        msgLoading.hide();
    }
    
    if ( req.readyState() == -1 )
    {
        return true;
    }
    
    // Parse Response and callback function
    var r_text = req.responseText();
    
    var before = "";
    var js_text = "";
    var after = "";
    
    var tag_left = "%exec_func_body_begin%";
    var tag_right = "%exec_func_body_end%";
    
    var from = r_text.indexOf(tag_left);
    var to = r_text.indexOf(tag_right);
    if ( from == -1 || to == -1 )
    {
        before = r_text;
    }
    else
    {
        if ( from !== 0 )
        {
            before = r_text.substr(0, from);
        }
        from += tag_left.length;
        
        var end = to + tag_right.length;
        if ( end < r_text.length )
        {
            after = r_text.substr(end);
        }
    
        js_text = r_text.substr(from, to - from);
    }
    
    if ( js_text.length )
    {
        var div = AP.createElement("div");
        document.body.appendChild(div);
        
        var func_id = AP.uniqueId("_exec_func_");
        var text = "function " + func_id + "(ptrInterface) {" + js_text + "}";
        var script = document.createElement("script");
        script.setAttribute('type','text/javascript');
        if ( script.canHaveChildren == null || script.canHaveChildren )
        {
            script.appendChild(document.createTextNode(text));
        }
        else
        {
            script.text = text;
        }
        div.appendChild(script);
        
        //window[func_id](bi);
        try
        {
            window[func_id](bi);
        }
        catch(e)
        {
//            throw(e);
////          alert("Error ocuured.");
            var exceptString = e.description; // IE
            exceptString || (exceptString = e); // Mozilla
//            DebugLog.write("[EXCEPT]", exceptString, "[EXEC]<br>" + window[func_id]);
            DebugLog.write("[EXCEPT]:", exceptString);
        }
        
        document.body.removeChild(div);
    }
    
    if ( before.length || after.length )
    {
        var other = before + after;
        if ( other.search(/Maximum execution time/gmi) > -1 )
        {
            DebugLog.write( "<font color=\"red\">[ERROR]</font>: Maximum execution time exceeded<br>");
        }
        else if ( js_text.length )
        {
            DebugLog.write( "<font color=\"yellow\">[WARNING]</font> [BODY Contain Data]: ",
                            other );
        }
        else
        {
            alert(other);
        }
    }
    
    return true;
}

////////////////////////////////////////////////////////////////////////////
// onAskServerDialog
////////////////////////////////////////////////////////////////////////////
VLInterface.onAskServerDialog = function(param)
{
    var bi = param.subscriber;
    if ( param.code != VLN_ASKSRVMSG_BUTTON_CLICK )
    {
        return 0;
    }
    
    var msgLoading = param.producer;
    if ( param.param == IDCANCEL )
    {
        if ( msgLoading._request )
        {
            msgLoading._request.abort();
            msgLoading._request = null;
        }
        msgLoading.hide();
    }
    
    return 0;
}
