(function(){

  if (!self.com) {self.com = {}}
  if (!com.havertys) {com.havertys = {}}
  com.havertys.AjaxFns = {};
  var fns = com.havertys.AjaxFns;
  
  fns.inspect = function(obj, index) {
    var msg = 'Object is of type ' + typeof(obj) + '\nPropreties:\n----------\n';
    if (obj != null) {
	    var i = 0;
	    if (!index) {index = 0;}
	    index = (index < 0) ? 0 : index;
	    for (p in obj) {
	      if (i >= index) {
	      	try {
	            msg += p + " = " + obj[p] + "\n";
	        } catch (err) { msg += err + "\n"; }
	      }
	      i++;
	    }
	}
    alert(msg);
  };
  fns.visible = function(id, text) {
	var msg = dojo.byId(id); if (!msg){return;}
	if (text != null) { msg.innerHTML = text; }
	msg.style.visibility = 'visible';
  };
  fns.invisible = function(id, text) {
	var msg = dojo.byId(id);if (!msg){return;}
	msg.style.visibility = 'hidden';
  };
  fns.unhide = function(id, text) {
	var msg = dojo.byId(id);if (!msg){return;}
	var od = msg._oldDisplay;
	if (od && od != 'none') {
		msg.style.display = od;
	} else {
		msg.style.display = '';
	}
  };
  fns.hide = function(id, text) {
	var msg = dojo.byId(id);if (!msg){return;}
	msg._oldDisplay = msg.style.display;
	msg.style.display = 'none';
  };
  fns.unshiftNode = function(parent, child) {
    if (parent == null || child == null) { return; }
    if (parent.hasChildNodes()) {
  	  parent.insertBefore(child, parent.firstChild);
    } else {
      parent.appendChild(child);
    }
  };
  fns.selectOptByText = function(sel,text) {
    if (sel == null || text == null || sel.options == null) return;
    var opts = sel.options, found=false;
    for (var i = 0; i < opts.length; i++) {
      if (opts[i].text == text) {sel.selectedIndex = i; found=true;break;}
    }
    return found;
  };
  fns.selectOptByValue = function(sel,val) {
    if (sel == null || val == null || sel.options == null) return;
    var opts = sel.options, found=false;
    for (var i = 0; i < opts.length; i++) {
      if (opts[i].value == val) {sel.selectedIndex = i; found=true;break;}
    }
    return found;
  };
  fns.moveAll = function(srcSel,destSel,removeOpt)
  {
    if (srcSel && destSel)
    {
      var toCopy, newOpts = new Array();
      for (var i=srcSel.length-1; i>=0; i--)
      {
        toCopy = srcSel.options[i];
        newOpts[newOpts.length] = new Option(toCopy.text, toCopy.value);
        if (removeOpt) {
          srcSel.remove(i);
        }
      }
      com.havertys.AjaxFns.insertAndSort(newOpts, destSel);
    }
  };
  fns.insertAndSort = function(newOpts, sel)
  {
  //or find, insert before
    var curOpts = sel.options;
    var keys = new Array();
    var map = new Array();
    var o;
    for (var i=0; newOpts && (i < newOpts.length); i++)
    {
      o = newOpts[i];
      keys[keys.length] = o.text;
      map[o.text] = o;
    }
    for (var i=0;i<sel.length;i++)
    {
      if (! map[curOpts[i].text] )
      {
        keys[keys.length] = curOpts[i].text;
        map[curOpts[i].text] = curOpts[i];
      }
    }

    keys.sort();
    sel.options.length=0;
    for (i=0;i<keys.length;i++)
    {
      sel.options[i] = map[keys[i]];
    }
  };
  fns.createElement = function(type, id, content /*either innerHTML or value*/) {
    var el = document.createElement(type);
    if (id != null) {el.id = id; }
    if (content != null) {
      if (typeof el.innerHTML != 'undefined') {el.innerHTML = content;}
      else if (typeof el.value != 'undefined') {el.value = content;}
    }
    return el;
  };
  fns.setContent = function(id,content) {
    var el = dojo.byId(id);
    if (!el) {return;}
    if (content != null) {
      if (typeof el.innerHTML != 'undefined') {el.innerHTML = content;}
      else if (typeof el.value != 'undefined') {el.value = content;}
    }
  }
  fns.createXmlDoc = function(text) {
  	var xmlDoc;
    try {//Internet Explorer
      xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
      xmlDoc.async="false";
      xmlDoc.loadXML(text);
    } catch(e) {
      try {//Firefox, Mozilla, Opera, etc.
        parser=new DOMParser();
        xmlDoc=parser.parseFromString(text,"text/xml");
      } catch(e) {}
    }
	return xmlDoc;
  }
  fns.toArray = function(pseudoArray) {
  		if (pseudoArray instanceof Array) return pseudoArray;
        var realArray = [];
        if (pseudoArray && pseudoArray.length){
            for (var arrayIndex = 0; arrayIndex < pseudoArray.length; arrayIndex++) {
                realArray.push(pseudoArray[arrayIndex]);
            }
        }
        return realArray;
    }
  fns.sendForm = function(theForm/*required*/, loadFn/*required*/, errMsgId, toMsgId) {
	fns._sendForm(theForm, loadFn, errMsgId, toMsgId, "text/html");
  }
  fns.sendFormJson = function(theForm/*required*/, loadFn/*required*/, errMsgId, toMsgId) {
	fns._sendForm(theForm, loadFn, errMsgId, toMsgId, "text/json");
  }
  fns._sendForm = function (theForm, loadFn, errMsgId, toMsgId, mime) {
    var req = fns.createReq(theForm, loadFn, errMsgId, toMsgId, mime);
    if (errMsgId != null) {this.hide(errMsgId);}
    if (toMsgId != null) {this.hide(toMsgId);}
    dojo.io.bind(req);
  };
  fns.createJsonReq = function(theForm/*required*/, loadFn/*required*/, errMsgId, toMsgId) {
    return fns.createReq(theForm, loadFn, errMsgId, toMsgId, "text/json");
  };
  fns.createReq = function(theForm/*required*/, loadFn/*required*/, errMsgId, toMsgId, mime) {
    mime = mime || "text/html";
    var req = { formNode: theForm, 
		load	: loadFn,
		mimetype: mime,
		method	: "GET",
		error	: fns._sendError /*event.connect to sendError not this event*/,
		timeoutSeconds: (navigator.appVersion.indexOf('Safari') == -1)? 15 : 20,
		timeout	: fns._sendTimeout /*event.connect to sendTimeout not this event*/
    };
    req.errMsgId = errMsgId; req.toMsgId = toMsgId;
    return req;
  };
  fns._sendError = function(type, data, evt) {
    if (!fns.sendError()){return;}
    if (this.errMsgId) { fns.unhide(this.errMsgId); }
  };
  fns.sendError = function(){return true;};
  fns._sendTimeout = function(type, data, evt) {
  	if (!fns.sendTimeout()){return;}
    if (this.toMsgId) { fns.unhide(this.toMsgId); }
  };
  fns.sendTimeout = function(){return true;}
  /**
   * Creates and / or sends an ajax request
   * Accepts the params used in dojo.io.bind:
   * url, formNode, load, mimetype, method, error,
   * timeoutSeconds, timeout
   * NOTE* defaults will be provided for mimetype, method, error,
   * 	   timeoutSeconds, and timeout
   * 
   * Additional params are:
   * send  -> true (default) | false ~ whether or not send the request
   * msgId -> the id of the element used to display messages
   * hideType 'none' (default) | 'hidden' ~ display none
   * 									  ~ visibility hidden
   * 		> used to hide the element referenced by msgId
   * timeoutMsg (default: 'Your request timed out. Please try again.')
   * 		> the message to display if request times out, *requires msgId
   * 		> override by providing a timeout function
   * errorMsg (default: 'There was an error processing your request.')
   * 		> the message to display if an error occurs, *requires msgId
   * 		> override by providing an error function
   * dialogId -> the idModifier for the dialog to overlay while the
   * 		> request is being made.  This makes the request modal.
   * 		> This requires uimgr must be present.
   * openDialog true (default) | false ~ if a dialogId is provided,
   * 		> whether to open the dialog or leave in its current viewing
   * 		> state.
   * dialogMsg -> The message to display in the modal dialog
   *			> The dialog has its own default msg is none is provided
   * 
   * @param {Object} arg ~ an object with the above properties
   * @return req the request prepared for dojo.io.bind
   */
  fns.ajaxRequest= function(arg) {
    var req = {
		mimetype: "text/html",
		method	: "GET",
		error	: fns._ajaxSendError /*event.connect to ajaxSendError not this event*/,
		timeoutSeconds: (navigator.appVersion.indexOf('Safari') == -1)? 15 : 20,
		timeout	: fns._ajaxSendTimeout, /*event.connect to ajaxSendTimeout not this event*/
		send    : true,
		openDialog: true,
		hideType: 'none',
		timeoutMsg: 'Your request timed out. Please try again.',
		errorMsg  : 'There was an error processing your request.'
    };
	for (prop in arg) {
		req[prop] = arg[prop];
	}
	if (req.send) {
		//display msgs
		if (req.msgId) {
			if (req.hideType == 'hidden') {
				com.havertys.AjaxFns.invisible(req.msgId);
			} else {
				com.havertys.AjaxFns.hide(req.msgId);
			}
		}
		//modal dialog
		if (req.dialogId) {
			uimgr.lockDialog(req.dialogId, {show: req.openDialog,
											msg : req.dialogMsg});
			req.unlockDialog=com.havertys.AjaxFns.unlockDialog;
		}
		req._load = req.load;
		req.load = AjaxFns._ajaxCallLoad;
		dojo.io.bind(req);
	}
	return req;
  }/* end ajaxRequest */
  fns.ajaxCallLoad =  function(){return true;};
  fns._ajaxCallLoad = function(type, data, evt) {
    if (!fns.ajaxCallLoad(type, data, evt)){return;}
    if (this._load) {
	  this._load.apply(this, new Array(type, data, evt));
    }
  };
  fns._ajaxSendError = function(type, data, evt) {
    if (!fns.sendError()){return;}
    if (this.dialogId) {
      uimgr.unlockDialog(this.dialogId, {hide: this.openDialog})
    }
	com.havertys.AjaxFns.showAjaxMsg(this.msgId,this.errorMsg,this.hideType);
  };
  fns.ajaxSendError = function(){return true;};
  fns._ajaxSendTimeout = function(type, data, evt) {
  	if (!fns.sendTimeout()){return;}
  	if (this.dialogId) {
      uimgr.unlockDialog(this.dialogId, {hide: this.openDialog})
    }
    com.havertys.AjaxFns.showAjaxMsg(this.msgId,this.timeoutMsg,this.hideType);
  };
  fns.ajaxSendTimeout = function(){return true;};
  fns.unlockDialog = function(req){
    req = req || this;
    uimgr.unlockDialog(req.dialogId, {hide: req.openDialog || req.closeDialog});
  };
  fns.isJsonValidSesssion = function(html) {
  	var data;
  	if (typeof html == 'string') {
		data = eval("(" + html+ ")");
	}else {
		data = html;
	}
	//if property set use it, otherwise session is valid
  	return data.validSession || !('validSession' in data);
  };
  fns.isHTMLValidSesssion = function(html) {
    var errlog = html.indexOf('CMN3101E');
    var hasErrCode = errlog != -1;
    var hasRelog = html.indexOf('<title>Session Expired</title>') != -1 || html.indexOf('http-equiv="Refresh"') != -1;
  	//return !(html.indexOf('ReLogonFormView') != -1 || html.indexOf('CMN3101E') != -1);
  	return !hasRelog && !hasErrCode;
  };
  fns.showAjaxMsg = function(msgId,msg,hideType)
  {
	com.havertys.AjaxFns.setContent(msgId,msg);
	if (hideType == 'hidden') {
		com.havertys.AjaxFns.visible(msgId);
	} else {
		com.havertys.AjaxFns.unhide(msgId);
	}
  };
  fns.popUp = function(contentid, obj, e, xoff, yoff) {
    if (!obj) return;
    if (typeof obj == 'string'){obj = dojo.byId(obj);}
    if (window.event) {event.cancelBubble=true;}
    else if (e && e.stopPropagation) {
      try { e.stopPropagation(); 
      } catch (err) {/* dojo may overwrite default function */}
    }
    var dropmenuobj=document.getElementById(contentid);
    dojo.byId(contentid).style.top = '-10000px';
    fns.unhide(contentid);
    fns.visible(contentid);
	this.Position.repositionPopupMenu(contentid, obj.id, xoff, yoff);
	
  };
  fns.Position = {
  	clearbrowseredge: function (dropmenuobj, obj, whichedge){
		var edgeoffset=0;
		if (whichedge=="rightedge"){
			var windowedge=ie4 && !window.opera? this.iecompattest().scrollLeft+this.iecompattest().clientWidth-15 : window.pageXOffset+window.innerWidth-15;
			if(dropmenuobj.offsetWidth)
				dropmenuobj.contentmeasure = dropmenuobj.offsetWidth;
			else {
				dropmenuobj.contentmeasure = 287;
			}
			if (windowedge-dropmenuobj.x < dropmenuobj.contentmeasure) {
				edgeoffset = dropmenuobj.contentmeasure - (windowedge - dropmenuobj.x);
			}
		} else {
			var topedge=ie4 && !window.opera? this.iecompattest().scrollTop : window.pageYOffset;
			var windowedge=ie4 && !window.opera? this.iecompattest().scrollTop+this.iecompattest().clientHeight-15 : window.pageYOffset+window.innerHeight-18;
			dropmenuobj.contentmeasure=dropmenuobj.offsetHeight;
			if (windowedge-dropmenuobj.y < dropmenuobj.contentmeasure){ 
				edgeoffset=dropmenuobj.contentmeasure+obj.offsetHeight;
				if ((dropmenuobj.y-topedge)<dropmenuobj.contentmeasure) 
					edgeoffset=dropmenuobj.y+obj.offsetHeight-topedge;
			}
		}
		return edgeoffset;
	},
	iecompattest: function(){
		return (document.compatMode && document.compatMode!="BackCompat")? document.documentElement : document.body;
	},
	getParentOffset: function(obj, offsettype){
		var totaloffset=0;
		var parentEl=obj.offsetParent;
		while (parentEl!=null){
			totaloffset=(offsettype=="left")? totaloffset+parentEl.offsetLeft : totaloffset+parentEl.offsetTop;
			parentEl=parentEl.offsetParent;
		}
		return totaloffset;
	},
	getposOffset: function(obj, offsettype){
		var totaloffset=(offsettype=="left")? obj.offsetLeft : obj.offsetTop;
		return totaloffset + this.getParentOffset(obj, offsettype);
	},
	repositionPopupMenu: function(elId,refId,xoff,yoff) {
	    var el = dojo.byId(elId);
	    xoff = xoff || 0; yoff = yoff || 0;
	    el.style.top = '-10000px';
	    setTimeout('com.havertys.AjaxFns.Position.doReposition("'+elId+'","'+refId+'","'+xoff+'","'+yoff+'");',0);
	},
	doReposition: function(elId,refId,xoff,yoff) {
		xoff = parseInt(xoff ||0); yoff=parseInt(yoff||0);
		var el = dojo.byId(elId);
		var ref = dojo.byId(refId);
		fns.invisible(elId);
		el.x=parseInt(getposOffset(ref, "left")) + xoff;
		el.y=parseInt(getposOffset(ref, "top")) + yoff;
		el.style.left=el.x - this.getParentOffset(el, "left") -(this.clearbrowseredge(el, ref, "rightedge"))+"px";
		el.style.top=el.y - this.getParentOffset(el, "top") -this.clearbrowseredge(el, ref, "bottomedge")+(ref.offsetHeight)+"px";
		fns.visible(elId);
	}
  };
  fns.wrapDojoIoBind = function(inv) {
  	if (inv.args.length == 0) { return inv.proceed();} 
  	
  	var req = inv.args[0];
  	if (req.load != null) {
  		var loadFn = req.load;
  		req.load = function (type,data,evt) {
  			var validSession;
			try {
				var isJson = (typeof data != 'string');
				if (isJson) {
					try {
						validSession = com.havertys.AjaxFns.isJsonValidSesssion(data)
					} catch (err) {//try raw data
						validSession = com.havertys.AjaxFns.isHTMLValidSesssion(evt.responseText)
					}
				} else {
					validSession = com.havertys.AjaxFns.isHTMLValidSesssion(data)
				}
				validSession = validSession || (uType == 'G')
			}
			catch(err){
				return loadFn.apply(this, new Array(type, data, evt));
			}
			if (! validSession) {
				goToReLogon();
			} else {
				return loadFn.apply(this, new Array(type, data, evt));
			}
  		}
  	}
  	return inv.proceed();
  };
  fns.initAjaxWrapper = function() {
  	if (! com.havertys.AjaxFns.initAjaxWrapper.done) {
	  	dojo.event.connect('around', dojo.io, 'bind', com.havertys.AjaxFns, 'wrapDojoIoBind');
	}
  	com.havertys.AjaxFns.initAjaxWrapper.done = true;
  };
  //delete fns;
})();
var AjaxFns = com.havertys.AjaxFns;
AjaxFns.initAjaxWrapper();