/*
|-----------------------------------------------------------------------------|
|                                sDumper 1.1                                  |
|-----------------------------------------------------------------------------|
|                                Developed By:                                |
|                              Joshua Blackburn                               |
|                         (http://joshuablackburn.com)                        |
|-----------------------------------------------------------------------------|
| JavaScript data structure visualization.                                    |
| IE 6 + Firefox + Opera                                                      |
| Please email me any bugs or enhancements @ joshua.blackburn@gmail.com       |
|-----------------------------------------------------------------------------|
| GPL - The GNU General Public License    http://www.gnu.org/licenses/gpl.txt |
| Permits anyone the right to use and modify the software without limitations |
| as long as proper  credits are given  and the original  and modified source |
| code are included. Requires  that the final product, software derivate from |
| the original  source or any  software  utilizing a GPL  component, such  as |
| this, is also licensed under the GPL license.                               |
|-----------------------------------------------------------------------------|
| September 2004 | sDumper created                                            |
| March     2005 | sDumper 1.0.  Optimization and cross-browser support.      |
| November  2005 | sDumper 1.1.  Support for domelement and domcollection.    |
|-----------------------------------------------------------------------------|
| Usage:                                                                      |
|   sDumper(args [,args..N]);                                                 |
| Example:                                                                    |
|   sDumper([1,2,3], 'string', { a : 1 }, /[A-Z]/, 23, variable);             |
|-----------------------------------------------------------------------------|
*/

var sDumperRef = "", dumpObjs = 0;

function sDumper() {
  if ( sDumperRef == "" ) { sDumperRef = new _sDumper(); }
 
  switch ( arguments.length ) { 
    case 0:
      return;
      break;
    case 1:
      sDumperRef.sDrawDumper(arguments[0]);
      break;
    default:
      for ( var t = 0; t < arguments.length; t++ ) {
	sDumperRef.sDrawDumper(arguments[t]);
      }
  }

  sDumperRef.finishDumper();
}

function _sDumper() {
  this.str = ['<div>'];
  this.dumperColors = {
    varray             : ['#8b008b', '#FFF'],
    vobject            : ['#836fff', '#000'],
    vregex             : ['#cd3700', '#FFF'],
    vstring            : ['#66cd00', '#000'],
    vnumber            : ['#caff70', '#000'],
    vdate              : ['#EEEE00', '#000'],
    vmath              : ['#8b'    , '#FFF'],
    vfunction          : ['#53868b', '#FFF'],
    vboolean           : ['#ffa500', '#000'],
    vwindow            : ['#FFACAC', '#000'],
    vevent             : ['#000'   , '#fff'],
    vdomelement        : ['#cd6839', '#000'],
    vtextnode          : ['#cd6839', '#000'],
    vtextrange         : ['#cd6839', '#000'],
    verror             : ['#FFF'   , '#fff'],
    varguments         : ['#cd8500', '#000'],
    vdomcollection     : ['#cd6839', '#000'],
    vplugincollection  : ['#cd6839', '#000'],
    vmimetypecollection: ['#cd6839', '#000'],
    vnull              : ['#000'   , '#fff'],
    vundefined         : ['#000'   , '#fff']
  };
  this.myType;
  this.myCounter = 0;
  this.myTypeChild;
  this.htmldocument = false; // IE and Opera go into an infinite loop when dumping document.  Only allow document to recurse once.

  this.beginTags = '<tr><td onClick="if(this.parentNode.childNodes[1].style.display != \'none\'){this.parentNode.childNodes[1].style.display = \'none\';this.style.fontStyle = \'italic\';this.style.fontWeight = \'bold\';}else{ this.parentNode.childNodes[1].style.display = \'block\';this.style.fontStyle = \'normal\';this.style.fontWeight = \'normal\';}" onMouseOver="this.style.cursor = \'pointer\';" style="width:1.2em;padding:2px 2px 2px 2px;text-align:left;vertical-align:top;font-size:11px;color:#000;background:#CCC;border:1px solid #000;font-family:verdana;background:';

  this.middleTags = '</td><td style="padding:2px 2px 2px 2px;text-align:left;vertical-align:top;font-size:11px;color:#000;background:#DDD;font-family:verdana;border:1px solid #000;"><pre>';

  this.endTags = '</pre></td></tr>';

  this.nullTags = '<tr><td onClick="if(this.parentNode.childNodes[1].style.display != \'none\'){this.parentNode.childNodes[1].style.display = \'none\';this.style.fontStyle = \'italic\';this.style.fontWeight = \'bold\';}else{ this.parentNode.childNodes[1].style.display = \'block\';this.style.fontStyle = \'normal\';this.style.fontWeight = \'normal\';}" onMouseOver="this.style.cursor = \'pointer\';" class="dumper_type" style="width:1.2em;background:'+this.dumperColors['vnull'][0]+';color:'+this.dumperColors['vnull'][1]+';">';

  
}

_sDumper.prototype.sDrawDumper = function (dumpVar) {
  this.myCounter = this.myCounter + 1;
  this.myType = this.tf(dumpVar);

  this.str.push('<table cellspacing="0">');

  switch ( this.myType ) {
    case 'error':
    case 'object':
    case 'htmldocument':
      if ( this.htmldocument && this.myType == 'htmldocument' ) break; 
      this.htmldocument = true;
      for ( var i in dumpVar ) {
        try {
          this.myCounter = this.myCounter + 1;
          if ( dumpVar[i] != null ) {
            this.myTypeChild = this.tf(dumpVar[i]); 
            this.str.push(this.beginTags + (this.dumperColors["v" + this.myTypeChild] ? this.dumperColors["v" + this.myTypeChild][0] : "#FFF") + ';color:' + (this.dumperColors["v" + this.myTypeChild] ? this.dumperColors["v" + this.myTypeChild][1] : "#FFF")+';">' + i + this.middleTags);
            switch ( typeof(dumpVar[i]) ) {
              case 'object':
                this.sDrawDumper(dumpVar[i]);
                break;
              default:
                try { this.str.push(dumpVar[i].replace(/\</g, '&lt;').replace(/\>/g, '&gt;')); } catch(e) { this.str.push(dumpVar[i]); }
                break;
            }
            this.str.push(this.endTags);
          } else {
            this.str.push(this.nullTags + i + this.middleTags + "null" + this.endTags);
          }
        } catch(e) {};
      }
      break;
    case 'array':
      for ( var j = dumpVar.length - 1; j >= 0; j-- ) {
        try {
          this.myCounter = this.myCounter + 1;
          if ( dumpVar[j] != null ) {
            this.myTypeChild = this.tf(dumpVar[j]);
            this.str.push(this.beginTags + (this.dumperColors["v" + this.myTypeChild] ? this.dumperColors["v" + this.myTypeChild][0] : "#FFF") + ';color:' + (this.dumperColors["v" + this.myTypeChild] ? this.dumperColors["v" + this.myTypeChild][1] : "#FFF")+';">' + j + this.middleTags); 
            switch ( typeof(dumpVar[j]) ) {
              case 'object':
                this.sDrawDumper(dumpVar[j]);
                break;
              default:
                try { this.str.push(dumpVar[j].replace(/\</g, '&lt;').replace(/\>/g, '&gt;')); } catch(e) { this.str.push(dumpVar[j]); }
                break;
            }
            this.str.push(this.endTags);
          } else {
            this.str.push(this.nullTags + j + this.middleTags + "null" + this.endTags);
          }
        } catch(e) {};
      } 
      break;
    case 'domelement':
      this.str.push(this.beginTags + (this.dumperColors["v" + this.myType] ? this.dumperColors["v" + this.myType][0] : "#FFF") + ';color:' + (this.dumperColors["v" + this.myType] ? this.dumperColors["v" + this.myType][1] : "#FFF")+';">' + this.myType + this.middleTags);
      this.sDrawDumper({'tagName' : dumpVar.tagName, 'innerHTML' : (dumpVar.innerHTML).toString() });
      this.str.push(this.endTags);
      break;
    case 'domcollection':
      this.str.push(this.beginTags + (this.dumperColors["v" + this.myType] ? this.dumperColors["v" + this.myType][0] : "#FFF") + ';color:' + (this.dumperColors["v" + this.myType] ? this.dumperColors["v" + this.myType][1] : "#FFF")+';">' + this.myType + this.middleTags);
      try { this.str.push(((dumpVar.innerHTML).toString()).replace(/\</g, '&lt;').replace(/\>/g, '&gt;') + this.endTags); } catch(e) { this.str.push(dumpVar + this.endTags); }
      break;
    default:
      this.str.push(this.beginTags + (this.dumperColors["v" + this.myType] ? this.dumperColors["v" + this.myType][0] : "#FFF") + ';color:' + (this.dumperColors["v" + this.myType] ? this.dumperColors["v" + this.myType][1] : "#FFF")+';">' + this.myType + this.middleTags);
      try { this.str.push(dumpVar.replace(/\</g, '&lt;').replace(/\>/g, '&gt;') + this.endTags); } catch(e) { this.str.push(dumpVar + this.endTags); }
      break;
  } 
  this.str.push('</table>');
}

_sDumper.prototype.finishDumper = function () {
  this.str.push('</div>');
  this.standAlone();
}

_sDumper.prototype.standAlone = function () {
  if ( ! document.getElementById('sDumperHolder') ) {
    var o = document.createElement("div");
    o.setAttribute("style","width:100%;");
    o.setAttribute("id","sDumperHolder");
    oB = document.body;
    vContains = oB.insertBefore(o, null); 
    vContains.innerHTML = this.str.join('');
    
    this.str = null;this.str = ['<div>'];
  } else { 
    document.getElementById("sDumperHolder").innerHTML = this.str.join('');
    this.str = null;this.str = ['<div>'];
  }
}

_sDumper.prototype.tf = function ( obj ) {
  var vType = typeof(obj);

  if( vType == "function" ) {
    var vFunction = obj.toString();
    if( ( /^\/.*\/[gi]??[gi]??$/ ).test( vFunction ) ) {
      return "regex";
    } else if( ( /^\[object.*\]$/i ).test( vFunction ) ) {
      vType = "object"
    }
  }

  if( vType != "object" ) {
    return vType;
  }

  switch( obj ) {
    case null:
      return "null";
    case window:
      return "window";
    case window.event:
      return "event";
  }

  if( window.event && ( event.type == obj.type ) ) {
    return "event";
  }

  var fConstructor = obj.constructor;
  if( fConstructor != null ) {
    switch( fConstructor ) {
      case Array:
        vType = "array";
        break;
      case Date:
        return "date";
      case RegExp:
        return "regex";
      case Object:
        vType = "object";
      break;
      case ReferenceError:
        return "error";
      default:
        var sConstructor = fConstructor.toString();
        var aMatch = sConstructor.match( /\s*function (.*)\(/ );
        if( aMatch != null ) {
          return 'object';
        }
    }
  }

  var nNodeType = obj.nodeType;
  if( nNodeType != null ) {
    switch( nNodeType ) {
      case 1:
        if( obj.item == null ) {
          return "domelement";
        }
        break;
      case 3:
        return "textnode";
    }
  }

  if( obj.toString != null ) {
    var sExpression = obj.toString();
    var aMatch = sExpression.match( /^\[object (.*)\]$/i );
    if( aMatch != null ) {
      var sMatch = aMatch[ 1 ];
      switch( sMatch.toLowerCase() ) {
        case "event":
          return "event";
        case "math":
          return "math";
        case "error":
          return "error";
        case "mimetypearray":
          return "mimetypecollection";
        case "pluginarray":
          return "plugincollection";
        case "windowcollection":
          return "window";
        case "nodelist":
        case "htmlcollection":
        case "elementarray":
          return "domcollection";
        case "htmldocument":
          return "htmldocument";
      }
    }
  }

  if( obj.moveToBookmark && obj.moveToElementText ) {
    return "textrange";
  } else if( obj.callee != null ) {
    return "array";
  } else if( obj.item != null ) {
    return "domcollection";
  }

  return vType;

}

/* --------------------------------------------------------------------------------------------------------------
*	API:			JSMX (JavaScript MX) - This is a ColdFusion API for AJAX.	
*	AUTHOR: 		Todd Kingham [todd@lalabird.com] - Jan Jannek [jan.jannek@Cetecom.de]
*	CREATED:		8.21.2005
*	VERSION:		2.6.0
*	DESCRIPTION:	This API uses XMLHttpRequest to post/get data from a ColdFusion interface.
*					The CFC's/CFM's will return a string representation of a JS variable: response_param.
*					The "onreadystatechange event handler" will eval() the string into a JS variable 
*					and pass the value back to the "return function". To Download a full copy of the sample 
*					application visit: http://www.lalabird.com/JSMX/?fa=JSMX.downloads
*
*	HISTORY:		2.0.0:	Todd: Scripted Out Original Version
*					2.1.0:	Todd: Modified for Download
*					2.2.0:	Todd: Modified the firstWord() function to be backward compatable with
*								  CF5 and to be more stable all-around.
*					2.3.0:	Todd: Added "wait div" functionality
*					2.4.0:	Todd: XML!!!! Now JSMX will allow you to pass XML Documents to the API in
*								  addition to the original JavaScript method.
*					2.4.1:	Jan:  2006-02-16, XMLHTTP requests can now handle more than one request at once. By placing the onreadystatechange event as a local variable inside the actual http() function.
*							Jan:  Added fix for strange IE bug that returned Header Info.
*							Todd: Added the jsmx object to allow users to override defaults and set custom "async", "wait" and "error" methods
*					2.5.0:	Todd: Added JSON Support! So now you can pass JavaScript, XML, or JSON.
*					2.5.1:	Todd: Version 2.5.0 was premature. Needed to fix an eval() bug when I introduced JSON.
*					2.5.2:	Todd: Fixed a bug in the onreadystatechange. Based on the order you call the event handler... "State Change 1" gets called twice. Added code to only process code inside 'CASE 1:' once
*					2.5.3:	Todd: Fixed a bug in the try/catch of the parser by placing the callback() call within the try/catch statement. This caused errors in the callback function to be "masked" and appear as "parsing errors", even when the parse was successful.
*					2.6.0: 	Todd: Added WDDX Parser! Now you can return WDDX Strings as well.
*
*	LICENSE:		THIS IS AN OPEN SOURCE API. YOU ARE FREE TO USE THIS API IN ANY APPLICATION,
*               	TO COPY IT OR MODIFY THE FUNCTIONS FOR YOUR OWN NEEDS, AS LONG THIS HEADER INFORMATION
*              	 	REMAINS IN TACT AND YOU DON'T CHARGE ANY MONEY FOR IT. USE THIS API AT YOUR OWN
*               	RISK. NO WARRANTY IS EXPRESSED OR IMPLIED, AND NO LIABILITY ASSUMED FOR THE RESULT OF
*               	USING THIS API.
*
*               	THIS API IS LICENSED UNDER THE CREATIVE COMMONS ATTRIBUTION-SHAREALIKE LICENSE.
*               	FOR THE FULL LICENSE TEXT PLEASE VISIT: http://creativecommons.org/licenses/by-sa/2.5/
*
-----------------------------------------------------------------------------------------------------------------*/
// UNCOMMENT THE FOLLOWING LINE IF YOU WILL BE RETURNING QUERY OBJECTS. (note: you may need to point the SRC to an alternate location.
document.writeln('<SCRIPT TYPE="text/javascript" LANGUAGE="JavaScript" SRC="/CFIDE/scripts/wddx.js"></SCRIPT >');

jsmx = new jsmxConstructor();
function jsmxConstructor(){
	this.async = true;
	this.onError = onError;
	this.onWait = popWait;
	this.onWaitEnd = killWait;
}


// perform the XMLHttpRequest();
// must have parameters in the form of:
// ajax("POST" | "GET", url of template to get data from, return method, waiting method, query string if verb is "POST");
function ajax(verb,url,rm,wm,qry) {
    //reference our arguments
	var callback = rm;
	var qryStr = (!qry) ? '' : toQueryString(qry);
	var calledOnce = false; //this is to prevent a bug in onreadystatechange... "state 1" gets called twice.
	try{//this should work for most modern browsers excluding: IE Mac
		var req = ( window.XMLHttpRequest ) ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP") ;
			req.onreadystatechange = function(){
			switch(req.readyState){
				case 1: 
					if(!calledOnce){
						if(wm)
							jsmx.onWait = wm;
						jsmx.onWait();
						
						calledOnce = true;
					}
					break;
				case 2: break;
				case 3: break;
				case 4:
					if(!wm)
						jsmx.onWaitEnd();
					if ( req.status == 200 ){// only if "OK"

						try{
							rObj = parseResponse( req ) ;
						
							success = true;
						}catch(e){ 
							jsmx.onError('Parsing Error: The value returned could not be evaluated.');
							success = false;
						}
						if(success)
						{
							if(callback)
								callback( rObj );
						}
					}else{ 
						jsmx.onError("There was a problem retrieving the data:\n" + req.statusText);
					}
					break;
				}
			}
			req.open( verb , noCache(url) , jsmx.async );
			if(verb.toLowerCase() == 'post')	
			req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
			req.send(qryStr);
	}catch(e){//a browser not equiped to handle XMLHttp
		//jsmx.onError("There was a problem retrieving the data:");
	}
}

/*--- BEGIN: RESPONSE PARSING FUNCTIONS ---*/
	function parseResponse(rO){
		//FIRST TRY IT AS XML
		if(rO.getResponseHeader("Content-Type").split(';')[0] == 'text/xml'){	
			return rO.responseXML;
		}	
		
		var str = rO.responseText;
		// jan.jannek@cetecom.de, 2006-02-16, weird error: some IEs show the responseText followed by the complete response (header and body again) 
		var i = str.indexOf("HTTP/1");
		if (i > -1) {
			str = str.substring(i, str.length);
			i = str.indexOf(String.fromCharCode(13, 10, 13, 10));
			if (i > -1) {
				str = str.substring(i + 2, str.length);
			}
		}		
		
		//NEXT TRY IT AS WDDX
		if(str.indexOf("<wddxPacket") > -1){
			return parseWDDX(str);	
		}
		
		
		//DO THE STRING EVAL
		try{//next try JSON eval();
			return parseJSON(str);
		}catch(e){//then try Classic eval();
			return parseJS(str);
		}
	}	
	function parseJS(str){ 
		eval(str);
		var r = eval(str.split('=')[0].replace(/\s/g,''));
		return r;
	}
	function parseJSON(str){
		return  eval('('+str+')');;
	}

function parseWDDX(str){ 
	var wddx = xmlStr2Doc(str); 
	var data = wddx.getElementsByTagName("data"); 
	return __parseWDDXnode(data[0].firstChild); 
} 

function xmlStr2Doc(str){ 
	var xml; 
	if(typeof(DOMParser) == 'undefined'){ 
		xml=new ActiveXObject("Microsoft.XMLDOM"); 
		xml.async="false"; 
		xml.loadXML(str); 
	}
	else{ 
		var domParser = new DOMParser(); 
		xml = domParser.parseFromString(str, 'application/xml'); 
	} 
	return xml; 
} 
function __parseWDDXnode(n){ 
	var val; 
	switch(n.tagName){ 
		case 'string': 
			val = __parseWDDXstring(n); 
			break; 
		case 'number': 
			val = parseFloat(n.firstChild.data); 
			break; 
		case 'boolean': 
			val = n.getAttribute('value'); 
			break; 
		case 'dateTime': 
			val = Date(n.firstChild.data); 
			break; 
		case 'array': 
			val = __parseWDDXarray(n); 
			break; 
		case 'struct': 
			val = __parseWDDXstruct(n); 
			break; 
		case 'recordset': 
			val = __parseWDDXrecordset(n); 
			break; 
		case 'binary': 
			val = n.firstChild.data; 
			break; 
		case 'char': 
			val = __parseWDDXchar(n); 
			break; 
		case 'null': 
			val = ''; 
			break; 
		default: 
			val = n.tagName;
			break; 
	} 
	return val; 
} 

function __parseWDDXstring(node){ 
	var items = node.childNodes; 
	var str = ''; 
	for(var x=0;x < items.length;x++){ 
		if(typeof(items[x].data) != 'undefined') 
			str += items[x].data; 
		else str += __parseWDDXnode(items[x]); 
	} return str; 
} 

function __parseWDDXchar(node){ 
	switch(node.getAttribute('code')){ 
		case '0d': 
			return '\r'; 
		case '0c': 
			return '\f'; 
		case '0a': 
			return '\n'; 
		case '09': 
			return '\t'; 
	} 
}

function __parseWDDXarray(node){ 
	var items = node.childNodes; 
	var arr = new Array(); 
	for(var i=0;i < items.length;i++){ 
		arr[i] = __parseWDDXnode(items[i]); 
	} 
	return arr; 
} 

function __parseWDDXstruct(node){ 
	var items = node.childNodes; 
	var obj = new Object(); 
	
	for(var i=0;i < items.length;i++){ 
		obj[items[i].getAttribute('name').toLowerCase()] = __parseWDDXnode(items[i].childNodes[0]); 
	} 
	return obj; 
} 

function __parseWDDXrecordset(node){ 
	var qry = new Object(); 
	var fields = node.getElementsByTagName("field"); 
	var items; 
	var dataType; 
	var values; 
	
	for(var x = 0; x < fields.length; x++){ 
		items = fields[x].childNodes; 
		values = new Array(); 
		for(var i = 0; i < items.length; i++){ 
			values[values.length] = __parseWDDXnode(items[i]); 
		} 
		qry[fields[x].getAttribute('name').toLowerCase()] = values; 
	} 
	return qry; 
}
//END: WDDX deserializer functions

/*--- END: RESPONSE PARSING FUNCTIONS ---*/


/*--- BEGIN: REQUEST PARAMETER FUNCTIONS ---*/
	function toQueryString(obj){
		//determine the variable type
		if(typeof(obj) == 'string')
			return obj;
		if(typeof(obj) == 'object'){
			if(typeof(obj.elements) == 'undefined')//It's an Object()!
				return object2queryString(obj);
			else //It's a form!
				return form2queryString(obj);
		}	
	}
	
	function object2queryString(obj){
		var ar = new Array();
		for(x in obj) ar[ar.length] = x+'='+obj[x];
		return ar.join('&');
	}
	
	function form2queryString(form){
		var obj = new Object();
		var ar = new Array();
		for(var i=0;i<form.elements.length;i++){
			try {
				elm = form.elements[i];
				nm = elm.name;
				if(nm != ''){
					switch(elm.type.split('-')[0]){
						case "select":
							for(var s=0;s<elm.options.length;s++){
								if(elm.options[s].selected){
									if(typeof(obj[nm]) == 'undefined') obj[nm] = new Array();
									obj[nm][obj[nm].length] = escape(elm.options[s].value);
								}	
							}
							break;
						
						case "radio":
							if(elm.checked){
								if(typeof(obj[nm]) == 'undefined') obj[nm] = new Array();
								obj[nm][obj[nm].length] = escape(elm.value);
							}	
							break;
						
						case "checkbox":
							if(elm.checked){
								if(typeof(obj[nm]) == 'undefined') obj[nm] = new Array();
								obj[nm][obj[nm].length] = escape(elm.value);
							}	
							break;
						
						default:
							if(typeof(obj[nm]) == 'undefined') obj[nm] = new Array();
							obj[nm][obj[nm].length] = escape(elm.value);
							break;
					}
				}
			}catch(e){}
		}
		for(x in obj) ar[ar.length] = x+'='+obj[x].join(',');
	return ar.join('&');
	}
/*--- END: REQUEST PARAMETER FUNCTIONS ---*/


//IE likes to cache so we will fix it's wagon!
function noCache(url){
	var qs = new Array();
	var arr = url.split('?');
	var scr = arr[0];
	if(arr[1]) qs = arr[1].split('&');
	qs[qs.length]='nocache='+new Date().getTime();
return scr+'?'+qs.join('&');
}

function popWait(){ 
	proc = document.getElementById("JSMX_loading");
	if( proc == null ){
		var p = document.createElement("div");
		p.id = "JSMX_loading";
		document.body.appendChild(p);
	}
}

function killWait(){
	proc = document.getElementById("JSMX_loading");
	if( proc != null ) document.body.removeChild(proc);
}

function onError(str){ alert(str); }
function $(id){ return document.getElementById(id); }
