@qooxdoo/framework
Version:
The JS Framework for Coders
373 lines (297 loc) • 10.3 kB
JavaScript
/* ************************************************************************
qooxdoo - the new era of web development
http://qooxdoo.org
Copyright:
2004-2008 1&1 Internet AG, Germany, http://www.1und1.de
License:
MIT: https://opensource.org/licenses/MIT
See the LICENSE file in the project's top-level directory for details.
Authors:
* Sebastian Werner (wpbasti)
************************************************************************ */
/**
* Feature-rich console appender for the qooxdoo logging system.
*
* Creates a small inline element which is placed in the top-right corner
* of the window. Prints all messages with a nice color highlighting.
*
* * Allows user command inputs.
* * Command history enabled by default (Keyboard up/down arrows).
* * Lazy creation on first open.
* * Clearing the console using a button.
* * Display of offset (time after loading) of each message
* * Supports keyboard shortcuts F7 or Ctrl+D to toggle the visibility
*
* Note this class must be disposed of after use
*
* @require(qx.event.handler.Window)
* @require(qx.event.handler.Keyboard)
* @require(qx.event.handler.Gesture)
*/
qx.Class.define("qx.log.appender.Console",
{
statics :
{
/*
---------------------------------------------------------------------------
INITIALIZATION AND SHUTDOWN
---------------------------------------------------------------------------
*/
__main : null,
__log : null,
__cmd : null,
__lastCommand : null,
/**
* Initializes the console, building HTML and pushing last
* log messages to the output window.
*
*/
init : function()
{
// Build style sheet content
var style =
[
'.qxconsole{z-index:10000;width:600px;height:300px;top:0px;right:0px;position:absolute;border-left:1px solid black;color:black;border-bottom:1px solid black;color:black;font-family:Consolas,Monaco,monospace;font-size:11px;line-height:1.2;}',
'.qxconsole .control{background:#cdcdcd;border-bottom:1px solid black;padding:4px 8px;}',
'.qxconsole .control a{text-decoration:none;color:black;}',
'.qxconsole .messages{background:white;height:100%;width:100%;overflow:auto;}',
'.qxconsole .messages div{padding:0px 4px;}',
'.qxconsole .messages .user-command{color:blue}',
'.qxconsole .messages .user-result{background:white}',
'.qxconsole .messages .user-error{background:#FFE2D5}',
'.qxconsole .messages .level-debug{background:white}',
'.qxconsole .messages .level-info{background:#DEEDFA}',
'.qxconsole .messages .level-warn{background:#FFF7D5}',
'.qxconsole .messages .level-error{background:#FFE2D5}',
'.qxconsole .messages .level-user{background:#E3EFE9}',
'.qxconsole .messages .type-string{color:black;font-weight:normal;}',
'.qxconsole .messages .type-number{color:#155791;font-weight:normal;}',
'.qxconsole .messages .type-boolean{color:#15BC91;font-weight:normal;}',
'.qxconsole .messages .type-array{color:#CC3E8A;font-weight:bold;}',
'.qxconsole .messages .type-map{color:#CC3E8A;font-weight:bold;}',
'.qxconsole .messages .type-key{color:#565656;font-style:italic}',
'.qxconsole .messages .type-class{color:#5F3E8A;font-weight:bold}',
'.qxconsole .messages .type-instance{color:#565656;font-weight:bold}',
'.qxconsole .messages .type-stringify{color:#565656;font-weight:bold}',
'.qxconsole .command{background:white;padding:2px 4px;border-top:1px solid black;}',
'.qxconsole .command input{width:100%;border:0 none;font-family:Consolas,Monaco,monospace;font-size:11px;line-height:1.2;}',
'.qxconsole .command input:focus{outline:none;}'
];
// Include stylesheet
qx.bom.Stylesheet.createElement(style.join(""));
// Build markup
var markup =
[
'<div class="qxconsole">',
'<div class="control"><a href="javascript:qx.log.appender.Console.clear()">Clear</a> | <a href="javascript:qx.log.appender.Console.toggle()">Hide</a></div>',
'<div class="messages">',
'</div>',
'<div class="command">',
'<input type="text"/>',
'</div>',
'</div>'
];
// Insert HTML to access DOM node
var wrapper = document.createElement("DIV");
wrapper.innerHTML = markup.join("");
var main = wrapper.firstChild;
document.body.appendChild(wrapper.firstChild);
// Make important DOM nodes available
this.__main = main;
this.__log = main.childNodes[1];
this.__cmd = main.childNodes[2].firstChild;
// Correct height of messages frame
this.__onResize();
// Finally register to log engine
qx.log.Logger.register(this);
// Register to object manager
qx.core.ObjectRegistry.register(this);
},
/**
* Used by the object registry to dispose this instance e.g. remove listeners etc.
*
*/
dispose : function()
{
qx.event.Registration.removeListener(document.documentElement, "keypress", this.__onKeyPress, this);
qx.log.Logger.unregister(this);
},
/*
---------------------------------------------------------------------------
INSERT & CLEAR
---------------------------------------------------------------------------
*/
/**
* Clears the current console output.
*
*/
clear : function()
{
// Remove all messages
this.__log.innerHTML = "";
},
/**
* Processes a single log entry
*
* @signature function(entry)
* @param entry {Map} The entry to process
*/
process : function(entry)
{
// Append new content
this.__log.appendChild(qx.log.appender.Util.toHtml(entry));
// Scroll down
this.__scrollDown();
},
/**
* Automatically scroll down to the last line
*/
__scrollDown : function() {
this.__log.scrollTop = this.__log.scrollHeight;
},
/*
---------------------------------------------------------------------------
VISIBILITY TOGGLING
---------------------------------------------------------------------------
*/
/** @type {Boolean} Flag to store last visibility status */
__visible : true,
/**
* Toggles the visibility of the console between visible and hidden.
*
*/
toggle : function()
{
if (!this.__main)
{
this.init();
}
else if (this.__main.style.display == "none")
{
this.show();
}
else
{
this.__main.style.display = "none";
}
},
/**
* Shows the console.
*
*/
show : function()
{
if (!this.__main) {
this.init();
} else {
this.__main.style.display = "block";
this.__log.scrollTop = this.__log.scrollHeight;
}
},
/*
---------------------------------------------------------------------------
COMMAND LINE SUPPORT
---------------------------------------------------------------------------
*/
/** @type {Array} List of all previous commands. */
__history : [],
/**
* Executes the currently given command
*
*/
execute : function()
{
var value = this.__cmd.value;
if (value == "") {
return;
}
if (value == "clear") {
this.clear();
return;
}
var command = document.createElement("div");
command.innerHTML = qx.log.appender.Util.escapeHTML(">>> " + value);
command.className = "user-command";
this.__history.push(value);
this.__lastCommand = this.__history.length;
this.__log.appendChild(command);
this.__scrollDown();
try {
var ret = window.eval(value);
}
catch (ex) {
qx.log.Logger.error(ex);
}
if (ret !== undefined) {
qx.log.Logger.debug(ret);
}
},
/*
---------------------------------------------------------------------------
EVENT LISTENERS
---------------------------------------------------------------------------
*/
/**
* Event handler for resize listener
*
* @param e {Event} Event object
*/
__onResize : function(e) {
this.__log.style.height = (this.__main.clientHeight - this.__main.firstChild.offsetHeight - this.__main.lastChild.offsetHeight) + "px";
},
/**
* Event handler for keydown listener
*
* @param e {Event} Event object
*/
__onKeyPress : function(e)
{
if (e instanceof qx.event.type.Tap || e instanceof qx.event.type.Pointer) {
var target = e.getTarget();
if (target && target.className && target.className.indexOf && target.className.indexOf("navigationbar") != -1) {
this.toggle();
}
return;
}
var iden = e.getKeyIdentifier();
// Console toggling
if ((iden == "F7") || (iden == "D" && e.isCtrlPressed()))
{
this.toggle();
e.preventDefault();
}
// Not yet created
if (!this.__main) {
return;
}
// Active element not in console
if (!qx.dom.Hierarchy.contains(this.__main, e.getTarget())) {
return;
}
// Command execution
if (iden == "Enter" && this.__cmd.value != "")
{
this.execute();
this.__cmd.value = "";
}
// History management
if (iden == "Up" || iden == "Down")
{
this.__lastCommand += iden == "Up" ? -1 : 1;
this.__lastCommand = Math.min(Math.max(0, this.__lastCommand), this.__history.length);
var entry = this.__history[this.__lastCommand];
this.__cmd.value = entry || "";
this.__cmd.select();
}
}
},
/*
*****************************************************************************
DEFER
*****************************************************************************
*/
defer : function(statics) {
qx.event.Registration.addListener(document.documentElement, "keypress", statics.__onKeyPress, statics);
qx.event.Registration.addListener(document.documentElement, "longtap", statics.__onKeyPress, statics);
}
});