// $Id$

/**
 * For the purpose of editing the context strings:
 *                 stored in     stored in           stored in edit field
 * db item         element id    option property     input property
 * ---------------------------------------------------------------------
 * word_pk             num                             
 * word_id             xref                            
 * word                acro                            
 * context_pk                         value          tabIndex
 *
 * word_id is the unique href identifier for the particular definition
 * word_pk is the primary key of the acronym used to get the possible
 * word is the acronym
 * context_pk is the primary key of the context entry
 * 
 * since the context list is sorted and the values are distinct, the  
 * relationship to the acronyms
 * is ignored except when restoring the edited context to the database at
 * which time all the instances of the context are replaced with the newly 
 * edited version.  This is done in the php
 * file by getting the opt context via the index, context_pk, and  then
 * changing all instances of the
 * opt context to the new context.
 */

function GetXmlHttpObject(){
//alert("0 In GetXmlHttpObject() function.");
  var xmlHttp = null;
  try{
    // Firefox, Opera 8.0+, Safari
    xmlHttp = new XMLHttpRequest();
    //DO NOT reference httpRequest.overrideMimeType) - it will cause an ERROR
  }
  catch (e){
  //Internet Explorer
    try{
      xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
    }
    catch (e){
      xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
    }
  }
  return xmlHttp;
};

/**
 * remove control characters from a string
 */
function ctlPurge(str) {
  var num = str.length;
  var r = ''; var i;
  for(i=0; i<num; i++) {
    if (str[i] == '\t' ||
        str[i] == '\n' ||
        (str[i] >= ' ' && str[i] <= '~')
        ) { 
      r += str[i];
    }
  }
  return r;
};

function striptags(instr) {
  outstr = instr.replace(/<[^>]+>/g,"");
  return outstr;
};

/**
 * _to_id(word) - changes acronym/word into its (almost unique) id/href equivalent
 * word - the acronym, buzzword or whatever
 * To make the id unique, any duplicates must have a digit added to the end.
 * Which digit is determined by the order in the list of duplicates.
 */
function _to_id(word) {
  id = '';
  // handle cases of multiple acronyms in the acronym column (separated by a space and maybe a comma)
  word1 = trim(word);
  if (x = word1.split(',')) { // if no comma, sets word1 anyway
    word1 = x[0];
  }
  if (y = word1.split(' ')) { // if no space, sets word1 anyway
    word1 = y[0];
  }
  c = word1.charAt(0);
  switch (c) {
    case '-':
      id = 'H' + c;
      break;
      
    case '.':
      id = 'P' + c;
      break;
      
    case '_':
      id = 'U' + c;
      break;
     
    case '/':
      id = 'S' + c;
      break;
      
    default:
      if ( (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) {
        id = c;
      }
      else if (c >= '0' && c <= '9') {
        id = 'D' + c;
      }
      else {
        return '';
      }
      break;
      
  }
  for (n = 1; n < word1.length; n++) {
    c = word1.charAt(n);
    if (c == '/') { 
      id = id + ':';
    } 
    else if (
             (c >= 'A' && c <= 'Z') || 
             (c >= 'a' && c <= 'z') ||
             (c >= '0' && c <= '9') ||
             c == '-'  ||
             c == '.'  ||
             c == '_'  
            ) {
      id = id + c; // we're backwards: add char to front
    }
    else {
      return word1;
    }  
  }
  return id;
}

/**
 * trim - remove whitespace from ends of a string: similar to php trim function
 */
function trim (word) { // approximates PHP trim function
  if (typeof(word) != "string") {
    return word;
  }
  a = word[word.length - 1];
  // rtrim
  while (word.length > 1 &&
         (word[word.length - 1] == ' ' || 
          word[word.length - 1] == '\t' || 
          word[word.length - 1] == '\n' || 
          word[word.length - 1] == '\r')) {
    word = word.substring(0, word.length - 1);
  }
  // ltrim
  while (word.length > 1 &&
         (word[0] == ' ' || 
          word[0] == '\t' || 
          word[0] == '\n' || 
          word[0] == '\r')) {
    word = word.substring(1, word.length);
  }
  return word;
}

/**
 * is_in - see if a string is a member of a list
 */
function is_in(item, list) { // is an item in the list?
//alert("is_in 0: item = " + item + ", list[0] = " + list[0]);
  // could not get for ... in to work correctly or at all
  x = item;
  if (typeof(item) == "string") {
    x = trim(x);
  }  
  for (i = 0; i < list.length; ++i) {
    if (x ==  list[i]) {
      return true;
    }
  }
  return false;
}

/**
 * displayContexts for acronym editing pages
 */
function displayContexts(xmlHttp) { 
//alert("displayContexts() 0: Server readyState: "+xmlHttp.readyState);
  var result;
  var row = new Array();
  var datum = new Array();
  var i;
  try {
    if (xmlHttp.readyState == 4) {
      try {
        if (xmlHttp.status == 200) {
          result = ctlPurge(xmlHttp.responseText);
          n = result.indexOf("<b>");
          if ( n >= 0 && n <= 10 ) {
            alert(striptags(result));
          } 
          else {
            // copies chosen context ids to possible ???
            var chosen = new Array();
            if ((chos = document.getElementById("chosen")) != null) {
              for (j = 0; j < chos.options.length; j++) {
                chosen[j] = chos.options[j].value;
              }
            }
            var sel = document.getElementById("possible");
            sel.options.length = 0; // empty the list
            row = result.split('\n');
            // This is a list of unique possible;
            //  we'll save the indexes to save database lookups.
            var opt;
            for (i=0;i<row.length-1; i++) {
              datum = row[i].split("\t");
              if(is_in(datum[0], chosen)) {
                continue;
              }
              opt = document.createElement("option");
              opt.value = datum[0];
              opt.text = datum[1];
              sel.appendChild(opt);
            }
          }
        } 
        else {
          alert("displayContexts() 5: xmlHttp.status != 200 or");
          altert("xmlHttp.status == "+xmlHttp.status);  
        }
      }
      catch(e) {
        alert('displayContexts() 6: Caught Exception in reference request: ' + e.number+"-"+e.name+"; "+e.description+"; "+e.message);
      }
    } 
    else {
      if (xmlHttp.readyState < 0 || xmlHttp.readyState > 4) 
      alert("displayContexts() 7: Unidentified readyState from request: "+xmlHttp.readyState);
    }
  }
  catch(e) {
    alert('IdisplayContexts() 8: Caught Exception number: ' + e.number+"\nname: "+e.name+"\ndescription: "+e.description+"\nmessage: "+e.message);
    //alert('Server Status: '+xmlHttp.statusText+' : '+xmlHttp.readyState);
  }
  if ( location.hostname == "www.kexsof.com" ) {
    _uacct = "UA-2492202-1";
    urchinTracker();
  }
};

/**
 * loadContexts - ajax initializer for displayContexts
 */
function loadContexts() { 
//alert("loadContexts() 0");
  xmlHttp = GetXmlHttpObject();
  if (xmlHttp == null){
    alert ("Browser does not support HTTP Request");
    return;
  }
  var url="acrymdbGet.php";
  xmlHttp.onreadystatechange = function () {displayContexts(xmlHttp);};
  xmlHttp.open("POST", url, true);
  xmlHttp.send(null);
};

/**
 * displayAcros - load edit page drop-down list with all acros
 * For the purpose of loading the acro strings:
 *                 stored in     stored in           stored in edit field
 * db item         element id    option property     input property
 * ---------------------------------------------------------------------
 * word_pk             num                             
 * word_id             xref                            
 * word                acro                            
 * context_pk                         value           tabIndex
 *
 * word_id is the unique href identifier for the particular definition
 * word_pk is the primary key of the acronym used to get the possible
 * word is the acronym
 * context_pk is the primary key of the context entry
 */
function displayAcros(xmlHttp) { 
//alert("displayAcros() 0: Server readyState: "+xmlHttp.readyState);
  var result;
  var row = new Array();
  var datum = new Array();
  var i;
  try {
    if (xmlHttp.readyState == 4) {
      try {
        if (xmlHttp.status == 200) {
          result = ctlPurge(xmlHttp.responseText);
          n = result.indexOf("<b>");
          if (n >= 0) {
            alert(striptags(result));
          } // end of if  n >= 0 && n <= 10
          else {
            var sel = document.getElementById("acro");
            row = result.split('\n');
            var t; var opt;
            opt = document.createElement("option");
            opt.id = "select"; 
            opt.title = "Select an acronym from the drop-down menu"; 
            opt.text = "Select"; // word
            sel.appendChild(opt);
            for (i = 0; i < row.length - 1; i++) { 
              datum = row[i].split("\t");  // always 3 items
              if (datum[2] === undefined) {
                continue;
              }
              opt = document.createElement("option");
              opt.value = datum[0]; // word_pk
              opt.title = datum[1]; // word_id
              opt.text = datum[2]; // word
              sel.appendChild(opt);
            } // end of for
          } // end of if  n >= 0 && n <= 10 else
        } // end of if xmlHttp.status == 200
        else {
          alert("displayAcros() 5: xmlHttp.status != 200 or  ...");
          alert("xmlHttp.status == "+xmlHttp.status);  
        } // end of if xmlHttp.status == 200 else
      } // end of try inside if xmlHttp.readyState == 4
      catch( e ) {
        alert('displayAcros() 6: Caught Exception in reference request: ' + e.number+"-"+e.name+"; "+e.description+"; "+e.message);
      }
    } // end of if xmlHttp.readyState == 4
    else {
      if (xmlHttp.readyState < 0 || xmlHttp.readyState > 4) {
        alert("displayAcros() 7: Unidentified readyState from request: "+xmlHttp.readyState);
      }
    } // end of if xmlHttp.readyState == 4 else
  } // end of first try
  catch( e ) {
    alert('displayAcros() 8: Caught Exception number: ' + e.number+"\nname: "+e.name+"\ndescription: "+e.description+"\nmessage: "+e.message);
    //alert('Server Status: '+xmlHttp.statusText+' : '+xmlHttp.readyState);
  }
  // loadContexts();
  if ( location.hostname == "www.kexsof.com" ) {
    _uacct = "UA-2492202-1";
    urchinTracker();
  }
};

/**
 * loadAcros - ajax initializer for displayAcros
 */
function loadAcros() {
//alert("loadAcros() 0");
  // clear out any previous data
  sel = document.getElementById("acro");
  sel.options.length = null;
  
  xmlHttp = GetXmlHttpObject();
  if (xmlHttp == null) {
    alert ("Browser does not support HTTP Request");
    return;
  }
  var url="acrymsGet.php";
  xmlHttp.onreadystatechange = function () {displayAcros(xmlHttp);};
  xmlHttp.open("POST",url,true);
  xmlHttp.send(null);
};

/**
 * init_acrymdb() - clears out / initializes acronym  edit page (acrymdb.php)
 */
function init_acrymdb() {
  // clear out any previous data
  prev = document.getElementById("num");
  prev.value = ''; // word_pk
  prev = document.getElementById("xptr");
  prev.value = ''; // word_id
  prev = document.getElementById("expand");
  prev.value = ''; // expansion
  prev = document.getElementById("explain");
  prev.value = ''; // explanation
  prev = document.getElementById("possible");
  prev.options.length = 0; // removes all options
  prev = document.getElementById("chosen");
  prev.options.length = 0; // removes all options
  prev = document.getElementById("type");
  prev.value = ''; // word_type
  prev = document.getElementById("author");
  prev.value = ''; // author
  prev = document.getElementById("start");
  prev.value = ''; // start date
  prev = document.getElementById("stop");
  prev.value = ''; // stop date
  prev = document.getElementById("era");
  prev.value = ''; // era
  prev = document.getElementById("source");
  prev.value = ''; // source
  loadAcros();
  // loadContexts();
};

/**
 * new_word_id: determines the word_id/href of the proposed new acronym and insert
 */
function new_word_id(xmlHttp) { 
//alert("new_word_id() 0: Server readyState: "+xmlHttp.readyState);
  var result;
  var row = new Array();
  var datum = new Array(15);
  var i;
  try {
    if (xmlHttp.readyState == 4) {
      try {
        if (xmlHttp.status == 200) {
          result = ctlPurge(xmlHttp.responseText);
          // leave any previous "chosen" possible in case we want them ...
          
          opt = document.getElementById("new_word_id");
          word = opt.text;
          word_id = _to_id(word); // word_id - id/href value of word
          n = result.indexOf("<b>");
          if (n >= 0) {
            if (result.indexOf("Sorry, ") === -1) { // screen out not found method
              alert(result); // there was a problem
              return;
            }
          } 
          else {
            // determine new word_id/href value
            row = result.split('\n');
//###################################### FILLS IN TABLE WITH CURRENT ACRONYM
            var theDiv = document.getElementById("theDiv");
            var theTable;
            if (theDiv.getElementsByTagName("table").length === 0) {
              theTable = newAcroTable();
              createHeader(theTable);
              theDiv.appendChild(theTable);
              //cleanup();
            } 
            else {
              theTable = theDiv.getElementsByTagName("table")[0];
            }
            var h = document.createElement("tbody");
            theTable.appendChild(h);
            for (i = 0; i < row.length - 1; i++) { // decrement because \n ends rows
              var datum = new Array();
              datum = row[i].split("\t");  // always 4 items
              if (item = document.getElementById(datum[1])) { // if the word is already in the list
                continue;
              } 
              var r = document.createElement("tr");
                var c = document.createElement("td");
                c.className = "tdacrymckbx";
                  var b = document.createElement("input");
                  b.type = "checkbox";
                  b.id = "x"+datum[1];  // word_id or href
                  b.value = "box";
                  b.className = "acrymckbx"; // syntax verfied for IE
                c.appendChild(b);
              r.appendChild(c); // checkbox
                c = document.createElement("td");
                c.className = "tdacro";
                  var a = document.createElement("a");
                  a.className = "acrymFind";
                  a.addEventListener('focus',function (e) {anchFocusColor(this);},false);
                  a.addEventListener('blur',function (e) 
                      {anchBlurColor(this);},false);
                  a.id = datum[1]; // word_id or href
                  a.innerHTML = datum[2]; // acronym
                c.appendChild(a);
              r.appendChild(c); // acronym
                c = document.createElement("td");
                c.className = "tdacro";
                c.innerHTML = datum[3];
              r.appendChild(c); // context
                c = document.createElement("td");
                c.className = "tdacro";
                c.innerHTML = datum[4];
              r.appendChild(c); // explanation - expansion
              if (ie) {
                h.appendChild(r);
              } 
              else {
                theTable.appendChild(r);
              }
            }
//######################################
            len = row.length - 1; // the last row returned is blank ...
            if (len === 1) {
              word_id = word_id + ":00";
            }
            else {
              if (len > 11) {
                word_id += ":" + (len - 1);
              }
              else {
                word_id += ":0" + (len - 1);                
              }
            }
          }
          var input = document.getElementById("num");
          input.value = ''; // word_pk - primary key of word
          input = document.getElementById("xptr");
          input.value = word_id; // word_id - id/href value of word
          // acro
          input = document.getElementById("expand");
          input.value = ''; // expansion
          input = document.getElementById("explain");
          input.value = ''; // explanation
          input = document.getElementById("type");
          input.value = ''; // word_type
          input = document.getElementById("author");
          input.value = ''; // author
          input = document.getElementById("start");
          input.value = ''; // start date
          input = document.getElementById("stop");
          input.value = ''; // stop date
          input = document.getElementById("era");
          input.value = ''; // era
          input = document.getElementById("source");
          input.value = ''; // source
        } 
        else {
          alert("new_word_id() 5: xmlHttp.status != 200 or");
          alert("xmlHttp.status == "+xmlHttp.status);  
        }
      }
      catch( e ) {
        alert('new_word_id() 6: Caught Exception in reference request: ' + e.number+"-"+e.name+"; "+e.description+"; "+e.message);
      }
    } 
    else {
      if (xmlHttp.readyState < 0 || xmlHttp.readyState > 4) {
        alert("new_word_id() 7: Unidentified readyState from request: "+xmlHttp.readyState);
      }
    }
  }
  catch( e ) {
    alert('new_word_id() 8: Caught Exception number: ' + e.number+"\nname: "+e.name+"\ndescription: "+e.description+"\nmessage: "+e.message);
    //alert('Server Status: '+xmlHttp.statusText+' : '+xmlHttp.readyState);
  }
  if( location.hostname == "www.kexsof.com" ) {
    _uacct = "UA-2492202-1";
    urchinTracker();
  }
};

/**
 * db_new - creates ajax initial word, word_id values for 
 * new buttion in the database page
 */
function db_new() {
  // get new acronym and confirm
  item = document.getElementById('q');
  word = item.value;  // user inputs word to search for
  // put new acronym at the end of the select list and select it
  // it will be sorted in the select list only after it has been 
  // entered into the database
  var acrolist = document.getElementById("acro");
  var opt = document.createElement("option");
  opt.id = "new_word_id"; // word_pk
  opt.title = word; // help
  opt.text = word; // word
  acrolist.appendChild(opt);
  opt.selected = true;
  
  xmlHttp = GetXmlHttpObject();
  if (!xmlHttp) {
    alert ("Browser does not support HTTP Request");
    return;
  }
  var url="acrymGet.php";
  var args = "q="+word+"";
  xmlHttp.onreadystatechange = function () {new_word_id(xmlHttp); };
  xmlHttp.open("POST",url,true);
  xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); 
  xmlHttp.send(args);
};

function db_delete() {
  if(confirm("Are you sure you want to delete the acronym?")) {
  }
};

function db_clear() {
  if(confirm("Are you sure you want to clear the page?")) {
    prev = document.getElementById("num");
    prev.value = ''; // word_pk
    prev = document.getElementById("xptr");
    prev.value = ''; // word_id
    prev = document.getElementById("expand");
    prev.value = ''; // expansion
    prev = document.getElementById("explain");
    prev.value = ''; // explanation
    prev = document.getElementById("type");
    prev.value = ''; // word_type
    prev = document.getElementById("author");
    prev.value = ''; // author
    prev = document.getElementById("start");
    prev.value = ''; // start date
    prev = document.getElementById("stop");
    prev.value = ''; // stop date
    prev = document.getElementById("era");
    prev.value = ''; // era
    prev = document.getElementById("source");
    prev.value = ''; // source
    loadAcros();
  }
};

/**
 * update_acro - intercepts ajax request from db_update(): display update status
 */
function update_acro(xmlHttp) { 
//alert("displayWord() 0: Server readyState: "+xmlHttp.readyState);
  var result;
  var row = new Array();
  var datum = new Array(15);
  var i;
  try {
    if (xmlHttp.readyState == 4) {
      try {
        if (xmlHttp.status == 200) {
          result = ctlPurge(xmlHttp.responseText);
          row = result.split('\n');
          datum = row[0].split("\t");  // first row contains word data; always 6 items
          word_pk = datum[0];
          word_id = datum[1];
          list = document.getElementById("acro");
          target = list.options[list.selectedIndex];
          target.value = word_pk;
          //target.id = word_id; // don't: same id may be in search table above
          var input = document.getElementById("num");
          input.value = word_pk; // word_pk - primary key of word
          input = document.getElementById("xptr");
          input.value = word_id; // word_id - id/href value of word
          // acronym/word has already been selected and displayed
          //input = document.getElementById("acro"); // datum[2]
          input = document.getElementById("expand");
          input.value = datum[3]; // expansion
          input = document.getElementById("explain");
          input.value = datum[4]; // explanation
          input = document.getElementById("type");
          input.value = datum[5]; // word_type
          input = document.getElementById("author");
          input.value = datum[6]; // author
          input = document.getElementById("start");
          input.value = datum[7]; // start date
          input = document.getElementById("stop");
          input.value = datum[8]; // stop date
          input = document.getElementById("era");
          input.value = datum[9]; // era
          input = document.getElementById("source");
          input.value = datum[10]; // source
          return;
        } 
        else {
          alert("update_acro() 5: xmlHttp.status != 200 or xmlHttp.status == "+xmlHttp.status);  
        }
      }
      catch( e ) {
        alert('update_acro() 6: Caught Exception in reference request: ' + e.number+"-"+e.name+"; "+e.description+"; "+e.message);
      }
    } 
    else {
      if (xmlHttp.readyState < 0 || xmlHttp.readyState > 4) {
        alert("update_acro() 7: Unidentified readyState from request: "+xmlHttp.readyState);
      }
    }
  }
  catch( e ) {
    alert('update_acro() 8: Caught Exception number: ' + e.number+"\nname: "+e.name+"\ndescription: "+e.description+"\nmessage: "+e.message);
    //alert('Server Status: '+xmlHttp.statusText+' : '+xmlHttp.readyState);
  }
  if( location.hostname == "www.kexsof.com" ) {
    _uacct = "UA-2492202-1";
    urchinTracker();
  }
};

function db_update() {
  // put new acronym at the end of the select list and select it
  // it will be sorted in the select list only after it has been 
  // entered into the database
  rec = '';
  num_l = document.getElementById("num");
  num = num_l.value;
  rec += "" + num + "`";
  word_id_l = document.getElementById("xptr");
  word_id = word_id_l.value;
  rec += "" + word_id + "`";
  acro_sel = document.getElementById("acro");
  acro = acro_sel.options[acro_sel.selectedIndex].text
  rec += "" + acro + "`";
  expansion_l = document.getElementById("expand");
  expansion = expansion_l.value;
  rec += "" + escape(expansion) + "`";
  explanation_l = document.getElementById("explain");
  explanation = explanation_l.value;
  rec += "" + escape(explanation) + "`";
  type_l = document.getElementById("type");
  type = type_l.value;
  rec += "" + type + "`";
  author_l = document.getElementById("author");
  author = author_l.value;
  rec += "" + author + "`";
  start_l = document.getElementById("start");
  start = start_l.value;
  rec += "" + start + "`";
  stop_l = document.getElementById("stop");
  stop = stop_l.value;
  rec += "" + stop + "`";
  era_l = document.getElementById("era");
  era = era_l.value;
  rec += "" + era + "`";
  source_l = document.getElementById("source");
  source = source_l.value;
  rec += "" + escape(source) + "\n";
  bing = rec;
  bing = bing.replace(/`/g,'\n');
  if(!confirm(bing + "\nAre you sure you want to save this change?")) {
    return;
  }
  chosen_l = document.getElementById("chosen");
  for (i = 0; i < chosen_l.length; i++) {
    rec += chosen_l.options[i].value; // numbers: don't need to escape() these
    if (i + 1 < chosen_l.length) { // if not the last one ...
      rec += "\n";
    }
  }
  xmlHttp = GetXmlHttpObject();
  if (!xmlHttp) {
    alert ("Browser does not support HTTP Request");
    return;
  }
  var url="acrymUpdate.php";
  var args = "q="+rec;
  xmlHttp.onreadystatechange = function () {update_acro(xmlHttp); };
  xmlHttp.open("POST",url,true);
  xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); 
  xmlHttp.send(args);
};

/**
 * displayWord - intercepts ajax request from loadWord(): display acronym data
 */
function displayWord(xmlHttp) { 
//alert("displayWord() 0: Server readyState: "+xmlHttp.readyState);
  var result;
  var row = new Array();
  var datum = new Array(15);
  var i;
  try {
    if (xmlHttp.readyState == 4) {
      try {
        if (xmlHttp.status == 200) {
          result = ctlPurge(xmlHttp.responseText);
          n = result.indexOf("<b>");
          if( n >= 0 && n <= 10 ) {
            alert(striptags(result));
          } 
          else {
            // put any previous "chosen" possible back into the possible list
            var chosen = document.getElementById("chosen");
            possible = document.getElementById("possible");
            for (j = 0; j < chosen.options.length; j++) {
              opt = document.createElement("option");
              opt.value = chosen.options[j].value;
              opt.text = chosen.options[j].text;
              possible.appendChild(opt);
            }
            chosen.options.length = 0;  // clear the "chosen" list
            // "chosen" possible list is now empty
            // populate the acronym data
            row = result.split('\n');
            datum = row[0].split("\t");  // first row contains word data; always 6 items
            var input = document.getElementById("num");
            input.value = datum[0]; // word_pk - primary key of word
            word_pk = datum[0];
            input = document.getElementById("xptr");
            input.value = datum[1]; // word_id - id/href value of word
            // acronym/word has already been selected and displayed, so ... check it!
            input = document.getElementById("acro");
            word = input.options[input.selectedIndex].text; // word_pk
            word_id = input.options[input.selectedIndex].id; // word_pk
            if (datum[2] != word) {
              alert(
                    "Database returned acronym '" + datum[2] + 
                    "' with word_id '" + datum[1] + 
                    "' when asked to fetch the acronym '" + word + 
                    "' with word_id '" + word_id + 
                    "'.  Please report the details on our about page and try again later."
                   );
              return false;
            }
            input = document.getElementById("expand");
            input.value = datum[3]; // expansion
            input = document.getElementById("explain");
            input.value = datum[4]; // explanation
            input = document.getElementById("type");
            input.value = datum[5]; // word_type
            input = document.getElementById("author");
            input.value = datum[6]; // author
            input = document.getElementById("start");
            input.value = datum[7]; // start date
            input = document.getElementById("stop");
            input.value = datum[8]; // stop date
            input = document.getElementById("era");
            input.value = datum[9]; // era
            input = document.getElementById("source");
            input.value = datum[10]; // source
            // get each context for this acronym
            len = possible.options.length; // size of possible possible list
            for (i = 1; i < row.length - 1; i++) { // get possible so ignore first row
             datum = row[i].split("\t");  // only need key and context
              opt = document.createElement("option"); // like a new option data structure
              opt.value = datum[0]; // context_pk is tracked between lists
              context = datum[1]; // raw database string for context
              opt.text = context; // context string, gratuitous assign for code symmetry
              if (context != undefined) {
                chosen.appendChild(opt);  
                // remove the context from the "possible" list
                for (j = 0; j < len; j++ ) {
                  if (possible.options[j].text == context) {
                    possible.options[j] = null;
                    len--; // must recalc option list length
                  }
                }
              }
              else {
                opt.text = "no string for context #"+datum[0];
                chosen.appendChild(opt);
              }
            }
          }
        } 
        else {
          alert("displayWord() 5: xmlHttp.status != 200 or xmlHttp.status == "+xmlHttp.status);  
        }
      }
      catch( e ) {
        alert('displayWord() 6: Caught Exception in reference request: ' + e.number+"-"+e.name+"; "+e.description+"; "+e.message);
      }
    } 
    else {
      if (xmlHttp.readyState < 0 || xmlHttp.readyState > 4) {
        alert("displayWord() 7: Unidentified readyState from request: "+xmlHttp.readyState);
      }
    }
  }
  catch( e ) {
    alert('displayWord() 8: Caught Exception number: ' + e.number+"\nname: "+e.name+"\ndescription: "+e.description+"\nmessage: "+e.message);
    //alert('Server Status: '+xmlHttp.statusText+' : '+xmlHttp.readyState);
  }
  if( location.hostname == "www.kexsof.com" ) {
    _uacct = "UA-2492202-1";
    urchinTracker();
  }
};

/**
 * loadWord() - initiates ajax request to show data for a specific acronym
 */
function loadWord() { 
  var mylist = document.getElementById("acro");
  str = mylist.options[mylist.selectedIndex].value; // word_pk
//alert("loadWord() 0:\n arg="+str);
  xmlHttp = GetXmlHttpObject();
  if (!xmlHttp) {
    alert ("Browser does not support HTTP Request");
    return;
  }
  var url="acrymdbGetWord.php";
  var args = "q="+str+"";
  xmlHttp.onreadystatechange = function () {displayWord(xmlHttp); };
  xmlHttp.open("POST",url,true);
  xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); 
  xmlHttp.send(args);
};

/**
 * copyToList - used to copy from one option list to another
 */
function copyToList(from, to) {
  fromList = eval(document.getElementById(from));
  toList = eval(document.getElementById(to));
  var selected = false;
  len = fromList.options.length;
  for (i = 0; i < len; i++) {
    var current = fromList.options[i];
    if (current.selected) {
      selected = true;
      opt = document.createElement('option');
      opt.text = current.text;
      opt.value = current.value;
      toList.appendChild(opt);
      fromList.options[i] = null;
      // we just removed the ith option causing
      // all succeeding options were moved up (less) one
      // compared to their previous index,
      // so to continue we look at the same index again:
      len = fromList.options.length;
      i--;
    }
  }
  sortOptions(to);
  if (!selected) {
    alert ('You haven\'t selected any context!');
  }
};

/**
 * copyToField - copy from option list to input field for editing
 * For the purpose of editing the context strings:
 * item            stored in option property         stored in input property
 *                 stored in     stored in           stored in
 * db item         element id    option property     input property
 * ---------------------------------------------------------------------
 * context_pk                         value          tabIndex
 * context                            text           value
 *
 * context_pk is the primary key of the context entry
 * context is the context string
 * from/input is the option list
 * to/output is the input edit field
 */
function copyToField(from, to) {
//alert("copyToField() 0");
  input = eval(document.getElementById(from));
  output = eval(document.getElementById(to));
  var selindex = input.selectedIndex;
  if (!(selindex >= 0)) {
    alert ('You haven\'t selected a context from the possible list!');
    return;
  }
  // save the previous edit value
  if (output.value != '') {
    context = output.value;
    context_pk = output.tabIndex;
  }
  else {
    context = '';
    context_pk = '';
  }
  output.value = input.options[selindex].text;
  output.tabIndex = input.options[selindex].value;
  // if there's a previous edit, replace selected edit
  if (context != '') {
    // save some cpus, don't: opt = document.createElement('option');
    opt = document.createElement('option');
    input.options[selindex];
    opt.text = context;
    opt.value = context_pk;
    input.appendChild(opt);
  }
  input.options[selindex] = null;
};

function mod1copyToField(from, to) {
  copyToField(from, to);
  input = document.getElementById(to);
  output = document.getElementById("key");
  output.value  = input.tabIndex;
}

/**
 * copyFmField - copies edited context from input field to option list
 * For the purpose of editing the context strings:
 *                 stored in     stored in           stored in edit field
 * db item         element id    option property     input property
 * ---------------------------------------------------------------------
 * context_pk                         value          tabIndex
 * context                            text           value
 *
 * context_pk is the primary key of the context entry
 * context is the context string
 */
function copyFmField(from, to) {
//alert("copyFmField() 0");
  var arr = new Array(500);
  input = document.getElementById(from);
  output = document.getElementById(to);
  opt = document.createElement('option');
  opt.value = input.tabIndex;
  opt.text = input.value;
  output.appendChild(opt);
  sortOptions(to);
  //arr = output.options[];
  //output.options = arr.sort(text);
  input.value = null;
  input.tabIndex = null;
};

function mod1copyFmField(from, to) {
  copyFmField(from, to);
  key = document.getElementById("key");
  key.value  = '';
}

function allSelect() {
  List = document.forms[0].chosen;
  for (i=0;i<List.length;i++) {
    List.options[i].selected = true;
  }
};

/**
 * updateContext - intercepts ajax request from fixContext(): 
 * display update status and new primary key
 */
function updateContext(xmlHttp) { 
//alert("displayWord() 0: Server readyState: "+xmlHttp.readyState);
  var result;
  var row = new Array();
  var datum = new Array(15);
  var i;
  try {
    if (xmlHttp.readyState == 4) {
      try {
        if (xmlHttp.status == 200) {
          result = ctlPurge(xmlHttp.responseText);
          n = result.indexOf("<b>");
          if( n >= 0 && n <= 10 ) {
            alert(striptags(result));
          } 
          else {
            alert(result);
            context_pk = result;
            key = document.getElementById("key");
            key.value = context_pk;
            item = document.getElementById("contextitem");
            item.tabIndex = context_pk;
            return;
          }
        } 
        else {
          alert("update_acro() 5: xmlHttp.status != 200 or xmlHttp.status == "+xmlHttp.status);  
        }
      }
      catch( e ) {
        alert('update_acro() 6: Caught Exception in reference request: ' + e.number+"-"+e.name+"; "+e.description+"; "+e.message);
      }
    } 
    else {
      if (xmlHttp.readyState < 0 || xmlHttp.readyState > 4) {
        alert("update_acro() 7: Unidentified readyState from request: "+xmlHttp.readyState);
      }
    }
  }
  catch( e ) {
    alert('update_acro() 8: Caught Exception number: ' + e.number+"\nname: "+e.name+"\ndescription: "+e.description+"\nmessage: "+e.message);
    //alert('Server Status: '+xmlHttp.statusText+' : '+xmlHttp.readyState);
  }
  if( location.hostname == "www.kexsof.com" ) {
    _uacct = "UA-2492202-1";
    urchinTracker();
  }
};

/**
 * init_acrymdbctx() - clears out / initializes acrymdbctx.php edit page 
 */
function init_acrymdbctx() {
  // clear out any previous data
  prev = document.getElementById("key");
  prev.value = ''; // context_pk
  prev = document.getElementById("possible");
  prev.options.length = 0; // removes all options
  prev = document.getElementById("changeto");
  prev.options.length = 0; // removes all options
  prev = document.getElementById("contextitem");
  prev.value = ''; // source
  prev.tabIndex = '';
  loadContexts();
};

/**
 * fixContext()
 * IF the "Changed To:" (changeto) list is mpty, then either have a changeto
 * context string or a new context string.  If the context_pk is missing
 * then we have a new context entry in contextitem; otherwise, since the
 * changeto list is empty, the contextitem is an update to the context
 * string for context_pk
 * If the changeto list is non-empty, then the contextitem with context_pk
 * is to be "deleted" and the cross references are to be updated with
 * the initial instance of the old context_fk to be replaced with the
 * first item in the changeto list and for each item in the changeto list
 * after the first, a duplicate of the first cross-reference list will
 * be added but with the context_fk of the succeeding changeto item.
 * In other words, the old context will be split into several contexts.
 *
 * So, for the new context, an empty (null) key and the new string will be
 * handed off to the php code, and for the changeto context, a context_pk
 * primrary key and the updated string will be handed off to the php code.
 * For the "deleted" context string, two or more (key,context string) pairs
 * will be handed off with the first pair always the context to be "deleted".
 */
function fixContext() {
  item = document.getElementById("contextitem");
  if (item === null || item === false || item < 0) {
    alert("'contextitem' list is missing from the page.");
    return;
  }
  if (item.value === '') {
    alert("There's no context to add or update in the edit field.");
    return;
  }
  if (item.tabIndex === null) {
    item.tabIndex = '';
  }
  changeto = document.getElementById("changeto");
  if (changeto === null || changeto < 0 || changeto === false) {
    alert("'Change to' list is missing from the page.");
    return;
  }
  // end of checks
  era = document.getElementById('era');
  source = document.getElementById('source');
  // set up contents of edit field
  str = (item.tabIndex === 0 ? '' : item.tabIndex) + "`" + escape(item.value) + "`" + escape(era.value) + "`" + escape(source.value);
  // NOTE: each '\n' (newline) adds an EXTRA line to the total counted in php explode()
  changeto_length = changeto.length;
  if (changeto_length > 0) { // contextitem will be replace by these items
    for (i = 0; i < changeto_length; ++i) {
      // add changed to contexts here
      str += "`\n" + changeto.options[i].value + "`" + escape(changeto.options[i].text);
    }
  }
  xmlHttp = GetXmlHttpObject();
  if (xmlHttp == null) {
    alert ("Browser does not support HTTP Request");
    return;
  }
alert(str);
  var url="acrymdbctxUpdate.php";
  var args = "q="+str+"";
  xmlHttp.onreadystatechange = function () {updateContext(xmlHttp);};
  xmlHttp.open("POST",url,true);
  xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); 
  xmlHttp.send(args);
};

function sortOptions(select_id) {
//alert("sortOptions()-0: " + select_id + "\n");
  var theList = document.getElementById(select_id);
  var num = theList.length;
  if (num < 2) {
    return;
  }
  var mark = new Array(num); // an array to mark the objects already sorted
  var values = new Array(num);
  var texts = new Array(num);
  var ids = new Array(num);
  for (n = 0; n < num; n++) { 
    mark[n] = 1;
    values[n] = '';
    texts[n]  = '';
    ids[n]    = '';
  }
  for (n = 0; n < num; n++) { 
    for (i = 0; i < num; i++) { 
      if (mark[i] === 0) {
        continue;
      }
      if (texts[n] === '' ||
          theList.options[i].text.toLowerCase() < texts[n].toLowerCase()) {
        values[n] = theList.options[i].value;
        texts[n]  = theList.options[i].text;
        ids[n]    = theList.options[i].id;
        x = i;
      }
    }
    mark[x] = 0;
  }
  
  for (n = 0; n < num; n++) {
    opt = document.createElement('option');
    opt.value = values[n];
    opt.text  = texts[n];
    opt.id    = ids[n];
    theList.appendChild(opt);
    if (theList.length > 1) {
      theList.options[0] = null;
    }
  }
}


