define("dojo/_firebug/firebug", [ "../_base/kernel", "require", "../_base/html", "../sniff", "../_base/array", "../_base/lang", "../_base/event", "../_base/unload"], function(dojo, require, html, has){ // module: // dojo/_firebug/firebug // summary: // Firebug Lite, the baby brother to Joe Hewitt's Firebug for Mozilla Firefox // description: // Opens a console for logging, debugging, and error messages. // Contains partial functionality to Firebug. See function list below. // // NOTE: // Firebug is a Firefox extension created by Joe Hewitt (see license). You do not need Dojo to run Firebug. // Firebug Lite is included in Dojo by permission from Joe Hewitt // If you are new to Firebug, or used to the Dojo 0.4 dojo.debug, you can learn Firebug // functionality by reading the function comments below or visiting http://www.getfirebug.com/docs.html // // NOTE: // To test Firebug Lite in Firefox: // // - FF2: set "console = null" before loading dojo and set djConfig.isDebug=true // - FF3: disable Firebug and set djConfig.isDebug=true // // example: // Supports inline objects in object inspector window (only simple trace of dom nodes, however) // | console.log("my object", {foo:"bar"}) // example: // Option for console to open in popup window // | var djConfig = {isDebug: true, popup:true }; // example: // Option for console height (ignored for popup) // | var djConfig = {isDebug: true, debugHeight:100 } var isNewIE = (/Trident/.test(window.navigator.userAgent)); if(isNewIE){ // Fixing IE's console // IE doesn't insert space between arguments. How annoying. var calls = ["log", "info", "debug", "warn", "error"]; for(var i=0;i"); str = str.replace(/\t/g, "    "); logRow([str], "dir"); }, dirxml: function(node){ var html = []; appendNode(node, html); logRow(html, "dirxml"); }, group: function(){ // summary: // collects log messages into a group, starting with this call and ending with // groupEnd(). Missing collapse functionality logRow(arguments, "group", pushGroup); }, groupEnd: function(){ // summary: // Closes group. See above logRow(arguments, "", popGroup); }, time: function(name){ // summary: // Starts timers assigned to name given in argument. Timer stops and displays on timeEnd(title); // example: // | console.time("load"); // | console.time("myFunction"); // | console.timeEnd("load"); // | console.timeEnd("myFunction"); timeMap[name] = new Date().getTime(); }, timeEnd: function(name){ // summary: // See above. if(name in timeMap){ var delta = (new Date()).getTime() - timeMap[name]; logFormatted([name+ ":", delta+"ms"]); delete timeMap[name]; } }, count: function(name){ // summary: // Not supported if(!countMap[name]) countMap[name] = 0; countMap[name]++; logFormatted([name+": "+countMap[name]]); }, trace: function(_value){ var stackAmt = _value || 3; var f = console.trace.caller; //function that called trace console.log(">>> console.trace(stack)"); for(var i=0;i=0&&s.href){ var h=s.href.replace(/(&|%5C?)forceReload=\d+/,''); s.href=h+(h.indexOf('?')>=0?'&':'?')+'forceReload='+new Date().valueOf(); } } } }; // *************************************************************************** function toggleConsole(forceOpen){ frameVisible = forceOpen || !frameVisible; if(consoleFrame){ consoleFrame.style.display = frameVisible ? "block" : "none"; } } function focusCommandLine(){ toggleConsole(true); if(commandLine){ commandLine.focus(); } } function openWin(x,y,w,h){ var win = window.open("","_firebug","status=0,menubar=0,resizable=1,top="+y+",left="+x+",width="+w+",height="+h+",scrollbars=1,addressbar=0"); if(!win){ var msg = "Firebug Lite could not open a pop-up window, most likely because of a blocker.\n" + "Either enable pop-ups for this domain, or change the djConfig to popup=false."; alert(msg); } createResizeHandler(win); var newDoc=win.document; //Safari needs an HTML height var HTMLstring= 'Firebug Lite\n' + '\n' + '
' + ''; newDoc.write(HTMLstring); newDoc.close(); return win; } function createResizeHandler(wn){ // summary: // Creates handle for onresize window. Called from script in popup's body tag (so that it will work with IE). // var d = new Date(); d.setTime(d.getTime()+(60*24*60*60*1000)); // 60 days d = d.toUTCString(); var dc = wn.document, getViewport; if (wn.innerWidth){ getViewport = function(){ return{w:wn.innerWidth, h:wn.innerHeight}; }; }else if (dc.documentElement && dc.documentElement.clientWidth){ getViewport = function(){ return{w:dc.documentElement.clientWidth, h:dc.documentElement.clientHeight}; }; }else if (dc.body){ getViewport = function(){ return{w:dc.body.clientWidth, h:dc.body.clientHeight}; }; } window.onFirebugResize = function(){ //resize the height of the console log body layout(getViewport().h); clearInterval(wn._firebugWin_resize); wn._firebugWin_resize = setTimeout(function(){ var x = wn.screenLeft, y = wn.screenTop, w = wn.outerWidth || wn.document.body.offsetWidth, h = wn.outerHeight || wn.document.body.offsetHeight; document.cookie = "_firebugPosition=" + [x,y,w,h].join(",") + "; expires="+d+"; path=/"; }, 5000); //can't capture window.onMove - long timeout gives better chance of capturing a resize, then the move }; } /*****************************************************************************/ function createFrame(){ if(consoleFrame){ return; } toggleConsole(true); if(dojo.config.popup){ var containerHeight = "100%"; var cookieMatch = document.cookie.match(/(?:^|; )_firebugPosition=([^;]*)/); var p = cookieMatch ? cookieMatch[1].split(",") : [2,2,320,480]; _firebugWin = openWin(p[0],p[1],p[2],p[3]); // global _firebugDoc = _firebugWin.document; // global dojo.config.debugContainerId = 'fb'; // connecting popup _firebugWin.console = window.console; _firebugWin.dojo = window.dojo; }else{ _firebugDoc = document; containerHeight = (dojo.config.debugHeight || 300) + "px"; } var styleElement = _firebugDoc.createElement("link"); styleElement.href = require.toUrl("./firebug.css"); styleElement.rel = "stylesheet"; styleElement.type = "text/css"; var styleParent = _firebugDoc.getElementsByTagName("head"); if(styleParent){ styleParent = styleParent[0]; } if(!styleParent){ styleParent = _firebugDoc.getElementsByTagName("html")[0]; } if(has("ie")){ window.setTimeout(function(){ styleParent.appendChild(styleElement); }, 0); }else{ styleParent.appendChild(styleElement); } if(dojo.config.debugContainerId){ consoleFrame = _firebugDoc.getElementById(dojo.config.debugContainerId); } if(!consoleFrame){ consoleFrame = _firebugDoc.createElement("div"); _firebugDoc.body.appendChild(consoleFrame); } consoleFrame.className += " firebug"; consoleFrame.id = "firebug"; consoleFrame.style.height = containerHeight; consoleFrame.style.display = (frameVisible ? "block" : "none"); var buildLink = function(label, title, method, _class){ return '
  • '+label+'
  • '; }; consoleFrame.innerHTML = '
    ' + '
      ' + buildLink("Clear", "Remove All Console Logs", "clear", "") + buildLink("ReCSS", "Refresh CSS without reloading page", "recss", "") + buildLink("Console", "Show Console Logs", "openConsole", "gap") + buildLink("DOM", "Show DOM Inspector", "openDomInspector", "") + buildLink("Object", "Show Object Inspector", "openObjectInspector", "") + ((dojo.config.popup) ? "" : buildLink("Close", "Close the console", "close", "gap")) + '
    ' + '
    ' + '' + '
    ' + '' + ''; 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 = ''+getObjectAbbr(object)+''; appendLink( str , html); } } logRow(html, className); // Now that the row is inserted in the DOM, loop through all of the links that were just created for(i=0; i"; })); } } 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, '', '' ]; 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; }); });