///////////////////////////////////////////////////////////////////////////////////////////////
// Doc-O-Matic(R) 10 script file.
// Copyright (C) 2000-2019 by toolsfactory software inc.
// http://www.doc-o-matic.com
//
// Distribution permitted as part of browser-based
// Help systems generated by Doc-O-Matic(R).
///////////////////////////////////////////////////////////////////////////////////////////////


///////////////////////////////////////////////////////////////////////////////////////////////
// Available variables which are resolved when Doc-O-Matic use the file:
//
//    HEADER_FILE, TOCIDX_FILE, DEFAULT_TITLE_FILE, DEFAULT_TOPIC_FILE
//
//    SCRIPT_FILE, SCRIPT_FUNCTION_ONLOAD
//    STYLESHEET_FILE
//
//    WINDOW_NAME_HEADER, WINDOW_NAME_TOPIC, WINDOW_NAME_NAVIGATION
//    WINDOW_NAME_ADDINFO, WINDOW_NAME_HIERARCHY, WINDOW_NAME_SEEALSO,
//    WINDOW_NAME_LEGEND, WINDOW_NAME_BODYSOURCE, WINDOW_NAME_TOCIDX
//
//    TOC_IMAGE_PLUS, TOC_IMAGE_MINUS, SECTION_IMAGE_PLUS, SECTION_IMAGE_MINUS,
//    COLLAPSE_COOKIE_NAME, COLLAPSE_PERSISTENTSTORE_NAME,
//    COLLAPSE_STATESAVE_USECOOKIES, COLLAPSE_STATESAVE_USEPERSISTENCE
//
//    TOC_GROUP_CLASSNAME, TOC_TOPIC_CLASSNAME
//    TOC_HIGHLIGHT_GROUP_CLASSNAME, TOC_HIGHLIGHT_TOPIC_CLASSNAME
//
//    TABBEDSECTION_COOKIE_NAME, TABBEDSECTION_ELEMENT_CLASSNAMES
//
///////////////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////////////////
// retrieves a variable from the search string
function getStringVar(varname) {
    var searchstr = document.location.search;
    var varidx = searchstr.indexOf(varname);

    if(varidx >= 0) {
        var startpos = varidx + varname.length +1;
        searchstr = searchstr.substring(startpos, searchstr.length);

        var nextpos = searchstr.length;
        if (searchstr.indexOf('&') >= 0) {
            nextpos = searchstr.indexOf('&');
        }

        searchstr = searchstr.substring(0, nextpos);
    } else {
        searchstr = '';
    }

    return unescape(searchstr);
}

///////////////////////////////////////////////////////////////////////////////////////////////
// searches the entire frameset and returns
// the frame with name frmname
function findFrame(w, frmname) {
    var res = null;

    if (frmname != '') {
        res = w.frames[frmname];

        // if it's not in the current window
        // search the sub-frames
        if (res == null) {
            var L = w.frames.length;
            var i;

            for (i = 0; i < L; i++) {
                res = findFrame(w.frames[i], frmname);
                if (res != null) {
                    break;
                }
            }
        }
    } else {
        result = this;
    }

    return res;
}

///////////////////////////////////////////////////////////////////////////////////////////////
// loads frame frmname with frmfile
function fillFrame(frmname, frmfile) {
    var theframe = findFrame(top, frmname);

    if (theframe != null) {
        theframe.location.replace(frmfile);
    }
    return true;
}

///////////////////////////////////////////////////////////////////////////////////////////////
// Called when the frameset file is loaded.
// Loads the framefile passed on the
// search string into the frame also passed
// on the search string
function loadTopicFrame() {
    var frmname = getStringVar('frmname');
    var frmfile = getStringVar('frmfile');

    if ((frmname != '') && (frmfile != '')) {
        fillFrame(frmname, frmfile);
    }
    
    return true;
}


var called = false;

///////////////////////////////////////////////////////////////////////////////////////////////
// ensures the current file is displayed within
// a frameset, if not loads the frame set which
// loads the file itself into the frameset.
function loadFrameSetOrTitle(framesetfile, targetframe, topicfile)
{
    if (!called) {
        called = true;
        if (self == top) {
            top.location.replace(framesetfile + '?frmname=' + escape(targetframe) + '&frmfile=' + escape(topicfile));
        }
    }

    return true;
}

function pathFromResource(path)
{
    var result = "";
    var a = path.split("/");
    var i;
    // reassemble but leave the last part out
    for (i = 0; i < (a.length-1); i++) {
        result = result + a[i] + "/";
    }
    return result;
}

function setNewImageSource(img, filename)
{
    var newsrc;
    var a = filename.split("/");
    if (a.length <= 1) {
        newsrc = pathFromResource(img.src) + filename;
    } else {
        newsrc = filename;
    }

    img.src = newsrc;
}


function addClassToElement(element, classname)
{
    element.className += (" " + classname);
}

function removeClassFromElement(element, classname)
{
    var re = new RegExp("(?:^|\\s)" + classname + "(?!\\S)","g");
    element.className = element.className.replace(re, '');
}

function hasClassName(element, classname)
{
    var re = new RegExp("(?:^|\\s)" + classname + "(?!\\S)","g");
    return element.className.match(re);
}

///////////////////////////////////////////////////////////////////////////////////////////////
// shows or hides a DIV based on whether
// it's visible or not. Also toggles the corresponding
// expand/collaps graphic.

function setElementDisplayed(element, displayed) {
    if (element == null)
        return;
        
    if (displayed) {
        element.style.display = '';
    } else {
        element.style.display = 'none';
    }
}

function internalToggleVisibilityEx2(theDocument, storeID, storeVisibilityState, forceHide, forceShow)
{
    var divID = "div" + storeID;
    var imgID_expanded = "imge" + storeID;
    var imgID_collapsed = "imgc" + storeID;

    var div = theDocument.getElementById(divID);
    var img_expanded = theDocument.getElementById(imgID_expanded);
    var img_collapsed = theDocument.getElementById(imgID_collapsed);
    
/* Debugging
    alert("toggling image '" + imgID + "' (" + img + ")\ndiv '" + divID + "' (" + div + ")");
*/
    if (div != null) {
        var isDisplayed = false;
        var setState = false;
    
        // Unfold the branch if it isn't visible
        if (((!forceHide) || forceShow) && (div.style.display == 'none')) {
            isDisplayed = true;
            setState = true;
        // Collapse the branch if it IS visible
        } else if (!forceShow) {
            isDisplayed = false;
            setState = true;
        }

        if (setState) {
            setElementDisplayed(div, isDisplayed);
            setElementDisplayed(img_expanded, isDisplayed);
            setElementDisplayed(img_collapsed, !isDisplayed);

            // store the state so we can recreate it
            if (storeVisibilityState) {
                saveVisibilityState(storeID, isDisplayed);
            }
        }
    }
}

function internalToggleVisibilityEx(storeID, storeVisibilityState, forceHide, forceShow)
{
    internalToggleVisibilityEx2(document, storeID, storeVisibilityState, forceHide, forceShow);
}


function setSectionVisibility(storeID, show)
{
    internalToggleVisibilityEx(storeID, true, !show, show);
}

function toggleVisibility(storeID, stored)
{
    if ((storeID != null) && (storeID.length) && (typeof(storeID) == "string")) {
        internalToggleVisibilityEx(storeID, stored, false, false);
    }
}

function isCorrespondingTOCItem(href, topicfile)
{
    var result = false;
    var pathidx = href.lastIndexOf("/");
    var filename = "";

    if (pathidx >= 0) {
        filename = href.substring(pathidx+1, href.length);

        if (filename == topicfile) {
            result = true;
        }
    }

    return result;
}

function expandTOC(framedoc, element)
{
    var baseid = "";
    var outerdiv = null;
    var pelement = element.parentNode;

    while (pelement != null) {
        if ((pelement.tagName == "DIV") && (pelement.id.substring(0, 3) == "div")) {
            baseid = pelement.id.substring(3, pelement.id.length);
            outerdiv = pelement;
            break;
        }

        pelement = pelement.parentNode;
    }

    if ((baseid != "") && (outerdiv != null)) {
        // expand the div if necessary
        internalToggleVisibilityEx2(framedoc, baseid, false, false, true);

        // expand outer divs
        expandTOC(framedoc, outerdiv);
    }

    return true;
}

// ensures element is scrolled into view
// so it's visible on the page.
function ensureTOCEntryVisible(framedoc, element)
{
    var pos = 0;
    var scrollelement;
    var id = "areascroll";

    // first see if we have a scroll area div
    scrollelement = framedoc.getElementById(id);

    if (scrollelement == null) {
        scrollelement = framedoc.body;
    }

    if (scrollelement != null) {
        var delta = 0;

        var viewtop = scrollelement.scrollTop + scrollelement.offsetTop;
        var viewbottom = viewtop + scrollelement.offsetHeight;
        var scrollbarheight = 30;
        // the bottom-scrollbar's area is included in offsetHeight, so we have
        // to subtract a appropriate amount to account for that
        if (viewbottom > (scrollbarheight * 2)) {
            viewbottom = viewbottom - scrollbarheight;
        }
        
        var elementtop = element.offsetTop;
        if (navigator.family == 'ie4') {
            elementtop = elementtop + scrollelement.offsetTop;
        }
        var elementbottom = elementtop + element.offsetHeight;

        if (elementtop < viewtop) {
            delta = (elementtop - viewtop);
        } else if (elementbottom > viewbottom) {
            delta = (elementbottom-viewbottom);
        }

        if (delta != 0) {
            scrollelement.scrollTop = scrollelement.scrollTop + delta;
        }
    }
}

var currentTOCHighlightEntry = null;
var currentTOCHighlightEntryClass = "";

// hightlights the TOC entry that has been scrolled
// into view.
function highlightTOCEntry(framedoc, element)
{
    if (framedoc.currentTOCHighlightEntry != null) {
        framedoc.currentTOCHighlightEntry.className = framedoc.currentTOCHighlightEntryClass;

        framedoc.currentTOCHighlightEntry = null;
        framedoc.currentTOCHighlightEntryClass = "";
    }

    if (element != null) {
        var newclassname = "";

        if (element.className == "ContentGroup") {
            newclassname = "ContentGroup_highlight";
        } else if (element.className == "ContentTopic") {
            newclassname = "ContentTopic_highlight";
        }

        if (newclassname != "") {
            framedoc.currentTOCHighlightEntry = element;
            framedoc.currentTOCHighlightEntryClass = element.className;

            element.className = newclassname;

            var pelement = element.parentNode;

            if (pelement.tagName == "DIV") {
                pelement.className += " DynamicContentItem_selected";
            }
        }
    }
}

// searches for a link to topicfile in the TOC and
// highlights the corresponding node in the tree.
function doSynchTOCInFrame(topicfile, frm)
{
    var result = null;
    
    var links = null;
    var idx;
    var toctreeid = "toctree";
    var treeroot;

    treeroot = frm.document.getElementById(toctreeid);

    if (treeroot != null) {
        links = treeroot.getElementsByTagName("a");

        for (idx=0; idx < links.length; idx++) {
            if (isCorrespondingTOCItem(links[idx].href, topicfile)) {
                expandTOC(frm.document, links[idx]);
                ensureTOCEntryVisible(frm.document, links[idx]);
                highlightTOCEntry(frm.document, links[idx]);
                result = links[idx];
                break;
            }
        }
    }

    return result;
}

function doSynchTOC(topicfile)
{
    var result = null;

    var frm = findFrame(top, "");

    if (frm != null) {
       result = doSynchTOCInFrame(topicfile, frm);
    }
    
    return result;
}

// Initiates the TOC synchronization. If the
// TOC or index file is being loaded this
// functions finds the name of the topic file 
// currently displayed and synchronizes the
// TOC with that topic.
function synchTOC(topicfile)
{
    var frm = findFrame(top, "");
    if (frm != null) {
        // if we're loading the TOC or index file
        // then frm.document == document
        if (document.location == frm.document.location) {
            var topicfrm = findFrame(top, "");
            if (topicfrm != null) {
                var href = topicfrm.document.location.href;
                var pathidx = href.lastIndexOf("/");

                if (pathidx >= 0) {
                    topicfile = href.substring(pathidx+1, href.length);
                }
            }
        }
    }

    // now do the synchronization
    doSynchTOC(topicfile);
}


///////////////////////////////////////////////////////////////////////////////////////////////
// Copies the content of the element identified by ID
// to the clipboard. Works with Internet Explorer only.
function CopyElementToClipboard(ID)
{
    var element = document.getElementById(ID);

    if (element != null) {
        window.clipboardData.setData("Text", element.innerText);
    }
}

///////////////////////////////////////////////////////////////////////////////////////////////
// Expand/Collapse storage functions

var collapseExpandStoreName = "DOM_collapseExpand";
var tabSelectionStoreName = "DOM_tabSelection";
var filteredCategoriesStoreName = "DOM_filteredCategories";

// If we create browser based HTML files, this variable will be true
var useLocalStorage = true;

// If we create HTML Help or Help 2, this variable will be true
var usePersistence = false;

var tabbedSectionElementClassNames = ["SectionTabs_FirstTab_selected", "SectionTabs_FirstTab_unselected", "SectionTabs_MiddleTabs_selected", "SectionTabs_MiddleTabs_unselected", "SectionTabs_LastTab_selected", "SectionTabs_LastTab_unselected"];

///////////////////////////////////////////////////////////////////////////////////////////////
// Cookie helper functions
// from http://www.quirksmode.org/js/cookies.html

function createCookie(name,value,days)
{
    var expires = "";

    if (days) {
        var date = new Date();
        date.setTime(date.getTime()+(days*24*60*60*1000));
        expires = "; expires="+date.toGMTString();
    }

//    document.cookie = name+"="+value+expires+"; path=/";
    document.cookie = name+"="+escape(value)+expires;
}

function readCookie(name)
{
    var nameEQ = name + "=";
    var ca = document.cookie.split(';');
    for(var i=0;i < ca.length;i++) {
        var c = ca[i];
        while (c.charAt(0)==' ') c = c.substring(1,c.length);
        if (c.indexOf(nameEQ) == 0) return unescape(c.substring(nameEQ.length,c.length));
    }
    return null;
}

function eraseCookie(name)
{
    createCookie(name, "", 0);
}

///////////////////////////////////////////////////////////////////////////////////////////////
// Persistence functions for use in HTML Help and Help 2

// This variable temporarily holds the collapsed section
// ids until the get stored using persistence.
var persistentCollapsedIDs = "";

// Saves the persistent data from our temporary
// variable which holds the value to the persistent
// storage.
function savePersistentData()
{
    var id = "persistenceDiv";
    var pdiv = document.getElementById(id);
    if (pdiv != null) {
        try {
            pdiv.setAttribute("collapsedIDs", persistentCollapsedIDs);
            pdiv.save(collapseExpandStoreName);
        } catch (e) {
            // HTML Help may trigger an exception
        }
    }
    return;
}

// Loads the persistent data from the persistent
// storage into our temporary variable which holds
// the value for further use.
function loadPersistentData()
{
    persistentCollapsedIDs = "";

    var id = "persistenceDiv";
    var pdiv = document.getElementById(id);
    if (pdiv != null) {
        try {
            pdiv.load(collapseExpandStoreName);
            var data = pdiv.getAttribute("collapsedIDs");
            if (data != null) {
                persistentCollapsedIDs = data;
            }
        }
        catch (e) {
            // HTML Help may trigger an exception
        }
    }
    return;
}

// Removes the persistent data from the storage.
function removePersistenceData()
{
    var id = "persistenceDiv";
    var pdiv = document.getElementById(id);
    if (pdiv != null) {
        try {
            pdiv.removeAttribute("collapsedIDs");
            pdiv.save(collapseExpandStoreName);
        }
        catch (e) {
            // HTML Help may trigger an exception
        }
    }
    return;
}

// Saves the persistent data to our temporary variable that
// acts as storage while the page is being displayed.
function savePersistentKey(key, value)
{
    persistentCollapsedIDs = value;
    return;
}

// Returns the content in our temporary variable that
// acts as storage while the page is being displayed.
function loadPersistentKey(key)
{
    return persistentCollapsedIDs;
}

// Clears our temporary variable and erases
// the value from the persistent storage.
function removePersitentKey(key)
{
    persistentCollapsedIDs = "";
    removePersistenceData();
    return;
}

///////////////////////////////////////////////////////////////////////////////////////////////
// General storage functions, use appropriate storage mechanisms

//var localStorageTested = false;
var localStorageTested = true;
var localStorageTestSucceeded = false; 

function supportsHTML5LocalStorage(varname) {

    if (!localStorageTested) {    
        localStorageTested = true;
        try {
            var d = (typeof(Storage) !== "undefined") && 
                     ("localStorage" in window) && 
                     (window["localStorage"] !== null);
            
            if (d) {
                // try reading the value, if an exception is raised, we know it doesn't work
                // IE will not tell us the unavailablility any other way 
                var t = localStorage.getItem(varname);
                
                localStorageTestSucceeded = true;
            }
        } catch (e) {
        }
    }

    return localStorageTestSucceeded;
}

// Saves the ID list in ids either using
// local storage, cookies or persistent storage,
// depending on what we use right now.
function saveVariable(varname, value)
{
    if (useLocalStorage) {
        if (supportsHTML5LocalStorage(varname)) {
            localStorage.setItem(varname, value);
        } else {
            createCookie(varname, value, 14);  // we store the cookie for 14 days
        }
    } else if (usePersistence) {
        savePersistentKey(varname, value);
        savePersistentData();
    }

    return;
}

// Loads the collapsed ID list either from
// local storage, cookies or persistent storage,
// depending on what we use right now.
function loadVariable(varname)
{
    var data = "";
    if (useLocalStorage) {
        if (supportsHTML5LocalStorage(varname)) {
            data = localStorage.getItem(varname);
        } else {
            data = readCookie(varname);
        }
    } else if (usePersistence) {
        data = loadPersistentKey(varname);
    }

    return data;
}

function saveVariableChecked(varname, value) {
    saveVariable(varname, value);
/* Debugging
    var readval = loadVariable(varname);
    if (readval != value) {
        alert("Save of variable '" + varname + "' FAILED\nSaved: '" + value + "'\nLoaded: '" + readval + "'");
    }
     else {
        alert("Save of variable '" + varname + "' WORKED\nSaved: '" + value + "'\nLoaded: '" + readval + "'");
    }
*/
}

// Removes the collapsed ID list either from
// local storage, cookies or persistent storage,
// depending on what we use right now.
function eraseVariable(varname)
{
    if (useLocalStorage) {
        if (supportsHTML5LocalStorage(varname)) {
            localStorage.removeItem(varname);
        } else {
            eraseCookie(varname);
        }
    } else if (usePersistence) {
        removePersitentKey(varname);
    }

    return;
}

//////////////////////////////////////////////////////////////////////////////////////////////

// Adds an ID to a list of IDs
function doAddId(res, addId)
{
    var result = res;

    if (result != "") {
        result = result + ",";
    }

    result = result + addId;

    return result;
}

// Converts the stored id into a div and
// img Id an calls the showing function
function doShowHideCollapsedId(storeID, visible)
{
    internalToggleVisibilityEx(storeID, false, !visible, visible);
}

// Goes through the list of Ids passed in ids and
// either adds a new ID, removes an ID, collapses
// or expands the elements in the list.
// Returns:
//   The new list of IDs.
// Parameters:
//   ids -        a string with the list of IDs, separated
//                by commas, ("ID1,ID2,ID3").
//   addId -      an ID to be added to the list.
//   removeId -   an ID to be removed from the list.
//   collapsIds - a boolean that indicates if the elements
//                in the list shall be collapsed.
//   expandIds -  a boolean that indicates if the elements
//                in the list shall be expanded.
function processCollapsedIds(ids, addId, removeId, collapsIds, expandIds)
{
    var result = "";
    var idlist = ids;

    while (idlist.length > 0) {
        var id = "";
        var idx = idlist.indexOf(',');

        if (idx >= 0) {
            id = idlist.substring(0, idx);
            idlist = idlist.substring(idx+1);
        } else {
            id = idlist;
            idlist = "";
        }

        if (collapsIds) {
            doShowHideCollapsedId(id, false);
        }

        if (expandIds) {
            doShowHideCollapsedId(id, true);
        }

        // check if add Id is
        // already in the list
        // so we don't add it twice
        if (addId.length > 0) {
            if (id == addId) {
                addId = "";
            }
        }

        // if the Id doesn't match
        // removeId, we preserve it.
        if (removeId.length > 0) {
            if (id == removeId) {
                id = "";
            }
        }

        if (id.length > 0) {
            result = doAddId(result, id);
        }
    }

    // if addId was not removed
    // we add it.
    if (addId != "") {
        result = doAddId(result, addId);
    }

    return result;
}

// Reads the current collapse list and adds or
// removes an ID to/from it.
function modifyCollapseState(addid, removeid)
{
    var ids = loadVariable(collapseExpandStoreName);

    if (ids == null) {
        ids = "";
    }

    ids = processCollapsedIds(ids, addid, removeid, false, false);

    if (ids != "") {
        saveVariableChecked(collapseExpandStoreName, ids);
    } else {
        eraseVariable(collapseExpandStoreName);
    }
}

// Depending on visibility, removes or adds
// an ID to the collaps list.
function saveVisibilityState(id, visible)
{
    if (visible) {
        modifyCollapseState("", id);
    } else {
        modifyCollapseState(id, "");
    }
}

// Restores the collaps states of all
// stored elements.
function loadCollapseStates()
{
    var ids = loadVariable(collapseExpandStoreName);

    if (ids != null) {
        processCollapsedIds(ids, "", "", true, false);
    }
    
/* Debugging
    alert("Loaded '" + collapseExpandStoreName + "'\nValue: '" + ids + "'");
*/    
}


///////////////////////////////////////////////////////////////////////////////////////////////
// Dynamic Index Display
          
          
var theIndex = null;
var indexOptions = {
        "caseSensitive": false,
        "wholeWords": false
     };

function trimString(text)
{
  text = text.replace( /^\s+/g, "" );// strip leading
  text = text.replace( /\s+$/g, "" );// strip trailing
  return text;
}

// returns a regular expression for string matching
function IndexPrepareSearchExpression(text)
{
  var result = null;
  
  var searchText = trimString(text); 
  
  if (searchText.length) {           
    // make sure the text doesn't contain regular expressions
    searchText = searchText.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
    
    var expr = '';
    if (indexOptions.wholeWords) {
      expr = ".*\\b" + searchText + "\\b.*";
    } else {
      expr = ".*" + searchText + ".*";
    }
      
    var modifiers = "";
    if (!indexOptions.caseSensitive) {
      modifiers += "i";
    }

    result = new RegExp(expr, modifiers);
  }
  
  return result;
}

function IndexMatchesEntry(entry, regExpression)
{
  var result = false;
  
  var mainIdx = -1;
  var subIdx = -1;
    
  mainIdx = 3;
  subIdx = 4;
  
  result = regExpression.test(entry[mainIdx]);
  
  if (!result) {
    result = regExpression.test(entry[subIdx]); 
  }
    
  return result;
}

function GetQuote()
{
    return unescape("%22");
}

function IndexEscapeHTML(txt)
{ 
    return txt.replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/'/g, "&#039;");
}

function IndexPrintEntry(text, url, divclass)
{
    var result = "";
    var target = "";

    result = "<div class=" + GetQuote() + divclass + GetQuote() + ">";

    if (url.length > 0) {
        if (target.length > 0) {
            result = result + "<a href=" + GetQuote() + url + GetQuote() + " target=" + GetQuote() + target + GetQuote() + ">";
        } else {
            result = result + "<a href=" + GetQuote() + url + GetQuote() + ">";
        }
    }

    result = result + IndexEscapeHTML(text);

    if (url.length > 0) {
        result = result + "</a>";
    }

    result = result + "</div>";

    return result;
}

function IndexGetEntry(lastentry, entry, classmain, classsub)
{
    var result = "";

    var printmainentry = true;
    var printsubentry = false;
    var urlmainentry = "";
    var urlsubentry = "";

    if (entry[1].length > 0) {
        printsubentry = true;

        if (lastentry != null) {
            if (lastentry[0] == entry[0]) {
                printmainentry = false;
            }
        }
    }

    if ((printmainentry) && (!printsubentry)) {
        urlmainentry = entry[2];
    }

    if (printsubentry) {
        urlsubentry = entry[2];
    }

    if (printmainentry) {
        result = result + IndexPrintEntry(entry[3], urlmainentry, classmain);
    }
    if (printsubentry) {
        result = result + IndexPrintEntry(entry[4], urlsubentry, classsub);
    }

    return result;
}

var searchTimer = null;
var currentSearchText = "";
var searchDynamicDivID = "";
var searchResultDivID = "";
var searchClassMainEntry = "";
var searchClassSubEntry = "";

function IndexClearSearchTimer()
{
    if (searchTimer != null) {
       clearTimeout(searchTimer);
       searchTimer = null;
    }

    return true;
}

function IndexUnescape()
{
    var entry, k, i;
    for(k = 0; k < theIndex.length; k++) {
        entry = theIndex[k];

        for(i = 0; i < entry.length; i++) {
            entry[i] = unescape(entry[i]);
        }
    }
}

function IndexRestoreOptionForId(aid, defaultValue)
{
    var result = defaultValue;

    var checkbox = document.getElementById(aid);
    
    if (checkbox != null) {
        var storedValue = loadVariable(aid);

        if ((storedValue != null) && (storedValue != "")) {
            result = (storedValue == "true");
        }
         checkbox.checked = result; 
    }
    
    return result;
}

function IndexRestoreOptions()
{
    indexOptions.caseSensitive = IndexRestoreOptionForId("indexSearchOptionCaseSensitiveCheckbox", indexOptions.caseSensitive);
    indexOptions.wholeWords = IndexRestoreOptionForId("indexSearchOptionWholeWordsCheckbox", indexOptions.wholeWords);
}

function IndexSetOption(checkbox)
{
    var cbId = checkbox.id;
    var cbVal = checkbox.checked;
    saveVariable(cbId, cbVal.toString());

    if (cbId == "indexSearchOptionCaseSensitiveCheckbox") {
        indexOptions.caseSensitive = cbVal;
    }
    if (cbId == "indexSearchOptionWholeWordsCheckbox") {
        indexOptions.wholeWords = cbVal;
    }
}

function DoIndexSearch()
{
    var dynamicdiv, resultdiv;
    var entry, lastentry, cnt, k;
    var outputHTML = "";

    IndexClearSearchTimer();

    dynamicdiv = document.getElementById(searchDynamicDivID);
    resultdiv = document.getElementById(searchResultDivID);

    if ((dynamicdiv != null) && (resultdiv != null)) {
        cnt = 0;
        var regExp = IndexPrepareSearchExpression(currentSearchText);

        if (regExp != null) {
            lastentry = null;

            for(k = 0; k < theIndex.length; k++) {
                entry = theIndex[k];
                
                if (IndexMatchesEntry(entry, regExp)) {
                    outputHTML = outputHTML + IndexGetEntry(lastentry, entry, searchClassMainEntry, searchClassSubEntry);

                    lastentry = entry;
                    cnt++;
                }
            }
        }

        if (cnt > 0) {
            resultdiv.innerHTML = outputHTML;
            dynamicdiv.style.display = '';
        } else {
            dynamicdiv.style.display = 'none';
        }
    }

    return true;
}

// instant index search invoked by pressing the search button
function IndexSearchKeyword(text, delayed, dynamicdivid, resultdivid, classmain, classsub, forceSearch)
{
    if (forceSearch || (text != currentSearchText)) {
        IndexClearSearchTimer();

        currentSearchText = text;
        searchDynamicDivID = dynamicdivid;
        searchResultDivID = resultdivid;
        searchClassMainEntry = classmain;
        searchClassSubEntry = classsub;

        if (!delayed) {
            DoIndexSearch();
        } else {
            searchTimer = setTimeout("DoIndexSearch();", 500);
        }
    }
    
    return true;
}

///////////////////////////////////////////////////////////////////////////////////////////////
// event handlers


// Opens the big version of an image in a secondary window
function openBigImage(image)
{
    window.open(image, "_blank", "toolbar=no,status=no,menubar=no,resizable=yes");
    return true;
}

function openExternalLink(href)
{
    window.open(href, "_blank", "");
    return true;
}

function switchImage(img, src)
{
    setNewImageSource(img, src);
    return true;
}

// opens a mail window and fills the
// address, subject and body
function sendFeedback(mailto, subject, body)
{
    var href = "mailto:" + mailto + "?subject=" + subject + "&body=" + body;
    window.open(href, "_top");
}


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// tabbed section

function addTabbedSectionId(tabidlist, tabsetid)
{
    if (tabidlist == null) {
        return tabsetid;
    } else {
        var result = tabidlist;
        var addId = true;
        var tabsetids = tabidlist.split(",");
        for(var i=0; i < tabsetids.length; i++) {
            var ts = tabsetids[i];

            if (ts == tabsetid) {
                addId = false;
                break;
            }
        }
        if (addId) {
            if (result = "")
                result = tabsetid;
            else
                result = tabsetid + "," + result;
        }

        return result;
    }
}

function storeTabbedSectionState(tabsetid, selectedIdx)
{
    var tabsetids = loadVariable(tabSelectionStoreName);

    tabsetids = addTabbedSectionId(tabsetids, tabsetid);
    saveVariable(tabSelectionStoreName, tabsetids);
    
    var varName = tabSelectionStoreName + tabsetid;
    var idx = selectedIdx + "";
    saveVariable(varName, idx);
}

function restoreTabbedSectionState(tabsetid)
{
    var varName = tabSelectionStoreName + tabsetid;
    var selectedTab = loadVariable(varName);
    
    if ((selectedTab != null) && (selectedTab != "")) {
        var idx = parseInt(selectedTab, 10);

        doSwitchTabs(tabsetid, idx, -1, false);
    }
}

function restoreTabbedSectionStates()
{
    var tabidlist = loadVariable(tabSelectionStoreName);
    
    if ((tabidlist != null) && (tabidlist != "")) {
        var ids = tabidlist.split(",");
        for(var i=0; i < ids.length; i++) {
            restoreTabbedSectionState(ids[i]);
        }
    }
}

function setTabSelectionState(tabSetId, index, maxIdx, selected)
{
    var result = false;

    var tabid = "tab" + tabSetId + "_" + index;
    var divid = "div" + tabSetId + "_" + index;

    var tab = document.getElementById(tabid);
    var div = document.getElementById(divid);

    if ((tab != null) && (div != null)) {
        var elementIdx = 0;
        if (index > 0) {
            if (index == maxIdx) {
                elementIdx = 4;
            } else {
                elementIdx = 2;
            }
        }

        if (selected) {
            tab.className = tabbedSectionElementClassNames[elementIdx];
            div.style.display = "";
        } else {
            tab.className = tabbedSectionElementClassNames[elementIdx+1];
            div.style.display = "none";
        }

        result = true;
    }

    return result;
}

function doSwitchTabs(tabSetId, selectedIndex, tabCount, storeState)
{
    var foundSelected = false;
    var maxIdx = tabCount-1;
    var realMaxIdx = -1;
    var i = 0;
    while ((i <= maxIdx) || (maxIdx < 0)) {
        if (setTabSelectionState(tabSetId, i, maxIdx, (i == selectedIndex))) {
            realMaxIdx = i;
            if (i == selectedIndex) {
                foundSelected = true;
            }

            i++;
        } else {
            break;
        }
    }

    if (realMaxIdx > -1) {
        // if we didn't find the selected
        // tab (can happend when restoring)
        // we select the first
        if (!foundSelected) {
            setTabSelectionState(tabSetId, 0, maxIdx, true);
        }
        // When we're restoring redo the last tab so it gets the
        // correct class applied.
        if (maxIdx < 0) {
            setTabSelectionState(tabSetId, realMaxIdx, realMaxIdx, selectedIndex == realMaxIdx);
        }
    }

    if (storeState) {
        storeTabbedSectionState(tabSetId, selectedIndex);
    }
}

function switchTabs(tabSetId, selectedIndex, tabCount)
{
    doSwitchTabs(tabSetId, selectedIndex, tabCount, true);
}

