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>'
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="w"></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
}
}
}
Event.observe(window,"load",function(){logConsole=new LogConsole()})
function inspect(element,hideProperties,hideMethods){
var properties=[]
var methods=[]
element=$(element)
for(var internal in element){
try{
if(element[internal]instanceof Function){
if(!hideMethods)methods.push(internal+":\t"+element[internal])
}
else{
if(!hideProperties)properties.push(internal+":\t"+element[internal])
}
}
catch(e){
Logger.error("Excetion thrown while inspecting object.",e)
}
}
properties.sort()
methods.sort()
var internals=properties.concat(methods)
var output=""
for(var i=0;i<internals.length;i++){
output+=(internals[i]+"\n")
}
return output
}
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])}
