|
1 /*** |
|
2 |
|
3 MochiKit.LoggingPane 1.4 |
|
4 |
|
5 See <http://mochikit.com/> for documentation, downloads, license, etc. |
|
6 |
|
7 (c) 2005 Bob Ippolito. All rights Reserved. |
|
8 |
|
9 ***/ |
|
10 |
|
11 if (typeof(dojo) != 'undefined') { |
|
12 dojo.provide('MochiKit.LoggingPane'); |
|
13 dojo.require('MochiKit.Logging'); |
|
14 dojo.require('MochiKit.Base'); |
|
15 } |
|
16 |
|
17 if (typeof(JSAN) != 'undefined') { |
|
18 JSAN.use("MochiKit.Logging", []); |
|
19 JSAN.use("MochiKit.Base", []); |
|
20 } |
|
21 |
|
22 try { |
|
23 if (typeof(MochiKit.Base) == 'undefined' || typeof(MochiKit.Logging) == 'undefined') { |
|
24 throw ""; |
|
25 } |
|
26 } catch (e) { |
|
27 throw "MochiKit.LoggingPane depends on MochiKit.Base and MochiKit.Logging!"; |
|
28 } |
|
29 |
|
30 if (typeof(MochiKit.LoggingPane) == 'undefined') { |
|
31 MochiKit.LoggingPane = {}; |
|
32 } |
|
33 |
|
34 MochiKit.LoggingPane.NAME = "MochiKit.LoggingPane"; |
|
35 MochiKit.LoggingPane.VERSION = "1.4"; |
|
36 MochiKit.LoggingPane.__repr__ = function () { |
|
37 return "[" + this.NAME + " " + this.VERSION + "]"; |
|
38 }; |
|
39 |
|
40 MochiKit.LoggingPane.toString = function () { |
|
41 return this.__repr__(); |
|
42 }; |
|
43 |
|
44 /** @id MochiKit.LoggingPane.createLoggingPane */ |
|
45 MochiKit.LoggingPane.createLoggingPane = function (inline/* = false */) { |
|
46 var m = MochiKit.LoggingPane; |
|
47 inline = !(!inline); |
|
48 if (m._loggingPane && m._loggingPane.inline != inline) { |
|
49 m._loggingPane.closePane(); |
|
50 m._loggingPane = null; |
|
51 } |
|
52 if (!m._loggingPane || m._loggingPane.closed) { |
|
53 m._loggingPane = new m.LoggingPane(inline, MochiKit.Logging.logger); |
|
54 } |
|
55 return m._loggingPane; |
|
56 }; |
|
57 |
|
58 /** @id MochiKit.LoggingPane.LoggingPane */ |
|
59 MochiKit.LoggingPane.LoggingPane = function (inline/* = false */, logger/* = MochiKit.Logging.logger */) { |
|
60 |
|
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; |
|
65 } |
|
66 this.logger = 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; |
|
71 var win = window; |
|
72 var uid = "_MochiKit_LoggingPane"; |
|
73 if (typeof(MochiKit.DOM) != "undefined") { |
|
74 win = MochiKit.DOM.currentWindow(); |
|
75 } |
|
76 if (!inline) { |
|
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"); |
|
81 if (!nwin) { |
|
82 alert("Not able to open debugging window due to pop-up blocking."); |
|
83 return undefined; |
|
84 } |
|
85 nwin.document.write( |
|
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>' |
|
90 ); |
|
91 nwin.document.close(); |
|
92 nwin.document.title += ' ' + win.document.title; |
|
93 win = nwin; |
|
94 } |
|
95 var doc = win.document; |
|
96 this.doc = doc; |
|
97 |
|
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; |
|
105 } |
|
106 |
|
107 if (existing_pane) { |
|
108 // clear any existing contents |
|
109 var child; |
|
110 while ((child = debugPane.firstChild)) { |
|
111 debugPane.removeChild(child); |
|
112 } |
|
113 } else { |
|
114 debugPane = doc.createElement("div"); |
|
115 debugPane.id = uid; |
|
116 } |
|
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"); |
|
126 |
|
127 /* Set up the functions */ |
|
128 var listenerId = uid + "_Listener"; |
|
129 this.colorTable = clone(this.colorTable); |
|
130 var messages = []; |
|
131 var messageFilter = null; |
|
132 |
|
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]; |
|
138 } |
|
139 return level; |
|
140 }; |
|
141 |
|
142 /** @id MochiKit.LoggingPane.messageText */ |
|
143 var messageText = function (msg) { |
|
144 return msg.info.join(" "); |
|
145 }; |
|
146 |
|
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; |
|
160 } else { |
|
161 logPaneArea.scrollTop = logPaneArea.scrollHeight; |
|
162 } |
|
163 }, this); |
|
164 |
|
165 /** @id MochiKit.LoggingPane.addMessage */ |
|
166 var addMessage = function (msg) { |
|
167 messages[messages.length] = msg; |
|
168 addMessageText(msg); |
|
169 }; |
|
170 |
|
171 /** @id MochiKit.LoggingPane.buildMessageFilter */ |
|
172 var buildMessageFilter = function () { |
|
173 var levelre, infore; |
|
174 try { |
|
175 /* Catch any exceptions that might arise due to invalid regexes */ |
|
176 levelre = new RegExp(levelFilterField.value); |
|
177 infore = new RegExp(infoFilterField.value); |
|
178 } catch(e) { |
|
179 /* If there was an error with the regexes, do no filtering */ |
|
180 logDebug("Error in filter regex: " + e.message); |
|
181 return null; |
|
182 } |
|
183 |
|
184 return function (msg) { |
|
185 return ( |
|
186 levelre.test(messageLevel(msg)) && |
|
187 infore.test(messageText(msg)) |
|
188 ); |
|
189 }; |
|
190 }; |
|
191 |
|
192 /** @id MochiKit.LoggingPane.clearMessagePane */ |
|
193 var clearMessagePane = function () { |
|
194 while (logPane.firstChild) { |
|
195 logPane.removeChild(logPane.firstChild); |
|
196 } |
|
197 }; |
|
198 |
|
199 /** @id MochiKit.LoggingPane.clearMessages */ |
|
200 var clearMessages = function () { |
|
201 messages = []; |
|
202 clearMessagePane(); |
|
203 }; |
|
204 |
|
205 /** @id MochiKit.LoggingPane.closePane */ |
|
206 var closePane = bind(function () { |
|
207 if (this.closed) { |
|
208 return; |
|
209 } |
|
210 this.closed = true; |
|
211 if (MochiKit.LoggingPane._loggingPane == this) { |
|
212 MochiKit.LoggingPane._loggingPane = null; |
|
213 } |
|
214 this.logger.removeListener(listenerId); |
|
215 try { |
|
216 try { |
|
217 debugPane.loggingPane = null; |
|
218 } catch(e) { logFatal("Bookmarklet was closed incorrectly."); } |
|
219 if (inline) { |
|
220 debugPane.parentNode.removeChild(debugPane); |
|
221 } else { |
|
222 this.win.close(); |
|
223 } |
|
224 } catch(e) {} |
|
225 }, this); |
|
226 |
|
227 /** @id MochiKit.LoggingPane.filterMessages */ |
|
228 var filterMessages = function () { |
|
229 clearMessagePane(); |
|
230 |
|
231 for (var i = 0; i < messages.length; i++) { |
|
232 var msg = messages[i]; |
|
233 if (messageFilter === null || messageFilter(msg)) { |
|
234 addMessageText(msg); |
|
235 } |
|
236 } |
|
237 }; |
|
238 |
|
239 this.buildAndApplyFilter = function () { |
|
240 messageFilter = buildMessageFilter(); |
|
241 |
|
242 filterMessages(); |
|
243 |
|
244 this.logger.removeListener(listenerId); |
|
245 this.logger.addListener(listenerId, messageFilter, addMessage); |
|
246 }; |
|
247 |
|
248 |
|
249 /** @id MochiKit.LoggingPane.loadMessages */ |
|
250 var loadMessages = bind(function () { |
|
251 messages = this.logger.getMessages(); |
|
252 filterMessages(); |
|
253 }, this); |
|
254 |
|
255 /** @id MochiKit.LoggingPane.filterOnEnter */ |
|
256 var filterOnEnter = bind(function (event) { |
|
257 event = event || window.event; |
|
258 key = event.which || event.keyCode; |
|
259 if (key == 13) { |
|
260 this.buildAndApplyFilter(); |
|
261 } |
|
262 }, this); |
|
263 |
|
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; |
|
266 if (inline) { |
|
267 style += "; height: 10em; border-top: 2px solid black"; |
|
268 } else { |
|
269 style += "; height: 100%;"; |
|
270 } |
|
271 debugPane.style.cssText = style; |
|
272 |
|
273 if (!existing_pane) { |
|
274 doc.body.appendChild(debugPane); |
|
275 } |
|
276 |
|
277 /* Create the filter fields */ |
|
278 style = {"cssText": "width: 33%; display: inline; font: " + this.logFont}; |
|
279 |
|
280 updatetree(levelFilterField, { |
|
281 "value": "FATAL|ERROR|WARNING|INFO|DEBUG", |
|
282 "onkeypress": filterOnEnter, |
|
283 "style": style |
|
284 }); |
|
285 debugPane.appendChild(levelFilterField); |
|
286 |
|
287 updatetree(infoFilterField, { |
|
288 "value": ".*", |
|
289 "onkeypress": filterOnEnter, |
|
290 "style": style |
|
291 }); |
|
292 debugPane.appendChild(infoFilterField); |
|
293 |
|
294 /* Create the buttons */ |
|
295 style = "width: 8%; display:inline; font: " + this.logFont; |
|
296 |
|
297 filterButton.appendChild(doc.createTextNode("Filter")); |
|
298 filterButton.onclick = bind("buildAndApplyFilter", this); |
|
299 filterButton.style.cssText = style; |
|
300 debugPane.appendChild(filterButton); |
|
301 |
|
302 loadButton.appendChild(doc.createTextNode("Load")); |
|
303 loadButton.onclick = loadMessages; |
|
304 loadButton.style.cssText = style; |
|
305 debugPane.appendChild(loadButton); |
|
306 |
|
307 clearButton.appendChild(doc.createTextNode("Clear")); |
|
308 clearButton.onclick = clearMessages; |
|
309 clearButton.style.cssText = style; |
|
310 debugPane.appendChild(clearButton); |
|
311 |
|
312 closeButton.appendChild(doc.createTextNode("Close")); |
|
313 closeButton.onclick = closePane; |
|
314 closeButton.style.cssText = style; |
|
315 debugPane.appendChild(closeButton); |
|
316 |
|
317 /* Create the logging pane */ |
|
318 logPaneArea.style.cssText = "overflow: auto; width: 100%"; |
|
319 logPane.style.cssText = "width: 100%; height: " + (inline ? "8em" : "100%"); |
|
320 |
|
321 logPaneArea.appendChild(logPane); |
|
322 debugPane.appendChild(logPaneArea); |
|
323 |
|
324 this.buildAndApplyFilter(); |
|
325 loadMessages(); |
|
326 |
|
327 if (inline) { |
|
328 this.win = undefined; |
|
329 } else { |
|
330 this.win = win; |
|
331 } |
|
332 this.inline = inline; |
|
333 this.closePane = closePane; |
|
334 this.closed = false; |
|
335 |
|
336 |
|
337 return this; |
|
338 }; |
|
339 |
|
340 MochiKit.LoggingPane.LoggingPane.prototype = { |
|
341 "logFont": "8pt Verdana,sans-serif", |
|
342 "colorTable": { |
|
343 "ERROR": "red", |
|
344 "FATAL": "darkred", |
|
345 "WARNING": "blue", |
|
346 "INFO": "black", |
|
347 "DEBUG": "green" |
|
348 } |
|
349 }; |
|
350 |
|
351 |
|
352 MochiKit.LoggingPane.EXPORT_OK = [ |
|
353 "LoggingPane" |
|
354 ]; |
|
355 |
|
356 MochiKit.LoggingPane.EXPORT = [ |
|
357 "createLoggingPane" |
|
358 ]; |
|
359 |
|
360 MochiKit.LoggingPane.__new__ = function () { |
|
361 this.EXPORT_TAGS = { |
|
362 ":common": this.EXPORT, |
|
363 ":all": MochiKit.Base.concat(this.EXPORT, this.EXPORT_OK) |
|
364 }; |
|
365 |
|
366 MochiKit.Base.nameFunctions(this); |
|
367 |
|
368 MochiKit.LoggingPane._loggingPane = null; |
|
369 |
|
370 }; |
|
371 |
|
372 MochiKit.LoggingPane.__new__(); |
|
373 |
|
374 MochiKit.Base._exportSymbols(this, MochiKit.LoggingPane); |