Hover over HTML elements in the main page. Click to hold selection.
';
consoleToolbar = _firebugDoc.getElementById("firebugToolbar");
commandLine = _firebugDoc.getElementById("firebugCommandLine");
addEvent(commandLine, "keydown", onCommandLineKeyDown);
addEvent(_firebugDoc, has("ie") || has("safari") ? "keydown" : "keypress", onKeyDown);
consoleBody = _firebugDoc.getElementById("firebugLog");
consoleObjectInspector = _firebugDoc.getElementById("objectLog");
consoleDomInspector = _firebugDoc.getElementById("domInspect");
fireBugTabs = _firebugDoc.getElementById("fireBugTabs");
layout();
flush();
}
dojo.addOnLoad(createFrame);
function clearFrame(){
_firebugDoc = null;
if(_firebugWin.console){
_firebugWin.console.clear();
}
_firebugWin = null;
consoleFrame = null;
consoleBody = null;
consoleObjectInspector = null;
consoleDomInspector = null;
commandLine = null;
messageQueue = [];
groupStack = [];
timeMap = {};
}
function evalCommandLine(){
var text = commandLine.value;
commandLine.value = "";
logRow(["> ", text], "command");
var value;
try{
value = eval(text);
}catch(e){
console.debug(e); // put exception on the console
}
console.log(value);
}
function layout(h){
var tHeight = 25; //consoleToolbar.offsetHeight; // tab style not ready on load - throws off layout
var height = h ?
h - (tHeight + commandLine.offsetHeight +25 + (h*.01)) + "px" :
(consoleFrame.offsetHeight - tHeight - commandLine.offsetHeight) + "px";
consoleBody.style.top = tHeight + "px";
consoleBody.style.height = height;
consoleObjectInspector.style.height = height;
consoleObjectInspector.style.top = tHeight + "px";
consoleDomInspector.style.height = height;
consoleDomInspector.style.top = tHeight + "px";
commandLine.style.bottom = 0;
dojo.addOnWindowUnload(clearFrame);
}
function logRow(message, className, handler){
if(consoleBody){
writeMessage(message, className, handler);
}else{
messageQueue.push([message, className, handler]);
}
}
function flush(){
var queue = messageQueue;
messageQueue = [];
for(var i = 0; i < queue.length; ++i){
writeMessage(queue[i][0], queue[i][1], queue[i][2]);
}
}
function writeMessage(message, className, handler){
var isScrolledToBottom =
consoleBody.scrollTop + consoleBody.offsetHeight >= consoleBody.scrollHeight;
handler = handler||writeRow;
handler(message, className);
if(isScrolledToBottom){
consoleBody.scrollTop = consoleBody.scrollHeight - consoleBody.offsetHeight;
}
}
function appendRow(row){
var container = groupStack.length ? groupStack[groupStack.length-1] : consoleBody;
container.appendChild(row);
}
function writeRow(message, className){
var row = consoleBody.ownerDocument.createElement("div");
row.className = "logRow" + (className ? " logRow-"+className : "");
row.innerHTML = message.join("");
appendRow(row);
}
function pushGroup(message, className){
logFormatted(message, className);
//var groupRow = consoleBody.ownerDocument.createElement("div");
//groupRow.className = "logGroup";
var groupRowBox = consoleBody.ownerDocument.createElement("div");
groupRowBox.className = "logGroupBox";
//groupRow.appendChild(groupRowBox);
appendRow(groupRowBox);
groupStack.push(groupRowBox);
}
function popGroup(){
groupStack.pop();
}
// ***************************************************************************
function logFormatted(objects, className){
var html = [];
var format = objects[0];
var objIndex = 0;
if(typeof(format) != "string"){
format = "";
objIndex = -1;
}
var parts = parseFormat(format);
for(var i = 0; i < parts.length; ++i){
var part = parts[i];
if(part && typeof part == "object"){
part.appender(objects[++objIndex], html);
}else{
appendText(part, html);
}
}
var ids = [];
var obs = [];
for(i = objIndex+1; i < objects.length; ++i){
appendText(" ", html);
var object = objects[i];
if(object === undefined || object === null ){
appendNull(object, html);
}else if(typeof(object) == "string"){
appendText(object, html);
}else if(object instanceof Date){
appendText(object.toString(), html);
}else if(object.nodeType == 9){
appendText("[ XmlDoc ]", html);
}else{
// Create link for object inspector
// need to create an ID for this link, since it is currently text
var id = "_a" + __consoleAnchorId__++;
ids.push(id);
// need to save the object, so the arrays line up
obs.push(object);
var str = '";
}));
}
}
function parseFormat(format){
var parts = [];
var reg = /((^%|[^\\]%)(\d+)?(\.)([a-zA-Z]))|((^%|[^\\]%)([a-zA-Z]))/;
var appenderMap = {s: appendText, d: appendInteger, i: appendInteger, f: appendFloat};
for(var m = reg.exec(format); m; m = reg.exec(format)){
var type = m[8] ? m[8] : m[5];
var appender = type in appenderMap ? appenderMap[type] : appendObject;
var precision = m[3] ? parseInt(m[3]) : (m[4] == "." ? -1 : 0);
parts.push(format.substr(0, m[0][0] == "%" ? m.index : m.index+1));
parts.push({appender: appender, precision: precision});
format = format.substr(m.index+m[0].length);
}
parts.push(format);
return parts;
}
function escapeHTML(value){
function replaceChars(ch){
switch(ch){
case "<":
return "<";
case ">":
return ">";
case "&":
return "&";
case "'":
return "'";
case '"':
return """;
}
return "?";
}
return String(value).replace(/[<>&"']/g, replaceChars);
}
function objectToString(object){
try{
return object+"";
}catch(e){
return null;
}
}
// ***************************************************************************
function appendLink(object, html){
// needed for object links - no HTML escaping
html.push( objectToString(object) );
}
function appendText(object, html){
html.push(escapeHTML(objectToString(object)));
}
function appendNull(object, html){
html.push('', escapeHTML(objectToString(object)), '');
}
function appendString(object, html){
html.push('"', escapeHTML(objectToString(object)),
'"');
}
function appendInteger(object, html){
html.push('', escapeHTML(objectToString(object)), '');
}
function appendFloat(object, html){
html.push('', escapeHTML(objectToString(object)), '');
}
function appendFunction(object, html){
html.push('', getObjectAbbr(object), '');
}
function appendObject(object, html){
try{
if(object === undefined){
appendNull("undefined", html);
}else if(object === null){
appendNull("null", html);
}else if(typeof object == "string"){
appendString(object, html);
}else if(typeof object == "number"){
appendInteger(object, html);
}else if(typeof object == "function"){
appendFunction(object, html);
}else if(object.nodeType == 1){
appendSelector(object, html);
}else if(typeof object == "object"){
appendObjectFormatted(object, html);
}else{
appendText(object, html);
}
}catch(e){
/* squelch */
}
}
function appendObjectFormatted(object, html){
var text = objectToString(object);
var reObject = /\[object (.*?)\]/;
var m = reObject.exec(text);
html.push('', m ? m[1] : text, '');
}
function appendSelector(object, html){
html.push('');
html.push('', escapeHTML(object.nodeName.toLowerCase()), '');
if(object.id){
html.push('#', escapeHTML(object.id), '');
}
if(object.className){
html.push('.', escapeHTML(object.className), '');
}
html.push('');
}
function appendNode(node, html){
if(node.nodeType == 1){
html.push(
'',
'<', node.nodeName.toLowerCase(), '');
for(var i = 0; i < node.attributes.length; ++i){
var attr = node.attributes[i];
if(!attr.specified){ continue; }
html.push(' ', attr.nodeName.toLowerCase(),
'="', escapeHTML(attr.nodeValue),
'"');
}
if(node.firstChild){
html.push('>
');
for(var child = node.firstChild; child; child = child.nextSibling){
appendNode(child, html);
}
html.push('
</',
node.nodeName.toLowerCase(), '>
');
}else{
html.push('/>');
}
}else if (node.nodeType == 3){
html.push('', escapeHTML(node.nodeValue),
'
');
}
}
// ***************************************************************************
function addEvent(object, name, handler){
if(document.all){
object.attachEvent("on"+name, handler);
}else{
object.addEventListener(name, handler, false);
}
}
function removeEvent(object, name, handler){
if(document.all){
object.detachEvent("on"+name, handler);
}else{
object.removeEventListener(name, handler, false);
}
}
function cancelEvent(event){
if(document.all){
event.cancelBubble = true;
}else{
event.stopPropagation();
}
}
function onError(msg, href, lineNo){
var lastSlash = href.lastIndexOf("/");
var fileName = lastSlash == -1 ? href : href.substr(lastSlash+1);
var html = [
'', msg, '',
'', fileName, ' (line ', lineNo, ')
'
];
logRow(html, "error");
}
//After converting to div instead of iframe, now getting two keydowns right away in IE 6.
//Make sure there is a little bit of delay.
var onKeyDownTime = new Date().getTime();
function onKeyDown(event){
var timestamp = (new Date()).getTime();
if(timestamp > onKeyDownTime + 200){
event = dojo.fixEvent(event);
var keys = dojo.keys;
var ekc = event.keyCode;
onKeyDownTime = timestamp;
if(ekc == keys.F12){
toggleConsole();
}else if(
(ekc == keys.NUMPAD_ENTER || ekc == 76) &&
event.shiftKey &&
(event.metaKey || event.ctrlKey)
){
focusCommandLine();
}else{
return;
}
cancelEvent(event);
}
}
function onCommandLineKeyDown(e){
var dk = dojo.keys;
if(e.keyCode == 13 && commandLine.value){
addToHistory(commandLine.value);
evalCommandLine();
}else if(e.keyCode == 27){
commandLine.value = "";
}else if(e.keyCode == dk.UP_ARROW || e.charCode == dk.UP_ARROW){
navigateHistory("older");
}else if(e.keyCode == dk.DOWN_ARROW || e.charCode == dk.DOWN_ARROW){
navigateHistory("newer");
}else if(e.keyCode == dk.HOME || e.charCode == dk.HOME){
historyPosition = 1;
navigateHistory("older");
}else if(e.keyCode == dk.END || e.charCode == dk.END){
historyPosition = 999999;
navigateHistory("newer");
}
}
var historyPosition = -1;
var historyCommandLine = null;
function addToHistory(value){
var history = cookie("firebug_history");
history = (history) ? dojo.fromJson(history) : [];
var pos = dojo.indexOf(history, value);
if (pos != -1){
history.splice(pos, 1);
}
history.push(value);
cookie("firebug_history", dojo.toJson(history), 30);
while(history.length && !cookie("firebug_history")){
history.shift();
cookie("firebug_history", dojo.toJson(history), 30);
}
historyCommandLine = null;
historyPosition = -1;
}
function navigateHistory(direction){
var history = cookie("firebug_history");
history = (history) ? dojo.fromJson(history) : [];
if(!history.length){
return;
}
if(historyCommandLine === null){
historyCommandLine = commandLine.value;
}
if(historyPosition == -1){
historyPosition = history.length;
}
if(direction == "older"){
--historyPosition;
if(historyPosition < 0){
historyPosition = 0;
}
}else if(direction == "newer"){
++historyPosition;
if(historyPosition > history.length){
historyPosition = history.length;
}
}
if(historyPosition == history.length){
commandLine.value = historyCommandLine;
historyCommandLine = null;
}else{
commandLine.value = history[historyPosition];
}
}
function cookie(name, value){
var c = document.cookie;
if(arguments.length == 1){
var matches = c.match(new RegExp("(?:^|; )" + name + "=([^;]*)"));
return matches ? decodeURIComponent(matches[1]) : undefined; // String or undefined
}else{
var d = new Date();
d.setMonth(d.getMonth()+1);
document.cookie = name + "=" + encodeURIComponent(value) + ((d.toUtcString) ? "; expires=" + d.toUTCString() : "");
}
}
function isArray(it){
return it && it instanceof Array || typeof it == "array";
}
//***************************************************************************************************
// Print Object Helpers
function objectLength(o){
var cnt = 0;
for(var nm in o){
cnt++;
}
return cnt;
}
function printObject(o, i, txt, used){
// Recursively trace object, indenting to represent depth for display in object inspector
var ind = " \t";
txt = txt || "";
i = i || ind;
used = used || [];
var opnCls;
if(o && o.nodeType == 1){
var html = [];
appendNode(o, html);
return html.join("");
}
var br=",\n", cnt = 0, length = objectLength(o);
if(o instanceof Date){
return i + o.toString() + br;
}
looking:
for(var nm in o){
cnt++;
if(cnt==length){br = "\n";}
if(o[nm] === window || o[nm] === document){
// do nothing
}else if(o[nm] === null){
txt += i+nm + " : NULL" + br;
}else if(o[nm] && o[nm].nodeType){
if(o[nm].nodeType == 1){
//txt += i+nm + " : < "+o[nm].tagName+" id=\""+ o[nm].id+"\" />" + br;
}else if(o[nm].nodeType == 3){
txt += i+nm + " : [ TextNode "+o[nm].data + " ]" + br;
}
}else if(typeof o[nm] == "object" && (o[nm] instanceof String || o[nm] instanceof Number || o[nm] instanceof Boolean)){
txt += i+nm + " : " + o[nm] + "," + br;
}else if(o[nm] instanceof Date){
txt += i+nm + " : " + o[nm].toString() + br;
}else if(typeof(o[nm]) == "object" && o[nm]){
for(var j = 0, seen; seen = used[j]; j++){
if(o[nm] === seen){
txt += i+nm + " : RECURSION" + br;
continue looking;
}
}
used.push(o[nm]);
opnCls = (isArray(o[nm]))?["[","]"]:["{","}"];
txt += i+nm +" : " + opnCls[0] + "\n";//non-standard break, (no comma)
txt += printObject(o[nm], i+ind, "", used);
txt += i + opnCls[1] + br;
}else if(typeof o[nm] == "undefined"){
txt += i+nm + " : undefined" + br;
}else if(nm == "toString" && typeof o[nm] == "function"){
var toString = o[nm]();
if(typeof toString == "string" && toString.match(/function ?(.*?)\(/)){
toString = escapeHTML(getObjectAbbr(o[nm]));
}
txt += i+nm +" : " + toString + br;
}else{
txt += i+nm +" : "+ escapeHTML(getObjectAbbr(o[nm])) + br;
}
}
return txt;
}
function getObjectAbbr(obj){
// Gets an abbreviation of an object for display in log
// X items in object, including id
// X items in an array
// TODO: Firebug Sr. actually goes by char count
var isError = (obj instanceof Error);
if(obj.nodeType == 1){
return escapeHTML('< '+obj.tagName.toLowerCase()+' id=\"'+ obj.id+ '\" />');
}
if(obj.nodeType == 3){
return escapeHTML('[TextNode: "'+obj.nodeValue+'"]');
}
var nm = (obj && (obj.id || obj.name || obj.ObjectID || obj.widgetId));
if(!isError && nm){ return "{"+nm+"}"; }
var obCnt = 2;
var arCnt = 4;
var cnt = 0;
if(isError){
nm = "[ Error: "+(obj.message || obj.description || obj)+" ]";
}else if(isArray(obj)){
nm = "[" + obj.slice(0,arCnt).join(",");
if(obj.length > arCnt){
nm += " ... ("+obj.length+" items)";
}
nm += "]";
}else if(typeof obj == "function"){
nm = obj + "";
var reg = /function\s*([^\(]*)(\([^\)]*\))[^\{]*\{/;
var m = reg.exec(nm);
if(m){
if(!m[1]){
m[1] = "function";
}
nm = m[1] + m[2];
}else{
nm = "function()";
}
}else if(typeof obj != "object" || typeof obj == "string"){
nm = obj + "";
}else{
nm = "{";
for(var i in obj){
cnt++;
if(cnt > obCnt){ break; }
nm += i+":"+escapeHTML(obj[i])+" ";
}
nm+="}";
}
return nm;
}
//*************************************************************************************
//window.onerror = onError;
addEvent(document, has("ie") || has("safari") ? "keydown" : "keypress", onKeyDown);
if( (document.documentElement.getAttribute("debug") == "true")||
(dojo.config.isDebug)
){
toggleConsole(true);
}
dojo.addOnWindowUnload(function(){
// Erase the globals and event handlers I created, to prevent spurious leak warnings
removeEvent(document, has("ie") || has("safari") ? "keydown" : "keypress", onKeyDown);
window.onFirebugResize = null;
window.console = null;
});
});