Initial check-in
[dygraphs.git] / mochikit_v14 / MochiKit / LoggingPane.js
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);