|
1 /*** |
|
2 |
|
3 MochiKit.LoggingPane 1.4.2 |
|
4 |
|
5 See <http://mochikit.com/> for documentation, downloads, license, etc. |
|
6 |
|
7 (c) 2005 Bob Ippolito. All rights Reserved. |
|
8 |
|
9 ***/ |
|
10 |
|
11 MochiKit.Base._deps('LoggingPane', ['Base', 'Logging']); |
|
12 |
|
13 MochiKit.LoggingPane.NAME = "MochiKit.LoggingPane"; |
|
14 MochiKit.LoggingPane.VERSION = "1.4.2"; |
|
15 MochiKit.LoggingPane.__repr__ = function () { |
|
16 return "[" + this.NAME + " " + this.VERSION + "]"; |
|
17 }; |
|
18 |
|
19 MochiKit.LoggingPane.toString = function () { |
|
20 return this.__repr__(); |
|
21 }; |
|
22 |
|
23 /** @id MochiKit.LoggingPane.createLoggingPane */ |
|
24 MochiKit.LoggingPane.createLoggingPane = function (inline/* = false */) { |
|
25 var m = MochiKit.LoggingPane; |
|
26 inline = !(!inline); |
|
27 if (m._loggingPane && m._loggingPane.inline != inline) { |
|
28 m._loggingPane.closePane(); |
|
29 m._loggingPane = null; |
|
30 } |
|
31 if (!m._loggingPane || m._loggingPane.closed) { |
|
32 m._loggingPane = new m.LoggingPane(inline, MochiKit.Logging.logger); |
|
33 } |
|
34 return m._loggingPane; |
|
35 }; |
|
36 |
|
37 /** @id MochiKit.LoggingPane.LoggingPane */ |
|
38 MochiKit.LoggingPane.LoggingPane = function (inline/* = false */, logger/* = MochiKit.Logging.logger */) { |
|
39 |
|
40 /* Use a div if inline, pop up a window if not */ |
|
41 /* Create the elements */ |
|
42 if (typeof(logger) == "undefined" || logger === null) { |
|
43 logger = MochiKit.Logging.logger; |
|
44 } |
|
45 this.logger = logger; |
|
46 var update = MochiKit.Base.update; |
|
47 var updatetree = MochiKit.Base.updatetree; |
|
48 var bind = MochiKit.Base.bind; |
|
49 var clone = MochiKit.Base.clone; |
|
50 var win = window; |
|
51 var uid = "_MochiKit_LoggingPane"; |
|
52 if (typeof(MochiKit.DOM) != "undefined") { |
|
53 win = MochiKit.DOM.currentWindow(); |
|
54 } |
|
55 if (!inline) { |
|
56 // name the popup with the base URL for uniqueness |
|
57 var url = win.location.href.split("?")[0].replace(/[#:\/.><&%-]/g, "_"); |
|
58 var name = uid + "_" + url; |
|
59 var nwin = win.open("", name, "dependent,resizable,height=200"); |
|
60 if (!nwin) { |
|
61 alert("Not able to open debugging window due to pop-up blocking."); |
|
62 return undefined; |
|
63 } |
|
64 nwin.document.write( |
|
65 '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" ' |
|
66 + '"http://www.w3.org/TR/html4/loose.dtd">' |
|
67 + '<html><head><title>[MochiKit.LoggingPane]</title></head>' |
|
68 + '<body></body></html>' |
|
69 ); |
|
70 nwin.document.close(); |
|
71 nwin.document.title += ' ' + win.document.title; |
|
72 win = nwin; |
|
73 } |
|
74 var doc = win.document; |
|
75 this.doc = doc; |
|
76 |
|
77 // Connect to the debug pane if it already exists (i.e. in a window orphaned by the page being refreshed) |
|
78 var debugPane = doc.getElementById(uid); |
|
79 var existing_pane = !!debugPane; |
|
80 if (debugPane && typeof(debugPane.loggingPane) != "undefined") { |
|
81 debugPane.loggingPane.logger = this.logger; |
|
82 debugPane.loggingPane.buildAndApplyFilter(); |
|
83 return debugPane.loggingPane; |
|
84 } |
|
85 |
|
86 if (existing_pane) { |
|
87 // clear any existing contents |
|
88 var child; |
|
89 while ((child = debugPane.firstChild)) { |
|
90 debugPane.removeChild(child); |
|
91 } |
|
92 } else { |
|
93 debugPane = doc.createElement("div"); |
|
94 debugPane.id = uid; |
|
95 } |
|
96 debugPane.loggingPane = this; |
|
97 var levelFilterField = doc.createElement("input"); |
|
98 var infoFilterField = doc.createElement("input"); |
|
99 var filterButton = doc.createElement("button"); |
|
100 var loadButton = doc.createElement("button"); |
|
101 var clearButton = doc.createElement("button"); |
|
102 var closeButton = doc.createElement("button"); |
|
103 var logPaneArea = doc.createElement("div"); |
|
104 var logPane = doc.createElement("div"); |
|
105 |
|
106 /* Set up the functions */ |
|
107 var listenerId = uid + "_Listener"; |
|
108 this.colorTable = clone(this.colorTable); |
|
109 var messages = []; |
|
110 var messageFilter = null; |
|
111 |
|
112 /** @id MochiKit.LoggingPane.messageLevel */ |
|
113 var messageLevel = function (msg) { |
|
114 var level = msg.level; |
|
115 if (typeof(level) == "number") { |
|
116 level = MochiKit.Logging.LogLevel[level]; |
|
117 } |
|
118 return level; |
|
119 }; |
|
120 |
|
121 /** @id MochiKit.LoggingPane.messageText */ |
|
122 var messageText = function (msg) { |
|
123 return msg.info.join(" "); |
|
124 }; |
|
125 |
|
126 /** @id MochiKit.LoggingPane.addMessageText */ |
|
127 var addMessageText = bind(function (msg) { |
|
128 var level = messageLevel(msg); |
|
129 var text = messageText(msg); |
|
130 var c = this.colorTable[level]; |
|
131 var p = doc.createElement("span"); |
|
132 p.className = "MochiKit-LogMessage MochiKit-LogLevel-" + level; |
|
133 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; |
|
134 p.appendChild(doc.createTextNode(level + ": " + text)); |
|
135 logPane.appendChild(p); |
|
136 logPane.appendChild(doc.createElement("br")); |
|
137 if (logPaneArea.offsetHeight > logPaneArea.scrollHeight) { |
|
138 logPaneArea.scrollTop = 0; |
|
139 } else { |
|
140 logPaneArea.scrollTop = logPaneArea.scrollHeight; |
|
141 } |
|
142 }, this); |
|
143 |
|
144 /** @id MochiKit.LoggingPane.addMessage */ |
|
145 var addMessage = function (msg) { |
|
146 messages[messages.length] = msg; |
|
147 addMessageText(msg); |
|
148 }; |
|
149 |
|
150 /** @id MochiKit.LoggingPane.buildMessageFilter */ |
|
151 var buildMessageFilter = function () { |
|
152 var levelre, infore; |
|
153 try { |
|
154 /* Catch any exceptions that might arise due to invalid regexes */ |
|
155 levelre = new RegExp(levelFilterField.value); |
|
156 infore = new RegExp(infoFilterField.value); |
|
157 } catch(e) { |
|
158 /* If there was an error with the regexes, do no filtering */ |
|
159 logDebug("Error in filter regex: " + e.message); |
|
160 return null; |
|
161 } |
|
162 |
|
163 return function (msg) { |
|
164 return ( |
|
165 levelre.test(messageLevel(msg)) && |
|
166 infore.test(messageText(msg)) |
|
167 ); |
|
168 }; |
|
169 }; |
|
170 |
|
171 /** @id MochiKit.LoggingPane.clearMessagePane */ |
|
172 var clearMessagePane = function () { |
|
173 while (logPane.firstChild) { |
|
174 logPane.removeChild(logPane.firstChild); |
|
175 } |
|
176 }; |
|
177 |
|
178 /** @id MochiKit.LoggingPane.clearMessages */ |
|
179 var clearMessages = function () { |
|
180 messages = []; |
|
181 clearMessagePane(); |
|
182 }; |
|
183 |
|
184 /** @id MochiKit.LoggingPane.closePane */ |
|
185 var closePane = bind(function () { |
|
186 if (this.closed) { |
|
187 return; |
|
188 } |
|
189 this.closed = true; |
|
190 if (MochiKit.LoggingPane._loggingPane == this) { |
|
191 MochiKit.LoggingPane._loggingPane = null; |
|
192 } |
|
193 this.logger.removeListener(listenerId); |
|
194 try { |
|
195 try { |
|
196 debugPane.loggingPane = null; |
|
197 } catch(e) { logFatal("Bookmarklet was closed incorrectly."); } |
|
198 if (inline) { |
|
199 debugPane.parentNode.removeChild(debugPane); |
|
200 } else { |
|
201 this.win.close(); |
|
202 } |
|
203 } catch(e) {} |
|
204 }, this); |
|
205 |
|
206 /** @id MochiKit.LoggingPane.filterMessages */ |
|
207 var filterMessages = function () { |
|
208 clearMessagePane(); |
|
209 |
|
210 for (var i = 0; i < messages.length; i++) { |
|
211 var msg = messages[i]; |
|
212 if (messageFilter === null || messageFilter(msg)) { |
|
213 addMessageText(msg); |
|
214 } |
|
215 } |
|
216 }; |
|
217 |
|
218 this.buildAndApplyFilter = function () { |
|
219 messageFilter = buildMessageFilter(); |
|
220 |
|
221 filterMessages(); |
|
222 |
|
223 this.logger.removeListener(listenerId); |
|
224 this.logger.addListener(listenerId, messageFilter, addMessage); |
|
225 }; |
|
226 |
|
227 |
|
228 /** @id MochiKit.LoggingPane.loadMessages */ |
|
229 var loadMessages = bind(function () { |
|
230 messages = this.logger.getMessages(); |
|
231 filterMessages(); |
|
232 }, this); |
|
233 |
|
234 /** @id MochiKit.LoggingPane.filterOnEnter */ |
|
235 var filterOnEnter = bind(function (event) { |
|
236 event = event || window.event; |
|
237 key = event.which || event.keyCode; |
|
238 if (key == 13) { |
|
239 this.buildAndApplyFilter(); |
|
240 } |
|
241 }, this); |
|
242 |
|
243 /* Create the debug pane */ |
|
244 var style = "display: block; z-index: 1000; left: 0px; bottom: 0px; position: fixed; width: 100%; background-color: white; font: " + this.logFont; |
|
245 if (inline) { |
|
246 style += "; height: 10em; border-top: 2px solid black"; |
|
247 } else { |
|
248 style += "; height: 100%;"; |
|
249 } |
|
250 debugPane.style.cssText = style; |
|
251 |
|
252 if (!existing_pane) { |
|
253 doc.body.appendChild(debugPane); |
|
254 } |
|
255 |
|
256 /* Create the filter fields */ |
|
257 style = {"cssText": "width: 33%; display: inline; font: " + this.logFont}; |
|
258 |
|
259 updatetree(levelFilterField, { |
|
260 "value": "FATAL|ERROR|WARNING|INFO|DEBUG", |
|
261 "onkeypress": filterOnEnter, |
|
262 "style": style |
|
263 }); |
|
264 debugPane.appendChild(levelFilterField); |
|
265 |
|
266 updatetree(infoFilterField, { |
|
267 "value": ".*", |
|
268 "onkeypress": filterOnEnter, |
|
269 "style": style |
|
270 }); |
|
271 debugPane.appendChild(infoFilterField); |
|
272 |
|
273 /* Create the buttons */ |
|
274 style = "width: 8%; display:inline; font: " + this.logFont; |
|
275 |
|
276 filterButton.appendChild(doc.createTextNode("Filter")); |
|
277 filterButton.onclick = bind("buildAndApplyFilter", this); |
|
278 filterButton.style.cssText = style; |
|
279 debugPane.appendChild(filterButton); |
|
280 |
|
281 loadButton.appendChild(doc.createTextNode("Load")); |
|
282 loadButton.onclick = loadMessages; |
|
283 loadButton.style.cssText = style; |
|
284 debugPane.appendChild(loadButton); |
|
285 |
|
286 clearButton.appendChild(doc.createTextNode("Clear")); |
|
287 clearButton.onclick = clearMessages; |
|
288 clearButton.style.cssText = style; |
|
289 debugPane.appendChild(clearButton); |
|
290 |
|
291 closeButton.appendChild(doc.createTextNode("Close")); |
|
292 closeButton.onclick = closePane; |
|
293 closeButton.style.cssText = style; |
|
294 debugPane.appendChild(closeButton); |
|
295 |
|
296 /* Create the logging pane */ |
|
297 logPaneArea.style.cssText = "overflow: auto; width: 100%"; |
|
298 logPane.style.cssText = "width: 100%; height: " + (inline ? "8em" : "100%"); |
|
299 |
|
300 logPaneArea.appendChild(logPane); |
|
301 debugPane.appendChild(logPaneArea); |
|
302 |
|
303 this.buildAndApplyFilter(); |
|
304 loadMessages(); |
|
305 |
|
306 if (inline) { |
|
307 this.win = undefined; |
|
308 } else { |
|
309 this.win = win; |
|
310 } |
|
311 this.inline = inline; |
|
312 this.closePane = closePane; |
|
313 this.closed = false; |
|
314 |
|
315 |
|
316 return this; |
|
317 }; |
|
318 |
|
319 MochiKit.LoggingPane.LoggingPane.prototype = { |
|
320 "logFont": "8pt Verdana,sans-serif", |
|
321 "colorTable": { |
|
322 "ERROR": "red", |
|
323 "FATAL": "darkred", |
|
324 "WARNING": "blue", |
|
325 "INFO": "black", |
|
326 "DEBUG": "green" |
|
327 } |
|
328 }; |
|
329 |
|
330 |
|
331 MochiKit.LoggingPane.EXPORT_OK = [ |
|
332 "LoggingPane" |
|
333 ]; |
|
334 |
|
335 MochiKit.LoggingPane.EXPORT = [ |
|
336 "createLoggingPane" |
|
337 ]; |
|
338 |
|
339 MochiKit.LoggingPane.__new__ = function () { |
|
340 this.EXPORT_TAGS = { |
|
341 ":common": this.EXPORT, |
|
342 ":all": MochiKit.Base.concat(this.EXPORT, this.EXPORT_OK) |
|
343 }; |
|
344 |
|
345 MochiKit.Base.nameFunctions(this); |
|
346 |
|
347 MochiKit.LoggingPane._loggingPane = null; |
|
348 |
|
349 }; |
|
350 |
|
351 MochiKit.LoggingPane.__new__(); |
|
352 |
|
353 MochiKit.Base._exportSymbols(this, MochiKit.LoggingPane); |