//*************************************
// Helper functions      //
//*************************************

var NODE_ELEMENT = 1;
var NODE_ATTRIBUTE = 2;
var NODE_TEXT = 3;
var NODE_CDATA = 4;
var NODE_ENTITYREF = 5;
var NODE_ENTITY = 6;
var NODE_PI = 7;
var NODE_COMMENT = 8;
var NODE_DOCUMENT = 9;
var NODE_DOCTYPE = 10;
var NODE_DOCFRAG = 11;
var NODE_NOTATION = 12;

function findPosX(obj)
{
    var curleft = 0;
    if (obj.offsetParent)
    {
        while (obj.offsetParent)
        {
            curleft += obj.offsetLeft;
            obj = obj.offsetParent;
        }
    }
    else if (obj.x)
        curleft += obj.x;
    return curleft;
}

function findPosY(obj)
{
    var curtop = 0;
    if (obj.offsetParent)
    {
        while (obj.offsetParent)
        {
            curtop += obj.offsetTop;
            obj = obj.offsetParent;
        }
    }
    else if (obj.y)
        curtop += obj.y;
    return curtop;
}

function moveNodeAttr( toNode, fromNode, attr ) {
    try {
        var f = fromNode.getAttribute( attr );
        if ( f ) toNode.setAttribute( attr, f );
    }
    catch ( e ) {
        alert( e );
    }
}
function setAbsPosition( element, left, top, width, height ) {
    element.style.left = left + "px";
    element.style.top = top + "px";
    element.style.width = width + "px";
    element.style.height = height + "px";
}
function getWindowWH() {
  var myWidth = 0, myHeight = 0;
  if( typeof( window.innerWidth ) == 'number' ) {
    //Non-IE
    myWidth = window.innerWidth;
    myHeight = window.innerHeight;
  } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
    //IE 6+ in 'standards compliant mode'
    myWidth = document.documentElement.clientWidth;
    myHeight = document.documentElement.clientHeight;
  } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
    //IE 4 compatible
    myWidth = document.body.clientWidth;
    myHeight = document.body.clientHeight;
  }
  return [myWidth, myHeight ];
}
function getScrollXY() {
  var scrOfX = 0, scrOfY = 0;
  if( typeof( window.pageYOffset ) == 'number' ) {
    //Netscape compliant
    scrOfY = window.pageYOffset;
    scrOfX = window.pageXOffset;
  } else if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) {
    //DOM compliant
    scrOfY = document.body.scrollTop;
    scrOfX = document.body.scrollLeft;
  } else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) {
    //IE6 standards compliant mode
    scrOfY = document.documentElement.scrollTop;
    scrOfX = document.documentElement.scrollLeft;
  }
  return [ scrOfX, scrOfY ];
}

function setOpacity(obj, opacity) {
  opacity = (opacity == 100)?99.999:opacity;
  // IE/Win
  obj.style.filter = "alpha(opacity:"+opacity+")";
  // Safari<1.2, Konqueror
  obj.style.KHTMLOpacity = opacity/100;
  // Older Mozilla and Firefox
  obj.style.MozOpacity = opacity/100;
  // Safari 1.2, newer Firefox and Mozilla, CSS3
  obj.style.opacity = opacity/100;
}
function indexOf( array, obj ) {
    if ( array.indexOf ) return array.indexOf( obj );
    else {
        var ret = -1;
        for ( var i=0;i<array.length;i++ ) {
            if ( array[i] == obj ) {
                ret = i;
                break;
            }
        }
        return ret;
    }
}


function setComboOptions(input, choiceNames, choices ) {

    for ( var i=0;i<choices.length;i++ ) {
        var ch = document.createElement( "OPTION" );
        ch.setAttribute( "value", choices[i] );
        ch.appendChild( document.createTextNode(choiceNames[i] ) );
        input.appendChild( ch );
    }
}


function setValue( inputItem, value ) {
    if ( value == "null" || value == null ) value = "";
    inputItem.value = value;
}


function isTime(s) {
    var rex = /^[0-9]*:?[0-9]*:?[0-9]*$/;
    return ( s.match( rex ) != null) ;
}

function isDecimalNumber(s) {
    var rex = /^[0-9]*\.?[0-9]*$/;
    return ( s.match( rex ) != null) ;
}

function isInteger(s) {
    var rex = /^[0-9]*$/;
    return ( s.match( rex ) != null) ;
}


function trim(str)
{
   if ( !str ) return "";
   return str.replace(/^\s*|\s*$/g,"");
}


function getDocWidth() {
    if ( document.documentElement ) { return document.documentElement.clientWidth ; }
    else return document.body.clientWidth;
}

function getDocHeight() {
    if ( document.documentElement ) { return document.documentElement.clientHeight ; }
    else return document.body.clientHeight;
}

// do it both ways to work with IE and Firefox
function setClass( element, className ) {
  if ( element ) {
      element.setAttribute( "class", className );
      element.setAttribute( "className", className );
  }
}

function addEventHandler( htmlObject, handlerName, callback ){
  //htmlObject.setAttribute(handlerName, callback); works with firefox, but not IE.
  htmlObject[handlerName] = new Function ( callback ); // seems to work with both
}

function setElementProp( elementName, propname, value ) {
  var el = document.getElementById( elementName );
  if ( el ) el[propname] = value;
}


var isRequesting = false;
var requestPurpose = "";
var requestStartingTime;

function showProgress( show ) {
    var el = document.getElementById("transferInProgress");
    if ( el ) el.style.display = show;
}

function releaseHttpRequest() {
    isRequesting = false;
    requestPurpose = "";
    showProgress( "none" );
    if ( requestStartingTime ) {
        var doneTime = new Date();
        var diff = doneTime.getTime() - requestStartingTime.getTime();
        var el = document.getElementById("timingReportBox");
        if ( el ) el.innerHTML = " (time: " + (diff/1000) + " seconds)";
    }
}


function loadXMLHttpRequest(purpose) {
  var cnt = 0;
  while ( isRequesting ) {
      alert("There is a request in progress....please wait for: " + requestPurpose + " before trying: " + purpose);
      if ( cnt++ > 10 ) return null;
  }
  requestStartingTime = new Date();
  var el = document.getElementById("timingReportBox");
  if ( el ) el.innerHTML = "";
  showProgress("");
  requestPurpose = purpose;
  isRequesting = true;
  var req = false;
  // branch for native XMLHttpRequest object
  if(window.XMLHttpRequest) {
    try {
      req = new XMLHttpRequest();
    } catch(e) {
      req = false;
    }
  // branch for IE/Windows ActiveX version
  } else if(window.ActiveXObject) {
    try {
      req = new ActiveXObject("Msxml2.XMLHTTP");
    } catch(e) {
      try {
        req = new ActiveXObject("Microsoft.XMLHTTP");
      } catch(e) {
        req = false;
      }
    }
  }
  return req;

}


function loadXMLHttpRequestNoPurpose() {
  var req = false;
  // branch for native XMLHttpRequest object
  if(window.XMLHttpRequest) {
    try {
      req = new XMLHttpRequest();
    } catch(e) {
      req = false;
    }
  // branch for IE/Windows ActiveX version
  } else if(window.ActiveXObject) {
    try {
      req = new ActiveXObject("Msxml2.XMLHTTP");
    } catch(e) {
      try {
        req = new ActiveXObject("Microsoft.XMLHTTP");
      } catch(e) {
        req = false;
      }
    }
  }
  return req;

}


function getEventSrc( e ) {
    if ( e.srcElement ) return e.srcElement;
    else return e.target;
}

function getEvent(e) {
  if (typeof e == 'undefined') e = window.event;
  if (typeof e.layerX == 'undefined') e.layerX = e.offsetX;
  if (typeof e.layerY == 'undefined') e.layerY = e.offsetY;
  return e;
}

function cancelEvent( e ) {
    // for Moz
    if (e.stopPropagation) {
        e.stopPropagation();
    }
    if (e.preventDefault) {
        e.preventDefault();
    }
    // for IE
    e.cancelBubble = true;
    e.returnValue = false;
}

function makeXmlSafe( str ) {
    str = fixQuotes( str );
    str = str.replace(/&/g, "&amp;");
    str = str.replace(/>/g, "&gt;");
    str = str.replace(/</g, "&lt;");
    str = str.replace(/'/g, "&apos;");
    str = str.replace(/\"/g, "&quot;");
    return str.replace();
}

function fixQuotes( str ) {
    str = str.replace( /\u2019|\u2018|&lsquo;|&rsquo;/gi, "'" );
    str = str.replace( /&ldquo;|&rdquo;|\u201C|\u201D/gi, "\"");
    return str;
}

function genAttributeStr( name, value ) {
    return " " + name + "=\"" + makeXmlSafe( value ) + "\" ";
}

function getElementText( element ) {
    var ret = "";
    for ( var i=0;i<element.childNodes.length;i++ ) {
        if ( element.childNodes[i].nodeType == NODE_TEXT ) {
            ret += element.childNodes[i].nodeValue;
        }
    }
    return ret;
}

function getElementCData( element ) {
    var ret = "";
    for ( var i=0;i<element.childNodes.length;i++ ) {
        if ( element.childNodes[i].nodeType == NODE_CDATA ) {
            ret += element.childNodes[i].nodeValue;
        }
    }
    return ret;
}

function PageQuery(q) {

  if(q.length > 1) this.q = q.substring(1, q.length);
  else this.q = null;
  this.keyValuePairs = new Array();
  if(this.q) {
      var kvs = this.q.split("&");
      for(var i=0; i < kvs.length; i++) {
          this.keyValuePairs[i] = kvs[i];
      }
  }

  this.getKeyValuePairs = function() { return this.keyValuePairs; }

  this.getValue = function(s) {
    var kv;
    for(var j=0; j < this.keyValuePairs.length; j++) {
      kv = this.keyValuePairs[j].split("=");
      if(kv[0] == s) return kv[1];
    }
    return false;
  }

  this.getParameters = function() {
    var a = new Array(this.getLength());
    for(var j=0; j < this.keyValuePairs.length; j++) {
      a[j] = this.keyValuePairs[j].split("=")[0];
    }
    return a;
  }

  this.getLength = function() { return this.keyValuePairs.length; }
}

var pageQuery = false;

function getQueryString(key){
    if ( !pageQuery ) pageQuery = new PageQuery(window.location.search);
    if ( pageQuery.getValue(key) )
    return unescape(pageQuery.getValue(key));
    else return null;
}



function readyStateName( readyState ) {
    if ( readyState == 1 ) {
      return "sending request";
    } else if ( readyState == 2 ) {
      return "waiting for reply";
    } else if ( readyState == 3 ) {
      return "loading";
    } else return "state: " + readyState ;

}


function RequestHandler( url, purpose, method, onComplete, onError, onProgress, sendString, cb ) {

    this._url = url;
    this._purpose = purpose;
    this._method = method;
    this._onComplete = onComplete;
    this._onError = onError;
    this._onProgress = onProgress;
    this._sendString = sendString;
    this._cb = cb;
}

RequestHandler.prototype.start = function () {
      var treq;
      var hasPurp = this._purpose != null ;
      if ( hasPurp ) treq = loadXMLHttpRequest(this._purpose);
      else treq = loadXMLHttpRequestNoPurpose();
      if ( treq ) {
        var onComplete = this._onComplete;
        var onError = this._onError;
        var onProgress = this._onProgress;
        var cb = this._cb;
        treq.onreadystatechange = function(  ) {
                      var req = treq;
                      if ( onProgress ) {
                          onProgress( req, cb );
                      }
                      if ( req.readyState == 4 ) {
                          if ( hasPurp ) releaseHttpRequest();
                          if ( req.status == 200 ) {
                               if ( onComplete ) onComplete( req, cb );
                            } else {
                                if ( onError ) onError( req, cb );
                            }
                        }
                    };
        treq.open(this._method, this._url, true );
        if ( this._sendString ) treq.send( this._sendString ) ;
        else treq.send("");
        return true;
      } else {
        return false;
      }
    }


function HttpAction( url, requestName, onRequestComplete ) {
    this.requestName = requestName;
    this.url = url; //
    this.onRequestComplete = onRequestComplete;
}

HttpAction.prototype.start = function ( send ) {
    var url = this.url;
    if ( send ) {
      new RequestHandler( url, this.requestName,
        "POST", this.onComplete, this.onError, this.onProgress, send, this ).start();
    } else {
      new RequestHandler( url, this.requestName,
        "GET", this.onComplete, this.onError, this.onProgress, "", this ).start();
    }

}

HttpAction.prototype.onProgress = function ( req, cb ) {
   if ( showStatusLabel ) showStatusLabel(cb.requestName + "...(" + readyStateName(req.readyState) + ")");
}


HttpAction.prototype.onError = function ( req, cb ) {
      if ( showStatusLabel ) showStatusLabel("HTTP result: " + req.statusText);
      alert("Error: "+cb.requestName+":\n" + req.statusText + "  " + req.status);
}


HttpAction.prototype.onComplete = function ( req, cb ) {
      if ( showStatusLabel ) showStatusLabel(cb.requestName + " complete.");
      cb.onRequestComplete( req );
}


/*****************************
*  resizing
************************************/

window.onresize = fireWindowSizeChanged;
var resizeHandlers = new Array();

function fireWindowSizeChanged() {
  var tw = getDocWidth();
  var th = getDocHeight();
  for ( var i=0;i<resizeHandlers.length;i++ ) {
      if ( resizeHandlers[i] ) resizeHandlers[i](tw, th);
  }
}

function addResizeHandler( handler ) {
  for ( var i=0;i<resizeHandlers.length;i++ ) {
      if ( resizeHandlers[i] == handler ) return;
  }
  resizeHandlers.push( handler );
}

function showNewWindow(  url, name ) {
    return window.open(url, name, "titlebar=0,width=620,height=650,scrollbars=1,status=0" );
}

function removeFromArray( arr, value ) {
    for ( var i=0;i<arr.length;i++ ) {
        if ( arr[i] = value ) {
            arr = arr.splice( i, 1 );
            return arr;
        }
    }
    return arr;
}

//----- String

if (!String.prototype.startsWith) {
  String.prototype.startsWith = function(prefix) {
//    return (this.substr(0, prefix.length) == prefix);
    return (this.indexOf(prefix) === 0);
  };
}

if (!String.prototype.endsWith) {
  String.prototype.endsWith = function(suffix) {
    var startPos = this.length - suffix.length;
    if (startPos < 0) {
      return false;
    }
    return (this.lastIndexOf(suffix, startPos) == startPos);
  };
}

if (!String.prototype.withoutPrefix) {
  String.prototype.withoutPrefix = function(prefix) {
    if (this.startsWith(prefix)) {
      return this.substr(prefix.length);
    } else {
      return this;
    }
  };
}

if (!String.prototype.withoutSuffix) {
  String.prototype.withoutSuffix = function(suffix) {
    if (this.endsWith(suffix)) {
      return this.substr(0, this.length - suffix.length);
    } else {
      return this;
    }
  };
}

if (!String.prototype.strip) {
  String.prototype.strip = function() {
    return this.replace(/^\s*(.*?)\s*$/, "$1");
  };
}

if (!String.prototype.format) {
  // This function substitutes placeholders -- {0}, {1}, ... -- with
  // its arguments. The substituted value can be formatted by a function
  // like this
  // 'The list is {0, formatList}'.format(['a', 'b', 'c', 'd'])
  // with
  // function formatList(l) {
  //   if (l.length == 0) return 'empty';
  //   if (l.length == 1) return l[0];
  //   if (l.length == 2) return l[0] + ' and ' + l[1];
  //   var s = '';
  //   for (var i = 0; i < l.length - 1; i++)
  //     s += l[i] + ', ';
  //   return s + 'and ' + l[i];
  // }
  String.prototype.format = function() {
    var args = arguments;
    return this.replace(
      /\{\{[^{}]*\}\}|\{(\d+)(,\s*([\w.]+))?\}/g,
      function(m, a1, a2, a3) {
        if (m.chatAt == '{') {
          return m.slice(1, -1);
        }
        var rpl = args[a1];
        if (a3) {
          var f = eval(a3);
          rpl = f(rpl);
        }
        return rpl ? rpl : '';
      });
  };
}

if (!String.isBlank) {
  String.isBlank = function(s) {
    return (!s || (/^\s*$/).test(s));
  };
}

if (!String.compare) {
  String.compare = function(s1, s2) {
    if (s1 == s2) {
      return 0;
    }
    if (s1 > s2) {
      return 1;
    }
    return -1;
  };
}
/****flash helpers *******/
function supportsTransparentWmode() {
    // convert all characters to lowercase to simplify testing
    var agt=navigator.userAgent.toLowerCase();
    // *** PLATFORM ***
    var is_win   = ( (agt.indexOf("win")!=-1) || (agt.indexOf("16bit")!=-1) );
    var is_mac    = (agt.indexOf("mac")!=-1);
    return is_win || is_mac;
}
