// ****************************************************************************
// Networks In Motion, Inc.
//
// Copyright (c) 2007 Networks In Motion, Inc.
// All rights reserved.  This file and associated materials are the
// trade secrets, confidential information, and copyrighted works of
// Networks In Motion, Inc.
//
// This intellectual property is for the internal use only by Networks
// In Motion, Inc.  This source code contains proprietary information
// of Networks In Motion, Inc., and shall not be used, copied by, or
// disclosed to, anyone other than a Networks In Motion, Inc.,
// certified employee that has written authorization to view or modify
// said source code.
// ****************************************************************************

// Constants
var COOKIE_NO_EXPIRE = 10 * 365 * 24 * 60 * 60 * 1000; // 10 years
var DIALOG_NORMAL    = 0;
var DIALOG_NOTIFY    = 1;
var DIALOG_PROMPT    = 2;
var DIALOG_ERROR     = 3;
var INDEX_PAGE       = 'index.html';

// Objects
var _browser = new Browser();
var _locales = new Array();

// ----------------------------------------------------------------------------
// Objects
// ----------------------------------------------------------------------------

function Browser()
{
  var ua = navigator.userAgent.toLowerCase();

  this.isChrome  = (ua.indexOf('chrome')  != -1);
  this.isFirefox = (ua.indexOf('firefox') != -1);
  this.isIE      = (ua.indexOf('msie')    != -1);
  this.isOpera   = (ua.indexOf('opera')   != -1);
  this.isSafari  = (ua.indexOf('safari')  != -1);

  // browser version
  this.versionMinor = parseFloat(navigator.appVersion);

  // correct version number
  if (this.isIE && this.versionMinor >= 4) {
    this.versionMinor = parseFloat(ua.substring(ua.indexOf('msie ') + 5));
  } else if (this.isFirefox) {
    this.versionMinor = parseFloat(ua.substring(ua.indexOf('firefox/') + 8));
  } else if (this.isMozilla) {
    this.versionMinor = parseFloat(ua.substring(ua.indexOf('rv:') + 3));
  } else if (this.isOpera) {
    this.versionMinor = parseFloat(ua.substring(ua.indexOf('opera') + 6));
  } else if (this.isSafari) {
    this.versionMinor = parseFloat(ua.substring(ua.lastIndexOf('safari/') + 7));
  }

  this.versionMajor = parseInt(this.versionMinor);

  this.isIE5 = this.isIE && this.versionMajor == 5;
  this.isIE6 = this.isIE && this.versionMajor == 6;
  this.isIE7 = this.isIE && this.versionMajor == 7;
}

// ----------------------------------------------------------------------------
// Functions
// ----------------------------------------------------------------------------

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

function closeDialog()
{
  removeElement('_DIM_SCREEN');
  removeElement('_DIALOG');

  if ((_browser.isIE6) && (window.location.pathname == "/settings.html")){
    var locales = document.getElementById('LOCALES');
    if (locales != null) {
      locales.style.display="inline-block";
    }
  }
}

function convertDegrees(decimalDegrees)
{
  var degrees = '' + decimalDegrees;
  var decimal = degrees.indexOf('.');

  var d;
  var m;
  var s;

  if (decimal == -1) {
    d = degrees;
    m = '0';
    s = '0';
  } else {
    d = degrees.substring(0, decimal);
    var minutes = '' + (60.0 * degrees.substring(decimal));
    decimal = minutes.indexOf('.');
    m = '' + minutes.substring(0, decimal);;
    if (decimal == -1) {
      s = '0';
    } else {
      fraction = 1.0 * minutes.substring(decimal);
      var s = '' + Math.round(60.0 * fraction * 100) / 100;
    }
  }
  return d + '&deg; ' + m + '\' ' + s + '"';
}

function convertToFeet(meters)
{
  var feet = meters * 39.37 / 12;
  return Math.round(feet * 10) / 10;
}

function convertToMiles(kilometers)
{
  var miles = kilometers * 0.621371192
  return Math.round(miles * 10) / 10;
}

function convertToUnicode(s)
{
  var result  = '';
  var hexVal  = '';
  var uniChar = '';

  for (var i = 0; i < s.length; ++i) {
    //Convert char to hex
    hexVal = Number(s.charCodeAt(i)).toString(16);

    //Convert to unicode by making sure hex is 4 chars long, padding with 0's if less
    uniChar = '\\u' + ('000' + hexVal).match(/.{4}$/)[0];

    // Add to result
    result += uniChar;
  }

  return result;
}

function cookieGet(name, defaultValue)
{
  var start = document.cookie.indexOf(name + '=');
  var len = start + name.length + 1;

  if (defaultValue == undefined) {
    defaultValue = null;
  }

  if ((!start) && (name != document.cookie.substring(0, name.length))) {
    return defaultValue;
  }

  if (start == -1) {
    return defaultValue;
  }

  var end = document.cookie.indexOf(';', len);
  if (end == -1) {
    end = document.cookie.length;
  }

  return unescape(document.cookie.substring(len, end));
}

function cookieDelete(name, path, domain)
{
  if (cookieGet(name)) {
    document.cookie = name + '=' +
      ((path) ? ';path=' + path : '') +
      ((domain) ? ';domain=' + domain : '') +
      ';expires=Thu, 01-Jan-1970 00:00:01 GMT';
  }
}

function cookieSet(name, value, expires, path, domain, secure, duration)
{
  // set time (milliseconds)
  var today = new Date();
  today.setTime(today.getTime());

  if (expires) {
    if (duration == 'years') {
      expires = expires * 365 * 24 * 60 * 60 * 1000;
    } else if (duration == 'days') {
      expires = expires * 24 * 60 * 60 * 1000;
    } else if (duration == 'hours') {
      expires = expires * 60 * 60 * 1000;
    } else if (duration == 'minutes') {
      expires = expires * 60 * 1000;
    } else if (duration == 'seconds') {
      expires = expires * 1000;
    }
  }
  var expires_date = new Date(today.getTime() + (expires));

  document.cookie = escape(name) + '=' + escape(value) +
    ((expires) ? ';expires=' + expires_date.toGMTString() : '' ) +
    ((path)    ? ';path=' + path : '' ) +
    ((domain)  ? ';domain=' + domain : '' ) +
    ((secure)  ? ';secure' : '' );
}

function copyObject(obj)
{
  var newobj = new Object();

  for (var o in obj) {
    newobj[o] = obj[o];
  }

  return newobj;
}

function createElement(type, id, className, parent)
{
  var element = document.createElement(type);
  if (element) {
    if (id != null) {
      element.id = id;
    }
    if (className != null) {
      element.className = className;
    }
    if (parent == null) {
      document.body.appendChild(element);
    } else {
      parent.appendChild(element);
    }
  }
  return element;
}

function createRegEx(pattern, caseless)
{
  if (pattern != undefined) {
    if (pattern.indexOf('\\') != -1) {
      pattern = pattern.replace(/\\/g, '\\\\');
    }
    if (pattern.indexOf('/') != -1) {
      pattern = pattern.replace(/\//g, '\\\/');
    }
    if (pattern.indexOf('(') != -1) {
      pattern = pattern.replace(/\(/g, '\\\(');
    }
    if (pattern.indexOf(')') != -1) {
      pattern = pattern.replace(/\)/g, '\\\)');
    }
    if (pattern.indexOf('{') != -1) {
      pattern = pattern.replace(/\{/g, '\\\{');
    }
    if (pattern.indexOf('}') != -1) {
      pattern = pattern.replace(/\}/g, '\\\}');
    }
    if (pattern.indexOf('[') != -1) {
      pattern = pattern.replace(/\[/g, '\\\[');
    }
    if (pattern.indexOf(']') != -1) {
      pattern = pattern.replace(/\]/g, '\\\]');
    }
    if (pattern.indexOf('^') != -1) {
      pattern = pattern.replace(/\^/g, '\\\^');
    }
    if (pattern.indexOf('$') != -1) {
      pattern = pattern.replace(/\$/g, '\\\$');
    }
    if (pattern.indexOf('.') != -1) {
      pattern = pattern.replace(/\./g, '\\\.');
    }
    if (pattern.indexOf('?') != -1) {
      pattern = pattern.replace(/\?/g, '\\\?');
    }
    if (pattern.indexOf('+') != -1) {
      pattern = pattern.replace(/\+/g, '\\\+');
    }
    if (pattern.indexOf('*') != -1) {
      pattern = pattern.replace(/\*/g, '\\\*');
    }
    if (pattern.indexOf('|') != -1) {
      pattern = pattern.replace(/\|/g, '\\\|');
    }

    if (caseless) {
      return new RegExp(pattern, 'i');
    } else {
      return new RegExp(pattern);
    }
  }

  return null;
}


function customDialog(classname, title, html, type)
{

  if (document.getElementById('_DIM_SCREEN')) {
    return;
  }

  if (type == undefined) {
    type = DIALOG_NORMAL;
  }

  var div = createElement('div', '_DIM_SCREEN', 'DimScreen', null);
  if (_browser.isIE) {
    var diff = Math.abs(screen.height - document.documentElement.clientHeight);
    div.style.height = screen.height - diff + 'px';
  }

  var dialog = createElement('div', '_DIALOG', 'Dialog ' + classname, null);
  var header = createElement('div', null, 'DialogHeader', dialog);
  var span1 = createElement('span', null, 'TL', header);
  var span2 = createElement('span', null, 'TR', span1);
  var span3 = createElement('span', null, 'TC', span2);

  if (type == DIALOG_ERROR) {
    title = '<img width="15" height="15" class="Error" src="/images/error.gif"/><span class="DialogTitle">' + title + '</span>';
  } else {
    title = '<span class="DialogTitle">' + title + '</span>';
  }

  span3.innerHTML = title;

  if (type == DIALOG_ERROR) {
    var rule = createElement('div', null, 'DialogRule', dialog);
  }

  var divcontent = createElement('div', null, 'DialogContent', dialog);
  divcontent.innerHTML = html;

  var footer = createElement('div', null, 'DialogFooter', dialog);
  var span4 = createElement('span', null, 'BL', footer);
  var span5 = createElement('span', null, 'BR', span4);
  var span6 = createElement('span', null, 'BC', span5);

  var a = createElement('a', 'CLOSE', 'Close', dialog);
  a.href = 'javascript:closeDialog();';

  //update search when changing 'Route Type'
  if(classname == 'DialogRoute') {
	  if (document.getElementById('DIRECTIONS_FROM').value != '' && document.getElementById('DIRECTIONS_TO').value != '') {
		  a.href += 'search(1, undefined, undefined, true);';
	  }
  }

  a.tabIndex = 0;
  a.innerHTML = i18n['close'];

  var windowWidth = getElementWidth(document.documentElement);
  var dialogWidth = getElementWidth(dialog);

  dialog.style.left = ((windowWidth - dialogWidth) / 2) + 'px';

  //workaround for CSS bug in IE7
  var minWidth = getElementWidth(header);
  if (_browser.isIE7) {
	  minWidth -= 20;
	  span3.style.width = minWidth;
	  span6.style.width = minWidth;
  }

  dialog.style.visibility = 'visible';
}

function customErrorDialog(err, action)
{
  var html = '';

  html += '<div class="DialogText">';
  html += err;
  html += '</div>';
  html += '<div class="DialogSeparator"></div>';
  html += '<div class="DialogButtons">';
  if (_browser.isIE6 || _browser.isIE7) {
	  html += '<div class="Button" style="height: 22px;">';
  }
  if (action != undefined) {
    html +=     '<a id="OK" class="Button2" tabIndex="0" href="javascript:closeDialog();' + action + ';"><span>' + i18n['ok'] + '</span></a>';
  } else {
    html +=     '<a id="OK" class="Button2" tabIndex="0" href="javascript:closeDialog();"><span>' + i18n['ok'] + '</span></a>';
  }
  if (_browser.isIE6 || _browser.isIE7) {
    html += '</div>';
  }
  html += '</div>';

  customDialog('DialogError', 'Error', html, DIALOG_ERROR);
  document.getElementById('OK').focus();
}

function customNotifyDialog(title, txt, button, action)
{

  if ((_browser.isIE6) && (window.location.pathname == "/settings.html")){
    var locales = document.getElementById('LOCALES');
    if(locales != null) {
      locales.style.display="none";
    }
  }  
  
  var html = '';
  html += '<div class="DialogText">';
  html += txt;
  html += '</div>';
  html += '<div class="DialogSeparator"></div>';
  html += '<div class="DialogButtons" style="display:inline-block">';
  html +=     '<a id="BUTTON" class="Button2" tabIndex="0" href="javascript:' + action + ';"><span>' + button + '</span></a>';
  html += '</div>';

  customDialog('DialogNotify', title, html, DIALOG_NOTIFY);
  //document.getElementById('BUTTON').focus();
}

function customPromptDialog(title, txt, button1, button2, action1, action2)
{
  var html = '';

  html += '<div class="DialogText">';
  html += txt;
  html += '</div>';
  html += '<div class="DialogSeparator"></div>';
  html += '<div class="DialogButtons">';
  if (_browser.isIE6 || _browser.isIE7) {
    html += '<div class="Button">';
  }
  html +=     '<a id="CANCEL" class="Button1" tabIndex="0" href="javascript:' + action1 + ';"><span>' + button1 + '</span></a>';
  html +=     '<a id="OK" class="Button2" tabIndex="0" href="javascript:' + action2 + ';"><span>' + button2 + '</span></a>';
  if (_browser.isIE6 || _browser.isIE7) {
    html += '</div>';
  }
  html += '</div>';

  customDialog('DialogPrompt', title, html, DIALOG_PROMPT);
  document.getElementById('CANCEL').focus();
}

function dialogLanguage()
{
  var page = getCurrentPage();
  if (page == INDEX_PAGE) {
    page = '';
  }

  var html = '';

  html += '<div class="DialogSubtitle">' + i18n['Select_Language'] + '</div>';
  html += '<form id="FORM_LANGUAGE" method="post" action="language">';
  html +=   '<input type="hidden" name="action" value="updateLocale"/>';
  html +=   '<input type="hidden" name="redirect" value="' + page + '"/>'
  html +=   '<div class="DialogOption">';
  html +=     '<select name="locale" onChange="javascript:switchLanguage();">';
  for (var i = 0; i < _locales.length; i++) {
    var parts = _locales[i].split(':');
    if (_locale == parts[0]) {
      html += '<option value="' + parts[0] + '" selected>' + parts[1] + '</option>';
    } else {
      html += '<option value="' + parts[0] + '">' + parts[1] + '</option>';
    }
  }
  html +=     '</select>';
  html +=   '</div>';
  html += '</form>';

  customDialog('DialogLanguage', '', html);
  scroll(0,0);
}

function dumpProps(obj, parent)
{
  // Go through all the properties of the passed-in object
  for (var i in obj) {
    // if a parent (2nd parameter) was passed in, then use that to
    // build the message. Message includes i (the object's property name)
    // then the object's property value on a new line
    if (parent) {
      var msg = parent + "." + i + "\n" + obj[i];
    } else {
      var msg = i + "\n" + obj[i];
    }

    // Display the message. If the user clicks "OK", then continue. If they
    // click "CANCEL" then quit this level of recursion
    if (!confirm(msg)) {
      return;
    }

    // If this property (i) is an object, then recursively process the object
    if (typeof obj[i] == "object") {
      if (parent) {
        dumpProps(obj[i], parent + "." + i);
      } else {
        dumpProps(obj[i], i);
      }
    }
  }
}

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

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

function formatPhoneNumber(phoneNumber) {

  var formattedNumber = phoneNumber;

  // Swedish number...
  if((phoneNumber.length == 11) && (phoneNumber.substring(0,2) == '46')) {
    formattedNumber = '+' + (phoneNumber.substring(0,2) + ' - (0)' + phoneNumber.substring(2,4) + ' ' + phoneNumber.substring(4,7) + ' ' + phoneNumber.substring(7,9) + ' ' + phoneNumber.substring(9,11));
  }

  // TODO: Add more countries here...

  return formattedNumber;
}

function getComputedHeight(id)
{
  var height;

  if (_browser.isIE) {
    height = document.getElementById(id).offsetHeight;
  } else {
    var obj = document.getElementById(id);
    var tmp = document.defaultView.getComputedStyle(obj, "").getPropertyValue("height");
    tmp = tmp.split('px');
    height = tmp[0];
  }

  return height;
}

function getComputedWidth(id)
{
  var width;

  if (_browser.isIE) {
    width = document.getElementById(id).offsetWidth;
  } else {
    var obj = document.getElementById(id);
    var tmp = document.defaultView.getComputedStyle(obj, "").getPropertyValue("width");
    tmp = tmp.split('px');
    width = tmp[0];
  }

  return width;
}

function getCurrentPage()
{
  var loc = location.toString();
  var end = loc.indexOf('?');

  if (end < 0) {
    end = location.toString().length;
  }

  var stem = loc.substr(0, end);
  var start = stem.lastIndexOf('/') + 1;
  var url = loc.substr(start, end - start);

  if (url == '') {
    url = INDEX_PAGE;
  }
  return url.toLowerCase();
}

function getElementHeight(element)
{
  if (element) {
    return element.clientHeight || element.offsetHeight;
  }
  return -1;
}

function getElementOffset(element)
{
  var position = new Object();

  position.left = element.offsetLeft;
  position.top = element.offsetTop;

  element = element.offsetParent;
  while (element != null)
  {
    position.left += element.offsetLeft;
    position.top += element.offsetTop;
    element = element.offsetParent;
  }

  return position;
}

function getElementWidth(element)
{
  if (element) {
    return element.clientWidth || element.offsetWidth;
  }
  return -1;
}

function getParameter(name, parameters)
{
  var _parameters = new Array();
  if (parameters == null) {
    parameters = window.location.search.substr(1);
  }
  if (parameters) {
    for (var i = 0; i < parameters.split('&').length; i++) {
      _parameters[i] = parameters.split('&')[i];
    }
  }
  if (name != null) {
    for (var i = 0; i < _parameters.length; i++) {
      if (_parameters[i].split('=')[0] == name) {
        var param = _parameters[i].split('=')[1];
        // Unescape
        param = unescape(param);
        // Remove control characters
        param = param.clean();
        // Replace <> with entities
        param = param.replace(/\>/g, '&gt;')
        param = param.replace(/\</g, '&lt;')
        return param;
      }
    }
  }
  return null;
}

function getRadioInput(id, name)
{
  var value = null;

  var form = document.getElementById(id);
  for (var i = 0; i < form[name].length; i++) {
    if (form[name][i].checked) {
      value = form[name][i].value;
      break;
    }
  }
  return value;
}

function getUrl(page, secure)
{
  var url = window.location + '';
  var first = url.indexOf(':');
  var last = 0;
  for (var i = 0; i < 3; i++) {
    last = url.indexOf('/', last + 1);
  }
  var protocol = 'http';
  if (secure) {
    protocol = 'https';
  }

  return protocol + url.substring(first, last) + page;
}

function hide(id)
{
  var obj = document.getElementById(id);
  if (obj) {
    obj.style.display = 'none';
  }
}

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

  return unescape(n);
}

function removeChildren(obj)
{
  var o = obj.firstChild;
  while (o) {
    next = o.nextSibling;
    obj.removeChild(o);
    o = next;
  }
}

function removeElement(id)
{
  var element = document.getElementById(id);
  if (element) {
    document.body.removeChild(element);
  }
}

function round(number, prec)
{
  return Math.round(number * prec) / prec;
}

function setClass(id, name)
{
  var obj = document.getElementById(id);
  if (obj) {
    obj.className = name;
  }
}

function setFocus(id)
{
  var obj = document.getElementById(id);
  if (obj) {
    obj.focus();
  }
}

function setInnerHTML(id, html)
{
  var obj = document.getElementById(id);
  if (obj) {
    obj.innerHTML = html;
  }
}

function setSelection(id)
{
  var obj = document.getElementById(id);
  if (obj) {
    obj.focus();
    obj.select();
  }
}

function setSelectionRange(input, start, end)
{
  if (input.setSelectionRange) {
    input.focus();
    input.setSelectionRange(start, end);
  } else if (input.createTextRange) {
    var range = input.createTextRange();
    range.collapse(true);
    range.moveEnd('character', end);
    range.moveStart('character', start);
    range.select();
  }
}

function setSource(id, source)
{
  var obj = document.getElementById(id);
  if (obj) {
    obj.src = source;
  }
}

function setRadioChecked(id)
{
  var obj = document.getElementById(id);
  if (obj) {
    obj.checked = 'checked';
  }
}

function setValue(id, value)
{
  var obj = document.getElementById(id);
  if (obj) {
    obj.value = value;
  }
}

function show(id, display)
{
  var obj = document.getElementById(id);
  if (obj) {
    if (display) {
      obj.style.display = display;
    } else {
      obj.style.display = 'block';
    }
  }
}

String.prototype.clean = function()
{
  // Remove control characters
  return this.replace(/\cA-\cZ/g, '');
}

String.prototype.isAlpha = function()
{
  if (this.match(/[a-z]/ig)) {
    return true;
  } else {
    return false;
  }
}

String.prototype.isNumeric = function()
{
  if (this.match(/\D/g)) {
    return false;
  } else {
    return true;
  }
}

String.prototype.normalize = function()
{
  // Normalize carriage return and newline
  return this.replace(/\r\n\t/g, '\n');
}

String.prototype.toProperCase = function()
{
  return this.toLowerCase().replace(/^(.)|\s(.)/g, function($1) { return $1.toUpperCase(); });
}

String.prototype.remove = function(type)
{
  if (type == 'alpha') {
    return this.replace(/[\D]/ig, '');
  }

  if (type == 'numeric') {
    return this.replace(/[\d]/ig, '');
  }
}

String.prototype.trim = function()
{
  // Strip leading and trailing white-space
  return this.replace(/^\s*|\s*$/g, '');
}

function strip(text)
{
  text = text.split("|").join("");
  text = text.split("&").join("");
  text = text.split("'").join("");
  text = text.split("#").join("");
  text = text.split("$").join("");
  text = text.split("%").join("");
  text = text.split("^").join("");
  text = text.split("*").join("");
  text = text.split(":").join("");
  text = text.split("!").join("");
  text = text.split("<").join("");
  text = text.split(">").join("");
  text = text.split("~").join("");
  text = text.split(";").join("");
  text = text.split("®").join("");
  text = text.split("�?�").join("");
  text = text.split(" ").join("+");

  return text;
}

function switchLanguage()
{
  var form = document.getElementById('FORM_LANGUAGE');
  form.submit();
  closeDialog();
  return false;
}

function windowNew(a, url, title, options)
{
  a.target = "_blank";

  if (title == undefined) {
    title = '';
  }

  // IE Complains
  if (title.length) {
    title = title.replace(/ /g, '');
  }

  if (options == undefined) {
    window.open(url, title);
  } else {
    window.open(url, title, options);
  }

  return false;
}

function xmlGetAttributes(node)
{
  var o = null;
  if (node && node.attributes) {
    o = new Object();
    for (var i = 0; i < node.attributes.length; i++) {
      var attrib = node.attributes[i];
      o[attrib.nodeName] = unescape(attrib.nodeValue);
    }
  }
  return o;
}

function xmlGetValue(doc, name)
{
  var nodes = doc.getElementsByTagName(name);
  if (nodes[0].hasChildNodes()) {
    return unescape(nodes[0].childNodes[0].nodeValue);
  } else {
    return '';
  }
}

function xmlGetValues(node)
{
  var o =  null;
  if (node.hasChildNodes) {
    o = new Object();
    for (var i = 0; i < node.childNodes.length; i++) {
      var child = node.childNodes[i];
      if (child.hasChildNodes()) {
        o[child.nodeName] = child.childNodes[0].nodeValue;
      } else {
        o[child.nodeName] = '';
      }
    }
  }
  return o;
}

function xmlParse(xmlString)
{
  var xmlDoc;

  try
  {
    if (window.ActiveXObject) {
      xmlDoc = new ActiveXObject('Microsoft.XMLDOM');
      xmlDoc.async = false;
      xmlDoc.loadXML(xmlString);
    } else if (document.implementation && document.implementation.createDocument) {
      // code for Mozilla, etc.
      var objDOMParser = new DOMParser();
      var objDoc = objDOMParser.parseFromString(xmlString, 'text/xml');
      return objDoc;
    } else {
      alert('Error creating xml document');
    }
  } catch(e) {
    alert('An exception occurred in the script. Error name: ' + e + '. Error message: ' + e.message);
  }

  return xmlDoc;
}

//=============================================================================
// XmlHttpRequest
//=============================================================================

function XmlHttpRequest() {}

XmlHttpRequest.create = function()
{
  var xmlHttpReq = null;

  if (window.XMLHttpRequest) {
    // IE 7, Mozilla, Safari
    xmlHttpReq = new XMLHttpRequest();
    if (xmlHttpReq.overrideMimeType) {
      xmlHttpReq.overrideMimeType('text/xml');
    }
  } else if (window.ActiveXObject) {
    // IE 6
    try {
      xmlHttpReq = new ActiveXObject('Msxml2.XMLHTTP.5.0');
    } catch(e) {
      try {
        xmlHttpReq = new ActiveXObject('Msxml2.XMLHTTP.4.0');
      } catch(e) {
        try {
          xmlHttpReq = new ActiveXObject('Msxml2.XMLHTTP.3.0');
        } catch(e) {
          try {
            xmlHttpReq = new ActiveXObject('Msxml2.XMLHTTP');
          } catch(e) {
            try {
              xmlHttpReq = new ActiveXObject('Microsoft.XMLHTTP');
            } catch(e) {
              xmlHttpReq = null;
            }
          }
        }
      }
    }
  }

  return xmlHttpReq;
}

XmlHttpRequest.prototype.send = function(host, query, handler, callback, async)
{
  var xmlHttpReq = XmlHttpRequest.create();
  if (xmlHttpReq) {
    if (async == undefined) {
      xmlHttpReq.open('POST', host, true);
    } else {
      xmlHttpReq.open('POST', host, async);
    }
    xmlHttpReq.setRequestHeader("Content-Type", "text/xml");
    xmlHttpReq.onreadystatechange = function()
    {
      if (xmlHttpReq.readyState == 4) {
        // Wininet errors (mainly IE6 on https)
        switch (xmlHttpReq.status)
        {
        case 12002: // The request has timed out.
        case 12029: // The attempt to connect to the server failed.
        case 12030: // The connection with the server has been terminated.
        case 12031: // The connection with the server has been reset.
        case 12032: // Retry needed
        case 12152: // The server response could not be parsed.
        case 13030: // Custom code in Mozilla/FF when the o object's status and statusText properties are unavailable.
          // 1 shot retry
          xmlRequest(host, query, callback);
        break;
        default:
          if (xmlHttpReq.status == 200) {
            handler(callback, xmlHttpReq.responseText);
          }
        }
      }
    }
    xmlHttpReq.send(query);
    if (async == false) {
      //synchronous doesn't use handlers.  needs to return the response.
      return xmlHttpReq.responseText;
    }
  } else {
    alert('Unable to create xmlHttpReq');
  }
}
