//alert('desc');
   var first = true;

   var dSpace = '&nbsp;&nbsp;&nbsp;&nbsp;';
   var dLine = '&mdash;';
   var dDots = '&nbsp;.&nbsp;.'
   var descendantNav = new Object();
         descendantNav.curD = null;
         descendantNav.curId = 'Dxx';


   function dToken(ThisIndiv, BaseId, GenLevel, LineMap, IsLastChild, OtherParentIndex) {
      this.localRoot = ThisIndiv;
      this.baseId = BaseId;
      this.genLevel = GenLevel;
      this.lineMap = LineMap;
      this.isLastChild = IsLastChild;
      this.otherParentIndex = OtherParentIndex;
      }


   function xiChild(iElemPtr) {
      this.iElem = iElemPtr;
      }
   xiChild.prototype.bDateCompareTo = function(b) {
      var aDate = this.iElem.getAttribute("bDate");
      var bDate = b.iElem.getAttribute("bDate");
      return (aDate == bDate)?0:((aDate > bDate)?1:-1);
      }
   xiChild.bDateCompare = function(a, b) { return a.bDateCompareTo(b); }

   function iFamily(iElemPtr, childs) {
      this.iElem = iElemPtr;
      this.children = childs;
      }
   iFamily.prototype.sortDateCompareTo = function(b)  {
      var aSort = this.iElem.getAttribute("partnerSortDate");
      var bSort = b.iElem.getAttribute("partnerSortDate");
      if (aSort == bSort)  {
        return (this.iElem.partnerRef > b.iElem.partnerRef)?1:-1;
        }
      else  { 
        return (aSort == bSort)?0:((aSort > bSort)?1:-1);
        }
      }
   iFamily.sortDateCompare = function(a, b) { return a.sortDateCompareTo(b); }



   function collectDFamily(thisIndiv)  {
       var partners = thisIndiv.getElementsByTagName("partner");
       var family = new Array();  
       if (partners.length > 0)  {
         for (var i=0; i < partners.length; i++)  {

           var thisSpouse = null;
           if (partners[i].getAttribute("partnerRef"))   {
              thisSpouse = iIndex[partners[i].getAttribute("partnerRef")].iElem;
              }

           var myPair = pIndex[partners[i].getAttribute("partnerPairRef")];
           var progeny = myPair.getElementsByTagName("progeny");
           var children = new Array();
           if (progeny.length > 0)  {
             for (var j=0; j < progeny.length; j++)  {
                children.push(new xiChild(iIndex[progeny[j].getAttribute("childRef")].iElem));
                }
             children.sort(xiChild.bDateCompare);
             
             }         // ********* if (progeny.length > 0)
           family.push(new iFamily(thisSpouse, children));

           }        // ********* for (var i=0; i < partners.length; i++)
        }
        family.sort(iFamily.sortDateCompare);
        return family;  
      }

  
   function displayPrimary(thisToken)  {
     var thisHTML = ''; 
     var thisIndiv = thisToken.localRoot;
     var thisLineMap = thisToken.lineMap;
     var thisParentId = thisToken.baseId.substring(0, thisToken.baseId.length - 2);
     var preHTML = dSpace + '&nbsp;';
     for (var i = 0; i < (thisToken.genLevel + 1); i++)  {
        preHTML += dSpace;
        if ((thisLineMap & 1) == 1) { 
           preHTML += '|'; 
           }
        else {
           preHTML += '&nbsp;';
           } 
        thisLineMap = (thisLineMap >>> 1);
        }
     thisHTML += '<SPAN class = "mono">' + preHTML + '</SPAN><BR> ';
     thisHTML += '<SPAN class = "mono">' + preHTML.substring(0, preHTML.length - 1) + '+' + dLine + '</SPAN>' +
                  '<SPAN id = "' + thisToken.baseId  + '" class = "boxD">';
     thisHTML += linkedName(thisIndiv, false) + '</SPAN> ';
     thisHTML += '<SPAN id = "' + thisToken.baseId + 'P" class = "pseudoAttribute">' + thisParentId + 's' + 
                   String(thisToken.otherParentIndex) + '</SPAN> <BR>';
     return thisHTML;
     }

   function displaySpouse(thisToken, spouseElem, spouseIndex, spouseFirstChild)  {
     var thisHTML = '';
     var thisLineMap = thisToken.lineMap;
     var preHTML = dSpace + '&nbsp;';
     for (var i = 0; i < (thisToken.genLevel + 1); i++)  {
        preHTML += dSpace;
        if ((thisLineMap & 1) == 1) { 
           preHTML += '|'; 
           }
        else  { 
           preHTML += '&nbsp;'; 
           }
        thisLineMap = thisLineMap >>> 1;
        }
     thisHTML += '<SPAN class = "mono">' + preHTML + '</SPAN><BR> ';
     thisHTML += '<SPAN class = "mono">' + preHTML + dDots + ' </SPAN>' +
                   '<SPAN id = "' + thisToken.baseId + 's' + String(spouseIndex) + '" class = "boxDS">';

     if (spouseElem)  {
        thisHTML += linkedName(spouseElem, true) + '</SPAN>';
        }
     else   {
       thisHTML += '[spouse: not available]</SPAN>';
       }

     thisHTML += '<SPAN class = "pseudoAttribute">' + spouseFirstChild + '</SPAN> <BR>';
     return thisHTML;
     } 



   function iterateD(myToken)  {
      var thisToken = myToken;
      var dThisHTML = '';
      var thisIndiv = thisToken.localRoot;
      var thisFamily = collectDFamily(thisIndiv);
      dThisHTML += displayPrimary(thisToken);
      var maxChildCount = 0;
      for (var i = 0; i < thisFamily.length; i++) {
         maxChildCount += thisFamily[i].children.length;
         }
      var childCount = 0;
      var thisMapBit = ((thisFamily.length > 0)?1:0) << (thisToken.genLevel + 1);
      thisToken.lineMap = thisToken.lineMap | thisMapBit;
      for (var i = 0; i < thisFamily.length; i++)  {
         thisSpouse = thisFamily[i].iElem;
         var spouseFirstChild = (thisFamily[i].children.length == 0)?-1:childCount;
         dThisHTML += displaySpouse(thisToken, thisSpouse, i, spouseFirstChild);
         var childGenLevel = thisToken.genLevel + 1;
         if ((thisToken.isLastChild) && (i == (thisFamily.length - 1)))  {
            childLineMap = thisToken.lineMap ^ (1 << (myToken.genLevel));
            }
         else {
            childLineMap = thisToken.lineMap;
            }
         for (var j = 0; j < thisFamily[i].children.length; j++)  {
            var thisChildIndex = String(childCount + j);
            if (thisChildIndex.length < 2) thisChildIndex = '0' + thisChildIndex;
            var childId = thisToken.baseId + thisChildIndex;
            var childElem = thisFamily[i].children[j].iElem;
            var childIsLastChild = (j == thisFamily[i].children.length - 1);
            var childToken = new dToken(childElem, childId, childGenLevel, childLineMap, childIsLastChild, i);
            dThisHTML += iterateD(childToken);
            }
         childCount = childCount + thisFamily[i].children.length;
         }
     return dThisHTML;
     }          

/*
 *  ************* dNav support functions **************
 */

   function elemIdDnav(x)
   { 
     if (x) { 
        var newId = x.getAttribute('id');
        return newId; 
        }
     else { return descendantNav.curId; }
   }

   function stubDnav()
   {
     var work = descendantNav.curId;
     var len = work.length;
     return (work.substr(0, len - 2));
   }

   function extDnav()
   {
     var work = descendantNav.curId;
     var len = work.length;
     return (work.substring(len - 2));
   }

   function atSpouseDnav()
   {
     if (atRootDnav()) { return false; }
     var work = descendantNav.curId;
     var len = work.length;
     var result = (work.charAt(len-2) == 's');
     return (result);
   }

   function atRootDnav()
   {  return (descendantNav.curId == 'D00'); }  

   function parentElemDnav()
   {  
     if (atRootDnav() || atSpouseDnav()) { return null; }
     var work = descendantNav.curId;
     var len = work.length;
     return (document.getElementById(work.substr(0, len-2)));
   }

   function spouseElemDnav()
   {
     var targetId;
     var work = descendantNav.curId;
     var len = work.length;
     if (atSpouseDnav()) {
       targetId = work.substr(0, len-2);
       }
     else {
       targetId = work + 's0';
       }
     return (document.getElementById(targetId)); 
   }

   function nextCoSpouseElemDnav()
   {
     if (!atSpouseDnav()) { return null }
     var work = descendantNav.curId;
     var len = work.length;
     var thisId = stubDnav() + 's' + String(Number(work.charAt(len-1)) + 1);
     return (document.getElementById(thisId));
   }

   function prevCoSpouseElemDnav()
   {
     if (!atSpouseDnav() || (extDnav() == 'a')) { return null }
     var work = descendantNav.curId;
     var len = work.length;
     var thisId = stubDnav() + 's' + String(Number(work.charAt(len-1)) - 1);
     return (document.getElementById(thisId));
   }

   function nextSibElemDnav()
   {
     if (atRootDnav() || atSpouseDnav()) { return null; }
     var len = descendantNav.curId.length;
     var sibNum = String(Number(descendantNav.curId.substring(len-2)) + 1);
     while (sibNum.length < 2) { sibNum = '0' + sibNum; }
     var thisId = (stubDnav() + sibNum);
     var newElem = document.getElementById(thisId);
     return (newElem);
   }

   function prevSibElemDnav()
   {
     if (atRootDnav() || atSpouseDnav() || (extDnav() == 'A')) { return null; }
     var len = descendantNav.curId.length;
     var sibNum = String(Number(descendantNav.curId.substring(len-2)) - 1);
     while (sibNum.length < 2) { sibNum = '0' + sibNum; }
     var thisId = (stubDnav() + sibNum);
     return (document.getElementById(thisId));
   }

   function childElemDnav()
   {
     var work = descendantNav.curId;
     var len = work.length;
     var thatId;
     if (atSpouseDnav())
     { thatId = descendantNav.curD.nextSibling.innerHTML; }
     else
     { thatId = work + '00'; }
     return (document.getElementById(thatId));
   }

   function oParentElemDnav()
   {
     if (atSpouseDnav() || atRootDnav()) { return null; }
     var pseudo = document.getElementById(descendantNav.curId + 'P');
     if (!(pseudo)) { return null; }
     var thatId = pseudo.innerHTML;
     if (thatId != '*') { 
        oParentElem = document.getElementById(thatId);
        return (oParentElem); 
        }
     else { return null; }
   }

   function resetIdDnav(newId)
   {
     if (descendantNav.curD) { descendantNav.curD.style.backgroundColor = dBackgroundColor; }
     descendantNav.curId = newId;
     descendantNav.curD = document.getElementById(newId);
     resetDnav();
   }

   function resetElemDnav(newElem)
   {
     if (newElem)  {
       if (descendantNav.curD) { descendantNav.curD.style.backgroundColor = dBackgroundColor; }
       descendantNav.curD = newElem;
       descendantNav.curId = elemIdDnav(newElem);
       resetDnav();
     }
   }

   function resetDnav()
   {
     descendantNav.curD.style.backgroundColor = atSpouseDnav()?dSelectColorSpouse:dSelectColor;
     document.getElementById('dRefocusButton').disabled = atRootDnav();
     document.getElementById('dRootButton').disabled = atRootDnav();
     document.getElementById('dChildButton').disabled = !(childElemDnav());
     document.getElementById('dParentButton').disabled = !(parentElemDnav());
     document.getElementById('dOtherParentButton').disabled = !(oParentElemDnav());
     document.getElementById('dSpouseButton').disabled = !(spouseElemDnav());
     document.getElementById('dSibNextButton').disabled = !(nextSibElemDnav());
     document.getElementById('dSibPrevButton').disabled = !(prevSibElemDnav());
     document.getElementById('dCoSpouseNextButton').disabled = !(nextCoSpouseElemDnav());
     document.getElementById('dCoSpousePrevButton').disabled = !(prevCoSpouseElemDnav());
     descendantNav.curD.scrollIntoView();
     var dCount = (descendantNav.curId.length - 1)/2;
     if (atSpouseDnav()) { dCount = dCount - 1; }
     var gc;
     switch (dCount)
     {
       case 1:
        gc = 'self';
        break;
       case 2:
        gc = 'child';
        break;
       case 3:
        gc = 'gchild';
        break
       case 4:
        gc = 'Ggchild';
        break;
       default:
        gc = '(' + String(dCount-3) + ')Ggchild';
        break;
     }
     if (atSpouseDnav()) { gc = 'sp-' + gc; }
     document.getElementById('dNavRel').innerHTML = gc;

//     var reFocuser = document.getElementById('dNavRel');
//     reFocuser.style.visibility = 'visible';
//     reFocuser.focus();

   }

   function refocusDnav() {
      descendantNav.curD.firstChild.onclick();    
      }

   function rootDnav()
   { resetIdDnav('D00'); }

   function childDnav()
   {  resetElemDnav(childElemDnav()); }

   function parentDnav()
   {  resetElemDnav(parentElemDnav()); }
   
   function spouseDnav()  {
      resetElemDnav(spouseElemDnav()); 
      }

   function sibNextDnav()
   {  resetElemDnav(nextSibElemDnav()); }

   function sibPrevDnav() {
      resetElemDnav(prevSibElemDnav()); 
      }

   function coSpouseNextDnav()
   {  resetElemDnav(nextCoSpouseElemDnav()); }

   function coSpousePrevDnav()
   {  resetElemDnav(prevCoSpouseElemDnav()); }

   function oParentDnav()
   {  resetElemDnav(oParentElemDnav()); }


 //  ******************************************************

   function buildDesc() {
      var thisV = mySelectG.value;
      var thisRoot = iIndex[thisV].iElem;
      var htmlBlock = '';
      var rootMap = 1;
      var rootToken = new dToken(thisRoot, 'D00', 0, rootMap, true, 99);
      htmlBlock += iterateD(rootToken, htmlBlock) + '<BR>&nbsp;';
//document.getElementById('asis').innerHTML = html2txt(htmlBlock);
      return htmlBlock;
     }

