var _dom = document.all ? 3 :
           document.layers ? 2 :
           document.getElementById ? 1 :
           0;

function getNodeInfo(node) {
  if(node){
    var s = node.nodeName;
    switch (node.nodeType) {
    case 1:
      if (node.id) s+='('+node.id+')';
      else if (node.name) s += '['+node.name+']';
      else if (node.className) s += '{'+node.className+'}';
      break;
    }
    return s;
  }
  return 'null';
}
function isChild(elem, obj) {
  while (elem) {
    if (elem == obj)
      return true;
    elem = elem.parentNode;
  }
  return false;
}

function isString() {
  if (typeof arguments[0] == 'string') return true;
  if (typeof arguments[0] == 'object') {
    var criterion = arguments[0].constructor.toString().match(/string/i);
    return criterion != null;
  }
  return false;
}
function isArray() {
  if (typeof arguments[0] == 'object') {
    var criterion = arguments[0].constructor.toString().match(/array/i);
    return criterion != null;
  }
  return false;
}
function objType(obj) {
  if (typeof obj != 'object') return typeof obj;
  var str = arguments[0].constructor.toString();
  return str.substring(9,str.indexOf('('));
}

// Coordinates

// Find the x,y location in pixels for a relatively positioned object
function GetPos(obj) {
  var res = { x:0, y:0 };       // IE or DOM browsers
  while (obj.offsetParent) {
    res.x += obj.offsetLeft;
    res.y += obj.offsetTop;
    obj = obj.offsetParent;
  }
  return res;
}
function GetPosX(obj) {
  var x = 0;
  if (obj.offsetParent) {
    while (obj.offsetParent) {
      x += obj.offsetLeft;
      obj = obj.offsetParent;
    }
  }
  else if (obj.offsetLeft) {
    x = obj.style.left;
  }
  else if (obj.style && obj.style.left) {
    x = obj.style.left;
  }
  else if (obj.x) {
    x = obj.x;
  }
  return x;
}
function GetPosY(obj) {
  var y = 0;
  if (obj.offsetParent) {
    while (obj.offsetParent) {
      y += obj.offsetTop;
      obj = obj.offsetParent;
    }
  }
  else if (obj.offsetTop) {
    x = obj.style.top;
  }
  else if (obj.style && obj.style.top) {
    x = obj.style.top;
  }
  else if (obj.y) {
    y = obj.y;
  }
  return y;
}
function GetCoords(obj) {
  if (typeof obj != 'object')
    obj = document.getElementById(obj);

  var coords = { top:0, bottom:0, left:0, right:0 };
  coords.top    = GetPosY(obj);
  coords.bottom = coords.top + obj.offsetHeight - 1;
  coords.left   = GetPosX(obj);
  coords.right  = coords.left + obj.offsetWidth - 1;

  return coords;
}
function inRegion(x,y,box) {
  if (x < box.left || x > box.right)
    return false;
  if (y < box.top  || y > box.bottom)
    return false;
  return true;
}

function DumpCoords(obj) {
  if (typeof obj != 'object')
    obj = document.getElementById(obj);

  var top   = GetPosY(obj);
  var bot   = top + obj.offsetHeight - 1;
  var left  = GetPosX(obj);
  var right = left + obj.offsetWidth - 1;
  window.status = NameOf(obj)+': geom('+left+'x'+top+'+'+obj.offsetWidth+'+'+obj.offsetHeight+'), coords('+left+','+top+','+right+','+bot+')';
}
function DumpCoordsObj(obj) {
  window.status = NameOf(obj)+': coords('+obj.left+','+obj.top+','+obj.right+','+obj.bottom+')';
}


// Cookies

function SetCookie(name,value) {
  // 8-6-06: For now, clear default path cookie, if present
  // 8-6-06: Also, IE6 keeps the previous value around, until IE exit
  document.cookie = name + "=; expires=01-Jan-70 00:00:01 GMT";

  var expires = new Date();
  var year = expires.getFullYear();
  expires.setFullYear(year+1);
  document.cookie = name + "=" + value +
                    "; expires=" + expires.toGMTString() +
                    "; path=/"; // + (path != '' ? path : '/');
  //alert(DumpCookies());
}
function GetCookie(name) {
  //alert(DumpCookies());
  var value  = null;
  var cookies = document.cookie.split(';');
  var prefix = name + '=';
  for (i = 0; i < cookies.length; i++) {
    var cookie = cookies[i];
    if (cookie.charAt(0) == ' ')
      cookie = cookie.substring(1,cookie.length);
    if ((index = cookie.indexOf(prefix)) == 0) {
      value = cookie.substring(index+prefix.length);
      // 8-6-06: ignore the old deleted value
      //if (value != '') break;
    }
  }
  return value;
}
function DeleteCookie(name) {
  document.cookie = name + "=; expires=01-Jan-70 00:00:01 GMT; path=/";
  // 8-6-06: For now, clear default path cookie, too
  document.cookie = name + "=; expires=01-Jan-70 00:00:01 GMT";
}
function DumpCookies() {
  var result  = document.cookie;
  var cookies = document.cookie.split(';');
  for (i = 0; i < cookies.length; i++) {
    var cookie = cookies[i];
    if (cookie.charAt(0) == ' ')
      cookie = cookie.substring(1,cookie.length);
    result += "\n"+i+": "+cookie;
  }
  return result;
}

// Elements

function ShowElement(elem, ctrl, offsetX, offsetY) {
  if (typeof elem != 'object')
    elem = document.getElementById(elem);
  if (typeof ctrl != 'object')
    ctrl = document.getElementById(ctrl);

  if (elem && ctrl) {
    var x = GetPosX(ctrl) + offsetX; if (x < 0) x = 0;
    var y = GetPosY(ctrl) + offsetY; if (y < 0) x = 0;
    elem.style.left = x + 'px';
    elem.style.top  = y + 'px';
    elem.style.visibility = 'visible';
  }
  return false;
}
function HideElement(elem) {
  if (typeof elem != 'object') {
    elem = document.getElementById(elem);
  }
  if (elem) {
    elem.style.visibility = 'hidden';
  }
  return false;
}
// Returns null string if element is not defined or has no name.
function NameOf(elem) {
  return elem ? elem.name ? elem.name :
                elem.id ? elem.id :
                elem.className ? elem.className :
                '' : '';
}

// Routines to hide/show an element
//function ShowElement(id) {
//  var elem = document.getElementById(id);
//  if (elem) elem.className = 'showit';
//  return false;
//}
//function HideElement(id) {
//  var elem = document.getElementById(id);
//  if (elem) elem.className = 'hideit';
//  return false;
//}
//function ToggleVisibility(id) {
//  var elem = document.getElementById(id);
//  if (elem.className == 'showit') {
//    elem.className = 'hideit';
//  } else {
//    elem.className = 'showit';
//  }
//  return false;
//}
//function ShowProperty(id,name) {
//  var opt = document.getElementById('opt'+id);
//  var val = document.getElementById('val'+id);
//  var def = document.getElementById('def'+id);
//  var err = document.getElementById('err'+id);
//  if (!opt || opt.checked) {
//    val.className = 'showit';
//    def.className = 'hideit';
//    if (name) {
//      if (val = document.getElementById('val'+name)) {
//        val.focus();
//        val.select();
//      }
//    }
//  } else {
//    val.className = 'hideit';
//    def.className = 'showit';
//    if (err) err.innerHTML = '';
//  }
//  return false;
//}
//function InitProperty(id,showit) {
//  var val = document.getElementById('val'+id);
//  var def = document.getElementById('def'+id);
//  var err = document.getElementById('err'+id);
//  if (showit) {
//    if (val) val.className = 'showit';
//    if (def) def.className = 'hideit';
//  } else {
//    if (val) val.className = 'hideit';
//    if (def) def.className = 'showit';
//  }
//  if (err) err.innerHTML = '';
//}


// XML routines

//if (document.implementation.createDocument) {
//  function _Node_getXML() {
//    var serializer = new XMLSerializer;
//    return serializer.serializeToString(this);
//  }
//  Node.prototype.__defineGetter__("xml"), _Node_getXML);
//}

// DOM NodeTypes:
// 1 ELEMENT_NODE 
// 2 ATTRIBUTE_NODE 
// 3 TEXT_NODE 
// 4 CDATA_SECTION_NODE 
// 5 ENTITY_REFERENCE_NODE 
// 6 ENTITY_NODE 
// 7 PROCESSING_INSTRUCTION_NODE 
// 8 COMMENT_NODE 
// 9 DOCUMENT_NODE 
// 10 DOCUMENT_TYPE_NODE 
// 11 DOCUMENT_FRAGMENT_NODE 
// 12 NOTATION_NODE 

function LoadXML(url)
{
  //if (document.implementation && document.implementation.createDocument) {
  if (document.implementation.createDocument) {
    xmlDoc = document.implementation.createDocument("", "", null);
  }
  else if (window.ActiveXObject) {
    //xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
    //xmlDoc = new ActiveXObject("Msxml.DOMDocument");
    xmlDoc = new ActiveXObject("Msxml2.DOMDocument.3.0");
  }
  else {
    // xml is not supported
    return false;
  }
  xmlDoc.async = false;
  try {
    xmlDoc.load(url);
  } catch (e) {
    alert('[LoadXML] Error: '+e.toString());
    return false;
  }
  //IE specific
  //if (xmlDoc.parseError.errorCode) {
  //  alert('Error loading doc');
  //  return false;
  //} else {
  //  alert(xmlDoc.documentElement.xml);
  //}

  return xmlDoc.firstChild ? xmlDoc : false;
}

var xmlDoc;
function ProcessXML(url, callback)
{
  //if (document.implementation && document.implementation.createDocument) {
  if (document.implementation.createDocument) {
    xmlDoc = document.implementation.createDocument("", "", null);
    if (callback) xmlDoc.onload = callback;
  }
  else if (window.ActiveXObject) {
    //xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
    xmlDoc = new ActiveXObject("Msxml2.DOMDocument.3.0");
    if (callback) {
      xmlDoc.onreadystatechange = function () {
        if (xmlDoc.readyState == 4) callback();
      };
    }
  }
  else {
    // xml is not supported
    return false;
  }
  xmlDoc.async = true;
  try {
    xmlDoc.load(url);
  } catch (e) {
    alert('[ProcessXML] Error: '+e.toString());
  }
  //IE specific
  //if (xmlDoc.parseError.errorCode) {
  //  alert('Error loading doc');
  //  return false;
  //} else {
  //  alert(xmlDoc.documentElement.xml);
  //}

  return true;
}


// File routines
function ValidFilename(filename) {
  if (filename.replace(/ /g,'') == '') {
    return 'Missing filename';
  }
  else if (!filename.match(/[^\\\/\.]+\.[^\\\/\.]+$/)) {
    return 'Invalid or missing filename';
  }
  else if (filename.match(/[:\*\?"<>\|]/)) {
    return 'Invalid characters in filename';
  }
  return '';
}
function ValidFileSpec(filespec) {
  if (filespec.replace(/ /g,'') == '') {
    return 'Missing filespec';
  }
  if (path.match(/^\w:/)) {
    if (!path.match(/^[A-Za-z]:(\\[^\\]+)*[^\\\.]+\.[^\\\.]+$/)) {
      return 'Invalid DOS/Windows filename';
    }
    if (path.match(/[\*\?"<>\|]/)) {
      return 'Invalid characters in file path';
    }
  }
  else {
    if (!path.match(/^[\\\/]{2}([^\\\/]+[\\\/])*[^\\\/\.]+\.[^\\\/\.]+$/)) {
      return 'Invalid UNC network filespec (\\\\server\\share\\filename)';
    }
    if (path.match(/[:\*\?"<>\|]/)) {
      return 'Invalid characters in file path';
    }
  }
  return '';
}
function ValidPath(path) {
  if (path.replace(/ /g,'') == '') {
    return 'Missing file path';
  }
  if (path.match(/^\w:/)) {
    if (!path.match(/^[A-Za-z]:(\\[^\\]*)+$/)) {
      return 'Invalid DOS/Windows path';
    }
    if (path.match(/[\*\?"<>\|]/)) {
      return 'Invalid characters in file path';
    }
  }
  else {
    if (!path.match(/^[\\\/]{2}[^\\\/]+[\\\/]\w+/)) {
      return 'Invalid UNC network filespec (\\\\server\\share\\filename)';
    }
    if (path.match(/[:*?"<>\|]/)) {
      return 'Invalid characters in file path';
    }
  }
  return '';
}
function ValidDosPath(path) {
  if (path.replace(/ /g,'') == '') {
    return 'Missing file path';
  }
  if (!path.match(/^[A-Za-z]:(\\[^\\]*)+$/)) {
    return 'Invalid DOS/Windows path';
  }
  if (path.match(/[\*\?"<>\|]/)) {
    return 'Invalid characters in file path';
  }
  return '';
}
function ValidUncPath(path) {
  if (path.replace(/ /g,'') == '') {
    return 'Missing file path';
  }
  if (!path.match(/^[\\\/]{2}[^\\\/]+[\\\/]\w+/)) {
    return 'Invalid UNC network filespec (\\\\server\\share\\filename)';
  }
  if (path.match(/[:*?"<>\|]/)) {
    return 'Invalid characters in file path';
  }
  return '';
}
function ValidRelPath(path) {
  if (path.replace(/ /g,'') == '') {
    return 'Missing relative path';
  }
  //else if (!path.match(/^([\\\/][^\\\/]*)+$/)) {
  //  return 'Invalid relative path';
  //}
  else if (path.match(/[:*?"<>\|]/)) {
    return 'Invalid characters in file path';
  }
  return '';
}
function ValidPathChars(path) {
  if (path.replace(/ /g,'') == '') {
    return 'Missing file path';
  }
  else if (path.match(/[:*?"<>\|]/)) {
    return 'Invalid characters in file path';
  }
  return '';
}
function ValidDOSPathChars(path) {
  if (path.replace(/ /g,'') == '') {
    return 'Missing file path';
  }
  else if (path.match(/[\*\?"<>\|]/)) {
    return 'Invalid characters in file path';
  }
  return '';
}
function ValidEmailAddress(email) {
  if (email.replace(/ /g,'') == '') {
    return 'Missing e-mail address';
  }
  else if (email.match(/[ ",:;\\<>\(\)\[\]]/)) {
    return 'Invalid characters in e-mail address';
  }
  else if (!email.match(/^[^@]+@[\w\-\.]+\.\w+$/)) {
    return 'Invalid e-mail address';
  }
  return '';
}

// Event Handling

// eventObject:
// - attrChange[ro]: 1: modification, 2: addition, 3: removal
// - attrName[ro]: name of attribute for DOMAttrModified mutation events
// - bubbles[ro]:
// - cancelable[ro]:
// - cancelBubble[rw]: true=prevent event from further processing
// - charCode[ro]: key even unicode character
// - currentTarget[ro]: reference to element currently processing event
// - detail[ro]: extra info depending on event
// - eventPhase[ro]: 1: capture, 2: bubble (target), 3: during bubbling (ancestors), 0: manually created event object that hasn't yet fired
// - fromElement[ro]: previous element the mouse was over for mouseover events
// - metaKey[ro]: true = system meta key is pressed
// - newValue[ro]: new value after mutation event
// - preventDefault()[ro]: prevents default action from occuring after event processing is complete
// - prevValue[ro]: previous nodeValue before mutation event
// - relatedNode[ro]: similar to relatedTarget for mutation events
// - relatedTarget[ro]: related element for related events (eg, mouseover)
// - returnValue[rw]: true = prevent default action from occuring after event processing is complete
// - stopPropagation()[ro]: prevents event being processed by more handlers
// - toElement[ro]: element mouse is about to move over for mouseout events

//http://www.din.or.jp/~hagi3/JavaScript/JSTips/Mozilla/Samples/MouseEvent.htm
//function mousehandler(e){
//  if(document.all) e=window.event; // for IE
//  var f=document.f;
// 
//  if(e.clickCount) f.clickCount.value=e.clickCount;
// 
//  if(_dom==2){
//    f.altKey.value  =(e.modifiers&Event.ALT_MASK)?true:false;
//    f.ctrlKey.value =(e.modifiers&Event.CONTROL_MASK)?true:false;
//    f.shiftKey.value=(e.modifiers&Event.SHIFT_MASK)?true:false;
//    f.metaKey.value =(e.modifiers&Event.META_MASK)?true:false;
//    f.button.value =e.which;
//    f.clientX.value=e.pageX;
//    f.clientY.value=e.pageY;
//  } else {
//    f.altKey.value =e.altKey;
//    f.ctrlKey.value=e.ctrlKey;
//    f.shiftKey.value=e.shiftKey;
//    f.metaKey.value=e.metaKey;
//    f.button.value =e.button;
//    f.clientX.value=e.clientX;
//    f.clientY.value=e.clientY;
//  }
//  f.screenX.value=e.screenX;
//  f.screenY.value=e.screenY;
// 
//  f.relatedNode.value=e.relatedNode?getNodeInfo(e.relatedNode):
//                      (e.relatedTarget?getNodeInfo(e.relatedTarget):'');
//  if(e.preventBubble) e.preventBubble(); // for Mozilla
//  e.cancelBubble = true;  // for IE5
//  e.returnValue  = false; // for IE5
//  return false;
//}

function AddHandler(obj, event, handler)
{
  if (window.addEventListener) { // Mozilla, Netscape, Firefox
    obj.addEventListener(event, handler, false);
    //obj.myflag = "test";
    //obj.mydata = "123";
  } else if (window.attachEvent) { // IE
    obj.attachEvent(event, handler);
    //obj.myflag = "test";
    //obj.mydata = "123";
  }
}

function RemoveHandler(obj, event, handler)
{
  if (window.removeEventListener) { // Mozilla, Netscape, Firefox
    obj.removeEventListener(event, handler, false);
  } else if (window.detachEvent) { // IE
    obj.detachEvent(event, handler);
  }
}

function TestEvent(evt) {
	var e_out;
	var ie_var = "srcElement";
	var moz_var = "target";
	var prop_var = "id";
	// "target" for Mozilla, Netscape, Firefox et al. ; "srcElement" for IE
	evt[moz_var] ? e_out = evt[moz_var][prop_var] : e_out = evt[ie_var][prop_var];
	alert(e_out);
	prop_var = "mydata";
	evt[moz_var] ? e_out = evt[moz_var][prop_var] : e_out = evt[ie_var][prop_var];
	alert(e_out);
}

function DumpEvent() {
  if (document.all) e = window.event;
  s = '';
  if (e.attrChange) s += ', attrChange='+e.attrChange;
  if (e.attrName) s += ', attrName='+e.attrName;
  if (e.bubbles) s += ', bubbles='+e.bubbles;
  if (e.cancelable) s += ', cancelable='+e.cancelable;
  if (e.cancelBubble) s += ', cancelBubble='+e.cancelBubble;
  if (e.charCode) s += ', charCode='+e.charCode;
  if (e.currentTarget) s += ', currentTarget='+getNodeInfo(e.currentTarget);
  if (e.detail) s += ', detail='+e.detail;
  if (e.eventPhase) s += ', eventPhase='+e.eventPhase;
  if (e.fromElement) s += ', fromElement='+getNodeInfo(e.fromElement);
  if (e.metaKey) s += ', metaKey='+e.metaKey;
  if (e.newValue) s += ', newValue='+e.newValue;
  if (e.prevValue) s += ', prevValue='+e.prevValue;
  if (e.relatedNode) s += ', relatedNode='+getNodeInfo(e.relatedNode);
  if (e.relatedTarget) s += ', relatedTarget='+getNodeInfo(e.relatedTarget);
  if (e.returnValue) s += ', returnValue='+e.returnValue;
  if (e.toElement) s += ', toElement='+getNodeInfo(e.toElement);
  if (_dom == 2) {
    s += ', client('+e.pageX+','+e.pageY+')';
  } else {
    s += ', client('+e.clientX+','+e.clientY+')';
  }
  s += ', screen('+e.screenX+','+e.screenY+')';
  node = e.relatedNode   ? e.relatedNode :
         e.relatedTarget ? e.relatedTarget : null;
  if (node) s += ', otherNode='+getNodeInfo(node);
  s += ', child='+(node?isChild(node, document.getElementById('PageOpts')):'unknown');
  window.status = s;
}

// Error Handling

function ReportError(name,e)
{
    if (e.description == null) {
        alert(name + " Exception: " + e.message);
    } else {
        alert(name + " Exception: " + e.description);
    }
}

// Debug Routines

function DumpForm(form) {
  document.writeln("<b>"+form.name+"</b> fields:<br>");
  document.writeln("<table border=1 cellspacing=0>");
  for (j = 0; j < form.elements.length; j++) {
    elem = form.elements[j];
    if (elem.name) {
      document.write(" <tr>");
      document.write("<td align=right>"+elem.name+":</td>");
      document.write("<td>"+elem.value+"</td>");
      document.writeln("</tr>");
    }
  }
  document.writeln("</table>");
}
function DumpForms() {
  document.write("<h4>Document Forms</h4>");
  for (i = 0; i < document.forms.length; i++) {
    document.write("<p>");
    DumpForm(document.forms[i]);
    document.writeln("</p>");
  }
}

function DumpDOM(doc) {
  if (isObject(doc)) {
    document.write('<h4>DOM Document: '+(doc.documentURI?doc.documentURI:
                                     doc.nodeName?doc.NodeName:'')+'</h4>');
    DumpDOMTree(doc, '');
    document.write('<br/>');
  }
}
var NodeTypes;
function InitNodeTypes() {
  if (!NodeTypes) {
    NodeTypes = new Array('unknown', 'Element', 'Attr', 'Text', 'CData',
      'Entity Reference', 'Entity', 'Processing Instruction', 'Comment',
      'Document', 'Doc Type', 'Doc Frag', 'Notation'
    );
  }
}
function DumpDOMTree(parent) {
  var node; InitNodeTypes();
  if (node = parent.firstChild) {
    document.write('<ol>');
    while (node) {
      document.write('<li>'+node.nodeName +
                     ' ('+NodeTypes[node.nodeType]+' ['+node.nodeType+'])');
      if (node.nodeValue) {
        if (typeof node.nodeValue == 'string') {
          var s = trim(node.nodeValue);
          document.write(' = '+(s?(s+' ['+s.length+']'):'[empty]'));
        } else {
          document.write(' = '+node.nodeValue+' type('+typeof(node)+')');
        }
      }
      document.write('</li>');
      DumpDOMTree(node);
      node = node.nextSibling;
    }
    document.write('</ol>');
  }
}
