1 /* ************************************************************************
3 qooxdoo - the new era of web development
8 2006 by STZ-IDA, Germany, http://www.stz-ida.de
11 LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
14 * Til Schneider (til132)
16 ************************************************************************ */
18 /* ************************************************************************
23 ************************************************************************ */
26 * An appender that writes all messages to a log window.
28 * This class does not depend on qooxdoo widgets, so it also works when there
29 * are problems with widgets or when the widgets are not yet initialized.
31 * @param name {string ? "qx_log"} the name of the log window.
33 qx.OO.defineClass("qx.dev.log.WindowAppender", qx.dev.log.Appender,
35 qx.dev.log.Appender.call(this);
37 this._id = qx.dev.log.WindowAppender.register(this);
38 this._name = (name == null) ? "qx_log" : name;
40 this._logWindowOpened = false;
45 * The maximum number of messages to show. If null the number of messages is not
48 qx.OO.addProperty({ name:"maxMessages", type:"number", defaultValue:500 });
50 /** Whether the window should appear under the main window. */
51 qx.OO.addProperty({ name:"popUnder", type:"boolean", defaultValue:false, allowNull:false });
55 * Creates and opens the log window if it doesn't alread exist.
57 qx.Proto.openWindow = function() {
58 if (this._logWindowOpened) {
59 // The window is already open -> Nothing to do
63 // Open the logger window
66 var winLeft = window.screen.width - winWidth;
67 var winTop = window.screen.height - winHeight;
68 var params = "toolbar=no,scrollbars=yes,resizable=yes,"
69 + "width=" + winWidth + ",height=" + winHeight
70 + ",left=" + winLeft + ",top=" + winTop;
72 // NOTE: In window.open the browser will process the event queue.
73 // Which means that other log events may arrive during this time.
74 // The log window is then in an inconsistent state, because the
75 // this._logElem is not created yet. These events will be added to the
76 // this._logEventQueue and logged after this._logElem is created.
77 this._logWindow = window.open("", this._name, params);
79 if (!this._logWindow || this._logWindow.closed)
81 if (!this._popupBlockerWarning) {
82 alert("Couldn't open debug window. Please disable your popup blocker!");
85 this._popupBlockerWarning = true;
89 // Seems to be OK now.
90 this._popupBlockerWarning = false;
92 // Store that window is open
93 this._logWindowOpened = true;
95 if (this.getPopUnder()) {
96 this._logWindow.blur();
100 var logDocument = this._logWindow.document;
101 // NOTE: We have to use a static onunload handler, because an onunload
102 // that is set later using DOM is ignored completely.
103 // (at least in Firefox, but maybe in IE, too)
105 logDocument.write("<html><head><title>" + this._name + "</title></head>"
106 + '<body onload="qx = opener.qx;" onunload="try{qx.dev.log.WindowAppender._registeredAppenders[' + this._id + '].closeWindow()}catch(e){}">'
107 + '<pre id="log" wrap="wrap" style="font-size:11"></pre></body></html>');
110 this._logElem = logDocument.getElementById("log");
112 // Log the events from the queue
113 if (this._logEventQueue != null) {
114 for (var i = 0; i < this._logEventQueue.length; i++) {
115 this.appendLogEvent(this._logEventQueue[i]);
117 this._logEventQueue = null;
123 * Closes the log window.
125 qx.Proto.closeWindow = function() {
126 if (this._logWindow != null) {
127 this._logWindow.close();
128 this._logWindow = null;
129 this._logElem = null;
130 this._logWindowOpened = false;
136 qx.Proto.appendLogEvent = function(evt) {
137 if (!this._logWindowOpened) {
138 this._logEventQueue = [];
139 this._logEventQueue.push(evt);
143 // Popup-Blocker was active!
144 if (!this._logWindowOpened) {
147 } else if (this._logElem == null) {
148 // The window is currenlty opening, but not yet finished
149 // -> Put the event in the queue
150 this._logEventQueue.push(evt);
152 var divElem = this._logWindow.document.createElement("div");
153 if (evt.level == qx.dev.log.Logger.LEVEL_ERROR) {
154 divElem.style.backgroundColor = "#FFEEEE";
155 } else if (evt.level == qx.dev.log.Logger.LEVEL_DEBUG) {
156 divElem.style.color = "gray";
158 divElem.innerHTML = this.formatLogEvent(evt).replace(/&/g, "&")
159 .replace(/</g, "<").replace(/ /g, "  ").replace(/[\n]/g, "<br>");
160 this._logElem.appendChild(divElem);
162 while (this._logElem.childNodes.length > this.getMaxMessages()) {
163 this._logElem.removeChild(this._logElem.firstChild);
165 if (this._removedMessageCount == null) {
166 this._removedMessageCount = 1;
168 this._removedMessageCount++;
172 if (this._removedMessageCount != null) {
173 this._logElem.firstChild.innerHTML = "(" + this._removedMessageCount
174 + " messages removed)";
178 this._logWindow.scrollTo(0, this._logElem.offsetHeight);
184 qx.Proto.dispose = function() {
185 if (this.getDisposed()) {
191 return qx.dev.log.Appender.prototype.dispose.call(this);
195 qx.Class._nextId = 1;
196 qx.Class._registeredAppenders = {};
200 * Registers a WindowAppender. This is used by the WindowAppender internally.
201 * You don't have to call this.
203 * @param appender {WindowAppender} the WindowAppender to register.
204 * @return {int} the ID.
206 qx.Class.register = function(appender) {
207 var WindowAppender = qx.dev.log.WindowAppender;
209 var id = WindowAppender._nextId++;
210 WindowAppender._registeredAppenders[id] = appender;
217 * Returns a prviously registered WindowAppender.
219 * @param id {int} the ID of the wanted WindowAppender.
220 * @return {WindowAppender} the WindowAppender or null if no
221 * WindowAppender with this ID is registered.
223 qx.Class.getAppender = function(id) {
224 return qx.dev.log.WindowAppender._registeredAppenders[id];