// window.onbeforeunload is called twice by IE so we have a flag 
var _onBeforeUnloadHandled = false;

// Used for jQuery table date pickers
var _currentEditCell;

// Used for selectsingles that use the JQuery dialog box in grids
var _currentGridId;
var _currentGridColumnIndex;
var _currentGridColumnKey;
var _currentGridRowIndex;
var _currentGridRowKey;
var _currentTableId;
var _currentjQueryDialogId;
var _currentTableSelectSingleTextDivId;

var _clientDialogCreated = false; 
var _projectDialogCreated = false;

var _controlIDs = new Array();

var _tableSelectSingleHtml = "<div id=\"[GridId]_ci_0_[ColumnIndex]_[RowIndex]__tss\" \
class=\"TableSelectSingle\" \
onclick=\"_currentGridId = '[GridId]'; _currentGridColumnIndex = '[ColumnIndex]'; _currentGridRowIndex = '[RowIndex]'; _currentjQueryDialogId = '#[GridId][ColumnIndex]'; _currentTableSelectSingleTextDivId = '#[GridId]_ci_0_[ColumnIndex]_[RowIndex]__tss__ts'; $('#[GridId][ColumnIndex]').dialog('open');\">\
<div id=\"[GridId]_ci_0_[ColumnIndex]_[RowIndex]__tss__ts\" class=\"TableSelectSingleDivInner\">[DefaultText]</div> \
</div>";

function MyAssociativeArray() { var A = {}; var B = 0; this.exists = function(C) { return (typeof A[C] != "undefined") }; this.setEntry = function(C, D) { if (D == null && A[C] != null) { B-- } else { if (D != A[C]) { B++ } } A[C] = D }; this.getEntry = function(C) { return A[C] }; this.count = function() { return B }; this.getDelimitedString = function(D) { var C = []; for (var E in A) { C.push(E + "=" + A[E]) } return C.join(D) } } var _addButton1; var _addButton2; var _addCounter = 0; var _xmlAddCounter = 0; var _beforeUpdateRowTime; var _cancelCellChange = false; var _cellText1; var _cellText2; var _cellTextStripped; var _deleteCounter = 0; var _editCounter = 0; var _inEditMode = false; var _inXmlRequest = false; var _originalCellText; var _cellIDToEditAfterXmlRequest = ""; var _xmlEditCounter = 0; var _xmlEditDictionary = new Object(); var _xmlPagingPending = false; var _editDictionary = new Object(); var _xmlHTTPResponseRowID; var _checkClickAway = true; var _checkMutex = false; var _interval; var _invalidCells; var _rowInsertMutex = false; var _newRowKeyPaddingValue = 1000000000; var _rowUpdateComplete = false; var _startTime = new Date().getTime(); var _status = ""; var _timespan1 = 0; var _timespan2 = 0; var _updateInProgress = false; var _updateResult = true; var _gridValidationList = new MyAssociativeArray(); var _columnUpdatedList = new MyAssociativeArray(); var _pendingSubmitButton = null; function getAnchorPosition(B) { var E = false; var J = new Object(); var I = 0, G = 0; var D = false, F = false, H = false; if (document.getElementById) { D = true } else { if (document.all) { F = true } else { if (document.layers) { H = true } } } if (D && document.all) { I = AnchorPosition_getPageOffsetLeft(document.all[B]); G = AnchorPosition_getPageOffsetTop(document.all[B]) } else { if (D) { var A = document.getElementById(B); I = A.offsetLeft; G = A.offsetTop } else { if (F) { I = AnchorPosition_getPageOffsetLeft(document.all[B]); G = AnchorPosition_getPageOffsetTop(document.all[B]) } else { if (H) { var K = 0; for (var C = 0; C < document.anchors.length; C++) { if (document.anchors[C].name == B) { K = 1; break } } if (K == 0) { J.x = 0; J.y = 0; return J } I = document.anchors[C].x; G = document.anchors[C].y } else { J.x = 0; J.y = 0; return J } } } } J.x = I; J.y = G; return J } function getAnchorWindowPosition(B) { var C = getAnchorPosition(B); var A = 0; var D = 0; if (document.getElementById) { if (isNaN(window.screenX)) { A = C.x - document.body.scrollLeft + window.screenLeft; D = C.y - document.body.scrollTop + window.screenTop } else { A = C.x + window.screenX + (window.outerWidth - window.innerWidth) - window.pageXOffset; D = C.y + window.screenY + (window.outerHeight - 24 - window.innerHeight) - window.pageYOffset } } else { if (document.all) { A = C.x - document.body.scrollLeft + window.screenLeft; D = C.y - document.body.scrollTop + window.screenTop } else { if (document.layers) { A = C.x + window.screenX + (window.outerWidth - window.innerWidth) - window.pageXOffset; D = C.y + window.screenY + (window.outerHeight - 24 - window.innerHeight) - window.pageYOffset } } } C.x = A; C.y = D; return C } function AnchorPosition_getPageOffsetLeft(B) { var A = B.offsetLeft; while ((B = B.offsetParent) != null) { A += B.offsetLeft } return A } function AnchorPosition_getWindowOffsetLeft(A) { return AnchorPosition_getPageOffsetLeft(A) - document.body.scrollLeft } function AnchorPosition_getPageOffsetTop(A) { var B = A.offsetTop; while ((A = A.offsetParent) != null) { B += A.offsetTop } return B } function AnchorPosition_getWindowOffsetTop(A) { return AnchorPosition_getPageOffsetTop(A) - document.body.scrollTop } function RTrim(A) { return (A.replace(/^\s*/, "")) } function LTrim(A) { return (A.replace(/\s*$/, "")) } function Trim(A) { return (RTrim(LTrim(A))) } function setGridCellValue(B, C) { var A = igtbl_getCellById(B); A.Element.children[1].value = C } function setGridCellDescription(C, B) { var A = igtbl_getCellById(C); A.setValue(B) } function SuppressPostBack(A, B) { tree = igtree_getTreeById(A); tree.CancelPostBack = true } 

function SuppressPostBackGrid(gridID, itemID)
{
    grid = igtbl_getGridById(gridID);
    grid.CancelPostBack = true;
}

function ToggleAllRows(A, B) { grid = igtbl_getGridById(A); rows = grid.Rows; grid.suspendUpdates(true); for (i = 0; i < rows.length; i++) { row = rows.getRow(i); if (B) { row.setExpanded(true) } else { row.setExpanded(false) } } grid.suspendUpdates(false) } function ToggleAllNodes(B, A) { tree = igtree_getTreeById(B); nodes = tree.getNodes(); ToggleNodes(nodes, A) } function ToggleNodes(B, D) { for (var C = 0, A = B.length; C < A; C++) { node = B[C]; if (node.hasChildren()) { node.setExpanded(D); var E = node.getChildNodes(); ToggleNodes(E, D) } } }

function FilterPicker(B) {
    selectedFirstNode = false;
    divNodes = document.getElementById("T_" + B).all.tags("div");
    divNodeCount = divNodes.length; tree = igtree_getTreeById(B);
    filter = document.all.tags("input")["f1_c1_f_Item0_Field0"].value.toLowerCase();
    var C = null;
    for (var A = 1; A < divNodeCount; A++) {
        if (divNodes[A].id.indexOf("M_") == -1) {
            if (divNodes[A].innerText.toLowerCase().indexOf(filter) == -1) {
                divNodes[A].style.display = "none"
            }
            else {
                divNodes[A].style.display = "";

                if (C != null) {
                    C.style.display = ""
                }

                if (!selectedFirstNode) {
                    node = igtree_getNodeById(divNodes[A].id);
                    tree.setSelectedNode(node);
                    selectedFirstNode = true
                }
            }
        }
        else {
            C = divNodes[A]
        }
    }

    document.all.tags("input")["f1_c1_f_Item0_Field0"].focus();
}

// Called when a new row is added.
function AfterRowInsert(gridID, rowID) 
{
    var grid = igtbl_getGridById(gridID);
    var row = igtbl_getRowById(rowID);
    var cellCounter = 0;

    for (cellCounter = 0; cellCounter < row.cells.length; cellCounter++) {
        cell = row.getCell(cellCounter);
        //cellID = grid.Id + "rc_" + row.getIndex + "_" + cell.Index;
        //hiddenID = grid.Id + "hidden_" + row.getIndex + "_" + cell.Index;

        if (cell.Column != null) {// Need this null check--don't ask why

            key = cell.Column.Key;
            args = key.split("|");

            if (args[1] == "9") {// SelectSinglePicker column--set default value

                cellValue = args[2];
                cellPropertyIndex = args[0];

                regRow = new RegExp("#row#", "g");
                regCol = new RegExp("#col#", "g");
                regDoubleQuote = new RegExp("#doublequote#", "g");
                regLess = new RegExp("&lt;", "g");
                regGreater = new RegExp("&gt;", "g");
                regAmp = new RegExp("&amp;", "g");
                regSpace = new RegExp("&nbsp;", "g");

                cellValue = cellValue.replace(regRow, grid.Rows.length - 1);
                cellValue = cellValue.replace(regCol, cell.Column.Index);
                cellValue = cellValue.replace(regDoubleQuote, "\"");
                cellValue = cellValue.replace(regLess, "<");
                cellValue = cellValue.replace(regGreater, ">");
                cellValue = cellValue.replace(regAmp, "&");
                cellValue = cellValue.replace(regSpace, " ");
                //cell.value = cellValue;
                cell.Element.innerHTML = cellValue;
                //cell.Element.innerHTML = "&lt;a&nbsp;href=\"http://www.ibm.com\"&gt;IBM&lt;/a&gt;"
                //cell.Element.innerHTML = "<a href=\"http://www.ibm.com\">IBM</a>"
            }
        }
    }
}

function AddRow(gridID) 
{
    // First get grid object so we can figure out the row index of the new row (goes
    // on the end of the grid)
    var grid = igtbl_getGridById(gridID);

    // Add row
    var row = igtbl_addNew(gridID, 0);

    // Initialize the new row
    InitializeNewRow(grid, row);
    
    // Increment counter so we can check for pending rows upon clickaway
    _addCounter++;

    // If we are hosted by a WebTab, we need to repaint the tab so it will grow to accomodate the new row
    RepaintWebTab();
    
    // Return false so the browser will not submit to server (adding rows
    // is a client-side operation)
    return false;
}

// Repaints the WebTab to accomodate changes in tab contents size, or floating buttons.
function RepaintWebTab()
{
    // Get all ASP.NET AJAX components on the page
    var c = Sys.Application.getComponents();
    
    for (var i = 0; i < c.length; i++) 
    {
        var control = c[i];
        var type = Object.getType(c[i]).getName();
        
        if (type == 'Infragistics.Web.UI.WebTab')
        {// We have a WebTab--repaint it
        
            control.repaint();
        }
    }
}

function InitializeNewRow(grid, row) 
{
    // Roll through the cells 
    for (var i = 0; i < row.cells.length; i++)
    {
        args = row.cells[i].Column.Key.split("|"); 
        if (args[1] == "7")
        {// This is a selectsingle column.  We need to create a new cell template.

            var tableSelectSingleTemplateHtml = _tableSelectSingleHtml;

            // Massage the template for this cell
            tableSelectSingleTemplateHtml = GetTableSelectSingleTemplateHtml(tableSelectSingleTemplateHtml,
                                                                             grid.ClientID,
                                                                             i,
                                                                             grid.Rows.length - 1, 
                                                                             row.cells[i].Column.ValueListPrompt);

            // Assign cell template html to this cell
            $('#' + row.cells[i].Id).html(tableSelectSingleTemplateHtml);
        }
    }
}

function GetTableSelectSingleTemplateHtml(template, gridId, columnIndex, rowIndex, defaultText)
{
    template = ReplaceAll(template, '[GridId]', gridId);
    template = ReplaceAll(template, '[ColumnIndex]', columnIndex);
    template = ReplaceAll(template, '[RowIndex]', rowIndex);
    template = ReplaceAll(template, '[DefaultText]', defaultText);

    return template;
}

function ReplaceAll(text, strA, strB) 
{
    while (text.indexOf(strA) != -1) {
        text = text.replace(strA, strB);
    }
    return text;
}

function AddRowMultiple(A, B, C) { grid = igtbl_getGridById(A); igtbl_addNew(A, 0); _addCounter++; grid.Rows.getRow(grid.Rows.length - 1).getCell(B).setValue(C) } function SuspendUpdates(B, A) { grid = igtbl_getGridById(B); grid.suspendUpdates(A) } function EditRow(B, C) { var A = igtbl_getCellById(C); if (A != null) { var E = A.Row.getIndex; var D = B + E; if (_editDictionary[D] == null) { _editDictionary[D] = 1; _editCounter++ } } } 

function OnBeforeUnload() 
{ 
    if (! _onBeforeUnloadHandled)
    {// This event has not fired already and been handled here--continue
    
        // Serialize grid template cell values
        // No don't do this here anymore.  It will mess up with the button disable after a click code that 
        // tries to prevent multiple submits.  This runs on the button clicks now.
        // SerializeGridTemplateClientState();
        
        // Check if we have unsaved values in a grid
        if ((_addCounter > 0 || _editCounter > 0 || _deleteCounter > 0) && _checkClickAway) 
        {// There are unsaved data--do clickaway warning
         
            event.returnValue = "You have added, edited, and/or deleted rows pending on this page.  These changes have not been saved to the database.  If you click OK, you will lose changes you have made to these rows.  If you click Cancel, you will have an opportunity to save changes you have made to these rows.";  
        }
        else
        {// No unsaved data--set mutex to true so we don't come through here again (IE fires OnBeforeUnload twice)
    
            // Set flag
            _onBeforeUnloadHandled = true;
        }
    }
} 
    
function RemoveAllRows(A) { grid = igtbl_getGridById(A); counter = 0; if (grid.Rows.length > 0) { lastIndex = grid.Rows.length - 1; while (counter <= lastIndex) { row = igtbl_getRowById(A + "r_" + counter); row.remove(); counter++ } } return false } function CheckMaxLength(C, A) { var B; var D = C.value; B = D.length; if (B > A) { C.value = D.substring(0, A) } }

// Submits the page.  Usually called by an onkeydown event.  The submit occurs if return was pressed.
function submitPage(buttonID) 
{
    if (event.keyCode == 13) 
    {
        document.getElementById(buttonID).click();
        event.returnValue = false
    }
}

function OnNodeChecked(C, D, A) { if (!_checkMutex) { _checkMutex = true; if (window.event.ctrlKey) { var B = igtree_getNodeById(D); if (B.getChildNodes().length > 0) { CheckNodes(B.getChildNodes(), A, false); B.setExpanded(true) } } _checkMutex = false } } function CheckAllNodes(B, A) { _checkMutex = true; document.body.style.cursor = "wait"; tree = igtree_getTreeById(B); tree.Events.NodeChecked[0] = ""; nodes = tree.getNodes(); CheckNodes(nodes, A, true); tree.Events.NodeChecked[0] = "OnNodeChecked"; document.body.style.cursor = "default"; _checkMutex = false } function CheckNodes(B, D, E) { for (var C = 0, A = B.length; C < A; C++) { if (B[C].getChecked() != D && B[C].getEnabled()) { B[C].setChecked(D) } if (B[C].hasChildren() && E) { CheckNodes(B[C].getChildNodes(), D, true) } } } 

function BeforeEnterEditModeHandler(gridID, cellID)
{
    cell = igtbl_getCellById(cellID);
    args = cell.Column.Key.split("|");
    
    if (args[3] == "1")
    // This is a multiple add picker source column--do not allow editing
        return true;
    else 
        return false;
}

function SessionWarning(A) { alert(A); window.clearInterval(_interval) } function CheckForBrowserClose() { if (screenTop > 9999) { window.open("Logout.aspx?type=1", "CtrlWindow", "toolbar=no,menubar=no,location=no,scrollbars=no,resizable=no,width=200,height=200") } } function BeforeCellUpdateHandler(A, B, C) { cell = igtbl_getCellById(B); args = cell.Column.Key.split("|"); if (window.event != null && window.event.ctrlKey) { if (args[1] == 6 || args[1] == 7) { grid = igtbl_getGridById(A); for (i = 0; i < grid.Rows.length; i++) { grid.Rows.getRow(i).getCell(cell.Index).setValue(C) } } } return false } function ItemClick(B, A) { } function AfterRowDeleted2(A, B) { _deleteCounter++ }

function AfterCellUpdate2(B, C) {
    var A = igtbl_getCellById(C);
    if (A != null) {
        var E = A.Row.getIndex;
        var D = B + E;
        if (_editDictionary[D] == null) {
            _editDictionary[D] = 1;
            _editCounter++
        }
    }
}

function AfterRowInsert2(gridID, rowID) 
{
    var grid = igtbl_getGridById(gridID);
    var row = grid.getActiveRow();

    // Was storing the first editable cell in the FooterClass.  Can't do this anymore as FooterClass 
    // is used to store actually CSS classes.
    // Initial edit cell has not been specified--use the first editable cell
    // OK, can't even get the first editable cell into edit mode.  Give up.

    // Increment counter so we can check upon clickaway
    _addCounter++;

    // Return false so we don't postback
    return true;
}

function AddRowXML(gridID) 
{
    // First get grid object so we can figure out the row index of the new row (goes
    // on the end of the grid)
    var grid = igtbl_getGridById(gridID);

    if (grid.getActiveRow() != null) 
    {// There is an active row--get the band number from this row

        // Add row to the current band
        igtbl_addNew(gridID, grid.getActiveRow().Band.Index);
    }
    else {// No active row--just add to the end

        igtbl_addNew(gridID, 0);
    }

    // Add new row
    //    igtbl_addNew(gridID, 0); 

    var row = igtbl_getActiveRow(gridID);

    var cell;

    // Find the first editable cell and put it into edit mode (it is kept in the band footer class)
    if (grid.Bands[0].FooterClass != "") 
    {// Initial edit cell has been specified

        cell = row.getCellFromKey(grid.Bands[0].FooterClass);
    }
    else 
    {// Initial edit cell has not been specified--use the first editable cell

        var cellIndex = 0;
        cell = row.getCell(cellIndex);

        while (cell != null && cell.Column.AllowUpdate != 1) {
            cellIndex++;
            cell = row.getCell(cellIndex);
        }
    }

    // Put it into edit mode
    if (cell != null) cell.beginEdit();

    // Set the row key to a unique value.  This helps with keeping track of rows on the client side 
    // (validation).
    row.DataKey = NewRowKey(grid);

    // Increment counter so we can check for pending rows upon clickaway
    _xmlAddCounter++;

    // Return false so the browser will not submit to server (adding rows
    // is a client-side operation)
    return false;
}

function DeleteGridRows(A) { document.body.style.cursor = "wait"; var B = igtbl_getGridById(A); if (igtbl_getLength(B.SelectedRows) > 0) { if (confirm("You are about to delete all selected rows.  Click OK to continue or click Cancel to stop deletion of selected rows.")) { for (var C in B.SelectedRows) { var D = igtbl_getRowById(C); D.deleteRow() } if (_gridValidationList.count() == 0) { B.invokeXmlHttpRequest(B.eReqType.Page, B, B.CurrentPageIndex) } } } else { alert("No tasks are selected.  You need to select at least one task to delete.") } document.body.style.cursor = "default"; return false } function NewRowKey(A) { var C = 0; var D = 0; var B = A.Rows.getRow(D); while (B != null) { if ((+B.DataKey) > C) { C = (+B.DataKey) } D++; B = A.Rows.getRow(D) } if (C < _newRowKeyPaddingValue) { C += _newRowKeyPaddingValue } else { C++ } return String(C) } function AfterRowInsert(A, B) { return false } function ColumnHeaderClick(A, E, B) { var C = igtbl_getGridById(A); var D = igtbl_getColumnById(E); if (B == 0) { C.addSortColumn(E, true); C.invokeXmlHttpRequest(C.eReqType.Sort, C.Rows, D.Index); igtbl_cancelPostBack(A) } return true } function OverlibOnMouseOver(A) { return overlib(A.srcElement.toolTip, WRAP, HAUTO, SHADOW, SHADOWX, 2, SHADOWY, 2, FGCLASS, "ToolTipFGClass", BGCLASS, "ToolTipBGClass", AUTOSTATUSCAP, TEXTFONTCLASS, "ToolTipTextFontClass", CAPTION, A.srcElement.toolTipTitle, CAPTIONFONTCLASS, "ToolTipCaptionFontClass", CGCLASS, "ToolTipCGClass") } function OverlibOnMouseOut(A) { return nd() } function BeforeRowActivate(A, B) { } function BeforeXmlHttpRequest(A, B) { _inXmlRequest = true; switch (B) { case 5: window.status = "Adding row..."; break; case 7: window.status = "Updating row..."; var C = A.replace("x", "_").replace("x", "_").replace("x", "_").replace("x", "_").replace("x", "_").replace("x", "_"); _addButton1 = document.getElementById(C + "AddButton1"); _addButton2 = document.getElementById(C + "AddButton2"); if (_addButton1 != null) { _addButton1.disabled = true } if (_addButton2 != null) { _addButton2.disabled = true } break; case 9: window.status = "Fetching new page..." } } function XmlHTTPResponse(M, J, C) { var A = igtbl_getGridById(M); switch (C.ReqType) { case 3: break; case 5: case 7: _xmlHTTPResponseRowID = J; var P = igtbl_getRowById(J); var K = C.Tag.split("|"); var L = 0; var N = P.getCell(L); while (N != null && N.Element != null) { N.Element.style.border = ""; N.Element.detachEvent("onmouseover", OverlibOnMouseOver); N.Element.detachEvent("onmouseout", OverlibOnMouseOut); L++; N = P.getCell(L) } if (C.Tag != "") { var I = K[0].split("^"); var H = K[1].split("^"); for (F = 0; F < I.length; F++) { P.getCellFromKey(I[F]).Element.style.border = "solid 2px #ff0000"; P.getCellFromKey(I[F]).Element.toolTip = H[F]; P.getCellFromKey(I[F]).Element.toolTipTitle = "Invalid Cell"; P.getCellFromKey(I[F]).Element.attachEvent("onmouseover", OverlibOnMouseOver); P.getCellFromKey(I[F]).Element.attachEvent("onmouseout", OverlibOnMouseOut) } _gridValidationList.setEntry(P.DataKey, 1) } else { if (P.DataKey == null) { _xmlAddCounter-- } else { _xmlEditDictionary[P.DataKey] = null; _xmlEditCounter-- } _gridValidationList.setEntry(P.DataKey, null); if (_gridValidationList.count() == 0 && document.getElementById("f1_c1__checkAutoRecalc").checked) { _xmlPagingPending = true; A.invokeXmlHttpRequest(A.eReqType.Page, A, A.CurrentPageIndex); C.StatusMessage = C.StatusMessage + " Grid refreshed." } } window.defaultStatus = C.StatusMessage; break; case 6: if (_gridValidationList.count() == 0 && igtbl_getLength(A.SelectedRows) <= 1) { A.invokeXmlHttpRequest(A.eReqType.Page, A, A.CurrentPageIndex) } window.defaultStatus = C.StatusMessage; break; case 8: var E = A.Bands[0].getColumnFromKey(C.StatusMessage); var D = C.Tag.split("^"); var G = D.length; var B = new Array(); for (var F = 0; F < G; F++) { var O = D[F].split("|"); B[F] = new Array(O[0], O[1]) } E.ValueList = B; break; case 9: _xmlPagingPending = false; break } if (_addButton1 != null && !_xmlPagingPending) { _addButton1.disabled = false } if (_addButton2 != null && !_xmlPagingPending) { _addButton2.disabled = false } } function AfterXmlHttpResponseProcessed(B) { if (_xmlHTTPResponseRowID != null) { var F = igtbl_getRowById(_xmlHTTPResponseRowID); if (F != null) { var C = 0; A = F.getCell(C); while (A != null) { if (A.Column != null && DecodeInputTypeFromColumnInfo(A.Column) == "13") { var E = A.Element.innerHTML; E = E.replace("&lt;", "<"); E = E.replace("&gt;", ">"); E = E.replace("&lt;", "<"); E = E.replace("&gt;", ">"); A.Element.innerHTML = E } C++; A = F.getCell(C) } } } igtbl_cancelPostBack(B); _inXmlRequest = false; if (_cellIDToEditAfterXmlRequest != "" && !_xmlPagingPending) { document.body.style.cursor = "default"; var A = igtbl_getCellById(_cellIDToEditAfterXmlRequest); if (A != null) { A.activate(); A.setSelected(true); A.beginEdit() } } if (_pendingSubmitButton != null) { _rowUpdateComplete = true; var D = document.getElementById(_pendingSubmitButton); _pendingSubmitButton = null; D.click() } } function InitializeRow(A, B) { var C = igtbl_getRowById(B) } function SetParentValue(D, C, A, B) { textControl = igedit_getById(D); textControl.setText(C); valueControl = igedit_getById(A); valueControl.setText(B) }

function BeforeEnterEditMode2(B, D) {
    _inEditMode = true;

    if (_inXmlRequest) {
        _cellIDToEditAfterXmlRequest = D;
        document.body.style.cursor = "wait";
        return true
    }
    else {
        var A = igtbl_getCellById(D);
        _originalCellText = A.Element.innerHTML;
        cellText = A.Element.innerHTML;

        if (A.Column != null && DecodeInputTypeFromColumnInfo(A.Column) == "13" && Trim(cellText) != "") {
            _cellText1 = cellText.toLowerCase().substring(0, cellText.toLowerCase().indexOf(">") + 1);
            _cellText2 = cellText.toLowerCase().substring(cellText.toLowerCase().indexOf("</a>"));
            _cellTextStripped = cellText.substring(cellText.toLowerCase().indexOf(">") + 1, cellText.toLowerCase().indexOf("</a>"));

            A.setValue(_cellTextStripped)
        }
        else {
            if (_cellIDToEditAfterXmlRequest == "") {
                if (A.Column != null && DecodeInputTypeFromColumnInfo(A.Column) == "7") { if (DecodeDependencyKeyFromColumnInfo(A.Column) != "null") { var F = DecodeDependencyKeyFromColumnInfo(A.Column); var C = igtbl_getGridById(B); var E = A.Column.Key; C.invokeXmlHttpRequest(C.eReqType.Custom, null, E); _columnUpdatedList.setEntry(F, null); _cellIDToEditAfterXmlRequest = D; return true } }
            }
        } _cellIDToEditAfterXmlRequest = ""
    }
}

function BeforeExitEditMode2(C, D, E) {

    var B = igtbl_getCellById(D);
    var A = false;
    if (DecodeInputTypeFromColumnInfo(B.Column) == "13") {
        if (_cellText1.length > 1 && _cellText1.substr(0, 2).toLowerCase() == "<a") {
            E = _cellText1 + E + _cellText2
        }
    }

    return A
}

function AfterExitEditMode(A, B) { _inEditMode = false } function ExpandedStateChanging(B, C) { var E = document.getElementById("f1:Navigation"); var A = document.getElementById("_mainNavCollapseDiv"); var D = document.getElementById("f1__tableCellMainNavCollapse"); if (B == "collapse") { A.runtimeStyle.display = "none"; D.runtimeStyle.display = "none"; E.runtimeStyle.display = "block" } else { A.runtimeStyle.display = "block"; D.runtimeStyle.display = "block"; E.runtimeStyle.display = "none"; C.cancel = true } } function DecodeInputTypeFromColumnInfo(A) { args = A.FooterText.split("|"); return args[0] } function DecodeDependencyKeyFromColumnInfo(A) { args = A.FooterText.split("|"); return args[1] } function EditKeyDown(C, B, E) { var F = igtbl_getCellById(B); var I = F.getRow(); switch (E) { case 40: var G = I.getNextRow(); if (G != null) { F.endEdit(true); G.getCell(F.Index).activate(); G.getCell(F.Index).beginEdit() } break; case 38: var A = I.getPrevRow(); if (A != null) { F.endEdit(true); A.getCell(F.Index).activate(); A.getCell(F.Index).beginEdit() } break; case 39: var H = F.getNextCell(); if (H != null) { F.endEdit(true); H.activate(); H.beginEdit() } break; case 37: var D = F.getPrevCell(); if (D != null) { F.endEdit(true); D.activate(); D.beginEdit() } break } } function CheckForPostback(C) { var A; if (!_rowUpdateComplete) { var D = igtbl_getGridById("f1_c1_t1_t1Grid"); for (rowID in D.ChangedRows) { var E = igtbl_getRowById(rowID); var B = E.processUpdateRow() } } else { _rowUpdateComplete = false } if (_inXmlRequest) { _pendingSubmitButton = C; A = false } else { A = true } return A }

function WebSpellChecker_ButtonClick(B, A) { A.checkTextComponent(B) }

function WebSpellChecker_GetText(C, B, A) {
    return A
}

function WebSpellChecker_SetText(C, B, A) { }

function TreeDeleteNode(B) { var A = igtree_getTreeById(B); var C = A.getSelectedNode(); if (C == null) { } else { C.remove() } } function TreeAddNode(C, B) { var A = igtree_getTreeById(C); var D = A.getSelectedNode(); if (D == null) { A.addRoot(B, "TreeItem") } else { D.addChild(B, "TreeItem") } } function TreeDrop(B, A, C) { C.sourceName = C.sourceObject.getTag() } function TreeBeforeBeginNodeEdit(C, D) { var A = false; var B = igtree_getNodeById(D); if (B.getTag() == -1) { A = true } return A };

function SearchRedirect(SiteUrl) {
    var q = escape(document.getElementById('q').value);

    // We will default to searching by project (p=0 would be across projects)
    var p = 1;

    var url = SiteUrl + 'SearchList.aspx?q=#q#&p=#p#';
    var redirUrl = url.replace("#q#", q).replace("#p#", p);

    window.location.href = redirUrl;
    return false;
}

// Set focus to userid or password box
function SetLoginFormFocus() 
{
    // Using JQuery here

    if ($('#f1_c1_frmLogin_Item0_Field1').val() == '') {// The login user id box is blank--set focus to it

        $('#f1_c1_frmLogin_Item0_Field1').focus();
    }
    else {// The login user id box is filled in--set focus to password box

        $('#f1_c1_frmLogin_Item1_Field2').focus(); 
    }
}

//This event is fired after any action is performed on the HTML Editor, and cannot be cancelled.  
//Note: parameters p4,p5,p6,p7,p8 are not public, and are subject to change in future releases.
function WebHtmlEditor_AfterAction(editor, actionID, event, p4, p5, p6, p7, p8) {
    if (actionID == "InsertLink") {// An anchor link is being inserted--make sure it's target is set

        // Get all anchors
        var anchors = editor._elem.getElementsByTagName("A");

        // Iterate through them
        for (var i = 0; i < anchors.length; i++) {
            // If a target is blank, set it to _blank to pop up a new window
            if (anchors[i].target == "") anchors[i].target = "_blank";
        }
    }
}

function ToggleProjectPicker() 
{
    if (!_projectDialogCreated)
    {// Project dialog not instanced--do it now and reset flag

        var x = $("#ProjectPickerDiv").position().left;
        var y = $("#ProjectPickerDiv").position().top + $("#ProjectPickerDiv").height() + 5;
        $("#ProjectDialog").dialog({ autoOpen: false, 
                              draggable: false,
                              height: 400,
                              position: [x,y],
                              resizable: true,
                              title: 'Switch Project',
                              width: 400 });
        _projectDialogCreated = true;
    }

    if (! $("#ProjectDialog").dialog("isOpen")) {// Picker is hidden--show it and load it if necessary

        if ($("#ProjectDialog").text() == "") {// Nothing in the picker div--load it via AJAX web service--it will be shown in the callback

            var nocache = Math.ceil(Math.random() * 100000000);
            var ret = CPM.iCPMService.GetProjectPickerHtml(nocache, OnProjectSuccedeed, OnFailed);
        }
        else {// Picker already loaded--just show it

            $("#ProjectDialog").dialog("open");
        }
    }
    else {// Picker is visible--just hide it

        $("#ProjectDialog").dialog("close");
    }
}

function OnProjectSuccedeed(response) 
{
    $("#ProjectDialog").html(response);
    $("#ProjectDialog").dialog("open");
}

function ToggleClientPicker() 
{
    if (! _clientDialogCreated) {// Client dialog not instanced--do it now and reset flag

        var x = $("#ClientPickerDiv").position().left;
        var y = $("#ClientPickerDiv").position().top + $("#ClientPickerDiv").height() + 5;
        $("#ClientDialog").dialog({ autoOpen: false,
            draggable: false,
            height: 400,
            position: [x, y],
            resizable: true,
            title: 'Switch Company',
            width: 400
        });
        _clientDialogCreated = true;
    }

    if (!$("#ClientDialog").dialog("isOpen")) {// Picker is hidden--show it and load it if necessary

        if ($("#ClientDialog").text() == "") {// Nothing in the picker div--load it via AJAX web service--it will be shown in the callback

            var ret = CPM.iCPMService.GetClientPickerHtml(OnClientSuccedeed, OnFailed);
        }
        else {// Picker already loaded--just show it

            $("#ClientDialog").dialog("open");
        }
    }
    else {// Picker is visible--just hide it

        $("#ClientDialog").dialog("close");
    }
}

function OnClientSuccedeed(response) {
    $("#ClientDialog").html(response);
    $("#ClientDialog").dialog("open");
}

function OnFailed(error) 
{
    // Alert user to the error.
    alert(error.get_message());
}

// Called when a selected tab changes
function AfterSelectedTabChange(webTab, tab, event)
{
    // Set all button menus to normal static state
    $('div.FloatMenuDiv').css("width", "")
                         .css("height", "")
                         .css("padding-top", "")
                         .css("padding-left", "")
                         .css("border-top", "none")
                         .css("border-left", "none")
                         .css("-ms-filter", "")
                         .css("filter", "")
                         .removeClass("ui-state-highlight")
                         .removeAttr("buttonBarHeightOffset")
                         .css("position", "static");

    // Get starting button menu Y positions and record them.  Use a timeout to delay a bit because in this event
    // handler, the new tab is not visible yet
    setTimeout('GetAllButtonMenuStartingYValues()', 200);

    // Float button menus if necessary
    setTimeout('FloatMenu()', 250);

    // Refire autogrow code in case the textarea was hidden when the page loaded (not on the first tab)
    if (jQuery.browser.msie && jQuery.browser.version == "7.0") {// Browser is IE7--don't do textarea autogrow, just set the height

        $('textarea').css('height', '80px');
    }
    else {// Browser is NOT IE7--do textarea autogrow

        // For now, don't do the autogrow for other browsers either.  It causes buttons to get
        // pushed out of view on tabs (the tab container does not grow).
        //$('textarea.TextAreaAutoGrow').elastic();
        $('textarea').css('height', '80px');
    }

    // On FYIDetail, we need to check if we are switching to the Discussion tab--if we are, we need to dynamically
    // resize the IFrame on that tab.  The tab was invisible when the page loaded so it could not be resized when
    // the page loaded.
    var selectedIndex = eventArgs.get_tabIndex();
    var selectedTab = webTab.get_tabs()[selectedIndex];
    
    if (webTab.ID == 'f1_c1_t1_ctl00' && selectedTab.text == 'Discussion') 
    {
        setTimeout("IFrameResize()", 100)
    }
}

function WebTab_SelectedIndexChanged(webTab, eventArgs)
{
    // Set all button menus to normal static state
    $('div.FloatMenuDiv').css("width", "")
                         .css("height", "")
                         .css("padding-top", "")
                         .css("padding-left", "")
                         .css("border-top", "none")
                         .css("border-left", "none")
                         .css("-ms-filter", "")
                         .css("filter", "")
                         .removeClass("ui-state-highlight")
                         .removeAttr("buttonBarHeightOffset")
                         .css("position", "static");

    // Get starting button menu Y positions and record them.  Use a timeout to delay a bit because in this event
    // handler, the new tab is not visible yet
    setTimeout('GetAllButtonMenuStartingYValues()', 200);

    // Float button menus if necessary
    setTimeout('FloatMenu()', 200);

    // Refire autogrow code in case the textarea was hidden when the page loaded (not on the first tab)
    if (jQuery.browser.msie && jQuery.browser.version == "7.0") {// Browser is IE7--don't do textarea autogrow, just set the height

        $('textarea').css('height', '80px');
    }
    else {// Browser is NOT IE7--do textarea autogrow

        // For now, don't do the autogrow for other browsers either.  It causes buttons to get
        // pushed out of view on tabs (the tab container does not grow).
        //$('textarea.TextAreaAutoGrow').elastic();
        $('textarea').css('height', '80px');
    }

    // On FYIDetail, we need to check if we are switching to the Discussion tab--if we are, we need to dynamically
    // resize the IFrame on that tab.  The tab was invisible when the page loaded so it could not be resized when
    // the page loaded.
    if (webTab.get_id() == 'f1_c1_t1__tab' && webTab.get_tabs()[webTab.get_selectedIndex()].get_text() == 'Discussion') 
    {
        setTimeout("IFrameResize()", 100)
    }
    
    // Set new selected tab index so server side code can read this
    var currentTabIndexHiddenID = webTab.get_id().substring(0, webTab.get_id().length - 4) + 'CurrentTabIndex';
    $('#' + currentTabIndexHiddenID).val(eventArgs.get_tabIndex());
    
    // Repaint the tab so it will grow to accomodate the new row
    setTimeout('RepaintWebTab()', 400);
}

function GetAllButtonMenuStartingYValues()
{
    // Set
    $('div.FloatMenuDiv').each(function(pos) { GetButtonMenuStartingYValue(this); });
}

function GetButtonMenuStartingYValue(buttonMenuDiv) 
{
    if ($('#' + GetAnchorDivId($(buttonMenuDiv).attr('id'))).offset().top != 0)
    {// Starting button menu Y pos is available--record it
        
        startingMenuYList[$(buttonMenuDiv).attr('id')] = $('#' + GetAnchorDivId($(buttonMenuDiv).attr('id'))).offset().top;
    }
}

// Returns if an element is really visible or not (check's parents' visibility)
function ReallyVisible(element) 
{
    return !(jQuery(element).is(':hidden') || jQuery(element).parents(':hidden').length);
}

function TogglePowerSearchDialog(powerSearchFilterId)
{
    var $powerSearchPane = $('div.PowerSearchFilterDiv');

    if (powerSearchFilterId != null) 
    {// Called with a particular filter passed--need to let the user change or remove this filter--only
     // show this filter's items along with the remove link

        // Hide all filters then show the one in question
        $powerSearchPane.children().hide();
        $powerSearchPane.children('#' + powerSearchFilterId).show();

        // Show the remove link for the filter in question
        //$powerSearchPane.children('#' + powerSearchFilterId + '_remove').css('display','');
        $powerSearchPane.children('#' + powerSearchFilterId + '_remove').show();
    }
    else 
    {// Called with no filter specified--add filter link clicked--just show the dialog with all filters
    
        // Show the filters
        $powerSearchPane.children().show();

        // First hide any remove links
        $powerSearchPane.find('a.RemoveLink').hide();
    }

    if ($powerSearchPane.dialog('isOpen'))
        $powerSearchPane.dialog('close');
    else 
    {
        $powerSearchPane.dialog('open');
    }
}

// Makes sure the toolbar button menu is visible by floating it if necessary
function FloatOneMenu(pos) 
{
    if (startingMenuYList[$(this).attr('id')] != undefined && (ReallyVisible(this) || $(this).css('position') == 'fixed')) 
    {// This button menu's starting Y position has been recorded and it is either visible or already floating--continue

        var buttonBarHeightOffsetCheck = 30;
        var $this = $(this);
        
        if ($('div.FloatMenuDiv').is('.ui-state-highlight')) buttonBarHeightOffsetCheck = 60;

        if (startingMenuYList[$this.attr('id')] + buttonBarHeightOffsetCheck < $(window).height() + $(document).scrollTop()) 
        {// Button/element is visible on the screen--put it in it's normal place by setting it's position back to static

            $this.css("width", "")
                 .css("height", "")
                 .css("padding-top", "")
                 .css("padding-left", "")
                 .css("border-top", "none")
                 .css("border-left", "none")
                 .css("margin-top", "")
                 .removeClass("ui-state-highlight")
                 .removeAttr("buttonBarHeightOffset");
            //$this.css("opacity", "");
            //$this.css("filter", "");

            // If there is a button bar header, hide it
            if ($this.children('#_bbh').length == 1) $this.children('#_bbh').css("display", "none");

            $this.css("position", "static");
            
            // Repaint any WebTabs on the page because a button going back to position static can change the height
            // of a tab's content.
            // No we don't do this anymore.  A repaint is causing a problem with old grids.  So now the anchor div contains
            // the button bar div as a child.  So when the child floats, the anchor div remains so that content doesn't flow.
            //RepaintWebTab();
        }
        else 
        {// Button/element is below the visible browser client area--move toolbar so it is visible at bottom of the page

            var buttonBarHeightOffset = 30;
            if ($('div.FloatMenuDiv').is('.ui-state-highlight')) buttonBarHeightOffset = 60;
            if ($this.attr('buttonBarHeightOffset') != undefined) buttonBarHeightOffset = $this.attr('buttonBarHeightOffset')

            // We do this with absolute positioning
            $this.css("position", "fixed")
                 .css("z-index", "200")
                 .css("width", "100%")
                 .css("height", "24px")
                 .css("padding-top", "5px")
                 .css("padding-left", "5px")
                 .css("border-top", "solid 1px #cccccc")
                 .css("border-left", "solid 1px #cccccc")
                 .css("margin-top", "0px")
                 .addClass("ui-state-highlight")
                 .attr('buttonBarHeightOffset', buttonBarHeightOffset);
            //$this.css("background-color", "#f6f6f6");
            //$this.css("opacity", ".90");
            //$this.css("filter", "alpha(opacity=90)");

            // If there is a button bar header, light it up
            if ($this.children('#_bbh').length == 1) $this.children('#_bbh').css("display", "");

            $this.bgiframe();
            var offset = $(window).height() - buttonBarHeightOffset + "px";
            
            $this.css("top", offset)
                 .css("left", "0");
        }
    }
}

// Table2 client side events ######################################################################################
// Associative array used for Table2 grid template column cell state, keyed by grid, then by row/column key.
var _templateClientState = new Object();

function ActiveCellChanged(sender, e) 
{
    var cell = e.getActiveCell();
    var column = cell.get_column();
    var grid = sender;
    var editingBehavior = grid.get_behaviors().get_editingCore().get_behaviors().get_cellEditing();
    var readOnly = editingBehavior.get_columnSettings()._items[column.get_index()].get_readOnly();
    
    if (column.get_type() == "date" && ! readOnly)
    {// We are on an editable date cell--set the focus to the date textbox so the datepicker appears

        cell._element.childNodes[0].focus();
    }
}

// Fires when a change is made to column filtering.  We will write the filtering state to a form element.  This
// will be used on the server side to restore the filtering state.
function DataFiltering(sender, e) 
{
    var filteringState = new Object();
    
    // Get the column filters array
    var columnFilters = e.get_columnFilters();
    var columnFilterCount = columnFilters.length;
    
    // Roll through column filters and save to filtering state array
    for (var i = 0; i < columnFilterCount; i++)
    {
        // Get the column key and condition rule
        var key = columnFilters[i].get_columnKey();
        var condition = columnFilters[i].get_condition();
        var value = condition.get_value();
        
        filteringState[key] = value;
    }
    
    // Serialize and save in the form
    $("#" + sender.get_element().parentElement.id.replace(/\$/g, "_", true) + "__filteringState").val(Sys.Serialization.JavaScriptSerializer.serialize(filteringState));
}

function EnteringEditMode(sender, e)
{
    var cell = e.getCell();
    var inputType = cell.get_column().get_footerText();
    var cellText = cell.get_element().innerHTML;

    // Save original value
    _originalCellValue = e.getCell().get_value();
    
    if (inputType.toUpperCase() == "URL" && Trim(cellText) != "")
    {// InputType.URL and there is cell text--this text must be linked so we need to strip the HTML anchor for editing
        
        _cellText1 = cellText.toLowerCase().substring(0, cellText.toLowerCase().indexOf(">") + 1);
        _cellText2 = cellText.toLowerCase().substring(cellText.toLowerCase().indexOf("</a>"));
        
        cellTextStripped = cellText.substring(cellText.toLowerCase().indexOf(">") + 1, cellText.toLowerCase().indexOf("</a>"));
        
        // Set edit box text and strip anchor html tags
        cell.set_value(cellTextStripped);
    }
}

function ExitingEditMode(sender, e) 
{
    // Check for a cell value change
    if (e.getCell().get_value() != e.get_displayText()) _editCounter++;

    // If we are hosted by a WebTab, we need to repaint the tab so it will grow to accomodate the edit
    // No don't do this...the page will scroll up to put the tab strip in view...that is highly annoying
    //RepaintWebTab();
}

// Saves changes to template column cell values to a client side structure.  This structure is 
// checked on postback to apply value changes to the data.
function SetTemplateCellValueState(tableID, rowKey, columnKey, value)
{
    // If client state associative array doesn't have any elements yet, add this grid as an element
    if (_templateClientState[tableID] == null) 
    {// No array for this grid--make one
        
        _templateClientState[tableID] = new Object();
    }
    
    // If client state associative array does not have a row element for this grid yet, add it
    if (_templateClientState[tableID][rowKey] == null) 
    {// No array for this grid--make one
        
        _templateClientState[tableID][rowKey] = new Object();
    }
    
    // We just set the cell's client state in the array.  If the cell key is not already there, 
    // it will be created.  If it is there, the value will be updated.
    _templateClientState[tableID][rowKey][columnKey] = value;
    
    // Now increment the edit counter for ClickAway processing
    _editCounter++;
}

function SerializeGridTemplateClientState()
{
    // Need to serialize any cell values that changed in templated columns.  We do this here because
    // the grid won't save these values to it's client state.

    // Serialize each Table2    
    for (var key in _templateClientState)
    {
        // Set hidden input element to serialized value
        $('#' + key + '__templateClientState').val(Sys.Serialization.JavaScriptSerializer.serialize(_templateClientState[key]));
        
        // Escape any $ or jQuery will blow...
        //key = ReplaceAll(key, '$', '\\$');

        // Need to use $ delimited name here
        //$('#' + key + '__templateClientState').val(Sys.Serialization.JavaScriptSerializer.serialize(_templateClientState[key]));
    }
}

function FilterDropdownDisplaying(sender, e)
{
    // Cancel this--we don't show the rule dropdowns
    e.set_cancel(true);
}

function ExportGrid(gridID) 
{
    // Set hidden value so server side code knows to do the export
    //$('#' + gridID + '__exportGridState').val('1');

    // Postback
    __doPostBack(gridID + '__exportGridState', '1');
}

function IndexChanged(gridID, dropDownListID) 
{
	var dropdownlist = document.getElementById(dropDownListID);

	var grid = $find(gridID);
	var newValue = dropdownlist.selectedIndex;
	grid.get_behaviors().get_paging().set_pageIndex(newValue);
}

function FirstPage(gridID) 
{
	var grid = $find(gridID);
    
	grid.get_behaviors().get_paging().set_pageIndex(0);
}

function PreviousPage(gridID) 
{
	var grid = $find(gridID);
    
	if (grid.get_behaviors().get_paging().get_pageIndex() > 0 ) 
	{
		grid.get_behaviors().get_paging().set_pageIndex(grid.get_behaviors().get_paging().get_pageIndex() - 1);
	}
}

function NextPage(gridID) 
{
	var grid = $find(gridID);

	if (grid.get_behaviors().get_paging().get_pageIndex() < grid.get_behaviors().get_paging().get_pageCount() - 1) 
	{
		grid.get_behaviors().get_paging().set_pageIndex(grid.get_behaviors().get_paging().get_pageIndex() + 1);
	}
}

function LastPage(gridID) 
{
	var grid = $find(gridID);
    
	grid.get_behaviors().get_paging().set_pageIndex(grid.get_behaviors().get_paging().get_pageCount() - 1);
}

function HighlightNewRow(gridID, rowKey)
{
    // Must use a key array to find the row
    var keyArray = new Array(); 
    keyArray[0] = rowKey;  
    
    var grid = $find(gridID);
    var selection = grid.get_behaviors().get_selection(); 
    var row = grid.get_rows().get_rowFromKey(keyArray);
    
    // We may not find the row cause it might be on another page
    if (row != null)
    {
        selection.get_selectedRows().add(row); 
        $.scrollTo(row.get_element()); 
    }
}

function TextEditor_ValueChanged(sender, e) 
{
    // Get the old value in the editor
    var oldValue = e.get_oldValue();

    // Get the new value in the editor
    var newValue = Trim(e.get_value());
    
    // Get cell element
    var control = sender.get_inputElement();
    
    if (newValue == '')
    {// New value will be blank--disallow this and alert the user
        
        alert("This field is required, so it cannot be left blank.  If you try to save this field as a blank, the text previously typed in the field will appear again.");
    }
}

// Called when the navigation menu collapses
function WebDataMenu_ItemCollapsing(sender, e) 
{
    //Gets the DataMenuItem object that is collapsing
    var item = e.getItem();

    if (item.get_parentItem() == null) 
    {// Collapsing to root level--show any Silverlight
    
        $('#silverlightControlHost').show();
    }
}

// Called when the navigation menu expands
function WebDataMenu_ItemExpanding(sender, e) 
{
    //Gets the DataMenuItem object that is expanding
    var item = e.getItem();

    if (item.get_parentItem() == null) 
    {// Expanding from root level--hide any Silverlight

        $('#silverlightControlHost').hide();
    }
}

// Scrolls a node into view
function UltraWebTree_ScrollNodeIntoView(treeId, nodeId) 
{
    var tree = igtree_getTreeById(treeId);
    var node = UltraWebTree_GetNodeById(tree.getNodes(), nodeId);

    if (node != null) node.scrollIntoView();
}

// Get a node from an UltraWebTree by node id
function UltraWebTree_GetNodeById(nodes, nodeId)
{
    for (var i = 0, len = nodes.length; i < len; i++)
    {
		var node = nodes[i];
		if (node.getTag() == nodeId) return node;

		if (node.hasChildren())
		{
		    var childNodes = node.getChildNodes();
		    return UltraWebTree_GetNodeById(childNodes, nodeId);
		}
	}
}

