Project

General

Profile

1
/**
2
 * @fileoverview Javascript Logger (in the spirit of log4j)
3
 * This library is designed to make the writing and debugging
4
 * of javascript code easier, by allowing the programmer to perform
5
 * debug or log output at any place in their code.  This supports
6
 * the concept of different levels of logging (debug < info < warn < error < fatal << none)
7
 * as well as different log outputs.  Three log outputs are included, but you can
8
 * add your own.  The included log outputs are {@link Log#writeLogger},
9
 * {@link Log#alertLogger}, and {@link Log#popupLogger}.  For debugging on Safari,
10
 * the log ouput {@link Log#consoleLogger} is also included.  To turn off debugging
11
 * but still leave the logger calls in your script, use the log level {@link Log#NONE}.
12
 *
13
 * Example usage:
14
 * <pre>
15
 * &lt;html&gt;
16
 *  &lt;head&gt;
17
 *      &lt;script src="log4js.js" type="text/javascript"&gt;&lt;/script&gt;
18
 *  &lt;/head&gt;
19
 *  &lt;body&gt;
20
 *     Log4JS test...&lt;hr/&gt;
21
 *     &lt;script&gt;
22
 *        // Setup log objects
23
 *        //
24
 *        //  log object of priority debug and the popup logger
25
 *        var log = new Log(Log.DEBUG, Log.popupLogger);
26
 *        //  log object of priority warn and the alert logger
27
 *        var log2 = new Log(Log.WARN, Log.alertLogger);
28
 *        //  log object of priority debug and the console logger (Safari)
29
 *        var log3 = new Log(Log.DEBUG, Log.consoleLogger);
30
 *
31
 *        log.debug('foo1');     // will popup a new window and log 'foo'
32
 *        log.warn('bar1');      // will add a new 'bar' message to the popup
33
 *        log2.debug('foo2');    // will do nothing (Log object's priority threshold is WARN)
34
 *        log2.warn('bar2');     // will display a javascript alert with the string 'bar'
35
 *        log3.debug('foo3');    // will log message to Safari console or existing popup
36
 *        log3.warn('bar3');     // same
37
 *
38
 * 	      log.info(Log.dumpObject(new Array('apple','pear','orange','banana')));
39
 *     &lt;/script&gt;
40
 *  &lt;/body&gt;
41
 * &lt;/html&gt;
42
 * </pre>
43
 *
44
 * @author Marcus R Breese mailto:mbreese@users.sourceforge.net
45
 * @license Apache License 2.0
46
 * @version 0.31
47
 *<pre>
48
 **************************************************************
49
 *
50
 * Copyright 2005 Fourspaces Consulting, LLC
51
 *
52
 * Licensed under the Apache License, Version 2.0 (the "License"); 
53
 * you may not use this file except in compliance with the License. 
54
 * You may obtain a copy of the License at 
55
 *
56
 * http://www.apache.org/licenses/LICENSE-2.0 
57
 *
58
 * Unless required by applicable law or agreed to in writing, software 
59
 * distributed under the License is distributed on an "AS IS" BASIS, 
60
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
61
 * See the License for the specific language governing permissions and 
62
 * limitations under the License
63
 *
64
 **************************************************************
65
 *
66
 * Changelog:
67
 * 0.31 Bug fix (resizeable should be resizable - Darryl Lyons)
68
 * 0.3  Migrated to SF.net SVN repository - test cleanups
69
 * 0.2 	- Added consoleLogger for Safari
70
 * 		- Changed popupLogger so that it only notifies once (or twice)
71
 *		  that a popup blocker is active.	
72
 *		- Added Log.NONE level for silencing all logging
73
 * </pre>
74
 */
75

    
76

    
77

    
78
/**
79
 * Create a new logger
80
 * @constructor
81
 * @class The main Log class.  Create a new instance of this class to send all logging events.
82
 * @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}.
83
 * @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}.
84
 */
85
function Log(level,logger,prefix) {
86
       var _currentLevel = Log.WARN;
87
       var _logger = Log.writeLogger; // default to write Logger
88
       var _prefix = false;
89
       /**
90
        * Sets the current logger prefix 
91
        * @param {String} prefix This prefix will be prepended to all messages.
92
        */
93
       this.setPrefix = function(pre) {
94
           if (pre!='undefined') { _prefix = pre; }
95
	   else { _prefix = false; }
96
       }
97
       /**
98
        * Sets the current logger function
99
        * @param logger The function that will be called when a log event needs to be displayed
100
        */
101
       this.setLogger = function(logger) {
102
           if (logger!='undefined') { _logger = logger; }
103
       }
104

    
105
       /**
106
        * Sets the current threshold log level for this Log instance.  Only events that have a priority of this level or greater are logged.
107
        * @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"].
108
        */
109
       this.setLevel = function(level) { 
110
           if (level!='undefined' && typeof level =='number') {
111
                   _currentLevel = level;
112
           } else if (level!='undefined') {
113
                   if (level=='debug') { _currentLevel = Log.DEBUG; }
114
                   else if (level=='info') { _currentLevel = Log.INFO; }
115
                   else if (level=='error') { _currentLevel = Log.ERROR; }
116
                   else if (level=='fatal') { _currentLevel = Log.FATAL; }
117
                   else if (level=='warn') { _currentLevel = Log.WARN; }
118
                   else { _currentLevel = Log.NONE; }
119
           }
120
       }
121

    
122
       /**
123
        * Gets the current prefix
124
	* @return current prefix
125
	*/
126
       
127
       this.getPrefix = function() { return _prefix; }
128

    
129
       /**
130
        * Gets the current event logger function
131
	* @return current logger
132
	*/
133
       
134
       this.getLogger = function() { return _logger; }
135

    
136
       /**
137
        * Gets the current threshold priority level
138
	* @return current level
139
	*/
140
       
141
       this.getLevel = function() { return _currentLevel; }
142
       
143
       if (level!='undefined') { this.setLevel(level); }
144
       if (logger!='undefined') { this.setLogger(logger); }
145
       if (prefix!='undefined') { this.setPrefix(prefix); }
146
}
147
/**
148
 * Log an event with priority of "debug"
149
 * @param s the log message
150
 */
151
Log.prototype.debug     = function(s) { if (this.getLevel()<=Log.DEBUG) { this._log(s,"DEBUG",this); } }
152
/**
153
 * Log an event with priority of "info"
154
 * @param s the log message
155
 */
156
Log.prototype.info      = function(s) { if (this.getLevel()<=Log.INFO ) { this._log(s,"INFO",this); } }
157
/**
158
 * Log an event with priority of "warn"
159
 * @param s the log message
160
 */
161
Log.prototype.warn      = function(s) { if (this.getLevel()<=Log.WARN ) { this._log(s,"WARN",this); } }
162
/**
163
 * Log an event with priority of "error"
164
 * @param s the log message
165
 */
166
Log.prototype.error     = function(s) { if (this.getLevel()<=Log.ERROR) { this._log(s,"ERROR",this); } }
167
/**
168
 * Log an event with priority of "fatal" 
169
 * @param s the log message
170
 */
171
Log.prototype.fatal     = function(s) { if (this.getLevel()<=Log.FATAL) { this._log(s,"FATAL",this); } }
172

    
173
/**
174
 * _log is the function that actually calling the configured logger function.
175
 * It is possible that this function could be extended to allow for more
176
 * than one logger.
177
 * 
178
 * This method is used by {@link Log#debug}, {@link Log#info}, {@link Log#warn}, {@link Log#error}, and {@link Log#fatal}
179
 * @private
180
 * @param {String} msg The message to display
181
 * @param level The priority level of this log event
182
 * @param {Log} obj The originating {@link Log} object.
183
 */
184
Log.prototype._log = function(msg,level,obj) { 
185
	if (this.getPrefix()) {
186
		this.getLogger()(this.getPrefix()+" - "+msg,level,obj); 
187
	} else {
188
		this.getLogger()(msg,level,obj); 
189
	}
190

    
191
}
192

    
193
Log.DEBUG       = 1;
194
Log.INFO        = 2;
195
Log.WARN        = 3;
196
Log.ERROR       = 4;
197
Log.FATAL       = 5;
198
Log.NONE		= 6;
199

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

    
213

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

    
230
/**
231
 * Static popup logger method.  This logger will popup a new window (if necessary), and add the log message to the end of a list.
232
 * @param {String} msg The message to display
233
 * @param level The priority level of this log event
234
 * @param {Log} obj The originating {@link Log} object.
235
 */
236
Log.popupLogger = function(msg,level,obj) {
237
       if (obj.popupBlocker) {
238
	return;
239
       }
240
       if (!obj._window || !obj._window.document) {
241
               obj._window = window.open("",'logger_popup_window','width=420,height=320,scrollbars=1,status=0,toolbars=0,resizable=1');
242
               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; }
243
	       if (!obj._window.document.getElementById('loggerTable')) {
244
                       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>");
245
                       obj._window.document.close();
246
               }
247
       }
248
       var tbl = obj._window.document.getElementById("loggerTable");
249
       var row = tbl.insertRow(-1);
250

    
251
       var cell_1 = row.insertCell(-1);
252
       var cell_2 = row.insertCell(-1);
253
       var cell_3 = row.insertCell(-1);
254

    
255
       var d = new Date();
256
       var h = d.getHours();
257
       if (h<10) { h="0"+h; }
258
       var m = d.getMinutes();
259
       if (m<10) { m="0"+m; }
260
       var s = d.getSeconds();
261
       if (s<10) { s="0"+s; }
262
       var date = (d.getMonth()+1)+"/"+d.getDate()+"/"+d.getFullYear()+"&nbsp;-&nbsp;"+h+":"+m+":"+s;
263

    
264
       cell_1.style.fontSize="8pt";
265
       cell_1.style.fontWeight="bold";
266
       cell_1.style.paddingRight="6px";
267
       
268
       cell_2.style.fontSize="8pt";
269
       
270
       cell_3.style.fontSize="8pt";
271
       cell_3.style.whiteSpace="nowrap";
272
       cell_3.style.width="100%";
273

    
274
       if (tbl.rows.length % 2 == 0) {
275
       	cell_1.style.backgroundColor="#eeeeee";
276
       	cell_2.style.backgroundColor="#eeeeee";
277
       	cell_3.style.backgroundColor="#eeeeee";
278
       }
279
       
280
       cell_1.innerHTML=date
281
       cell_2.innerHTML=level;
282
       cell_3.innerHTML=msg;
283
}
284

    
285
/**
286
 * This method is a utility function that takes an object and creates a string representation of it's members.
287
 * @param {Object} the Object that you'd like to see
288
 * @return {String} a String representation of the object passed
289
 */
290
Log.dumpObject=function (obj,indent) {
291
	if (!indent) { indent="";}
292
	if (indent.length>20) { return ; } // don't go too far...
293
	var s="{\n";
294
		for (var p in obj) {
295
			s+=indent+p+":";
296
			var type=typeof(obj[p]);
297
			type=type.toLowerCase();
298
			if (type=='object') {
299
				s+= Log.dumpObject(obj[p],indent+"----");
300
			} else {
301
				s+= obj[p];
302
			}
303
			s+="\n";
304
		}
305
		s+=indent+"}";
306
		return s;
307
}
308

    
(7-7/16)