]> dev.renevier.net Git - syp.git/blob - openlayers/lib/Firebug/firebug.js
initial commit
[syp.git] / openlayers / lib / Firebug / firebug.js
1
2 if (!window.console || !console.firebug) { (function()
3 {
4     window.console = 
5     {
6         log: function()
7         {
8             logFormatted(arguments, "");
9         },
10         
11         debug: function()
12         {
13             logFormatted(arguments, "debug");
14         },
15         
16         info: function()
17         {
18             logFormatted(arguments, "info");
19         },
20         
21         warn: function()
22         {
23             logFormatted(arguments, "warning");
24         },
25         
26         error: function()
27         {
28             logFormatted(arguments, "error");
29         },
30         
31         assert: function(truth, message)
32         {
33             if (!truth)
34             {
35                 var args = [];
36                 for (var i = 1; i < arguments.length; ++i)
37                     args.push(arguments[i]);
38                 
39                 logFormatted(args.length ? args : ["Assertion Failure"], "error");
40                 throw message ? message : "Assertion Failure";
41             }
42         },
43         
44         dir: function(object)
45         {
46             var html = [];
47                         
48             var pairs = [];
49             for (var name in object)
50             {
51                 try
52                 {
53                     pairs.push([name, object[name]]);
54                 }
55                 catch (exc)
56                 {
57                 }
58             }
59             
60             pairs.sort(function(a, b) { return a[0] < b[0] ? -1 : 1; });
61             
62             html.push('<table>');
63             for (var i = 0; i < pairs.length; ++i)
64             {
65                 var name = pairs[i][0], value = pairs[i][1];
66                 
67                 html.push('<tr>', 
68                 '<td class="propertyNameCell"><span class="propertyName">',
69                     escapeHTML(name), '</span></td>', '<td><span class="propertyValue">');
70                 appendObject(value, html);
71                 html.push('</span></td></tr>');
72             }
73             html.push('</table>');
74             
75             logRow(html, "dir");
76         },
77         
78         dirxml: function(node)
79         {
80             var html = [];
81             
82             appendNode(node, html);
83             logRow(html, "dirxml");
84         },
85         
86         group: function()
87         {
88             logRow(arguments, "group", pushGroup);
89         },
90         
91         groupEnd: function()
92         {
93             logRow(arguments, "", popGroup);
94         },
95         
96         time: function(name)
97         {
98             timeMap[name] = (new Date()).getTime();
99         },
100         
101         timeEnd: function(name)
102         {
103             if (name in timeMap)
104             {
105                 var delta = (new Date()).getTime() - timeMap[name];
106                 logFormatted([name+ ":", delta+"ms"]);
107                 delete timeMap[name];
108             }
109         },
110         
111         count: function()
112         {
113             this.warn(["count() not supported."]);
114         },
115         
116         trace: function()
117         {
118             this.warn(["trace() not supported."]);
119         },
120         
121         profile: function()
122         {
123             this.warn(["profile() not supported."]);
124         },
125         
126         profileEnd: function()
127         {
128         },
129         
130         clear: function()
131         {
132             consoleBody.innerHTML = "";
133         },
134
135         open: function()
136         {
137             toggleConsole(true);
138         },
139         
140         close: function()
141         {
142             if (frameVisible)
143                 toggleConsole();
144         }
145     };
146  
147     // ********************************************************************************************
148        
149     var consoleFrame = null;
150     var consoleBody = null;
151     var commandLine = null;
152     
153     var frameVisible = false;
154     var messageQueue = [];
155     var groupStack = [];
156     var timeMap = {};
157     
158     var clPrefix = ">>> ";
159     
160     var isFirefox = navigator.userAgent.indexOf("Firefox") != -1;
161     var isIE = navigator.userAgent.indexOf("MSIE") != -1;
162     var isOpera = navigator.userAgent.indexOf("Opera") != -1;
163     var isSafari = navigator.userAgent.indexOf("AppleWebKit") != -1;
164
165     // ********************************************************************************************
166
167     function toggleConsole(forceOpen)
168     {
169         frameVisible = forceOpen || !frameVisible;
170         if (consoleFrame)
171             consoleFrame.style.visibility = frameVisible ? "visible" : "hidden";
172         else
173             waitForBody();
174     }
175
176     function focusCommandLine()
177     {
178         toggleConsole(true);
179         if (commandLine)
180             commandLine.focus();
181     }
182
183     function waitForBody()
184     {
185         if (document.body)
186             createFrame();
187         else
188             setTimeout(waitForBody, 200);
189     }    
190
191     function createFrame()
192     {
193         if (consoleFrame)
194             return;
195         
196         window.onFirebugReady = function(doc)
197         {
198             window.onFirebugReady = null;
199
200             var toolbar = doc.getElementById("toolbar");
201             toolbar.onmousedown = onSplitterMouseDown;
202
203             commandLine = doc.getElementById("commandLine");
204             addEvent(commandLine, "keydown", onCommandLineKeyDown);
205
206             addEvent(doc, isIE || isSafari ? "keydown" : "keypress", onKeyDown);
207             
208             consoleBody = doc.getElementById("log");
209             layout();
210             flush();
211         }
212
213         var baseURL = getFirebugURL();
214
215         consoleFrame = document.createElement("iframe");
216         consoleFrame.setAttribute("src", baseURL+"/firebug.html");
217         consoleFrame.setAttribute("frameBorder", "0");
218         consoleFrame.style.visibility = (frameVisible ? "visible" : "hidden");    
219         consoleFrame.style.zIndex = "2147483583";
220         consoleFrame.style.position = document.all ? "absolute" : "fixed";
221         consoleFrame.style.width = "100%";
222         consoleFrame.style.left = "0";
223         consoleFrame.style.bottom = "0";
224         consoleFrame.style.height = "200px";
225         document.body.appendChild(consoleFrame);
226     }
227     
228     function getFirebugURL()
229     {
230         var scripts = document.getElementsByTagName("script");
231         for (var i = 0; i < scripts.length; ++i)
232         {
233             if (scripts[i].src.indexOf("firebug.js") != -1)
234             {
235                 var lastSlash = scripts[i].src.lastIndexOf("/");
236                 return scripts[i].src.substr(0, lastSlash);
237             }
238         }
239     }
240     
241     function evalCommandLine()
242     {
243         var text = commandLine.value;
244         commandLine.value = "";
245
246         logRow([clPrefix, text], "command");
247         
248         var value;
249         try
250         {
251             value = eval(text);
252         }
253         catch (exc)
254         {
255         }
256
257         console.log(value);
258     }
259     
260     function layout()
261     {
262         var toolbar = consoleBody.ownerDocument.getElementById("toolbar");
263         var height = consoleFrame.offsetHeight - (toolbar.offsetHeight + commandLine.offsetHeight);
264         height = Math.max(height, 0);
265         consoleBody.style.top = toolbar.offsetHeight + "px";
266         consoleBody.style.height = height + "px";
267         
268         commandLine.style.top = (consoleFrame.offsetHeight - commandLine.offsetHeight) + "px";
269     }
270     
271     function logRow(message, className, handler)
272     {
273         if (consoleBody)
274             writeMessage(message, className, handler);
275         else
276         {
277             messageQueue.push([message, className, handler]);
278             waitForBody();
279         }
280     }
281     
282     function flush()
283     {
284         var queue = messageQueue;
285         messageQueue = [];
286         
287         for (var i = 0; i < queue.length; ++i)
288             writeMessage(queue[i][0], queue[i][1], queue[i][2]);
289     }
290
291     function writeMessage(message, className, handler)
292     {
293         var isScrolledToBottom =
294             consoleBody.scrollTop + consoleBody.offsetHeight >= consoleBody.scrollHeight;
295
296         if (!handler)
297             handler = writeRow;
298         
299         handler(message, className);
300         
301         if (isScrolledToBottom)
302             consoleBody.scrollTop = consoleBody.scrollHeight - consoleBody.offsetHeight;
303     }
304     
305     function appendRow(row)
306     {
307         var container = groupStack.length ? groupStack[groupStack.length-1] : consoleBody;
308         container.appendChild(row);
309     }
310
311     function writeRow(message, className)
312     {
313         var row = consoleBody.ownerDocument.createElement("div");
314         row.className = "logRow" + (className ? " logRow-"+className : "");
315         row.innerHTML = message.join("");
316         appendRow(row);
317     }
318
319     function pushGroup(message, className)
320     {
321         logFormatted(message, className);
322
323         var groupRow = consoleBody.ownerDocument.createElement("div");
324         groupRow.className = "logGroup";
325         var groupRowBox = consoleBody.ownerDocument.createElement("div");
326         groupRowBox.className = "logGroupBox";
327         groupRow.appendChild(groupRowBox);
328         appendRow(groupRowBox);
329         groupStack.push(groupRowBox);
330     }
331
332     function popGroup()
333     {
334         groupStack.pop();
335     }
336     
337     // ********************************************************************************************
338
339     function logFormatted(objects, className)
340     {
341         var html = [];
342
343         var format = objects[0];
344         var objIndex = 0;
345
346         if (typeof(format) != "string")
347         {
348             format = "";
349             objIndex = -1;
350         }
351
352         var parts = parseFormat(format);
353         for (var i = 0; i < parts.length; ++i)
354         {
355             var part = parts[i];
356             if (part && typeof(part) == "object")
357             {
358                 var object = objects[++objIndex];
359                 part.appender(object, html);
360             }
361             else
362                 appendText(part, html);
363         }
364
365         for (var i = objIndex+1; i < objects.length; ++i)
366         {
367             appendText(" ", html);
368             
369             var object = objects[i];
370             if (typeof(object) == "string")
371                 appendText(object, html);
372             else
373                 appendObject(object, html);
374         }
375         
376         logRow(html, className);
377     }
378
379     function parseFormat(format)
380     {
381         var parts = [];
382
383         var reg = /((^%|[^\\]%)(\d+)?(\.)([a-zA-Z]))|((^%|[^\\]%)([a-zA-Z]))/;    
384         var appenderMap = {s: appendText, d: appendInteger, i: appendInteger, f: appendFloat};
385
386         for (var m = reg.exec(format); m; m = reg.exec(format))
387         {
388             var type = m[8] ? m[8] : m[5];
389             var appender = type in appenderMap ? appenderMap[type] : appendObject;
390             var precision = m[3] ? parseInt(m[3]) : (m[4] == "." ? -1 : 0);
391
392             parts.push(format.substr(0, m[0][0] == "%" ? m.index : m.index+1));
393             parts.push({appender: appender, precision: precision});
394
395             format = format.substr(m.index+m[0].length);
396         }
397
398         parts.push(format);
399
400         return parts;
401     }
402
403     function escapeHTML(value)
404     {
405         function replaceChars(ch)
406         {
407             switch (ch)
408             {
409                 case "<":
410                     return "&lt;";
411                 case ">":
412                     return "&gt;";
413                 case "&":
414                     return "&amp;";
415                 case "'":
416                     return "&#39;";
417                 case '"':
418                     return "&quot;";
419             }
420             return "?";
421         };
422         return String(value).replace(/[<>&"']/g, replaceChars);
423     }
424
425     function objectToString(object)
426     {
427         try
428         {
429             return object+"";
430         }
431         catch (exc)
432         {
433             return null;
434         }
435     }
436
437     // ********************************************************************************************
438
439     function appendText(object, html)
440     {
441         html.push(escapeHTML(objectToString(object)));
442     }
443
444     function appendNull(object, html)
445     {
446         html.push('<span class="objectBox-null">', escapeHTML(objectToString(object)), '</span>');
447     }
448
449     function appendString(object, html)
450     {
451         html.push('<span class="objectBox-string">&quot;', escapeHTML(objectToString(object)),
452             '&quot;</span>');
453     }
454
455     function appendInteger(object, html)
456     {
457         html.push('<span class="objectBox-number">', escapeHTML(objectToString(object)), '</span>');
458     }
459
460     function appendFloat(object, html)
461     {
462         html.push('<span class="objectBox-number">', escapeHTML(objectToString(object)), '</span>');
463     }
464
465     function appendFunction(object, html)
466     {
467         var reName = /function ?(.*?)\(/;
468         var m = reName.exec(objectToString(object));
469         var name = m ? m[1] : "function";
470         html.push('<span class="objectBox-function">', escapeHTML(name), '()</span>');
471     }
472     
473     function appendObject(object, html)
474     {
475         try
476         {
477             if (object == undefined)
478                 appendNull("undefined", html);
479             else if (object == null)
480                 appendNull("null", html);
481             else if (typeof object == "string")
482                 appendString(object, html);
483             else if (typeof object == "number")
484                 appendInteger(object, html);
485             else if (typeof object == "function")
486                 appendFunction(object, html);
487             else if (object.nodeType == 1)
488                 appendSelector(object, html);
489             else if (typeof object == "object")
490                 appendObjectFormatted(object, html);
491             else
492                 appendText(object, html);
493         }
494         catch (exc)
495         {
496         }
497     }
498         
499     function appendObjectFormatted(object, html)
500     {
501         var text = objectToString(object);
502         var reObject = /\[object (.*?)\]/;
503
504         var m = reObject.exec(text);
505         html.push('<span class="objectBox-object">', m ? m[1] : text, '</span>')
506     }
507     
508     function appendSelector(object, html)
509     {
510         html.push('<span class="objectBox-selector">');
511
512         html.push('<span class="selectorTag">', escapeHTML(object.nodeName.toLowerCase()), '</span>');
513         if (object.id)
514             html.push('<span class="selectorId">#', escapeHTML(object.id), '</span>');
515         if (object.className)
516             html.push('<span class="selectorClass">.', escapeHTML(object.className), '</span>');
517
518         html.push('</span>');
519     }
520
521     function appendNode(node, html)
522     {
523         if (node.nodeType == 1)
524         {
525             html.push(
526                 '<div class="objectBox-element">',
527                     '&lt;<span class="nodeTag">', node.nodeName.toLowerCase(), '</span>');
528
529             for (var i = 0; i < node.attributes.length; ++i)
530             {
531                 var attr = node.attributes[i];
532                 if (!attr.specified)
533                     continue;
534                 
535                 html.push('&nbsp;<span class="nodeName">', attr.nodeName.toLowerCase(),
536                     '</span>=&quot;<span class="nodeValue">', escapeHTML(attr.nodeValue),
537                     '</span>&quot;')
538             }
539
540             if (node.firstChild)
541             {
542                 html.push('&gt;</div><div class="nodeChildren">');
543
544                 for (var child = node.firstChild; child; child = child.nextSibling)
545                     appendNode(child, html);
546                     
547                 html.push('</div><div class="objectBox-element">&lt;/<span class="nodeTag">', 
548                     node.nodeName.toLowerCase(), '&gt;</span></div>');
549             }
550             else
551                 html.push('/&gt;</div>');
552         }
553         else if (node.nodeType == 3)
554         {
555             html.push('<div class="nodeText">', escapeHTML(node.nodeValue),
556                 '</div>');
557         }
558     }
559
560     // ********************************************************************************************
561     
562     function addEvent(object, name, handler)
563     {
564         if (document.all)
565             object.attachEvent("on"+name, handler);
566         else
567             object.addEventListener(name, handler, false);
568     }
569     
570     function removeEvent(object, name, handler)
571     {
572         if (document.all)
573             object.detachEvent("on"+name, handler);
574         else
575             object.removeEventListener(name, handler, false);
576     }
577     
578     function cancelEvent(event)
579     {
580         if (document.all)
581             event.cancelBubble = true;
582         else
583             event.stopPropagation();        
584     }
585
586     function onError(msg, href, lineNo)
587     {
588         var html = [];
589         
590         var lastSlash = href.lastIndexOf("/");
591         var fileName = lastSlash == -1 ? href : href.substr(lastSlash+1);
592         
593         html.push(
594             '<span class="errorMessage">', msg, '</span>', 
595             '<div class="objectBox-sourceLink">', fileName, ' (line ', lineNo, ')</div>'
596         );
597         
598         logRow(html, "error");
599     };
600
601     function onKeyDown(event)
602     {
603         if (event.keyCode == 123)
604             toggleConsole();
605         else if ((event.keyCode == 108 || event.keyCode == 76) && event.shiftKey
606                  && (event.metaKey || event.ctrlKey))
607             focusCommandLine();
608         else
609             return;
610         
611         cancelEvent(event);
612     }
613
614     function onSplitterMouseDown(event)
615     {
616         if (isSafari || isOpera)
617             return;
618         
619         addEvent(document, "mousemove", onSplitterMouseMove);
620         addEvent(document, "mouseup", onSplitterMouseUp);
621
622         for (var i = 0; i < frames.length; ++i)
623         {
624             addEvent(frames[i].document, "mousemove", onSplitterMouseMove);
625             addEvent(frames[i].document, "mouseup", onSplitterMouseUp);
626         }
627     }
628     
629     function onSplitterMouseMove(event)
630     {
631         var win = document.all
632             ? event.srcElement.ownerDocument.parentWindow
633             : event.target.ownerDocument.defaultView;
634
635         var clientY = event.clientY;
636         if (win != win.parent)
637             clientY += win.frameElement ? win.frameElement.offsetTop : 0;
638         
639         var height = consoleFrame.offsetTop + consoleFrame.clientHeight;
640         var toolbar = consoleBody.ownerDocument.getElementById("toolbar");
641         var y = Math.max(height - clientY,
642                          toolbar.offsetHeight + commandLine.offsetHeight);
643         
644         consoleFrame.style.height = y + "px";
645         layout();
646     }
647     
648     function onSplitterMouseUp(event)
649     {
650         removeEvent(document, "mousemove", onSplitterMouseMove);
651         removeEvent(document, "mouseup", onSplitterMouseUp);
652
653         for (var i = 0; i < frames.length; ++i)
654         {
655             removeEvent(frames[i].document, "mousemove", onSplitterMouseMove);
656             removeEvent(frames[i].document, "mouseup", onSplitterMouseUp);
657         }
658     }
659     
660     function onCommandLineKeyDown(event)
661     {
662         if (event.keyCode == 13)
663             evalCommandLine();
664         else if (event.keyCode == 27)
665             commandLine.value = "";
666     }
667     
668     window.onerror = onError;
669     addEvent(document, isIE || isSafari ? "keydown" : "keypress", onKeyDown);
670     
671     if (document.documentElement.getAttribute("debug") == "true")
672         toggleConsole(true);
673 })();
674 }