﻿/************************************************************************************
 * StraightReach IVR JavaScript library, including floating panel, clickable tree and
 * JSON logic.
 * All global vars and functions starts with "ivr", use as a namespace.
 * USAGE: 
 * www.straightreach.com will give out standard code snippet to use the code  
 *  
 * keywords used by Obfuscation Enforcement Monitor Service:                                                               
/*************************************************************************************/

/******************** global public configuration data ******************************/
//IMPORTANT CONFIGURATION: "localhost" "beta" "prod"
var ivrDeployAt = ""; 
 
//turn on/off debug mode
var ivrDebug = false;

//get data from DB/JSON/XML: for dev
var ivrIsDataFromDB = true;
var ivrIsDataFromJson = false;

//location of the server script and files
var ivrUrls = new Array( /********* server/directory ********/
                         /*0*/ "" /*default, same directory*/,
                         /*1*/ "http://copernicus/ivrtest/", 
                         /*2*/ "http://localhost/ivrtest/",     /*old local client*/  
                         /*3*/ "http://semperon/test/lytest/",  /*old remote server*/
                         /************* local location ***************/
                         /*4 "http://copernicus/ivr/", */       /*ivr local server*/
						 /*4*/ "http://localhost:2580/StraightReach/",
                         /************* file ***************/
                         /*5*/ "IvrGetTree.aspx", 
                         /*6*/ "straightreach.json",
                         /*7*/ "straightreach.xml",
                         /*8*/ "straightreach2.json", 
                         /********** prod locations ********/ 
                         /*9*/  "http://www.straightreach.com/", 
                         /*10*/ "https://www.straightreach.com/", 
                         /********** beta locations ********/
                         /*11*/ "http://204.170.208.190/", 
                         /*12*/ "https://204.170.208.190/"
                        );
//local: 4; prod: 9, beta: 11;                 
var ivrServerLoc = "";  
var ivrServerScriptLoc = ""; /* where to get tree */

//tree icons
var ivrRightArrowImg = new Image();
var ivrRightDownArrowImg = new Image();
var ivrTreeRootName = "phone-menu.gif";

//floating panel parameters
//part of the IvrFloatingPanel class
IvrFloatingPanel.X_OFFSET = 0;  // Pixels to the right of the mouse pointer
IvrFloatingPanel.Y_OFFSET = 0;  // Pixels below the mouse pointer
IvrFloatingPanel.SHADOW_X_OFFSET = 4;  // shadow
IvrFloatingPanel.SHADOW_Y_OFFSET = 4;  // shadow
IvrFloatingPanel.SHOW_DELAY = 100;    //when click/mouseover, how long before show 
IvrFloatingPanel.RETRY_DELAY = 666; //If the data is not loaded yet, how long to retry
IvrFloatingPanel.SHIFT_OFFSET = 30;

/******************** global private data, don't touch ****************************/
//phone numbers and their associated data in the client's page
//the main container
var ivrObjsPointer = -1;  
var ivrObjs = new Array();
var ivrObjsCurrentPointer;

//test browser
var ivrNumber = "number"; 

//build the tree content global var
var ivrTmpArray;
var ivrTmpArrayPointer;
var ivrId = -1;
var ivrIsCodeUseLegal = true; 
var ivrIsHttps = false;
/******************** public API, for the user to call ***************************/
//ivrShow('2151234567', this, event); 'this'/target is the html element, e.g. <img/>
function srShow(inputPhoneNum, target, evt) 
{
    //sanity check for image code use
    if(target == null)
        ivrIsCodeUseLegal = false
    else {
        var imgUsed = target.src;
        if(imgUsed != (ivrUrls[9] + "image/" + ivrTreeRootName) &&
           imgUsed != (ivrUrls[10] + "image/" + ivrTreeRootName) ) 
            ivrIsCodeUseLegal = false;
    }   
    
    //get location (ivrDeployAt)
    if(ivrDeployAt == "") {
        var scriptElementsArray = new Array();
        scriptElementsArray = document.getElementsByTagName("script");
        
        for (var i = 0; i < scriptElementsArray.length; i++) {
            var scriptElement = scriptElementsArray[i];
            if(scriptElement.src.indexOf("straightreach.js") > -1) {
                if(scriptElement.src.indexOf("localhost") > -1 || 
                    scriptElement.src.indexOf("copernicus") > -1 ) 
                    ivrDeployAt = "localhost";
                else if(scriptElement.src.indexOf("204.170.208.190") > -1) 
                    ivrDeployAt = "beta";
                else if(scriptElement.src.indexOf("straightreach.com") > -1) 
                    ivrDeployAt = "prod";
                break;
            }
        }  
        
        //check if https or http
        if("https:" == document.location.protocol) {
            ivrIsHttps = true;
            ivrServerLoc = (ivrDeployAt == "prod") ? ivrUrls[10] : ((ivrDeployAt == "beta") ? ivrUrls[12]: ivrUrls[4]);  
        } else {
            //local: 4; prod: 9, beta: 11;                 
            ivrServerLoc = (ivrDeployAt == "prod") ? ivrUrls[9] : ((ivrDeployAt == "beta") ? ivrUrls[11]: ivrUrls[4]);  
        }
        
        ivrServerScriptLoc = ivrServerLoc + ivrUrls[5]; // where to get tree 
    }//get location ends 
    
    //load images
    ivrRightArrowImg.src = ivrServerLoc + "image/ivrRightArrow.gif"; 
    ivrRightDownArrowImg.src = ivrServerLoc + "image/ivrRightDownArrow.gif";
    
    //real stuff
    window.onresize = ivrResize;
    //document.body.onresize = ivrResize;
    //window.onscroll = ivrResize;
    var phoneNum = ivrNormalizePhoneNum(inputPhoneNum);
    var seenIndex = ivrGetSeenNumberIndex(phoneNum);
    
    if(seenIndex == -1) {                  
        //never seen before in this page     
        ivrObjsPointer++;
        var newIvrObj = new IvrFloatingPanel(phoneNum, ivrObjsPointer, target);
        ivrObjs[ivrObjsPointer] = newIvrObj;  
        seenIndex = ivrObjsPointer;  
        newIvrObj.getTreeContentFromServer(); 
    }   

    ivrObjs[seenIndex].scheduleShow(target, evt.clientX, evt.clientY); 
}

function srHide()
{
    for(var i = 0; i < ivrObjs.length; i++)
        ivrObjs[i].hide();
}
/******************** floating panel code *************************/
// The constructor function for the IvrFloatingPanel class
function IvrFloatingPanel(inputPhoneNum, inputIndex, target)      
{    
    this.imgObj = target;
    this.phoneNum = inputPhoneNum;   
    this.treeContent = "";   
    this.index = inputIndex;
    ivrObjsCurrentPointer = this.index;  
     
    //get the container div of the table/tree     
    this.panel = document.createElement("div"); // create div for content
    this.panel.className = "ivrFloatingPanel";   
       
    this.shadow = document.createElement("div");  
    this.shadow.className = "ivrFloatingPanelShadow";
     
    //this.panel.appendChild(this.shadow);
    
    // Add the IvrFloatingPanel to the document if it has not been added before
    if (this.panel.parentNode != document.body) 
        document.body.appendChild(this.panel);
    if (this.shadow.parentNode != document.body)
        document.body.appendChild(this.shadow);
    
    /*** the tree in a table ***/
    this.contentTable = document.createElement("table");
    this.contentTable.className = "ivrFloatingPanelTable";
    this.contentTable.setAttribute("border", "0");
    this.contentTable.setAttribute("cellspacing", "0");
    this.contentTable.cellSpacing = "0";
    this.contentTable.setAttribute("cellpadding", "3");
    this.panel.appendChild(this.contentTable);
    
    //head
    this.closeHead = document.createElement("thead");
    this.contentTable.appendChild(this.closeHead);
    
    this.closeRow = document.createElement("tr"); 
    this.closeHead.appendChild(this.closeRow);
    
    this.hintCell = document.createElement("td");
    this.hintCell.setAttribute("align", "left");
    this.hintCell.className = "ivrFloatingPanelHintCell";
    this.closeRow.appendChild(this.hintCell); 
    this.hintTxt = document.createTextNode("Click on \"+\" to expand");
    this.hintCell.appendChild(this.hintTxt); 
     
    this.closeCell = document.createElement("td");
    this.closeRow.appendChild(this.closeCell); 
    this.closeCell.className = "ivrFloatingPanelCloseCell";
    this.closeCell.setAttribute("align", "right");
    this.closeTxt = document.createTextNode("Close"); 
    this.closeCell.appendChild(this.closeTxt); 
    
    //body
    this.contentBody = document.createElement("tbody");
    this.contentTable.appendChild(this.contentBody);
    
    this.contentRow = document.createElement("tr");
    this.contentBody.appendChild(this.contentRow);
    
    this.contentCell = document.createElement("td");
    this.contentCell.colSpan = "2";
    this.contentCell.className = "ivrFloatingPanelContentCell";
    this.contentCell.setAttribute("align", "left");
    this.contentRow.appendChild(this.contentCell);
    
    //foot
    this.tableFoot = document.createElement("tfoot");
    this.contentTable.appendChild(this.tableFoot);
    
    this.footRow = document.createElement("tr");
    this.tableFoot.appendChild(this.footRow);
    
    this.footCell = document.createElement("td");
    this.footCell.colSpan = "2";
    this.footCell.setAttribute("align", "left");
    this.footCell.className = "ivrFloatingPanelFootCell";
    this.footRow.appendChild(this.footCell);
    
	this.infoTxt = document.createTextNode("Powered by ");
    this.footCell.appendChild(this.infoTxt); 
    
    this.aCell = document.createElement("a");
    this.aCell.className = "ivrFloatingPanelFootACell"
    this.aCell.href = "#";
    ivrAddEventFunction(this.aCell, "click", clickPower);
    function clickPower() { 
        window.open((ivrIsHttps ? "https://" : "http://" ) + "www.straightreach.com", 
                    '', 
                    'toolbar=yes,location=yes,directories=yes,status=yes,menubar=yes,scrollbars=yes,resizable=yes,width=900,height=700,left=0,top=0'); 
        return false;    
    } 
    
    this.aTxtCell = document.createTextNode("StraightReach");
    this.aCell.appendChild(this.aTxtCell);
    this.footCell.appendChild(this.aCell);
     
    this.supCell = document.createElement("sup"); 
    this.supTxt = document.createTextNode("SM");
    this.supCell.className = "ivrFloatingPanelFootSupCell";
    this.supCell.appendChild(this.supTxt); 
    this.footCell.appendChild(this.supCell); 
    /*** table ends ***/
}

//target is e.g. the img element, e is the event e.g. click.. 
IvrFloatingPanel.prototype.scheduleShow = function(target, clientX, clientY) { 
    
    //for offsetwidth
    this.originalClientX = clientX; 
    this.originalClientY = clientY;
    
    // Schedule the display of the IvrFloatingPanel
    var self = this;  //need this for the nested functions below
    /*var insideTimer;
    var timer = window.setTimeout(function() {  
                                      insideTimer = self.show(clientX, clientY); 
                                  }, IvrFloatingPanel.SHOW_DELAY);
                                  */
    this.show(clientX, clientY);                           

    //register an onclick handler to hide a IvrFloatingPanel or cancel
    //the pending display of a IvrFloatingPanel. 
    ivrAddEventFunction(this.closeCell, "click", clickClose);
    function clickClose() { 
        self.hide();                // Hide the IvrFloatingPanel if it is displayed,
       //window.clearTimeout(timer); // cancel any pending display or retry
        //window.clearTimeout(insideTimer);
        ivrRemoveEventFunction(self.closeCell, "click", clickClose);
        ivrRemoveEventFunction(self.panel, "click", checkOverflow);
        //ivrRemoveEventFunction(self.panel, "click", resizeShadow);
    } 
    
    ivrAddEventFunction(this.panel, "click", checkOverflow); 
    function checkOverflow() { 
        self.checkOverflow(); 
    }
}  
  
// Set the content and position of the IvrFloatingPanel and display it 
IvrFloatingPanel.prototype.show = function(clientX, clientY) { 
    //hide others 
    for(var i = 0; i < ivrObjs.length; i++)
        ivrObjs[i].hide();

    //show self
    //1.load information
    var self = this;
    var retryId;    
    if(this.treeContent == "") {
        this.contentCell.innerHTML = "Loading...";
        retryId = window.setInterval( function() {
                var currentInnerHTMLStr = self.contentCell.innerHTML;
                if(self.treeContent == "") {
                    if(currentInnerHTMLStr.indexOf("................") > -1)
                        self.treeContent = "Information temporarily unavailable. Please try again later. Error Code: 103 (Internal Error)";
                    else {
                        self.contentCell.innerHTML = currentInnerHTMLStr + ".";
                    }
                } else { 
                    self.contentCell.innerHTML = self.treeContent;
                    window.clearInterval(retryId);
                }
                self.resizeShadow();
            }, IvrFloatingPanel.RETRY_DELAY);
    } else {
        self.contentCell.innerHTML = self.treeContent; 
    } 
       
    // 2. decide position 
    // event object holds the mouse position in window coordinate   
    // Convert these to document coordinates using the ivrGeometry module
    // window coor -> doc coor
    var x = clientX + ivrGetHorizontalScroll();
    var y = clientY + ivrGetVerticalScroll();
    
    //compare left vs right, top vs down, whereever is bigger, put the panel there.
    //imp: set others to auto  
    if(clientX > ivrGetViewportWidth()/2) { //right 
        var right = (ivrGetViewportWidth() - x) - IvrFloatingPanel.X_OFFSET;
        this.panel.style.right = right + "px";
        this.panel.style.left = "auto";
        this.originalRight = this.panel.style.right;
    } else {  //left
        var left = x + IvrFloatingPanel.X_OFFSET; 
        this.panel.style.left = left + "px"; 
        this.panel.style.right = "auto";  
    } 
        
    if(clientY > ivrGetViewportHeight()/2) { //bottom
        var bottom = ivrGetViewportHeight() - y;
        this.panel.style.bottom = bottom + "px";
        this.panel.style.top = "auto";
        this.originalBottom = this.panel.style.bottom;
    } else { //top
        var top = y + IvrFloatingPanel.Y_OFFSET;
        this.panel.style.top = top + "px";
        this.panel.style.bottom = "auto";
    }
    
    this.panel.style.width = "auto";  
    this.panel.style.height = "auto";
     
    //3. show panel 
    this.panel.style.display = "block";     

    //4. show shadow  
    this.shadow.style.display = "block";  
    this.resizeShadow(); 
         
    return retryId;                                     
};

IvrFloatingPanel.prototype.resizeShadow = function() { 
    if(this.shadow) {
        var left = this.panel.style.left;
        var right = this.panel.style.right; 
        var top = this.panel.style.top; 
        var bottom = this.panel.style.bottom; 
        var leftInt = parseInt(left);
        var rightInt = parseInt(right); 
        var topInt = parseInt(top); 
        var bottomInt = parseInt(bottom);   
        
        this.shadow.style.width = this.panel.offsetWidth + "px";
        this.shadow.style.height = this.panel.offsetHeight + "px";
         
        //TODO: Left/Right no need to adjust shadow offset. Why?
        if(left.indexOf("auto") > -1) {
            this.shadow.style.right = (rightInt - IvrFloatingPanel.SHADOW_X_OFFSET) + "px";
            //this.shadow.style.right = rightInt + "px";
            this.shadow.style.left = "auto";
        } else if(right.indexOf("auto") > -1) {
            //this.shadow.style.left = (leftInt + IvrFloatingPanel.SHADOW_X_OFFSET) + "px";
            this.shadow.style.left = leftInt + "px";
            this.shadow.style.right = "auto";
        } 
        
        if(top.indexOf("auto") > -1) {
            this.shadow.style.bottom = (bottomInt - IvrFloatingPanel.SHADOW_Y_OFFSET) + "px";
            this.shadow.style.top = "auto";
        } else if(bottom.indexOf("auto") > -1) {
            this.shadow.style.top = (topInt + IvrFloatingPanel.SHADOW_Y_OFFSET) + "px"; 
            this.shadow.style.bottom = "auto";
        }
    }
}

IvrFloatingPanel.prototype.checkWindowResize = function() { 
    if(this.panel.style.display == "none" && this.shadow.style.display == "none")
        return;
    //this.hide(); 
    //this.scheduleShow(null, this.originalClientX, this.originalClientY);
    //get the current tooltips position on the fly, and show the floating panel
    this.getImgPos();
    this.currentImgObjLeft -= ivrGetHorizontalScroll();
    this.currentImgObjTop -= ivrGetVerticalScroll();
    this.scheduleShow(null, this.currentImgObjLeft + 6, this.currentImgObjTop + 3);
} 

//IvrFloatingPanel.SHIFT_OFFSET = 6; 
IvrFloatingPanel.prototype.checkOverflow = function() { 
    if(this.panel.style.left == "auto" && this.panel.offsetWidth <= this.originalClientX) {
        this.panel.style.right = this.originalRight;
    } else if(this.panel.style.left == "auto" && this.panel.offsetWidth > this.originalClientX) {
        var right = ivrGetViewportWidth() - this.panel.offsetWidth - IvrFloatingPanel.SHIFT_OFFSET - ivrGetHorizontalScroll();
        this.panel.style.right = right + "px";
    } 
     
    if(this.panel.style.top == "auto" && this.panel.offsetHeight < this.originalClientY ) {
        this.panel.style.bottom = this.originalBottom;
    } else if(this.panel.style.top == "auto" && this.panel.offsetHeight > this.originalClientY ) {
        var bottom = ivrGetViewportHeight() - this.panel.offsetHeight - IvrFloatingPanel.SHIFT_OFFSET - ivrGetVerticalScroll();
        this.panel.style.bottom = bottom + "px";
    }    
    
    this.resizeShadow();
}

// Hide the IvrFloatingPanel
IvrFloatingPanel.prototype.hide = function() {
    this.panel.style.display = "none";
    this.shadow.style.display = "none";
}; 

//get the img object current position
IvrFloatingPanel.prototype.getImgPos = function() {
	//this.imgObj, this.currentImgObjLeft, this.currentImgObjTop;
	var tmpLeft = tmpTop = 0;
	var tmpImgObj = this.imgObj
	if(tmpImgObj && tmpImgObj.offsetParent) {
	    do {
	        tmpLeft += tmpImgObj.offsetLeft;
			tmpTop += tmpImgObj.offsetTop;
		} while (tmpImgObj = tmpImgObj.offsetParent);
		
		//set results
		this.currentImgObjLeft = tmpLeft;
		this.currentImgObjTop = tmpTop;
	}
}

/******************** clickable tree code *************************/
//dynamically expand tree
function ivrShowTreeBranch(branch) 
{
    var branchStyle = 
        ivrGetElementById(branch).style; 
        
    if(branchStyle.display == "block")
        branchStyle.display = "none";
    else
        branchStyle.display = "block";
}
   
function ivrSwapTreeIcon(img) 
{
    var objImg = ivrGetElementById(img);
    if(objImg.src.indexOf('ivrRightArrow.gif')>-1)
        objImg.src = ivrRightDownArrowImg.src;
    else
        objImg.src = ivrRightArrowImg.src;
}

/******************** utility functions **********************/
function ivrNormalizePhoneNum(phoneNum) 
{ 
    return phoneNum.replace(/[^\d]/g, "");
}

//if not seen, return -1 
function ivrGetSeenNumberIndex(inputPhoneNum)
{
    for(var i = 0; i < ivrObjs.length; i++) {
        if(ivrObjs[i].phoneNum.indexOf(inputPhoneNum) > -1)
            return i;
    }
    return -1; 
} 

//cross-browser getElementById
function ivrGetElementById(id)
{
	return(document.getElementById ? document.getElementById(id)
			: document.all ? document.all[id]
			: null);
}  

//cross-browser register events 
function ivrAddEventFunction(element, eventString, func)
{ 
	if(element)
	{
		if(element.addEventListener)
			element.addEventListener(eventString, func, false);
		else if(element.attachEvent)
			element.attachEvent("on" + eventString, func);
	    else {
	        if(ivrDebug)
	            alert("sth wrong inside ivrAddEventFunction()");  
	    }
	}
}

function ivrRemoveEventFunction(element, eventString, func)
{
	if(element)
	{
		if(element.removeEventListener)
			element.removeEventListener(eventString, func, false);
		else if(element.attachEvent) 
			element.detachEvent("on" + eventString, func);
	    else { 
	        if(ivrDebug)
	            alert("sth wrong inside ivrRemoveEventFunction()");  
	    } 
	} 
}
 
//geometry code starts
//1. viewport width/height  
function ivrGetViewportWidth()
{
    if( typeof( window.innerWidth ) == ivrNumber &&
        typeof( window.innerHeight ) == ivrNumber ) {
        //Non-IE
        return window.innerWidth; 
    } else if( document.documentElement &&  
              typeof(document.documentElement.clientWidth) == ivrNumber &&
              typeof(document.documentElement.clientHeight) == ivrNumber &&
              document.documentElement.clientWidth != 0 && 
              document.documentElement.clientHeight != 0 ) {
        //IE 6+ in 'standards compliant mode'
        return document.documentElement.clientWidth; 
    } else {
        //IE 4 compatible
        return document.body.clientWidth; 
    } 
} 

function ivrGetViewportHeight() 
{
    if( typeof( window.innerWidth ) == ivrNumber &&
        typeof( window.innerHeight ) == ivrNumber ) {
        //Non-IE
        return window.innerHeight; 
    } else if( document.documentElement &&  
               typeof(document.documentElement.clientWidth) == ivrNumber &&
               typeof(document.documentElement.clientHeight) == ivrNumber &&
               document.documentElement.clientWidth != 0 && 
               document.documentElement.clientHeight != 0 ) {
        //IE 6+ in 'standards compliant mode'
        return document.documentElement.clientHeight; 
    } else {
        //IE 4 compatible
        return document.body.clientHeight; 
    }
} 

//2.scrollbar position
function ivrGetHorizontalScroll()
{ 
    if( typeof( window.pageYOffset ) == ivrNumber && 
        typeof( window.pageXOffset ) == ivrNumber ) {
        //Netscape compliant
        return window.pageXOffset; 
    } else if( document.documentElement && 
               typeof(document.documentElement.scrollLeft) == ivrNumber && 
               typeof(document.documentElement.scrollTop) == ivrNumber && 
               !(
                 document.body && 
                 typeof(document.body.scrollLeft) == ivrNumber &&
                 typeof(document.body.scrollTop) == ivrNumber && 
                 (
                  (document.documentElement.scrollLeft == 0 && document.body.scrollLeft != 0) ||
                  (document.documentElement.scrollTop == 0 && document.body.scrollTop != 0)
                 ) 
                )
             )   {
        //IE6 standards compliant mode 
        return document.documentElement.scrollLeft;  
    } else  {
        //DOM compliant
        return document.body.scrollLeft;  
    } 
} 

function ivrGetVerticalScroll() 
{
    if( typeof( window.pageYOffset ) == ivrNumber && 
        typeof( window.pageXOffset ) == ivrNumber ) {
        //Netscape compliant 
        return window.pageYOffset;  
    } else if( document.documentElement && 
               typeof(document.documentElement.scrollLeft) == ivrNumber && 
               typeof(document.documentElement.scrollTop) == ivrNumber && 
               !(
                 document.body && 
                 typeof(document.body.scrollLeft) == ivrNumber &&
                 typeof(document.body.scrollTop) == ivrNumber && 
                 (
                  (document.documentElement.scrollLeft == 0 && document.body.scrollLeft != 0) ||
                  (document.documentElement.scrollTop == 0 && document.body.scrollTop != 0)
                 ) 
                )
             )   {
        //IE6 standards compliant mode 
        return document.documentElement.scrollTop; 
    } else {
        //DOM compliant
        return document.body.scrollTop; 
    } 
} 
//geomery ends

//deal with window resize
//for now just hide the tree
function ivrResize() 
{
    ivrObjs[ivrObjsCurrentPointer].checkWindowResize();
}

/********************** JSON codes *****************************/ 
//the class function of a Panel 
IvrFloatingPanel.prototype.getTreeContentFromServer = function () {
    //for dev 
    if(ivrIsDataFromJson == false && ivrIsDataFromDB == false) {
        this.ajaxGetTreeContentFromServer();
        return; 
    }
    
    var jsonReq = new ivrJsonRequest(this.phoneNum, "ivrJsonCallback");
    jsonReq.appendScriptTag(); 
}

/*for dev: use ajax to get tree , should not be used in prod 
IvrFloatingPanel.prototype.ajaxGetTreeContentFromServer = function() {  
    var result;
    this.treeContent = "";
     
    var xhr; 
	try {  
	    xhr = new ActiveXObject('Msxml2.XMLHTTP');   
	} catch (e) {
		try {   
		    xhr = new ActiveXObject('Microsoft.XMLHTTP');    
		} catch (e2) {
			  try {  
			    xhr = new XMLHttpRequest();     
			  } catch (e3) {  
			    xhr = false;   
			  }
		}
    }
	  
	var self = this;
	xhr.onreadystatechange = function()
	{ 
		 if(xhr.readyState  == 4)
		 {
			  if(xhr.status  == 200) {
					var doc = xhr.responseXML;
					//init the tmp storage
                    
                    ivrTmpArray = new Array();
                    ivrTmpArrayPointer = -1; 
					var phoneNums = doc.getElementsByTagName("phoneNumber");
                    for(var i = 0, foundFlag = false; i < phoneNums.length; i++) {
                        if(phoneNums[i].childNodes[0].nodeValue.indexOf(self.phoneNum) > -1) {
                            foundFlag = true;
                            break;
                        }
                    }
                    
                    if(foundFlag) {        
                        ivrTraverse(phoneNums[i].parentNode);
                    } else {
                        ivrTmpArray[++ivrTmpArrayPointer] = "Information regarding this phone number cannot be found."
                    } 
					result = ivrTmpArray.join(" ");
					self.treeContent = result;
						
			    } else 
					result = "Information Currently Unavailabel. Ec: " + xhr.status;
	      }
	}; 

    //pass the phone number as a parameter 
	xhr.open('GET', ivrServerScriptLoc, true);  
	xhr.send(null);
} for dev: ajax get tree ends */ 

//the callback function of JSON
function ivrJsonCallback(jsonData)   
{    
    try {
        var currentIvrObj = ivrObjs[ivrObjsCurrentPointer]; 
        if(ivrIsCodeUseLegal == false) {
            currentIvrObj.treeContent = "The information is temporarily unavailable. Please try again later. Error Code: 104 (Unauthorized use of code snippet)";
        } else if(jsonData.xmlContent.indexOf("Error Code") > -1) { 
            currentIvrObj.treeContent = jsonData.xmlContent;
        } else {
            var xmlDoc = ivrLoadXmlFromString(jsonData.xmlContent); 
            ivrBuildTreeResult(xmlDoc, currentIvrObj.phoneNum);
	        currentIvrObj.treeContent = ivrTmpArray.join(" ");
        }
    } catch(e) {
        //do nothing: try to avoid ff "location.toString()" exception.
    }  
}
 
function ivrLoadXmlFromString(txt) 
{
    try { //Internet Explorer
        xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
        xmlDoc.async="false";
        xmlDoc.loadXML(txt);
        return xmlDoc; 
    } catch(e) {
        try { //Firefox, Mozilla, Opera, etc.
            parser=new DOMParser();
            xmlDoc=parser.parseFromString(txt, "text/xml");
            return xmlDoc;
        } catch(e) {
            if(ivrDebug)
                alert("The browser does not support the XML Dom functionality." + e.message);
        }
    }
    return null;
}

//the class constructor of the Json request class
function ivrJsonRequest(inputPhoneNum, callbackName) 
{                                  
    var url = ivrServerScriptLoc; 
    
    if(ivrIsDataFromDB) {
        url += "?phoneNum=" + inputPhoneNum + "\&callback=" + callbackName;
        url += "\&referer=" + window.location.href;
    } 
    
    //build the dynamic script tag 
    this.scriptTag = document.createElement("script");
    this.scriptTag.setAttribute("type", "text/javascript"); 
    this.scriptTag.setAttribute("charset", "utf-8");
    this.scriptTag.setAttribute("src", url); 
} 

ivrJsonRequest.prototype.appendScriptTag = function() {
    document.body.appendChild(this.scriptTag);
}
 
function ivrBuildTreeResult(doc, inputPhoneNum)  
{
    //init the tmp storage 
    ivrTmpArray = new Array();
    ivrTmpArrayPointer = -1; 
    
    if(ivrIsDataFromDB) {    
        ivrTraverse(doc.getElementsByTagName("baseMenu")[0]); 
    } else { //for client side only, only for dev
        var phoneNums = doc.getElementsByTagName("phoneNumber");
        for(var i = 0, foundFlag = false; i < phoneNums.length; i++) {
            var pn = ivrNormalizePhoneNum(phoneNums[i].childNodes[0].nodeValue)
            if(pn.indexOf(inputPhoneNum) > -1) {
                foundFlag = true;
                break;
            }
        }
        
        if(foundFlag) {        
            ivrTraverse(phoneNums[i].parentNode);
        } else {
            ivrTmpArray[++ivrTmpArrayPointer] = "Information regarding this phone number cannot be found."
        } 
    }//for dev
}
 
//initially pass in a baseMenu node 
function ivrTraverse(node) 
{ 
    if(node.nodeName.indexOf("Menu") > -1) {
        var toAppend = "";
        var children = node.childNodes; 
        if(ivrHasMenuChild(children)) {
            var branchId = ivrGetId();
            var imgId = ivrGetId();
            ivrAppendToTmpTree("<img alt=\"\" src=\"" + ivrServerLoc + "image/ivrRightArrow.gif\" id=" + ivrGetQuotes(imgId) + " class=\"srTreeExpansionPoint\" onclick=\"ivrShowTreeBranch(" + ivrGetSingleQuotes(branchId) + "); ");
            ivrAppendToTmpTree("ivrSwapTreeIcon(" + ivrGetSingleQuotes(imgId) + ")\" /> "); 
            ivrAppendToTmpTree("<span class=\"ivrTreeLine\"> " + (node.nodeName.indexOf("base") > -1 ? ivrGetTextForMenu(node, "phone") : "Press&nbsp;" + ivrGetTextForMenu(node, "key")) + "&nbsp;(" + ivrGetTextForMenu(node, "short") + ")</span><br/> "); 
            ivrAppendToTmpTree("<div class=\"ivrTreeBranch\" id=" + ivrGetQuotes(branchId) + ">");
            
            for(var i = 0; i < children.length; i++)
                ivrTraverse(children[i]);
            ivrAppendToTmpTree("</div>");
        } else {
            var key = ivrGetTextForMenu(node, "key");
            var phone;
            if (key == undefined)
                phone = ivrGetTextForMenu(node, "phone");
            ivrAppendToTmpTree("<img class=\"ivrTreeIcon\" alt=\"\" src=\"" + ivrServerLoc + "image/ivrTreeLeaf.jpg\" /> <span class=\"ivrTreeLine\">" + (key == undefined ? phone : "Press " +  key) + " (" + ivrGetTextForMenu(node, "short") + ")</span><br/>");   
        }
    } 
}
 
function ivrHasMenuChild(children) 
{
    for(var i = 0; i < children.length; i++)
        if(children[i].nodeName.indexOf("Menu") > -1)
            return true;
    return false;
}

function ivrGetQuotes(s) 
{   
    return "\"" + s + "\"";
}

function ivrGetSingleQuotes(s)
{
    return "\'" + s + "\'";
}

//input is a menu node, type could be "phone", "key", "short".
function ivrGetTextForMenu(node, type)
{       
    var children = node.childNodes;
    for(var i = 0; i < children.length; i++) {
        if(children[i].nodeName.indexOf(type) > -1)
            return ivrGetNodeText(children[i]);
    }
}

function ivrGetNodeText(node) 
{
    var children = node.childNodes;
    for(var i = 0; i < children.length; i++) {
        if(children[i].nodeType == 3) {
            return children[i].nodeValue;
        }
    }
}

function ivrGetChildNode(node, index)
{
    return node.childNodes[index];
}

function ivrGetId() 
{ 
    return "ivr" + ++ivrId;
}
 
function ivrAppendToTmpTree(toAppend)
{
    ivrTmpArray[++ivrTmpArrayPointer] = toAppend;
} 

 
/******** run at the very begining (nothing now, so can put in <head>) ***********
function ivrInit()
{
    
}*/

//ivrInit();

/*********************** test and debug, for dev only! *************************/
function ivrShowCoords(event)
{
    if(!ivrDebug)
        return;
        
    x=event.clientX
    y=event.clientY
    alert("X coords: " + x + ", Y coords: " + y)
} 

function debug(info)
{   
    if(!ivrDebug)
        return;
        
    if(!ivrGetElementById("debugDiv")) {
        var d = document.createElement("div");
        d.setAttribute("id", "debugDiv");
        document.body.appendChild(d);
    }
    
    debugDiv.innerHTML = debugDiv.innerHTML + "<br/>" + info;   
}
