Bug 435739 Poor performance of Firefox 3 with no X RENDER extension
[wine-gecko.git] / testing / mochitest / MochiKit / LoggingPane.js
blob8ecf410a7e44183f235c128626252733552f4f01
1 /***
3 MochiKit.LoggingPane 1.4
5 See <http://mochikit.com/> for documentation, downloads, license, etc.
7 (c) 2005 Bob Ippolito.  All rights Reserved.
9 ***/
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", []);
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!";
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;
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;
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");
127     /* Set up the functions */
128     var listenerId = uid + "_Listener";
129     this.colorTable = clone(this.colorTable);
130     var messages = [];
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];
138         }
139         return level;
140     };
142     /** @id MochiKit.LoggingPane.messageText */
143     var messageText = function (msg) {
144         return msg.info.join(" ");
145     };
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);
165     /** @id MochiKit.LoggingPane.addMessage */
166     var addMessage = function (msg) {
167         messages[messages.length] = msg;
168         addMessageText(msg);
169     };
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         }
184         return function (msg) {
185             return (
186                 levelre.test(messageLevel(msg)) &&
187                 infore.test(messageText(msg))
188             );
189         };
190     };
192     /** @id MochiKit.LoggingPane.clearMessagePane */
193     var clearMessagePane = function () {
194         while (logPane.firstChild) {
195             logPane.removeChild(logPane.firstChild);
196         }
197     };
199     /** @id MochiKit.LoggingPane.clearMessages */
200     var clearMessages = function () {
201         messages = [];
202         clearMessagePane();
203     };
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);
216         debugPane.loggingPane = null;
218         if (inline) {
219             debugPane.parentNode.removeChild(debugPane);
220         } else {
221             this.win.close();
222         }
223     }, this);
225     /** @id MochiKit.LoggingPane.filterMessages */
226     var filterMessages = function () {
227         clearMessagePane();
229         for (var i = 0; i < messages.length; i++) {
230             var msg = messages[i];
231             if (messageFilter === null || messageFilter(msg)) {
232                 addMessageText(msg);
233             }
234         }
235     };
237     this.buildAndApplyFilter = function () {
238         messageFilter = buildMessageFilter();
240         filterMessages();
242         this.logger.removeListener(listenerId);
243         this.logger.addListener(listenerId, messageFilter, addMessage);
244     };
247     /** @id MochiKit.LoggingPane.loadMessages */
248     var loadMessages = bind(function () {
249         messages = this.logger.getMessages();
250         filterMessages();
251     }, this);
253     /** @id MochiKit.LoggingPane.filterOnEnter */
254     var filterOnEnter = bind(function (event) {
255         event = event || window.event;
256         key = event.which || event.keyCode;
257         if (key == 13) {
258             this.buildAndApplyFilter();
259         }
260     }, this);
262     /* Create the debug pane */
263     var style = "display: block; z-index: 1000; left: 0px; bottom: 0px; position: fixed; width: 100%; background-color: white; font: " + this.logFont;
264     if (inline) {
265         style += "; height: 10em; border-top: 2px solid black";
266     } else {
267         style += "; height: 100%;";
268     }
269     debugPane.style.cssText = style;
271     if (!existing_pane) {
272         doc.body.appendChild(debugPane);
273     }
275     /* Create the filter fields */
276     style = {"cssText": "width: 33%; display: inline; font: " + this.logFont};
278     updatetree(levelFilterField, {
279         "value": "FATAL|ERROR|WARNING|INFO|DEBUG",
280         "onkeypress": filterOnEnter,
281         "style": style
282     });
283     debugPane.appendChild(levelFilterField);
285     updatetree(infoFilterField, {
286         "value": ".*",
287         "onkeypress": filterOnEnter,
288         "style": style
289     });
290     debugPane.appendChild(infoFilterField);
292     /* Create the buttons */
293     style = "width: 8%; display:inline; font: " + this.logFont;
295     filterButton.appendChild(doc.createTextNode("Filter"));
296     filterButton.onclick = bind("buildAndApplyFilter", this);
297     filterButton.style.cssText = style;
298     debugPane.appendChild(filterButton);
300     loadButton.appendChild(doc.createTextNode("Load"));
301     loadButton.onclick = loadMessages;
302     loadButton.style.cssText = style;
303     debugPane.appendChild(loadButton);
305     clearButton.appendChild(doc.createTextNode("Clear"));
306     clearButton.onclick = clearMessages;
307     clearButton.style.cssText = style;
308     debugPane.appendChild(clearButton);
310     closeButton.appendChild(doc.createTextNode("Close"));
311     closeButton.onclick = closePane;
312     closeButton.style.cssText = style;
313     debugPane.appendChild(closeButton);
315     /* Create the logging pane */
316     logPaneArea.style.cssText = "overflow: auto; width: 100%";
317     logPane.style.cssText = "width: 100%; height: " + (inline ? "8em" : "100%");
319     logPaneArea.appendChild(logPane);
320     debugPane.appendChild(logPaneArea);
322     this.buildAndApplyFilter();
323     loadMessages();
325     if (inline) {
326         this.win = undefined;
327     } else {
328         this.win = win;
329     }
330     this.inline = inline;
331     this.closePane = closePane;
332     this.closed = false;
334     return this;
337 MochiKit.LoggingPane.LoggingPane.prototype = {
338     "logFont": "8pt Verdana,sans-serif",
339     "colorTable": {
340         "ERROR": "red",
341         "FATAL": "darkred",
342         "WARNING": "blue",
343         "INFO": "black",
344         "DEBUG": "green"
345     }
349 MochiKit.LoggingPane.EXPORT_OK = [
350     "LoggingPane"
353 MochiKit.LoggingPane.EXPORT = [
354     "createLoggingPane"
357 MochiKit.LoggingPane.__new__ = function () {
358     this.EXPORT_TAGS = {
359         ":common": this.EXPORT,
360         ":all": MochiKit.Base.concat(this.EXPORT, this.EXPORT_OK)
361     };
362     
363     MochiKit.Base.nameFunctions(this);
365     MochiKit.LoggingPane._loggingPane = null;
366   
369 MochiKit.LoggingPane.__new__();
371 MochiKit.Base._exportSymbols(this, MochiKit.LoggingPane);