Commit | Line | Data |
---|---|---|
6a1aa64f DV |
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); |