//========== basicFcts.js: general Javascript basic functions ===========
//Created by "pm .=. phmartin dot info" on 2007-05-05
//See also resultsWinFcts.js which needs functions from this file 
//=======================================================================


//************************* Characters ************************************

//function /*Natural*/ asciiCodeOf(c) { return c.charCodeAt(0); }

/*boolean functions:
function isSpace(c) { return (!c ||(c==' ')||(c=='\n')||(c=='\r')||(c=='\t')||(c=='\f')); }
function isIn (str1,str2) { return (str2.indexOf(str1) >= 0); }
function isLower (str) { return (str==str.toLowerCase()); }
function isUpper (str) { return (str==str.toUpperCase()); }
*/


//************************* Numbers ************************************
//predefined: parseInt(str), parseFloat(str)

function isNotNumber (str)
{ var n= str.charAt(0);   return ((n<'0') || (n>'9'));
} //on Unix only:  isNaN(s)  or:  var n= parseFloat(str); return (n==NaN);


//************************* Strings ************************************
function isEmpty (str)  { return ((str=="") || (str==" ")); }

// function /*Number*/ regExprIn (/*String*/regularExpression, str)//->index/-1
// { var reg = new RegExp(regularExpression);  return reg.search(str);
// }//developer.netscape.com/docs/manuals/communicator/jsref/corea3.htm#1158210
// //or: developer.netscape.com/docs/manuals/communicator/jsguide4/expr.htm

// function /*String*/ selectedTextInDoc(doc)  //work with child window's doc?
// { if (doc.selection)  doc.selection; //for MSIE4
//   if (doc.getSelection) return doc.getSelection(); //if (navigator.appName=="Netscape")
//   return NULL;
// }

// function /*Natural*/ strspn (s1,s2,fromIndex) //as strspn() in string(3C):
//          //returns the length of the part of the string s1 after fromIndex
//          //        that consists entirely of characters from string s2
// { var l=fromIndex;  var ls1 = s1.length;
//   while ( (l < ls1) && (s2.indexOf(s1.charAt(l)) >= 0) )  l++;
//   return l;
// }

// function /*Natural*/ strcspn (s1,s2,fromIndex) //as strcspn() in string(3C):
//          //returns the length of the part of the string s1 after fromIndex
//          //        that consists entirely of characters not from string s2
// { var l=fromIndex;  var ls1 = s1.length;
//   while ( (l < ls1) && (s2.indexOf(s1.charAt(l)) < 0) )  l++;
//   return l;
// }

//************************* Arrays ************************************
// function /*bool*/ isInStrings (str, strArray)
// { for (i in strArray) { if (strArray[i]==str) return true; }
//   return false;
// }

//************************* SelectArrays **************************************
function /*String*/ selectedValueInSelectArray (selArray)
{ return selArray[selArray.selectedIndex].value; }

//function /*String*/ selectedTextInSelectArray (selArray)
//{ return selArray[selArray.selectedIndex].text; }


//************************* Traces and errors *****************************

// function /*bool*/ error (str) { return confirm(str+"."); } //error message

// function /*bool*/ tr () //trace function with a variable number of arguments
// { var str=""; //return confirm(slotsOfObject(tr.arguments));
//   var nbArg = tr.arguments.length;
//   for (var i=0; i<nbArg; i++)  str += tr.arguments[i] + ";\n";
//   return confirm(str);
// }

// function /*bool*/ trs (obj) //trace the object's slots and values
// { if (!obj) { alert("Empty object"); return true; }
//   confirm(obj); var str=""; //the next stuff generates an exception in Mozilla
//   for (var slot in obj) str += slot + ": " + obj[slot] + ";\n  ";
//   return confirm(str);
// }

// function /*bool*/ trr (obj) //recursively trace the object's slots and values
// { return confirm(recursContent(obj,""));
// }
// function /*String*/ recursContent(obj,indent)
// { var str=""; var s=String(obj);
//   if ((s.length > 1) && (s.charAt(0)=='['))
//   { for (var slot in obj)
//     { str+= indent + "(\n" + recursContent(slot,indent+"   ") + '\n' +
//             indent + ")\n";
//       var value= obj[slot];
//       if (!value)  str+=indent+"{undefined}\n";
//       else str+=indent+"{\n"+ recursContent(obj[slot],indent+"   ")+ '\n' +
//                 indent + "}\n";
//     }
//     return str;
//   }
//   else return indent+s;
// }

// function /*String*/ slotsOfObject (anObject)
// { var str="";
//   for (var slot in anObject)
//     str += slot + ": " + anObject[slot] + ";\n  ";
//   return str;
// }



//************************* Window's URL **********************************

// function /*void*/ reload() {  history.go(0); }

// function /*void*/ goThereInTime(url,milliseconds)
// { setTimeout("self.location.href="+url, milliseconds); }



//**************** Pop-up windows (see also resultsWinFcts.js) **********************
var WinNotOpenableMess="A new window could not be opened. May be you have too many"+
     " open windows (if so, try to close some of them and retry),"+
     " or you have prevented the use of pop-up windows (if so, please allow them),"+
     " or your browser has run out of memory (if so, restart your browser)";
var ThePopupWin= null;

/*bool*/function popupWin_open (url, winName)
    //2007/05: only called for the buttons of ../index.html and each result page
{ if (parent.menuFrame) { parent.menuFrame.location= url;  return true; }
  if (ThePopupWin) ThePopupWin.close();   //ThePopupWin -> window.ThePopupWin ??
  ThePopupWin= window.open(url,winName,
                           'width=690,height=315,resizable=yes,scrollbars=yes');
                         //'width=700,height=540,resizable=yes,scrollbars=yes'
  if (!ThePopupWin) { alert(WinNotOpenableMess); return false; }
     //JAVASCRIPT PERMISSION PB (on any platform) IF url is ABSOLUTE:
  ThePopupWin.resultsWin= window; //useful?
  ThePopupWin.opener= window;  //no need on Windows&Unix and
      //ThePopupWin's initialization scripts already executed
  ThePopupWin.focus();  //useful?
  return true;
  //var f= document.forms[0]; var v= f.categ.value;
  //if (v && (v!="")) ThePopupWin.categ=v;
  //"location=no,directories=no,copyhistory=no,status=no,menubar=no" or
  //"resizable=yes,width="+width+",height="+height+',toolbar=no,location=no'+
  //",directories=no,copyhistory=no,status=yes,menubar=yes,scrollbars=yes");
  //what is not mentioned is "no" by default 
}

//***************** Parameters (see also resultsWinFcts.js) *************************
var ParamsWin= self;   //var Params=null;

/*String*/function mkQueryUsingParams (url)  //used by index.html and _prefDisplay.html
{ if (!ParamsWin.Params) return url;
  var q= url;  var first= true;
  for (var prop in ParamsWin.Params)
    if (isNotNumber(prop) && (ParamsWin.Params[prop]!=null))
    { var v= ParamsWin.Params[prop];
      if (first) { first=false; q+='?'+prop+'='+((v===true)?'':escape(v)); }
      else q+='&'+prop+'='+((v===true)?'':escape(v));
    }                      //"===" necessary since with "=="  "1" is true
  return q;   //alert('q='+q);
}//exemple of call:  ResultsWin.location= mkQueryUsingParams(URLprocessor);




//************************* Cookies **************************************************

/*bool*/function setParamsWithCookies ()  //ParamsWin.Params declared and initialized before
{ var s= getCookie("w_HTMLchoice");       if (s=="") return false;
  //  alert("setParamsWithCookies()"); //alert(htmlChoice); alert(document.cookie);
  //  ParamsWin.Params.frameChoice= getCookie("w_frameChoice");  + optionButtons????
  if (s=="0"||s=="1")/*was: s!="2"*/ ParamsWin.Params.withHTML= s; 
  else if (s!="2") ParamsWin.Params.withMenuOnCategories= s;

  s=getCookie("w_formalnessChoice");      if (s!="0") ParamsWin.Params.formal= true;
  s=getCookie("w_explanationChoice");     if (s!="0") ParamsWin.Params.explanations= true;
                             //pm: was: ParamsWin.Params.explanations= (s!="0")?true:null;
  s=getCookie("w_showMetadataChoice");    if (s!="2") ParamsWin.Params.metadata= s;
  s=getCookie("w_formatChoice");   if ((s!="")&&(s!="null")) ParamsWin.Params.format= s;
  s=getCookie("w_ontologyChoice"); if ((s!="")&&(s!="null")) ParamsWin.Params.ontology= s;
  s=getCookie("w_abbreviationChoice");    if (s!="0") ParamsWin.Params.linkAbbreviations=true;
  s=getCookie("w_listAssertionsChoice");  if (s=="0") ParamsWin.Params.noStatement= true;
  s=getCookie("w_showHiddenAnnotsChoice");if (s!="0") ParamsWin.Params.hiddenAnnot= true;
  s=getCookie("w_showAltKeysChoice");     if (s!="0") ParamsWin.Params.altKeys= true;
  s=getCookie("w_dotChoice");             if (s!="0") ParamsWin.Params.noDot= true;
  s=getCookie("w_creatorInput");          if (s!="")  ParamsWin.Params.creator= s;
  s=getCookie("w_nonCreatorInput");       if (s!="")  ParamsWin.Params.nonCreator= s;
  return true;
}

function registerCookie (name, value) //http://www.quirksmode.org/js/cookies.html
{ var today= new Date();  var expirationDate= new Date();
  expirationDate.setTime(today.getTime()+1000*60*60*24*365);//in a year
                  //to remove: replace '+' above by '-' (so: past date)
  document.cookie= name+"="+escape(value) +
                   "; expires=" + expirationDate.toGMTString() + "; path=/";
  //"path=/": the cookie will be in the document.cookie of any page of the site
}

function setCookie (name, value, /*optional*/expirationDate) //not called
{ if (expirationDate)
    document.cookie= name+"="+escape(value) +
                     "; expires=" + expirationDate.toGMTString();
  else document.cookie= name + "=" + escape(value);
} //escape() encodes in hexadecimal characters such as ';', ',' and spaces

   //this fct uses indexOf(); this is dangerous if "name+'='" is in a value
/*String*/ function getCookie (name)   //a version using a "while" is in categUpdate.html
{ if (document.cookie.length <= 0) return ""; //no cookie
  var cookieBeginning= document.cookie.indexOf(name+"=");
  if (cookieBeginning == -1) return ""; //no such cookie
  var valueBeginning= cookieBeginning + name.length + 1;
  var valueEnd= document.cookie.indexOf(";",valueBeginning);
  if (valueEnd == -1) valueEnd= document.cookie.length;
  return unescape(document.cookie.substring(valueBeginning,valueEnd));
}



//********************** Cascading Menus ******************************************

function makeCascadingMenuForCategories (/*bool*/ isFormal)
{ makeCascadingMenu("categoryMenu",
    "Make this category the first node","this is a placeholder for a url",
    "Expand node here","displayGotoMenuForCategory() will update this placeholder too");
  makeCascadingMenu("unexpandCategoryMenu",
    "Make this category the first node","this is a placeholder for a url",
    "Unexpand node here","displayGotoMenuForCategory() will update this placeholder too");
  makeCascadingMenu("linkMenu", (isFormal)?
     "Show all and only the categories (un-)directly accessible via this link from this type":
     "Insert all the categories directly accessible via this link here",
    "this is a placeholder for a url", (isFormal)?
      "Insert all the categories directly accessible via this link here":
      "Show all and only the categories (un-)directly accessible via this link from this type",  
    "displayGotoMenuForLink() will update this placeholder too");
}

//this comes from http://www.crimecommission.gov.au/scripts/acc_internet_script.js
var CursorInMenu=false;  var LastMenuId=0;

//based on findPos*, by ppk (http://www.quirksmode.org/js/findpos.html):
function findPosX (obj) 
{ var curLeft= 0;
  if (typeof obj.offsetParent != "undefined") //was: (obj.offsetParent)
    do { curLeft += obj.offsetLeft; } while (obj = obj.offsetParent);
  else if (typeof obj.x != "undefined")  //was:  (obj.x)
    curLeft+= obj.x;
  return curLeft;
}

function findPosY (obj)
{ var curLeft= 0;
  if (typeof obj.offsetParent != "undefined") //was: (obj.offsetParent)
  { curLeft= obj.offsetHeight
    do { curLeft += obj.offsetTop; } while (obj = obj.offsetParent);
  }
  else if (typeof obj.y != "undefined")  //was:  (obj.y)
  { curLeft= obj.height
    curLeft+= obj.y;
  }
  return curLeft;
}

function eraseMenu (menuId) //called by displayMenu and hideMenuAfterTimeout
{ if (CursorInMenu && LastMenuId==menuId) return;
  getObjectById(menuId).style.visibility="hidden";
  //getObjectById(menuId+"_caller").style.backgroundColor="white";
}

function highlightMenuItem (menuId, itemId) //onmouseover not triggered, why?
{ CursorInMenu=true;  LastMenuId=menuId; //if (!document.getElementById) return;
  getObjectById(itemId).style.backgroundColor="silver";
}

function unHighlightMenuItem (menuId, itemId) //e.g. unHighlightMenuItem("menu1","a1")
{ hideMenuAfterTimeout(menuId); // if (!document.getElementById) return;
  getObjectById(itemId).style.backgroundColor="white";
}

function hideMenuAfterTimeout (menuId)
    //caller: unHighlightMenuItem + onmouseout on menuCaller
{ CursorInMenu=false;   window.setTimeout("eraseMenu('"+menuId+"');",500);
}

function makeCascadingMenu (menuId)
{ var nbArgs= arguments.length; // first cell url, first cell label, 
                                // second cell url, second cell label,
                                // ...
  var nbCell=0;
  if (nbArgs <= 2)
  { alert("internal error: expected arguments: menuId, first cell url, first cell label,...");
    return;
  }
  document.write("<div id='"+menuId+"' style='position: absolute;"+
                 "   background-color: white; visibility: hidden;'>");
  document.write("  <table border='1' cellpadding='3' cellspacing='0'>");
  for (var i=1; i < nbArgs; i+=2)
  { nbCell++;
    document.write("  <tr><td id='"+menuId+"_cell"+nbCell+"' onmouseover=\""  
      + "   highlightMenuItem('"+menuId+"','"+menuId+"_cell"+nbCell+"');\""
      + "onmouseout=\"unHighlightMenuItem('"+menuId+"','"+menuId+"_cell"+nbCell+"');\">");
    document.write("<a id='"+menuId+"_href"+nbCell+"' href='"+arguments[i+1]+"'>" 
      + arguments[i]+"</a></td></tr>");
  }
  document.write("  </table></div>");
}

function displayGotoMenuForLink (obj,menuId,href,formal)
{ if (formal)
  { getObjectById(menuId+"_href1").href= href + "&blockBasedRecursPrint";
    getObjectById(menuId+"_href2").href= href;
  }
  else
  { getObjectById(menuId+"_href2").href= href+"&blockBasedRecursPrint";
    getObjectById(menuId+"_href1").href= href;
  }
  var box= getObjectById(menuId);   box.style.visibility="visible";
      box.style.backgroundColor= "white";   //box.style.width="250px";
  box.style.left= findPosX(obj);
  box.style.top= findPosY(obj);
}

function displayGotoMenuForCategory (obj,href,href2,menuId)
{ if (LastMenuId) eraseMenu(LastMenuId); 
  var nbCategs=2; var o1=getObjectById(menuId+"_href1");
  if (!o1) { alert("No menu named "+menuId+"_href1"); return; }
  o1.href=href;  var o2=getObjectById(menuId+"_href2");
  if (!o2) { alert("No menu named "+menuId+"_href1"); return; }
  o2.href=document.location.href+href2; 

  CursorInMenu=true;
  var box= getObjectById(menuId);   box.style.visibility="visible";
      box.style.backgroundColor="white";   
  box.style.left= findPosX(obj);
  box.style.top=  findPosY(obj);
}

/* lexical version for menu
function displayGotoMenuForCategory (obj,href,menuId,srcCateg,linkFromSrcCateg,unexpandCateg)
{ if (LastMenuId) eraseMenu(LastMenuId); 
  var afterCateg= (href.split("categ="))[1];
  var categValue= (afterCateg.split("&"))[0];
  var nbCategs=2;
  while (document.location.href.indexOf('categ'+nbCategs+'=')>=0) nbCategs++;

  var newParameters="&categ"+nbCategs+"="+categValue+"&srcCateg"+nbCategs+"="+srcCateg
                   +"&linkFromSrcCateg"+nbCategs+"="+linkFromSrcCateg;

  getObjectById(menuId+"_href1").href=href;
  if (!unexpandCateg)
  { getObjectById(menuId+"_href2").href=document.location+newParameters; }
  else
  { for(i=2; i<nbCategs; i++)
    { var param= "&categ"+i+"="+categValue+"&srcCateg"+i+"="+srcCateg+
                 "&linkFromSrcCateg"+i+"="+linkFromSrcCateg;
      alert(param);
      if (document.location.href.indexOf(param)>=0)
      { getObjectById(menuId+"_href2").href= document.location.substring(0,indexOf(param))+
                                             document.location.substring(indexOf(param)+
                                             param.length);
      }
    }
  }

  CursorInMenu=true;
  var box= getObjectById(menuId);   box.style.visibility="visible";
      box.style.backgroundColor="white";   //box.style.width="250px";
  box.style.left= findPosX(obj);
  box.style.top=  findPosY(obj);
}*/

function getObjectById (id) 
{ if (document.getElementById) return document.getElementById(id);
  else if (document.all) return document.all(id); //for IE4
  else if (document.layers) return eval('document.'+id); //Netscape 4
  else return;
}



/* Not yet used:
//************************* Right Click Menus *****************************************
// to do: add the possibility to go to the traditional context menu

//document.oncontextmenu is null here
document.oncontextmenu= displayRightClickMenu;  //right-click event 
document.onclick= hidemenu; //left-click event
var Box=null;
var SecondOptionSelected=false;

function displayRightClickMenu (e)
{ if (!SecondOptionSelected)
  { //display menu:
    Box= getObjectById("menu");   
    Box.style.left= Xmouse(e); Box.style.top=  Ymouse(e); Box.style.visibility="visible";
    stopPropagation(e); return false; //-> stop showing traditional browser right-click menu
  } 
  if (false)//else 
  { document.oncontextmenu=displayRightClickMenu; alert(1);SecondOptionSelected=false; return true; }
}

function executeRightClickEvent ()
{ var fireOnThis = document;
  SecondOptionSelected=true;
  document.oncontextmenu=null;
  if (document.createEvent) 
  { var evObj = document.createEvent('mouseEvents');
    evObj.initEvent('contextmenu',true,false);
    fireOnThis.dispatchEvent(evObj);
  } 
  else if (document.createEventObject) 
  { fireOnThis.fireEvent('oncontextmenu'); }
}

function stopPropagation (e)
{ if (window.event && window.event.cancelBubble)
    window.event.cancelBubble= true;
  if (e && e.stopPropagation) e.stopPropagation();
}

function hidemenu (e)
{ if (Box) Box.style.visibility="hidden";
  Box=null;
}

function Xmouse (e)
{ var event=typeof window.event!='undefined'?window.event:e;
  var Xfen, scrollL;
  if(document.documentElement.scrollLeft!=0) scrollL=document.documentElement.scrollLeft;
  else if(document.body.scrollLeft!=0) scrollL=document.body.scrollLeft;
  else scrollL=0;	
  Xfen=event.clientX;
  return Xfen+scrollL;
}

function Ymouse (e)
{ var event=typeof window.event!='undefined'?window.event:e;
  var Yfen, scrollT;
  if(document.documentElement.scrollTop!=0) scrollT=document.documentElement.scrollTop;
  else if(document.body.scrollTop!=0) scrollT=document.body.scrollTop;
  else scrollT=0;
  Yfen=event.clientY;
  return Yfen+scrollT;	
}

function highlightMenu (menu)
{ menu.style.backgroundColor='silver'; }

function unhighlightMenu (menu)
{ menu.style.backgroundColor='white'; }

function makeRightClickMenu ()
{ document.write(
     "<div id='menu' style='position: absolute; background-color: white; visibility: hidden;'>"
    +"<table border='2' cellpadding='3' cellspacing='0'>"
    +"  <tr> <td id='options' onclick='' onmouseover='highlightMenu(this);'" 
    +"           onmouseout='unhighlightMenu(this);'><b>Change the default formatting options</b></td> </tr>"
    +"  <tr> <td id='traditional' onclick='executeRightClickEvent();' onmouseover='highlightMenu(this);'"
    +"           onmouseout='unhighlightMenu(this);'><b>Your traditional browser right-click menu</b></td> </tr>"
    +"  <tr> <td id='reload' onclick='location.reload();' onmouseover='highlightMenu(this);'" 
    +"           onmouseout='unhighlightMenu(this);'>&nbsp; &nbsp; Reload</td> </tr>"
    +"  <tr> <td id='back' onclick='history.back();' onmouseover='highlightMenu(this);'" 
    +"           onmouseout='unhighlightMenu(this);'>&nbsp; &nbsp; Back</td> </tr>"
    +"  <tr> <td id='forward' onclick='history.forward();' onmouseover='highlightMenu(this);'" 
    +"           onmouseout='unhighlightMenu(this);'>&nbsp; &nbsp; Forward</td> </tr>"
    +"</table>"
    +"</div>");
}

*/


//************************* Other *****************************************

