3 MochiKit.LoggingPane 1.4
5 See <http://mochikit.com/> for documentation, downloads, license, etc.
7 (c) 2005 Bob Ippolito. All rights Reserved.
11 if (typeof(dojo
) != 'undefined') {
12 dojo
.provide('MochiKit.LoggingPane');
13 dojo
.require('MochiKit.Logging');
14 dojo
.require('MochiKit.Base');
17 if (typeof(JSAN
) != 'undefined') {
18 JSAN
.use("MochiKit.Logging", []);
19 JSAN
.use("MochiKit.Base", []);
23 if (typeof(MochiKit
.Base
) == 'undefined' || typeof(MochiKit
.Logging
) == 'undefined') {
27 throw "MochiKit.LoggingPane depends on MochiKit.Base and MochiKit.Logging!";
30 if (typeof(MochiKit
.LoggingPane
) == 'undefined') {
31 MochiKit
.LoggingPane
= {};
34 MochiKit
.LoggingPane
.NAME
= "MochiKit.LoggingPane";
35 MochiKit
.LoggingPane
.VERSION
= "1.4";
36 MochiKit
.LoggingPane
.__repr__ = function () {
37 return "[" + this.NAME
+ " " + this.VERSION
+ "]";
40 MochiKit
.LoggingPane
.toString = function () {
41 return this.__repr__();
44 /** @id MochiKit.LoggingPane.createLoggingPane */
45 MochiKit
.LoggingPane
.createLoggingPane = function (inline
/* = false */, windowHeight
) {
46 var m
= MochiKit
.LoggingPane
;
48 if (m
._loggingPane
&& m
._loggingPane
.inline
!= inline
) {
49 m
._loggingPane
.closePane();
50 m
._loggingPane
= null;
52 if (!m
._loggingPane
|| m
._loggingPane
.closed
) {
53 m
._loggingPane
= new m
.LoggingPane(inline
, MochiKit
.Logging
.logger
, windowHeight
);
55 return m
._loggingPane
;
58 /** @id MochiKit.LoggingPane.LoggingPane */
59 MochiKit
.LoggingPane
.LoggingPane = function (inline
/* = false */, logger
/* = MochiKit.Logging.logger */, windowHeight
) {
61 /* Use a div if inline, pop up a window if not */
62 /* Create the elements */
63 if (typeof(logger
) == "undefined" || logger
=== null) {
64 logger
= MochiKit
.Logging
.logger
;
67 var update
= MochiKit
.Base
.update
;
68 var updatetree
= MochiKit
.Base
.updatetree
;
69 var bind
= MochiKit
.Base
.bind
;
70 var clone
= MochiKit
.Base
.clone
;
72 var uid
= "_MochiKit_LoggingPane";
73 if (typeof(MochiKit
.DOM
) != "undefined") {
74 win
= MochiKit
.DOM
.currentWindow();
76 if(!windowHeight
) windowHeight
= 200;
78 // name the popup with the base URL for uniqueness
79 var url
= win
.location
.href
.split("?")[0].replace(/[#:\/.><&-]/g, "_");
80 var name
= uid
+ "_" + url
;
81 var nwin
= win
.open("", name
, "dependent,resizable,height=" + windowHeight
);
83 alert("Not able to open debugging window due to pop-up blocking.");
87 '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" '
88 + '"http://www.w3.org/TR/html4/loose.dtd">'
89 + '<html><head><title>[MochiKit.LoggingPane]</title></head>'
90 + '<body></body></html>'
92 nwin
.document
.close();
93 nwin
.document
.title
+= ' ' + win
.document
.title
;
96 var doc
= win
.document
;
99 // Connect to the debug pane if it already exists (i.e. in a window orphaned by the page being refreshed)
100 var debugPane
= doc
.getElementById(uid
);
101 var existing_pane
= !!debugPane
;
102 if (debugPane
&& typeof(debugPane
.loggingPane
) != "undefined") {
103 debugPane
.loggingPane
.logger
= this.logger
;
104 debugPane
.loggingPane
.buildAndApplyFilter();
105 return debugPane
.loggingPane
;
109 // clear any existing contents
111 while ((child
= debugPane
.firstChild
)) {
112 debugPane
.removeChild(child
);
115 debugPane
= doc
.createElement("div");
118 debugPane
.loggingPane
= this;
119 var levelFilterField
= doc
.createElement("input");
120 var infoFilterField
= doc
.createElement("input");
121 var filterButton
= doc
.createElement("button");
122 var loadButton
= doc
.createElement("button");
123 var clearButton
= doc
.createElement("button");
124 var closeButton
= doc
.createElement("button");
125 var logPaneArea
= doc
.createElement("div");
126 var logPane
= doc
.createElement("div");
128 /* Set up the functions */
129 var listenerId
= uid
+ "_Listener";
130 this.colorTable
= clone(this.colorTable
);
132 var messageFilter
= null;
134 /** @id MochiKit.LoggingPane.messageLevel */
135 var messageLevel = function (msg
) {
136 var level
= msg
.level
;
137 if (typeof(level
) == "number") {
138 level
= MochiKit
.Logging
.LogLevel
[level
];
143 /** @id MochiKit.LoggingPane.messageText */
144 var messageText = function (msg
) {
145 return msg
.info
.join(" ");
148 /** @id MochiKit.LoggingPane.addMessageText */
149 var addMessageText
= bind(function (msg
) {
150 var level
= messageLevel(msg
);
151 var text
= messageText(msg
);
152 var c
= this.colorTable
[level
];
153 var p
= doc
.createElement("span");
154 p
.className
= "MochiKit-LogMessage MochiKit-LogLevel-" + level
;
155 p
.style
.cssText
= "margin: 0px; white-space: -moz-pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; white-space: pre-line; word-wrap: break-word; wrap-option: emergency; color: " + c
;
156 p
.appendChild(doc
.createTextNode(level
+ ": " + text
));
157 logPane
.appendChild(p
);
158 logPane
.appendChild(doc
.createElement("br"));
159 if (logPaneArea
.offsetHeight
> logPaneArea
.scrollHeight
) {
160 logPaneArea
.scrollTop
= 0;
162 logPaneArea
.scrollTop
= logPaneArea
.scrollHeight
;
166 /** @id MochiKit.LoggingPane.addMessage */
167 var addMessage = function (msg
) {
168 messages
[messages
.length
] = msg
;
172 /** @id MochiKit.LoggingPane.buildMessageFilter */
173 var buildMessageFilter = function () {
176 /* Catch any exceptions that might arise due to invalid regexes */
177 levelre
= new RegExp(levelFilterField
.value
);
178 infore
= new RegExp(infoFilterField
.value
);
180 /* If there was an error with the regexes, do no filtering */
181 logDebug("Error in filter regex: " + e
.message
);
185 return function (msg
) {
187 levelre
.test(messageLevel(msg
)) &&
188 infore
.test(messageText(msg
))
193 /** @id MochiKit.LoggingPane.clearMessagePane */
194 var clearMessagePane = function () {
195 while (logPane
.firstChild
) {
196 logPane
.removeChild(logPane
.firstChild
);
200 /** @id MochiKit.LoggingPane.clearMessages */
201 var clearMessages = function () {
206 /** @id MochiKit.LoggingPane.closePane */
207 var closePane
= bind(function () {
212 if (MochiKit
.LoggingPane
._loggingPane
== this) {
213 MochiKit
.LoggingPane
._loggingPane
= null;
215 this.logger
.removeListener(listenerId
);
218 debugPane
.loggingPane
= null;
219 } catch(e
) { logFatal("Bookmarklet was closed incorrectly."); }
221 debugPane
.parentNode
.removeChild(debugPane
);
228 /** @id MochiKit.LoggingPane.filterMessages */
229 var filterMessages = function () {
232 for (var i
= 0; i
< messages
.length
; i
++) {
233 var msg
= messages
[i
];
234 if (messageFilter
=== null || messageFilter(msg
)) {
240 this.buildAndApplyFilter = function () {
241 messageFilter
= buildMessageFilter();
245 this.logger
.removeListener(listenerId
);
246 this.logger
.addListener(listenerId
, messageFilter
, addMessage
);
250 /** @id MochiKit.LoggingPane.loadMessages */
251 var loadMessages
= bind(function () {
252 messages
= this.logger
.getMessages();
256 /** @id MochiKit.LoggingPane.filterOnEnter */
257 var filterOnEnter
= bind(function (event
) {
258 event
= event
|| window
.event
;
259 key
= event
.which
|| event
.keyCode
;
261 this.buildAndApplyFilter();
265 /* Create the debug pane */
266 var style
= "display: block; z-index: 1000; left: 0px; bottom: 0px; position: fixed; width: 100%; background-color: white; font: " + this.logFont
;
268 style
+= "; height: 10em; border-top: 2px solid black";
270 style
+= "; height: 98%; top:0px;"; //100%, top-alignment causes the bottom line to be partially hidden --ccarpita
272 debugPane
.style
.cssText
= style
;
274 if (!existing_pane
) {
275 doc
.body
.appendChild(debugPane
);
278 /* Create the filter fields */
279 style
= {"cssText": "width: 33%; display: inline; font: " + this.logFont
};
281 updatetree(levelFilterField
, {
282 "value": "FATAL|ERROR|WARNING|INFO|DEBUG",
283 "onkeypress": filterOnEnter
,
286 debugPane
.appendChild(levelFilterField
);
288 updatetree(infoFilterField
, {
290 "onkeypress": filterOnEnter
,
293 debugPane
.appendChild(infoFilterField
);
295 /* Create the buttons */
296 style
= "width: 8%; display:inline; font: " + this.logFont
;
298 filterButton
.appendChild(doc
.createTextNode("Filter"));
299 filterButton
.onclick
= bind("buildAndApplyFilter", this);
300 filterButton
.style
.cssText
= style
;
301 debugPane
.appendChild(filterButton
);
303 loadButton
.appendChild(doc
.createTextNode("Load"));
304 loadButton
.onclick
= loadMessages
;
305 loadButton
.style
.cssText
= style
;
306 debugPane
.appendChild(loadButton
);
308 clearButton
.appendChild(doc
.createTextNode("Clear"));
309 clearButton
.onclick
= clearMessages
;
310 clearButton
.style
.cssText
= style
;
311 debugPane
.appendChild(clearButton
);
313 closeButton
.appendChild(doc
.createTextNode("Close"));
314 closeButton
.onclick
= closePane
;
315 closeButton
.style
.cssText
= style
;
316 debugPane
.appendChild(closeButton
);
318 /* Create the logging pane */
319 logPaneArea
.style
.cssText
= "overflow: auto; width: 100%";
320 logPane
.style
.cssText
= "width: 100%; height: " + (inline
? "8em" : "100%");
322 logPaneArea
.appendChild(logPane
);
323 debugPane
.appendChild(logPaneArea
);
325 this.buildAndApplyFilter();
329 this.win
= undefined;
333 this.inline
= inline
;
334 this.closePane
= closePane
;
341 MochiKit
.LoggingPane
.LoggingPane
.prototype = {
342 "logFont": "8pt Verdana,sans-serif",
353 MochiKit
.LoggingPane
.EXPORT_OK
= [
357 MochiKit
.LoggingPane
.EXPORT
= [
361 MochiKit
.LoggingPane
.__new__ = function () {
363 ":common": this.EXPORT
,
364 ":all": MochiKit
.Base
.concat(this.EXPORT
, this.EXPORT_OK
)
367 MochiKit
.Base
.nameFunctions(this);
369 MochiKit
.LoggingPane
._loggingPane
= null;
373 MochiKit
.LoggingPane
.__new__();
375 MochiKit
.Base
._exportSymbols(this, MochiKit
.LoggingPane
);