CustomEvent = Class.create()
CustomEvent.prototype = {
initialize : function() {
this.listeners = []
},
addListener : function(method) {
this.listeners.push(method)
},
removeListener : function(method) {
var foundIndexes = this._findListenerIndexes(method)
for(var i = 0; i < foundIndexes.length; i++) {
this.listeners.splice(foundIndexes[i], 1)
}
},
dispatch : function(handler) {
for(var i = 0; i < this.listeners.length; i++) {
try {
this.listeners[i](handler)
}
catch (e) {
alert("Could not run the listener " + this.listeners[i] + ". " + e)
}
}
},
_findListenerIndexes : function(method) {
var indexes = []
for(var i = 0; i < this.listeners.length; i++) {
if (this.listeners[i] == method) {
indexes.push(i)
}
}
return indexes
}
}
var Cookie = {
set : function(name, value, expirationInDays, path) {
var cookie = escape(name) + "=" + escape(value)
if (expirationInDays) {
var date = new Date()
date.setDate(date.getDate() + expirationInDays)
cookie += "; expires=" + date.toGMTString()
} 
if (path) {
cookie += ";path=" + path
}
document.cookie = cookie
if (value && (expirationInDays == undefined || expirationInDays > 0) && !this.get(name)) {
Logger.error("Cookie (" + name + ") was not set correctly... The value was " + value.toString().length + " charachters long (This may be over the cookie limit)");
}
},
get : function(name) {
var pattern = "(^|;)\\s*" + escape(name) + "=([^;]+)"
var m = document.cookie.match(pattern)
if (m && m[2]) {
return unescape(m[2])
}
else return null
},
getAll : function() {
var cookies = document.cookie.split(';')
var cookieArray = []
for (var i = 0; i < cookies.length; i++) {
try {
var name = unescape(cookies[i].match(/^\s*([^=]+)/m)[1])
var value = unescape(cookies[i].match(/=(.*$)/m)[1])
}
catch (e) {
continue
}
cookieArray.push({name : name, value : value})
if (cookieArray[name] != undefined) {
Logger.waring("Trying to retrieve cookie named(" + name + "). There appears to be another property with this name though.");
}
cookieArray[name] = value
}
return cookieArray
},
clear : function(name) {
this.set(name, "", -1)
},
clearAll : function() {
var cookies = this.getAll()
for(var i = 0; i < cookies.length; i++) {
this.clear(cookies[i].name)
}
}
} 
Logger = {
logEntries : [],
onupdate : new CustomEvent(),
onclear : new CustomEvent(),
log : function(message, tag) {
var logEntry = new LogEntry(message, tag || "info")
this.logEntries.push(logEntry)
this.onupdate.dispatch(logEntry)
},
info : function(message) {
this.log(message, 'info')
}, 
debug : function(message) {
this.log(message, 'debug')
},
warn : function(message) {
this.log(message, 'warning')
},
error : function(message, error) {
this.log(message + ": \n" + error, 'error')
},
clear : function () {
this.logEntries = []
this.onclear.dispatch()
}
}
LogEntry = Class.create()
LogEntry.prototype = {
initialize : function(message, tag) {
this.message = message
this.tag = tag
}
}
LogConsole = Class.create()
LogConsole.prototype = {
commandHistory : [],
commandIndex : 0,
initialize : function() {
this.outputCount = 0
this.tagPattern = Cookie.get('tagPattern') || ".*"
this.logElement = document.createElement('div')
document.body.appendChild(this.logElement)
Element.hide(this.logElement)
this.logElement.style.position = "absolute"
this.logElement.style.left = '0px'
this.logElement.style.width = '100%'
this.logElement.style.textAlign = "left"
this.logElement.style.fontFamily = "lucida console"
this.logElement.style.fontSize = "100%"
this.logElement.style.backgroundColor = 'darkgray'
this.logElement.style.opacity = 0.9 
this.logElement.style.zIndex = 2000 
this.toolbarElement = document.createElement('div')
this.logElement.appendChild(this.toolbarElement) 
this.toolbarElement.style.padding = "0 0 0 2px"
this.buttonsContainerElement = document.createElement('span')
this.toolbarElement.appendChild(this.buttonsContainerElement) 
this.buttonsContainerElement.innerHTML += '<button onclick="logConsole.toggle()" style="float:right;color:black">close</button>'
this.buttonsContainerElement.innerHTML += '<button onclick="Logger.clear()" style="float:right;color:black">clear</button>'
if(!Prado.Inspector.disabled)
this.buttonsContainerElement.innerHTML += '<button onclick="Prado.Inspector.inspect()" style="float:right;color:black; margin-right:15px;">Object Tree</button>'
this.tagFilterContainerElement = document.createElement('span')
this.toolbarElement.appendChild(this.tagFilterContainerElement) 
this.tagFilterContainerElement.style.cssFloat = 'left'
this.tagFilterContainerElement.appendChild(document.createTextNode("Log Filter"))
this.tagFilterElement = document.createElement('input')
this.tagFilterContainerElement.appendChild(this.tagFilterElement)
this.tagFilterElement.style.width = '200px'
this.tagFilterElement.value = this.tagPattern
this.tagFilterElement.setAttribute('autocomplete', 'off')
Event.observe(this.tagFilterElement, 'keyup', this.updateTags.bind(this))
Event.observe(this.tagFilterElement, 'click', function() {this.tagFilterElement.select()}.bind(this))
this.outputElement = document.createElement('div')
this.logElement.appendChild(this.outputElement)
this.outputElement.style.overflow = "auto"
this.outputElement.style.clear = "both"
this.outputElement.style.height = "200px"
this.outputElement.style.backgroundColor = 'black' 
this.inputContainerElement = document.createElement('div')
this.inputContainerElement.style.width = "100%"
this.logElement.appendChild(this.inputContainerElement)
this.inputElement = document.createElement('input')
this.inputContainerElement.appendChild(this.inputElement)
this.inputElement.style.width = '100%'
this.inputElement.style.borderWidth = '0px'
this.inputElement.style.margin = '0px'
this.inputElement.style.padding = '0px'
this.inputElement.value = 'Type command here' 
this.inputElement.setAttribute('autocomplete', 'off')
Event.observe(this.inputElement, 'keyup', this.handleInput.bind(this))
Event.observe(this.inputElement, 'click', function() {this.inputElement.select()}.bind(this))
window.setInterval(this.repositionWindow.bind(this), 500)
this.repositionWindow()
Logger.onupdate.addListener(this.logUpdate.bind(this))
Logger.onclear.addListener(this.clear.bind(this))
for (var i = 0; i < Logger.logEntries.length; i++) {
this.logUpdate(Logger.logEntries[i])
} 
Event.observe(window, 'error', function(msg, url, lineNumber) {Logger.error("Error in (" + (url || location) + ") on line "+lineNumber+"", msg)})
var accessElement = document.createElement('span')
accessElement.innerHTML = '<button style="position:absolute;top:-100px" onclick="javascript:logConsole.toggle()" accesskey="d"></button>'
document.body.appendChild(accessElement)
if (Cookie.get('ConsoleVisible') == 'true') {
this.toggle()
}
},
toggle : function() {
if (this.logElement.style.display == 'none') {
this.show()
}
else {
this.hide()
}
}, 
show : function() {
Element.show(this.logElement)
this.outputElement.scrollTop = this.outputElement.scrollHeight
Cookie.set('ConsoleVisible', 'true')
 this.inputElement.select()
}, 
hide : function() {
Element.hide(this.logElement)
Cookie.set('ConsoleVisible', 'false')
},
output : function(message, style) {
var shouldScroll = (this.outputElement.scrollTop + (2 * this.outputElement.clientHeight)) >= this.outputElement.scrollHeight
this.outputCount++
style = (style ? style += ';' : '')
style += 'padding:1px;margin:0 0 5px 0' 
if (this.outputCount % 2 == 0) style += ";background-color:#101010"
message = message || "undefined"
message = message.toString().escapeHTML()
this.outputElement.innerHTML += "<pre style='" + style + "'>" + message + "</pre>"
if (shouldScroll) {
this.outputElement.scrollTop = this.outputElement.scrollHeight
}
},
updateTags : function() {
var pattern = this.tagFilterElement.value
if (this.tagPattern == pattern) return
try {
new RegExp(pattern)
}
catch (e) {
return
}
this.tagPattern = pattern
Cookie.set('tagPattern', this.tagPattern)
this.outputElement.innerHTML = ""
this.outputCount = 0;
for (var i = 0; i < Logger.logEntries.length; i++) {
this.logUpdate(Logger.logEntries[i])
}
},
repositionWindow : function() {
var offset = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
var pageHeight = self.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
this.logElement.style.top = (offset + pageHeight - Element.getHeight(this.logElement)) + "px"
},
logUpdate : function(logEntry) {
if (logEntry.tag.search(new RegExp(this.tagPattern, 'igm')) == -1) return
var style = ''
if (logEntry.tag.search(/error/) != -1) style += 'color:red'
else if (logEntry.tag.search(/warning/) != -1) style += 'color:orange'
else if (logEntry.tag.search(/debug/) != -1) style += 'color:green'
 else if (logEntry.tag.search(/info/) != -1) style += 'color:white'
else style += 'color:yellow'
this.output(logEntry.message, style)
},
clear : function(e) {
this.outputElement.innerHTML = ""
},
handleInput : function(e) {
if (e.keyCode == Event.KEY_RETURN ) {
var command = this.inputElement.value
switch(command) {
case "clear":
Logger.clear()
break
default:
var consoleOutput = "" 
try {
consoleOutput = eval(this.inputElement.value)
}
catch (e) {
Logger.error("Problem parsing input <" + command + ">", e)
break
}
Logger.log(consoleOutput)
break
}
if (this.inputElement.value != "" && this.inputElement.value != this.commandHistory[0]) {
this.commandHistory.unshift(this.inputElement.value)
}
this.commandIndex = 0 
this.inputElement.value = ""
}
else if (e.keyCode == Event.KEY_UP && this.commandHistory.length > 0) {
this.inputElement.value = this.commandHistory[this.commandIndex]
if (this.commandIndex < this.commandHistory.length - 1) {
this.commandIndex += 1
}
} 
else if (e.keyCode == Event.KEY_DOWN && this.commandHistory.length > 0) {
if (this.commandIndex > 0) {
this.commandIndex -= 1
} 
this.inputElement.value = this.commandHistory[this.commandIndex]
} 
 else {
this.commandIndex = 0
}
}
} 
var logConsole;
Event.OnLoad(function() { logConsole = new LogConsole()}); 
function inspect(o) 
{
var objtype = typeof(o);
if (objtype == "undefined") {
return "undefined";
} else if (objtype == "number" || objtype == "boolean") {
return o + "";
} else if (o === null) {
return "null";
}
try {
var ostring = (o + "");
} catch (e) {
return "[" + typeof(o) + "]";
}
if (typeof(o) == "function") 
{
o = ostring.replace(/^\s+/, "");
var idx = o.indexOf("{");
if (idx != -1) {
o = o.substr(0, idx) + "{...}";
}
return o;
 }
var reprString = function (o) 
{ 
return ('"' + o.replace(/(["\\])/g, '\\$1') + '"'
).replace(/[\f]/g, "\\f"
).replace(/[\b]/g, "\\b"
).replace(/[\n]/g, "\\n"
).replace(/[\t]/g, "\\t"
).replace(/[\r]/g, "\\r");
};
if (objtype == "string") {
return reprString(o);
}
var me = arguments.callee;
var newObj;
if (typeof(o.__json__) == "function") {
newObj = o.__json__();
if (o !== newObj) {
return me(newObj);
}
}
if (typeof(o.json) == "function") {
newObj = o.json();
if (o !== newObj) {
return me(newObj);
}
}
if (objtype != "function" && typeof(o.length) == "number") {
var res = [];
for (var i = 0; i < o.length; i++) {
var val = me(o[i]);
if (typeof(val) != "string") {
val = "undefined";
}
res.push(val);
}
return "[" + res.join(", ") + "]";
}
res = [];
for (var k in o) {
var useKey;
if (typeof(k) == "number") {
useKey = '"' + k + '"';
} else if (typeof(k) == "string") {
useKey = reprString(k);
} else {
continue;
}
val = me(o[k]);
if (typeof(val) != "string") {
continue;
}
res.push(useKey + ":" + val);
}
return "{" + res.join(", ") + "}";
} 
Array.prototype.contains = function(object) {
for(var i = 0; i < this.length; i++) {
if (object == this[i]) return true
}
return false
}
var puts = function() {return Logger.log(arguments[0], arguments[1])}
if(typeof Prado == "undefined")
var Prado = {};
Prado.Inspector = 
{
d : document,
types : new Array(),
objs : new Array(),
hidden : new Array(),
opera : window.opera,
displaying : '',
nameList : new Array(),
format : function(str) {
if(typeof(str) != "string") return str;
str=str.replace(/</g,"&lt;");
str=str.replace(/>/g,"&gt;");
return str;
},
parseJS : function(obj) {
var name;
if(typeof obj == "string") {name = obj; obj = eval(obj); }
win= typeof obj == 'undefined' ? window : obj;
this.displaying = name ? name : win.toString();
for(js in win) {
try {
if(win[js] && js.toString().indexOf("Inspector")==-1 && (win[js]+"").indexOf("[native code]")==-1) {
t=typeof(win[js]);
if(!this.objs[t.toString()]) {
this.types[this.types.length]=t;
this.objs[t]={};
this.nameList[t] = new Array();
}
this.nameList[t].push(js);
this.objs[t][js] = this.format(win[js]+"");
}
} catch(err) { }
}
for(i=0;i<this.types.length;i++) 
this.nameList[this.types[i]].sort();
},
show : function(objID) {
this.d.getElementById(objID).style.display=this.hidden[objID]?"none":"block";
this.hidden[objID]=this.hidden[objID]?0:1;
},
changeSpan : function(spanID) {
if(this.d.getElementById(spanID).innerHTML.indexOf("+")>-1){
this.d.getElementById(spanID).innerHTML="[-]";
} else {
this.d.getElementById(spanID).innerHTML="[+]";
}
},
buildInspectionLevel : function()
{
var display = this.displaying;
var list = display.split(".");
var links = ["<a href=\"javascript:var_dump()\">[object Window]</a>"];
var name = '';
if(display.indexOf("[object ") >= 0) return links.join(".");
for(var i = 0; i < list.length; i++)
{
name += (name.length ? "." : "") + list[i];
links[i+1] = "<a href=\"javascript:var_dump('"+name+"')\">"+list[i]+"</a>"; 
}
return links.join(".");
},
buildTree : function() {
mHTML = "<div>Inspecting "+this.buildInspectionLevel()+"</div>";
mHTML +="<ul class=\"topLevel\">";
this.types.sort();
var so_objIndex=0;
for(i=0;i<this.types.length;i++) 
{
mHTML+="<li style=\"cursor:pointer;\" onclick=\"Prado.Inspector.show('ul"+i+"');Prado.Inspector.changeSpan('sp" + i + "')\"><span id=\"sp" + i + "\">[+]</span><b>" + this.types[i] + "</b> (" + this.nameList[this.types[i]].length + ")</li><ul style=\"display:none;\" id=\"ul"+i+"\">";
this.hidden["ul"+i]=0;
for(e=0;e<this.nameList[this.types[i]].length;e++) 
{
var prop = this.nameList[this.types[i]][e];
var value = this.objs[this.types[i]][prop]
var more = "";
if(value.indexOf("[object ") >= 0 && /^[a-zA-Z_]/.test(prop))
{
if(this.displaying.indexOf("[object ") < 0)
more = " <a href=\"javascript:var_dump('"+this.displaying+"."+prop+"')\"><b>more</b></a>";
else if(this.displaying.indexOf("[object Window]") >= 0)
more = " <a href=\"javascript:var_dump('"+prop+"')\"><b>more</b></a>";
}
mHTML+="<li style=\"cursor:pointer;\" onclick=\"Prado.Inspector.show('mul" + so_objIndex + "');Prado.Inspector.changeSpan('sk" + so_objIndex + "')\"><span id=\"sk" + so_objIndex + "\">[+]</span>" + prop + "</li><ul id=\"mul" + so_objIndex + "\" style=\"display:none;\"><li style=\"list-style-type:none;\"><pre>" + value + more + "</pre></li></ul>";
this.hidden["mul"+so_objIndex]=0;
so_objIndex++;
}
mHTML+="</ul>";
}
mHTML+="</ul>";
this.d.getElementById("so_mContainer").innerHTML =mHTML;
},
handleKeyEvent : function(e) {
keyCode=document.all?window.event.keyCode:e.keyCode;
if(keyCode==27) {
this.cleanUp();
}
},
cleanUp : function() 
{
if(this.d.getElementById("so_mContainer"))
{
this.d.body.removeChild(this.d.getElementById("so_mContainer"));
this.d.body.removeChild(this.d.getElementById("so_mStyle"));
if(typeof Event != "undefined")
Event.stopObserving(this.d, "keydown", this.dKeyDownEvent);
this.types = new Array();
this.objs = new Array();
this.hidden = new Array();
}
},
disabled : document.all && !this.opera,
inspect : function(obj) 
{
if(this.disabled)return alert("Sorry, this only works in Mozilla and Firefox currently.");
this.cleanUp();
mObj=this.d.body.appendChild(this.d.createElement("div"));
mObj.id="so_mContainer";
sObj=this.d.body.appendChild(this.d.createElement("style"));
sObj.id="so_mStyle";
sObj.type="text/css";
sObj.innerHTML = this.style;
this.dKeyDownEvent = this.handleKeyEvent.bind(this);
if(typeof Event != "undefined")
Event.observe(this.d, "keydown", this.dKeyDownEvent);
this.parseJS(obj);
this.buildTree();
cObj=mObj.appendChild(this.d.createElement("div"));
cObj.className="credits";
cObj.innerHTML = "<b>[esc] to <a href=\"javascript:Prado.Inspector.cleanUp();\">close</a></b><br />Javascript Object Tree V2.0.";
window.scrollTo(0,0);
},
style : "#so_mContainer { position:absolute; top:5px; left:5px; background-color:#E3EBED; text-align:left; font:9pt verdana; width:85%; border:2px solid #000; padding:5px; z-index:1000;color:#000; } " + 
"#so_mContainer ul { padding-left:20px; } " + 
"#so_mContainer ul li { display:block; list-style-type:none; list-style-image:url(); line-height:2em; -moz-border-radius:.75em; font:10px verdana; padding:0; margin:2px; color:#000; } " +
"#so_mContainer li:hover { background-color:#E3EBED; } " + 
"#so_mContainer ul li span { position:relative; width:15px; height:15px; margin-right:4px; } " +
"#so_mContainer pre { background-color:#F9FAFB; border:1px solid #638DA1; height:auto; padding:5px; font:9px verdana; color:#000; } " + 
"#so_mContainer .topLevel { margin:0; padding:0; } " +
"#so_mContainer .credits { float:left; width:200px; font:6.5pt verdana; color:#000; padding:2px; margin-left:5px; text-align:left; border-top:1px solid #000; margin-top:15px; width:75%; } " +
"#so_mContainer .credits a { font:9px verdana; font-weight:bold; color:#004465; text-decoration:none; background-color:transparent; }"
}
function var_dump(obj)
{
Prado.Inspector.inspect(obj);
}
var print_r = inspect;