hjg
2024-07-09 30304784e82d4bba24121328da8eb8490aec4f4f
提交 | 用户 | 时间
58d006 1
A 2 if (!("console" in window) || !("firebug" in console)) {
3 (function()
4 {
5     window.console = 
6     {
7         log: function()
8         {
9             logFormatted(arguments, "");
10         },
11         
12         debug: function()
13         {
14             logFormatted(arguments, "debug");
15         },
16         
17         info: function()
18         {
19             logFormatted(arguments, "info");
20         },
21         
22         warn: function()
23         {
24             logFormatted(arguments, "warning");
25         },
26         
27         error: function()
28         {
29             logFormatted(arguments, "error");
30         },
31         
32         assert: function(truth, message)
33         {
34             if (!truth)
35             {
36                 var args = [];
37                 for (var i = 1; i < arguments.length; ++i)
38                     args.push(arguments[i]);
39                 
40                 logFormatted(args.length ? args : ["Assertion Failure"], "error");
41                 throw message ? message : "Assertion Failure";
42             }
43         },
44         
45         dir: function(object)
46         {
47             var html = [];
48                         
49             var pairs = [];
50             for (var name in object)
51             {
52                 try
53                 {
54                     pairs.push([name, object[name]]);
55                 }
56                 catch (exc)
57                 {
58                 }
59             }
60             
61             pairs.sort(function(a, b) { return a[0] < b[0] ? -1 : 1; });
62             
63             html.push('<table>');
64             for (var i = 0; i < pairs.length; ++i)
65             {
66                 var name = pairs[i][0], value = pairs[i][1];
67                 
68                 html.push('<tr>', 
69                 '<td class="propertyNameCell"><span class="propertyName">',
70                     escapeHTML(name), '</span></td>', '<td><span class="propertyValue">');
71                 appendObject(value, html);
72                 html.push('</span></td></tr>');
73             }
74             html.push('</table>');
75             
76             logRow(html, "dir");
77         },
78         
79         dirxml: function(node)
80         {
81             var html = [];
82             
83             appendNode(node, html);
84             logRow(html, "dirxml");
85         },
86         
87         group: function()
88         {
89             logRow(arguments, "group", pushGroup);
90         },
91         
92         groupEnd: function()
93         {
94             logRow(arguments, "", popGroup);
95         },
96         
97         time: function(name)
98         {
99             timeMap[name] = (new Date()).getTime();
100         },
101         
102         timeEnd: function(name)
103         {
104             if (name in timeMap)
105             {
106                 var delta = (new Date()).getTime() - timeMap[name];
107                 logFormatted([name+ ":", delta+"ms"]);
108                 delete timeMap[name];
109             }
110         },
111         
112         count: function()
113         {
114             this.warn(["count() not supported."]);
115         },
116         
117         trace: function()
118         {
119             this.warn(["trace() not supported."]);
120         },
121         
122         profile: function()
123         {
124             this.warn(["profile() not supported."]);
125         },
126         
127         profileEnd: function()
128         {
129         },
130         
131         clear: function()
132         {
133             consoleBody.innerHTML = "";
134         },
135
136         open: function()
137         {
138             toggleConsole(true);
139         },
140         
141         close: function()
142         {
143             if (frameVisible)
144                 toggleConsole();
145         }
146     };
147  
148     // ********************************************************************************************
149        
150     var consoleFrame = null;
151     var consoleBody = null;
152     var commandLine = null;
153     
154     var frameVisible = false;
155     var messageQueue = [];
156     var groupStack = [];
157     var timeMap = {};
158     
159     var clPrefix = ">>> ";
160     
161     var isFirefox = navigator.userAgent.indexOf("Firefox") != -1;
162     var isIE = navigator.userAgent.indexOf("MSIE") != -1;
163     var isOpera = navigator.userAgent.indexOf("Opera") != -1;
164     var isSafari = navigator.userAgent.indexOf("AppleWebKit") != -1;
165
166     // ********************************************************************************************
167
168     function toggleConsole(forceOpen)
169     {
170         frameVisible = forceOpen || !frameVisible;
171         if (consoleFrame)
172             consoleFrame.style.visibility = frameVisible ? "visible" : "hidden";
173         else
174             waitForBody();
175     }
176
177     function focusCommandLine()
178     {
179         toggleConsole(true);
180         if (commandLine)
181             commandLine.focus();
182     }
183
184     function waitForBody()
185     {
186         if (document.body)
187             createFrame();
188         else
189             setTimeout(waitForBody, 200);
190     }    
191
192     function createFrame()
193     {
194         if (consoleFrame)
195             return;
196         
197         window.onFirebugReady = function(doc)
198         {
199             window.onFirebugReady = null;
200
201             var toolbar = doc.getElementById("toolbar");
202             toolbar.onmousedown = onSplitterMouseDown;
203
204             commandLine = doc.getElementById("commandLine");
205             addEvent(commandLine, "keydown", onCommandLineKeyDown);
206
207             addEvent(doc, isIE || isSafari ? "keydown" : "keypress", onKeyDown);
208             
209             consoleBody = doc.getElementById("log");
210             layout();
211             flush();
212         }
213
214         var baseURL = getFirebugURL();
215
216         consoleFrame = document.createElement("iframe");
217         consoleFrame.setAttribute("src", baseURL+"/firebug.html");
218         consoleFrame.setAttribute("frameBorder", "0");
219         consoleFrame.style.visibility = (frameVisible ? "visible" : "hidden");    
220         consoleFrame.style.zIndex = "2147483647";
221         consoleFrame.style.position = "fixed";
222         consoleFrame.style.width = "100%";
223         consoleFrame.style.left = "0";
224         consoleFrame.style.bottom = "0";
225         consoleFrame.style.height = "200px";
226         document.body.appendChild(consoleFrame);
227     }
228     
229     function getFirebugURL()
230     {
231         var scripts = document.getElementsByTagName("script");
232         for (var i = 0; i < scripts.length; ++i)
233         {
234             if (scripts[i].src.indexOf("firebug.js") != -1)
235             {
236                 var lastSlash = scripts[i].src.lastIndexOf("/");
237                 return scripts[i].src.substr(0, lastSlash);
238             }
239         }
240     }
241     
242     function evalCommandLine()
243     {
244         var text = commandLine.value;
245         commandLine.value = "";
246
247         logRow([clPrefix, text], "command");
248         
249         var value;
250         try
251         {
252             value = eval(text);
253         }
254         catch (exc)
255         {
256         }
257
258         console.log(value);
259     }
260     
261     function layout()
262     {
263         var toolbar = consoleBody.ownerDocument.getElementById("toolbar");
264         var height = consoleFrame.offsetHeight - (toolbar.offsetHeight + commandLine.offsetHeight);
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 y = height - clientY;
641         
642         consoleFrame.style.height = y + "px";
643         layout();
644     }
645     
646     function onSplitterMouseUp(event)
647     {
648         removeEvent(document, "mousemove", onSplitterMouseMove);
649         removeEvent(document, "mouseup", onSplitterMouseUp);
650
651         for (var i = 0; i < frames.length; ++i)
652         {
653             removeEvent(frames[i].document, "mousemove", onSplitterMouseMove);
654             removeEvent(frames[i].document, "mouseup", onSplitterMouseUp);
655         }
656     }
657     
658     function onCommandLineKeyDown(event)
659     {
660         if (event.keyCode == 13)
661             evalCommandLine();
662         else if (event.keyCode == 27)
663             commandLine.value = "";
664     }
665     
666     window.onerror = onError;
667     addEvent(document, isIE || isSafari ? "keydown" : "keypress", onKeyDown);
668     
669     if (document.documentElement.getAttribute("debug") == "true")
670         toggleConsole(true);
671 })();
672 }