Zapatec Utils

log4js.js

Summary

Javascript Logger (in the spirit of log4j) This library is designed to make the writing and debugging of javascript code easier, by allowing the programmer to perform debug or log output at any place in their code. This supports the concept of different levels of logging (debug < info < warn < error < fatal << none) as well as different log outputs. Three log outputs are included, but you can add your own. The included log outputs are Log.writeLogger(), Log.alertLogger(), and Log.popupLogger(). For debugging on Safari, the log ouput Log.consoleLogger() is also included. To turn off debugging but still leave the logger calls in your script, use the log level Log.NONE. Example usage:

 <html>
  <head>
      <script src="log4js.js" type="text/javascript"></script>
  </head>
  <body>
     Log4JS test...<hr/>
     <script>
        // Setup log objects
        //
        //  log object of priority debug and the popup logger
        var log = new Log(Log.DEBUG, Log.popupLogger);
        //  log object of priority warn and the alert logger
        var log2 = new Log(Log.WARN, Log.alertLogger);
        //  log object of priority debug and the console logger (Safari)
        var log3 = new Log(Log.DEBUG, Log.consoleLogger);

        log.debug('foo1');     // will popup a new window and log 'foo'
        log.warn('bar1');      // will add a new 'bar' message to the popup
        log2.debug('foo2');    // will do nothing (Log object's priority threshold is WARN)
        log2.warn('bar2');     // will display a javascript alert with the string 'bar'
        log3.debug('foo3');    // will log message to Safari console or existing popup
        log3.warn('bar3');     // same

 	      log.info(Log.dumpObject(new Array('apple','pear','orange','banana')));
     </script>
  </body>
 </html>
 


Version: 0.3
*************************************************************

 Copyright 2005 Fourspaces Consulting, LLC

 Licensed under the Apache License, Version 2.0 (the "License"); 
 you may not use this file except in compliance with the License. 
 You may obtain a copy of the License at 

 http://www.apache.org/licenses/LICENSE-2.0 

 Unless required by applicable law or agreed to in writing, software 
 distributed under the License is distributed on an "AS IS" BASIS, 
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 See the License for the specific language governing permissions and 
 limitations under the License

*************************************************************

 Changelog:
 0.2 	- Added consoleLogger for Safari
 		- Changed popupLogger so that it only notifies once (or twice)
		  that a popup blocker is active.	
		- Added Log.NONE level for silencing all logging
 


Author: Marcus R Breese mailto:mbreese@fourspaces.com


Class Summary
Log The main Log class.

// $Id: log4js.js 7554 2007-07-15 17:54:14Z alex $
/*
 * <pre>
 * Copyright (c) 2004-2006 by Zapatec, Inc.
 * http://www.zapatec.com
 * 1700 MLK Way, Berkeley, California,
 * 94709, U.S.A.
 * All rights reserved.
 * </pre>
 */

/**
 * @fileoverview Javascript Logger (in the spirit of log4j)
 * This library is designed to make the writing and debugging
 * of javascript code easier, by allowing the programmer to perform
 * debug or log output at any place in their code.  This supports
 * the concept of different levels of logging (debug < info < warn < error < fatal << none)
 * as well as different log outputs.  Three log outputs are included, but you can
 * add your own.  The included log outputs are {@link Log#writeLogger},
 * {@link Log#alertLogger}, and {@link Log#popupLogger}.  For debugging on Safari,
 * the log ouput {@link Log#consoleLogger} is also included.  To turn off debugging
 * but still leave the logger calls in your script, use the log level {@link Log#NONE}.
 *
 * Example usage:
 * <pre>
 * &lt;html&gt;
 *  &lt;head&gt;
 *      &lt;script src="log4js.js" type="text/javascript"&gt;&lt;/script&gt;
 *  &lt;/head&gt;
 *  &lt;body&gt;
 *     Log4JS test...&lt;hr/&gt;
 *     &lt;script&gt;
 *        // Setup log objects
 *        //
 *        //  log object of priority debug and the popup logger
 *        var log = new Log(Log.DEBUG, Log.popupLogger);
 *        //  log object of priority warn and the alert logger
 *        var log2 = new Log(Log.WARN, Log.alertLogger);
 *        //  log object of priority debug and the console logger (Safari)
 *        var log3 = new Log(Log.DEBUG, Log.consoleLogger);
 *
 *        log.debug('foo1');     // will popup a new window and log 'foo'
 *        log.warn('bar1');      // will add a new 'bar' message to the popup
 *        log2.debug('foo2');    // will do nothing (Log object's priority threshold is WARN)
 *        log2.warn('bar2');     // will display a javascript alert with the string 'bar'
 *        log3.debug('foo3');    // will log message to Safari console or existing popup
 *        log3.warn('bar3');     // same
 *
 * 	      log.info(Log.dumpObject(new Array('apple','pear','orange','banana')));
 *     &lt;/script&gt;
 *  &lt;/body&gt;
 * &lt;/html&gt;
 * </pre>
 *
 * @author Marcus R Breese mailto:mbreese@fourspaces.com
 * @license Apache License 2.0
 * @version 0.3
 *<pre>
 **************************************************************
 *
 * Copyright 2005 Fourspaces Consulting, LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at 
 *
 * http://www.apache.org/licenses/LICENSE-2.0 
 *
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
 * limitations under the License
 *
 **************************************************************
 *
 * Changelog:
 * 0.2 	- Added consoleLogger for Safari
 * 		- Changed popupLogger so that it only notifies once (or twice)
 *		  that a popup blocker is active.	
 *		- Added Log.NONE level for silencing all logging
 * </pre>
 */



/**
 * Create a new logger
 * @constructor
 * @class The main Log class.  Create a new instance of this class to send all logging events.
 * @param level The cut-off logger level.  You can adjust this level in the constructor and leave all other logging events in place.  Defaults to {@link Log#WARN}.
 * @param logger The logger to use.  The logger is a function that accepts the logging events and informs the user or developer. Defaults to {@link Log#writeLogger}.
 */
function Log(level,logger,prefix) {
			 var _currentLevel = Log.WARN;
			 var _logger = Log.writeLogger; // default to write Logger
			 var _prefix = false;
			 /**
				* Sets the current logger prefix 
				* @param {String} prefix This prefix will be prepended to all messages.
				*/
			 this.setPrefix = function(pre) {
					 if (pre!='undefined') { _prefix = pre; }
		 else { _prefix = false; }
			 }
			 /**
				* Sets the current logger function
				* @param logger The function that will be called when a log event needs to be displayed
				*/
			 this.setLogger = function(logger) {
					 if (logger!='undefined') { _logger = logger; }
			 }

			 /**
				* Sets the current threshold log level for this Log instance.  Only events that have a priority of this level or greater are logged.
				* @param level The new threshold priority level for logging events.  This can be one of the static members {@link Log#DEBUG},  {@link Log#INFO}, {@link Log#WARN}, {@link Log#ERROR}, {@link Log#FATAL}, {@link Log#NONE}, or it can be one of the strings ["debug", "info", "warn", "error", "fatal", "none"].
				*/
			 this.setLevel = function(level) { 
					 if (level!='undefined' && typeof level =='number') {
									 _currentLevel = level;
					 } else if (level!='undefined') {
									 if (level=='debug') { _currentLevel = Log.DEBUG; }
									 else if (level=='info') { _currentLevel = Log.INFO; }
									 else if (level=='error') { _currentLevel = Log.ERROR; }
									 else if (level=='fatal') { _currentLevel = Log.FATAL; }
									 else if (level=='warn') { _currentLevel = Log.WARN; }
									 else { _currentLevel = Log.NONE; }
					 }
			 }

			 /**
				* Gets the current prefix
	* @return current prefix
	*/
			 
			 this.getPrefix = function() { return _prefix; }

			 /**
				* Gets the current event logger function
	* @return current logger
	*/
			 
			 this.getLogger = function() { return _logger; }

			 /**
				* Gets the current threshold priority level
	* @return current level
	*/
			 
			 this.getLevel = function() { return _currentLevel; }
			 
			 if (level!='undefined') { this.setLevel(level); }
			 if (logger!='undefined') { this.setLogger(logger); }
			 if (prefix!='undefined') { this.setPrefix(prefix); }
}
/**
 * Log an event with priority of "debug"
 * @param s the log message
 */
Log.prototype.debug     = function(s) { if (this.getLevel()<=Log.DEBUG) { this._log(s,"DEBUG",this); } }

Log.prototype.json = function(s) {
	if (Zapatec && Zapatec.Transport) {
		this.debug(Zapatec.Transport.serializeJsonObj(s));
	}
}

/**
 * Log an event with priority of "info"
 * @param s the log message
 */
Log.prototype.info      = function(s) { if (this.getLevel()<=Log.INFO ) { this._log(s,"INFO",this); } }
/**
 * Log an event with priority of "warn"
 * @param s the log message
 */
Log.prototype.warn      = function(s) { if (this.getLevel()<=Log.WARN ) { this._log(s,"WARN",this); } }
/**
 * Log an event with priority of "error"
 * @param s the log message
 */
Log.prototype.error     = function(s) { if (this.getLevel()<=Log.ERROR) { this._log(s,"ERROR",this); } }
/**
 * Log an event with priority of "fatal" 
 * @param s the log message
 */
Log.prototype.fatal     = function(s) { if (this.getLevel()<=Log.FATAL) { this._log(s,"FATAL",this); } }

/**
 * _log is the function that actually calling the configured logger function.
 * It is possible that this function could be extended to allow for more
 * than one logger.
 * 
 * This method is used by {@link Log#debug}, {@link Log#info}, {@link Log#warn}, {@link Log#error}, and {@link Log#fatal}
 * @private
 * @param {String} msg The message to display
 * @param level The priority level of this log event
 * @param {Log} obj The originating {@link Log} object.
 */
Log.prototype._log = function(msg,level,obj) { 
	if (this.getPrefix()) {
		this.getLogger()(this.getPrefix()+" - "+msg,level,obj); 
	} else {
		this.getLogger()(msg,level,obj); 
	}

}

Log.DEBUG       = 1;
Log.INFO        = 2;
Log.WARN        = 3;
Log.ERROR       = 4;
Log.FATAL       = 5;
Log.NONE		= 6;

/**
 * Static alert logger method.  This logger will display a javascript alert (messagebox) with the message.
 * @param {String} msg The message to display
 * @param level The priority level of this log event
 */
Log.alertLogger = function(msg,level) { alert(level+" - "+msg); }
/**
 * Static write logger method.  This logger will print the message out to the web page using document.writeln.
 * @param {String} msg The message to display
 * @param level The priority level of this log event
 */
Log.writeLogger = function(msg,level) { document.writeln(level+"&nbsp;-&nbsp;"+msg+"<br/>"); }


/**
 * Static Safari WebKit console logger method. This logger will write messages to the Safari javascript console, if available.
 * If this browser doesn't have a javascript console (IE/Moz), then it degrades gracefully to {@link Log#popupLogger}
 * @param {String} msg The message to display
 * @param level The priority level of this log event
 * @param {Log} obj The originating {@link Log} object.
 */
Log.consoleLogger = function(msg,level,obj) {
	if (window.console) {
		window.console.log(level+" - "+msg);
	} else {
		Log.popupLogger(msg,level,obj);
	}
}
 

/**
 * Static popup logger method.  This logger will popup a new window (if necessary), and add the log message to the top of a list.
 * @param {String} msg The message to display
 * @param level The priority level of this log event
 * @param {Log} obj The originating {@link Log} object.
 */
Log.popupLogger = function(msg,level,obj) {
			 if (obj.popupBlocker) {
	return;
			 }
			 if (!obj._window || !obj._window.document) {
							 obj._window = window.open("",'logger_popup_window');
							 if (!obj._window) { obj.popupBlocker=true; alert("You have a popup window manager blocking the log4js log popup display.\n\nThis must be disabled to properly see logged events."); return; }
				 if (!obj._window.document.getElementById('loggerTable')) {
											 obj._window.document.writeln("<table width='100%' id='loggerTable'><tr><th align='left'>Time</th><th width='100%' colspan='2' align='left'>Message</th></tr></table>");
											 obj._window.document.close();
							 }
			 }
			 var tbl = obj._window.document.getElementById("loggerTable");
			 var row = tbl.insertRow(1);

			 var cell_1 = row.insertCell(-1);
			 var cell_2 = row.insertCell(-1);
			 var cell_3 = row.insertCell(-1);

			 var d = new Date();
			 var h = d.getHours();
			 if (h<10) { h="0"+h; }
			 var m = d.getMinutes();
			 if (m<10) { m="0"+m; }
			 var s = d.getSeconds();
			 if (s<10) { s="0"+s; }
			 var date = (d.getMonth()+1)+"/"+d.getDate()+"/"+d.getFullYear()+"&nbsp;-&nbsp;"+h+":"+m+":"+s;

			 cell_1.style.fontSize="8pt";
			 cell_1.style.fontWeight="bold";
			 cell_1.style.paddingRight="6px";
			 
			 cell_2.style.fontSize="8pt";
			 
			 cell_3.style.fontSize="8pt";
			 cell_3.style.whiteSpace="nowrap";
			 cell_3.style.width="100%";

			 if (tbl.rows.length % 2 == 0) {
				cell_1.style.backgroundColor="#eeeeee";
				cell_2.style.backgroundColor="#eeeeee";
				cell_3.style.backgroundColor="#eeeeee";
			 }
			 
			 cell_1.innerHTML=date
			 cell_2.innerHTML=level;
			 cell_3.innerHTML=msg;
}

/**
 * This method is a utility function that takes an object and creates a string representation of it's members.
 * @param {Object} the Object that you'd like to see
 * @return {String} a String representation of the object passed
 */
Log.dumpObject=function (obj,indent) {
	if (!indent) { indent="";}
	if (indent.length>20) { return ; } // don't go too far...
	var s="{\n";
		for (var p in obj) {
			s+=indent+p+":";
			var type=typeof(obj[p]);
			type=type.toLowerCase();
			if (type=='object') {
				s+= Log.dumpObject(obj[p],indent+"----");
			} else {
				s+= obj[p];
			}
			s+="\n";
		}
		s+=indent+"}";
		return s;
}


/**
 * This method will set the properties for the zpdumpObject config
 * @param {Object} the Object to tune the dump of an object
 */
Log.zpdumpObject_config=function(objArgs) {

config={}
config.indent="&nbsp;&nbsp;&nbsp;"
config.depth=1;
config.maxdepth=10;
config.objSkip={}
config.objSkip['function']=true
// Show the value of the variable?
config.bShowValues=true
// Show the type of the variable
config.bShowType=true
// Skip empty values, empty string, 
config.bSkipEmpty=true
// Skip undefined
config.bSkipUndefined=true
config.bHtml=true
if (objArgs)
	for (var i in objArgs) 
		if (config[i] == 'undefined')
			alert(i + ' is not a valid option')
		else
			config[i]=objArgs[i]

return config
}

/*
 * Recursive function to dump the object
 * @param {obj}   - object to dump
 * @param {name}  - name of object
 * @param {configIn} - object to tune the dump of this object
*/
Log.zpdumpObject=function(obj, name, configIn) {

var config=Log.zpdumpObject_config(configIn)

var self=this
var strEOL=config.bHtml ? "<br>" : '\n'
var strIndent=config.bHtml ? "&nbsp;&nbsp;&nbsp;" : '\t'

//----------------------------------------------------------------------------
//--- RECURSIVE FUNCTION ---
var funcRecurse=function(obj, name, depth, indent) {

var strName, strVal, strType, strOut
if (depth > config.maxdepth)
	return indent + name + ": <Maximum Depth Reached>" + strEOL;

if (typeof obj == "object") {
	var child = null;
	var output = (indent + name)
	if (config.bShowType)
		output+=' (' + typeof obj + ')'
	output+=strEOL

	indent += strIndent
	for (var item in obj) {

	try {
		child = obj[item];
	} catch (e) {
		child = "<Unable to Evaluate>";
	}

	strName=name+'.'+item
	strType=typeof child
	strOut = indent + strName 
	if (config.bShowType)
		strOut += ' ('+strType+')'

	if (strType=='object') 
		output += funcRecurse(child, strName, depth + 1, indent);
	else 
	if (config.objSkip[strType] != true) 
	{
		if (config.bShowValues)
		{
			if (config.bSkipEmpty && !child)
				// Skip properties that has 'empty' values
				;
			else
			if (config.bSkipUndefined && strType == 'undefined')
				// Skip properties that has undefined values
				;
			else
				output += strOut + "=" + child + strEOL;
		}
		else
				output += strOut + strEOL;
	} // end not objSkip

} // end for

return output;
} 
else // NOT object, just return the value
{
	return obj;
}
} // end recurse
//--- END RECURSIVE FUNCTION ---
//----------------------------------------------------------------------------

return funcRecurse(obj, name, 1, '')
}

// Makes your life easier
var log = new Log(Log.DEBUG, Log.popupLogger);

Zapatec Utils

Documentation generated by JSDoc on Thu Aug 16 12:18:39 2007