3798ae404e3f8a75406ed5311df0a773cf4ea729
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 */) {
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
);
55 return m
._loggingPane
;
58 /** @id MochiKit.LoggingPane.LoggingPane */
59 MochiKit
.LoggingPane
.LoggingPane
= function (inline
/* = false */, logger
/* = MochiKit.Logging.logger */) {
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();
77 // name the popup with the base URL for uniqueness
78 var url
= win
.location
.href
.split("?")[0].replace(/[#:\/.><&-]/g
, "_");
79 var name
= uid
+ "_" + url
;
80 var nwin
= win
.open("", name
, "dependent,resizable,height=200");
82 alert("Not able to open debugging window due to pop-up blocking.");
86 '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" '
87 + '"http://www.w3.org/TR/html4/loose.dtd">'
88 + '<html><head><title>[MochiKit.LoggingPane]</title></head>'
89 + '<body></body></html>'
91 nwin
.document
.close();
92 nwin
.document
.title
+= ' ' + win
.document
.title
;
95 var doc
= win
.document
;
98 // Connect to the debug pane if it already exists (i.e. in a window orphaned by the page being refreshed)
99 var debugPane
= doc
.getElementById(uid
);
100 var existing_pane
= !!debugPane
;
101 if (debugPane
&& typeof(debugPane
.loggingPane
) != "undefined") {
102 debugPane
.loggingPane
.logger
= this.logger
;
103 debugPane
.loggingPane
.buildAndApplyFilter();
104 return debugPane
.loggingPane
;
108 // clear any existing contents
110 while ((child
= debugPane
.firstChild
)) {
111 debugPane
.removeChild(child
);
114 debugPane
= doc
.createElement("div");
117 debugPane
.loggingPane
= this;
118 var levelFilterField
= doc
.createElement("input");
119 var infoFilterField
= doc
.createElement("input");
120 var filterButton
= doc
.createElement("button");
121 var loadButton
= doc
.createElement("button");
122 var clearButton
= doc
.createElement("button");
123 var closeButton
= doc
.createElement("button");
124 var logPaneArea
= doc
.createElement("div");
125 var logPane
= doc
.createElement("div");
127 /* Set up the functions */
128 var listenerId
= uid
+ "_Listener";
129 this.colorTable
= clone(this.colorTable
);
131 var messageFilter
= null;
133 /** @id MochiKit.LoggingPane.messageLevel */
134 var messageLevel
= function (msg
) {
135 var level
= msg
.level
;
136 if (typeof(level
) == "number") {
137 level
= MochiKit
.Logging
.LogLevel
[level
];
142 /** @id MochiKit.LoggingPane.messageText */
143 var messageText
= function (msg
) {
144 return msg
.info
.join(" ");
147 /** @id MochiKit.LoggingPane.addMessageText */
148 var addMessageText
= bind(function (msg
) {
149 var level
= messageLevel(msg
);
150 var text
= messageText(msg
);
151 var c
= this.colorTable
[level
];
152 var p
= doc
.createElement("span");
153 p
.className
= "MochiKit-LogMessage MochiKit-LogLevel-" + level
;
154 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
;
155 p
.appendChild(doc
.createTextNode(level
+ ": " + text
));
156 logPane
.appendChild(p
);
157 logPane
.appendChild(doc
.createElement("br"));
158 if (logPaneArea
.offsetHeight
> logPaneArea
.scrollHeight
) {
159 logPaneArea
.scrollTop
= 0;
161 logPaneArea
.scrollTop
= logPaneArea
.scrollHeight
;
165 /** @id MochiKit.LoggingPane.addMessage */
166 var addMessage
= function (msg
) {
167 messages
[messages
.length
] = msg
;
171 /** @id MochiKit.LoggingPane.buildMessageFilter */
172 var buildMessageFilter
= function () {
175 /* Catch any exceptions that might arise due to invalid regexes */
176 levelre
= new RegExp(levelFilterField
.value
);
177 infore
= new RegExp(infoFilterField
.value
);
179 /* If there was an error with the regexes, do no filtering */
180 logDebug("Error in filter regex: " + e
.message
);
184 return function (msg
) {
186 levelre
.test(messageLevel(msg
)) &&
187 infore
.test(messageText(msg
))
192 /** @id MochiKit.LoggingPane.clearMessagePane */
193 var clearMessagePane
= function () {
194 while (logPane
.firstChild
) {
195 logPane
.removeChild(logPane
.firstChild
);
199 /** @id MochiKit.LoggingPane.clearMessages */
200 var clearMessages
= function () {
205 /** @id MochiKit.LoggingPane.closePane */
206 var closePane
= bind(function () {
211 if (MochiKit
.LoggingPane
._loggingPane
== this) {
212 MochiKit
.LoggingPane
._loggingPane
= null;
214 this.logger
.removeListener(listenerId
);
217 debugPane
.loggingPane
= null;
218 } catch(e
) { logFatal("Bookmarklet was closed incorrectly."); }
220 debugPane
.parentNode
.removeChild(debugPane
);
227 /** @id MochiKit.LoggingPane.filterMessages */
228 var filterMessages
= function () {
231 for (var i
= 0; i
< messages
.length
; i
++) {
232 var msg
= messages
[i
];
233 if (messageFilter
=== null || messageFilter(msg
)) {
239 this.buildAndApplyFilter
= function () {
240 messageFilter
= buildMessageFilter();
244 this.logger
.removeListener(listenerId
);
245 this.logger
.addListener(listenerId
, messageFilter
, addMessage
);
249 /** @id MochiKit.LoggingPane.loadMessages */
250 var loadMessages
= bind(function () {
251 messages
= this.logger
.getMessages();
255 /** @id MochiKit.LoggingPane.filterOnEnter */
256 var filterOnEnter
= bind(function (event
) {
257 event
= event
|| window
.event
;
258 key
= event
.which
|| event
.keyCode
;
260 this.buildAndApplyFilter();
264 /* Create the debug pane */
265 var style
= "display: block; z-index: 1000; left: 0px; bottom: 0px; position: fixed; width: 100%; background-color: white; font: " + this.logFont
;
267 style
+= "; height: 10em; border-top: 2px solid black";
269 style
+= "; height: 100%;";
271 debugPane
.style
.cssText
= style
;
273 if (!existing_pane
) {
274 doc
.body
.appendChild(debugPane
);
277 /* Create the filter fields */
278 style
= {"cssText": "width: 33%; display: inline; font: " + this.logFont
};
280 updatetree(levelFilterField
, {
281 "value": "FATAL|ERROR|WARNING|INFO|DEBUG",
282 "onkeypress": filterOnEnter
,
285 debugPane
.appendChild(levelFilterField
);
287 updatetree(infoFilterField
, {
289 "onkeypress": filterOnEnter
,
292 debugPane
.appendChild(infoFilterField
);
294 /* Create the buttons */
295 style
= "width: 8%; display:inline; font: " + this.logFont
;
297 filterButton
.appendChild(doc
.createTextNode("Filter"));
298 filterButton
.onclick
= bind("buildAndApplyFilter", this);
299 filterButton
.style
.cssText
= style
;
300 debugPane
.appendChild(filterButton
);
302 loadButton
.appendChild(doc
.createTextNode("Load"));
303 loadButton
.onclick
= loadMessages
;
304 loadButton
.style
.cssText
= style
;
305 debugPane
.appendChild(loadButton
);
307 clearButton
.appendChild(doc
.createTextNode("Clear"));
308 clearButton
.onclick
= clearMessages
;
309 clearButton
.style
.cssText
= style
;
310 debugPane
.appendChild(clearButton
);
312 closeButton
.appendChild(doc
.createTextNode("Close"));
313 closeButton
.onclick
= closePane
;
314 closeButton
.style
.cssText
= style
;
315 debugPane
.appendChild(closeButton
);
317 /* Create the logging pane */
318 logPaneArea
.style
.cssText
= "overflow: auto; width: 100%";
319 logPane
.style
.cssText
= "width: 100%; height: " + (inline
? "8em" : "100%");
321 logPaneArea
.appendChild(logPane
);
322 debugPane
.appendChild(logPaneArea
);
324 this.buildAndApplyFilter();
328 this.win
= undefined
;
332 this.inline
= inline
;
333 this.closePane
= closePane
;
340 MochiKit
.LoggingPane
.LoggingPane
.prototype = {
341 "logFont": "8pt Verdana,sans-serif",
352 MochiKit
.LoggingPane
.EXPORT_OK
= [
356 MochiKit
.LoggingPane
.EXPORT
= [
360 MochiKit
.LoggingPane
.__new__
= function () {
362 ":common": this.EXPORT
,
363 ":all": MochiKit
.Base
.concat(this.EXPORT
, this.EXPORT_OK
)
366 MochiKit
.Base
.nameFunctions(this);
368 MochiKit
.LoggingPane
._loggingPane
= null;
372 MochiKit
.LoggingPane
.__new__();
374 MochiKit
.Base
._exportSymbols(this, MochiKit
.LoggingPane
);