1 if(!dojo._hasResource["dojo._firebug.firebug"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
2 dojo._hasResource["dojo._firebug.firebug"] = true;
3 dojo.provide("dojo._firebug.firebug");
5 dojo.deprecated = function(/*String*/ behaviour, /*String?*/ extra, /*String?*/ removal){
7 // Log a debug message to indicate that a behavior has been
9 // extra: Text to append to the message.
11 // Text to indicate when in the future the behavior will be removed.
12 var message = "DEPRECATED: " + behaviour;
13 if(extra){ message += " " + extra; }
14 if(removal){ message += " -- will be removed in version: " + removal; }
15 console.warn(message);
18 dojo.experimental = function(/* String */ moduleName, /* String? */ extra){
19 // summary: Marks code as experimental.
21 // This can be used to mark a function, file, or module as
22 // experimental. Experimental code is not ready to be used, and the
23 // APIs are subject to change without notice. Experimental code may be
24 // completed deleted without going through the normal deprecation
27 // The name of a module, or the name of a module file or a specific
30 // some additional message for the user
32 // | dojo.experimental("dojo.data.Result");
34 // | dojo.experimental("dojo.weather.toKelvin()", "PENDING approval from NOAA");
35 var message = "EXPERIMENTAL: " + moduleName + " -- APIs subject to change without notice.";
36 if(extra){ message += " " + extra; }
37 console.warn(message);
41 // summary: Firebug Lite, the baby brother to Joe Hewitt's Firebug for Mozilla Firefox
43 // Opens a console for logging, debugging, and error messages.
44 // Contains partial functionality to Firebug. See function list below.
46 // Firebug is a Firefox extension created by Joe Hewitt (see license). You do not need Dojo to run Firebug.
47 // Firebug Lite is included in Dojo by permission from Joe Hewitt
48 // If you are new to Firebug, or used to the Dojo 0.4 dojo.debug, you can learn Firebug
49 // functionality by reading the function comments below or visiting http://www.getfirebug.com/docs.html
51 // To test Firebug Lite in Firefox, set console = null;
54 // Supports inline objects in object inspector window (only simple trace of dom nodes, however)
55 // | console.log("my object", {foo:"bar"})
57 // Option for console to open in popup window
58 // | var djConfig = {isDebug: true, popup:true };
60 // Option for console height (ignored for popup)
61 // | var djConfig = {isDebug: true, debugHeight:100 };
63 if((!("console" in window) || !("firebug" in console)) &&
64 dojo.config.noFirebugLite !== true){
67 // don't build a firebug frame in iframes
69 if(window != window.parent){
70 // but if we've got a parent logger, connect to it
71 if(window.parent["console"]){
72 window.console = window.parent.console;
76 }catch(e){/*squelch*/}
82 // Sends arguments to console.
83 logFormatted(arguments, "");
88 // Sends arguments to console. Missing finctionality to show script line of trace.
89 logFormatted(arguments, "debug");
94 // Sends arguments to console, highlighted with (I) icon.
95 logFormatted(arguments, "info");
100 // Sends warning arguments to console, highlighted with (!) icon and blue style.
101 logFormatted(arguments, "warning");
106 // Sends error arguments (object) to console, highlighted with (X) icon and yellow style
107 // NEW: error object now displays in object inspector
108 logFormatted(arguments, "error");
111 assert: function(truth, message){
113 // Tests for true. Throws exception if false.
116 for(var i = 1; i < arguments.length; ++i){
117 args.push(arguments[i]);
120 logFormatted(args.length ? args : ["Assertion Failure"], "error");
121 throw message ? message : "Assertion Failure";
125 dir: function(object){
127 // Traces object. Only partially implemented.
130 for(var prop in object){
132 pairs.push([prop, object[prop]]);
138 pairs.sort(function(a, b){
139 return a[0] < b[0] ? -1 : 1;
142 var html = ['<table>'];
143 for(var i = 0; i < pairs.length; ++i){
144 var name = pairs[i][0], value = pairs[i][1];
147 '<td class="propertyNameCell"><span class="propertyName">',
148 escapeHTML(name), '</span></td>', '<td><span class="propertyValue">');
149 appendObject(value, html);
150 html.push('</span></td></tr>');
152 html.push('</table>');
157 dirxml: function(node){
162 appendNode(node, html);
163 logRow(html, "dirxml");
168 // collects log messages into a group, starting with this call and ending with
169 // groupEnd(). Missing collapse functionality
170 logRow(arguments, "group", pushGroup);
173 groupEnd: function(){
175 // Closes group. See above
176 logRow(arguments, "", popGroup);
179 time: function(name){
181 // Starts timers assigned to name given in argument. Timer stops and displays on timeEnd(title);
183 // | console.time("load");
184 // | console.time("myFunction");
185 // | console.timeEnd("load");
186 // | console.timeEnd("myFunction");
187 timeMap[name] = (new Date()).getTime();
190 timeEnd: function(name){
194 var delta = (new Date()).getTime() - timeMap[name];
195 logFormatted([name+ ":", delta+"ms"]);
196 delete timeMap[name];
203 this.warn(["count() not supported."]);
209 this.warn(["trace() not supported."]);
215 this.warn(["profile() not supported."]);
218 profileEnd: function(){ },
222 // Clears message console. Do not call this directly
223 while(consoleBody.childNodes.length){
224 dojo._destroyElement(consoleBody.firstChild);
226 dojo.forEach(this._connects,dojo.disconnect);
231 // Opens message console. Do not call this directly
237 // Closes message console. Do not call this directly
242 closeObjectInspector:function(){
244 // Closes object inspector and opens message console. Do not call this directly
245 consoleObjectInspector.innerHTML = "";
246 consoleObjectInspector.style.display = "none";
247 consoleBody.style.display = "block";
251 // ***************************************************************************
253 // using global objects so they can be accessed
254 // most of the objects in this script are run anonomously
255 var _firebugDoc = document;
256 var _firebugWin = window;
257 var __consoleAnchorId__ = 0;
259 var consoleFrame = null;
260 var consoleBody = null;
261 var commandLine = null;
262 var consoleToolbar = null;
264 var frameVisible = false;
265 var messageQueue = [];
269 var clPrefix = ">>> ";
271 // ***************************************************************************
273 function toggleConsole(forceOpen){
274 frameVisible = forceOpen || !frameVisible;
276 consoleFrame.style.display = frameVisible ? "block" : "none";
280 function focusCommandLine(){
287 function openWin(x,y,w,h){
288 var win = window.open("","_firebug","status=0,menubar=0,resizable=1,top="+y+",left="+x+",width="+w+",height="+h+",scrollbars=1,addressbar=0");
290 var msg = "Firebug Lite could not open a pop-up window, most likely because of a blocker.\n" +
291 "Either enable pop-ups for this domain, or change the djConfig to popup=false.";
294 createResizeHandler(win);
295 var newDoc=win.document;
296 //Safari needs an HTML height
297 HTMLstring= '<html style="height:100%;"><head><title>Firebug Lite</title></head>\n' +
298 '<body bgColor="#ccc" style="height:98%;" onresize="opener.onFirebugResize()">\n' +
299 '<div id="fb"></div>' +
302 newDoc.write(HTMLstring);
307 function createResizeHandler(wn){
309 // Creates handle for onresize window. Called from script in popup's body tag (so that it will work with IE).
313 d.setTime(d.getTime()+(60*24*60*60*1000)); // 60 days
316 var dc = wn.document,
320 getViewport = function(){
321 return{w:wn.innerWidth, h:wn.innerHeight};
323 }else if (dc.documentElement && dc.documentElement.clientWidth){
324 getViewport = function(){
325 return{w:dc.documentElement.clientWidth, h:dc.documentElement.clientHeight};
328 getViewport = function(){
329 return{w:dc.body.clientWidth, h:dc.body.clientHeight};
334 window.onFirebugResize = function(){
336 //resize the height of the console log body
337 layout(getViewport().h);
339 clearInterval(wn._firebugWin_resize);
340 wn._firebugWin_resize = setTimeout(function(){
341 var x = wn.screenLeft,
343 w = wn.outerWidth || wn.document.body.offsetWidth,
344 h = wn.outerHeight || wn.document.body.offsetHeight;
346 document.cookie = "_firebugPosition=" + [x,y,w,h].join(",") + "; expires="+d+"; path=/";
348 }, 5000); //can't capture window.onMove - long timeout gives better chance of capturing a resize, then the move
354 /*****************************************************************************/
357 function createFrame(){
362 if(dojo.config.popup){
363 var containerHeight = "100%";
364 var cookieMatch = document.cookie.match(/(?:^|; )_firebugPosition=([^;]*)/);
365 var p = cookieMatch ? cookieMatch[1].split(",") : [2,2,320,480];
367 _firebugWin = openWin(p[0],p[1],p[2],p[3]); // global
368 _firebugDoc = _firebugWin.document; // global
370 djConfig.debugContainerId = 'fb';
373 _firebugWin.console = window.console;
374 _firebugWin.dojo = window.dojo;
376 _firebugDoc = document;
377 containerHeight = (dojo.config.debugHeight || 300) + "px";
380 var styleElement = _firebugDoc.createElement("link");
381 styleElement.href = dojo.moduleUrl("dojo._firebug", "firebug.css");
382 styleElement.rel = "stylesheet";
383 styleElement.type = "text/css";
384 var styleParent = _firebugDoc.getElementsByTagName("head");
386 styleParent = styleParent[0];
389 styleParent = _firebugDoc.getElementsByTagName("html")[0];
392 window.setTimeout(function(){ styleParent.appendChild(styleElement); }, 0);
394 styleParent.appendChild(styleElement);
397 if(dojo.config.debugContainerId){
398 consoleFrame = _firebugDoc.getElementById(dojo.config.debugContainerId);
401 consoleFrame = _firebugDoc.createElement("div");
402 _firebugDoc.body.appendChild(consoleFrame);
404 consoleFrame.className += " firebug";
405 consoleFrame.style.height = containerHeight;
406 consoleFrame.style.display = (frameVisible ? "block" : "none");
408 var closeStr = dojo.config.popup ? "" : ' <a href="#" onclick="console.close(); return false;">Close</a>';
409 consoleFrame.innerHTML =
410 '<div id="firebugToolbar">'
411 + ' <a href="#" onclick="console.clear(); return false;">Clear</a>'
412 + ' <span class="firebugToolbarRight">'
416 + '<input type="text" id="firebugCommandLine" />'
417 + '<div id="firebugLog"></div>'
418 + '<div id="objectLog" style="display:none;"></div>';
421 consoleToolbar = _firebugDoc.getElementById("firebugToolbar");
422 consoleToolbar.onmousedown = onSplitterMouseDown;
424 commandLine = _firebugDoc.getElementById("firebugCommandLine");
425 addEvent(commandLine, "keydown", onCommandLineKeyDown);
427 addEvent(_firebugDoc, dojo.isIE || dojo.isSafari ? "keydown" : "keypress", onKeyDown);
429 consoleBody = _firebugDoc.getElementById("firebugLog");
430 consoleObjectInspector = _firebugDoc.getElementById("objectLog");
436 dojo.addOnLoad(createFrame);
438 function clearFrame(){
441 if(_firebugWin.console){
442 _firebugWin.console.clear();
447 consoleObjectInspector = null;
453 dojo.addOnUnload(clearFrame);
455 function evalCommandLine(){
456 var text = commandLine.value;
457 commandLine.value = "";
459 logRow([clPrefix, text], "command");
465 console.debug(e); // put exception on the console
473 h - (consoleToolbar.offsetHeight + commandLine.offsetHeight +25 + (h*.01)) + "px" :
474 consoleFrame.offsetHeight - (consoleToolbar.offsetHeight + commandLine.offsetHeight) + "px";
476 consoleBody.style.top = consoleToolbar.offsetHeight + "px";
477 consoleBody.style.height = height;
478 consoleObjectInspector.style.height = height;
479 consoleObjectInspector.style.top = consoleToolbar.offsetHeight + "px";
480 commandLine.style.bottom = 0;
483 function logRow(message, className, handler){
485 writeMessage(message, className, handler);
487 messageQueue.push([message, className, handler]);
492 var queue = messageQueue;
495 for(var i = 0; i < queue.length; ++i){
496 writeMessage(queue[i][0], queue[i][1], queue[i][2]);
500 function writeMessage(message, className, handler){
501 var isScrolledToBottom =
502 consoleBody.scrollTop + consoleBody.offsetHeight >= consoleBody.scrollHeight;
504 handler = handler||writeRow;
506 handler(message, className);
508 if(isScrolledToBottom){
509 consoleBody.scrollTop = consoleBody.scrollHeight - consoleBody.offsetHeight;
513 function appendRow(row){
514 var container = groupStack.length ? groupStack[groupStack.length-1] : consoleBody;
515 container.appendChild(row);
518 function writeRow(message, className){
519 var row = consoleBody.ownerDocument.createElement("div");
520 row.className = "logRow" + (className ? " logRow-"+className : "");
521 row.innerHTML = message.join("");
525 function pushGroup(message, className){
526 logFormatted(message, className);
528 //var groupRow = consoleBody.ownerDocument.createElement("div");
529 //groupRow.className = "logGroup";
530 var groupRowBox = consoleBody.ownerDocument.createElement("div");
531 groupRowBox.className = "logGroupBox";
532 //groupRow.appendChild(groupRowBox);
533 appendRow(groupRowBox);
534 groupStack.push(groupRowBox);
541 // ***************************************************************************
543 function logFormatted(objects, className){
546 var format = objects[0];
549 if(typeof(format) != "string"){
554 var parts = parseFormat(format);
556 for(var i = 0; i < parts.length; ++i){
558 if(part && typeof part == "object"){
559 part.appender(objects[++objIndex], html);
561 appendText(part, html);
568 for(i = objIndex+1; i < objects.length; ++i){
569 appendText(" ", html);
571 var object = objects[i];
572 if(object === undefined || object === null ){
573 appendNull(object, html);
575 }else if(typeof(object) == "string"){
576 appendText(object, html);
578 }else if(object.nodeType == 9){
579 appendText("[ XmlDoc ]", html);
581 }else if(object.nodeType == 1){
582 // simple tracing of dom nodes
583 appendText("< "+object.tagName+" id=\""+ object.id+"\" />", html);
586 // Create link for object inspector
587 // need to create an ID for this link, since it is currently text
588 var id = "_a" + __consoleAnchorId__++;
590 // need to save the object, so the arrays line up
592 var str = '<a id="'+id+'" href="javascript:void(0);">'+getObjectAbbr(object)+'</a>';
594 appendLink( str , html);
598 logRow(html, className);
600 // Now that the row is inserted in the DOM, loop through all of the links that were just created
601 for(i=0; i<ids.length; i++){
602 var btn = _firebugDoc.getElementById(ids[i]);
603 if(!btn){ continue; }
605 // store the object in the dom btn for reference later
606 // avoid parsing these objects unless necessary
609 _firebugWin.console._connects.push(dojo.connect(btn, "onclick", function(){
611 consoleBody.style.display = "none";
612 consoleObjectInspector.style.display = "block";
613 // create a back button
614 var bkBtn = '<a href="javascript:console.closeObjectInspector();"> << Back</a>';
616 printObject(this.obj);
620 consoleObjectInspector.innerHTML = bkBtn + "<pre>" + printObject( this.obj ) + "</pre>";
625 function parseFormat(format){
628 var reg = /((^%|[^\\]%)(\d+)?(\.)([a-zA-Z]))|((^%|[^\\]%)([a-zA-Z]))/;
629 var appenderMap = {s: appendText, d: appendInteger, i: appendInteger, f: appendFloat};
631 for(var m = reg.exec(format); m; m = reg.exec(format)){
632 var type = m[8] ? m[8] : m[5];
633 var appender = type in appenderMap ? appenderMap[type] : appendObject;
634 var precision = m[3] ? parseInt(m[3]) : (m[4] == "." ? -1 : 0);
636 parts.push(format.substr(0, m[0][0] == "%" ? m.index : m.index+1));
637 parts.push({appender: appender, precision: precision});
639 format = format.substr(m.index+m[0].length);
647 function escapeHTML(value){
648 function replaceChars(ch){
663 return String(value).replace(/[<>&"']/g, replaceChars);
666 function objectToString(object){
674 // ***************************************************************************
675 function appendLink(object, html){
676 // needed for object links - no HTML escaping
677 html.push( objectToString(object) );
680 function appendText(object, html){
681 html.push(escapeHTML(objectToString(object)));
684 function appendNull(object, html){
685 html.push('<span class="objectBox-null">', escapeHTML(objectToString(object)), '</span>');
688 function appendString(object, html){
689 html.push('<span class="objectBox-string">"', escapeHTML(objectToString(object)),
693 function appendInteger(object, html){
694 html.push('<span class="objectBox-number">', escapeHTML(objectToString(object)), '</span>');
697 function appendFloat(object, html){
698 html.push('<span class="objectBox-number">', escapeHTML(objectToString(object)), '</span>');
701 function appendFunction(object, html){
702 html.push('<span class="objectBox-function">', getObjectAbbr(object), '</span>');
705 function appendObject(object, html){
707 if(object === undefined){
708 appendNull("undefined", html);
709 }else if(object === null){
710 appendNull("null", html);
711 }else if(typeof object == "string"){
712 appendString(object, html);
713 }else if(typeof object == "number"){
714 appendInteger(object, html);
715 }else if(typeof object == "function"){
716 appendFunction(object, html);
717 }else if(object.nodeType == 1){
718 appendSelector(object, html);
719 }else if(typeof object == "object"){
720 appendObjectFormatted(object, html);
722 appendText(object, html);
729 function appendObjectFormatted(object, html){
730 var text = objectToString(object);
731 var reObject = /\[object (.*?)\]/;
733 var m = reObject.exec(text);
734 html.push('<span class="objectBox-object">', m ? m[1] : text, '</span>');
737 function appendSelector(object, html){
738 html.push('<span class="objectBox-selector">');
740 html.push('<span class="selectorTag">', escapeHTML(object.nodeName.toLowerCase()), '</span>');
742 html.push('<span class="selectorId">#', escapeHTML(object.id), '</span>');
744 if(object.className){
745 html.push('<span class="selectorClass">.', escapeHTML(object.className), '</span>');
748 html.push('</span>');
751 function appendNode(node, html){
752 if(node.nodeType == 1){
754 '<div class="objectBox-element">',
755 '<<span class="nodeTag">', node.nodeName.toLowerCase(), '</span>');
757 for(var i = 0; i < node.attributes.length; ++i){
758 var attr = node.attributes[i];
759 if(!attr.specified){ continue; }
761 html.push(' <span class="nodeName">', attr.nodeName.toLowerCase(),
762 '</span>="<span class="nodeValue">', escapeHTML(attr.nodeValue),
767 html.push('></div><div class="nodeChildren">');
769 for(var child = node.firstChild; child; child = child.nextSibling){
770 appendNode(child, html);
773 html.push('</div><div class="objectBox-element"></<span class="nodeTag">',
774 node.nodeName.toLowerCase(), '></span></div>');
776 html.push('/></div>');
778 }else if (node.nodeType == 3){
779 html.push('<div class="nodeText">', escapeHTML(node.nodeValue),
784 // ***************************************************************************
786 function addEvent(object, name, handler){
788 object.attachEvent("on"+name, handler);
790 object.addEventListener(name, handler, false);
794 function removeEvent(object, name, handler){
796 object.detachEvent("on"+name, handler);
798 object.removeEventListener(name, handler, false);
802 function cancelEvent(event){
804 event.cancelBubble = true;
806 event.stopPropagation();
810 function onError(msg, href, lineNo){
811 var lastSlash = href.lastIndexOf("/");
812 var fileName = lastSlash == -1 ? href : href.substr(lastSlash+1);
815 '<span class="errorMessage">', msg, '</span>',
816 '<div class="objectBox-sourceLink">', fileName, ' (line ', lineNo, ')</div>'
819 logRow(html, "error");
823 //After converting to div instead of iframe, now getting two keydowns right away in IE 6.
824 //Make sure there is a little bit of delay.
825 var onKeyDownTime = (new Date()).getTime();
827 function onKeyDown(event){
828 var timestamp = (new Date()).getTime();
829 if(timestamp > onKeyDownTime + 200){
830 event = dojo.fixEvent(event);
831 var keys = dojo.keys;
832 var ekc = event.keyCode;
833 onKeyDownTime = timestamp;
837 (ekc == keys.NUMPAD_ENTER || ekc == 76) &&
839 (event.metaKey || event.ctrlKey)
850 function onSplitterMouseDown(event){
851 if(dojo.isSafari || dojo.isOpera){
855 addEvent(document, "mousemove", onSplitterMouseMove);
856 addEvent(document, "mouseup", onSplitterMouseUp);
858 for(var i = 0; i < frames.length; ++i){
859 addEvent(frames[i].document, "mousemove", onSplitterMouseMove);
860 addEvent(frames[i].document, "mouseup", onSplitterMouseUp);
864 function onSplitterMouseMove(event){
865 var win = document.all ?
866 event.srcElement.ownerDocument.parentWindow :
867 event.target.ownerDocument.defaultView;
869 var clientY = event.clientY;
870 if(win != win.parent){
871 clientY += win.frameElement ? win.frameElement.offsetTop : 0;
874 var height = consoleFrame.offsetTop + consoleFrame.clientHeight;
875 var y = height - clientY;
877 consoleFrame.style.height = y + "px";
881 function onSplitterMouseUp(event){
882 removeEvent(document, "mousemove", onSplitterMouseMove);
883 removeEvent(document, "mouseup", onSplitterMouseUp);
885 for(var i = 0; i < frames.length; ++i){
886 removeEvent(frames[i].document, "mousemove", onSplitterMouseMove);
887 removeEvent(frames[i].document, "mouseup", onSplitterMouseUp);
891 function onCommandLineKeyDown(event){
892 if(event.keyCode == 13 && commandLine.value){
893 addToHistory(commandLine.value);
895 }else if(event.keyCode == 27){
896 commandLine.value = "";
897 }else if(event.keyCode == dojo.keys.UP_ARROW || event.charCode == dojo.keys.UP_ARROW){
898 navigateHistory("older");
899 }else if(event.keyCode == dojo.keys.DOWN_ARROW || event.charCode == dojo.keys.DOWN_ARROW){
900 navigateHistory("newer");
901 }else if(event.keyCode == dojo.keys.HOME || event.charCode == dojo.keys.HOME){
903 navigateHistory("older");
904 }else if(event.keyCode == dojo.keys.END || event.charCode == dojo.keys.END){
905 historyPosition = 999999;
906 navigateHistory("newer");
910 var historyPosition = -1;
911 var historyCommandLine = null;
913 function addToHistory(value){
914 var history = cookie("firebug_history");
915 history = (history) ? dojo.fromJson(history) : [];
916 var pos = dojo.indexOf(history, value);
918 history.splice(pos, 1);
921 cookie("firebug_history", dojo.toJson(history), 30);
922 while(history.length && !cookie("firebug_history")){
924 cookie("firebug_history", dojo.toJson(history), 30);
926 historyCommandLine = null;
927 historyPosition = -1;
930 function navigateHistory(direction){
931 var history = cookie("firebug_history");
932 history = (history) ? dojo.fromJson(history) : [];
937 if(historyCommandLine === null){
938 historyCommandLine = commandLine.value;
941 if(historyPosition == -1){
942 historyPosition = history.length;
945 if(direction == "older"){
947 if(historyPosition < 0){
950 }else if(direction == "newer"){
952 if(historyPosition > history.length){
953 historyPosition = history.length;
957 if(historyPosition == history.length){
958 commandLine.value = historyCommandLine;
959 historyCommandLine = null;
961 commandLine.value = history[historyPosition];
965 function cookie(name, value){
966 var c = document.cookie;
967 if(arguments.length == 1){
968 var matches = c.match(new RegExp("(?:^|; )" + name + "=([^;]*)"));
969 return matches ? decodeURIComponent(matches[1]) : undefined; // String or undefined
972 d.setMonth(d.getMonth()+1);
973 document.cookie = name + "=" + encodeURIComponent(value) + ((d.toUtcString) ? "; expires=" + d.toUTCString() : "");
977 function isArray(it){
978 return it && it instanceof Array || typeof it == "array";
981 //***************************************************************************************************
982 // Print Object Helpers
984 //Get amount of items in an object
986 return "[array with " + o.length + " slots]";
992 return "{object with " + i + " items}";
996 function printObject(o, i, txt, used){
997 // Recursively trace object, indenting to represent depth for display in object inspector
998 // TODO: counter to prevent overly complex or looped objects (will probably help with dom nodes)
999 var br = "\n"; // using a <pre>... otherwise we'd need a <br />
1006 if(o[nm] === window || o[nm] === document){
1008 }else if(o[nm] && o[nm].nodeType){
1009 if(o[nm].nodeType == 1){
1010 txt += i+nm + " : < "+o[nm].tagName+" id=\""+ o[nm].id+"\" />" + br;
1011 }else if(o[nm].nodeType == 3){
1012 txt += i+nm + " : [ TextNode "+o[nm].data + " ]" + br;
1014 }else if(typeof o[nm] == "object" && (o[nm] instanceof String || o[nm] instanceof Number || o[nm] instanceof Boolean)){
1015 txt += i+nm + " : " + o[nm] + br;
1016 }else if(typeof(o[nm]) == "object" && o[nm]){
1017 for(var j = 0, seen; seen = used[j]; j++){
1019 txt += i+nm + " : RECURSION" + br;
1024 txt += i+nm +" -> " + getAtts(o[nm]) + br;
1025 txt += printObject(o[nm], i+ind, "", used);
1026 }else if(typeof o[nm] == "undefined"){
1027 txt += i+nm + " : undefined" + br;
1028 }else if(nm == "toString" && typeof o[nm] == "function"){
1029 var toString = o[nm]();
1030 if(typeof toString == "string" && toString.match(/function ?(.*?)\(/)){
1031 toString = escapeHTML(getObjectAbbr(o[nm]));
1033 txt += i+nm +" : " + toString + br;
1035 txt += i+nm +" : "+ escapeHTML(getObjectAbbr(o[nm])) + br;
1038 txt += br; // keeps data from running to the edge of page
1042 function getObjectAbbr(obj){
1043 // Gets an abbreviation of an object for display in log
1044 // X items in object, including id
1045 // X items in an array
1046 // TODO: Firebug Sr. actually goes by char count
1047 var isError = (obj instanceof Error);
1048 var nm = (obj && (obj.id || obj.name || obj.ObjectID || obj.widgetId));
1049 if(!isError && nm){ return "{"+nm+"}"; }
1056 nm = "[ Error: "+(obj.message || obj.description || obj)+" ]";
1057 }else if(isArray(obj)){
1058 nm = "[" + obj.slice(0,arCnt).join(",");
1059 if(obj.length > arCnt){
1060 nm += " ... ("+obj.length+" items)";
1063 }else if(typeof obj == "function"){
1065 var reg = /function\s*([^\(]*)(\([^\)]*\))[^\{]*\{/;
1066 var m = reg.exec(nm);
1075 }else if(typeof obj != "object" || typeof obj == "string"){
1081 if(cnt > obCnt){ break; }
1082 nm += i+"="+obj[i]+" ";
1090 //*************************************************************************************
1092 window.onerror = onError;
1093 addEvent(document, dojo.isIE || dojo.isSafari ? "keydown" : "keypress", onKeyDown);
1095 if( (document.documentElement.getAttribute("debug") == "true")||
1096 (dojo.config.isDebug)
1098 toggleConsole(true);