var adminMode = false;          // admin mode

var errorList = new Array()     // errorList

var database = new Array();     // the actual database
var workDB = new Array();       // the working database
var sequenceDB = new Array();   // the sequencial stories database
var writerDB = new Array();

var showFrom = 0;               // the first image to show
var perPage = 30;               // the number of images to show
var navigationCutOff = 4        // cutoff for page navigation
var displayMode = 1;            // display mode (1=gallery,2=list)
var hasCookie=false;            // user has a cookie set
var windowMode = 2;             // open story in (1=current window, 2=new window, 3=iframe)

var columnNames = new Array();  // names of the columns
var cdbi;                       // sorted column
var sortAscending = false;      // how is the current cdbi sorted

var substr=false;               // substractictive filtering
var consec = false;             // consecutive filtering

var openedTab=null;             // direct acces to the currently opened tab
var openedTabContent=null;      // direct acces to the content of the currently opened tab

var historyId=0;                // id of page in history

var lastFilterCol = -1;            // last filtered column
var lastFilterTerm = -1;

var searchTerms = new Array();
searchTerms[0] = null;
searchTerms[1] = null;
searchTerms[2] = null;
searchTerms[3] = null;
searchTerms[0] = new Array();   // columns to search in 
searchTerms[1] = new Array();   // exact search
searchTerms[2] = new Array();   // substractive search
searchTerms[3] = new Array();   // terms to search for

var storyLocation = 'http://doc.tf-media.net/Stories/';
var imageLocation = 'http://doc.tf-media.net/Art/';
var imageColumn;






/**
 * Do all the necessary stuff to display
 * the needed content
 **/
function finalize() {
    loadStoryDatabase();

    cdbi = dateIndex;

    showAuthorList();
    showSpeciesList();

    populateDatabase();

    getParamTable();
    parseParameters();

    getCookie();

    document.getElementById('perPage').value=perPage;
    document.getElementById('listStyle').value=displayMode;
    document.getElementById('windowMode').value=windowMode;
    document.getElementById('tabBar').style.display="block";
    document.getElementById('formContainer').style.display="block";

    showList();
    initializeRSH();
    generateRSH();
}


/**
 * link all elements in the work database to the full database
 **/
function populateDatabase() {
    workDB = new Array();
    var i = 0;
    var storyCount = database.length;
    while (i < storyCount) {
        workDB[i] = database[i];
        i++;
    }
}


/**
 * sets perpage with sanity check
 **/
function setPerPage(i) {
    if (i > 0)
        perPage = i;
    else
        errorList[errorList.length] = 'At least one story must be shown per page'
}


/**
 * sets navigation cutoff with sanity check
 **/
function setNavigationCutOff(i) {
    if (i > 0)
        navigationCutOff = i;
    else
        errorList[errorList.length] = 'The navigation cutoff can not be 0 or negative'
}


/**
 * sets display mode with sanity check
 **/
function setDisplayMode(i) {
    if (i == 1 || i == 2)
        displayMode = i;
    else
        errorList[errorList.length] = 'The chosen display mode does not exsist'
}


/**
 * sets window mode with sanity check
 **/
function setWindowMode(i) {
    if (i == 1 || i == 2 || i == 3)
        windowMode = i;
    else
        errorList[errorList.length] = 'The chosen method for showing stories does not exsist'
}


/**
 * sets showFrom with sanity check
 **/
function setShowFrom(i) {
    if (i < 0 ) i = 0;
    if (i >= workDB.length) i = workDB.length-1;
    showFrom = i;
}


/**
 * show all stories
 **/
function reset() {
    populateDatabase();
    // if not consecutive then clear search history
    if (consec==false) {
        searchTerms[0] = new Array();   // columns to search in 
        searchTerms[1] = new Array();   // exact search
        searchTerms[2] = new Array();   // substractive search
        searchTerms[3] = new Array();   // terms to search for
    }

    showList();
    window.scrollTo(0,findPosY(document.getElementById('storyList'))-50);  
    generateRSH();
}


/**
 * show the story with id [storyId]
 **/
function setStoryById(storyId) {
    var backup = consec;
    consec = false;
    filterTableB('id', storyId, true);
    consec = backup;
}


function getStoryWithId(storyId) {
    var b = 0;
    var e = database.length;
    var found = false;
    while (!found && b<=e) {
        var i = Math.floor((e-b)/2)+b;
        found = (database[i][idIndex]==storyId);
        if (!found) {
            if (database[i][idIndex]>storyId) {
                b=i+1;
            }
            else {
                e=i-1;
            }
        }
    }
    return database[i];
}


/**
 * Sets the array of column names
 **/
function setColumnNames(names) {
    columnNames = names;

    idIndex          = getColumnIndex('id');
    dateIndex        = getColumnIndex('date');
    authorIndex      = getColumnIndex('author');
    titleIndex       = getColumnIndex('title');
    tftypeIndex      = getColumnIndex('tf type');
    tfcategoryIndex  = getColumnIndex('tf category');
    tfedsexIndex     = getColumnIndex('tf\'ed sex');
    degreeoftfIndex  = getColumnIndex('degree of tf');
    sexIndex         = getColumnIndex('sex');
    otherIndex       = getColumnIndex('other');
    urlIndex         = getColumnIndex('url');
    ratingIndex      = getColumnIndex('rating');
    partofIndex      = getColumnIndex('part of');
    descriptionIndex = getColumnIndex('description');
    imageColumn      = getColumnIndex('images');
}


/**
 * Returns the array of column names
 **/
function getColumnNames() {
    return columnNames;
}


/**
 * Returns the index of the column with name [columnName]
 **/
function getColumnIndex(columnName) {
    columnName = columnName.toLowerCase();
    var columns = getColumnNames();
    var length = columns.length - 1;

    var index = -1;
    var found = false;

    while (index < length && found ==false) {
        index++;
        found = (columnName == columns[index].toLowerCase());
    }

    return (found ? index : -1);
}


/**
 * check up on filtering modes in advanced
 * search box
 **/
function changeFilterMode() {
    substr = (document.getElementById("filterMode").selectedIndex==0 ? false : true);

    consec = (document.getElementById("filterType").selectedIndex==0 ? false : true);
}


/**
 * generate the author list and the author list window
 **/
function showAuthorList() {
    var authorList = new Array();
    var t = authorIndex;

    var  l = database.length;
    for (var i = 0 ; i < l ; i++) {
        var d = getAuthorData(database[i][t]);
        
        if (d==null) writerDB[writerDB.length] = [database[i][t],'',''];
    }
    var l = writerDB.length;
    for (var i = 0 ; i < l ; i++) {
        authorList[i] = writerDB[i][0];
    }


    authorList.sort(sortCaseInsensitive);

    var sb = new StringBuilder();
    sb.append('<table><tr>');

    var l = authorList.length;
    var p = Math.floor((l-1) / 5 + 1);


    for (var i = 0 ; i< l ; i++) {
        if (i%p == 0) sb.append('<td><ul>');
        sb.append('<li><span tabindex="10" class="click" onFocus=\'this.className="click hover"\' onBlur=\'this.className="click"\'  onMouseOver=\'this.className="click hover"\' onMouseOut=\'this.className="click"\' onclick=\'filterTable("author","'+ authorList[i].toLowerCase() + '",true);generateRSH();\'  onKeyPress=\'if (isReturn(event)) {filterTable("author","'+ authorList[i].toLowerCase() + '",true);generateRSH(); }\' >' + authorList[i] + '</span></li>');
        if ((i+1) % p == 0 || i == l-1) sb.append('</ul></td>');
    }

    sb.append('</tr></table>');

    document.getElementById("authorList").innerHTML = (sb.toString());
}


/**
 * generate the species list and the species list window
 **/
function showSpeciesList() {
    var sb = new StringBuilder();
    sb.append('<table><tr class="category">');

    var speciesList = new Array();
    var t = tfcategoryIndex;

    var  l = database.length;
    for (var i = 0 ; i < l ; i++) {
        var ll = database[i][t].length;
        for (var j = 0 ; j< ll ; j++) {
            if (! speciesList.inArray(database[i][t][j])) speciesList[speciesList.length] = database[i][t][j];
        }
    }

    speciesList.sort(sortCaseInsensitive);

    var l = speciesList.length;
    var p = Math.floor((l-1) / 5 + 1);

    for (var i = 0 ; i< l ; i++) {
        if (i%p == 0) sb.append('<td><ul>');
        sb.append('<li><span tabindex="8" class="click" onFocus=\'this.className="click hover"\' onBlur=\'this.className="click"\'  onMouseOver=\'this.className="click hover"\' onMouseOut=\'this.className="click"\' onclick=\'filterTable("tf category","'+ speciesList[i].toLowerCase() + '",true);generateRSH();\'  onKeyPress=\'if (isReturn(event)) {filterTable("tf category","'+ speciesList[i].toLowerCase() + '",true);generateRSH(); }\' >' + speciesList[i] + '</span></li>');
        if ((i+1) % p == 0 || i == l-1) sb.append('</ul></td>');
    }

    sb.append('</tr><tr>');

    var speciesList = new Array();
    var t = tftypeIndex;

    var  l = database.length;
    for (var i = 0 ; i < l ; i++) {
        var ll = database[i][t].length;
        for (var j = 0 ; j< ll ; j++) {
            if (! speciesList.inArray(database[i][t][j])) speciesList[speciesList.length] = database[i][t][j];
        }
    }

    speciesList.sort(sortCaseInsensitive);

    var l = speciesList.length;
    var p = Math.floor((l-1) / 5 + 1);

    for (var i = 0 ; i< l ; i++) {
        if (i%p == 0) sb.append('<td><ul>');
        sb.append('<li><span tabindex="8" class="click" onFocus=\'this.className="click hover"\' onBlur=\'this.className="click"\'  onMouseOver=\'this.className="click hover"\' onMouseOut=\'this.className="click"\' onclick=\'filterTable("tf type","'+ speciesList[i].toLowerCase() + '",true);generateRSH();\'  onKeyPress=\'if (isReturn(event)) {filterTable("tf type","'+ speciesList[i].toLowerCase() + '",true);generateRSH(); }\' >' + speciesList[i] + '</span></li>');
        if ((i+1) % p == 0 || i == l-1) sb.append('</ul></td>');
    }

    sb.append('</tr></table>');

    document.getElementById("speciesList").innerHTML = (sb.toString());
}


/**
 * Add a story to the database
 **/
function addStory(data) {
    // set index number
    data[columnNames.length] = database.length;
    database[database.length] = data;
}

function as(data) {
    addStory(data);
}


/**
 * Add a story sequence to the database
 **/
function addSequence(data) {
    ac(data);
}


function ac(data) {
    sequenceDB[sequenceDB.length] = data;
}


/**
 * Add a description to the current story in the database
 **/
function addDesc(desc) {
    database[database.length-1][descriptionIndex] = desc;
}

function ad(desc) {
    addDesc(desc);
}



/**
 * Add related images to the current story in the database
 **/
function addImages(img) {
    database[database.length-1][imageColumn] = img;
}

function ai(img) {
    addImages(img);
}


/**
 * Add writer details to the database
 **/
function addWriter(data) {
    writerDB[writerDB.length] = data;
}

function aw(data) {
    addWriter(data);
}


function getAuthorData(str) {
    var ret = null;
    
    var l = writerDB.length;
    var i = 0;
    while ( i < l && ret==null) {
        if (writerDB[i][0].toLowerCase()==str.toLowerCase()) {
            ret = writerDB[i];
        }
        i++
    }

    return ret;
}


/**
 * returns an item from the database given a row number and a column name
 **/
function getDatabaseItem(rowNumber, columnName) {
    var columnNumber = (getColumnIndex(columnName));
    return database[rowNumber][columnNumber];
}


/**
 * returns the navigation bar string
 **/
function getNavigationBar(l) {
    var sb = new StringBuilder();
    var storyCount = workDB.length;
    var elipsis = false;
    var nc = navigationCutOff*perPage;

    if (l > perPage || l < perPage) {
        var first = 0;

        var next = showFrom + perPage;
        if (next > l) next = showFrom;

        var previous = showFrom - perPage;
        if (previous < 0) previous = 0;

        var last = l - (l%perPage);
        if (last < 0) last = 0;


        sb.append('<div class="nav"><span class="wrapper">');
        sb.append('<span ' + (0==showFrom?'':'class="link" ') + 'onFocus=\'this.className="link hover"\' onBlur=\'this.className="link"\'  onMouseOver=\'this.className="' + (0==showFrom?'':'link hover') + '"\' onMouseOut=\'this.className="' + (0==showFrom?'':'link') + '"\' onclick="showFrom='+first+';showList();generateRSH();" onKeyPress="if (isReturn(event)) {showFrom='+ first + ';showList();generateRSH(); }"' + (0==showFrom?'':'tabindex="13"') + '>&lt;&lt;</span> ');
        sb.append('<span ' + (0==showFrom?'':'class="link" ') + 'onFocus=\'this.className="link hover"\' onBlur=\'this.className="link"\'  onMouseOver=\'this.className="' + (0==showFrom?'':'link hover') + '"\' onMouseOut=\'this.className="' + (0==showFrom?'':'link') + '"\' onclick="showFrom='+previous+';showList();generateRSH();" onKeyPress="if (isReturn(event)) {showFrom='+ previous + ';showList();generateRSH(); }"' + (0==showFrom?'':'tabindex="13"') + '>&lt;</span> ');

        for (i = 0 ; i<l; i+=perPage) {
            if (i< nc || i > last-nc || ( i > showFrom -nc && i <showFrom + nc)) {
                sb.append(getNavigationBarLink(i));
                elipsis = false;
            }
            else {
                if (!elipsis) {
                    sb.append(getNavigationBarElipsis());
                    elipsis = true;
                }
            }
        }

        sb.append('<span ' + (last==showFrom?'':'class="link" ') + 'onFocus=\'this.className="link hover"\' onBlur=\'this.className="link"\'  onMouseOver=\'this.className="' + (last==showFrom?'':'link hover') + '"\' onMouseOut=\'this.className="' + (last==showFrom?'':'link') + '"\' onclick="showFrom='+ next +';showList();generateRSH();" onKeyPress="if (isReturn(event)) {showFrom='+ next + ';showList();generateRSH(); }"' + (last==showFrom?'':'tabindex="13"') + '>&gt;</span> ');
        sb.append('<span ' + (last==showFrom?'':'class="link" ') + 'onFocus=\'this.className="link hover"\' onBlur=\'this.className="link"\'  onMouseOver=\'this.className="' + (last==showFrom?'':'link hover') + '"\' onMouseOut=\'this.className="' + (last==showFrom?'':'link') + '"\' onclick="showFrom='+ last +';showList();generateRSH();" onKeyPress="if (isReturn(event)) {showFrom='+ last + ';showList();generateRSH(); }"' + (last==showFrom?'':'tabindex="13"') + '>&gt;&gt;</span></span>');

        sb.append('<span class="storyCount" id="storyCount">Showing ' + (showFrom+1) + ' to ' + (showFrom + (l<perPage?l:perPage)) + ' of ' + storyCount + (storyCount!=1?' stories':' story') + '</span></div>');
    }

    return sb;
}

function getNavigationBarLink(i) {
    return '<span class="' + (i==showFrom?'current':'link') + '" onFocus=\'this.className="link hover"\' onBlur=\'this.className="link"\'  onMouseOver=\'this.className="' + (i==showFrom?'current':'link hover') + '"\' onMouseOut=\'this.className="' + (i==showFrom?'current':'link') + '"\' onclick="showFrom='+ i + ';showList();generateRSH();" onKeyPress="if (isReturn(event)) {showFrom='+ i + ';showList();generateRSH(); }"' + (i==showFrom?'':' tabindex="13"') + '>' + (i+perPage)/perPage + '</span> ';
}

function getNavigationBarElipsis() {
    return '<span>...</span>';
}

function getButtonBar() {
    var sb = new StringBuilder();
    sb.append('<div class="buttonbar"><span class="button" tabindex="13" onFocus=\'this.className="button hover"\' onBlur=\'this.className="button"\'  onclick="showRandomStory();" onKeyPress=\'if (isReturn(event)) { showRandomStory(); } \'>random story</span></div>');
    return sb;
}


/**
 * returns the sort bar string
 **/
function getSortBar() {
    var sb = new StringBuilder();
    var storyCount = workDB.length;

    if (displayMode==1 || storyCount==1) {
        sb.append('<div class="gallery"><table width="100%"><colgroup><col width="11%"><col width="11%"><col width="11%"><col width="11%"><col width="11%"><col width="11%"><col width="11%"><col width="11%"><col width="12%"></colgroup>');
    }
    else if (displayMode==2) {
        sb.append('<div class="list"><table width="100%"><colgroup><col width="8%"><col width="14%"><col width="20%"><col width="14%"><col width="12%"><col width="10%"><col width="4%"><col width="10%"><col width="8%"></colgroup>');
    }

    if (displayMode==2 || displayMode==1) {
        sb.append('<thead><tr>');
        sb.append('<td tabindex="13" class="' + (dateIndex==cdbi?(sortAscending?'sortDown':'sortUp') :'') + '"       onclick="sortDB(' + dateIndex + ');showList();generateRSH();"       onKeyPress="if (isReturn(event)) {sortDB(' + dateIndex + ');showList();generateRSH(); }">date</td>');
        sb.append('<td tabindex="13" class="' + (authorIndex==cdbi?(sortAscending?'sortDown':'sortUp') :'') + '"     onclick="sortDB(' + authorIndex + ');showList();generateRSH();"     onKeyPress="if (isReturn(event)) {sortDB(' + authorIndex + ');showList();generateRSH(); }">author</td>');
        sb.append('<td tabindex="13" class="' + (titleIndex==cdbi?(sortAscending?'sortDown':'sortUp') :'') + '"      onclick="sortDB(' + titleIndex + ');showList();generateRSH();"      onKeyPress="if (isReturn(event)) {sortDB(' + titleIndex + ');showList();generateRSH(); }">title</td>');
        sb.append('<td tabindex="13" class="' + (tftypeIndex==cdbi?(sortAscending?'sortDown':'sortUp') :'') + '"     onclick="sortDB(' + tftypeIndex + ');showList();generateRSH();"     onKeyPress="if (isReturn(event)) {sortDB(' + tftypeIndex + ');showList();generateRSH(); }">tf type</td>');
        sb.append('<td tabindex="13" class="' + (tfedsexIndex==cdbi?(sortAscending?'sortDown':'sortUp') :'') + '"    onclick="sortDB(' + tfedsexIndex + ');showList();generateRSH();"    onKeyPress="if (isReturn(event)) {sortDB(' + tfedsexIndex + ');showList();generateRSH(); }">tf\' ed sex</td>');
        sb.append('<td tabindex="13" class="' + (degreeoftfIndex==cdbi?(sortAscending?'sortDown':'sortUp') :'') + '" onclick="sortDB(' + degreeoftfIndex + ');showList();generateRSH();" onKeyPress="if (isReturn(event)) {sortDB(' + degreeoftfIndex + ');showList();generateRSH(); }">degree of tf</td>');
        sb.append('<td tabindex="13" class="' + (sexIndex==cdbi?(sortAscending?'sortDown':'sortUp') :'') + '"        onclick="sortDB(' + sexIndex + ');showList();generateRSH();"        onKeyPress="if (isReturn(event)) {sortDB(' + sexIndex + ');showList();generateRSH(); }">sex</td>');
        sb.append('<td tabindex="13" class="' + (otherIndex==cdbi?(sortAscending?'sortDown':'sortUp') :'') + '"      onclick="sortDB(' + otherIndex + ');showList();generateRSH();"      onKeyPress="if (isReturn(event)) {sortDB(' + otherIndex + ');showList();generateRSH(); }">other</td>');
        sb.append('<td tabindex="13" class="' + (ratingIndex==cdbi?(sortAscending?'sortDown':'sortUp') :'') + '"     onclick="sortDB(' + ratingIndex + ');showList();generateRSH();"     onKeyPress="if (isReturn(event)) {sortDB(' + ratingIndex + ');showList();generateRSH(); }">rating</td>');
        sb.append('</tr></thead>');
    }
    
    if (displayMode==1  || storyCount==1 ) {
        sb.append('</table></div>');
    }

    return sb;
}


/**
 * returns the story table string
 **/
function getStoryTable() {
    var storyCount = workDB.length;
    var lastStoryOnThisPage = showFrom + perPage;
    var lastStory = (lastStoryOnThisPage < storyCount ? lastStoryOnThisPage : storyCount);

    var sb = new StringBuilder();
    var i = showFrom;

    if (displayMode == 1 || storyCount==1) {
        while (i < lastStory) {
            var tft = stringArray(workDB[i][tftypeIndex],'tf type' );
            var po = stringArray(workDB[i][partofIndex],'part of' );

            sb.append('<div  class="gallery"><table width="100%"><colgroup><col width="25%"><col width="25%"><col width="25%"><col width="25%"></colgroup><tr><td colspan="3" class="title"><img src="img/story.gif" class="click story" onclick=\'ft("id",' + i + ', true);\'><a tabindex="13" ');
            if (windowMode < 3) {
                sb.append('href="' + storyLocation + workDB[i][urlIndex] + '" ');
                if (windowMode==2) sb.append('target="_blank"');
            }
            else {
                sb.append('onclick="showStory(' + i + ')" onKeyPress="if (isReturn(event)) {showStory(' + i + ') }"')
            }
            sb.append('>' + workDB[i][titleIndex]  +'</a> by <span class="click" onclick=\'ft("author",'+ i + ',true);\'>' + workDB[i][authorIndex] + '</span></td>');
            sb.append('<td class="title"><span class="click date" onclick=\'ft("date",' + i + ',true);\'>' + workDB[i][dateIndex] + '</span></td>');
            sb.append('</tr><tr><td colspan="4" class="desc"><span>' + workDB[i][descriptionIndex] + '</span></td></tr><tr>');
            sb.append('<td colspan="2">TF type: ' + tft + '</td>');
            sb.append('<td>TF\'ed sex: <span class="click" onclick=\'ft("tf%27ed sex",'+ i + ',true);\'>' + workDB[i][tfedsexIndex] + '</span></td>');
            sb.append('<td>Degree of tf: <span class="click" onclick=\'ft("degree of tf",'+ i + ',true);\'>' + workDB[i][degreeoftfIndex] + '</span></td></tr><tr>');
            sb.append('<td>Sex: <span class="click" onclick=\'ft("sex",'+ i + ',true);\'>' + workDB[i][sexIndex] + '</span></td>')
            sb.append('<td>Other: <span class="click" onclick=\'ft("other",'+ i + ',true);\'>' + workDB[i][otherIndex] + '</span></td>');
            sb.append('<td>Part of: ' + po + '</td>');
            sb.append('<td><span class="rate">Rating: <span class="click" onclick=\'ft("rating",'+ i + ',true);\'>' + workDB[i][ratingIndex] + '</span></span><a class="rate" tabindex="13" onclick="rate(' + i + ')" onKeyPress="if (isReturn(event)) {rate(' + i + ') }">Rate it</a></td></tr>');
            sb.append(getSequentialBar(i, partofIndex, idIndex));
            sb.append(getImages(i));
            if (adminMode) {
                sb.append('<tr><td colspan="2"><span class="click" onclick="showEditWindow(' + i + ');">Edit story</span></td><td colspan="2"><span class="click" onclick="remove(' + i + ');">Remove story</span></td></tr>');
            }
            sb.append('<tr class="content"><td colspan="4"  id="content'+i + '"></td></tr></table></div>');
            i++;
        }

    }
    else if (displayMode == 2) {

        while (i < lastStory) {
            var tft = stringArray(workDB[i][tftypeIndex],'tf type' );
            sb.append('<tr' + (i%2==0?'':' class="even"') + '><td onclick=\'ft("date",' + i + ',true);\'><span class="click">' + workDB[i][dateIndex] + '</span></td>');
            sb.append('<td onclick=\'ft("author",' + i + ',true);\'><span class="click">' + workDB[i][authorIndex] + '</span></td><td><img src="img/story.gif" class="click story" onclick=\'ft("id",' + i + ', true);\'><a tabindex="13" ');
            if (windowMode < 3) {
                sb.append('href="' + storyLocation + workDB[i][urlIndex] + '" ');
                if (windowMode==2) sb.append('target="_blank"');
            }
            else {
                sb.append('onclick="showStory(' + i + ')" onKeyPress="if (isReturn(event)) {showStory(' + i + ') }"')
            }
            sb.append('>' + workDB[i][titleIndex] + '</a></td><td onclick=\'ft("tf type",' + i + ',true);\'>' + tft + '</td>');
            sb.append('<td onclick=\'ft("tf%27ed sex",' + i + ',true);\'><span class="click">' + workDB[i][tfedsexIndex] + '</span></td>');
            sb.append('<td onclick=\'ft("degree of tf",' + i + ',true);\'><span class="click">' + workDB[i][degreeoftfIndex] + '</span></td>');
            sb.append('<td onclick=\'ft("sex",' + i + ',true);\'><span class="click">' + workDB[i][sexIndex] + '</span></td>');
            sb.append('<td onclick=\'ft("other",' + i + ',true);\'><span class="click">' + workDB[i][otherIndex] + '</span></td>');
            sb.append('<td onclick=\'ft("rating",' + i + ',true);\'><span class="rate click">' + workDB[i][ratingIndex] + '</span><a class="rate" tabindex="13" onclick="rate(' + i + ')" onKeyPress="if (isReturn(event)) {rate(' + i + ') }">Rate it</a></td></tr>');
            sb.append('<tr class="content"><td colspan="9"  id="content'+i + '"></td></tr>');
            i++;
        }

        sb.append('</table></div>');
    }

    return sb;
}


function getSequentialBar(i,partofIndex,idIndex) {
    var sb = new StringBuilder();
    if (isArray(workDB[i][partofIndex])) {
        for (var j = 0 ; j<workDB[i][partofIndex].length ; j++) {
            var sequenceName = workDB[i][partofIndex][j];
            var sequence = getSequence(sequenceName);
            if (sequence!=null) {
                sb.append('<tr><td colspan="4"><span class="chapterNav"><span class="click" onclick=\'ft("part of",'+ i + ',true);\'>' + sequenceName + '</span>:&nbsp;');
                if (sequence[0]!=workDB[i][idIndex]) {
                    sb.append('<span class="button" tabindex="13" onFocus=\'this.className="button hover"\' onBlur=\'this.className="button"\'  onclick=\'getFirstInSequence("' + sequenceName + '",' + i + ');\' onKeyPress=\'if(isReturn(event)) { getFirstInSequence("' + sequenceName + '",' + i + '); } \'>&lt;&lt;</span>');
                    sb.append('<span class="button" tabindex="13" onFocus=\'this.className="button hover"\' onBlur=\'this.className="button"\'  onclick=\'getPreviousInSequence("' + sequenceName + '",' + i + ');\' onKeyPress=\'if(isReturn(event)) { getPreviousInSequence("' + sequenceName + '",' + i + '); } \'>&lt;</span>');
                }
                sb.append('<select class="chapters" tabindex="13" id="seq' + i + '" onclick="">');
                for (k=0;k<sequence.length;k++) {
                    sb.append('<option' + (sequence[k]==workDB[i][idIndex]?' selected="selected"':'') + ' value="' + sequence[k] + '">' + getStoryWithId(sequence[k])[titleIndex]);
                }
                sb.append('</select>');
                sb.append('<span class="button" tabindex="13" onclick=\'filterTable("id",document.getElementById("seq' + i + '").value, true); \'>Go!</span>');


                if (sequence[sequence.length-1]!=workDB[i][idIndex]) {
                    sb.append('<span class="button" tabindex="13" onFocus=\'this.className="button hover"\' onBlur=\'this.className="button"\'  onclick=\'getNextInSequence("' + sequenceName + '",' + i + ');\' onKeyPress=\'if(isReturn(event)) { getNextInSequence("' + sequenceName + '",' + i + '); } \'>&gt;</span>');
                    sb.append('<span class="button" tabindex="13" onFocus=\'this.className="button hover"\' onBlur=\'this.className="button"\'  onclick=\'getLastInSequence("' + sequenceName + '",' + i + ');\' onKeyPress=\'if(isReturn(event)) { getLastInSequence("' + sequenceName + '",' + i + '); } \'>&gt;&gt;</span>');
                }
                sb.append('</span></td></tr>');
            }
        }
    }
    return sb;  
}


function getFirstInSequence(sequenceName,currentI) {
    var currentI = workDB[currentI][idIndex];
    var sequence = getSequence(sequenceName);
    if (sequence != null && isArray(sequence) && sequence[0]!=currentI) {
        setStoryById("" + sequence[0]);      
        showList();
        window.scrollTo(0,findPosY(document.getElementById('storyList'))-50);  
        generateRSH();

    }
}


function getLastInSequence(sequenceName,currentI) {
    var currentI = workDB[currentI][idIndex];
    var sequence = getSequence(sequenceName);
    if (sequence != null && isArray(sequence) && sequence[sequence.length-1]!= currentI) {
        setStoryById("" + sequence[sequence.length-1]);      
        showList();
        window.scrollTo(0,findPosY(document.getElementById('storyList'))-50);  
        generateRSH();
    }
}


function getPreviousInSequence(sequenceName,currentI) {
    var currentI = workDB[currentI][idIndex];
    var sequence = getSequence(sequenceName);
    if (sequence != null && isArray(sequence)) {
        var i = 0;
        while (i < sequence.length && sequence[i]!=currentI) {
            i++;
        }

        if (i>0 && sequence[i-1]!=currentI) {
            setStoryById("" + sequence[i-1]);      
            showList();
            window.scrollTo(0,findPosY(document.getElementById('storyList'))-50);  
            generateRSH();
        }
    }
}

function getNextInSequence(sequenceName,currentI) {
    var currentI = workDB[currentI][idIndex];
    var sequence = getSequence(sequenceName);
    if (sequence != null && isArray(sequence)) {
        var i = 0;
        while (i < sequence.length && sequence[i]!=currentI) {
            i++;
        }

        if (i<sequence.length-1 && sequence[i+1]!=currentI) {
            setStoryById("" + sequence[i+1]);      
            showList();
            window.scrollTo(0,findPosY(document.getElementById('storyList'))-50);  
            generateRSH();
        }
    }
}





function getSequence(sequenceName) {
    var i = 0;
    var found = false;
    while(i < sequenceDB.length && !found) {
        if (sequenceDB[i][0]==sequenceName) {
            found = true;
        }
        else {
            i++;
        }
    }


    return (found?sequenceDB[i][1]:null);
}


function showStory(i) {
    var url = storyLocation + workDB[i][urlIndex];
    if (windowMode == 1) {
        location.href = url;
    }
    else if (windowMode == 2) {
        window.open(url, 'story', 'toolbar=yes, directories=yes, location=yes, status=yes, menubar=yes, resizable=yes, scrollbars=yes');
    }
    else if (windowMode == 3) {
        var root = document.getElementById('content' + i);
        if (root.innerHTML=='')
            root.innerHTML = '<iframe src="' + url + '" style="width:100%;height:400px;border-width:0px"></iframe>';
        else
            root.innerHTML='';
    }
}


function getImages(i) {
    var res="";
    if (isArray(workDB[i][imageColumn])) {
        res+='<tr><td colspan="4" class="images">';
        for (var j = 0 ; j<workDB[i][imageColumn].length ; j++) {
            var thumb = imageLocation + workDB[i][imageColumn][j].substring(0,workDB[i][imageColumn][j].length-4) + "-t" + workDB[i][imageColumn][j].substring(workDB[i][imageColumn][j].length-4,workDB[i][imageColumn][j].length);
            res+='<a href="' + imageLocation + workDB[i][imageColumn][j] + '"><img src="' + thumb + '">';
        }
        res+="</td></tr>";
    }
    return res;
}

/**

 * call the ratings page of the story with index i
 **/
function rate(i) {
    location.href = 'rate.html?title=' + workDB[i][titleIndex] + '&author=' + workDB[i][authorIndex];
}


/**
 * show the story list and other related elements (navbar, sortbar,...)
 **/
function showList() {

    var storyCount = workDB.length;
    var sb = new StringBuilder();

    if (database.length <=0) {
        errorList[errorList.length] = 'No stories in the database';
    }
    else if (workDB.length <=0 ) {
        errorList[errorList.length] = 'No stories met your search criteria';
    }


    if (errorList.length <=0) {
        var nav = getNavigationBar(storyCount);

        if (adminMode) sb.append(getAdminBar());
        sb.append(nav);
        sb.append('<div style="clear:both;height:1em;"></div>');
        sb.append(getButtonBar());
        sb.append(getSortBar());
        sb.append(getStoryTable());
        sb.append(nav);
        sb.append('<div style="clear:both;height:1em;"></div>');
    }
    else {
        sb.append(getErrorReport());
    }

    document.getElementById('storyList').innerHTML = sb.toString();
    
    
    document.getElementById('extraData').innerHTML = "";
    // last filter was on author
    if (lastFilterCol == authorIndex) {
        var data = getAuthorData(lastFilterTerm);
        if (data != null) {
            var sb = new StringBuilder();
            sb.append('<h1>' + data[0] + '</h1>');
            sb.append('<p>e-mail : ' + (data[1]!=''?'<a href="mailto:' + data[1] + '">':'') + data[1] + (data[1]!=''?'</a>':'') + '<br>');
            sb.append('website : ' + (data[2]!=''?'<a href="' + data[2] + '">':'') + data[2] + (data[2]!=''?'</a>':'') +  '</p>');
            document.getElementById('extraData').innerHTML = sb.toString();
        }
    }

    // enable showall buttons
    if (storyCount < database.length)
        document.getElementById("showall").removeAttribute("disabled");
    else
        document.getElementById("showall").setAttribute("disabled",true);
}


function getErrorReport() {
    var sb = new StringBuilder();

    sb.append('<div class="list error"><table><thead><tr><td>System message</td></tr></thead>');
    for( var i = 0 ; i < errorList.length ; i++) {
        sb.append('<tr><td>' + errorList[i] + '</td></tr>');
    }
    sb.append('</table></div>')

    errorList  = new Array();

    return sb;
}


/**
 * sort the working database with the default js sort
 * expanded to cover multidim array and
 * ascending/descending sorting
 **/
function sortDB(columnIndex,sortDir) {
    if (typeof sortDir=='undefined' || sortDir==null){
        if (cdbi == columnIndex)
            sortAscending = (sortAscending ? false : true);
        else {
            cdbi = columnIndex;
            sortAscending = true;
        }
    }
    else {
        cdbi = columnIndex;
        sortAscending = sortDir;
    }


    if (sortAscending) {
        workDB.sort(sortByColAsc);
        }
    else {
        workDB.sort(sortByColDec);
    }
        
}


/**
 * sort the working database ascending
 **/
function sortByColAsc(a,b) {
    if ( (isArray(a[cdbi]) ? a[cdbi] : a[cdbi].toLowerCase()) < (isArray(b[cdbi]) ? b[cdbi] : b[cdbi].toLowerCase()))
        return -1;
    else
        return 1;
}

/**
 * sort the working database descending
 */
function sortByColDec(a,b) {
    if ( (isArray(a[cdbi]) ? a[cdbi] : a[cdbi].toLowerCase()) > (isArray(b[cdbi]) ? b[cdbi] : b[cdbi].toLowerCase()))
        return -1;
    else
        return 1;
}


/**
 * sort a string array case insensitive
 **/
function sortCaseInsensitive(a,b) {
    if ( (isArray(a) ? a : a.toLowerCase()) < (isArray(b) ? b : b.toLowerCase()))
        return -1;
    else
        return 1;
}


/**
 * checks if search_term is in the current array
 **/
 Array.prototype.inArray = function(search_term) {
   var i = this.length;
    if (i > 0) {
        do {
            if (this[i-1] == search_term) {
                return true;
            }
        } while (--i);
    }
    return false;
}


/**
 * parse a database array for display
 **/
function stringArray(array, searchTerm) {
    var sb = new StringBuilder();

    var  l = array.length-1;
    for (var i = 0 ; i < l ; i++) {
        sb.append('<span class="click" onclick=\'filterTable("' + searchTerm + '","'+ array[i] + '",true);generateRSH();\'>' + array[i] + '</span>, ');
    }
    if (l>=0) sb.append('<span class="click" onclick=\'filterTable("' + searchTerm + '","'+ array[l] + '",true);generateRSH();\'>' + array[l] + '</span>');

    return sb;
}


/**
 * Same as filterTable but called from the database
 * We process the term to match from col and DBel
 **/
function ft(col,DBel,rege,cat) {
    col = unescape(col);
    var match = "" + workDB[DBel][getColumnIndex(col)];
    var rege = true;

    filterTable(col,match,rege,cat);
    generateRSH();

}

/**
 * checks if the term [match] appears in one of [col] columns
 **/
function filterTable(col , match , rege, cat) {
    filterTableB(col , match , rege, cat);
    // enable showall buttons
    if (workDB.length < database.length) document.getElementById("showall").removeAttribute("disabled");

    sortAscending = (sortAscending?false:true);
    sortDB(cdbi);
    showList();
    window.scrollTo(0,findPosY(document.getElementById('storyList'))-50);  

}

function filterTableB(col , match , rege, cat) {

    // if not consecutive then clear search history
    if (consec==false) {
        searchTerms[0] = new Array();   // columns to search in 
        searchTerms[1] = new Array();   // exact search
        searchTerms[2] = new Array();   // substractive search
        searchTerms[3] = new Array();   // terms to search for
    }
    // populate search history
    searchTerms[0][searchTerms[0].length] = col;
    searchTerms[1][searchTerms[1].length] = rege;
    searchTerms[2][searchTerms[2].length] = substr;
    searchTerms[3][searchTerms[3].length] = match;


    match = match.toLowerCase();
    showFrom = 0;
    col = unescape(col);

    // if we don't search consecutive, reseed the database
    if (consec==false && workDB.length < database.length) populateDatabase();

    var resultDB = new Array();

    // split the column string in an array
    var cols = col.split('|');
    var colsLength = cols.length;

    // get the indices of every column name and put them in an
    // array if they are valid
    var columnIndex = new Array();
    for (var i = 0 ; i < colsLength ; i++) {
        var index = getColumnIndex(cols[i]);
        if (index >= 0) {
            columnIndex[columnIndex.length] = index;
            if (rege) {
                lastFilterCol = index;
                lastFilterTerm = match;
            }

        }
    }
    colsLength = columnIndex.length;

    var DBLength = workDB.length;
    for (var rowIndex = 0 ; rowIndex < DBLength ; rowIndex++) {
        var addrow=false;

        var i = 0;
        while ( i < colsLength && addrow==false) {
            addrow = getMatch(workDB[rowIndex][columnIndex[i]],match,rege);
            i++;
        }

        // swap order if substractive filtering
        if (substr) addrow = (addrow ? false : true);

        if  (addrow) {
            resultDB[resultDB.length] = workDB[rowIndex];
        }
    }

    workDB = resultDB;
}


/**
 * checks if two term match
 **/
function getMatch(a,b,rege) {
    var ret = false;

    if (isArray(a)) {
        var l = a.length;
        var i = 0;
        while (ret==false && i < l) {
            if (rege==false) {
                if (("" + a[i]).toLowerCase().indexOf(b) >= 0) ret = true;
            }
            else {
                if (("" + a[i]).toLowerCase()==b) ret = true;
            }
            i++;
        }
    }
    else {
        a = ("" + a).toLowerCase();
        if (rege==false) {
            if (a.indexOf(b) >= 0) ret = true;
        }
        else {
            if (a==b) ret = true;
        }
    }

    return ret;
}


/**
 * perform a search with search term gathered from input
 * field with id [id]
 **/
function doSearch(el,col) {
    var match = document.getElementById(el).value.toLowerCase();
    execSearch(match,col);
}


/**
 * execute a search with unprocessed search term [match]
 * in cols [col] and with exact match [rexp]
 * dnsl = true if list does not have to be shown
 **/
function execSearch(match,col,rexp,dnsl) {
    // fetch cols from search opptions if they aren't given
    if (typeof col=='undefined' || col==null){
        col="";
        col += (document.getElementById("filterDate").checked?"date|":"");
        col += (document.getElementById("filterAuthor").checked?"author|":"");
        col += (document.getElementById("filterTitle").checked?"title|":"");
        col += (document.getElementById("filterDescription").checked?"description|":"");
        col += (document.getElementById("filterTFtype").checked?"tf type|":"");
        col += (document.getElementById("filterTFcategory").checked?"tf category|":"");
        col += (document.getElementById("filterTFsex").checked?'tf\'ed sex|':"");
        col += (document.getElementById("filterTFdegree").checked?"degree of tf|":"");
        col += (document.getElementById("filterSex").checked?"sex|":"");
        col += (document.getElementById("filterOther").checked?"other|":"");
        col += (document.getElementById("filterRating").checked?"rating|":"");
    }

    // fetch exact match from search options if it isn't given
    if (typeof rexp=='undefined' || rexp==null) rexp = document.getElementById("regexp").checked;

    // handle ' in search term
    var re = new RegExp ('\'', 'gi') ;
    match = match.replace(re, "´");

    // handle AND operator
    re = new RegExp ('AND', 'gi') ;
    match = match.replace(re, "+");

    match_ar = match.split('+');
    var backup;
    var l  = match_ar.length
    for (var i = 0 ; i<l ; i++) {
        if (i==1) {
            backup = consec;
            consec = true;
        }

        filterTableB(col,trim(match_ar[i]),rexp,null);
    }

    // enable showall buttons
    if (workDB.length < database.length) document.getElementById("showall").removeAttribute("disabled");

    if (!dnsl) {
        sortAscending = (sortAscending?false:true);
        sortDB(cdbi);
        showList();
    }
    if (match_ar.length>1) consec=backup;
}


/**
 * parse parameter array
 **/
function parseParameters() {
  var backup = consec;
  var backup2 = substr;
  consec=true;
  var sortdir;
  var diff;
  var searchin = null;
  var rexp = null;

  for (var i = 0 ; i< keyw.length ; i++) {
    if (keyw[i]=="perpage") setPerPage(parseInt(param[i]));
    else if (keyw[i]=="liststyle") setDisplayMode(parseInt(param[i]));
    else if (keyw[i]=="windowmode") setWindowMode(parseInt(param[i]));
    else if (keyw[i]=="navigationcutoff") setNavigationCutOff(parseInt(param[i]));
    else if (keyw[i]=="showfrom") setShowFrom(parseInt(param[i]));
    else if (keyw[i]=="story") setStoryById(param[i]);
    else if (keyw[i]=="sortdirection") sortdir = (param[i]=="true"?true:false);
    else if (keyw[i]=="sort") {
        var index = getColumnIndex(param[i]);
        if (index >= 0) {
            sortDB(parseInt(index),sortdir);
        }
        else {
            errorList[errorList.length] = 'Unable to sort \'' + param[i] + '\' column. It does not excist';
        }
    }
    else if (keyw[i]=="search") execSearch(param[i],null,null,true);
    else if (keyw[i]=="searchin") searchin = param[i];
    else if (keyw[i]=="searchexact") rexp = (param[i]=="true"?true:false);
    else if (keyw[i]=="searchsubstractive") substr = (param[i]=="true"?true:false);
    else if (keyw[i]=="searchfor") execSearch(param[i],searchin,rexp,true);
    else if (getColumnIndex(keyw[i]) >= 0) execSearch(param[i],keyw[i],true,true);
    else if (keyw[i].length > 6 && keyw[i].substring(0,7) == "search " && getColumnIndex(keyw[i].substring(7,keyw[i].length)) >=0) execSearch(param[i],keyw[i].substring(7,keyw[i].length),false,true);
  }

  consec=backup;
  substr = backup2;
}


/**
 * Change layout mode and perpage depending on user settings
 **/
function changeOptions() {
    setPerPage(parseInt(document.getElementById('perPage').value));
    setDisplayMode(parseInt(document.getElementById('listStyle').value));
    setWindowMode(parseInt(document.getElementById('windowMode').value));

    if (document.getElementById("rememberMe").checked) {
        hasCookie = true;
        createCookie("docslab", displayMode + "|" + perPage + "|" + windowMode, 365);
    }
    else if (hasCookie) {
        hasCookie = false;
        createCookie("docslab", displayMode + "|" + perPage + "|" + windowMode, -1);
    }

    showFrom = showFrom - showFrom%perPage;

    showList();
}


/**
 * retrun true if return key has been pressed
 **/
function isReturn(e) {
    var key;

    if (window.event)
       key = window.event.keyCode;
    else if (e)
       key = e.which;

    return (key==13 ? true : false)
}


/**
 * retrun true if [a] is an array
 **/
function isArray(a) {
    return isObject(a) && a.constructor == Array;
}


/**
 * retrun true if [a] is an object
 **/
function isObject(a) {
    return (a && typeof a == 'object');
}


/**
 * checks if a cookie exsists
 * and read it in
 **/
function getCookie() {
    var cookie = readCookie("docslab");
    if (cookie != null) {
        cookie = cookie.split('|');
        if (cookie.length > 0) setDisplayMode(parseInt(cookie[0]));
        if (cookie.length > 1) setPerPage(parseInt(cookie[1]));
        if (cookie.length > 2) setWindowMode(parseInt(cookie[2]));
        document.getElementById("rememberMe").checked=true;
        hasCookie = true
    }
}


/**
 * create a cookkie with name [name], value [value]
 **/
function createCookie(name,value,days) {
    if (days) {
        var date = new Date();
        date.setTime(date.getTime()+(days*24*60*60*1000));
        var expires = "; expires="+date.toGMTString();
    }
    else expires = "";

    document.cookie = name+"="+value+expires+"; path=/";
}


/**
 * returns the cookie with name [name]
 **/
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 c.substring(nameEQ.length,c.length);
    }
    return null;
}


/**
 * save cookie when leaving page to retain duration
 **/
window.onunload = function(e) {
    if (hasCookie) {
        createCookie("docslab", displayMode + "|" + perPage + "|" + windowMode, 365);
    }
}



/**
 * opens a tab from the tabbar
 **/
function showTab(clickedTab, tabId) {
  if (openedTab != clickedTab) {
    closeTab();

    openedTab = clickedTab;
    openedTab.setAttribute("id","activeTab");
    openedTab.setAttribute("title","fold up " + openedTab.innerHTML + " tab");

    openedTabContent = document.getElementById(tabId);
    openedTabContent.style.display="block";

    document.getElementById('foldButton').className = "closeButton";
    document.getElementById('tabContent').style.borderBottomColor="#555";
  }
  else {
    closeTab();
  }
}


/**
 * closes the currently opened tab from the tabbar
 **/
function closeTab() {
  if (openedTab!=null) {
    openedTab.removeAttribute('id');
    openedTab.setAttribute("title","fold out " + openedTab.innerHTML + " tab");
  }

  if (openedTabContent!=null) {
    openedTabContent.style.display="none";
  }

  document.getElementById('foldButton').className = "";
  document.getElementById('tabContent').style.borderBottomColor="#333";

  openedTab = null;
  openedTabContent = null;
}


/**
 * returns xpos in pixels of element [obj]
 **/
function findPosX(obj)
{
    var curleft = 0;
    if (obj.offsetParent)
    {
        while (obj.offsetParent)
        {
            curleft += obj.offsetLeft
            obj = obj.offsetParent;
        }
    }
    else if (obj.x)
        curleft += obj.x;
    return curleft;
}


/**
 * returns ypos in pixels of element [obj]
 **/
function findPosY(obj)
{
    var curtop = 0;
    if (obj.offsetParent)
    {
        while (obj.offsetParent)
        {
            curtop += obj.offsetTop
            obj = obj.offsetParent;
        }
    }
    else if (obj.y)
        curtop += obj.y;
    return curtop;
}


function showRandomStory() {
    var resultDB = new Array();
    var i = parseInt(Math.random() * database.length);
    var storyId = "" + database[i][idIndex];
    setStoryById(storyId);
    showList();
    generateRSH();
}


function resetDatabase() {
    document.getElementById('databaseJS').src = "database.js";
}


function initializeRSH() {
   // initialize our DHTML history
   dhtmlHistory.initialize();
   // subscribe to DHTML history change
   // events
   dhtmlHistory.addListener(historyChange);
   
   // if this is the first time we have
   // loaded the page...
   if (dhtmlHistory.isFirstLoad()) {
   }
}
         
function generateRSH() {
   historyId=historyId+1;
   var msg = "";
   msg+="showfrom=" + showFrom;
//   msg+="&perpage=" + perPage;
   msg+="&sortdirection="+(sortAscending?"true":"false");
   msg+="&sort=" + columnNames[cdbi];
//   msg+="&liststyle=" + displayMode;
//   msg+="&window=" + windowMode;
   for (var i = 0 ; i<searchTerms[0].length;i++) {
       msg+="&searchin=" + searchTerms[0][i];
       msg+="&searchexact=" + searchTerms[1][i];
       msg+="&searchsubstractive=" + searchTerms[2][i];
       msg+="&searchfor=" + searchTerms[3][i];
   }
   dhtmlHistory.add(msg,msg);
}
         

function executeRSH(str) {
    param = new Array();
    keyw = new Array();
        searchTerms[0] = new Array();   // columns to search in 
        searchTerms[1] = new Array();   // exact search
        searchTerms[2] = new Array();   // substractive search
        searchTerms[3] = new Array();   // terms to search for
    parseParamString(str);
    parseParameters();
    document.getElementById('perPage').value=perPage;
    document.getElementById('listStyle').value=displayMode;
    document.getElementById('windowMode').value=windowMode;
    showList();
}

        
/** Our callback to receive history 
    change events. */
function historyChange(newLocation, historyData) {
   populateDatabase()
   var historyMsg = historyData;
   
   executeRSH(historyMsg);
}
