// DHTMLapi.js
//
// General utilities for DHTML
//
// To initialize, call initDHTMLapi();
//
// Author: Mike Bergsma
//
// Modifications:
//
//    $Log: DHTMLapi.js,v $
//    Revision 1.31  2008-12-28 00:24:02  bergsma
//    no message
//
//    Revision 1.30  2008-12-04 01:08:01  bergsma
//    *** empty log message ***
//
//    Revision 1.28  2008-06-10 06:12:29  bergsma
//    *** empty log message ***
//
//    Revision 1.26  2008-06-09 18:30:05  bergsma
//    no message
//
//    Revision 1.25  2008-06-08 21:23:25  bergsma
//    no message
//
//    Revision 1.24  2008-06-06 00:46:45  bergsma
//    no message
//
//    Revision 1.23  2008-06-01 16:58:05  bergsma
//    no message
//
//    Revision 1.22  2008-05-24 18:51:57  bergsma
//    no message
//
//    Revision 1.20  2008-05-15 18:15:42  bergsma
//    *** empty log message ***
//
//    Revision 1.19  2008-05-13 00:04:57  bergsma
//    Added functions from util,js
//
//    Revision 1.18  2008-05-09 18:27:25  bergsma
//    Missing initialization of debugLevel
//
//    Revision 1.17  2008-04-25 17:51:29  bergsma
//    no message
//
//

// Global variables
var isCSS, isW3C, isIE4, isNN4;
var detect = navigator.userAgent.toLowerCase();
var OS,browser,version,total,thestring;
var popper;
var popupnum ;
var debugLevel = 0 ;

// initialize upon load to let all browsers establish content objects
function initDHTMLapi() {

  initEnvironment()

  if ( document.images ) {

    isCSS = (document.body && document.body.style) ? true : false;
    isW3C = (isCSS && document.getElementById) ? true : false;
    isIE4 = (isCSS && document.all) ? true : false;
    isNN4 = (document.layers) ? true : false;
    isIE6CSS = (document.compatMode && document.compatMode.indexOf("CSS1") >= 0) ? true : false;
  }
}

function initEnvironment()
{
  if (checkIt('konqueror'))
  {
	browser = "Konqueror";
	OS = "Linux";
  }
  else if (checkIt('safari')) browser = "Safari"
  else if (checkIt('omniweb')) browser = "OmniWeb"
  else if (checkIt('opera')) browser = "Opera"
  else if (checkIt('webtv')) browser = "WebTV";
  else if (checkIt('icab')) browser = "iCab"
  else if (checkIt('msie')) browser = "Internet Explorer"
  else if (!checkIt('compatible'))
  {
	browser = "Netscape Navigator"
	version = detect.charAt(8);
  }
  else browser = "An unknown browser";

  if (!version) version = detect.charAt(place + thestring.length);

  if (!OS)
  {
	if (checkIt('linux')) OS = "Linux";
	else if (checkIt('x11')) OS = "Unix";
	else if (checkIt('mac')) OS = "Mac"
	else if (checkIt('win')) OS = "Windows"
	else OS = "an unknown operating system";
  }
}

function checkIt(string)
{
	place = detect.indexOf(string) + 1;
	thestring = string;
	return place;
}


// Seek nested NN4 layer from string name
function seekLayer(doc, name) {
    var theObj;
    for (var i = 0; i < doc.layers.length; i++) {
        if (doc.layers[i].name == name) {
            theObj = doc.layers[i];
            break;
        }
        // dive into nested layers if necessary
        if (doc.layers[i].document.layers.length > 0) {
            theObj = seekLayer(document.layers[i].document, name);
        }
    }
    return theObj;
}

// Convert object name string or object reference
// into a valid element object reference
function getRawObject(obj) {
    var theObj;
    if (typeof obj == "string") {
        if (isW3C) {
            theObj = document.getElementById(obj);
        } else if (isIE4) {
            theObj = document.all(obj);
        } else if (isNN4) {
            theObj = seekLayer(document, obj);
        }
    } else {
        // pass through object reference
        theObj = obj;
    }
    return theObj;
}

// Convert object name string or object reference
// into a valid style (or NN4 layer) reference
function getObject(obj) {
    var theObj = getRawObject(obj);
    if (theObj && isCSS) {
        theObj = theObj.style;
    }
    return theObj;
}


function getEventTarget(e) {

 	var targ;
	var lEvt;
	if (!e ) {
	  e = window.event;
	}
	if ( e.target ) {
	  targ = e.target;
	}
    	else if ( e.srcElement ) {
	  targ = e.srcElement;
  	}
	if ( targ.nodeType == 3 ) {
	  targ = targ.parentNode; // defeat Safari bug
	}
  	return targ;  
}


// Position an object at a specific pixel coordinate
function shiftTo(obj, x, y) {
    var theObj = getObject(obj);
    if (theObj) {
        if (isCSS) {
            // equalize incorrect numeric value type
            var units = (typeof theObj.left == "string") ? "px" : 0 
            theObj.left = x + units;
            theObj.top = y + units;
        } else if (isNN4) {
            theObj.moveTo(x,y)
        }
    }
}

// Move an object by x and/or y pixels
function shiftBy(obj, deltaX, deltaY) {
    var theObj = getObject(obj);
    if (theObj) {
        if (isCSS) {
            // equalize incorrect numeric value type
            var units = (typeof theObj.left == "string") ? "px" : 0 
            theObj.left = getObjectLeft(obj) + deltaX + units;
            theObj.top = getObjectTop(obj) + deltaY + units;
        } else if (isNN4) {
            theObj.moveBy(deltaX, deltaY);
        }
    }
}

// Set the z-order of an object
function setZIndex(obj, zOrder) {
    var theObj = getObject(obj);
    if (theObj) {
        theObj.zIndex = zOrder;
    }
}


// Sets an object to have "<some>" positioning
function setPosn(obj, posn) {
    var theObj = getObject(obj);
    if (theObj) {
        theObj.position = posn ;
    }
}

// Set the background color of an object
function setBGColor(obj, color) {
    var theObj = getObject(obj);
    if (theObj) {
        if (isNN4) {
            theObj.bgColor = color;
        } else if (isCSS) {
            theObj.backgroundColor = color;
        }
    }
}

// Set the visibility of an object to visible
function show(obj) {
    var theObj = getObject(obj);
    if (theObj) {
        theObj.visibility = "visible";
    }
}

// Set the visibility of an object to hidden
function hide(obj) {
    var theObj = getObject(obj);
    if (theObj) {
        theObj.visibility = "hidden";
    }
}

function hideElement(pNd){
    var node = getRawObject(pNd);
    if (node) {node.style.display = "none"};
  return node;
}

function showElement(pNd){
    var node = getRawObject(pNd);
    if (node) {node.style.display = ""};
  return node;
}

function findPosX(obj) {

 obj = getRawObject(obj);
 var leftOff = 0;
 var curleft = 0;
 if (obj.x) {
   return obj.x;
 } 
 else if (obj.offsetParent) {
   while (obj.offsetParent){
     if ( obj.style.left )  {
        curleft += parseInt(obj.style.left.substring(0,obj.style.left.length-2));
        return curleft;
     }
     else {
        curleft += obj.offsetLeft
     }
     obj = obj.offsetParent;
   }
 } 
 return curleft;
}

function findPosY(obj) {

 obj = getRawObject(obj);
 var curtop = 0;

 if (obj.y){
   return obj.y;
 } 
 else if (obj.offsetParent) {
   while (obj.offsetParent) {
     if ( obj.style.top ) {
        curtop += parseInt(obj.style.top.substring(0,obj.style.top.length-2));
        return curtop;
      }
      else {
          curtop += obj.offsetTop
       }
       obj = obj.offsetParent;
     }
   }
   return curtop;
}


// Retrieve the x coordinate of a positionable object
function getObjectLeft(obj)  {
    var elem = getRawObject(obj);
    var result = 0;
    if (document.defaultView) {
        var style = document.defaultView;
        var cssDecl = style.getComputedStyle(elem, "");
        result = cssDecl.getPropertyValue("left");
    } else if (elem.currentStyle) {
        result = elem.currentStyle.left;
    } else if (elem.style) {
        result = elem.style.left;
    } else if (isNN4) {
        result = elem.left;
    }
    return parseInt(result);
}

// Retrieve the y coordinate of a positionable object
function getObjectTop(obj)  {
    var elem = getRawObject(obj);
    var result = 0;
    if (document.defaultView) {
        var style = document.defaultView;
        var cssDecl = style.getComputedStyle(elem, "");
        result = cssDecl.getPropertyValue("top");
    } else if (elem.currentStyle) {
        result = elem.currentStyle.top;
    } else if (elem.style) {
        result = elem.style.top;
    } else if (isNN4) {
        result = elem.top;
    }
    return parseInt(result);
}

// Retrieve the rendered width of an element
function getObjectWidth(obj)  {
    var elem = getRawObject(obj);
    var result = 0;
    if (elem.offsetWidth) {
        result = elem.offsetWidth;
    } else if (elem.clip && elem.clip.width) {
        result = elem.clip.width;
    } else if (elem.style && elem.style.pixelWidth) {
        result = elem.style.pixelWidth;
    }
    return parseInt(result);
}

// Retrieve the rendered height of an element
function getObjectHeight(obj)  {
    var elem = getRawObject(obj);
    var result = 0;
    if (elem.offsetHeight) {
        result = elem.offsetHeight;
    } else if (elem.clip && elem.clip.height) {
        result = elem.clip.height;
    } else if (elem.style && elem.style.pixelHeight) {
        result = elem.style.pixelHeight;
    }
    return parseInt(result);
}


// Return the available content width space in browser window
function getInsideWindowWidth() {
    if (window.innerWidth) {
        return window.innerWidth;
    } else if (isIE6CSS) {
        // measure the html element's clientWidth
        return document.body.parentElement.clientWidth
    } else if (document.body && document.body.clientWidth) {
        return document.body.clientWidth;
    }
    return 0;
}
// Return the available content height space in browser window
function getInsideWindowHeight() {
    if (window.innerHeight) {
        return window.innerHeight;
    } else if (isIE6CSS) {
        // measure the html element's clientHeight
        return document.body.parentElement.clientHeight
    } else if (document.body && document.body.clientHeight) {
        return document.body.clientHeight;
    }
    return 0;
}

function inspect(elm){
  var str = "";
  for (var i in elm) {
    str += i + ": " + elm.getAttribute(i) + "\n";
  }
  alert(str);
}

function clearObject(obj)
{
  var node = getRawObject(obj);
  if ( node ) {

    while ( node.childNodes.length > 0 ) {
      try {
        node.removeChild(node.childNodes[0]);
      }
      catch ( e ) {
	break ;
      }
    }
  }
}

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 var expires = "";
	document.cookie = name+"="+value+expires+"; path=/";
}

function readCookie(name) {
	//alert("COOKIE "+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;
}

function eraseCookie(name) {
	createCookie(name,"",-1);
}

// Update the innerHTML of a node
function updateNode ( nodeName, htmlData )
{
  var DOMnode = document.getElementById(nodeName);
  // Get rid of the any \n
  htmlData = htmlData.replace( /\n/gi, "" );
  if ( DOMnode ) DOMnode.innerHTML = htmlData ; 
}

function replaceImage ( nodeName, src )
{
   getRawObject(nodeName).setAttribute('src',src) ;
}

function replaceTextAtNode ( nodeName, text )
{
  var DOMnode = document.getElementById(nodeName);
  if ( DOMnode ) {
    var t = document.createTextNode(text);
    var child = DOMnode.firstChild;
    if ( child ) 
      DOMnode.replaceChild(t,child);
    else
      DOMnode.appendChild(t);
  }
}
     
function appendTextToNode ( nodeName, text )
{
  var DOMnode = document.getElementById(nodeName);
  if ( DOMnode ) {
    var tn = document.createTextNode(text);
    DOMnode.appendChild(tn);
    var br = document.createElement("br");
    DOMnode.appendChild(br);
  }
}

function updateTableCell ( nodeName, rowNum, colNum, text )
{
  var DOMnode = document.getElementById(nodeName);
  if ( DOMnode ) {

    var ROWnode = DOMnode.rows[rowNum] ;
    if ( ROWnode ) {
  
      var CELLnode = ROWnode.cells[colNum] ;

      if ( CELLnode ) {
  
        var t = document.createTextNode(text);
        var child = CELLnode.firstChild;
        if ( child ) 
          CELLnode.replaceChild(t,child);
        else
          CELLnode.appendChild(t);
      }
    }
  }
}


// Update a input element
function updateInputElement ( element, value )
{
   var inpElement = getRawObject(element) ;
   if ( inpElement ) {
     inpElement.value = value ;
   }
   else
     alert ( "NO such input element "+element ) ;
}


// Update a input element
function updateInputChecked ( element, check )
{
   var inpElement = getRawObject(element) ;
   var checked2 = ( ( check || check=="1" || check==1) ? true : false );
   if ( inpElement ) {
     inpElement.checked = checked2 ;
   }
   else
     alert ( "NO such input element "+element ) ;
}



// Update a input element
function updateInputIndex ( element, index )
{
   var inpElement = getRawObject(element) ;
   if ( inpElement ) {
     inpElement.selectedIndex = index ;
   }
   else
     alert ( "NO such input element "+element ) ;
}



// Update a form element
function updateFormElement ( element, value )
{
   var frmElement = document.forms[0].elements[element] ;
   if ( frmElement ) {
     frmElement.value = value ;
   }
   else
     alert ( "NO such form element "+element ) ;
}


function horizBar ( element, w, h ) 
{
  theObj = getObject ( element ) ;

  if ( theObj ) {

    if( theObj.resizeTo ) {
      theObj.resizeTo( w, h );
    }
    var noPx = document.childNodes ? 'px' : 0;
    theObj.width = w + noPx;
    theObj.pixelWidth = w;
    theObj.height = h + noPx;
    theObj.pixelHeight = h;
  }
}


function popupURL (URL ) 
{
  var title = "  Page";
  var windowWidth  = 800; 
  var windowHeight = 400;
  var windowX = 10;
  var windowY = 10;
  var autocenter = true;
  var autoclose = true;
  var s = "width=" + windowWidth + ";height=" + windowHeight ;
  var beIE=document.all?true:false;

  if ( autocenter ) {
    windowX = (window.screen.width-windowWidth)/2;
    windowY = (window.screen.height-windowHeight)/2;
  }

  popupnum = popupnum + Math.floor(Math.random()*1000+1) ;
  var popupname = "popup" + popupnum ;
  popupnum++ ;

  if (beIE) {

    popper = window.open(URL,popupname,  "scrollbars=yes,resizable,"+s);
    popper.blur();
    popper.focus();
  }
  else {
    popper=window.open(URL,popupname,"scrollbars=yes,"+s);
    popper.blur();
    popper.focus(); 
 }   

 if (autoclose) {
    window.onunload = function(){popper.close();}
 }  

}

function setDebugLevel( level )
{
  debugLevel = level ;
}

function debug  ( text, displayLevel )
{
  // DisplayLevel
  // 0 = do not display
  // 1 = severe errors and critical messages
  // 2 = warnings
  // 3 = informative

  if ( displayLevel > debugLevel ) return ;
  var DOMnode = document.getElementById('consoleText');
  if ( DOMnode ) {
    var d = Date()+" ";
    var prefix = d.substring(0,24) + " : " ;
    var t = prefix + text ;
    var tn = document.createTextNode(t);
    DOMnode.appendChild(tn);
    var br = document.createElement("br");
    DOMnode.appendChild(br);
  }
}

function log ( text )
{
  //alert (text) ;
  var DOMnode = document.getElementById('logarea');
  if ( DOMnode ) {
    var t = ">" + text ;
    var tn = document.createTextNode(t);
    DOMnode.appendChild(tn);
    var br = document.createElement("br");
    DOMnode.appendChild(br);
  }
}


function urlDecode(str){
    str=str.replace(new RegExp('\\+','g'),' ');
    return unescape(str);
}

function urlEncode(str){
    str=escape(str);
    str=str.replace(new RegExp('\\+','g'),'%2B');
    return str.replace(new RegExp('%20','g'),'+');
}

var END_OF_INPUT = -1;

var base64Chars = new Array(
    'A','B','C','D','E','F','G','H',
    'I','J','K','L','M','N','O','P',
    'Q','R','S','T','U','V','W','X',
    'Y','Z','a','b','c','d','e','f',
    'g','h','i','j','k','l','m','n',
    'o','p','q','r','s','t','u','v',
    'w','x','y','z','0','1','2','3',
    '4','5','6','7','8','9','+','/'
);

var reverseBase64Chars = new Array();
for (var i=0; i < base64Chars.length; i++){
    reverseBase64Chars[base64Chars[i]] = i;
}

var base64Str;
var base64Count;
function setBase64Str(str){
    base64Str = str;
    base64Count = 0;
}
function readBase64(){
    if (!base64Str) return END_OF_INPUT;
    if (base64Count >= base64Str.length) return END_OF_INPUT;
    var c = base64Str.charCodeAt(base64Count) & 0xff;
    base64Count++;
    return c;
}
function encodeBase64(str){
    setBase64Str(str);
    var result = '';
    var inBuffer = new Array(3);
    var lineCount = 0;
    var done = false;
    while (!done && (inBuffer[0] = readBase64()) != END_OF_INPUT){
        inBuffer[1] = readBase64();
        inBuffer[2] = readBase64();
        result += (base64Chars[ inBuffer[0] >> 2 ]);
        if (inBuffer[1] != END_OF_INPUT){
            result += (base64Chars [(( inBuffer[0] << 4 ) & 0x30) | (inBuffer[1] >> 4) ]);
            if (inBuffer[2] != END_OF_INPUT){
                result += (base64Chars [((inBuffer[1] << 2) & 0x3c) | (inBuffer[2] >> 6) ]);
                result += (base64Chars [inBuffer[2] & 0x3F]);
            } else {
                result += (base64Chars [((inBuffer[1] << 2) & 0x3c)]);
                result += ('=');
                done = true;
            }
        } else {
            result += (base64Chars [(( inBuffer[0] << 4 ) & 0x30)]);
            result += ('=');
            result += ('=');
            done = true;
        }
        lineCount += 4;
        if (lineCount >= 76){
            result += ('\n');
            lineCount = 0;
        }
    }
    return result;
}
function readReverseBase64(){
    if (!base64Str) return END_OF_INPUT;
    while (true){
        if (base64Count >= base64Str.length) return END_OF_INPUT;
        var nextCharacter = base64Str.charAt(base64Count);
        base64Count++;
        if (reverseBase64Chars[nextCharacter]){
            return reverseBase64Chars[nextCharacter];
        }
        if (nextCharacter == 'A') return 0;
    }
    return END_OF_INPUT;
}

function ntos(n){
    n=n.toString(16);
    if (n.length == 1) n="0"+n;
    n="%"+n;
    return unescape(n);
}

function decodeBase64(str){
    setBase64Str(str);
    var result = "";
    var inBuffer = new Array(4);
    var done = false;
    while (!done && (inBuffer[0] = readReverseBase64()) != END_OF_INPUT
        && (inBuffer[1] = readReverseBase64()) != END_OF_INPUT){
        inBuffer[2] = readReverseBase64();
        inBuffer[3] = readReverseBase64();
        result += ntos((((inBuffer[0] << 2) & 0xff)| inBuffer[1] >> 4));
        if (inBuffer[2] != END_OF_INPUT){
            result +=  ntos((((inBuffer[1] << 4) & 0xff)| inBuffer[2] >> 2));
            if (inBuffer[3] != END_OF_INPUT){
                result +=  ntos((((inBuffer[2] << 6)  & 0xff) | inBuffer[3]));
            } else {
                done = true;
            }
        } else {
            done = true;
        }
    }
    return result;
}

var digitArray = new Array('0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f');
function toHex(n){
    var result = ''
    var start = true;
    for (var i=32; i>0;){
        i-=4;
        var digit = (n>>i) & 0xf;
        if (!start || digit != 0){
            start = false;
            result += digitArray[digit];
        }
    }
    return (result==''?'0':result);
}

function pad(str, len, pad){
    var result = str;
    for (var i=str.length; i<len; i++){
        result = pad + result;
    }
    return result;
}

function encodeHex(str){
    var result = "";
    for (var i=0; i<str.length; i++){
        result += pad(toHex(str.charCodeAt(i)&0xff),2,'0');
    }
    return result;
}

function decodeHex(str){
    str = str.replace(new RegExp("s/[^0-9a-zA-Z]//g"));
    var result = "";
    var nextchar = "";
    for (var i=0; i<str.length; i++){
        nextchar += str.charAt(i);
        if (nextchar.length == 2){
            result += ntos(eval('0x'+nextchar));
            nextchar = "";
        }
    }
    return result;

}