michael@0: /*** michael@0: michael@0: MochiKit.LoggingPane 1.4.2 michael@0: michael@0: See for documentation, downloads, license, etc. michael@0: michael@0: (c) 2005 Bob Ippolito. All rights Reserved. michael@0: michael@0: ***/ michael@0: michael@0: MochiKit.Base._deps('LoggingPane', ['Base', 'Logging']); michael@0: michael@0: MochiKit.LoggingPane.NAME = "MochiKit.LoggingPane"; michael@0: MochiKit.LoggingPane.VERSION = "1.4.2"; michael@0: MochiKit.LoggingPane.__repr__ = function () { michael@0: return "[" + this.NAME + " " + this.VERSION + "]"; michael@0: }; michael@0: michael@0: MochiKit.LoggingPane.toString = function () { michael@0: return this.__repr__(); michael@0: }; michael@0: michael@0: /** @id MochiKit.LoggingPane.createLoggingPane */ michael@0: MochiKit.LoggingPane.createLoggingPane = function (inline/* = false */) { michael@0: var m = MochiKit.LoggingPane; michael@0: inline = !(!inline); michael@0: if (m._loggingPane && m._loggingPane.inline != inline) { michael@0: m._loggingPane.closePane(); michael@0: m._loggingPane = null; michael@0: } michael@0: if (!m._loggingPane || m._loggingPane.closed) { michael@0: m._loggingPane = new m.LoggingPane(inline, MochiKit.Logging.logger); michael@0: } michael@0: return m._loggingPane; michael@0: }; michael@0: michael@0: /** @id MochiKit.LoggingPane.LoggingPane */ michael@0: MochiKit.LoggingPane.LoggingPane = function (inline/* = false */, logger/* = MochiKit.Logging.logger */) { michael@0: michael@0: /* Use a div if inline, pop up a window if not */ michael@0: /* Create the elements */ michael@0: if (typeof(logger) == "undefined" || logger === null) { michael@0: logger = MochiKit.Logging.logger; michael@0: } michael@0: this.logger = logger; michael@0: var update = MochiKit.Base.update; michael@0: var updatetree = MochiKit.Base.updatetree; michael@0: var bind = MochiKit.Base.bind; michael@0: var clone = MochiKit.Base.clone; michael@0: var win = window; michael@0: var uid = "_MochiKit_LoggingPane"; michael@0: if (typeof(MochiKit.DOM) != "undefined") { michael@0: win = MochiKit.DOM.currentWindow(); michael@0: } michael@0: if (!inline) { michael@0: // name the popup with the base URL for uniqueness michael@0: var url = win.location.href.split("?")[0].replace(/[#:\/.><&%-]/g, "_"); michael@0: var name = uid + "_" + url; michael@0: var nwin = win.open("", name, "dependent,resizable,height=200"); michael@0: if (!nwin) { michael@0: alert("Not able to open debugging window due to pop-up blocking."); michael@0: return undefined; michael@0: } michael@0: nwin.document.write( michael@0: '' michael@0: + '[MochiKit.LoggingPane]' michael@0: + '' michael@0: ); michael@0: nwin.document.close(); michael@0: nwin.document.title += ' ' + win.document.title; michael@0: win = nwin; michael@0: } michael@0: var doc = win.document; michael@0: this.doc = doc; michael@0: michael@0: // Connect to the debug pane if it already exists (i.e. in a window orphaned by the page being refreshed) michael@0: var debugPane = doc.getElementById(uid); michael@0: var existing_pane = !!debugPane; michael@0: if (debugPane && typeof(debugPane.loggingPane) != "undefined") { michael@0: debugPane.loggingPane.logger = this.logger; michael@0: debugPane.loggingPane.buildAndApplyFilter(); michael@0: return debugPane.loggingPane; michael@0: } michael@0: michael@0: if (existing_pane) { michael@0: // clear any existing contents michael@0: var child; michael@0: while ((child = debugPane.firstChild)) { michael@0: debugPane.removeChild(child); michael@0: } michael@0: } else { michael@0: debugPane = doc.createElement("div"); michael@0: debugPane.id = uid; michael@0: } michael@0: debugPane.loggingPane = this; michael@0: var levelFilterField = doc.createElement("input"); michael@0: var infoFilterField = doc.createElement("input"); michael@0: var filterButton = doc.createElement("button"); michael@0: var loadButton = doc.createElement("button"); michael@0: var clearButton = doc.createElement("button"); michael@0: var closeButton = doc.createElement("button"); michael@0: var logPaneArea = doc.createElement("div"); michael@0: var logPane = doc.createElement("div"); michael@0: michael@0: /* Set up the functions */ michael@0: var listenerId = uid + "_Listener"; michael@0: this.colorTable = clone(this.colorTable); michael@0: var messages = []; michael@0: var messageFilter = null; michael@0: michael@0: /** @id MochiKit.LoggingPane.messageLevel */ michael@0: var messageLevel = function (msg) { michael@0: var level = msg.level; michael@0: if (typeof(level) == "number") { michael@0: level = MochiKit.Logging.LogLevel[level]; michael@0: } michael@0: return level; michael@0: }; michael@0: michael@0: /** @id MochiKit.LoggingPane.messageText */ michael@0: var messageText = function (msg) { michael@0: return msg.info.join(" "); michael@0: }; michael@0: michael@0: /** @id MochiKit.LoggingPane.addMessageText */ michael@0: var addMessageText = bind(function (msg) { michael@0: var level = messageLevel(msg); michael@0: var text = messageText(msg); michael@0: var c = this.colorTable[level]; michael@0: var p = doc.createElement("span"); michael@0: p.className = "MochiKit-LogMessage MochiKit-LogLevel-" + level; michael@0: 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; michael@0: p.appendChild(doc.createTextNode(level + ": " + text)); michael@0: logPane.appendChild(p); michael@0: logPane.appendChild(doc.createElement("br")); michael@0: if (logPaneArea.offsetHeight > logPaneArea.scrollHeight) { michael@0: logPaneArea.scrollTop = 0; michael@0: } else { michael@0: logPaneArea.scrollTop = logPaneArea.scrollHeight; michael@0: } michael@0: }, this); michael@0: michael@0: /** @id MochiKit.LoggingPane.addMessage */ michael@0: var addMessage = function (msg) { michael@0: messages[messages.length] = msg; michael@0: addMessageText(msg); michael@0: }; michael@0: michael@0: /** @id MochiKit.LoggingPane.buildMessageFilter */ michael@0: var buildMessageFilter = function () { michael@0: var levelre, infore; michael@0: try { michael@0: /* Catch any exceptions that might arise due to invalid regexes */ michael@0: levelre = new RegExp(levelFilterField.value); michael@0: infore = new RegExp(infoFilterField.value); michael@0: } catch(e) { michael@0: /* If there was an error with the regexes, do no filtering */ michael@0: logDebug("Error in filter regex: " + e.message); michael@0: return null; michael@0: } michael@0: michael@0: return function (msg) { michael@0: return ( michael@0: levelre.test(messageLevel(msg)) && michael@0: infore.test(messageText(msg)) michael@0: ); michael@0: }; michael@0: }; michael@0: michael@0: /** @id MochiKit.LoggingPane.clearMessagePane */ michael@0: var clearMessagePane = function () { michael@0: while (logPane.firstChild) { michael@0: logPane.removeChild(logPane.firstChild); michael@0: } michael@0: }; michael@0: michael@0: /** @id MochiKit.LoggingPane.clearMessages */ michael@0: var clearMessages = function () { michael@0: messages = []; michael@0: clearMessagePane(); michael@0: }; michael@0: michael@0: /** @id MochiKit.LoggingPane.closePane */ michael@0: var closePane = bind(function () { michael@0: if (this.closed) { michael@0: return; michael@0: } michael@0: this.closed = true; michael@0: if (MochiKit.LoggingPane._loggingPane == this) { michael@0: MochiKit.LoggingPane._loggingPane = null; michael@0: } michael@0: this.logger.removeListener(listenerId); michael@0: try { michael@0: try { michael@0: debugPane.loggingPane = null; michael@0: } catch(e) { logFatal("Bookmarklet was closed incorrectly."); } michael@0: if (inline) { michael@0: debugPane.parentNode.removeChild(debugPane); michael@0: } else { michael@0: this.win.close(); michael@0: } michael@0: } catch(e) {} michael@0: }, this); michael@0: michael@0: /** @id MochiKit.LoggingPane.filterMessages */ michael@0: var filterMessages = function () { michael@0: clearMessagePane(); michael@0: michael@0: for (var i = 0; i < messages.length; i++) { michael@0: var msg = messages[i]; michael@0: if (messageFilter === null || messageFilter(msg)) { michael@0: addMessageText(msg); michael@0: } michael@0: } michael@0: }; michael@0: michael@0: this.buildAndApplyFilter = function () { michael@0: messageFilter = buildMessageFilter(); michael@0: michael@0: filterMessages(); michael@0: michael@0: this.logger.removeListener(listenerId); michael@0: this.logger.addListener(listenerId, messageFilter, addMessage); michael@0: }; michael@0: michael@0: michael@0: /** @id MochiKit.LoggingPane.loadMessages */ michael@0: var loadMessages = bind(function () { michael@0: messages = this.logger.getMessages(); michael@0: filterMessages(); michael@0: }, this); michael@0: michael@0: /** @id MochiKit.LoggingPane.filterOnEnter */ michael@0: var filterOnEnter = bind(function (event) { michael@0: event = event || window.event; michael@0: key = event.which || event.keyCode; michael@0: if (key == 13) { michael@0: this.buildAndApplyFilter(); michael@0: } michael@0: }, this); michael@0: michael@0: /* Create the debug pane */ michael@0: var style = "display: block; z-index: 1000; left: 0px; bottom: 0px; position: fixed; width: 100%; background-color: white; font: " + this.logFont; michael@0: if (inline) { michael@0: style += "; height: 10em; border-top: 2px solid black"; michael@0: } else { michael@0: style += "; height: 100%;"; michael@0: } michael@0: debugPane.style.cssText = style; michael@0: michael@0: if (!existing_pane) { michael@0: doc.body.appendChild(debugPane); michael@0: } michael@0: michael@0: /* Create the filter fields */ michael@0: style = {"cssText": "width: 33%; display: inline; font: " + this.logFont}; michael@0: michael@0: updatetree(levelFilterField, { michael@0: "value": "FATAL|ERROR|WARNING|INFO|DEBUG", michael@0: "onkeypress": filterOnEnter, michael@0: "style": style michael@0: }); michael@0: debugPane.appendChild(levelFilterField); michael@0: michael@0: updatetree(infoFilterField, { michael@0: "value": ".*", michael@0: "onkeypress": filterOnEnter, michael@0: "style": style michael@0: }); michael@0: debugPane.appendChild(infoFilterField); michael@0: michael@0: /* Create the buttons */ michael@0: style = "width: 8%; display:inline; font: " + this.logFont; michael@0: michael@0: filterButton.appendChild(doc.createTextNode("Filter")); michael@0: filterButton.onclick = bind("buildAndApplyFilter", this); michael@0: filterButton.style.cssText = style; michael@0: debugPane.appendChild(filterButton); michael@0: michael@0: loadButton.appendChild(doc.createTextNode("Load")); michael@0: loadButton.onclick = loadMessages; michael@0: loadButton.style.cssText = style; michael@0: debugPane.appendChild(loadButton); michael@0: michael@0: clearButton.appendChild(doc.createTextNode("Clear")); michael@0: clearButton.onclick = clearMessages; michael@0: clearButton.style.cssText = style; michael@0: debugPane.appendChild(clearButton); michael@0: michael@0: closeButton.appendChild(doc.createTextNode("Close")); michael@0: closeButton.onclick = closePane; michael@0: closeButton.style.cssText = style; michael@0: debugPane.appendChild(closeButton); michael@0: michael@0: /* Create the logging pane */ michael@0: logPaneArea.style.cssText = "overflow: auto; width: 100%"; michael@0: logPane.style.cssText = "width: 100%; height: " + (inline ? "8em" : "100%"); michael@0: michael@0: logPaneArea.appendChild(logPane); michael@0: debugPane.appendChild(logPaneArea); michael@0: michael@0: this.buildAndApplyFilter(); michael@0: loadMessages(); michael@0: michael@0: if (inline) { michael@0: this.win = undefined; michael@0: } else { michael@0: this.win = win; michael@0: } michael@0: this.inline = inline; michael@0: this.closePane = closePane; michael@0: this.closed = false; michael@0: michael@0: michael@0: return this; michael@0: }; michael@0: michael@0: MochiKit.LoggingPane.LoggingPane.prototype = { michael@0: "logFont": "8pt Verdana,sans-serif", michael@0: "colorTable": { michael@0: "ERROR": "red", michael@0: "FATAL": "darkred", michael@0: "WARNING": "blue", michael@0: "INFO": "black", michael@0: "DEBUG": "green" michael@0: } michael@0: }; michael@0: michael@0: michael@0: MochiKit.LoggingPane.EXPORT_OK = [ michael@0: "LoggingPane" michael@0: ]; michael@0: michael@0: MochiKit.LoggingPane.EXPORT = [ michael@0: "createLoggingPane" michael@0: ]; michael@0: michael@0: MochiKit.LoggingPane.__new__ = function () { michael@0: this.EXPORT_TAGS = { michael@0: ":common": this.EXPORT, michael@0: ":all": MochiKit.Base.concat(this.EXPORT, this.EXPORT_OK) michael@0: }; michael@0: michael@0: MochiKit.Base.nameFunctions(this); michael@0: michael@0: MochiKit.LoggingPane._loggingPane = null; michael@0: michael@0: }; michael@0: michael@0: MochiKit.LoggingPane.__new__(); michael@0: michael@0: MochiKit.Base._exportSymbols(this, MochiKit.LoggingPane);