]> git.wh0rd.org - tt-rss.git/blame - lib/dojo/_firebug/firebug.js
build custom layer of Dojo to speed up loading of tt-rss (refs #293)
[tt-rss.git] / lib / dojo / _firebug / firebug.js
CommitLineData
2f01fe57
AD
1/*
2 Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved.
3 Available via Academic Free License >= 2.1 OR the modified BSD license.
4 see: http://dojotoolkit.org/license for details
5*/
6
7
a089699c
AD
8if(!dojo._hasResource["dojo._firebug.firebug"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
9dojo._hasResource["dojo._firebug.firebug"] = true;
2f01fe57 10dojo.provide("dojo._firebug.firebug");
a089699c
AD
11
12dojo.deprecated = function(/*String*/ behaviour, /*String?*/ extra, /*String?*/ removal){
13 // summary:
14 // Log a debug message to indicate that a behavior has been
15 // deprecated.
16 // extra: Text to append to the message.
17 // removal:
18 // Text to indicate when in the future the behavior will be removed.
19 var message = "DEPRECATED: " + behaviour;
20 if(extra){ message += " " + extra; }
21 if(removal){ message += " -- will be removed in version: " + removal; }
22 console.warn(message);
2f01fe57 23};
a089699c
AD
24
25dojo.experimental = function(/* String */ moduleName, /* String? */ extra){
26 // summary: Marks code as experimental.
27 // description:
28 // This can be used to mark a function, file, or module as
29 // experimental. Experimental code is not ready to be used, and the
30 // APIs are subject to change without notice. Experimental code may be
31 // completed deleted without going through the normal deprecation
32 // process.
33 // moduleName:
34 // The name of a module, or the name of a module file or a specific
35 // function
36 // extra:
37 // some additional message for the user
38 // example:
39 // | dojo.experimental("dojo.data.Result");
40 // example:
41 // | dojo.experimental("dojo.weather.toKelvin()", "PENDING approval from NOAA");
42 var message = "EXPERIMENTAL: " + moduleName + " -- APIs subject to change without notice.";
43 if(extra){ message += " " + extra; }
44 console.warn(message);
2f01fe57 45};
a089699c
AD
46
47// FIREBUG LITE
48 // summary: Firebug Lite, the baby brother to Joe Hewitt's Firebug for Mozilla Firefox
49 // description:
50 // Opens a console for logging, debugging, and error messages.
51 // Contains partial functionality to Firebug. See function list below.
52 // NOTE:
53 // Firebug is a Firefox extension created by Joe Hewitt (see license). You do not need Dojo to run Firebug.
54 // Firebug Lite is included in Dojo by permission from Joe Hewitt
55 // If you are new to Firebug, or used to the Dojo 0.4 dojo.debug, you can learn Firebug
56 // functionality by reading the function comments below or visiting http://www.getfirebug.com/docs.html
57 // NOTE:
58 // To test Firebug Lite in Firefox:
59 // FF2: set "console = null" before loading dojo and set djConfig.isDebug=true
60 // FF3: disable Firebug and set djConfig.isDebug=true
61 //
62 // example:
63 // Supports inline objects in object inspector window (only simple trace of dom nodes, however)
64 // | console.log("my object", {foo:"bar"})
65 // example:
66 // Option for console to open in popup window
67 // | var djConfig = {isDebug: true, popup:true };
68 // example:
69 // Option for console height (ignored for popup)
70 // | var djConfig = {isDebug: true, debugHeight:100 }
71
72
73
2f01fe57 74(function(){
a089699c
AD
75
76 var isNewIE = (/Trident/.test(window.navigator.userAgent));
77 if(isNewIE){
78 // Fixing IE's console
79 // IE doesn't insert space between arguments. How annoying.
80 var calls = ["log", "info", "debug", "warn", "error"];
81 for(var i=0;i<calls.length;i++){
82 var m = calls[i];
83 var n = "_"+calls[i]
84 console[n] = console[m];
85 console[m] = (function(){
86 var type = n;
87 return function(){
88 console[type](Array.prototype.slice.call(arguments).join(" "));
89 }
90 })();
91 }
92 // clear the console on load. This is more than a convenience - too many logs crashes it.
93 // If closed it throws an error
94 try{ console.clear(); }catch(e){}
95 }
96
97 if(
98 !dojo.isFF && // Firefox has Firebug
99 (!dojo.isChrome || dojo.isChrome < 3) &&
100 (!dojo.isSafari || dojo.isSafari < 4) && // Safari 4 has a console
101 !isNewIE && // Has the new IE console
102 !window.firebug && // Testing for mozilla firebug lite
103 (typeof console != "undefined" && !console.firebug) && //A console that is not firebug's
104 !dojo.config.useCustomLogger && // Allow custom loggers
105 !dojo.isAIR // isDebug triggers AIRInsector, not Firebug
106 ){
107
108
109 // don't build firebug in iframes
110 try{
111 if(window != window.parent){
112 // but if we've got a parent logger, connect to it
113 if(window.parent["console"]){
114 window.console = window.parent.console;
115 }
116 return;
117 }
118 }catch(e){/*squelch*/}
119
120 // ***************************************************************************
121 // Placing these variables before the functions that use them to avoid a
122 // shrinksafe bug where variable renaming does not happen correctly otherwise.
123
124 // most of the objects in this script are run anonomously
125 var _firebugDoc = document;
126 var _firebugWin = window;
127 var __consoleAnchorId__ = 0;
128
129 var consoleFrame = null;
130 var consoleBody = null;
131 var consoleObjectInspector = null;
132 var fireBugTabs = null;
133 var commandLine = null;
134 var consoleToolbar = null;
135
136 var frameVisible = false;
137 var messageQueue = [];
138 var groupStack = [];
139 var timeMap = {};
140 var countMap = {};
141
142 var consoleDomInspector = null;
143 var _inspectionMoveConnection;
144 var _inspectionClickConnection;
145 var _inspectionEnabled = false;
146 var _inspectionTimer = null;
147 var _inspectTempNode = document.createElement("div");
148
149
150 var _inspectCurrentNode;
151 var _restoreBorderStyle;
152
153 // ***************************************************************************
154
155 window.console = {
156 _connects: [],
157 log: function(){
158 // summary:
159 // Sends arguments to console.
160 logFormatted(arguments, "");
161 },
162
163 debug: function(){
164 // summary:
165 // Sends arguments to console. Missing finctionality to show script line of trace.
166 logFormatted(arguments, "debug");
167 },
168
169 info: function(){
170 // summary:
171 // Sends arguments to console, highlighted with (I) icon.
172 logFormatted(arguments, "info");
173 },
174
175 warn: function(){
176 // summary:
177 // Sends warning arguments to console, highlighted with (!) icon and blue style.
178 logFormatted(arguments, "warning");
179 },
180
181 error: function(){
182 // summary:
183 // Sends error arguments (object) to console, highlighted with (X) icon and yellow style
184 // NEW: error object now displays in object inspector
185 logFormatted(arguments, "error");
186 },
187
188 assert: function(truth, message){
189 // summary:
190 // Tests for true. Throws exception if false.
191 if(!truth){
192 var args = [];
193 for(var i = 1; i < arguments.length; ++i){
194 args.push(arguments[i]);
195 }
196
197 logFormatted(args.length ? args : ["Assertion Failure"], "error");
198 throw message ? message : "Assertion Failure";
199 }
200 },
201
202 dir: function(obj){
203 var str = printObject( obj );
204 str = str.replace(/\n/g, "<br />");
205 str = str.replace(/\t/g, "&nbsp;&nbsp;&nbsp;&nbsp;");
206 logRow([str], "dir");
207 },
208
209 dirxml: function(node){
210 // summary:
211 //
212 var html = [];
213 appendNode(node, html);
214 logRow(html, "dirxml");
215 },
216
217 group: function(){
218 // summary:
219 // collects log messages into a group, starting with this call and ending with
220 // groupEnd(). Missing collapse functionality
221 logRow(arguments, "group", pushGroup);
222 },
223
224 groupEnd: function(){
225 // summary:
226 // Closes group. See above
227 logRow(arguments, "", popGroup);
228 },
229
230 time: function(name){
231 // summary:
232 // Starts timers assigned to name given in argument. Timer stops and displays on timeEnd(title);
233 // example:
234 // | console.time("load");
235 // | console.time("myFunction");
236 // | console.timeEnd("load");
237 // | console.timeEnd("myFunction");
238 timeMap[name] = new Date().getTime();
239 },
240
241 timeEnd: function(name){
242 // summary:
243 // See above.
244 if(name in timeMap){
245 var delta = (new Date()).getTime() - timeMap[name];
246 logFormatted([name+ ":", delta+"ms"]);
247 delete timeMap[name];
248 }
249 },
250
251 count: function(name){
252 // summary:
253 // Not supported
254 if(!countMap[name]) countMap[name] = 0;
255 countMap[name]++;
256 logFormatted([name+": "+countMap[name]]);
257 },
258
259 trace: function(_value){
260 var stackAmt = _value || 3;
261 var f = console.trace.caller; //function that called trace
262 console.log(">>> console.trace(stack)");
263 for(var i=0;i<stackAmt;i++){
264 var func = f.toString();
265 var args=[];
266 for (var a = 0; a < f.arguments.length; a++) {
267 args.push(f.arguments[a])
268 }
269 if(f.arguments.length){
270 console.dir({"function":func, "arguments":args});
271 }else{
272 console.dir({"function":func});
273 }
274
275 f = f.caller;
276 }
277 },
278
279 profile: function(){
280 // summary:
281 // Not supported
282 this.warn(["profile() not supported."]);
283 },
284
285 profileEnd: function(){ },
286
287 clear: function(){
288 // summary:
289 // Clears message console. Do not call this directly
290 if(consoleBody){
291 while(consoleBody.childNodes.length){
292 dojo.destroy(consoleBody.firstChild);
293 }
294 }
295 dojo.forEach(this._connects,dojo.disconnect);
296 },
297
298 open: function(){
299 // summary:
300 // Opens message console. Do not call this directly
301 toggleConsole(true);
302 },
303
304 close: function(){
305 // summary:
306 // Closes message console. Do not call this directly
307 if(frameVisible){
308 toggleConsole();
309 }
310 },
311 _restoreBorder: function(){
312 if(_inspectCurrentNode){
313 _inspectCurrentNode.style.border = _restoreBorderStyle;
314 }
315 },
316 openDomInspector: function(){
317 _inspectionEnabled = true;
318 consoleBody.style.display = "none";
319 consoleDomInspector.style.display = "block";
320 consoleObjectInspector.style.display = "none";
321 document.body.style.cursor = "pointer";
322 _inspectionMoveConnection = dojo.connect(document, "mousemove", function(evt){
323 if(!_inspectionEnabled){ return; }
324 if(!_inspectionTimer){
325 _inspectionTimer = setTimeout(function(){ _inspectionTimer = null; }, 50);
326 }else{
327 return;
328 }
329 var node = evt.target;
330 if(node && (_inspectCurrentNode !== node)){
331 var parent = true;
332
333 console._restoreBorder();
334 var html = [];
335 appendNode(node, html);
336 consoleDomInspector.innerHTML = html.join("");
337
338 _inspectCurrentNode = node;
339 _restoreBorderStyle = _inspectCurrentNode.style.border;
340 _inspectCurrentNode.style.border = "#0000FF 1px solid";
341 }
342 });
343 setTimeout(function(){
344 _inspectionClickConnection = dojo.connect(document, "click", function(evt){
345 document.body.style.cursor = "";
346 _inspectionEnabled = !_inspectionEnabled;
347 dojo.disconnect(_inspectionClickConnection);
348 // console._restoreBorder();
349 });
350 }, 30);
351 },
352 _closeDomInspector: function(){
353 document.body.style.cursor = "";
354 dojo.disconnect(_inspectionMoveConnection);
355 dojo.disconnect(_inspectionClickConnection);
356 _inspectionEnabled = false;
357 console._restoreBorder();
358 },
359 openConsole:function(){
360 // summary:
361 // Closes object inspector and opens message console. Do not call this directly
362 consoleBody.style.display = "block";
363 consoleDomInspector.style.display = "none";
364 consoleObjectInspector.style.display = "none";
365 console._closeDomInspector();
366 },
367 openObjectInspector:function(){
368 consoleBody.style.display = "none";
369 consoleDomInspector.style.display = "none";
370 consoleObjectInspector.style.display = "block";
371 console._closeDomInspector();
372 },
373 recss: function(){
374 // http://turtle.dojotoolkit.org/~david/recss.html
375 // this is placed in dojo since the console is most likely
376 // in another window and dojo is easilly accessible
377 var i,a,s;a=document.getElementsByTagName('link');
378 for(i=0;i<a.length;i++){
379 s=a[i];
380 if(s.rel.toLowerCase().indexOf('stylesheet')>=0&&s.href) {
381 var h=s.href.replace(/(&|%5C?)forceReload=\d+/,'');
382 s.href=h+(h.indexOf('?')>=0?'&':'?')+'forceReload='+new Date().valueOf();
383 }
384 }
385 }
386 }
387
388 // ***************************************************************************
389
390 function toggleConsole(forceOpen){
391 frameVisible = forceOpen || !frameVisible;
392 if(consoleFrame){
393 consoleFrame.style.display = frameVisible ? "block" : "none";
394 }
395 }
396
397 function focusCommandLine(){
398 toggleConsole(true);
399 if(commandLine){
400 commandLine.focus();
401 }
402 }
403
404 function openWin(x,y,w,h){
405 var win = window.open("","_firebug","status=0,menubar=0,resizable=1,top="+y+",left="+x+",width="+w+",height="+h+",scrollbars=1,addressbar=0");
406 if(!win){
407 var msg = "Firebug Lite could not open a pop-up window, most likely because of a blocker.\n" +
408 "Either enable pop-ups for this domain, or change the djConfig to popup=false.";
409 alert(msg);
410 }
411 createResizeHandler(win);
412 var newDoc=win.document;
413 //Safari needs an HTML height
414 var HTMLstring= '<html style="height:100%;"><head><title>Firebug Lite</title></head>\n' +
415 '<body bgColor="#ccc" style="height:97%;" onresize="opener.onFirebugResize()">\n' +
416 '<div id="fb"></div>' +
417 '</body></html>';
418
419 newDoc.write(HTMLstring);
420 newDoc.close();
421 return win;
422 }
423
424 function createResizeHandler(wn){
425 // summary
426 // Creates handle for onresize window. Called from script in popup's body tag (so that it will work with IE).
427 //
428
429 var d = new Date();
430 d.setTime(d.getTime()+(60*24*60*60*1000)); // 60 days
431 d = d.toUTCString();
432
433 var dc = wn.document,
434 getViewport;
435
436 if (wn.innerWidth){
437 getViewport = function(){
438 return{w:wn.innerWidth, h:wn.innerHeight};
439 };
440 }else if (dc.documentElement && dc.documentElement.clientWidth){
441 getViewport = function(){
442 return{w:dc.documentElement.clientWidth, h:dc.documentElement.clientHeight};
443 };
444 }else if (dc.body){
445 getViewport = function(){
446 return{w:dc.body.clientWidth, h:dc.body.clientHeight};
447 };
448 }
449
450
451 window.onFirebugResize = function(){
452
453 //resize the height of the console log body
454 layout(getViewport().h);
455
456 clearInterval(wn._firebugWin_resize);
457 wn._firebugWin_resize = setTimeout(function(){
458 var x = wn.screenLeft,
459 y = wn.screenTop,
460 w = wn.outerWidth || wn.document.body.offsetWidth,
461 h = wn.outerHeight || wn.document.body.offsetHeight;
462
463 document.cookie = "_firebugPosition=" + [x,y,w,h].join(",") + "; expires="+d+"; path=/";
464
465 }, 5000); //can't capture window.onMove - long timeout gives better chance of capturing a resize, then the move
466
467 };
468 }
469
470
471 /*****************************************************************************/
472
473
474 function createFrame(){
475 if(consoleFrame){
476 return;
477 }
478
479 if(dojo.config.popup){
480 var containerHeight = "100%";
481 var cookieMatch = document.cookie.match(/(?:^|; )_firebugPosition=([^;]*)/);
482 var p = cookieMatch ? cookieMatch[1].split(",") : [2,2,320,480];
483
484 _firebugWin = openWin(p[0],p[1],p[2],p[3]); // global
485 _firebugDoc = _firebugWin.document; // global
486
487 dojo.config.debugContainerId = 'fb';
488
489 // connecting popup
490 _firebugWin.console = window.console;
491 _firebugWin.dojo = window.dojo;
492 }else{
493 _firebugDoc = document;
494 containerHeight = (dojo.config.debugHeight || 300) + "px";
495 }
496
497 var styleElement = _firebugDoc.createElement("link");
498 styleElement.href = dojo.moduleUrl("dojo._firebug", "firebug.css");
499 styleElement.rel = "stylesheet";
500 styleElement.type = "text/css";
501 var styleParent = _firebugDoc.getElementsByTagName("head");
502 if(styleParent){
503 styleParent = styleParent[0];
504 }
505 if(!styleParent){
506 styleParent = _firebugDoc.getElementsByTagName("html")[0];
507 }
508 if(dojo.isIE){
509 window.setTimeout(function(){ styleParent.appendChild(styleElement); }, 0);
510 }else{
511 styleParent.appendChild(styleElement);
512 }
513
514 if(dojo.config.debugContainerId){
515 consoleFrame = _firebugDoc.getElementById(dojo.config.debugContainerId);
516 }
517 if(!consoleFrame){
518 consoleFrame = _firebugDoc.createElement("div");
519 _firebugDoc.body.appendChild(consoleFrame);
520 }
521 consoleFrame.className += " firebug";
522 consoleFrame.style.height = containerHeight;
523 consoleFrame.style.display = (frameVisible ? "block" : "none");
524
525 var buildLink = function(label, title, method, _class){
526 return '<li class="'+_class+'"><a href="javascript:void(0);" onclick="console.'+ method +'(); return false;" title="'+title+'">'+label+'</a></li>';
527 };
528 consoleFrame.innerHTML =
529 '<div id="firebugToolbar">'
530 + ' <ul id="fireBugTabs" class="tabs">'
531
532 + buildLink("Clear", "Remove All Console Logs", "clear", "")
533 + buildLink("ReCSS", "Refresh CSS without reloading page", "recss", "")
534
535 + buildLink("Console", "Show Console Logs", "openConsole", "gap")
536 + buildLink("DOM", "Show DOM Inspector", "openDomInspector", "")
537 + buildLink("Object", "Show Object Inspector", "openObjectInspector", "")
538 + ((dojo.config.popup) ? "" : buildLink("Close", "Close the console", "close", "gap"))
539
540 + ' </ul>'
541 + '</div>'
542 + '<input type="text" id="firebugCommandLine" />'
543 + '<div id="firebugLog"></div>'
544 + '<div id="objectLog" style="display:none;">Click on an object in the Log display</div>'
545 + '<div id="domInspect" style="display:none;">Hover over HTML elements in the main page. Click to hold selection.</div>';
546
547
548 consoleToolbar = _firebugDoc.getElementById("firebugToolbar");
549
550 commandLine = _firebugDoc.getElementById("firebugCommandLine");
551 addEvent(commandLine, "keydown", onCommandLineKeyDown);
552
553 addEvent(_firebugDoc, dojo.isIE || dojo.isSafari ? "keydown" : "keypress", onKeyDown);
554
555 consoleBody = _firebugDoc.getElementById("firebugLog");
556 consoleObjectInspector = _firebugDoc.getElementById("objectLog");
557 consoleDomInspector = _firebugDoc.getElementById("domInspect");
558 fireBugTabs = _firebugDoc.getElementById("fireBugTabs");
559 layout();
560 flush();
561 }
562
563 dojo.addOnLoad(createFrame);
564
565 function clearFrame(){
566 _firebugDoc = null;
567
568 if(_firebugWin.console){
569 _firebugWin.console.clear();
570 }
571 _firebugWin = null;
572 consoleFrame = null;
573 consoleBody = null;
574 consoleObjectInspector = null;
575 consoleDomInspector = null;
576 commandLine = null;
577 messageQueue = [];
578 groupStack = [];
579 timeMap = {};
580 }
581
582
583 function evalCommandLine(){
584 var text = commandLine.value;
585 commandLine.value = "";
586
587 logRow(["> ", text], "command");
588
589 var value;
590 try{
591 value = eval(text);
592 }catch(e){
593 console.debug(e); // put exception on the console
594 }
595
596 console.log(value);
597 }
598
599 function layout(h){
600 var tHeight = 25; //consoleToolbar.offsetHeight; // tab style not ready on load - throws off layout
601 var height = h ?
602 h - (tHeight + commandLine.offsetHeight +25 + (h*.01)) + "px" :
603 (consoleFrame.offsetHeight - tHeight - commandLine.offsetHeight) + "px";
604
605 consoleBody.style.top = tHeight + "px";
606 consoleBody.style.height = height;
607 consoleObjectInspector.style.height = height;
608 consoleObjectInspector.style.top = tHeight + "px";
609 consoleDomInspector.style.height = height;
610 consoleDomInspector.style.top = tHeight + "px";
611 commandLine.style.bottom = 0;
612
613 dojo.addOnWindowUnload(clearFrame)
614 }
615
616 function logRow(message, className, handler){
617 if(consoleBody){
618 writeMessage(message, className, handler);
619 }else{
620 messageQueue.push([message, className, handler]);
621 }
622 }
623
624 function flush(){
625 var queue = messageQueue;
626 messageQueue = [];
627
628 for(var i = 0; i < queue.length; ++i){
629 writeMessage(queue[i][0], queue[i][1], queue[i][2]);
630 }
631 }
632
633 function writeMessage(message, className, handler){
634 var isScrolledToBottom =
635 consoleBody.scrollTop + consoleBody.offsetHeight >= consoleBody.scrollHeight;
636
637 handler = handler||writeRow;
638
639 handler(message, className);
640
641 if(isScrolledToBottom){
642 consoleBody.scrollTop = consoleBody.scrollHeight - consoleBody.offsetHeight;
643 }
644 }
645
646 function appendRow(row){
647 var container = groupStack.length ? groupStack[groupStack.length-1] : consoleBody;
648 container.appendChild(row);
649 }
650
651 function writeRow(message, className){
652 var row = consoleBody.ownerDocument.createElement("div");
653 row.className = "logRow" + (className ? " logRow-"+className : "");
654 row.innerHTML = message.join("");
655 appendRow(row);
656 }
657
658 function pushGroup(message, className){
659 logFormatted(message, className);
660
661 //var groupRow = consoleBody.ownerDocument.createElement("div");
662 //groupRow.className = "logGroup";
663 var groupRowBox = consoleBody.ownerDocument.createElement("div");
664 groupRowBox.className = "logGroupBox";
665 //groupRow.appendChild(groupRowBox);
666 appendRow(groupRowBox);
667 groupStack.push(groupRowBox);
668 }
669
670 function popGroup(){
671 groupStack.pop();
672 }
673
674 // ***************************************************************************
675
676 function logFormatted(objects, className){
677 var html = [];
678
679 var format = objects[0];
680 var objIndex = 0;
681
682 if(typeof(format) != "string"){
683 format = "";
684 objIndex = -1;
685 }
686
687 var parts = parseFormat(format);
688
689 for(var i = 0; i < parts.length; ++i){
690 var part = parts[i];
691 if(part && typeof part == "object"){
692 part.appender(objects[++objIndex], html);
693 }else{
694 appendText(part, html);
695 }
696 }
697
698
699 var ids = [];
700 var obs = [];
701 for(i = objIndex+1; i < objects.length; ++i){
702 appendText(" ", html);
703
704 var object = objects[i];
705 if(object === undefined || object === null ){
706 appendNull(object, html);
707
708 }else if(typeof(object) == "string"){
709 appendText(object, html);
710
711 }else if(object instanceof Date){
712 appendText(object.toString(), html);
713
714 }else if(object.nodeType == 9){
715 appendText("[ XmlDoc ]", html);
716
717 }else{
718 // Create link for object inspector
719 // need to create an ID for this link, since it is currently text
720 var id = "_a" + __consoleAnchorId__++;
721 ids.push(id);
722 // need to save the object, so the arrays line up
723 obs.push(object);
724 var str = '<a id="'+id+'" href="javascript:void(0);">'+getObjectAbbr(object)+'</a>';
725
726 appendLink( str , html);
727 }
728 }
729
730 logRow(html, className);
731
732 // Now that the row is inserted in the DOM, loop through all of the links that were just created
733 for(i=0; i<ids.length; i++){
734 var btn = _firebugDoc.getElementById(ids[i]);
735 if(!btn){ continue; }
736
737 // store the object in the dom btn for reference later
738 // avoid parsing these objects unless necessary
739 btn.obj = obs[i];
740
741 _firebugWin.console._connects.push(dojo.connect(btn, "onclick", function(){
742
743 console.openObjectInspector();
744
745 try{
746 printObject(this.obj);
747 }catch(e){
748 this.obj = e;
749 }
750 consoleObjectInspector.innerHTML = "<pre>" + printObject( this.obj ) + "</pre>";
751 }));
752 }
753 }
754
755 function parseFormat(format){
756 var parts = [];
757
758 var reg = /((^%|[^\\]%)(\d+)?(\.)([a-zA-Z]))|((^%|[^\\]%)([a-zA-Z]))/;
759 var appenderMap = {s: appendText, d: appendInteger, i: appendInteger, f: appendFloat};
760
761 for(var m = reg.exec(format); m; m = reg.exec(format)){
762 var type = m[8] ? m[8] : m[5];
763 var appender = type in appenderMap ? appenderMap[type] : appendObject;
764 var precision = m[3] ? parseInt(m[3]) : (m[4] == "." ? -1 : 0);
765
766 parts.push(format.substr(0, m[0][0] == "%" ? m.index : m.index+1));
767 parts.push({appender: appender, precision: precision});
768
769 format = format.substr(m.index+m[0].length);
770 }
771
772 parts.push(format);
773
774 return parts;
775 }
776
777 function escapeHTML(value){
778 function replaceChars(ch){
779 switch(ch){
780 case "<":
781 return "&lt;";
782 case ">":
783 return "&gt;";
784 case "&":
785 return "&amp;";
786 case "'":
787 return "&#39;";
788 case '"':
789 return "&quot;";
790 }
791 return "?";
792 }
793 return String(value).replace(/[<>&"']/g, replaceChars);
794 }
795
796 function objectToString(object){
797 try{
798 return object+"";
799 }catch(e){
800 return null;
801 }
802 }
803
804 // ***************************************************************************
805 function appendLink(object, html){
806 // needed for object links - no HTML escaping
807 html.push( objectToString(object) );
808 }
809
810 function appendText(object, html){
811 html.push(escapeHTML(objectToString(object)));
812 }
813
814 function appendNull(object, html){
815 html.push('<span class="objectBox-null">', escapeHTML(objectToString(object)), '</span>');
816 }
817
818 function appendString(object, html){
819 html.push('<span class="objectBox-string">&quot;', escapeHTML(objectToString(object)),
820 '&quot;</span>');
821 }
822
823 function appendInteger(object, html){
824 html.push('<span class="objectBox-number">', escapeHTML(objectToString(object)), '</span>');
825 }
826
827 function appendFloat(object, html){
828 html.push('<span class="objectBox-number">', escapeHTML(objectToString(object)), '</span>');
829 }
830
831 function appendFunction(object, html){
832 html.push('<span class="objectBox-function">', getObjectAbbr(object), '</span>');
833 }
834
835 function appendObject(object, html){
836 try{
837 if(object === undefined){
838 appendNull("undefined", html);
839 }else if(object === null){
840 appendNull("null", html);
841 }else if(typeof object == "string"){
842 appendString(object, html);
843 }else if(typeof object == "number"){
844 appendInteger(object, html);
845 }else if(typeof object == "function"){
846 appendFunction(object, html);
847 }else if(object.nodeType == 1){
848 appendSelector(object, html);
849 }else if(typeof object == "object"){
850 appendObjectFormatted(object, html);
851 }else{
852 appendText(object, html);
853 }
854 }catch(e){
855 /* squelch */
856 }
857 }
858
859 function appendObjectFormatted(object, html){
860 var text = objectToString(object);
861 var reObject = /\[object (.*?)\]/;
862
863 var m = reObject.exec(text);
864 html.push('<span class="objectBox-object">', m ? m[1] : text, '</span>');
865 }
866
867 function appendSelector(object, html){
868 html.push('<span class="objectBox-selector">');
869
870 html.push('<span class="selectorTag">', escapeHTML(object.nodeName.toLowerCase()), '</span>');
871 if(object.id){
872 html.push('<span class="selectorId">#', escapeHTML(object.id), '</span>');
873 }
874 if(object.className){
875 html.push('<span class="selectorClass">.', escapeHTML(object.className), '</span>');
876 }
877
878 html.push('</span>');
879 }
880
881 function appendNode(node, html){
882 if(node.nodeType == 1){
883 html.push(
884 '<div class="objectBox-element">',
885 '&lt;<span class="nodeTag">', node.nodeName.toLowerCase(), '</span>');
886
887 for(var i = 0; i < node.attributes.length; ++i){
888 var attr = node.attributes[i];
889 if(!attr.specified){ continue; }
890
891 html.push('&nbsp;<span class="nodeName">', attr.nodeName.toLowerCase(),
892 '</span>=&quot;<span class="nodeValue">', escapeHTML(attr.nodeValue),
893 '</span>&quot;');
894 }
895
896 if(node.firstChild){
897 html.push('&gt;</div><div class="nodeChildren">');
898
899 for(var child = node.firstChild; child; child = child.nextSibling){
900 appendNode(child, html);
901 }
902
903 html.push('</div><div class="objectBox-element">&lt;/<span class="nodeTag">',
904 node.nodeName.toLowerCase(), '&gt;</span></div>');
905 }else{
906 html.push('/&gt;</div>');
907 }
908 }else if (node.nodeType == 3){
909 html.push('<div class="nodeText">', escapeHTML(node.nodeValue),
910 '</div>');
911 }
912 }
913
914 // ***************************************************************************
915
916 function addEvent(object, name, handler){
917 if(document.all){
918 object.attachEvent("on"+name, handler);
919 }else{
920 object.addEventListener(name, handler, false);
921 }
922 }
923
924 function removeEvent(object, name, handler){
925 if(document.all){
926 object.detachEvent("on"+name, handler);
927 }else{
928 object.removeEventListener(name, handler, false);
929 }
930 }
931
932 function cancelEvent(event){
933 if(document.all){
934 event.cancelBubble = true;
935 }else{
936 event.stopPropagation();
937 }
938 }
939
940 function onError(msg, href, lineNo){
941 var lastSlash = href.lastIndexOf("/");
942 var fileName = lastSlash == -1 ? href : href.substr(lastSlash+1);
943
944 var html = [
945 '<span class="errorMessage">', msg, '</span>',
946 '<div class="objectBox-sourceLink">', fileName, ' (line ', lineNo, ')</div>'
947 ];
948
949 logRow(html, "error");
950 }
951
952
953 //After converting to div instead of iframe, now getting two keydowns right away in IE 6.
954 //Make sure there is a little bit of delay.
955 var onKeyDownTime = new Date().getTime();
956
957 function onKeyDown(event){
958 var timestamp = (new Date()).getTime();
959 if(timestamp > onKeyDownTime + 200){
960 event = dojo.fixEvent(event);
961 var keys = dojo.keys;
962 var ekc = event.keyCode;
963 onKeyDownTime = timestamp;
964 if(ekc == keys.F12){
965 toggleConsole();
966 }else if(
967 (ekc == keys.NUMPAD_ENTER || ekc == 76) &&
968 event.shiftKey &&
969 (event.metaKey || event.ctrlKey)
970 ){
971 focusCommandLine();
972 }else{
973 return;
974 }
975 cancelEvent(event);
976 }
977 }
978
979 function onCommandLineKeyDown(e){
980 var dk = dojo.keys;
981 if(e.keyCode == 13 && commandLine.value){
982 addToHistory(commandLine.value);
983 evalCommandLine();
984 }else if(e.keyCode == 27){
985 commandLine.value = "";
986 }else if(e.keyCode == dk.UP_ARROW || e.charCode == dk.UP_ARROW){
987 navigateHistory("older");
988 }else if(e.keyCode == dk.DOWN_ARROW || e.charCode == dk.DOWN_ARROW){
989 navigateHistory("newer");
990 }else if(e.keyCode == dk.HOME || e.charCode == dk.HOME){
991 historyPosition = 1;
992 navigateHistory("older");
993 }else if(e.keyCode == dk.END || e.charCode == dk.END){
994 historyPosition = 999999;
995 navigateHistory("newer");
996 }
997 }
998
999 var historyPosition = -1;
1000 var historyCommandLine = null;
1001
1002 function addToHistory(value){
1003 var history = cookie("firebug_history");
1004 history = (history) ? dojo.fromJson(history) : [];
1005 var pos = dojo.indexOf(history, value);
1006 if (pos != -1){
1007 history.splice(pos, 1);
1008 }
1009 history.push(value);
1010 cookie("firebug_history", dojo.toJson(history), 30);
1011 while(history.length && !cookie("firebug_history")){
1012 history.shift();
1013 cookie("firebug_history", dojo.toJson(history), 30);
1014 }
1015 historyCommandLine = null;
1016 historyPosition = -1;
1017 }
1018
1019 function navigateHistory(direction){
1020 var history = cookie("firebug_history");
1021 history = (history) ? dojo.fromJson(history) : [];
1022 if(!history.length){
1023 return;
1024 }
1025
1026 if(historyCommandLine === null){
1027 historyCommandLine = commandLine.value;
1028 }
1029
1030 if(historyPosition == -1){
1031 historyPosition = history.length;
1032 }
1033
1034 if(direction == "older"){
1035 --historyPosition;
1036 if(historyPosition < 0){
1037 historyPosition = 0;
1038 }
1039 }else if(direction == "newer"){
1040 ++historyPosition;
1041 if(historyPosition > history.length){
1042 historyPosition = history.length;
1043 }
1044 }
1045
1046 if(historyPosition == history.length){
1047 commandLine.value = historyCommandLine;
1048 historyCommandLine = null;
1049 }else{
1050 commandLine.value = history[historyPosition];
1051 }
1052 }
1053
1054 function cookie(name, value){
1055 var c = document.cookie;
1056 if(arguments.length == 1){
1057 var matches = c.match(new RegExp("(?:^|; )" + name + "=([^;]*)"));
1058 return matches ? decodeURIComponent(matches[1]) : undefined; // String or undefined
1059 }else{
1060 var d = new Date();
1061 d.setMonth(d.getMonth()+1);
1062 document.cookie = name + "=" + encodeURIComponent(value) + ((d.toUtcString) ? "; expires=" + d.toUTCString() : "");
1063 }
1064 };
1065
1066 function isArray(it){
1067 return it && it instanceof Array || typeof it == "array";
1068 }
1069
1070 //***************************************************************************************************
1071 // Print Object Helpers
1072 function objectLength(o){
1073 var cnt = 0;
1074 for(var nm in o){
1075 cnt++
1076 }
1077 return cnt;
1078 }
1079
1080 function printObject(o, i, txt, used){
1081 // Recursively trace object, indenting to represent depth for display in object inspector
1082 var ind = " \t";
1083 txt = txt || "";
1084 i = i || ind;
1085 used = used || [];
1086 var opnCls;
1087
1088 if(o && o.nodeType == 1){
1089 var html = [];
1090 appendNode(o, html);
1091 return html.join("");
1092 }
1093
1094 var br=",\n", cnt = 0, length = objectLength(o);
1095
1096 if(o instanceof Date){
1097 return i + o.toString() + br;
1098 }
1099 looking:
1100 for(var nm in o){
1101 cnt++;
1102 if(cnt==length){br = "\n";}
1103 if(o[nm] === window || o[nm] === document){
1104 continue;
1105 }else if(o[nm] === null){
1106 txt += i+nm + " : NULL" + br;
1107 }else if(o[nm] && o[nm].nodeType){
1108 if(o[nm].nodeType == 1){
1109 //txt += i+nm + " : < "+o[nm].tagName+" id=\""+ o[nm].id+"\" />" + br;
1110 }else if(o[nm].nodeType == 3){
1111 txt += i+nm + " : [ TextNode "+o[nm].data + " ]" + br;
1112 }
1113
1114 }else if(typeof o[nm] == "object" && (o[nm] instanceof String || o[nm] instanceof Number || o[nm] instanceof Boolean)){
1115 txt += i+nm + " : " + o[nm] + "," + br;
1116
1117 }else if(o[nm] instanceof Date){
1118 txt += i+nm + " : " + o[nm].toString() + br;
1119
1120 }else if(typeof(o[nm]) == "object" && o[nm]){
1121 for(var j = 0, seen; seen = used[j]; j++){
1122 if(o[nm] === seen){
1123 txt += i+nm + " : RECURSION" + br;
1124 continue looking;
1125 }
1126 }
1127 used.push(o[nm]);
1128
1129 opnCls = (isArray(o[nm]))?["[","]"]:["{","}"];
1130 txt += i+nm +" : " + opnCls[0] + "\n";//non-standard break, (no comma)
1131 txt += printObject(o[nm], i+ind, "", used);
1132 txt += i + opnCls[1] + br;
1133
1134 }else if(typeof o[nm] == "undefined"){
1135 txt += i+nm + " : undefined" + br;
1136 }else if(nm == "toString" && typeof o[nm] == "function"){
1137 var toString = o[nm]();
1138 if(typeof toString == "string" && toString.match(/function ?(.*?)\(/)){
1139 toString = escapeHTML(getObjectAbbr(o[nm]));
1140 }
1141 txt += i+nm +" : " + toString + br;
1142 }else{
1143 txt += i+nm +" : "+ escapeHTML(getObjectAbbr(o[nm])) + br;
1144 }
1145 }
1146 return txt;
1147 }
1148
1149 function getObjectAbbr(obj){
1150 // Gets an abbreviation of an object for display in log
1151 // X items in object, including id
1152 // X items in an array
1153 // TODO: Firebug Sr. actually goes by char count
1154 var isError = (obj instanceof Error);
1155 if(obj.nodeType == 1){
1156 return escapeHTML('< '+obj.tagName.toLowerCase()+' id=\"'+ obj.id+ '\" />');
1157 }
1158 if(obj.nodeType == 3){
1159 return escapeHTML('[TextNode: "'+obj.nodeValue+'"]');
1160 }
1161 var nm = (obj && (obj.id || obj.name || obj.ObjectID || obj.widgetId));
1162 if(!isError && nm){ return "{"+nm+"}"; }
1163
1164 var obCnt = 2;
1165 var arCnt = 4;
1166 var cnt = 0;
1167
1168 if(isError){
1169 nm = "[ Error: "+(obj.message || obj.description || obj)+" ]";
1170 }else if(isArray(obj)){
1171 nm = "[" + obj.slice(0,arCnt).join(",");
1172 if(obj.length > arCnt){
1173 nm += " ... ("+obj.length+" items)";
1174 }
1175 nm += "]";
1176 }else if(typeof obj == "function"){
1177 nm = obj + "";
1178 var reg = /function\s*([^\(]*)(\([^\)]*\))[^\{]*\{/;
1179 var m = reg.exec(nm);
1180 if(m){
1181 if(!m[1]){
1182 m[1] = "function";
1183 }
1184 nm = m[1] + m[2];
1185 }else{
1186 nm = "function()";
1187 }
1188 }else if(typeof obj != "object" || typeof obj == "string"){
1189 nm = obj + "";
1190 }else{
1191 nm = "{";
1192 for(var i in obj){
1193 cnt++;
1194 if(cnt > obCnt){ break; }
1195 nm += i+":"+escapeHTML(obj[i])+" ";
1196 }
1197 nm+="}";
1198 }
1199
1200 return nm;
1201 }
1202
1203 //*************************************************************************************
1204
1205 //window.onerror = onError;
1206
1207 addEvent(document, dojo.isIE || dojo.isSafari ? "keydown" : "keypress", onKeyDown);
1208
1209 if( (document.documentElement.getAttribute("debug") == "true")||
1210 (dojo.config.isDebug)
1211 ){
1212 toggleConsole(true);
1213 }
1214
1215 dojo.addOnWindowUnload(function(){
1216 // Erase the globals and event handlers I created, to prevent spurious leak warnings
1217 removeEvent(document, dojo.isIE || dojo.isSafari ? "keydown" : "keypress", onKeyDown);
1218 window.onFirebugResize = null;
1219 window.console = null;
1220 });
2f01fe57 1221}
a089699c 1222
2f01fe57 1223})();
a089699c
AD
1224
1225
2f01fe57 1226}