- // ==UserScript==
- // @name log4javascript
- // @namespace Tim Down
- // @description log4javascript is a logging framework for JavaScript based on log4j
- // @copyright 2014 Tim Down
- // @version 1.4.11
- // @source http://log4javascript.org
- // @license Apache
- // ==/UserScript==
-
- /**
- * Copyright 2014 Tim Down.
- *
- * 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.
- */
-
- /**
- * log4javascript
- *
- * log4javascript is a logging framework for JavaScript based on log4j
- * for Java. This file contains all core log4javascript code and is the only
- * file required to use log4javascript, unless you require support for
- * document.domain, in which case you will also need console.html, which must be
- * stored in the same directory as the main log4javascript.js file.
- *
- * Author: Tim Down <tim@log4javascript.org>
- * Version: 1.4.11
- * Edition: log4javascript
- * Build date: 19 February 2015
- * Website: http://log4javascript.org
- */
-
- (function(factory, root) {
- if (typeof define == "function" && define.amd) {
- // AMD. Register as an anonymous module.
- define(factory);
- } else if (typeof module != "undefined" && typeof exports == "object") {
- // Node/CommonJS style
- module.exports = factory();
- } else {
- // No AMD or CommonJS support so we place log4javascript in (probably) the global variable
- root.log4javascript = factory();
- }
- })(function() {
- // Array-related stuff. Next three methods are solely for IE5, which is missing them
- if (!Array.prototype.push) {
- Array.prototype.push = function() {
- for (var i = 0, len = arguments.length; i < len; i++){
- this[this.length] = arguments[i];
- }
- return this.length;
- };
- }
-
- if (!Array.prototype.shift) {
- Array.prototype.shift = function() {
- if (this.length > 0) {
- var firstItem = this[0];
- for (var i = 0, len = this.length - 1; i < len; i++) {
- this[i] = this[i + 1];
- }
- this.length = this.length - 1;
- return firstItem;
- }
- };
- }
-
- if (!Array.prototype.splice) {
- Array.prototype.splice = function(startIndex, deleteCount) {
- var itemsAfterDeleted = this.slice(startIndex + deleteCount);
- var itemsDeleted = this.slice(startIndex, startIndex + deleteCount);
- this.length = startIndex;
- // Copy the arguments into a proper Array object
- var argumentsArray = [];
- for (var i = 0, len = arguments.length; i < len; i++) {
- argumentsArray[i] = arguments[i];
- }
- var itemsToAppend = (argumentsArray.length > 2) ?
- itemsAfterDeleted = argumentsArray.slice(2).concat(itemsAfterDeleted) : itemsAfterDeleted;
- for (i = 0, len = itemsToAppend.length; i < len; i++) {
- this.push(itemsToAppend[i]);
- }
- return itemsDeleted;
- };
- }
-
- /* ---------------------------------------------------------------------- */
-
- function isUndefined(obj) {
- return typeof obj == "undefined";
- }
-
- /* ---------------------------------------------------------------------- */
- // Custom event support
-
- function EventSupport() {}
-
- EventSupport.prototype = {
- eventTypes: [],
- eventListeners: {},
- setEventTypes: function(eventTypesParam) {
- if (eventTypesParam instanceof Array) {
- this.eventTypes = eventTypesParam;
- this.eventListeners = {};
- for (var i = 0, len = this.eventTypes.length; i < len; i++) {
- this.eventListeners[this.eventTypes[i]] = [];
- }
- } else {
- handleError("log4javascript.EventSupport [" + this + "]: setEventTypes: eventTypes parameter must be an Array");
- }
- },
-
- addEventListener: function(eventType, listener) {
- if (typeof listener == "function") {
- if (!array_contains(this.eventTypes, eventType)) {
- handleError("log4javascript.EventSupport [" + this + "]: addEventListener: no event called '" + eventType + "'");
- }
- this.eventListeners[eventType].push(listener);
- } else {
- handleError("log4javascript.EventSupport [" + this + "]: addEventListener: listener must be a function");
- }
- },
-
- removeEventListener: function(eventType, listener) {
- if (typeof listener == "function") {
- if (!array_contains(this.eventTypes, eventType)) {
- handleError("log4javascript.EventSupport [" + this + "]: removeEventListener: no event called '" + eventType + "'");
- }
- array_remove(this.eventListeners[eventType], listener);
- } else {
- handleError("log4javascript.EventSupport [" + this + "]: removeEventListener: listener must be a function");
- }
- },
-
- dispatchEvent: function(eventType, eventArgs) {
- if (array_contains(this.eventTypes, eventType)) {
- var listeners = this.eventListeners[eventType];
- for (var i = 0, len = listeners.length; i < len; i++) {
- listeners[i](this, eventType, eventArgs);
- }
- } else {
- handleError("log4javascript.EventSupport [" + this + "]: dispatchEvent: no event called '" + eventType + "'");
- }
- }
- };
-
- /* -------------------------------------------------------------------------- */
-
- var applicationStartDate = new Date();
- var uniqueId = "log4javascript_" + applicationStartDate.getTime() + "_" +
- Math.floor(Math.random() * 100000000);
- var emptyFunction = function() {};
- var newLine = "\r\n";
- var pageLoaded = false;
-
- // Create main log4javascript object; this will be assigned public properties
- function Log4JavaScript() {}
- Log4JavaScript.prototype = new EventSupport();
-
- var log4javascript = new Log4JavaScript();
- log4javascript.version = "1.4.11";
- log4javascript.edition = "log4javascript";
-
- /* -------------------------------------------------------------------------- */
- // Utility functions
-
- function toStr(obj) {
- if (obj && obj.toString) {
- return obj.toString();
- } else {
- return String(obj);
- }
- }
-
- function getExceptionMessage(ex) {
- if (ex.message) {
- return ex.message;
- } else if (ex.description) {
- return ex.description;
- } else {
- return toStr(ex);
- }
- }
-
- // Gets the portion of the URL after the last slash
- function getUrlFileName(url) {
- var lastSlashIndex = Math.max(url.lastIndexOf("/"), url.lastIndexOf("\\"));
- return url.substr(lastSlashIndex + 1);
- }
-
- // Returns a nicely formatted representation of an error
- function getExceptionStringRep(ex) {
- if (ex) {
- var exStr = "Exception: " + getExceptionMessage(ex);
- try {
- if (ex.lineNumber) {
- exStr += " on line number " + ex.lineNumber;
- }
- if (ex.fileName) {
- exStr += " in file " + getUrlFileName(ex.fileName);
- }
- } catch (localEx) {
- logLog.warn("Unable to obtain file and line information for error");
- }
- if (showStackTraces && ex.stack) {
- exStr += newLine + "Stack trace:" + newLine + ex.stack;
- }
- return exStr;
- }
- return null;
- }
-
- function bool(obj) {
- return Boolean(obj);
- }
-
- function trim(str) {
- return str.replace(/^\s+/, "").replace(/\s+$/, "");
- }
-
- function splitIntoLines(text) {
- // Ensure all line breaks are \n only
- var text2 = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
- return text2.split("\n");
- }
-
- var urlEncode = (typeof window.encodeURIComponent != "undefined") ?
- function(str) {
- return encodeURIComponent(str);
- }:
- function(str) {
- return escape(str).replace(/\+/g, "%2B").replace(/"/g, "%22").replace(/'/g, "%27").replace(/\//g, "%2F").replace(/=/g, "%3D");
- };
-
- function array_remove(arr, val) {
- var index = -1;
- for (var i = 0, len = arr.length; i < len; i++) {
- if (arr[i] === val) {
- index = i;
- break;
- }
- }
- if (index >= 0) {
- arr.splice(index, 1);
- return true;
- } else {
- return false;
- }
- }
-
- function array_contains(arr, val) {
- for(var i = 0, len = arr.length; i < len; i++) {
- if (arr[i] == val) {
- return true;
- }
- }
- return false;
- }
-
- function extractBooleanFromParam(param, defaultValue) {
- if (isUndefined(param)) {
- return defaultValue;
- } else {
- return bool(param);
- }
- }
-
- function extractStringFromParam(param, defaultValue) {
- if (isUndefined(param)) {
- return defaultValue;
- } else {
- return String(param);
- }
- }
-
- function extractIntFromParam(param, defaultValue) {
- if (isUndefined(param)) {
- return defaultValue;
- } else {
- try {
- var value = parseInt(param, 10);
- return isNaN(value) ? defaultValue : value;
- } catch (ex) {
- logLog.warn("Invalid int param " + param, ex);
- return defaultValue;
- }
- }
- }
-
- function extractFunctionFromParam(param, defaultValue) {
- if (typeof param == "function") {
- return param;
- } else {
- return defaultValue;
- }
- }
-
- function isError(err) {
- return (err instanceof Error);
- }
-
- if (!Function.prototype.apply){
- Function.prototype.apply = function(obj, args) {
- var methodName = "__apply__";
- if (typeof obj[methodName] != "undefined") {
- methodName += String(Math.random()).substr(2);
- }
- obj[methodName] = this;
-
- var argsStrings = [];
- for (var i = 0, len = args.length; i < len; i++) {
- argsStrings[i] = "args[" + i + "]";
- }
- var script = "obj." + methodName + "(" + argsStrings.join(",") + ")";
- var returnValue = eval(script);
- delete obj[methodName];
- return returnValue;
- };
- }
-
- if (!Function.prototype.call){
- Function.prototype.call = function(obj) {
- var args = [];
- for (var i = 1, len = arguments.length; i < len; i++) {
- args[i - 1] = arguments[i];
- }
- return this.apply(obj, args);
- };
- }
-
- /* ---------------------------------------------------------------------- */
- // Simple logging for log4javascript itself
-
- var logLog = {
- quietMode: false,
-
- debugMessages: [],
-
- setQuietMode: function(quietMode) {
- this.quietMode = bool(quietMode);
- },
-
- numberOfErrors: 0,
-
- alertAllErrors: false,
-
- setAlertAllErrors: function(alertAllErrors) {
- this.alertAllErrors = alertAllErrors;
- },
-
- debug: function(message) {
- this.debugMessages.push(message);
- },
-
- displayDebug: function() {
- alert(this.debugMessages.join(newLine));
- },
-
- warn: function(message, exception) {
- },
-
- error: function(message, exception) {
- if (++this.numberOfErrors == 1 || this.alertAllErrors) {
- if (!this.quietMode) {
- var alertMessage = "log4javascript error: " + message;
- if (exception) {
- alertMessage += newLine + newLine + "Original error: " + getExceptionStringRep(exception);
- }
- alert(alertMessage);
- }
- }
- }
- };
- log4javascript.logLog = logLog;
-
- log4javascript.setEventTypes(["load", "error"]);
-
- function handleError(message, exception) {
- logLog.error(message, exception);
- log4javascript.dispatchEvent("error", { "message": message, "exception": exception });
- }
-
- log4javascript.handleError = handleError;
-
- /* ---------------------------------------------------------------------- */
-
- var enabled = !((typeof log4javascript_disabled != "undefined") &&
- log4javascript_disabled);
-
- log4javascript.setEnabled = function(enable) {
- enabled = bool(enable);
- };
-
- log4javascript.isEnabled = function() {
- return enabled;
- };
-
- var useTimeStampsInMilliseconds = true;
-
- log4javascript.setTimeStampsInMilliseconds = function(timeStampsInMilliseconds) {
- useTimeStampsInMilliseconds = bool(timeStampsInMilliseconds);
- };
-
- log4javascript.isTimeStampsInMilliseconds = function() {
- return useTimeStampsInMilliseconds;
- };
-
-
- // This evaluates the given expression in the current scope, thus allowing
- // scripts to access private variables. Particularly useful for testing
- log4javascript.evalInScope = function(expr) {
- return eval(expr);
- };
-
- var showStackTraces = false;
-
- log4javascript.setShowStackTraces = function(show) {
- showStackTraces = bool(show);
- };
-
- /* ---------------------------------------------------------------------- */
- // Levels
-
- var Level = function(level, name) {
- this.level = level;
- this.name = name;
- };
-
- Level.prototype = {
- toString: function() {
- return this.name;
- },
- equals: function(level) {
- return this.level == level.level;
- },
- isGreaterOrEqual: function(level) {
- return this.level >= level.level;
- }
- };
-
- Level.ALL = new Level(Number.MIN_VALUE, "ALL");
- Level.TRACE = new Level(10000, "TRACE");
- Level.DEBUG = new Level(20000, "DEBUG");
- Level.INFO = new Level(30000, "INFO");
- Level.WARN = new Level(40000, "WARN");
- Level.ERROR = new Level(50000, "ERROR");
- Level.FATAL = new Level(60000, "FATAL");
- Level.OFF = new Level(Number.MAX_VALUE, "OFF");
-
- log4javascript.Level = Level;
-
- /* ---------------------------------------------------------------------- */
- // Timers
-
- function Timer(name, level) {
- this.name = name;
- this.level = isUndefined(level) ? Level.INFO : level;
- this.start = new Date();
- }
-
- Timer.prototype.getElapsedTime = function() {
- return new Date().getTime() - this.start.getTime();
- };
-
- /* ---------------------------------------------------------------------- */
- // Loggers
-
- var anonymousLoggerName = "[anonymous]";
- var defaultLoggerName = "[default]";
- var nullLoggerName = "[null]";
- var rootLoggerName = "root";
-
- function Logger(name) {
- this.name = name;
- this.parent = null;
- this.children = [];
-
- var appenders = [];
- var loggerLevel = null;
- var isRoot = (this.name === rootLoggerName);
- var isNull = (this.name === nullLoggerName);
-
- var appenderCache = null;
- var appenderCacheInvalidated = false;
-
- this.addChild = function(childLogger) {
- this.children.push(childLogger);
- childLogger.parent = this;
- childLogger.invalidateAppenderCache();
- };
-
- // Additivity
- var additive = true;
- this.getAdditivity = function() {
- return additive;
- };
-
- this.setAdditivity = function(additivity) {
- var valueChanged = (additive != additivity);
- additive = additivity;
- if (valueChanged) {
- this.invalidateAppenderCache();
- }
- };
-
- // Create methods that use the appenders variable in this scope
- this.addAppender = function(appender) {
- if (isNull) {
- handleError("Logger.addAppender: you may not add an appender to the null logger");
- } else {
- if (appender instanceof log4javascript.Appender) {
- if (!array_contains(appenders, appender)) {
- appenders.push(appender);
- appender.setAddedToLogger(this);
- this.invalidateAppenderCache();
- }
- } else {
- handleError("Logger.addAppender: appender supplied ('" +
- toStr(appender) + "') is not a subclass of Appender");
- }
- }
- };
-
- this.removeAppender = function(appender) {
- array_remove(appenders, appender);
- appender.setRemovedFromLogger(this);
- this.invalidateAppenderCache();
- };
-
- this.removeAllAppenders = function() {
- var appenderCount = appenders.length;
- if (appenderCount > 0) {
- for (var i = 0; i < appenderCount; i++) {
- appenders[i].setRemovedFromLogger(this);
- }
- appenders.length = 0;
- this.invalidateAppenderCache();
- }
- };
-
- this.getEffectiveAppenders = function() {
- if (appenderCache === null || appenderCacheInvalidated) {
- // Build appender cache
- var parentEffectiveAppenders = (isRoot || !this.getAdditivity()) ?
- [] : this.parent.getEffectiveAppenders();
- appenderCache = parentEffectiveAppenders.concat(appenders);
- appenderCacheInvalidated = false;
- }
- return appenderCache;
- };
-
- this.invalidateAppenderCache = function() {
- appenderCacheInvalidated = true;
- for (var i = 0, len = this.children.length; i < len; i++) {
- this.children[i].invalidateAppenderCache();
- }
- };
-
- this.log = function(level, params) {
- if (enabled && level.isGreaterOrEqual(this.getEffectiveLevel())) {
- // Check whether last param is an exception
- var exception;
- var finalParamIndex = params.length - 1;
- var lastParam = params[finalParamIndex];
- if (params.length > 1 && isError(lastParam)) {
- exception = lastParam;
- finalParamIndex--;
- }
-
- // Construct genuine array for the params
- var messages = [];
- for (var i = 0; i <= finalParamIndex; i++) {
- messages[i] = params[i];
- }
-
- var loggingEvent = new LoggingEvent(
- this, new Date(), level, messages, exception);
-
- this.callAppenders(loggingEvent);
- }
- };
-
- this.callAppenders = function(loggingEvent) {
- var effectiveAppenders = this.getEffectiveAppenders();
- for (var i = 0, len = effectiveAppenders.length; i < len; i++) {
- effectiveAppenders[i].doAppend(loggingEvent);
- }
- };
-
- this.setLevel = function(level) {
- // Having a level of null on the root logger would be very bad.
- if (isRoot && level === null) {
- handleError("Logger.setLevel: you cannot set the level of the root logger to null");
- } else if (level instanceof Level) {
- loggerLevel = level;
- } else {
- handleError("Logger.setLevel: level supplied to logger " +
- this.name + " is not an instance of log4javascript.Level");
- }
- };
-
- this.getLevel = function() {
- return loggerLevel;
- };
-
- this.getEffectiveLevel = function() {
- for (var logger = this; logger !== null; logger = logger.parent) {
- var level = logger.getLevel();
- if (level !== null) {
- return level;
- }
- }
- };
-
- this.group = function(name, initiallyExpanded) {
- if (enabled) {
- var effectiveAppenders = this.getEffectiveAppenders();
- for (var i = 0, len = effectiveAppenders.length; i < len; i++) {
- effectiveAppenders[i].group(name, initiallyExpanded);
- }
- }
- };
-
- this.groupEnd = function() {
- if (enabled) {
- var effectiveAppenders = this.getEffectiveAppenders();
- for (var i = 0, len = effectiveAppenders.length; i < len; i++) {
- effectiveAppenders[i].groupEnd();
- }
- }
- };
-
- var timers = {};
-
- this.time = function(name, level) {
- if (enabled) {
- if (isUndefined(name)) {
- handleError("Logger.time: a name for the timer must be supplied");
- } else if (level && !(level instanceof Level)) {
- handleError("Logger.time: level supplied to timer " +
- name + " is not an instance of log4javascript.Level");
- } else {
- timers[name] = new Timer(name, level);
- }
- }
- };
-
- this.timeEnd = function(name) {
- if (enabled) {
- if (isUndefined(name)) {
- handleError("Logger.timeEnd: a name for the timer must be supplied");
- } else if (timers[name]) {
- var timer = timers[name];
- var milliseconds = timer.getElapsedTime();
- this.log(timer.level, ["Timer " + toStr(name) + " completed in " + milliseconds + "ms"]);
- delete timers[name];
- } else {
- logLog.warn("Logger.timeEnd: no timer found with name " + name);
- }
- }
- };
-
- this.assert = function(expr) {
- if (enabled && !expr) {
- var args = [];
- for (var i = 1, len = arguments.length; i < len; i++) {
- args.push(arguments[i]);
- }
- args = (args.length > 0) ? args : ["Assertion Failure"];
- args.push(newLine);
- args.push(expr);
- this.log(Level.ERROR, args);
- }
- };
-
- this.toString = function() {
- return "Logger[" + this.name + "]";
- };
- }
-
- Logger.prototype = {
- trace: function() {
- this.log(Level.TRACE, arguments);
- },
-
- debug: function() {
- this.log(Level.DEBUG, arguments);
- },
-
- info: function() {
- this.log(Level.INFO, arguments);
- },
-
- warn: function() {
- this.log(Level.WARN, arguments);
- },
-
- error: function() {
- this.log(Level.ERROR, arguments);
- },
-
- fatal: function() {
- this.log(Level.FATAL, arguments);
- },
-
- isEnabledFor: function(level) {
- return level.isGreaterOrEqual(this.getEffectiveLevel());
- },
-
- isTraceEnabled: function() {
- return this.isEnabledFor(Level.TRACE);
- },
-
- isDebugEnabled: function() {
- return this.isEnabledFor(Level.DEBUG);
- },
-
- isInfoEnabled: function() {
- return this.isEnabledFor(Level.INFO);
- },
-
- isWarnEnabled: function() {
- return this.isEnabledFor(Level.WARN);
- },
-
- isErrorEnabled: function() {
- return this.isEnabledFor(Level.ERROR);
- },
-
- isFatalEnabled: function() {
- return this.isEnabledFor(Level.FATAL);
- }
- };
-
- Logger.prototype.trace.isEntryPoint = true;
- Logger.prototype.debug.isEntryPoint = true;
- Logger.prototype.info.isEntryPoint = true;
- Logger.prototype.warn.isEntryPoint = true;
- Logger.prototype.error.isEntryPoint = true;
- Logger.prototype.fatal.isEntryPoint = true;
-
- /* ---------------------------------------------------------------------- */
- // Logger access methods
-
- // Hashtable of loggers keyed by logger name
- var loggers = {};
- var loggerNames = [];
-
- var ROOT_LOGGER_DEFAULT_LEVEL = Level.DEBUG;
- var rootLogger = new Logger(rootLoggerName);
- rootLogger.setLevel(ROOT_LOGGER_DEFAULT_LEVEL);
-
- log4javascript.getRootLogger = function() {
- return rootLogger;
- };
-
- log4javascript.getLogger = function(loggerName) {
- // Use default logger if loggerName is not specified or invalid
- if (typeof loggerName != "string") {
- loggerName = anonymousLoggerName;
- logLog.warn("log4javascript.getLogger: non-string logger name " +
- toStr(loggerName) + " supplied, returning anonymous logger");
- }
-
- // Do not allow retrieval of the root logger by name
- if (loggerName == rootLoggerName) {
- handleError("log4javascript.getLogger: root logger may not be obtained by name");
- }
-
- // Create the logger for this name if it doesn't already exist
- if (!loggers[loggerName]) {
- var logger = new Logger(loggerName);
- loggers[loggerName] = logger;
- loggerNames.push(loggerName);
-
- // Set up parent logger, if it doesn't exist
- var lastDotIndex = loggerName.lastIndexOf(".");
- var parentLogger;
- if (lastDotIndex > -1) {
- var parentLoggerName = loggerName.substring(0, lastDotIndex);
- parentLogger = log4javascript.getLogger(parentLoggerName); // Recursively sets up grandparents etc.
- } else {
- parentLogger = rootLogger;
- }
- parentLogger.addChild(logger);
- }
- return loggers[loggerName];
- };
-
- var defaultLogger = null;
- log4javascript.getDefaultLogger = function() {
- if (!defaultLogger) {
- defaultLogger = createDefaultLogger();
- }
- return defaultLogger;
- };
-
- var nullLogger = null;
- log4javascript.getNullLogger = function() {
- if (!nullLogger) {
- nullLogger = new Logger(nullLoggerName);
- nullLogger.setLevel(Level.OFF);
- }
- return nullLogger;
- };
-
- // Destroys all loggers
- log4javascript.resetConfiguration = function() {
- rootLogger.setLevel(ROOT_LOGGER_DEFAULT_LEVEL);
- loggers = {};
- };
-
- /* ---------------------------------------------------------------------- */
- // Logging events
-
- var LoggingEvent = function(logger, timeStamp, level, messages,
- exception) {
- this.logger = logger;
- this.timeStamp = timeStamp;
- this.timeStampInMilliseconds = timeStamp.getTime();
- this.timeStampInSeconds = Math.floor(this.timeStampInMilliseconds / 1000);
- this.milliseconds = this.timeStamp.getMilliseconds();
- this.level = level;
- this.messages = messages;
- this.exception = exception;
- };
-
- LoggingEvent.prototype = {
- getThrowableStrRep: function() {
- return this.exception ?
- getExceptionStringRep(this.exception) : "";
- },
- getCombinedMessages: function() {
- return (this.messages.length == 1) ? this.messages[0] :
- this.messages.join(newLine);
- },
- toString: function() {
- return "LoggingEvent[" + this.level + "]";
- }
- };
-
- log4javascript.LoggingEvent = LoggingEvent;
-
- /* ---------------------------------------------------------------------- */
- // Layout prototype
-
- var Layout = function() {
- };
-
- Layout.prototype = {
- defaults: {
- loggerKey: "logger",
- timeStampKey: "timestamp",
- millisecondsKey: "milliseconds",
- levelKey: "level",
- messageKey: "message",
- exceptionKey: "exception",
- urlKey: "url"
- },
- loggerKey: "logger",
- timeStampKey: "timestamp",
- millisecondsKey: "milliseconds",
- levelKey: "level",
- messageKey: "message",
- exceptionKey: "exception",
- urlKey: "url",
- batchHeader: "",
- batchFooter: "",
- batchSeparator: "",
- returnsPostData: false,
- overrideTimeStampsSetting: false,
- useTimeStampsInMilliseconds: null,
-
- format: function() {
- handleError("Layout.format: layout supplied has no format() method");
- },
-
- ignoresThrowable: function() {
- handleError("Layout.ignoresThrowable: layout supplied has no ignoresThrowable() method");
- },
-
- getContentType: function() {
- return "text/plain";
- },
-
- allowBatching: function() {
- return true;
- },
-
- setTimeStampsInMilliseconds: function(timeStampsInMilliseconds) {
- this.overrideTimeStampsSetting = true;
- this.useTimeStampsInMilliseconds = bool(timeStampsInMilliseconds);
- },
-
- isTimeStampsInMilliseconds: function() {
- return this.overrideTimeStampsSetting ?
- this.useTimeStampsInMilliseconds : useTimeStampsInMilliseconds;
- },
-
- getTimeStampValue: function(loggingEvent) {
- return this.isTimeStampsInMilliseconds() ?
- loggingEvent.timeStampInMilliseconds : loggingEvent.timeStampInSeconds;
- },
-
- getDataValues: function(loggingEvent, combineMessages) {
- var dataValues = [
- [this.loggerKey, loggingEvent.logger.name],
- [this.timeStampKey, this.getTimeStampValue(loggingEvent)],
- [this.levelKey, loggingEvent.level.name],
- [this.urlKey, window.location.href],
- [this.messageKey, combineMessages ? loggingEvent.getCombinedMessages() : loggingEvent.messages]
- ];
- if (!this.isTimeStampsInMilliseconds()) {
- dataValues.push([this.millisecondsKey, loggingEvent.milliseconds]);
- }
- if (loggingEvent.exception) {
- dataValues.push([this.exceptionKey, getExceptionStringRep(loggingEvent.exception)]);
- }
- if (this.hasCustomFields()) {
- for (var i = 0, len = this.customFields.length; i < len; i++) {
- var val = this.customFields[i].value;
-
- // Check if the value is a function. If so, execute it, passing it the
- // current layout and the logging event
- if (typeof val === "function") {
- val = val(this, loggingEvent);
- }
- dataValues.push([this.customFields[i].name, val]);
- }
- }
- return dataValues;
- },
-
- setKeys: function(loggerKey, timeStampKey, levelKey, messageKey,
- exceptionKey, urlKey, millisecondsKey) {
- this.loggerKey = extractStringFromParam(loggerKey, this.defaults.loggerKey);
- this.timeStampKey = extractStringFromParam(timeStampKey, this.defaults.timeStampKey);
- this.levelKey = extractStringFromParam(levelKey, this.defaults.levelKey);
- this.messageKey = extractStringFromParam(messageKey, this.defaults.messageKey);
- this.exceptionKey = extractStringFromParam(exceptionKey, this.defaults.exceptionKey);
- this.urlKey = extractStringFromParam(urlKey, this.defaults.urlKey);
- this.millisecondsKey = extractStringFromParam(millisecondsKey, this.defaults.millisecondsKey);
- },
-
- setCustomField: function(name, value) {
- var fieldUpdated = false;
- for (var i = 0, len = this.customFields.length; i < len; i++) {
- if (this.customFields[i].name === name) {
- this.customFields[i].value = value;
- fieldUpdated = true;
- }
- }
- if (!fieldUpdated) {
- this.customFields.push({"name": name, "value": value});
- }
- },
-
- hasCustomFields: function() {
- return (this.customFields.length > 0);
- },
-
- formatWithException: function(loggingEvent) {
- var formatted = this.format(loggingEvent);
- if (loggingEvent.exception && this.ignoresThrowable()) {
- formatted += loggingEvent.getThrowableStrRep();
- }
- return formatted;
- },
-
- toString: function() {
- handleError("Layout.toString: all layouts must override this method");
- }
- };
-
- log4javascript.Layout = Layout;
-
- /* ---------------------------------------------------------------------- */
- // Appender prototype
-
- var Appender = function() {};
-
- Appender.prototype = new EventSupport();
-
- Appender.prototype.layout = new PatternLayout();
- Appender.prototype.threshold = Level.ALL;
- Appender.prototype.loggers = [];
-
- // Performs threshold checks before delegating actual logging to the
- // subclass's specific append method.
- Appender.prototype.doAppend = function(loggingEvent) {
- if (enabled && loggingEvent.level.level >= this.threshold.level) {
- this.append(loggingEvent);
- }
- };
-
- Appender.prototype.append = function(loggingEvent) {};
-
- Appender.prototype.setLayout = function(layout) {
- if (layout instanceof Layout) {
- this.layout = layout;
- } else {
- handleError("Appender.setLayout: layout supplied to " +
- this.toString() + " is not a subclass of Layout");
- }
- };
-
- Appender.prototype.getLayout = function() {
- return this.layout;
- };
-
- Appender.prototype.setThreshold = function(threshold) {
- if (threshold instanceof Level) {
- this.threshold = threshold;
- } else {
- handleError("Appender.setThreshold: threshold supplied to " +
- this.toString() + " is not a subclass of Level");
- }
- };
-
- Appender.prototype.getThreshold = function() {
- return this.threshold;
- };
-
- Appender.prototype.setAddedToLogger = function(logger) {
- this.loggers.push(logger);
- };
-
- Appender.prototype.setRemovedFromLogger = function(logger) {
- array_remove(this.loggers, logger);
- };
-
- Appender.prototype.group = emptyFunction;
- Appender.prototype.groupEnd = emptyFunction;
-
- Appender.prototype.toString = function() {
- handleError("Appender.toString: all appenders must override this method");
- };
-
- log4javascript.Appender = Appender;
-
- /* ---------------------------------------------------------------------- */
- // SimpleLayout
-
- function SimpleLayout() {
- this.customFields = [];
- }
-
- SimpleLayout.prototype = new Layout();
-
- SimpleLayout.prototype.format = function(loggingEvent) {
- return loggingEvent.level.name + " - " + loggingEvent.getCombinedMessages();
- };
-
- SimpleLayout.prototype.ignoresThrowable = function() {
- return true;
- };
-
- SimpleLayout.prototype.toString = function() {
- return "SimpleLayout";
- };
-
- log4javascript.SimpleLayout = SimpleLayout;
- /* ----------------------------------------------------------------------- */
- // NullLayout
-
- function NullLayout() {
- this.customFields = [];
- }
-
- NullLayout.prototype = new Layout();
-
- NullLayout.prototype.format = function(loggingEvent) {
- return loggingEvent.messages;
- };
-
- NullLayout.prototype.ignoresThrowable = function() {
- return true;
- };
-
- NullLayout.prototype.formatWithException = function(loggingEvent) {
- var messages = loggingEvent.messages, ex = loggingEvent.exception;
- return ex ? messages.concat([ex]) : messages;
- };
-
- NullLayout.prototype.toString = function() {
- return "NullLayout";
- };
-
- log4javascript.NullLayout = NullLayout;
- /* ---------------------------------------------------------------------- */
- // XmlLayout
-
- function XmlLayout(combineMessages) {
- this.combineMessages = extractBooleanFromParam(combineMessages, true);
- this.customFields = [];
- }
-
- XmlLayout.prototype = new Layout();
-
- XmlLayout.prototype.isCombinedMessages = function() {
- return this.combineMessages;
- };
-
- XmlLayout.prototype.getContentType = function() {
- return "text/xml";
- };
-
- XmlLayout.prototype.escapeCdata = function(str) {
- return str.replace(/\]\]>/, "]]>]]><![CDATA[");
- };
-
- XmlLayout.prototype.format = function(loggingEvent) {
- var layout = this;
- var i, len;
- function formatMessage(message) {
- message = (typeof message === "string") ? message : toStr(message);
- return "<log4javascript:message><![CDATA[" +
- layout.escapeCdata(message) + "]]></log4javascript:message>";
- }
-
- var str = "<log4javascript:event logger=\"" + loggingEvent.logger.name +
- "\" timestamp=\"" + this.getTimeStampValue(loggingEvent) + "\"";
- if (!this.isTimeStampsInMilliseconds()) {
- str += " milliseconds=\"" + loggingEvent.milliseconds + "\"";
- }
- str += " level=\"" + loggingEvent.level.name + "\">" + newLine;
- if (this.combineMessages) {
- str += formatMessage(loggingEvent.getCombinedMessages());
- } else {
- str += "<log4javascript:messages>" + newLine;
- for (i = 0, len = loggingEvent.messages.length; i < len; i++) {
- str += formatMessage(loggingEvent.messages[i]) + newLine;
- }
- str += "</log4javascript:messages>" + newLine;
- }
- if (this.hasCustomFields()) {
- for (i = 0, len = this.customFields.length; i < len; i++) {
- str += "<log4javascript:customfield name=\"" +
- this.customFields[i].name + "\"><![CDATA[" +
- this.customFields[i].value.toString() +
- "]]></log4javascript:customfield>" + newLine;
- }
- }
- if (loggingEvent.exception) {
- str += "<log4javascript:exception><![CDATA[" +
- getExceptionStringRep(loggingEvent.exception) +
- "]]></log4javascript:exception>" + newLine;
- }
- str += "</log4javascript:event>" + newLine + newLine;
- return str;
- };
-
- XmlLayout.prototype.ignoresThrowable = function() {
- return false;
- };
-
- XmlLayout.prototype.toString = function() {
- return "XmlLayout";
- };
-
- log4javascript.XmlLayout = XmlLayout;
- /* ---------------------------------------------------------------------- */
- // JsonLayout related
-
- function escapeNewLines(str) {
- return str.replace(/\r\n|\r|\n/g, "\\r\\n");
- }
-
- function JsonLayout(readable, combineMessages) {
- this.readable = extractBooleanFromParam(readable, false);
- this.combineMessages = extractBooleanFromParam(combineMessages, true);
- this.batchHeader = this.readable ? "[" + newLine : "[";
- this.batchFooter = this.readable ? "]" + newLine : "]";
- this.batchSeparator = this.readable ? "," + newLine : ",";
- this.setKeys();
- this.colon = this.readable ? ": " : ":";
- this.tab = this.readable ? "\t" : "";
- this.lineBreak = this.readable ? newLine : "";
- this.customFields = [];
- }
-
- /* ---------------------------------------------------------------------- */
- // JsonLayout
-
- JsonLayout.prototype = new Layout();
-
- JsonLayout.prototype.isReadable = function() {
- return this.readable;
- };
-
- JsonLayout.prototype.isCombinedMessages = function() {
- return this.combineMessages;
- };
-
- JsonLayout.prototype.format = function(loggingEvent) {
- var layout = this;
- var dataValues = this.getDataValues(loggingEvent, this.combineMessages);
- var str = "{" + this.lineBreak;
- var i, len;
-
- function formatValue(val, prefix, expand) {
- // Check the type of the data value to decide whether quotation marks
- // or expansion are required
- var formattedValue;
- var valType = typeof val;
- if (val instanceof Date) {
- formattedValue = String(val.getTime());
- } else if (expand && (val instanceof Array)) {
- formattedValue = "[" + layout.lineBreak;
- for (var i = 0, len = val.length; i < len; i++) {
- var childPrefix = prefix + layout.tab;
- formattedValue += childPrefix + formatValue(val[i], childPrefix, false);
- if (i < val.length - 1) {
- formattedValue += ",";
- }
- formattedValue += layout.lineBreak;
- }
- formattedValue += prefix + "]";
- } else if (valType !== "number" && valType !== "boolean") {
- formattedValue = "\"" + escapeNewLines(toStr(val).replace(/\"/g, "\\\"")) + "\"";
- } else {
- formattedValue = val;
- }
- return formattedValue;
- }
-
- for (i = 0, len = dataValues.length - 1; i <= len; i++) {
- str += this.tab + "\"" + dataValues[i][0] + "\"" + this.colon + formatValue(dataValues[i][1], this.tab, true);
- if (i < len) {
- str += ",";
- }
- str += this.lineBreak;
- }
-
- str += "}" + this.lineBreak;
- return str;
- };
-
- JsonLayout.prototype.ignoresThrowable = function() {
- return false;
- };
-
- JsonLayout.prototype.toString = function() {
- return "JsonLayout";
- };
-
- JsonLayout.prototype.getContentType = function() {
- return "application/json";
- };
-
- log4javascript.JsonLayout = JsonLayout;
- /* ---------------------------------------------------------------------- */
- // HttpPostDataLayout
-
- function HttpPostDataLayout() {
- this.setKeys();
- this.customFields = [];
- this.returnsPostData = true;
- }
-
- HttpPostDataLayout.prototype = new Layout();
-
- // Disable batching
- HttpPostDataLayout.prototype.allowBatching = function() {
- return false;
- };
-
- HttpPostDataLayout.prototype.format = function(loggingEvent) {
- var dataValues = this.getDataValues(loggingEvent);
- var queryBits = [];
- for (var i = 0, len = dataValues.length; i < len; i++) {
- var val = (dataValues[i][1] instanceof Date) ?
- String(dataValues[i][1].getTime()) : dataValues[i][1];
- queryBits.push(urlEncode(dataValues[i][0]) + "=" + urlEncode(val));
- }
- return queryBits.join("&");
- };
-
- HttpPostDataLayout.prototype.ignoresThrowable = function(loggingEvent) {
- return false;
- };
-
- HttpPostDataLayout.prototype.toString = function() {
- return "HttpPostDataLayout";
- };
-
- log4javascript.HttpPostDataLayout = HttpPostDataLayout;
- /* ---------------------------------------------------------------------- */
- // formatObjectExpansion
-
- function formatObjectExpansion(obj, depth, indentation) {
- var objectsExpanded = [];
-
- function doFormat(obj, depth, indentation) {
- var i, len, childDepth, childIndentation, childLines, expansion,
- childExpansion;
-
- if (!indentation) {
- indentation = "";
- }
-
- function formatString(text) {
- var lines = splitIntoLines(text);
- for (var j = 1, jLen = lines.length; j < jLen; j++) {
- lines[j] = indentation + lines[j];
- }
- return lines.join(newLine);
- }
-
- if (obj === null) {
- return "null";
- } else if (typeof obj == "undefined") {
- return "undefined";
- } else if (typeof obj == "string") {
- return formatString(obj);
- } else if (typeof obj == "object" && array_contains(objectsExpanded, obj)) {
- try {
- expansion = toStr(obj);
- } catch (ex) {
- expansion = "Error formatting property. Details: " + getExceptionStringRep(ex);
- }
- return expansion + " [already expanded]";
- } else if ((obj instanceof Array) && depth > 0) {
- objectsExpanded.push(obj);
- expansion = "[" + newLine;
- childDepth = depth - 1;
- childIndentation = indentation + " ";
- childLines = [];
- for (i = 0, len = obj.length; i < len; i++) {
- try {
- childExpansion = doFormat(obj[i], childDepth, childIndentation);
- childLines.push(childIndentation + childExpansion);
- } catch (ex) {
- childLines.push(childIndentation + "Error formatting array member. Details: " +
- getExceptionStringRep(ex) + "");
- }
- }
- expansion += childLines.join("," + newLine) + newLine + indentation + "]";
- return expansion;
- } else if (Object.prototype.toString.call(obj) == "[object Date]") {
- return obj.toString();
- } else if (typeof obj == "object" && depth > 0) {
- objectsExpanded.push(obj);
- expansion = "{" + newLine;
- childDepth = depth - 1;
- childIndentation = indentation + " ";
- childLines = [];
- for (i in obj) {
- try {
- childExpansion = doFormat(obj[i], childDepth, childIndentation);
- childLines.push(childIndentation + i + ": " + childExpansion);
- } catch (ex) {
- childLines.push(childIndentation + i + ": Error formatting property. Details: " +
- getExceptionStringRep(ex));
- }
- }
- expansion += childLines.join("," + newLine) + newLine + indentation + "}";
- return expansion;
- } else {
- return formatString(toStr(obj));
- }
- }
- return doFormat(obj, depth, indentation);
- }
- /* ---------------------------------------------------------------------- */
- // Date-related stuff
-
- var SimpleDateFormat;
-
- (function() {
- var regex = /('[^']*')|(G+|y+|M+|w+|W+|D+|d+|F+|E+|a+|H+|k+|K+|h+|m+|s+|S+|Z+)|([a-zA-Z]+)|([^a-zA-Z']+)/;
- var monthNames = ["January", "February", "March", "April", "May", "June",
- "July", "August", "September", "October", "November", "December"];
- var dayNames = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
- var TEXT2 = 0, TEXT3 = 1, NUMBER = 2, YEAR = 3, MONTH = 4, TIMEZONE = 5;
- var types = {
- G : TEXT2,
- y : YEAR,
- M : MONTH,
- w : NUMBER,
- W : NUMBER,
- D : NUMBER,
- d : NUMBER,
- F : NUMBER,
- E : TEXT3,
- a : TEXT2,
- H : NUMBER,
- k : NUMBER,
- K : NUMBER,
- h : NUMBER,
- m : NUMBER,
- s : NUMBER,
- S : NUMBER,
- Z : TIMEZONE
- };
- var ONE_DAY = 24 * 60 * 60 * 1000;
- var ONE_WEEK = 7 * ONE_DAY;
- var DEFAULT_MINIMAL_DAYS_IN_FIRST_WEEK = 1;
-
- var newDateAtMidnight = function(year, month, day) {
- var d = new Date(year, month, day, 0, 0, 0);
- d.setMilliseconds(0);
- return d;
- };
-
- Date.prototype.getDifference = function(date) {
- return this.getTime() - date.getTime();
- };
-
- Date.prototype.isBefore = function(d) {
- return this.getTime() < d.getTime();
- };
-
- Date.prototype.getUTCTime = function() {
- return Date.UTC(this.getFullYear(), this.getMonth(), this.getDate(), this.getHours(), this.getMinutes(),
- this.getSeconds(), this.getMilliseconds());
- };
-
- Date.prototype.getTimeSince = function(d) {
- return this.getUTCTime() - d.getUTCTime();
- };
-
- Date.prototype.getPreviousSunday = function() {
- // Using midday avoids any possibility of DST messing things up
- var midday = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 12, 0, 0);
- var previousSunday = new Date(midday.getTime() - this.getDay() * ONE_DAY);
- return newDateAtMidnight(previousSunday.getFullYear(), previousSunday.getMonth(),
- previousSunday.getDate());
- };
-
- Date.prototype.getWeekInYear = function(minimalDaysInFirstWeek) {
- if (isUndefined(this.minimalDaysInFirstWeek)) {
- minimalDaysInFirstWeek = DEFAULT_MINIMAL_DAYS_IN_FIRST_WEEK;
- }
- var previousSunday = this.getPreviousSunday();
- var startOfYear = newDateAtMidnight(this.getFullYear(), 0, 1);
- var numberOfSundays = previousSunday.isBefore(startOfYear) ?
- 0 : 1 + Math.floor(previousSunday.getTimeSince(startOfYear) / ONE_WEEK);
- var numberOfDaysInFirstWeek = 7 - startOfYear.getDay();
- var weekInYear = numberOfSundays;
- if (numberOfDaysInFirstWeek < minimalDaysInFirstWeek) {
- weekInYear--;
- }
- return weekInYear;
- };
-
- Date.prototype.getWeekInMonth = function(minimalDaysInFirstWeek) {
- if (isUndefined(this.minimalDaysInFirstWeek)) {
- minimalDaysInFirstWeek = DEFAULT_MINIMAL_DAYS_IN_FIRST_WEEK;
- }
- var previousSunday = this.getPreviousSunday();
- var startOfMonth = newDateAtMidnight(this.getFullYear(), this.getMonth(), 1);
- var numberOfSundays = previousSunday.isBefore(startOfMonth) ?
- 0 : 1 + Math.floor(previousSunday.getTimeSince(startOfMonth) / ONE_WEEK);
- var numberOfDaysInFirstWeek = 7 - startOfMonth.getDay();
- var weekInMonth = numberOfSundays;
- if (numberOfDaysInFirstWeek >= minimalDaysInFirstWeek) {
- weekInMonth++;
- }
- return weekInMonth;
- };
-
- Date.prototype.getDayInYear = function() {
- var startOfYear = newDateAtMidnight(this.getFullYear(), 0, 1);
- return 1 + Math.floor(this.getTimeSince(startOfYear) / ONE_DAY);
- };
-
- /* ------------------------------------------------------------------ */
-
- SimpleDateFormat = function(formatString) {
- this.formatString = formatString;
- };
-
- /**
- * Sets the minimum number of days in a week in order for that week to
- * be considered as belonging to a particular month or year
- */
- SimpleDateFormat.prototype.setMinimalDaysInFirstWeek = function(days) {
- this.minimalDaysInFirstWeek = days;
- };
-
- SimpleDateFormat.prototype.getMinimalDaysInFirstWeek = function() {
- return isUndefined(this.minimalDaysInFirstWeek) ?
- DEFAULT_MINIMAL_DAYS_IN_FIRST_WEEK : this.minimalDaysInFirstWeek;
- };
-
- var padWithZeroes = function(str, len) {
- while (str.length < len) {
- str = "0" + str;
- }
- return str;
- };
-
- var formatText = function(data, numberOfLetters, minLength) {
- return (numberOfLetters >= 4) ? data : data.substr(0, Math.max(minLength, numberOfLetters));
- };
-
- var formatNumber = function(data, numberOfLetters) {
- var dataString = "" + data;
- // Pad with 0s as necessary
- return padWithZeroes(dataString, numberOfLetters);
- };
-
- SimpleDateFormat.prototype.format = function(date) {
- var formattedString = "";
- var result;
- var searchString = this.formatString;
- while ((result = regex.exec(searchString))) {
- var quotedString = result[1];
- var patternLetters = result[2];
- var otherLetters = result[3];
- var otherCharacters = result[4];
-
- // If the pattern matched is quoted string, output the text between the quotes
- if (quotedString) {
- if (quotedString == "''") {
- formattedString += "'";
- } else {
- formattedString += quotedString.substring(1, quotedString.length - 1);
- }
- } else if (otherLetters) {
- // Swallow non-pattern letters by doing nothing here
- } else if (otherCharacters) {
- // Simply output other characters
- formattedString += otherCharacters;
- } else if (patternLetters) {
- // Replace pattern letters
- var patternLetter = patternLetters.charAt(0);
- var numberOfLetters = patternLetters.length;
- var rawData = "";
- switch(patternLetter) {
- case "G":
- rawData = "AD";
- break;
- case "y":
- rawData = date.getFullYear();
- break;
- case "M":
- rawData = date.getMonth();
- break;
- case "w":
- rawData = date.getWeekInYear(this.getMinimalDaysInFirstWeek());
- break;
- case "W":
- rawData = date.getWeekInMonth(this.getMinimalDaysInFirstWeek());
- break;
- case "D":
- rawData = date.getDayInYear();
- break;
- case "d":
- rawData = date.getDate();
- break;
- case "F":
- rawData = 1 + Math.floor((date.getDate() - 1) / 7);
- break;
- case "E":
- rawData = dayNames[date.getDay()];
- break;
- case "a":
- rawData = (date.getHours() >= 12) ? "PM" : "AM";
- break;
- case "H":
- rawData = date.getHours();
- break;
- case "k":
- rawData = date.getHours() || 24;
- break;
- case "K":
- rawData = date.getHours() % 12;
- break;
- case "h":
- rawData = (date.getHours() % 12) || 12;
- break;
- case "m":
- rawData = date.getMinutes();
- break;
- case "s":
- rawData = date.getSeconds();
- break;
- case "S":
- rawData = date.getMilliseconds();
- break;
- case "Z":
- rawData = date.getTimezoneOffset(); // This returns the number of minutes since GMT was this time.
- break;
- }
- // Format the raw data depending on the type
- switch(types[patternLetter]) {
- case TEXT2:
- formattedString += formatText(rawData, numberOfLetters, 2);
- break;
- case TEXT3:
- formattedString += formatText(rawData, numberOfLetters, 3);
- break;
- case NUMBER:
- formattedString += formatNumber(rawData, numberOfLetters);
- break;
- case YEAR:
- if (numberOfLetters <= 3) {
- // Output a 2-digit year
- var dataString = "" + rawData;
- formattedString += dataString.substr(2, 2);
- } else {
- formattedString += formatNumber(rawData, numberOfLetters);
- }
- break;
- case MONTH:
- if (numberOfLetters >= 3) {
- formattedString += formatText(monthNames[rawData], numberOfLetters, numberOfLetters);
- } else {
- // NB. Months returned by getMonth are zero-based
- formattedString += formatNumber(rawData + 1, numberOfLetters);
- }
- break;
- case TIMEZONE:
- var isPositive = (rawData > 0);
- // The following line looks like a mistake but isn't
- // because of the way getTimezoneOffset measures.
- var prefix = isPositive ? "-" : "+";
- var absData = Math.abs(rawData);
-
- // Hours
- var hours = "" + Math.floor(absData / 60);
- hours = padWithZeroes(hours, 2);
- // Minutes
- var minutes = "" + (absData % 60);
- minutes = padWithZeroes(minutes, 2);
-
- formattedString += prefix + hours + minutes;
- break;
- }
- }
- searchString = searchString.substr(result.index + result[0].length);
- }
- return formattedString;
- };
- })();
-
- log4javascript.SimpleDateFormat = SimpleDateFormat;
-
- /* ---------------------------------------------------------------------- */
- // PatternLayout
-
- function PatternLayout(pattern) {
- if (pattern) {
- this.pattern = pattern;
- } else {
- this.pattern = PatternLayout.DEFAULT_CONVERSION_PATTERN;
- }
- this.customFields = [];
- }
-
- PatternLayout.TTCC_CONVERSION_PATTERN = "%r %p %c - %m%n";
- PatternLayout.DEFAULT_CONVERSION_PATTERN = "%m%n";
- PatternLayout.ISO8601_DATEFORMAT = "yyyy-MM-dd HH:mm:ss,SSS";
- PatternLayout.DATETIME_DATEFORMAT = "dd MMM yyyy HH:mm:ss,SSS";
- PatternLayout.ABSOLUTETIME_DATEFORMAT = "HH:mm:ss,SSS";
-
- PatternLayout.prototype = new Layout();
-
- PatternLayout.prototype.format = function(loggingEvent) {
- var regex = /%(-?[0-9]+)?(\.?[0-9]+)?([acdfmMnpr%])(\{([^\}]+)\})?|([^%]+)/;
- var formattedString = "";
- var result;
- var searchString = this.pattern;
-
- // Cannot use regex global flag since it doesn't work with exec in IE5
- while ((result = regex.exec(searchString))) {
- var matchedString = result[0];
- var padding = result[1];
- var truncation = result[2];
- var conversionCharacter = result[3];
- var specifier = result[5];
- var text = result[6];
-
- // Check if the pattern matched was just normal text
- if (text) {
- formattedString += "" + text;
- } else {
- // Create a raw replacement string based on the conversion
- // character and specifier
- var replacement = "";
- switch(conversionCharacter) {
- case "a": // Array of messages
- case "m": // Message
- var depth = 0;
- if (specifier) {
- depth = parseInt(specifier, 10);
- if (isNaN(depth)) {
- handleError("PatternLayout.format: invalid specifier '" +
- specifier + "' for conversion character '" + conversionCharacter +
- "' - should be a number");
- depth = 0;
- }
- }
- var messages = (conversionCharacter === "a") ? loggingEvent.messages[0] : loggingEvent.messages;
- for (var i = 0, len = messages.length; i < len; i++) {
- if (i > 0 && (replacement.charAt(replacement.length - 1) !== " ")) {
- replacement += " ";
- }
- if (depth === 0) {
- replacement += messages[i];
- } else {
- replacement += formatObjectExpansion(messages[i], depth);
- }
- }
- break;
- case "c": // Logger name
- var loggerName = loggingEvent.logger.name;
- if (specifier) {
- var precision = parseInt(specifier, 10);
- var loggerNameBits = loggingEvent.logger.name.split(".");
- if (precision >= loggerNameBits.length) {
- replacement = loggerName;
- } else {
- replacement = loggerNameBits.slice(loggerNameBits.length - precision).join(".");
- }
- } else {
- replacement = loggerName;
- }
- break;
- case "d": // Date
- var dateFormat = PatternLayout.ISO8601_DATEFORMAT;
- if (specifier) {
- dateFormat = specifier;
- // Pick up special cases
- if (dateFormat == "ISO8601") {
- dateFormat = PatternLayout.ISO8601_DATEFORMAT;
- } else if (dateFormat == "ABSOLUTE") {
- dateFormat = PatternLayout.ABSOLUTETIME_DATEFORMAT;
- } else if (dateFormat == "DATE") {
- dateFormat = PatternLayout.DATETIME_DATEFORMAT;
- }
- }
- // Format the date
- replacement = (new SimpleDateFormat(dateFormat)).format(loggingEvent.timeStamp);
- break;
- case "f": // Custom field
- if (this.hasCustomFields()) {
- var fieldIndex = 0;
- if (specifier) {
- fieldIndex = parseInt(specifier, 10);
- if (isNaN(fieldIndex)) {
- handleError("PatternLayout.format: invalid specifier '" +
- specifier + "' for conversion character 'f' - should be a number");
- } else if (fieldIndex === 0) {
- handleError("PatternLayout.format: invalid specifier '" +
- specifier + "' for conversion character 'f' - must be greater than zero");
- } else if (fieldIndex > this.customFields.length) {
- handleError("PatternLayout.format: invalid specifier '" +
- specifier + "' for conversion character 'f' - there aren't that many custom fields");
- } else {
- fieldIndex = fieldIndex - 1;
- }
- }
- var val = this.customFields[fieldIndex].value;
- if (typeof val == "function") {
- val = val(this, loggingEvent);
- }
- replacement = val;
- }
- break;
- case "n": // New line
- replacement = newLine;
- break;
- case "p": // Level
- replacement = loggingEvent.level.name;
- break;
- case "r": // Milliseconds since log4javascript startup
- replacement = "" + loggingEvent.timeStamp.getDifference(applicationStartDate);
- break;
- case "%": // Literal % sign
- replacement = "%";
- break;
- default:
- replacement = matchedString;
- break;
- }
- // Format the replacement according to any padding or
- // truncation specified
- var l;
-
- // First, truncation
- if (truncation) {
- l = parseInt(truncation.substr(1), 10);
- var strLen = replacement.length;
- if (l < strLen) {
- replacement = replacement.substring(strLen - l, strLen);
- }
- }
- // Next, padding
- if (padding) {
- if (padding.charAt(0) == "-") {
- l = parseInt(padding.substr(1), 10);
- // Right pad with spaces
- while (replacement.length < l) {
- replacement += " ";
- }
- } else {
- l = parseInt(padding, 10);
- // Left pad with spaces
- while (replacement.length < l) {
- replacement = " " + replacement;
- }
- }
- }
- formattedString += replacement;
- }
- searchString = searchString.substr(result.index + result[0].length);
- }
- return formattedString;
- };
-
- PatternLayout.prototype.ignoresThrowable = function() {
- return true;
- };
-
- PatternLayout.prototype.toString = function() {
- return "PatternLayout";
- };
-
- log4javascript.PatternLayout = PatternLayout;
- /* ---------------------------------------------------------------------- */
- // AlertAppender
-
- function AlertAppender() {}
-
- AlertAppender.prototype = new Appender();
-
- AlertAppender.prototype.layout = new SimpleLayout();
-
- AlertAppender.prototype.append = function(loggingEvent) {
- alert( this.getLayout().formatWithException(loggingEvent) );
- };
-
- AlertAppender.prototype.toString = function() {
- return "AlertAppender";
- };
-
- log4javascript.AlertAppender = AlertAppender;
- /* ---------------------------------------------------------------------- */
- // BrowserConsoleAppender (only works in Opera and Safari and Firefox with
- // Firebug extension)
-
- function BrowserConsoleAppender() {}
-
- BrowserConsoleAppender.prototype = new log4javascript.Appender();
- BrowserConsoleAppender.prototype.layout = new NullLayout();
- BrowserConsoleAppender.prototype.threshold = Level.DEBUG;
-
- BrowserConsoleAppender.prototype.append = function(loggingEvent) {
- var appender = this;
-
- var getFormattedMessage = function() {
- var formattedMessage = appender.getLayout().formatWithException(loggingEvent);
- return (typeof formattedMessage == "string") ? [formattedMessage] : formattedMessage;
- };
-
- var console;
-
- if ( (console = window.console) && console.log) { // Safari and Firebug
- var formattedMessage = getFormattedMessage();
-
- // Log to Firebug or the browser console using specific logging
- // methods or revert to console.log otherwise
- var consoleMethodName;
-
- if (console.debug && Level.DEBUG.isGreaterOrEqual(loggingEvent.level)) {
- consoleMethodName = "debug";
- } else if (console.info && Level.INFO.equals(loggingEvent.level)) {
- consoleMethodName = "info";
- } else if (console.warn && Level.WARN.equals(loggingEvent.level)) {
- consoleMethodName = "warn";
- } else if (console.error && loggingEvent.level.isGreaterOrEqual(Level.ERROR)) {
- consoleMethodName = "error";
- } else {
- consoleMethodName = "log";
- }
-
- if (console[consoleMethodName].apply) {
- console[consoleMethodName].apply(console, formattedMessage);
- } else {
- console[consoleMethodName](formattedMessage);
- }
- } else if ((typeof opera != "undefined") && opera.postError) { // Opera
- opera.postError(getFormattedMessage());
- }
- };
-
- BrowserConsoleAppender.prototype.group = function(name) {
- if (window.console && window.console.group) {
- window.console.group(name);
- }
- };
-
- BrowserConsoleAppender.prototype.groupEnd = function() {
- if (window.console && window.console.groupEnd) {
- window.console.groupEnd();
- }
- };
-
- BrowserConsoleAppender.prototype.toString = function() {
- return "BrowserConsoleAppender";
- };
-
- log4javascript.BrowserConsoleAppender = BrowserConsoleAppender;
- /* ---------------------------------------------------------------------- */
- // AjaxAppender related
-
- var xhrFactory = function() { return new XMLHttpRequest(); };
- var xmlHttpFactories = [
- xhrFactory,
- function() { return new ActiveXObject("Msxml2.XMLHTTP"); },
- function() { return new ActiveXObject("Microsoft.XMLHTTP"); }
- ];
-
- var withCredentialsSupported = false;
- var getXmlHttp = function(errorHandler) {
- // This is only run the first time; the value of getXmlHttp gets
- // replaced with the factory that succeeds on the first run
- var xmlHttp = null, factory;
- for (var i = 0, len = xmlHttpFactories.length; i < len; i++) {
- factory = xmlHttpFactories[i];
- try {
- xmlHttp = factory();
- withCredentialsSupported = (factory == xhrFactory && ("withCredentials" in xmlHttp));
- getXmlHttp = factory;
- return xmlHttp;
- } catch (e) {
- }
- }
- // If we're here, all factories have failed, so throw an error
- if (errorHandler) {
- errorHandler();
- } else {
- handleError("getXmlHttp: unable to obtain XMLHttpRequest object");
- }
- };
-
- function isHttpRequestSuccessful(xmlHttp) {
- return isUndefined(xmlHttp.status) || xmlHttp.status === 0 ||
- (xmlHttp.status >= 200 && xmlHttp.status < 300) ||
- xmlHttp.status == 1223 /* Fix for IE */;
- }
-
- /* ---------------------------------------------------------------------- */
- // AjaxAppender
-
- function AjaxAppender(url, withCredentials) {
- var appender = this;
- var isSupported = true;
- if (!url) {
- handleError("AjaxAppender: URL must be specified in constructor");
- isSupported = false;
- }
-
- var timed = this.defaults.timed;
- var waitForResponse = this.defaults.waitForResponse;
- var batchSize = this.defaults.batchSize;
- var timerInterval = this.defaults.timerInterval;
- var requestSuccessCallback = this.defaults.requestSuccessCallback;
- var failCallback = this.defaults.failCallback;
- var postVarName = this.defaults.postVarName;
- var sendAllOnUnload = this.defaults.sendAllOnUnload;
- var contentType = this.defaults.contentType;
- var sessionId = null;
-
- var queuedLoggingEvents = [];
- var queuedRequests = [];
- var headers = [];
- var sending = false;
- var initialized = false;
-
- // Configuration methods. The function scope is used to prevent
- // direct alteration to the appender configuration properties.
- function checkCanConfigure(configOptionName) {
- if (initialized) {
- handleError("AjaxAppender: configuration option '" +
- configOptionName +
- "' may not be set after the appender has been initialized");
- return false;
- }
- return true;
- }
-
- this.getSessionId = function() { return sessionId; };
- this.setSessionId = function(sessionIdParam) {
- sessionId = extractStringFromParam(sessionIdParam, null);
- this.layout.setCustomField("sessionid", sessionId);
- };
-
- this.setLayout = function(layoutParam) {
- if (checkCanConfigure("layout")) {
- this.layout = layoutParam;
- // Set the session id as a custom field on the layout, if not already present
- if (sessionId !== null) {
- this.setSessionId(sessionId);
- }
- }
- };
-
- this.isTimed = function() { return timed; };
- this.setTimed = function(timedParam) {
- if (checkCanConfigure("timed")) {
- timed = bool(timedParam);
- }
- };
-
- this.getTimerInterval = function() { return timerInterval; };
- this.setTimerInterval = function(timerIntervalParam) {
- if (checkCanConfigure("timerInterval")) {
- timerInterval = extractIntFromParam(timerIntervalParam, timerInterval);
- }
- };
-
- this.isWaitForResponse = function() { return waitForResponse; };
- this.setWaitForResponse = function(waitForResponseParam) {
- if (checkCanConfigure("waitForResponse")) {
- waitForResponse = bool(waitForResponseParam);
- }
- };
-
- this.getBatchSize = function() { return batchSize; };
- this.setBatchSize = function(batchSizeParam) {
- if (checkCanConfigure("batchSize")) {
- batchSize = extractIntFromParam(batchSizeParam, batchSize);
- }
- };
-
- this.isSendAllOnUnload = function() { return sendAllOnUnload; };
- this.setSendAllOnUnload = function(sendAllOnUnloadParam) {
- if (checkCanConfigure("sendAllOnUnload")) {
- sendAllOnUnload = extractBooleanFromParam(sendAllOnUnloadParam, sendAllOnUnload);
- }
- };
-
- this.setRequestSuccessCallback = function(requestSuccessCallbackParam) {
- requestSuccessCallback = extractFunctionFromParam(requestSuccessCallbackParam, requestSuccessCallback);
- };
-
- this.setFailCallback = function(failCallbackParam) {
- failCallback = extractFunctionFromParam(failCallbackParam, failCallback);
- };
-
- this.getPostVarName = function() { return postVarName; };
- this.setPostVarName = function(postVarNameParam) {
- if (checkCanConfigure("postVarName")) {
- postVarName = extractStringFromParam(postVarNameParam, postVarName);
- }
- };
-
- this.getHeaders = function() { return headers; };
- this.addHeader = function(name, value) {
- if (name.toLowerCase() == "content-type") {
- contentType = value;
- } else {
- headers.push( { name: name, value: value } );
- }
- };
-
- // Internal functions
- function sendAll() {
- if (isSupported && enabled) {
- sending = true;
- var currentRequestBatch;
- if (waitForResponse) {
- // Send the first request then use this function as the callback once
- // the response comes back
- if (queuedRequests.length > 0) {
- currentRequestBatch = queuedRequests.shift();
- sendRequest(preparePostData(currentRequestBatch), sendAll);
- } else {
- sending = false;
- if (timed) {
- scheduleSending();
- }
- }
- } else {
- // Rattle off all the requests without waiting to see the response
- while ((currentRequestBatch = queuedRequests.shift())) {
- sendRequest(preparePostData(currentRequestBatch));
- }
- sending = false;
- if (timed) {
- scheduleSending();
- }
- }
- }
- }
-
- this.sendAll = sendAll;
-
- // Called when the window unloads. At this point we're past caring about
- // waiting for responses or timers or incomplete batches - everything
- // must go, now
- function sendAllRemaining() {
- var sendingAnything = false;
- if (isSupported && enabled) {
- // Create requests for everything left over, batched as normal
- var actualBatchSize = appender.getLayout().allowBatching() ? batchSize : 1;
- var currentLoggingEvent;
- var batchedLoggingEvents = [];
- while ((currentLoggingEvent = queuedLoggingEvents.shift())) {
- batchedLoggingEvents.push(currentLoggingEvent);
- if (queuedLoggingEvents.length >= actualBatchSize) {
- // Queue this batch of log entries
- queuedRequests.push(batchedLoggingEvents);
- batchedLoggingEvents = [];
- }
- }
- // If there's a partially completed batch, add it
- if (batchedLoggingEvents.length > 0) {
- queuedRequests.push(batchedLoggingEvents);
- }
- sendingAnything = (queuedRequests.length > 0);
- waitForResponse = false;
- timed = false;
- sendAll();
- }
- return sendingAnything;
- }
-
- this.sendAllRemaining = sendAllRemaining;
-
- function preparePostData(batchedLoggingEvents) {
- // Format the logging events
- var formattedMessages = [];
- var currentLoggingEvent;
- var postData = "";
- while ((currentLoggingEvent = batchedLoggingEvents.shift())) {
- formattedMessages.push( appender.getLayout().formatWithException(currentLoggingEvent) );
- }
- // Create the post data string
- if (batchedLoggingEvents.length == 1) {
- postData = formattedMessages.join("");
- } else {
- postData = appender.getLayout().batchHeader +
- formattedMessages.join(appender.getLayout().batchSeparator) +
- appender.getLayout().batchFooter;
- }
- if (contentType == appender.defaults.contentType) {
- postData = appender.getLayout().returnsPostData ? postData :
- urlEncode(postVarName) + "=" + urlEncode(postData);
- // Add the layout name to the post data
- if (postData.length > 0) {
- postData += "&";
- }
- postData += "layout=" + urlEncode(appender.getLayout().toString());
- }
- return postData;
- }
-
- function scheduleSending() {
- window.setTimeout(sendAll, timerInterval);
- }
-
- function xmlHttpErrorHandler() {
- var msg = "AjaxAppender: could not create XMLHttpRequest object. AjaxAppender disabled";
- handleError(msg);
- isSupported = false;
- if (failCallback) {
- failCallback(msg);
- }
- }
-
- function sendRequest(postData, successCallback) {
- try {
- var xmlHttp = getXmlHttp(xmlHttpErrorHandler);
- if (isSupported) {
- xmlHttp.onreadystatechange = function() {
- if (xmlHttp.readyState == 4) {
- if (isHttpRequestSuccessful(xmlHttp)) {
- if (requestSuccessCallback) {
- requestSuccessCallback(xmlHttp);
- }
- if (successCallback) {
- successCallback(xmlHttp);
- }
- } else {
- var msg = "AjaxAppender.append: XMLHttpRequest request to URL " +
- url + " returned status code " + xmlHttp.status;
- handleError(msg);
- if (failCallback) {
- failCallback(msg);
- }
- }
- xmlHttp.onreadystatechange = emptyFunction;
- xmlHttp = null;
- }
- };
- xmlHttp.open("POST", url, true);
- // Add withCredentials to facilitate CORS requests with cookies
- if (withCredentials && withCredentialsSupported) {
- xmlHttp.withCredentials = true;
- }
- try {
- for (var i = 0, header; header = headers[i++]; ) {
- xmlHttp.setRequestHeader(header.name, header.value);
- }
- xmlHttp.setRequestHeader("Content-Type", contentType);
- } catch (headerEx) {
- var msg = "AjaxAppender.append: your browser's XMLHttpRequest implementation" +
- " does not support setRequestHeader, therefore cannot post data. AjaxAppender disabled";
- handleError(msg);
- isSupported = false;
- if (failCallback) {
- failCallback(msg);
- }
- return;
- }
- xmlHttp.send(postData);
- }
- } catch (ex) {
- var errMsg = "AjaxAppender.append: error sending log message to " + url;
- handleError(errMsg, ex);
- isSupported = false;
- if (failCallback) {
- failCallback(errMsg + ". Details: " + getExceptionStringRep(ex));
- }
- }
- }
-
- this.append = function(loggingEvent) {
- if (isSupported) {
- if (!initialized) {
- init();
- }
- queuedLoggingEvents.push(loggingEvent);
- var actualBatchSize = this.getLayout().allowBatching() ? batchSize : 1;
-
- if (queuedLoggingEvents.length >= actualBatchSize) {
- var currentLoggingEvent;
- var batchedLoggingEvents = [];
- while ((currentLoggingEvent = queuedLoggingEvents.shift())) {
- batchedLoggingEvents.push(currentLoggingEvent);
- }
- // Queue this batch of log entries
- queuedRequests.push(batchedLoggingEvents);
-
- // If using a timer, the queue of requests will be processed by the
- // timer function, so nothing needs to be done here.
- if (!timed && (!waitForResponse || (waitForResponse && !sending))) {
- sendAll();
- }
- }
- }
- };
-
- function init() {
- initialized = true;
- // Add unload event to send outstanding messages
- if (sendAllOnUnload) {
- var oldBeforeUnload = window.onbeforeunload;
- window.onbeforeunload = function() {
- if (oldBeforeUnload) {
- oldBeforeUnload();
- }
- sendAllRemaining();
- };
- }
- // Start timer
- if (timed) {
- scheduleSending();
- }
- }
- }
-
- AjaxAppender.prototype = new Appender();
-
- AjaxAppender.prototype.defaults = {
- waitForResponse: false,
- timed: false,
- timerInterval: 1000,
- batchSize: 1,
- sendAllOnUnload: false,
- requestSuccessCallback: null,
- failCallback: null,
- postVarName: "data",
- contentType: "application/x-www-form-urlencoded"
- };
-
- AjaxAppender.prototype.layout = new HttpPostDataLayout();
-
- AjaxAppender.prototype.toString = function() {
- return "AjaxAppender";
- };
-
- log4javascript.AjaxAppender = AjaxAppender;
- /* ---------------------------------------------------------------------- */
- // PopUpAppender and InPageAppender related
-
- function setCookie(name, value, days, path) {
- var expires;
- path = path ? "; path=" + path : "";
- if (days) {
- var date = new Date();
- date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
- expires = "; expires=" + date.toGMTString();
- } else {
- expires = "";
- }
- document.cookie = escape(name) + "=" + escape(value) + expires + path;
- }
-
- function getCookie(name) {
- var nameEquals = escape(name) + "=";
- var ca = document.cookie.split(";");
- for (var i = 0, len = ca.length; i < len; i++) {
- var c = ca[i];
- while (c.charAt(0) === " ") {
- c = c.substring(1, c.length);
- }
- if (c.indexOf(nameEquals) === 0) {
- return unescape(c.substring(nameEquals.length, c.length));
- }
- }
- return null;
- }
-
- // Gets the base URL of the location of the log4javascript script.
- // This is far from infallible.
- function getBaseUrl() {
- var scripts = document.getElementsByTagName("script");
- for (var i = 0, len = scripts.length; i < len; ++i) {
- if (scripts[i].src.indexOf("log4javascript") != -1) {
- var lastSlash = scripts[i].src.lastIndexOf("/");
- return (lastSlash == -1) ? "" : scripts[i].src.substr(0, lastSlash + 1);
- }
- }
- return null;
- }
-
- function isLoaded(win) {
- try {
- return bool(win.loaded);
- } catch (ex) {
- return false;
- }
- }
-
- /* ---------------------------------------------------------------------- */
- // ConsoleAppender (prototype for PopUpAppender and InPageAppender)
-
- var ConsoleAppender;
-
- // Create an anonymous function to protect base console methods
- (function() {
- var getConsoleHtmlLines = function() {
- return [
- '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">',
- '<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">',
- ' <head>',
- ' <title>log4javascript</title>',
- ' <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />',
- ' <!-- Make IE8 behave like IE7, having gone to all the trouble of making IE work -->',
- ' <meta http-equiv="X-UA-Compatible" content="IE=7" />',
- ' <script type="text/javascript">var isIe = false, isIePre7 = false;</script>',
- ' <!--[if IE]><script type="text/javascript">isIe = true</script><![endif]-->',
- ' <!--[if lt IE 7]><script type="text/javascript">isIePre7 = true</script><![endif]-->',
- ' <script type="text/javascript">',
- ' //<![CDATA[',
- ' var loggingEnabled = true;',
- ' var logQueuedEventsTimer = null;',
- ' var logEntries = [];',
- ' var logEntriesAndSeparators = [];',
- ' var logItems = [];',
- ' var renderDelay = 100;',
- ' var unrenderedLogItemsExist = false;',
- ' var rootGroup, currentGroup = null;',
- ' var loaded = false;',
- ' var currentLogItem = null;',
- ' var logMainContainer;',
- '',
- ' function copyProperties(obj, props) {',
- ' for (var i in props) {',
- ' obj[i] = props[i];',
- ' }',
- ' }',
- '',
- ' /*----------------------------------------------------------------*/',
- '',
- ' function LogItem() {',
- ' }',
- '',
- ' LogItem.prototype = {',
- ' mainContainer: null,',
- ' wrappedContainer: null,',
- ' unwrappedContainer: null,',
- ' group: null,',
- '',
- ' appendToLog: function() {',
- ' for (var i = 0, len = this.elementContainers.length; i < len; i++) {',
- ' this.elementContainers[i].appendToLog();',
- ' }',
- ' this.group.update();',
- ' },',
- '',
- ' doRemove: function(doUpdate, removeFromGroup) {',
- ' if (this.rendered) {',
- ' for (var i = 0, len = this.elementContainers.length; i < len; i++) {',
- ' this.elementContainers[i].remove();',
- ' }',
- ' this.unwrappedElementContainer = null;',
- ' this.wrappedElementContainer = null;',
- ' this.mainElementContainer = null;',
- ' }',
- ' if (this.group && removeFromGroup) {',
- ' this.group.removeChild(this, doUpdate);',
- ' }',
- ' if (this === currentLogItem) {',
- ' currentLogItem = null;',
- ' }',
- ' },',
- '',
- ' remove: function(doUpdate, removeFromGroup) {',
- ' this.doRemove(doUpdate, removeFromGroup);',
- ' },',
- '',
- ' render: function() {},',
- '',
- ' accept: function(visitor) {',
- ' visitor.visit(this);',
- ' },',
- '',
- ' getUnwrappedDomContainer: function() {',
- ' return this.group.unwrappedElementContainer.contentDiv;',
- ' },',
- '',
- ' getWrappedDomContainer: function() {',
- ' return this.group.wrappedElementContainer.contentDiv;',
- ' },',
- '',
- ' getMainDomContainer: function() {',
- ' return this.group.mainElementContainer.contentDiv;',
- ' }',
- ' };',
- '',
- ' LogItem.serializedItemKeys = {LOG_ENTRY: 0, GROUP_START: 1, GROUP_END: 2};',
- '',
- ' /*----------------------------------------------------------------*/',
- '',
- ' function LogItemContainerElement() {',
- ' }',
- '',
- ' LogItemContainerElement.prototype = {',
- ' appendToLog: function() {',
- ' var insertBeforeFirst = (newestAtTop && this.containerDomNode.hasChildNodes());',
- ' if (insertBeforeFirst) {',
- ' this.containerDomNode.insertBefore(this.mainDiv, this.containerDomNode.firstChild);',
- ' } else {',
- ' this.containerDomNode.appendChild(this.mainDiv);',
- ' }',
- ' }',
- ' };',
- '',
- ' /*----------------------------------------------------------------*/',
- '',
- ' function SeparatorElementContainer(containerDomNode) {',
- ' this.containerDomNode = containerDomNode;',
- ' this.mainDiv = document.createElement("div");',
- ' this.mainDiv.className = "separator";',
- ' this.mainDiv.innerHTML = " ";',
- ' }',
- '',
- ' SeparatorElementContainer.prototype = new LogItemContainerElement();',
- '',
- ' SeparatorElementContainer.prototype.remove = function() {',
- ' this.mainDiv.parentNode.removeChild(this.mainDiv);',
- ' this.mainDiv = null;',
- ' };',
- '',
- ' /*----------------------------------------------------------------*/',
- '',
- ' function Separator() {',
- ' this.rendered = false;',
- ' }',
- '',
- ' Separator.prototype = new LogItem();',
- '',
- ' copyProperties(Separator.prototype, {',
- ' render: function() {',
- ' var containerDomNode = this.group.contentDiv;',
- ' if (isIe) {',
- ' this.unwrappedElementContainer = new SeparatorElementContainer(this.getUnwrappedDomContainer());',
- ' this.wrappedElementContainer = new SeparatorElementContainer(this.getWrappedDomContainer());',
- ' this.elementContainers = [this.unwrappedElementContainer, this.wrappedElementContainer];',
- ' } else {',
- ' this.mainElementContainer = new SeparatorElementContainer(this.getMainDomContainer());',
- ' this.elementContainers = [this.mainElementContainer];',
- ' }',
- ' this.content = this.formattedMessage;',
- ' this.rendered = true;',
- ' }',
- ' });',
- '',
- ' /*----------------------------------------------------------------*/',
- '',
- ' function GroupElementContainer(group, containerDomNode, isRoot, isWrapped) {',
- ' this.group = group;',
- ' this.containerDomNode = containerDomNode;',
- ' this.isRoot = isRoot;',
- ' this.isWrapped = isWrapped;',
- ' this.expandable = false;',
- '',
- ' if (this.isRoot) {',
- ' if (isIe) {',
- ' this.contentDiv = logMainContainer.appendChild(document.createElement("div"));',
- ' this.contentDiv.id = this.isWrapped ? "log_wrapped" : "log_unwrapped";',
- ' } else {',
- ' this.contentDiv = logMainContainer;',
- ' }',
- ' } else {',
- ' var groupElementContainer = this;',
- ' ',
- ' this.mainDiv = document.createElement("div");',
- ' this.mainDiv.className = "group";',
- '',
- ' this.headingDiv = this.mainDiv.appendChild(document.createElement("div"));',
- ' this.headingDiv.className = "groupheading";',
- '',
- ' this.expander = this.headingDiv.appendChild(document.createElement("span"));',
- ' this.expander.className = "expander unselectable greyedout";',
- ' this.expander.unselectable = true;',
- ' var expanderText = this.group.expanded ? "-" : "+";',
- ' this.expanderTextNode = this.expander.appendChild(document.createTextNode(expanderText));',
- ' ',
- ' this.headingDiv.appendChild(document.createTextNode(" " + this.group.name));',
- '',
- ' this.contentDiv = this.mainDiv.appendChild(document.createElement("div"));',
- ' var contentCssClass = this.group.expanded ? "expanded" : "collapsed";',
- ' this.contentDiv.className = "groupcontent " + contentCssClass;',
- '',
- ' this.expander.onclick = function() {',
- ' if (groupElementContainer.group.expandable) {',
- ' groupElementContainer.group.toggleExpanded();',
- ' }',
- ' };',
- ' }',
- ' }',
- '',
- ' GroupElementContainer.prototype = new LogItemContainerElement();',
- '',
- ' copyProperties(GroupElementContainer.prototype, {',
- ' toggleExpanded: function() {',
- ' if (!this.isRoot) {',
- ' var oldCssClass, newCssClass, expanderText;',
- ' if (this.group.expanded) {',
- ' newCssClass = "expanded";',
- ' oldCssClass = "collapsed";',
- ' expanderText = "-";',
- ' } else {',
- ' newCssClass = "collapsed";',
- ' oldCssClass = "expanded";',
- ' expanderText = "+";',
- ' }',
- ' replaceClass(this.contentDiv, newCssClass, oldCssClass);',
- ' this.expanderTextNode.nodeValue = expanderText;',
- ' }',
- ' },',
- '',
- ' remove: function() {',
- ' if (!this.isRoot) {',
- ' this.headingDiv = null;',
- ' this.expander.onclick = null;',
- ' this.expander = null;',
- ' this.expanderTextNode = null;',
- ' this.contentDiv = null;',
- ' this.containerDomNode = null;',
- ' this.mainDiv.parentNode.removeChild(this.mainDiv);',
- ' this.mainDiv = null;',
- ' }',
- ' },',
- '',
- ' reverseChildren: function() {',
- ' // Invert the order of the log entries',
- ' var node = null;',
- '',
- ' // Remove all the log container nodes',
- ' var childDomNodes = [];',
- ' while ((node = this.contentDiv.firstChild)) {',
- ' this.contentDiv.removeChild(node);',
- ' childDomNodes.push(node);',
- ' }',
- '',
- ' // Put them all back in reverse order',
- ' while ((node = childDomNodes.pop())) {',
- ' this.contentDiv.appendChild(node);',
- ' }',
- ' },',
- '',
- ' update: function() {',
- ' if (!this.isRoot) {',
- ' if (this.group.expandable) {',
- ' removeClass(this.expander, "greyedout");',
- ' } else {',
- ' addClass(this.expander, "greyedout");',
- ' }',
- ' }',
- ' },',
- '',
- ' clear: function() {',
- ' if (this.isRoot) {',
- ' this.contentDiv.innerHTML = "";',
- ' }',
- ' }',
- ' });',
- '',
- ' /*----------------------------------------------------------------*/',
- '',
- ' function Group(name, isRoot, initiallyExpanded) {',
- ' this.name = name;',
- ' this.group = null;',
- ' this.isRoot = isRoot;',
- ' this.initiallyExpanded = initiallyExpanded;',
- ' this.elementContainers = [];',
- ' this.children = [];',
- ' this.expanded = initiallyExpanded;',
- ' this.rendered = false;',
- ' this.expandable = false;',
- ' }',
- '',
- ' Group.prototype = new LogItem();',
- '',
- ' copyProperties(Group.prototype, {',
- ' addChild: function(logItem) {',
- ' this.children.push(logItem);',
- ' logItem.group = this;',
- ' },',
- '',
- ' render: function() {',
- ' if (isIe) {',
- ' var unwrappedDomContainer, wrappedDomContainer;',
- ' if (this.isRoot) {',
- ' unwrappedDomContainer = logMainContainer;',
- ' wrappedDomContainer = logMainContainer;',
- ' } else {',
- ' unwrappedDomContainer = this.getUnwrappedDomContainer();',
- ' wrappedDomContainer = this.getWrappedDomContainer();',
- ' }',
- ' this.unwrappedElementContainer = new GroupElementContainer(this, unwrappedDomContainer, this.isRoot, false);',
- ' this.wrappedElementContainer = new GroupElementContainer(this, wrappedDomContainer, this.isRoot, true);',
- ' this.elementContainers = [this.unwrappedElementContainer, this.wrappedElementContainer];',
- ' } else {',
- ' var mainDomContainer = this.isRoot ? logMainContainer : this.getMainDomContainer();',
- ' this.mainElementContainer = new GroupElementContainer(this, mainDomContainer, this.isRoot, false);',
- ' this.elementContainers = [this.mainElementContainer];',
- ' }',
- ' this.rendered = true;',
- ' },',
- '',
- ' toggleExpanded: function() {',
- ' this.expanded = !this.expanded;',
- ' for (var i = 0, len = this.elementContainers.length; i < len; i++) {',
- ' this.elementContainers[i].toggleExpanded();',
- ' }',
- ' },',
- '',
- ' expand: function() {',
- ' if (!this.expanded) {',
- ' this.toggleExpanded();',
- ' }',
- ' },',
- '',
- ' accept: function(visitor) {',
- ' visitor.visitGroup(this);',
- ' },',
- '',
- ' reverseChildren: function() {',
- ' if (this.rendered) {',
- ' for (var i = 0, len = this.elementContainers.length; i < len; i++) {',
- ' this.elementContainers[i].reverseChildren();',
- ' }',
- ' }',
- ' },',
- '',
- ' update: function() {',
- ' var previouslyExpandable = this.expandable;',
- ' this.expandable = (this.children.length !== 0);',
- ' if (this.expandable !== previouslyExpandable) {',
- ' for (var i = 0, len = this.elementContainers.length; i < len; i++) {',
- ' this.elementContainers[i].update();',
- ' }',
- ' }',
- ' },',
- '',
- ' flatten: function() {',
- ' var visitor = new GroupFlattener();',
- ' this.accept(visitor);',
- ' return visitor.logEntriesAndSeparators;',
- ' },',
- '',
- ' removeChild: function(child, doUpdate) {',
- ' array_remove(this.children, child);',
- ' child.group = null;',
- ' if (doUpdate) {',
- ' this.update();',
- ' }',
- ' },',
- '',
- ' remove: function(doUpdate, removeFromGroup) {',
- ' for (var i = 0, len = this.children.length; i < len; i++) {',
- ' this.children[i].remove(false, false);',
- ' }',
- ' this.children = [];',
- ' this.update();',
- ' if (this === currentGroup) {',
- ' currentGroup = this.group;',
- ' }',
- ' this.doRemove(doUpdate, removeFromGroup);',
- ' },',
- '',
- ' serialize: function(items) {',
- ' items.push([LogItem.serializedItemKeys.GROUP_START, this.name]);',
- ' for (var i = 0, len = this.children.length; i < len; i++) {',
- ' this.children[i].serialize(items);',
- ' }',
- ' if (this !== currentGroup) {',
- ' items.push([LogItem.serializedItemKeys.GROUP_END]);',
- ' }',
- ' },',
- '',
- ' clear: function() {',
- ' for (var i = 0, len = this.elementContainers.length; i < len; i++) {',
- ' this.elementContainers[i].clear();',
- ' }',
- ' }',
- ' });',
- '',
- ' /*----------------------------------------------------------------*/',
- '',
- ' function LogEntryElementContainer() {',
- ' }',
- '',
- ' LogEntryElementContainer.prototype = new LogItemContainerElement();',
- '',
- ' copyProperties(LogEntryElementContainer.prototype, {',
- ' remove: function() {',
- ' this.doRemove();',
- ' },',
- '',
- ' doRemove: function() {',
- ' this.mainDiv.parentNode.removeChild(this.mainDiv);',
- ' this.mainDiv = null;',
- ' this.contentElement = null;',
- ' this.containerDomNode = null;',
- ' },',
- '',
- ' setContent: function(content, wrappedContent) {',
- ' if (content === this.formattedMessage) {',
- ' this.contentElement.innerHTML = "";',
- ' this.contentElement.appendChild(document.createTextNode(this.formattedMessage));',
- ' } else {',
- ' this.contentElement.innerHTML = content;',
- ' }',
- ' },',
- '',
- ' setSearchMatch: function(isMatch) {',
- ' var oldCssClass = isMatch ? "searchnonmatch" : "searchmatch";',
- ' var newCssClass = isMatch ? "searchmatch" : "searchnonmatch";',
- ' replaceClass(this.mainDiv, newCssClass, oldCssClass);',
- ' },',
- '',
- ' clearSearch: function() {',
- ' removeClass(this.mainDiv, "searchmatch");',
- ' removeClass(this.mainDiv, "searchnonmatch");',
- ' }',
- ' });',
- '',
- ' /*----------------------------------------------------------------*/',
- '',
- ' function LogEntryWrappedElementContainer(logEntry, containerDomNode) {',
- ' this.logEntry = logEntry;',
- ' this.containerDomNode = containerDomNode;',
- ' this.mainDiv = document.createElement("div");',
- ' this.mainDiv.appendChild(document.createTextNode(this.logEntry.formattedMessage));',
- ' this.mainDiv.className = "logentry wrapped " + this.logEntry.level;',
- ' this.contentElement = this.mainDiv;',
- ' }',
- '',
- ' LogEntryWrappedElementContainer.prototype = new LogEntryElementContainer();',
- '',
- ' LogEntryWrappedElementContainer.prototype.setContent = function(content, wrappedContent) {',
- ' if (content === this.formattedMessage) {',
- ' this.contentElement.innerHTML = "";',
- ' this.contentElement.appendChild(document.createTextNode(this.formattedMessage));',
- ' } else {',
- ' this.contentElement.innerHTML = wrappedContent;',
- ' }',
- ' };',
- '',
- ' /*----------------------------------------------------------------*/',
- '',
- ' function LogEntryUnwrappedElementContainer(logEntry, containerDomNode) {',
- ' this.logEntry = logEntry;',
- ' this.containerDomNode = containerDomNode;',
- ' this.mainDiv = document.createElement("div");',
- ' this.mainDiv.className = "logentry unwrapped " + this.logEntry.level;',
- ' this.pre = this.mainDiv.appendChild(document.createElement("pre"));',
- ' this.pre.appendChild(document.createTextNode(this.logEntry.formattedMessage));',
- ' this.pre.className = "unwrapped";',
- ' this.contentElement = this.pre;',
- ' }',
- '',
- ' LogEntryUnwrappedElementContainer.prototype = new LogEntryElementContainer();',
- '',
- ' LogEntryUnwrappedElementContainer.prototype.remove = function() {',
- ' this.doRemove();',
- ' this.pre = null;',
- ' };',
- '',
- ' /*----------------------------------------------------------------*/',
- '',
- ' function LogEntryMainElementContainer(logEntry, containerDomNode) {',
- ' this.logEntry = logEntry;',
- ' this.containerDomNode = containerDomNode;',
- ' this.mainDiv = document.createElement("div");',
- ' this.mainDiv.className = "logentry nonielogentry " + this.logEntry.level;',
- ' this.contentElement = this.mainDiv.appendChild(document.createElement("span"));',
- ' this.contentElement.appendChild(document.createTextNode(this.logEntry.formattedMessage));',
- ' }',
- '',
- ' LogEntryMainElementContainer.prototype = new LogEntryElementContainer();',
- '',
- ' /*----------------------------------------------------------------*/',
- '',
- ' function LogEntry(level, formattedMessage) {',
- ' this.level = level;',
- ' this.formattedMessage = formattedMessage;',
- ' this.rendered = false;',
- ' }',
- '',
- ' LogEntry.prototype = new LogItem();',
- '',
- ' copyProperties(LogEntry.prototype, {',
- ' render: function() {',
- ' var logEntry = this;',
- ' var containerDomNode = this.group.contentDiv;',
- '',
- ' // Support for the CSS attribute white-space in IE for Windows is',
- ' // non-existent pre version 6 and slightly odd in 6, so instead',
- ' // use two different HTML elements',
- ' if (isIe) {',
- ' this.formattedMessage = this.formattedMessage.replace(/\\r\\n/g, "\\r"); // Workaround for IE\'s treatment of white space',
- ' this.unwrappedElementContainer = new LogEntryUnwrappedElementContainer(this, this.getUnwrappedDomContainer());',
- ' this.wrappedElementContainer = new LogEntryWrappedElementContainer(this, this.getWrappedDomContainer());',
- ' this.elementContainers = [this.unwrappedElementContainer, this.wrappedElementContainer];',
- ' } else {',
- ' this.mainElementContainer = new LogEntryMainElementContainer(this, this.getMainDomContainer());',
- ' this.elementContainers = [this.mainElementContainer];',
- ' }',
- ' this.content = this.formattedMessage;',
- ' this.rendered = true;',
- ' },',
- '',
- ' setContent: function(content, wrappedContent) {',
- ' if (content != this.content) {',
- ' if (isIe && (content !== this.formattedMessage)) {',
- ' content = content.replace(/\\r\\n/g, "\\r"); // Workaround for IE\'s treatment of white space',
- ' }',
- ' for (var i = 0, len = this.elementContainers.length; i < len; i++) {',
- ' this.elementContainers[i].setContent(content, wrappedContent);',
- ' }',
- ' this.content = content;',
- ' }',
- ' },',
- '',
- ' getSearchMatches: function() {',
- ' var matches = [];',
- ' var i, len;',
- ' if (isIe) {',
- ' var unwrappedEls = getElementsByClass(this.unwrappedElementContainer.mainDiv, "searchterm", "span");',
- ' var wrappedEls = getElementsByClass(this.wrappedElementContainer.mainDiv, "searchterm", "span");',
- ' for (i = 0, len = unwrappedEls.length; i < len; i++) {',
- ' matches[i] = new Match(this.level, null, unwrappedEls[i], wrappedEls[i]);',
- ' }',
- ' } else {',
- ' var els = getElementsByClass(this.mainElementContainer.mainDiv, "searchterm", "span");',
- ' for (i = 0, len = els.length; i < len; i++) {',
- ' matches[i] = new Match(this.level, els[i]);',
- ' }',
- ' }',
- ' return matches;',
- ' },',
- '',
- ' setSearchMatch: function(isMatch) {',
- ' for (var i = 0, len = this.elementContainers.length; i < len; i++) {',
- ' this.elementContainers[i].setSearchMatch(isMatch);',
- ' }',
- ' },',
- '',
- ' clearSearch: function() {',
- ' for (var i = 0, len = this.elementContainers.length; i < len; i++) {',
- ' this.elementContainers[i].clearSearch();',
- ' }',
- ' },',
- '',
- ' accept: function(visitor) {',
- ' visitor.visitLogEntry(this);',
- ' },',
- '',
- ' serialize: function(items) {',
- ' items.push([LogItem.serializedItemKeys.LOG_ENTRY, this.level, this.formattedMessage]);',
- ' }',
- ' });',
- '',
- ' /*----------------------------------------------------------------*/',
- '',
- ' function LogItemVisitor() {',
- ' }',
- '',
- ' LogItemVisitor.prototype = {',
- ' visit: function(logItem) {',
- ' },',
- '',
- ' visitParent: function(logItem) {',
- ' if (logItem.group) {',
- ' logItem.group.accept(this);',
- ' }',
- ' },',
- '',
- ' visitChildren: function(logItem) {',
- ' for (var i = 0, len = logItem.children.length; i < len; i++) {',
- ' logItem.children[i].accept(this);',
- ' }',
- ' },',
- '',
- ' visitLogEntry: function(logEntry) {',
- ' this.visit(logEntry);',
- ' },',
- '',
- ' visitSeparator: function(separator) {',
- ' this.visit(separator);',
- ' },',
- '',
- ' visitGroup: function(group) {',
- ' this.visit(group);',
- ' }',
- ' };',
- '',
- ' /*----------------------------------------------------------------*/',
- '',
- ' function GroupFlattener() {',
- ' this.logEntriesAndSeparators = [];',
- ' }',
- '',
- ' GroupFlattener.prototype = new LogItemVisitor();',
- '',
- ' GroupFlattener.prototype.visitGroup = function(group) {',
- ' this.visitChildren(group);',
- ' };',
- '',
- ' GroupFlattener.prototype.visitLogEntry = function(logEntry) {',
- ' this.logEntriesAndSeparators.push(logEntry);',
- ' };',
- '',
- ' GroupFlattener.prototype.visitSeparator = function(separator) {',
- ' this.logEntriesAndSeparators.push(separator);',
- ' };',
- '',
- ' /*----------------------------------------------------------------*/',
- '',
- ' window.onload = function() {',
- ' // Sort out document.domain',
- ' if (location.search) {',
- ' var queryBits = unescape(location.search).substr(1).split("&"), nameValueBits;',
- ' for (var i = 0, len = queryBits.length; i < len; i++) {',
- ' nameValueBits = queryBits[i].split("=");',
- ' if (nameValueBits[0] == "log4javascript_domain") {',
- ' document.domain = nameValueBits[1];',
- ' break;',
- ' }',
- ' }',
- ' }',
- '',
- ' // Create DOM objects',
- ' logMainContainer = $("log");',
- ' if (isIePre7) {',
- ' addClass(logMainContainer, "oldIe");',
- ' }',
- '',
- ' rootGroup = new Group("root", true);',
- ' rootGroup.render();',
- ' currentGroup = rootGroup;',
- ' ',
- ' setCommandInputWidth();',
- ' setLogContainerHeight();',
- ' toggleLoggingEnabled();',
- ' toggleSearchEnabled();',
- ' toggleSearchFilter();',
- ' toggleSearchHighlight();',
- ' applyFilters();',
- ' checkAllLevels();',
- ' toggleWrap();',
- ' toggleNewestAtTop();',
- ' toggleScrollToLatest();',
- ' renderQueuedLogItems();',
- ' loaded = true;',
- ' $("command").value = "";',
- ' $("command").autocomplete = "off";',
- ' $("command").onkeydown = function(evt) {',
- ' evt = getEvent(evt);',
- ' if (evt.keyCode == 10 || evt.keyCode == 13) { // Return/Enter',
- ' evalCommandLine();',
- ' stopPropagation(evt);',
- ' } else if (evt.keyCode == 27) { // Escape',
- ' this.value = "";',
- ' this.focus();',
- ' } else if (evt.keyCode == 38 && commandHistory.length > 0) { // Up',
- ' currentCommandIndex = Math.max(0, currentCommandIndex - 1);',
- ' this.value = commandHistory[currentCommandIndex];',
- ' moveCaretToEnd(this);',
- ' } else if (evt.keyCode == 40 && commandHistory.length > 0) { // Down',
- ' currentCommandIndex = Math.min(commandHistory.length - 1, currentCommandIndex + 1);',
- ' this.value = commandHistory[currentCommandIndex];',
- ' moveCaretToEnd(this);',
- ' }',
- ' };',
- '',
- ' // Prevent the keypress moving the caret in Firefox',
- ' $("command").onkeypress = function(evt) {',
- ' evt = getEvent(evt);',
- ' if (evt.keyCode == 38 && commandHistory.length > 0 && evt.preventDefault) { // Up',
- ' evt.preventDefault();',
- ' }',
- ' };',
- '',
- ' // Prevent the keyup event blurring the input in Opera',
- ' $("command").onkeyup = function(evt) {',
- ' evt = getEvent(evt);',
- ' if (evt.keyCode == 27 && evt.preventDefault) { // Up',
- ' evt.preventDefault();',
- ' this.focus();',
- ' }',
- ' };',
- '',
- ' // Add document keyboard shortcuts',
- ' document.onkeydown = function keyEventHandler(evt) {',
- ' evt = getEvent(evt);',
- ' switch (evt.keyCode) {',
- ' case 69: // Ctrl + shift + E: re-execute last command',
- ' if (evt.shiftKey && (evt.ctrlKey || evt.metaKey)) {',
- ' evalLastCommand();',
- ' cancelKeyEvent(evt);',
- ' return false;',
- ' }',
- ' break;',
- ' case 75: // Ctrl + shift + K: focus search',
- ' if (evt.shiftKey && (evt.ctrlKey || evt.metaKey)) {',
- ' focusSearch();',
- ' cancelKeyEvent(evt);',
- ' return false;',
- ' }',
- ' break;',
- ' case 40: // Ctrl + shift + down arrow: focus command line',
- ' case 76: // Ctrl + shift + L: focus command line',
- ' if (evt.shiftKey && (evt.ctrlKey || evt.metaKey)) {',
- ' focusCommandLine();',
- ' cancelKeyEvent(evt);',
- ' return false;',
- ' }',
- ' break;',
- ' }',
- ' };',
- '',
- ' // Workaround to make sure log div starts at the correct size',
- ' setTimeout(setLogContainerHeight, 20);',
- '',
- ' setShowCommandLine(showCommandLine);',
- ' doSearch();',
- ' };',
- '',
- ' window.onunload = function() {',
- ' if (mainWindowExists()) {',
- ' appender.unload();',
- ' }',
- ' appender = null;',
- ' };',
- '',
- ' /*----------------------------------------------------------------*/',
- '',
- ' function toggleLoggingEnabled() {',
- ' setLoggingEnabled($("enableLogging").checked);',
- ' }',
- '',
- ' function setLoggingEnabled(enable) {',
- ' loggingEnabled = enable;',
- ' }',
- '',
- ' var appender = null;',
- '',
- ' function setAppender(appenderParam) {',
- ' appender = appenderParam;',
- ' }',
- '',
- ' function setShowCloseButton(showCloseButton) {',
- ' $("closeButton").style.display = showCloseButton ? "inline" : "none";',
- ' }',
- '',
- ' function setShowHideButton(showHideButton) {',
- ' $("hideButton").style.display = showHideButton ? "inline" : "none";',
- ' }',
- '',
- ' var newestAtTop = false;',
- '',
- ' /*----------------------------------------------------------------*/',
- '',
- ' function LogItemContentReverser() {',
- ' }',
- ' ',
- ' LogItemContentReverser.prototype = new LogItemVisitor();',
- ' ',
- ' LogItemContentReverser.prototype.visitGroup = function(group) {',
- ' group.reverseChildren();',
- ' this.visitChildren(group);',
- ' };',
- '',
- ' /*----------------------------------------------------------------*/',
- '',
- ' function setNewestAtTop(isNewestAtTop) {',
- ' var oldNewestAtTop = newestAtTop;',
- ' var i, iLen, j, jLen;',
- ' newestAtTop = Boolean(isNewestAtTop);',
- ' if (oldNewestAtTop != newestAtTop) {',
- ' var visitor = new LogItemContentReverser();',
- ' rootGroup.accept(visitor);',
- '',
- ' // Reassemble the matches array',
- ' if (currentSearch) {',
- ' var currentMatch = currentSearch.matches[currentMatchIndex];',
- ' var matchIndex = 0;',
- ' var matches = [];',
- ' var actOnLogEntry = function(logEntry) {',
- ' var logEntryMatches = logEntry.getSearchMatches();',
- ' for (j = 0, jLen = logEntryMatches.length; j < jLen; j++) {',
- ' matches[matchIndex] = logEntryMatches[j];',
- ' if (currentMatch && logEntryMatches[j].equals(currentMatch)) {',
- ' currentMatchIndex = matchIndex;',
- ' }',
- ' matchIndex++;',
- ' }',
- ' };',
- ' if (newestAtTop) {',
- ' for (i = logEntries.length - 1; i >= 0; i--) {',
- ' actOnLogEntry(logEntries[i]);',
- ' }',
- ' } else {',
- ' for (i = 0, iLen = logEntries.length; i < iLen; i++) {',
- ' actOnLogEntry(logEntries[i]);',
- ' }',
- ' }',
- ' currentSearch.matches = matches;',
- ' if (currentMatch) {',
- ' currentMatch.setCurrent();',
- ' }',
- ' } else if (scrollToLatest) {',
- ' doScrollToLatest();',
- ' }',
- ' }',
- ' $("newestAtTop").checked = isNewestAtTop;',
- ' }',
- '',
- ' function toggleNewestAtTop() {',
- ' var isNewestAtTop = $("newestAtTop").checked;',
- ' setNewestAtTop(isNewestAtTop);',
- ' }',
- '',
- ' var scrollToLatest = true;',
- '',
- ' function setScrollToLatest(isScrollToLatest) {',
- ' scrollToLatest = isScrollToLatest;',
- ' if (scrollToLatest) {',
- ' doScrollToLatest();',
- ' }',
- ' $("scrollToLatest").checked = isScrollToLatest;',
- ' }',
- '',
- ' function toggleScrollToLatest() {',
- ' var isScrollToLatest = $("scrollToLatest").checked;',
- ' setScrollToLatest(isScrollToLatest);',
- ' }',
- '',
- ' function doScrollToLatest() {',
- ' var l = logMainContainer;',
- ' if (typeof l.scrollTop != "undefined") {',
- ' if (newestAtTop) {',
- ' l.scrollTop = 0;',
- ' } else {',
- ' var latestLogEntry = l.lastChild;',
- ' if (latestLogEntry) {',
- ' l.scrollTop = l.scrollHeight;',
- ' }',
- ' }',
- ' }',
- ' }',
- '',
- ' var closeIfOpenerCloses = true;',
- '',
- ' function setCloseIfOpenerCloses(isCloseIfOpenerCloses) {',
- ' closeIfOpenerCloses = isCloseIfOpenerCloses;',
- ' }',
- '',
- ' var maxMessages = null;',
- '',
- ' function setMaxMessages(max) {',
- ' maxMessages = max;',
- ' pruneLogEntries();',
- ' }',
- '',
- ' var showCommandLine = false;',
- '',
- ' function setShowCommandLine(isShowCommandLine) {',
- ' showCommandLine = isShowCommandLine;',
- ' if (loaded) {',
- ' $("commandLine").style.display = showCommandLine ? "block" : "none";',
- ' setCommandInputWidth();',
- ' setLogContainerHeight();',
- ' }',
- ' }',
- '',
- ' function focusCommandLine() {',
- ' if (loaded) {',
- ' $("command").focus();',
- ' }',
- ' }',
- '',
- ' function focusSearch() {',
- ' if (loaded) {',
- ' $("searchBox").focus();',
- ' }',
- ' }',
- '',
- ' function getLogItems() {',
- ' var items = [];',
- ' for (var i = 0, len = logItems.length; i < len; i++) {',
- ' logItems[i].serialize(items);',
- ' }',
- ' return items;',
- ' }',
- '',
- ' function setLogItems(items) {',
- ' var loggingReallyEnabled = loggingEnabled;',
- ' // Temporarily turn logging on',
- ' loggingEnabled = true;',
- ' for (var i = 0, len = items.length; i < len; i++) {',
- ' switch (items[i][0]) {',
- ' case LogItem.serializedItemKeys.LOG_ENTRY:',
- ' log(items[i][1], items[i][2]);',
- ' break;',
- ' case LogItem.serializedItemKeys.GROUP_START:',
- ' group(items[i][1]);',
- ' break;',
- ' case LogItem.serializedItemKeys.GROUP_END:',
- ' groupEnd();',
- ' break;',
- ' }',
- ' }',
- ' loggingEnabled = loggingReallyEnabled;',
- ' }',
- '',
- ' function log(logLevel, formattedMessage) {',
- ' if (loggingEnabled) {',
- ' var logEntry = new LogEntry(logLevel, formattedMessage);',
- ' logEntries.push(logEntry);',
- ' logEntriesAndSeparators.push(logEntry);',
- ' logItems.push(logEntry);',
- ' currentGroup.addChild(logEntry);',
- ' if (loaded) {',
- ' if (logQueuedEventsTimer !== null) {',
- ' clearTimeout(logQueuedEventsTimer);',
- ' }',
- ' logQueuedEventsTimer = setTimeout(renderQueuedLogItems, renderDelay);',
- ' unrenderedLogItemsExist = true;',
- ' }',
- ' }',
- ' }',
- '',
- ' function renderQueuedLogItems() {',
- ' logQueuedEventsTimer = null;',
- ' var pruned = pruneLogEntries();',
- '',
- ' // Render any unrendered log entries and apply the current search to them',
- ' var initiallyHasMatches = currentSearch ? currentSearch.hasMatches() : false;',
- ' for (var i = 0, len = logItems.length; i < len; i++) {',
- ' if (!logItems[i].rendered) {',
- ' logItems[i].render();',
- ' logItems[i].appendToLog();',
- ' if (currentSearch && (logItems[i] instanceof LogEntry)) {',
- ' currentSearch.applyTo(logItems[i]);',
- ' }',
- ' }',
- ' }',
- ' if (currentSearch) {',
- ' if (pruned) {',
- ' if (currentSearch.hasVisibleMatches()) {',
- ' if (currentMatchIndex === null) {',
- ' setCurrentMatchIndex(0);',
- ' }',
- ' displayMatches();',
- ' } else {',
- ' displayNoMatches();',
- ' }',
- ' } else if (!initiallyHasMatches && currentSearch.hasVisibleMatches()) {',
- ' setCurrentMatchIndex(0);',
- ' displayMatches();',
- ' }',
- ' }',
- ' if (scrollToLatest) {',
- ' doScrollToLatest();',
- ' }',
- ' unrenderedLogItemsExist = false;',
- ' }',
- '',
- ' function pruneLogEntries() {',
- ' if ((maxMessages !== null) && (logEntriesAndSeparators.length > maxMessages)) {',
- ' var numberToDelete = logEntriesAndSeparators.length - maxMessages;',
- ' var prunedLogEntries = logEntriesAndSeparators.slice(0, numberToDelete);',
- ' if (currentSearch) {',
- ' currentSearch.removeMatches(prunedLogEntries);',
- ' }',
- ' var group;',
- ' for (var i = 0; i < numberToDelete; i++) {',
- ' group = logEntriesAndSeparators[i].group;',
- ' array_remove(logItems, logEntriesAndSeparators[i]);',
- ' array_remove(logEntries, logEntriesAndSeparators[i]);',
- ' logEntriesAndSeparators[i].remove(true, true);',
- ' if (group.children.length === 0 && group !== currentGroup && group !== rootGroup) {',
- ' array_remove(logItems, group);',
- ' group.remove(true, true);',
- ' }',
- ' }',
- ' logEntriesAndSeparators = array_removeFromStart(logEntriesAndSeparators, numberToDelete);',
- ' return true;',
- ' }',
- ' return false;',
- ' }',
- '',
- ' function group(name, startExpanded) {',
- ' if (loggingEnabled) {',
- ' initiallyExpanded = (typeof startExpanded === "undefined") ? true : Boolean(startExpanded);',
- ' var newGroup = new Group(name, false, initiallyExpanded);',
- ' currentGroup.addChild(newGroup);',
- ' currentGroup = newGroup;',
- ' logItems.push(newGroup);',
- ' if (loaded) {',
- ' if (logQueuedEventsTimer !== null) {',
- ' clearTimeout(logQueuedEventsTimer);',
- ' }',
- ' logQueuedEventsTimer = setTimeout(renderQueuedLogItems, renderDelay);',
- ' unrenderedLogItemsExist = true;',
- ' }',
- ' }',
- ' }',
- '',
- ' function groupEnd() {',
- ' currentGroup = (currentGroup === rootGroup) ? rootGroup : currentGroup.group;',
- ' }',
- '',
- ' function mainPageReloaded() {',
- ' currentGroup = rootGroup;',
- ' var separator = new Separator();',
- ' logEntriesAndSeparators.push(separator);',
- ' logItems.push(separator);',
- ' currentGroup.addChild(separator);',
- ' }',
- '',
- ' function closeWindow() {',
- ' if (appender && mainWindowExists()) {',
- ' appender.close(true);',
- ' } else {',
- ' window.close();',
- ' }',
- ' }',
- '',
- ' function hide() {',
- ' if (appender && mainWindowExists()) {',
- ' appender.hide();',
- ' }',
- ' }',
- '',
- ' var mainWindow = window;',
- ' var windowId = "log4javascriptConsoleWindow_" + new Date().getTime() + "_" + ("" + Math.random()).substr(2);',
- '',
- ' function setMainWindow(win) {',
- ' mainWindow = win;',
- ' mainWindow[windowId] = window;',
- ' // If this is a pop-up, poll the opener to see if it\'s closed',
- ' if (opener && closeIfOpenerCloses) {',
- ' pollOpener();',
- ' }',
- ' }',
- '',
- ' function pollOpener() {',
- ' if (closeIfOpenerCloses) {',
- ' if (mainWindowExists()) {',
- ' setTimeout(pollOpener, 500);',
- ' } else {',
- ' closeWindow();',
- ' }',
- ' }',
- ' }',
- '',
- ' function mainWindowExists() {',
- ' try {',
- ' return (mainWindow && !mainWindow.closed &&',
- ' mainWindow[windowId] == window);',
- ' } catch (ex) {}',
- ' return false;',
- ' }',
- '',
- ' var logLevels = ["TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL"];',
- '',
- ' function getCheckBox(logLevel) {',
- ' return $("switch_" + logLevel);',
- ' }',
- '',
- ' function getIeWrappedLogContainer() {',
- ' return $("log_wrapped");',
- ' }',
- '',
- ' function getIeUnwrappedLogContainer() {',
- ' return $("log_unwrapped");',
- ' }',
- '',
- ' function applyFilters() {',
- ' for (var i = 0; i < logLevels.length; i++) {',
- ' if (getCheckBox(logLevels[i]).checked) {',
- ' addClass(logMainContainer, logLevels[i]);',
- ' } else {',
- ' removeClass(logMainContainer, logLevels[i]);',
- ' }',
- ' }',
- ' updateSearchFromFilters();',
- ' }',
- '',
- ' function toggleAllLevels() {',
- ' var turnOn = $("switch_ALL").checked;',
- ' for (var i = 0; i < logLevels.length; i++) {',
- ' getCheckBox(logLevels[i]).checked = turnOn;',
- ' if (turnOn) {',
- ' addClass(logMainContainer, logLevels[i]);',
- ' } else {',
- ' removeClass(logMainContainer, logLevels[i]);',
- ' }',
- ' }',
- ' }',
- '',
- ' function checkAllLevels() {',
- ' for (var i = 0; i < logLevels.length; i++) {',
- ' if (!getCheckBox(logLevels[i]).checked) {',
- ' getCheckBox("ALL").checked = false;',
- ' return;',
- ' }',
- ' }',
- ' getCheckBox("ALL").checked = true;',
- ' }',
- '',
- ' function clearLog() {',
- ' rootGroup.clear();',
- ' currentGroup = rootGroup;',
- ' logEntries = [];',
- ' logItems = [];',
- ' logEntriesAndSeparators = [];',
- ' doSearch();',
- ' }',
- '',
- ' function toggleWrap() {',
- ' var enable = $("wrap").checked;',
- ' if (enable) {',
- ' addClass(logMainContainer, "wrap");',
- ' } else {',
- ' removeClass(logMainContainer, "wrap");',
- ' }',
- ' refreshCurrentMatch();',
- ' }',
- '',
- ' /* ------------------------------------------------------------------- */',
- '',
- ' // Search',
- '',
- ' var searchTimer = null;',
- '',
- ' function scheduleSearch() {',
- ' try {',
- ' clearTimeout(searchTimer);',
- ' } catch (ex) {',
- ' // Do nothing',
- ' }',
- ' searchTimer = setTimeout(doSearch, 500);',
- ' }',
- '',
- ' function Search(searchTerm, isRegex, searchRegex, isCaseSensitive) {',
- ' this.searchTerm = searchTerm;',
- ' this.isRegex = isRegex;',
- ' this.searchRegex = searchRegex;',
- ' this.isCaseSensitive = isCaseSensitive;',
- ' this.matches = [];',
- ' }',
- '',
- ' Search.prototype = {',
- ' hasMatches: function() {',
- ' return this.matches.length > 0;',
- ' },',
- '',
- ' hasVisibleMatches: function() {',
- ' if (this.hasMatches()) {',
- ' for (var i = 0; i < this.matches.length; i++) {',
- ' if (this.matches[i].isVisible()) {',
- ' return true;',
- ' }',
- ' }',
- ' }',
- ' return false;',
- ' },',
- '',
- ' match: function(logEntry) {',
- ' var entryText = String(logEntry.formattedMessage);',
- ' var matchesSearch = false;',
- ' if (this.isRegex) {',
- ' matchesSearch = this.searchRegex.test(entryText);',
- ' } else if (this.isCaseSensitive) {',
- ' matchesSearch = (entryText.indexOf(this.searchTerm) > -1);',
- ' } else {',
- ' matchesSearch = (entryText.toLowerCase().indexOf(this.searchTerm.toLowerCase()) > -1);',
- ' }',
- ' return matchesSearch;',
- ' },',
- '',
- ' getNextVisibleMatchIndex: function() {',
- ' for (var i = currentMatchIndex + 1; i < this.matches.length; i++) {',
- ' if (this.matches[i].isVisible()) {',
- ' return i;',
- ' }',
- ' }',
- ' // Start again from the first match',
- ' for (i = 0; i <= currentMatchIndex; i++) {',
- ' if (this.matches[i].isVisible()) {',
- ' return i;',
- ' }',
- ' }',
- ' return -1;',
- ' },',
- '',
- ' getPreviousVisibleMatchIndex: function() {',
- ' for (var i = currentMatchIndex - 1; i >= 0; i--) {',
- ' if (this.matches[i].isVisible()) {',
- ' return i;',
- ' }',
- ' }',
- ' // Start again from the last match',
- ' for (var i = this.matches.length - 1; i >= currentMatchIndex; i--) {',
- ' if (this.matches[i].isVisible()) {',
- ' return i;',
- ' }',
- ' }',
- ' return -1;',
- ' },',
- '',
- ' applyTo: function(logEntry) {',
- ' var doesMatch = this.match(logEntry);',
- ' if (doesMatch) {',
- ' logEntry.group.expand();',
- ' logEntry.setSearchMatch(true);',
- ' var logEntryContent;',
- ' var wrappedLogEntryContent;',
- ' var searchTermReplacementStartTag = "<span class=\\\"searchterm\\\">";',
- ' var searchTermReplacementEndTag = "<" + "/span>";',
- ' var preTagName = isIe ? "pre" : "span";',
- ' var preStartTag = "<" + preTagName + " class=\\\"pre\\\">";',
- ' var preEndTag = "<" + "/" + preTagName + ">";',
- ' var startIndex = 0;',
- ' var searchIndex, matchedText, textBeforeMatch;',
- ' if (this.isRegex) {',
- ' var flags = this.isCaseSensitive ? "g" : "gi";',
- ' var capturingRegex = new RegExp("(" + this.searchRegex.source + ")", flags);',
- '',
- ' // Replace the search term with temporary tokens for the start and end tags',
- ' var rnd = ("" + Math.random()).substr(2);',
- ' var startToken = "%%s" + rnd + "%%";',
- ' var endToken = "%%e" + rnd + "%%";',
- ' logEntryContent = logEntry.formattedMessage.replace(capturingRegex, startToken + "$1" + endToken);',
- '',
- ' // Escape the HTML to get rid of angle brackets',
- ' logEntryContent = escapeHtml(logEntryContent);',
- '',
- ' // Substitute the proper HTML back in for the search match',
- ' var result;',
- ' var searchString = logEntryContent;',
- ' logEntryContent = "";',
- ' wrappedLogEntryContent = "";',
- ' while ((searchIndex = searchString.indexOf(startToken, startIndex)) > -1) {',
- ' var endTokenIndex = searchString.indexOf(endToken, searchIndex);',
- ' matchedText = searchString.substring(searchIndex + startToken.length, endTokenIndex);',
- ' textBeforeMatch = searchString.substring(startIndex, searchIndex);',
- ' logEntryContent += preStartTag + textBeforeMatch + preEndTag;',
- ' logEntryContent += searchTermReplacementStartTag + preStartTag + matchedText +',
- ' preEndTag + searchTermReplacementEndTag;',
- ' if (isIe) {',
- ' wrappedLogEntryContent += textBeforeMatch + searchTermReplacementStartTag +',
- ' matchedText + searchTermReplacementEndTag;',
- ' }',
- ' startIndex = endTokenIndex + endToken.length;',
- ' }',
- ' logEntryContent += preStartTag + searchString.substr(startIndex) + preEndTag;',
- ' if (isIe) {',
- ' wrappedLogEntryContent += searchString.substr(startIndex);',
- ' }',
- ' } else {',
- ' logEntryContent = "";',
- ' wrappedLogEntryContent = "";',
- ' var searchTermReplacementLength = searchTermReplacementStartTag.length +',
- ' this.searchTerm.length + searchTermReplacementEndTag.length;',
- ' var searchTermLength = this.searchTerm.length;',
- ' var searchTermLowerCase = this.searchTerm.toLowerCase();',
- ' var logTextLowerCase = logEntry.formattedMessage.toLowerCase();',
- ' while ((searchIndex = logTextLowerCase.indexOf(searchTermLowerCase, startIndex)) > -1) {',
- ' matchedText = escapeHtml(logEntry.formattedMessage.substr(searchIndex, this.searchTerm.length));',
- ' textBeforeMatch = escapeHtml(logEntry.formattedMessage.substring(startIndex, searchIndex));',
- ' var searchTermReplacement = searchTermReplacementStartTag +',
- ' preStartTag + matchedText + preEndTag + searchTermReplacementEndTag;',
- ' logEntryContent += preStartTag + textBeforeMatch + preEndTag + searchTermReplacement;',
- ' if (isIe) {',
- ' wrappedLogEntryContent += textBeforeMatch + searchTermReplacementStartTag +',
- ' matchedText + searchTermReplacementEndTag;',
- ' }',
- ' startIndex = searchIndex + searchTermLength;',
- ' }',
- ' var textAfterLastMatch = escapeHtml(logEntry.formattedMessage.substr(startIndex));',
- ' logEntryContent += preStartTag + textAfterLastMatch + preEndTag;',
- ' if (isIe) {',
- ' wrappedLogEntryContent += textAfterLastMatch;',
- ' }',
- ' }',
- ' logEntry.setContent(logEntryContent, wrappedLogEntryContent);',
- ' var logEntryMatches = logEntry.getSearchMatches();',
- ' this.matches = this.matches.concat(logEntryMatches);',
- ' } else {',
- ' logEntry.setSearchMatch(false);',
- ' logEntry.setContent(logEntry.formattedMessage, logEntry.formattedMessage);',
- ' }',
- ' return doesMatch;',
- ' },',
- '',
- ' removeMatches: function(logEntries) {',
- ' var matchesToRemoveCount = 0;',
- ' var currentMatchRemoved = false;',
- ' var matchesToRemove = [];',
- ' var i, iLen, j, jLen;',
- '',
- ' // Establish the list of matches to be removed',
- ' for (i = 0, iLen = this.matches.length; i < iLen; i++) {',
- ' for (j = 0, jLen = logEntries.length; j < jLen; j++) {',
- ' if (this.matches[i].belongsTo(logEntries[j])) {',
- ' matchesToRemove.push(this.matches[i]);',
- ' if (i === currentMatchIndex) {',
- ' currentMatchRemoved = true;',
- ' }',
- ' }',
- ' }',
- ' }',
- '',
- ' // Set the new current match index if the current match has been deleted',
- ' // This will be the first match that appears after the first log entry being',
- ' // deleted, if one exists; otherwise, it\'s the first match overall',
- ' var newMatch = currentMatchRemoved ? null : this.matches[currentMatchIndex];',
- ' if (currentMatchRemoved) {',
- ' for (i = currentMatchIndex, iLen = this.matches.length; i < iLen; i++) {',
- ' if (this.matches[i].isVisible() && !array_contains(matchesToRemove, this.matches[i])) {',
- ' newMatch = this.matches[i];',
- ' break;',
- ' }',
- ' }',
- ' }',
- '',
- ' // Remove the matches',
- ' for (i = 0, iLen = matchesToRemove.length; i < iLen; i++) {',
- ' array_remove(this.matches, matchesToRemove[i]);',
- ' matchesToRemove[i].remove();',
- ' }',
- '',
- ' // Set the new match, if one exists',
- ' if (this.hasVisibleMatches()) {',
- ' if (newMatch === null) {',
- ' setCurrentMatchIndex(0);',
- ' } else {',
- ' // Get the index of the new match',
- ' var newMatchIndex = 0;',
- ' for (i = 0, iLen = this.matches.length; i < iLen; i++) {',
- ' if (newMatch === this.matches[i]) {',
- ' newMatchIndex = i;',
- ' break;',
- ' }',
- ' }',
- ' setCurrentMatchIndex(newMatchIndex);',
- ' }',
- ' } else {',
- ' currentMatchIndex = null;',
- ' displayNoMatches();',
- ' }',
- ' }',
- ' };',
- '',
- ' function getPageOffsetTop(el, container) {',
- ' var currentEl = el;',
- ' var y = 0;',
- ' while (currentEl && currentEl != container) {',
- ' y += currentEl.offsetTop;',
- ' currentEl = currentEl.offsetParent;',
- ' }',
- ' return y;',
- ' }',
- '',
- ' function scrollIntoView(el) {',
- ' var logContainer = logMainContainer;',
- ' // Check if the whole width of the element is visible and centre if not',
- ' if (!$("wrap").checked) {',
- ' var logContainerLeft = logContainer.scrollLeft;',
- ' var logContainerRight = logContainerLeft + logContainer.offsetWidth;',
- ' var elLeft = el.offsetLeft;',
- ' var elRight = elLeft + el.offsetWidth;',
- ' if (elLeft < logContainerLeft || elRight > logContainerRight) {',
- ' logContainer.scrollLeft = elLeft - (logContainer.offsetWidth - el.offsetWidth) / 2;',
- ' }',
- ' }',
- ' // Check if the whole height of the element is visible and centre if not',
- ' var logContainerTop = logContainer.scrollTop;',
- ' var logContainerBottom = logContainerTop + logContainer.offsetHeight;',
- ' var elTop = getPageOffsetTop(el) - getToolBarsHeight();',
- ' var elBottom = elTop + el.offsetHeight;',
- ' if (elTop < logContainerTop || elBottom > logContainerBottom) {',
- ' logContainer.scrollTop = elTop - (logContainer.offsetHeight - el.offsetHeight) / 2;',
- ' }',
- ' }',
- '',
- ' function Match(logEntryLevel, spanInMainDiv, spanInUnwrappedPre, spanInWrappedDiv) {',
- ' this.logEntryLevel = logEntryLevel;',
- ' this.spanInMainDiv = spanInMainDiv;',
- ' if (isIe) {',
- ' this.spanInUnwrappedPre = spanInUnwrappedPre;',
- ' this.spanInWrappedDiv = spanInWrappedDiv;',
- ' }',
- ' this.mainSpan = isIe ? spanInUnwrappedPre : spanInMainDiv;',
- ' }',
- '',
- ' Match.prototype = {',
- ' equals: function(match) {',
- ' return this.mainSpan === match.mainSpan;',
- ' },',
- '',
- ' setCurrent: function() {',
- ' if (isIe) {',
- ' addClass(this.spanInUnwrappedPre, "currentmatch");',
- ' addClass(this.spanInWrappedDiv, "currentmatch");',
- ' // Scroll the visible one into view',
- ' var elementToScroll = $("wrap").checked ? this.spanInWrappedDiv : this.spanInUnwrappedPre;',
- ' scrollIntoView(elementToScroll);',
- ' } else {',
- ' addClass(this.spanInMainDiv, "currentmatch");',
- ' scrollIntoView(this.spanInMainDiv);',
- ' }',
- ' },',
- '',
- ' belongsTo: function(logEntry) {',
- ' if (isIe) {',
- ' return isDescendant(this.spanInUnwrappedPre, logEntry.unwrappedPre);',
- ' } else {',
- ' return isDescendant(this.spanInMainDiv, logEntry.mainDiv);',
- ' }',
- ' },',
- '',
- ' setNotCurrent: function() {',
- ' if (isIe) {',
- ' removeClass(this.spanInUnwrappedPre, "currentmatch");',
- ' removeClass(this.spanInWrappedDiv, "currentmatch");',
- ' } else {',
- ' removeClass(this.spanInMainDiv, "currentmatch");',
- ' }',
- ' },',
- '',
- ' isOrphan: function() {',
- ' return isOrphan(this.mainSpan);',
- ' },',
- '',
- ' isVisible: function() {',
- ' return getCheckBox(this.logEntryLevel).checked;',
- ' },',
- '',
- ' remove: function() {',
- ' if (isIe) {',
- ' this.spanInUnwrappedPre = null;',
- ' this.spanInWrappedDiv = null;',
- ' } else {',
- ' this.spanInMainDiv = null;',
- ' }',
- ' }',
- ' };',
- '',
- ' var currentSearch = null;',
- ' var currentMatchIndex = null;',
- '',
- ' function doSearch() {',
- ' var searchBox = $("searchBox");',
- ' var searchTerm = searchBox.value;',
- ' var isRegex = $("searchRegex").checked;',
- ' var isCaseSensitive = $("searchCaseSensitive").checked;',
- ' var i;',
- '',
- ' if (searchTerm === "") {',
- ' $("searchReset").disabled = true;',
- ' $("searchNav").style.display = "none";',
- ' removeClass(document.body, "searching");',
- ' removeClass(searchBox, "hasmatches");',
- ' removeClass(searchBox, "nomatches");',
- ' for (i = 0; i < logEntries.length; i++) {',
- ' logEntries[i].clearSearch();',
- ' logEntries[i].setContent(logEntries[i].formattedMessage, logEntries[i].formattedMessage);',
- ' }',
- ' currentSearch = null;',
- ' setLogContainerHeight();',
- ' } else {',
- ' $("searchReset").disabled = false;',
- ' $("searchNav").style.display = "block";',
- ' var searchRegex;',
- ' var regexValid;',
- ' if (isRegex) {',
- ' try {',
- ' searchRegex = isCaseSensitive ? new RegExp(searchTerm, "g") : new RegExp(searchTerm, "gi");',
- ' regexValid = true;',
- ' replaceClass(searchBox, "validregex", "invalidregex");',
- ' searchBox.title = "Valid regex";',
- ' } catch (ex) {',
- ' regexValid = false;',
- ' replaceClass(searchBox, "invalidregex", "validregex");',
- ' searchBox.title = "Invalid regex: " + (ex.message ? ex.message : (ex.description ? ex.description : "unknown error"));',
- ' return;',
- ' }',
- ' } else {',
- ' searchBox.title = "";',
- ' removeClass(searchBox, "validregex");',
- ' removeClass(searchBox, "invalidregex");',
- ' }',
- ' addClass(document.body, "searching");',
- ' currentSearch = new Search(searchTerm, isRegex, searchRegex, isCaseSensitive);',
- ' for (i = 0; i < logEntries.length; i++) {',
- ' currentSearch.applyTo(logEntries[i]);',
- ' }',
- ' setLogContainerHeight();',
- '',
- ' // Highlight the first search match',
- ' if (currentSearch.hasVisibleMatches()) {',
- ' setCurrentMatchIndex(0);',
- ' displayMatches();',
- ' } else {',
- ' displayNoMatches();',
- ' }',
- ' }',
- ' }',
- '',
- ' function updateSearchFromFilters() {',
- ' if (currentSearch) {',
- ' if (currentSearch.hasMatches()) {',
- ' if (currentMatchIndex === null) {',
- ' currentMatchIndex = 0;',
- ' }',
- ' var currentMatch = currentSearch.matches[currentMatchIndex];',
- ' if (currentMatch.isVisible()) {',
- ' displayMatches();',
- ' setCurrentMatchIndex(currentMatchIndex);',
- ' } else {',
- ' currentMatch.setNotCurrent();',
- ' // Find the next visible match, if one exists',
- ' var nextVisibleMatchIndex = currentSearch.getNextVisibleMatchIndex();',
- ' if (nextVisibleMatchIndex > -1) {',
- ' setCurrentMatchIndex(nextVisibleMatchIndex);',
- ' displayMatches();',
- ' } else {',
- ' displayNoMatches();',
- ' }',
- ' }',
- ' } else {',
- ' displayNoMatches();',
- ' }',
- ' }',
- ' }',
- '',
- ' function refreshCurrentMatch() {',
- ' if (currentSearch && currentSearch.hasVisibleMatches()) {',
- ' setCurrentMatchIndex(currentMatchIndex);',
- ' }',
- ' }',
- '',
- ' function displayMatches() {',
- ' replaceClass($("searchBox"), "hasmatches", "nomatches");',
- ' $("searchBox").title = "" + currentSearch.matches.length + " matches found";',
- ' $("searchNav").style.display = "block";',
- ' setLogContainerHeight();',
- ' }',
- '',
- ' function displayNoMatches() {',
- ' replaceClass($("searchBox"), "nomatches", "hasmatches");',
- ' $("searchBox").title = "No matches found";',
- ' $("searchNav").style.display = "none";',
- ' setLogContainerHeight();',
- ' }',
- '',
- ' function toggleSearchEnabled(enable) {',
- ' enable = (typeof enable == "undefined") ? !$("searchDisable").checked : enable;',
- ' $("searchBox").disabled = !enable;',
- ' $("searchReset").disabled = !enable;',
- ' $("searchRegex").disabled = !enable;',
- ' $("searchNext").disabled = !enable;',
- ' $("searchPrevious").disabled = !enable;',
- ' $("searchCaseSensitive").disabled = !enable;',
- ' $("searchNav").style.display = (enable && ($("searchBox").value !== "") &&',
- ' currentSearch && currentSearch.hasVisibleMatches()) ?',
- ' "block" : "none";',
- ' if (enable) {',
- ' removeClass($("search"), "greyedout");',
- ' addClass(document.body, "searching");',
- ' if ($("searchHighlight").checked) {',
- ' addClass(logMainContainer, "searchhighlight");',
- ' } else {',
- ' removeClass(logMainContainer, "searchhighlight");',
- ' }',
- ' if ($("searchFilter").checked) {',
- ' addClass(logMainContainer, "searchfilter");',
- ' } else {',
- ' removeClass(logMainContainer, "searchfilter");',
- ' }',
- ' $("searchDisable").checked = !enable;',
- ' } else {',
- ' addClass($("search"), "greyedout");',
- ' removeClass(document.body, "searching");',
- ' removeClass(logMainContainer, "searchhighlight");',
- ' removeClass(logMainContainer, "searchfilter");',
- ' }',
- ' setLogContainerHeight();',
- ' }',
- '',
- ' function toggleSearchFilter() {',
- ' var enable = $("searchFilter").checked;',
- ' if (enable) {',
- ' addClass(logMainContainer, "searchfilter");',
- ' } else {',
- ' removeClass(logMainContainer, "searchfilter");',
- ' }',
- ' refreshCurrentMatch();',
- ' }',
- '',
- ' function toggleSearchHighlight() {',
- ' var enable = $("searchHighlight").checked;',
- ' if (enable) {',
- ' addClass(logMainContainer, "searchhighlight");',
- ' } else {',
- ' removeClass(logMainContainer, "searchhighlight");',
- ' }',
- ' }',
- '',
- ' function clearSearch() {',
- ' $("searchBox").value = "";',
- ' doSearch();',
- ' }',
- '',
- ' function searchNext() {',
- ' if (currentSearch !== null && currentMatchIndex !== null) {',
- ' currentSearch.matches[currentMatchIndex].setNotCurrent();',
- ' var nextMatchIndex = currentSearch.getNextVisibleMatchIndex();',
- ' if (nextMatchIndex > currentMatchIndex || confirm("Reached the end of the page. Start from the top?")) {',
- ' setCurrentMatchIndex(nextMatchIndex);',
- ' }',
- ' }',
- ' }',
- '',
- ' function searchPrevious() {',
- ' if (currentSearch !== null && currentMatchIndex !== null) {',
- ' currentSearch.matches[currentMatchIndex].setNotCurrent();',
- ' var previousMatchIndex = currentSearch.getPreviousVisibleMatchIndex();',
- ' if (previousMatchIndex < currentMatchIndex || confirm("Reached the start of the page. Continue from the bottom?")) {',
- ' setCurrentMatchIndex(previousMatchIndex);',
- ' }',
- ' }',
- ' }',
- '',
- ' function setCurrentMatchIndex(index) {',
- ' currentMatchIndex = index;',
- ' currentSearch.matches[currentMatchIndex].setCurrent();',
- ' }',
- '',
- ' /* ------------------------------------------------------------------------- */',
- '',
- ' // CSS Utilities',
- '',
- ' function addClass(el, cssClass) {',
- ' if (!hasClass(el, cssClass)) {',
- ' if (el.className) {',
- ' el.className += " " + cssClass;',
- ' } else {',
- ' el.className = cssClass;',
- ' }',
- ' }',
- ' }',
- '',
- ' function hasClass(el, cssClass) {',
- ' if (el.className) {',
- ' var classNames = el.className.split(" ");',
- ' return array_contains(classNames, cssClass);',
- ' }',
- ' return false;',
- ' }',
- '',
- ' function removeClass(el, cssClass) {',
- ' if (hasClass(el, cssClass)) {',
- ' // Rebuild the className property',
- ' var existingClasses = el.className.split(" ");',
- ' var newClasses = [];',
- ' for (var i = 0, len = existingClasses.length; i < len; i++) {',
- ' if (existingClasses[i] != cssClass) {',
- ' newClasses[newClasses.length] = existingClasses[i];',
- ' }',
- ' }',
- ' el.className = newClasses.join(" ");',
- ' }',
- ' }',
- '',
- ' function replaceClass(el, newCssClass, oldCssClass) {',
- ' removeClass(el, oldCssClass);',
- ' addClass(el, newCssClass);',
- ' }',
- '',
- ' /* ------------------------------------------------------------------------- */',
- '',
- ' // Other utility functions',
- '',
- ' function getElementsByClass(el, cssClass, tagName) {',
- ' var elements = el.getElementsByTagName(tagName);',
- ' var matches = [];',
- ' for (var i = 0, len = elements.length; i < len; i++) {',
- ' if (hasClass(elements[i], cssClass)) {',
- ' matches.push(elements[i]);',
- ' }',
- ' }',
- ' return matches;',
- ' }',
- '',
- ' // Syntax borrowed from Prototype library',
- ' function $(id) {',
- ' return document.getElementById(id);',
- ' }',
- '',
- ' function isDescendant(node, ancestorNode) {',
- ' while (node != null) {',
- ' if (node === ancestorNode) {',
- ' return true;',
- ' }',
- ' node = node.parentNode;',
- ' }',
- ' return false;',
- ' }',
- '',
- ' function isOrphan(node) {',
- ' var currentNode = node;',
- ' while (currentNode) {',
- ' if (currentNode == document.body) {',
- ' return false;',
- ' }',
- ' currentNode = currentNode.parentNode;',
- ' }',
- ' return true;',
- ' }',
- '',
- ' function escapeHtml(str) {',
- ' return str.replace(/&/g, "&").replace(/[<]/g, "<").replace(/>/g, ">");',
- ' }',
- '',
- ' function getWindowWidth() {',
- ' if (window.innerWidth) {',
- ' return window.innerWidth;',
- ' } else if (document.documentElement && document.documentElement.clientWidth) {',
- ' return document.documentElement.clientWidth;',
- ' } else if (document.body) {',
- ' return document.body.clientWidth;',
- ' }',
- ' return 0;',
- ' }',
- '',
- ' function getWindowHeight() {',
- ' if (window.innerHeight) {',
- ' return window.innerHeight;',
- ' } else if (document.documentElement && document.documentElement.clientHeight) {',
- ' return document.documentElement.clientHeight;',
- ' } else if (document.body) {',
- ' return document.body.clientHeight;',
- ' }',
- ' return 0;',
- ' }',
- '',
- ' function getToolBarsHeight() {',
- ' return $("switches").offsetHeight;',
- ' }',
- '',
- ' function getChromeHeight() {',
- ' var height = getToolBarsHeight();',
- ' if (showCommandLine) {',
- ' height += $("commandLine").offsetHeight;',
- ' }',
- ' return height;',
- ' }',
- '',
- ' function setLogContainerHeight() {',
- ' if (logMainContainer) {',
- ' var windowHeight = getWindowHeight();',
- ' $("body").style.height = getWindowHeight() + "px";',
- ' logMainContainer.style.height = "" +',
- ' Math.max(0, windowHeight - getChromeHeight()) + "px";',
- ' }',
- ' }',
- '',
- ' function setCommandInputWidth() {',
- ' if (showCommandLine) {',
- ' $("command").style.width = "" + Math.max(0, $("commandLineContainer").offsetWidth -',
- ' ($("evaluateButton").offsetWidth + 13)) + "px";',
- ' }',
- ' }',
- '',
- ' window.onresize = function() {',
- ' setCommandInputWidth();',
- ' setLogContainerHeight();',
- ' };',
- '',
- ' if (!Array.prototype.push) {',
- ' Array.prototype.push = function() {',
- ' for (var i = 0, len = arguments.length; i < len; i++){',
- ' this[this.length] = arguments[i];',
- ' }',
- ' return this.length;',
- ' };',
- ' }',
- '',
- ' if (!Array.prototype.pop) {',
- ' Array.prototype.pop = function() {',
- ' if (this.length > 0) {',
- ' var val = this[this.length - 1];',
- ' this.length = this.length - 1;',
- ' return val;',
- ' }',
- ' };',
- ' }',
- '',
- ' if (!Array.prototype.shift) {',
- ' Array.prototype.shift = function() {',
- ' if (this.length > 0) {',
- ' var firstItem = this[0];',
- ' for (var i = 0, len = this.length - 1; i < len; i++) {',
- ' this[i] = this[i + 1];',
- ' }',
- ' this.length = this.length - 1;',
- ' return firstItem;',
- ' }',
- ' };',
- ' }',
- '',
- ' if (!Array.prototype.splice) {',
- ' Array.prototype.splice = function(startIndex, deleteCount) {',
- ' var itemsAfterDeleted = this.slice(startIndex + deleteCount);',
- ' var itemsDeleted = this.slice(startIndex, startIndex + deleteCount);',
- ' this.length = startIndex;',
- ' // Copy the arguments into a proper Array object',
- ' var argumentsArray = [];',
- ' for (var i = 0, len = arguments.length; i < len; i++) {',
- ' argumentsArray[i] = arguments[i];',
- ' }',
- ' var itemsToAppend = (argumentsArray.length > 2) ?',
- ' itemsAfterDeleted = argumentsArray.slice(2).concat(itemsAfterDeleted) : itemsAfterDeleted;',
- ' for (i = 0, len = itemsToAppend.length; i < len; i++) {',
- ' this.push(itemsToAppend[i]);',
- ' }',
- ' return itemsDeleted;',
- ' };',
- ' }',
- '',
- ' function array_remove(arr, val) {',
- ' var index = -1;',
- ' for (var i = 0, len = arr.length; i < len; i++) {',
- ' if (arr[i] === val) {',
- ' index = i;',
- ' break;',
- ' }',
- ' }',
- ' if (index >= 0) {',
- ' arr.splice(index, 1);',
- ' return index;',
- ' } else {',
- ' return false;',
- ' }',
- ' }',
- '',
- ' function array_removeFromStart(array, numberToRemove) {',
- ' if (Array.prototype.splice) {',
- ' array.splice(0, numberToRemove);',
- ' } else {',
- ' for (var i = numberToRemove, len = array.length; i < len; i++) {',
- ' array[i - numberToRemove] = array[i];',
- ' }',
- ' array.length = array.length - numberToRemove;',
- ' }',
- ' return array;',
- ' }',
- '',
- ' function array_contains(arr, val) {',
- ' for (var i = 0, len = arr.length; i < len; i++) {',
- ' if (arr[i] == val) {',
- ' return true;',
- ' }',
- ' }',
- ' return false;',
- ' }',
- '',
- ' function getErrorMessage(ex) {',
- ' if (ex.message) {',
- ' return ex.message;',
- ' } else if (ex.description) {',
- ' return ex.description;',
- ' }',
- ' return "" + ex;',
- ' }',
- '',
- ' function moveCaretToEnd(input) {',
- ' if (input.setSelectionRange) {',
- ' input.focus();',
- ' var length = input.value.length;',
- ' input.setSelectionRange(length, length);',
- ' } else if (input.createTextRange) {',
- ' var range = input.createTextRange();',
- ' range.collapse(false);',
- ' range.select();',
- ' }',
- ' input.focus();',
- ' }',
- '',
- ' function stopPropagation(evt) {',
- ' if (evt.stopPropagation) {',
- ' evt.stopPropagation();',
- ' } else if (typeof evt.cancelBubble != "undefined") {',
- ' evt.cancelBubble = true;',
- ' }',
- ' }',
- '',
- ' function getEvent(evt) {',
- ' return evt ? evt : event;',
- ' }',
- '',
- ' function getTarget(evt) {',
- ' return evt.target ? evt.target : evt.srcElement;',
- ' }',
- '',
- ' function getRelatedTarget(evt) {',
- ' if (evt.relatedTarget) {',
- ' return evt.relatedTarget;',
- ' } else if (evt.srcElement) {',
- ' switch(evt.type) {',
- ' case "mouseover":',
- ' return evt.fromElement;',
- ' case "mouseout":',
- ' return evt.toElement;',
- ' default:',
- ' return evt.srcElement;',
- ' }',
- ' }',
- ' }',
- '',
- ' function cancelKeyEvent(evt) {',
- ' evt.returnValue = false;',
- ' stopPropagation(evt);',
- ' }',
- '',
- ' function evalCommandLine() {',
- ' var expr = $("command").value;',
- ' evalCommand(expr);',
- ' $("command").value = "";',
- ' }',
- '',
- ' function evalLastCommand() {',
- ' if (lastCommand != null) {',
- ' evalCommand(lastCommand);',
- ' }',
- ' }',
- '',
- ' var lastCommand = null;',
- ' var commandHistory = [];',
- ' var currentCommandIndex = 0;',
- '',
- ' function evalCommand(expr) {',
- ' if (appender) {',
- ' appender.evalCommandAndAppend(expr);',
- ' } else {',
- ' var prefix = ">>> " + expr + "\\r\\n";',
- ' try {',
- ' log("INFO", prefix + eval(expr));',
- ' } catch (ex) {',
- ' log("ERROR", prefix + "Error: " + getErrorMessage(ex));',
- ' }',
- ' }',
- ' // Update command history',
- ' if (expr != commandHistory[commandHistory.length - 1]) {',
- ' commandHistory.push(expr);',
- ' // Update the appender',
- ' if (appender) {',
- ' appender.storeCommandHistory(commandHistory);',
- ' }',
- ' }',
- ' currentCommandIndex = (expr == commandHistory[currentCommandIndex]) ? currentCommandIndex + 1 : commandHistory.length;',
- ' lastCommand = expr;',
- ' }',
- ' //]]>',
- ' </script>',
- ' <style type="text/css">',
- ' body {',
- ' background-color: white;',
- ' color: black;',
- ' padding: 0;',
- ' margin: 0;',
- ' font-family: tahoma, verdana, arial, helvetica, sans-serif;',
- ' overflow: hidden;',
- ' -webkit-touch-callout: none;',
- ' -webkit-user-select: none;',
- ' -khtml-user-select: none;',
- ' -moz-user-select: none;',
- ' -ms-user-select: none;',
- ' user-select: none;',
- ' }',
- '',
- ' div#switchesContainer input {',
- ' margin-bottom: 0;',
- ' }',
- '',
- ' div.toolbar {',
- ' border-top: solid #ffffff 1px;',
- ' border-bottom: solid #aca899 1px;',
- ' background-color: #f1efe7;',
- ' padding: 3px 5px;',
- ' font-size: 68.75%;',
- ' }',
- '',
- ' div.toolbar, div#search input {',
- ' font-family: tahoma, verdana, arial, helvetica, sans-serif;',
- ' }',
- '',
- ' div.toolbar input.button {',
- ' padding: 0 5px;',
- ' font-size: 100%;',
- ' }',
- '',
- ' div.toolbar input.hidden {',
- ' display: none;',
- ' }',
- '',
- ' div#switches input#clearButton {',
- ' margin-left: 20px;',
- ' }',
- '',
- ' div#levels label {',
- ' font-weight: bold;',
- ' }',
- '',
- ' div#levels label, div#options label {',
- ' margin-right: 5px;',
- ' }',
- '',
- ' div#levels label#wrapLabel {',
- ' font-weight: normal;',
- ' }',
- '',
- ' div#search label {',
- ' margin-right: 10px;',
- ' }',
- '',
- ' div#search label.searchboxlabel {',
- ' margin-right: 0;',
- ' }',
- '',
- ' div#search input {',
- ' font-size: 100%;',
- ' }',
- '',
- ' div#search input.validregex {',
- ' color: green;',
- ' }',
- '',
- ' div#search input.invalidregex {',
- ' color: red;',
- ' }',
- '',
- ' div#search input.nomatches {',
- ' color: white;',
- ' background-color: #ff6666;',
- ' }',
- '',
- ' div#search input.nomatches {',
- ' color: white;',
- ' background-color: #ff6666;',
- ' }',
- '',
- ' div#searchNav {',
- ' display: none;',
- ' }',
- '',
- ' div#commandLine {',
- ' display: none;',
- ' }',
- '',
- ' div#commandLine input#command {',
- ' font-size: 100%;',
- ' font-family: Courier New, Courier;',
- ' }',
- '',
- ' div#commandLine input#evaluateButton {',
- ' }',
- '',
- ' *.greyedout {',
- ' color: gray !important;',
- ' border-color: gray !important;',
- ' }',
- '',
- ' *.greyedout *.alwaysenabled { color: black; }',
- '',
- ' *.unselectable {',
- ' -khtml-user-select: none;',
- ' -moz-user-select: none;',
- ' user-select: none;',
- ' }',
- '',
- ' div#log {',
- ' font-family: Courier New, Courier;',
- ' font-size: 75%;',
- ' width: 100%;',
- ' overflow: auto;',
- ' clear: both;',
- ' position: relative;',
- ' -webkit-touch-callout: text;',
- ' -webkit-user-select: text;',
- ' -khtml-user-select: text;',
- ' -moz-user-select: text;',
- ' -ms-user-select: text;',
- ' user-select: text;',
- ' }',
- '',
- ' div.group {',
- ' border-color: #cccccc;',
- ' border-style: solid;',
- ' border-width: 1px 0 1px 1px;',
- ' overflow: visible;',
- ' }',
- '',
- ' div.oldIe div.group, div.oldIe div.group *, div.oldIe *.logentry {',
- ' height: 1%;',
- ' }',
- '',
- ' div.group div.groupheading span.expander {',
- ' border: solid black 1px;',
- ' font-family: Courier New, Courier;',
- ' font-size: 0.833em;',
- ' background-color: #eeeeee;',
- ' position: relative;',
- ' top: -1px;',
- ' color: black;',
- ' padding: 0 2px;',
- ' cursor: pointer;',
- ' cursor: hand;',
- ' height: 1%;',
- ' }',
- '',
- ' div.group div.groupcontent {',
- ' margin-left: 10px;',
- ' padding-bottom: 2px;',
- ' overflow: visible;',
- ' }',
- '',
- ' div.group div.expanded {',
- ' display: block;',
- ' }',
- '',
- ' div.group div.collapsed {',
- ' display: none;',
- ' }',
- '',
- ' *.logentry {',
- ' overflow: visible;',
- ' display: none;',
- ' white-space: pre;',
- ' }',
- '',
- ' span.pre {',
- ' white-space: pre;',
- ' }',
- ' ',
- ' pre.unwrapped {',
- ' display: inline !important;',
- ' }',
- '',
- ' pre.unwrapped pre.pre, div.wrapped pre.pre {',
- ' display: inline;',
- ' }',
- '',
- ' div.wrapped pre.pre {',
- ' white-space: normal;',
- ' }',
- '',
- ' div.wrapped {',
- ' display: none;',
- ' }',
- '',
- ' body.searching *.logentry span.currentmatch {',
- ' color: white !important;',
- ' background-color: green !important;',
- ' }',
- '',
- ' body.searching div.searchhighlight *.logentry span.searchterm {',
- ' color: black;',
- ' background-color: yellow;',
- ' }',
- '',
- ' div.wrap *.logentry {',
- ' white-space: normal !important;',
- ' border-width: 0 0 1px 0;',
- ' border-color: #dddddd;',
- ' border-style: dotted;',
- ' }',
- '',
- ' div.wrap #log_wrapped, #log_unwrapped {',
- ' display: block;',
- ' }',
- '',
- ' div.wrap #log_unwrapped, #log_wrapped {',
- ' display: none;',
- ' }',
- '',
- ' div.wrap *.logentry span.pre {',
- ' overflow: visible;',
- ' white-space: normal;',
- ' }',
- '',
- ' div.wrap *.logentry pre.unwrapped {',
- ' display: none;',
- ' }',
- '',
- ' div.wrap *.logentry span.wrapped {',
- ' display: inline;',
- ' }',
- '',
- ' div.searchfilter *.searchnonmatch {',
- ' display: none !important;',
- ' }',
- '',
- ' div#log *.TRACE, label#label_TRACE {',
- ' color: #666666;',
- ' }',
- '',
- ' div#log *.DEBUG, label#label_DEBUG {',
- ' color: green;',
- ' }',
- '',
- ' div#log *.INFO, label#label_INFO {',
- ' color: #000099;',
- ' }',
- '',
- ' div#log *.WARN, label#label_WARN {',
- ' color: #999900;',
- ' }',
- '',
- ' div#log *.ERROR, label#label_ERROR {',
- ' color: red;',
- ' }',
- '',
- ' div#log *.FATAL, label#label_FATAL {',
- ' color: #660066;',
- ' }',
- '',
- ' div.TRACE#log *.TRACE,',
- ' div.DEBUG#log *.DEBUG,',
- ' div.INFO#log *.INFO,',
- ' div.WARN#log *.WARN,',
- ' div.ERROR#log *.ERROR,',
- ' div.FATAL#log *.FATAL {',
- ' display: block;',
- ' }',
- '',
- ' div#log div.separator {',
- ' background-color: #cccccc;',
- ' margin: 5px 0;',
- ' line-height: 1px;',
- ' }',
- ' </style>',
- ' </head>',
- '',
- ' <body id="body">',
- ' <div id="switchesContainer">',
- ' <div id="switches">',
- ' <div id="levels" class="toolbar">',
- ' Filters:',
- ' <input type="checkbox" id="switch_TRACE" onclick="applyFilters(); checkAllLevels()" checked="checked" title="Show/hide trace messages" /><label for="switch_TRACE" id="label_TRACE">trace</label>',
- ' <input type="checkbox" id="switch_DEBUG" onclick="applyFilters(); checkAllLevels()" checked="checked" title="Show/hide debug messages" /><label for="switch_DEBUG" id="label_DEBUG">debug</label>',
- ' <input type="checkbox" id="switch_INFO" onclick="applyFilters(); checkAllLevels()" checked="checked" title="Show/hide info messages" /><label for="switch_INFO" id="label_INFO">info</label>',
- ' <input type="checkbox" id="switch_WARN" onclick="applyFilters(); checkAllLevels()" checked="checked" title="Show/hide warn messages" /><label for="switch_WARN" id="label_WARN">warn</label>',
- ' <input type="checkbox" id="switch_ERROR" onclick="applyFilters(); checkAllLevels()" checked="checked" title="Show/hide error messages" /><label for="switch_ERROR" id="label_ERROR">error</label>',
- ' <input type="checkbox" id="switch_FATAL" onclick="applyFilters(); checkAllLevels()" checked="checked" title="Show/hide fatal messages" /><label for="switch_FATAL" id="label_FATAL">fatal</label>',
- ' <input type="checkbox" id="switch_ALL" onclick="toggleAllLevels(); applyFilters()" checked="checked" title="Show/hide all messages" /><label for="switch_ALL" id="label_ALL">all</label>',
- ' </div>',
- ' <div id="search" class="toolbar">',
- ' <label for="searchBox" class="searchboxlabel">Search:</label> <input type="text" id="searchBox" onclick="toggleSearchEnabled(true)" onkeyup="scheduleSearch()" size="20" />',
- ' <input type="button" id="searchReset" disabled="disabled" value="Reset" onclick="clearSearch()" class="button" title="Reset the search" />',
- ' <input type="checkbox" id="searchRegex" onclick="doSearch()" title="If checked, search is treated as a regular expression" /><label for="searchRegex">Regex</label>',
- ' <input type="checkbox" id="searchCaseSensitive" onclick="doSearch()" title="If checked, search is case sensitive" /><label for="searchCaseSensitive">Match case</label>',
- ' <input type="checkbox" id="searchDisable" onclick="toggleSearchEnabled()" title="Enable/disable search" /><label for="searchDisable" class="alwaysenabled">Disable</label>',
- ' <div id="searchNav">',
- ' <input type="button" id="searchNext" disabled="disabled" value="Next" onclick="searchNext()" class="button" title="Go to the next matching log entry" />',
- ' <input type="button" id="searchPrevious" disabled="disabled" value="Previous" onclick="searchPrevious()" class="button" title="Go to the previous matching log entry" />',
- ' <input type="checkbox" id="searchFilter" onclick="toggleSearchFilter()" title="If checked, non-matching log entries are filtered out" /><label for="searchFilter">Filter</label>',
- ' <input type="checkbox" id="searchHighlight" onclick="toggleSearchHighlight()" title="Highlight matched search terms" /><label for="searchHighlight" class="alwaysenabled">Highlight all</label>',
- ' </div>',
- ' </div>',
- ' <div id="options" class="toolbar">',
- ' Options:',
- ' <input type="checkbox" id="enableLogging" onclick="toggleLoggingEnabled()" checked="checked" title="Enable/disable logging" /><label for="enableLogging" id="enableLoggingLabel">Log</label>',
- ' <input type="checkbox" id="wrap" onclick="toggleWrap()" title="Enable / disable word wrap" /><label for="wrap" id="wrapLabel">Wrap</label>',
- ' <input type="checkbox" id="newestAtTop" onclick="toggleNewestAtTop()" title="If checked, causes newest messages to appear at the top" /><label for="newestAtTop" id="newestAtTopLabel">Newest at the top</label>',
- ' <input type="checkbox" id="scrollToLatest" onclick="toggleScrollToLatest()" checked="checked" title="If checked, window automatically scrolls to a new message when it is added" /><label for="scrollToLatest" id="scrollToLatestLabel">Scroll to latest</label>',
- ' <input type="button" id="clearButton" value="Clear" onclick="clearLog()" class="button" title="Clear all log messages" />',
- ' <input type="button" id="hideButton" value="Hide" onclick="hide()" class="hidden button" title="Hide the console" />',
- ' <input type="button" id="closeButton" value="Close" onclick="closeWindow()" class="hidden button" title="Close the window" />',
- ' </div>',
- ' </div>',
- ' </div>',
- ' <div id="log" class="TRACE DEBUG INFO WARN ERROR FATAL"></div>',
- ' <div id="commandLine" class="toolbar">',
- ' <div id="commandLineContainer">',
- ' <input type="text" id="command" title="Enter a JavaScript command here and hit return or press \'Evaluate\'" />',
- ' <input type="button" id="evaluateButton" value="Evaluate" class="button" title="Evaluate the command" onclick="evalCommandLine()" />',
- ' </div>',
- ' </div>',
- ' </body>',
- '</html>',
- ''
- ];
- };
-
- var defaultCommandLineFunctions = [];
-
- ConsoleAppender = function() {};
-
- var consoleAppenderIdCounter = 1;
- ConsoleAppender.prototype = new Appender();
-
- ConsoleAppender.prototype.create = function(inPage, container,
- lazyInit, initiallyMinimized, useDocumentWrite, width, height, focusConsoleWindow) {
- var appender = this;
-
- // Common properties
- var initialized = false;
- var consoleWindowCreated = false;
- var consoleWindowLoaded = false;
- var consoleClosed = false;
-
- var queuedLoggingEvents = [];
- var isSupported = true;
- var consoleAppenderId = consoleAppenderIdCounter++;
-
- // Local variables
- initiallyMinimized = extractBooleanFromParam(initiallyMinimized, this.defaults.initiallyMinimized);
- lazyInit = extractBooleanFromParam(lazyInit, this.defaults.lazyInit);
- useDocumentWrite = extractBooleanFromParam(useDocumentWrite, this.defaults.useDocumentWrite);
- var newestMessageAtTop = this.defaults.newestMessageAtTop;
- var scrollToLatestMessage = this.defaults.scrollToLatestMessage;
- width = width ? width : this.defaults.width;
- height = height ? height : this.defaults.height;
- var maxMessages = this.defaults.maxMessages;
- var showCommandLine = this.defaults.showCommandLine;
- var commandLineObjectExpansionDepth = this.defaults.commandLineObjectExpansionDepth;
- var showHideButton = this.defaults.showHideButton;
- var showCloseButton = this.defaults.showCloseButton;
-
- this.setLayout(this.defaults.layout);
-
- // Functions whose implementations vary between subclasses
- var init, createWindow, safeToAppend, getConsoleWindow, open;
-
- // Configuration methods. The function scope is used to prevent
- // direct alteration to the appender configuration properties.
- var appenderName = inPage ? "InPageAppender" : "PopUpAppender";
- var checkCanConfigure = function(configOptionName) {
- if (consoleWindowCreated) {
- handleError(appenderName + ": configuration option '" + configOptionName + "' may not be set after the appender has been initialized");
- return false;
- }
- return true;
- };
-
- var consoleWindowExists = function() {
- return (consoleWindowLoaded && isSupported && !consoleClosed);
- };
-
- this.isNewestMessageAtTop = function() { return newestMessageAtTop; };
- this.setNewestMessageAtTop = function(newestMessageAtTopParam) {
- newestMessageAtTop = bool(newestMessageAtTopParam);
- if (consoleWindowExists()) {
- getConsoleWindow().setNewestAtTop(newestMessageAtTop);
- }
- };
-
- this.isScrollToLatestMessage = function() { return scrollToLatestMessage; };
- this.setScrollToLatestMessage = function(scrollToLatestMessageParam) {
- scrollToLatestMessage = bool(scrollToLatestMessageParam);
- if (consoleWindowExists()) {
- getConsoleWindow().setScrollToLatest(scrollToLatestMessage);
- }
- };
-
- this.getWidth = function() { return width; };
- this.setWidth = function(widthParam) {
- if (checkCanConfigure("width")) {
- width = extractStringFromParam(widthParam, width);
- }
- };
-
- this.getHeight = function() { return height; };
- this.setHeight = function(heightParam) {
- if (checkCanConfigure("height")) {
- height = extractStringFromParam(heightParam, height);
- }
- };
-
- this.getMaxMessages = function() { return maxMessages; };
- this.setMaxMessages = function(maxMessagesParam) {
- maxMessages = extractIntFromParam(maxMessagesParam, maxMessages);
- if (consoleWindowExists()) {
- getConsoleWindow().setMaxMessages(maxMessages);
- }
- };
-
- this.isShowCommandLine = function() { return showCommandLine; };
- this.setShowCommandLine = function(showCommandLineParam) {
- showCommandLine = bool(showCommandLineParam);
- if (consoleWindowExists()) {
- getConsoleWindow().setShowCommandLine(showCommandLine);
- }
- };
-
- this.isShowHideButton = function() { return showHideButton; };
- this.setShowHideButton = function(showHideButtonParam) {
- showHideButton = bool(showHideButtonParam);
- if (consoleWindowExists()) {
- getConsoleWindow().setShowHideButton(showHideButton);
- }
- };
-
- this.isShowCloseButton = function() { return showCloseButton; };
- this.setShowCloseButton = function(showCloseButtonParam) {
- showCloseButton = bool(showCloseButtonParam);
- if (consoleWindowExists()) {
- getConsoleWindow().setShowCloseButton(showCloseButton);
- }
- };
-
- this.getCommandLineObjectExpansionDepth = function() { return commandLineObjectExpansionDepth; };
- this.setCommandLineObjectExpansionDepth = function(commandLineObjectExpansionDepthParam) {
- commandLineObjectExpansionDepth = extractIntFromParam(commandLineObjectExpansionDepthParam, commandLineObjectExpansionDepth);
- };
-
- var minimized = initiallyMinimized;
- this.isInitiallyMinimized = function() { return initiallyMinimized; };
- this.setInitiallyMinimized = function(initiallyMinimizedParam) {
- if (checkCanConfigure("initiallyMinimized")) {
- initiallyMinimized = bool(initiallyMinimizedParam);
- minimized = initiallyMinimized;
- }
- };
-
- this.isUseDocumentWrite = function() { return useDocumentWrite; };
- this.setUseDocumentWrite = function(useDocumentWriteParam) {
- if (checkCanConfigure("useDocumentWrite")) {
- useDocumentWrite = bool(useDocumentWriteParam);
- }
- };
-
- // Common methods
- function QueuedLoggingEvent(loggingEvent, formattedMessage) {
- this.loggingEvent = loggingEvent;
- this.levelName = loggingEvent.level.name;
- this.formattedMessage = formattedMessage;
- }
-
- QueuedLoggingEvent.prototype.append = function() {
- getConsoleWindow().log(this.levelName, this.formattedMessage);
- };
-
- function QueuedGroup(name, initiallyExpanded) {
- this.name = name;
- this.initiallyExpanded = initiallyExpanded;
- }
-
- QueuedGroup.prototype.append = function() {
- getConsoleWindow().group(this.name, this.initiallyExpanded);
- };
-
- function QueuedGroupEnd() {}
-
- QueuedGroupEnd.prototype.append = function() {
- getConsoleWindow().groupEnd();
- };
-
- var checkAndAppend = function() {
- // Next line forces a check of whether the window has been closed
- safeToAppend();
- if (!initialized) {
- init();
- } else if (consoleClosed && reopenWhenClosed) {
- createWindow();
- }
- if (safeToAppend()) {
- appendQueuedLoggingEvents();
- }
- };
-
- this.append = function(loggingEvent) {
- if (isSupported) {
- // Format the message
- var formattedMessage = appender.getLayout().formatWithException(loggingEvent);
- queuedLoggingEvents.push(new QueuedLoggingEvent(loggingEvent, formattedMessage));
- checkAndAppend();
- }
- };
-
- this.group = function(name, initiallyExpanded) {
- if (isSupported) {
- queuedLoggingEvents.push(new QueuedGroup(name, initiallyExpanded));
- checkAndAppend();
- }
- };
-
- this.groupEnd = function() {
- if (isSupported) {
- queuedLoggingEvents.push(new QueuedGroupEnd());
- checkAndAppend();
- }
- };
-
- var appendQueuedLoggingEvents = function() {
- while (queuedLoggingEvents.length > 0) {
- queuedLoggingEvents.shift().append();
- }
- if (focusConsoleWindow) {
- getConsoleWindow().focus();
- }
- };
-
- this.setAddedToLogger = function(logger) {
- this.loggers.push(logger);
- if (enabled && !lazyInit) {
- init();
- }
- };
-
- this.clear = function() {
- if (consoleWindowExists()) {
- getConsoleWindow().clearLog();
- }
- queuedLoggingEvents.length = 0;
- };
-
- this.focus = function() {
- if (consoleWindowExists()) {
- getConsoleWindow().focus();
- }
- };
-
- this.focusCommandLine = function() {
- if (consoleWindowExists()) {
- getConsoleWindow().focusCommandLine();
- }
- };
-
- this.focusSearch = function() {
- if (consoleWindowExists()) {
- getConsoleWindow().focusSearch();
- }
- };
-
- var commandWindow = window;
-
- this.getCommandWindow = function() { return commandWindow; };
- this.setCommandWindow = function(commandWindowParam) {
- commandWindow = commandWindowParam;
- };
-
- this.executeLastCommand = function() {
- if (consoleWindowExists()) {
- getConsoleWindow().evalLastCommand();
- }
- };
-
- var commandLayout = new PatternLayout("%m");
- this.getCommandLayout = function() { return commandLayout; };
- this.setCommandLayout = function(commandLayoutParam) {
- commandLayout = commandLayoutParam;
- };
-
- this.evalCommandAndAppend = function(expr) {
- var commandReturnValue = { appendResult: true, isError: false };
- var commandOutput = "";
- // Evaluate the command
- try {
- var result, i;
- // The next three lines constitute a workaround for IE. Bizarrely, iframes seem to have no
- // eval method on the window object initially, but once execScript has been called on
- // it once then the eval method magically appears. See http://www.thismuchiknow.co.uk/?p=25
- if (!commandWindow.eval && commandWindow.execScript) {
- commandWindow.execScript("null");
- }
-
- var commandLineFunctionsHash = {};
- for (i = 0, len = commandLineFunctions.length; i < len; i++) {
- commandLineFunctionsHash[commandLineFunctions[i][0]] = commandLineFunctions[i][1];
- }
-
- // Keep an array of variables that are being changed in the command window so that they
- // can be restored to their original values afterwards
- var objectsToRestore = [];
- var addObjectToRestore = function(name) {
- objectsToRestore.push([name, commandWindow[name]]);
- };
-
- addObjectToRestore("appender");
- commandWindow.appender = appender;
-
- addObjectToRestore("commandReturnValue");
- commandWindow.commandReturnValue = commandReturnValue;
-
- addObjectToRestore("commandLineFunctionsHash");
- commandWindow.commandLineFunctionsHash = commandLineFunctionsHash;
-
- var addFunctionToWindow = function(name) {
- addObjectToRestore(name);
- commandWindow[name] = function() {
- return this.commandLineFunctionsHash[name](appender, arguments, commandReturnValue);
- };
- };
-
- for (i = 0, len = commandLineFunctions.length; i < len; i++) {
- addFunctionToWindow(commandLineFunctions[i][0]);
- }
-
- // Another bizarre workaround to get IE to eval in the global scope
- if (commandWindow === window && commandWindow.execScript) {
- addObjectToRestore("evalExpr");
- addObjectToRestore("result");
- window.evalExpr = expr;
- commandWindow.execScript("window.result=eval(window.evalExpr);");
- result = window.result;
- } else {
- result = commandWindow.eval(expr);
- }
- commandOutput = isUndefined(result) ? result : formatObjectExpansion(result, commandLineObjectExpansionDepth);
-
- // Restore variables in the command window to their original state
- for (i = 0, len = objectsToRestore.length; i < len; i++) {
- commandWindow[objectsToRestore[i][0]] = objectsToRestore[i][1];
- }
- } catch (ex) {
- commandOutput = "Error evaluating command: " + getExceptionStringRep(ex);
- commandReturnValue.isError = true;
- }
- // Append command output
- if (commandReturnValue.appendResult) {
- var message = ">>> " + expr;
- if (!isUndefined(commandOutput)) {
- message += newLine + commandOutput;
- }
- var level = commandReturnValue.isError ? Level.ERROR : Level.INFO;
- var loggingEvent = new LoggingEvent(null, new Date(), level, [message], null);
- var mainLayout = this.getLayout();
- this.setLayout(commandLayout);
- this.append(loggingEvent);
- this.setLayout(mainLayout);
- }
- };
-
- var commandLineFunctions = defaultCommandLineFunctions.concat([]);
-
- this.addCommandLineFunction = function(functionName, commandLineFunction) {
- commandLineFunctions.push([functionName, commandLineFunction]);
- };
-
- var commandHistoryCookieName = "log4javascriptCommandHistory";
- this.storeCommandHistory = function(commandHistory) {
- setCookie(commandHistoryCookieName, commandHistory.join(","));
- };
-
- var writeHtml = function(doc) {
- var lines = getConsoleHtmlLines();
- doc.open();
- for (var i = 0, len = lines.length; i < len; i++) {
- doc.writeln(lines[i]);
- }
- doc.close();
- };
-
- // Set up event listeners
- this.setEventTypes(["load", "unload"]);
-
- var consoleWindowLoadHandler = function() {
- var win = getConsoleWindow();
- win.setAppender(appender);
- win.setNewestAtTop(newestMessageAtTop);
- win.setScrollToLatest(scrollToLatestMessage);
- win.setMaxMessages(maxMessages);
- win.setShowCommandLine(showCommandLine);
- win.setShowHideButton(showHideButton);
- win.setShowCloseButton(showCloseButton);
- win.setMainWindow(window);
-
- // Restore command history stored in cookie
- var storedValue = getCookie(commandHistoryCookieName);
- if (storedValue) {
- win.commandHistory = storedValue.split(",");
- win.currentCommandIndex = win.commandHistory.length;
- }
-
- appender.dispatchEvent("load", { "win" : win });
- };
-
- this.unload = function() {
- logLog.debug("unload " + this + ", caller: " + this.unload.caller);
- if (!consoleClosed) {
- logLog.debug("really doing unload " + this);
- consoleClosed = true;
- consoleWindowLoaded = false;
- consoleWindowCreated = false;
- appender.dispatchEvent("unload", {});
- }
- };
-
- var pollConsoleWindow = function(windowTest, interval, successCallback, errorMessage) {
- function doPoll() {
- try {
- // Test if the console has been closed while polling
- if (consoleClosed) {
- clearInterval(poll);
- }
- if (windowTest(getConsoleWindow())) {
- clearInterval(poll);
- successCallback();
- }
- } catch (ex) {
- clearInterval(poll);
- isSupported = false;
- handleError(errorMessage, ex);
- }
- }
-
- // Poll the pop-up since the onload event is not reliable
- var poll = setInterval(doPoll, interval);
- };
-
- var getConsoleUrl = function() {
- var documentDomainSet = (document.domain != location.hostname);
- return useDocumentWrite ? "" : getBaseUrl() + "console_uncompressed.html" +
- (documentDomainSet ? "?log4javascript_domain=" + escape(document.domain) : "");
- };
-
- // Define methods and properties that vary between subclasses
- if (inPage) {
- // InPageAppender
-
- var containerElement = null;
-
- // Configuration methods. The function scope is used to prevent
- // direct alteration to the appender configuration properties.
- var cssProperties = [];
- this.addCssProperty = function(name, value) {
- if (checkCanConfigure("cssProperties")) {
- cssProperties.push([name, value]);
- }
- };
-
- // Define useful variables
- var windowCreationStarted = false;
- var iframeContainerDiv;
- var iframeId = uniqueId + "_InPageAppender_" + consoleAppenderId;
-
- this.hide = function() {
- if (initialized && consoleWindowCreated) {
- if (consoleWindowExists()) {
- getConsoleWindow().$("command").blur();
- }
- iframeContainerDiv.style.display = "none";
- minimized = true;
- }
- };
-
- this.show = function() {
- if (initialized) {
- if (consoleWindowCreated) {
- iframeContainerDiv.style.display = "block";
- this.setShowCommandLine(showCommandLine); // Force IE to update
- minimized = false;
- } else if (!windowCreationStarted) {
- createWindow(true);
- }
- }
- };
-
- this.isVisible = function() {
- return !minimized && !consoleClosed;
- };
-
- this.close = function(fromButton) {
- if (!consoleClosed && (!fromButton || confirm("This will permanently remove the console from the page. No more messages will be logged. Do you wish to continue?"))) {
- iframeContainerDiv.parentNode.removeChild(iframeContainerDiv);
- this.unload();
- }
- };
-
- // Create open, init, getConsoleWindow and safeToAppend functions
- open = function() {
- var initErrorMessage = "InPageAppender.open: unable to create console iframe";
-
- function finalInit() {
- try {
- if (!initiallyMinimized) {
- appender.show();
- }
- consoleWindowLoadHandler();
- consoleWindowLoaded = true;
- appendQueuedLoggingEvents();
- } catch (ex) {
- isSupported = false;
- handleError(initErrorMessage, ex);
- }
- }
-
- function writeToDocument() {
- try {
- var windowTest = function(win) { return isLoaded(win); };
- if (useDocumentWrite) {
- writeHtml(getConsoleWindow().document);
- }
- if (windowTest(getConsoleWindow())) {
- finalInit();
- } else {
- pollConsoleWindow(windowTest, 100, finalInit, initErrorMessage);
- }
- } catch (ex) {
- isSupported = false;
- handleError(initErrorMessage, ex);
- }
- }
-
- minimized = false;
- iframeContainerDiv = containerElement.appendChild(document.createElement("div"));
-
- iframeContainerDiv.style.width = width;
- iframeContainerDiv.style.height = height;
- iframeContainerDiv.style.border = "solid gray 1px";
-
- for (var i = 0, len = cssProperties.length; i < len; i++) {
- iframeContainerDiv.style[cssProperties[i][0]] = cssProperties[i][1];
- }
-
- var iframeSrc = useDocumentWrite ? "" : " src='" + getConsoleUrl() + "'";
-
- // Adding an iframe using the DOM would be preferable, but it doesn't work
- // in IE5 on Windows, or in Konqueror prior to version 3.5 - in Konqueror
- // it creates the iframe fine but I haven't been able to find a way to obtain
- // the iframe's window object
- iframeContainerDiv.innerHTML = "<iframe id='" + iframeId + "' name='" + iframeId +
- "' width='100%' height='100%' frameborder='0'" + iframeSrc +
- " scrolling='no'></iframe>";
- consoleClosed = false;
-
- // Write the console HTML to the iframe
- var iframeDocumentExistsTest = function(win) {
- try {
- return bool(win) && bool(win.document);
- } catch (ex) {
- return false;
- }
- };
- if (iframeDocumentExistsTest(getConsoleWindow())) {
- writeToDocument();
- } else {
- pollConsoleWindow(iframeDocumentExistsTest, 100, writeToDocument, initErrorMessage);
- }
- consoleWindowCreated = true;
- };
-
- createWindow = function(show) {
- if (show || !initiallyMinimized) {
- var pageLoadHandler = function() {
- if (!container) {
- // Set up default container element
- containerElement = document.createElement("div");
- containerElement.style.position = "fixed";
- containerElement.style.left = "0";
- containerElement.style.right = "0";
- containerElement.style.bottom = "0";
- document.body.appendChild(containerElement);
- appender.addCssProperty("borderWidth", "1px 0 0 0");
- appender.addCssProperty("zIndex", 1000000); // Can't find anything authoritative that says how big z-index can be
- open();
- } else {
- try {
- var el = document.getElementById(container);
- if (el.nodeType == 1) {
- containerElement = el;
- }
- open();
- } catch (ex) {
- handleError("InPageAppender.init: invalid container element '" + container + "' supplied", ex);
- }
- }
- };
-
- // Test the type of the container supplied. First, check if it's an element
- if (pageLoaded && container && container.appendChild) {
- containerElement = container;
- open();
- } else if (pageLoaded) {
- pageLoadHandler();
- } else {
- log4javascript.addEventListener("load", pageLoadHandler);
- }
- windowCreationStarted = true;
- }
- };
-
- init = function() {
- createWindow();
- initialized = true;
- };
-
- getConsoleWindow = function() {
- var iframe = window.frames[iframeId];
- if (iframe) {
- return iframe;
- }
- };
-
- safeToAppend = function() {
- if (isSupported && !consoleClosed) {
- if (consoleWindowCreated && !consoleWindowLoaded && getConsoleWindow() && isLoaded(getConsoleWindow())) {
- consoleWindowLoaded = true;
- }
- return consoleWindowLoaded;
- }
- return false;
- };
- } else {
- // PopUpAppender
-
- // Extract params
- var useOldPopUp = appender.defaults.useOldPopUp;
- var complainAboutPopUpBlocking = appender.defaults.complainAboutPopUpBlocking;
- var reopenWhenClosed = this.defaults.reopenWhenClosed;
-
- // Configuration methods. The function scope is used to prevent
- // direct alteration to the appender configuration properties.
- this.isUseOldPopUp = function() { return useOldPopUp; };
- this.setUseOldPopUp = function(useOldPopUpParam) {
- if (checkCanConfigure("useOldPopUp")) {
- useOldPopUp = bool(useOldPopUpParam);
- }
- };
-
- this.isComplainAboutPopUpBlocking = function() { return complainAboutPopUpBlocking; };
- this.setComplainAboutPopUpBlocking = function(complainAboutPopUpBlockingParam) {
- if (checkCanConfigure("complainAboutPopUpBlocking")) {
- complainAboutPopUpBlocking = bool(complainAboutPopUpBlockingParam);
- }
- };
-
- this.isFocusPopUp = function() { return focusConsoleWindow; };
- this.setFocusPopUp = function(focusPopUpParam) {
- // This property can be safely altered after logging has started
- focusConsoleWindow = bool(focusPopUpParam);
- };
-
- this.isReopenWhenClosed = function() { return reopenWhenClosed; };
- this.setReopenWhenClosed = function(reopenWhenClosedParam) {
- // This property can be safely altered after logging has started
- reopenWhenClosed = bool(reopenWhenClosedParam);
- };
-
- this.close = function() {
- logLog.debug("close " + this);
- try {
- popUp.close();
- this.unload();
- } catch (ex) {
- // Do nothing
- }
- };
-
- this.hide = function() {
- logLog.debug("hide " + this);
- if (consoleWindowExists()) {
- this.close();
- }
- };
-
- this.show = function() {
- logLog.debug("show " + this);
- if (!consoleWindowCreated) {
- open();
- }
- };
-
- this.isVisible = function() {
- return safeToAppend();
- };
-
- // Define useful variables
- var popUp;
-
- // Create open, init, getConsoleWindow and safeToAppend functions
- open = function() {
- var windowProperties = "width=" + width + ",height=" + height + ",status,resizable";
- var frameInfo = "";
- try {
- var frameEl = window.frameElement;
- if (frameEl) {
- frameInfo = "_" + frameEl.tagName + "_" + (frameEl.name || frameEl.id || "");
- }
- } catch (e) {
- frameInfo = "_inaccessibleParentFrame";
- }
- var windowName = "PopUp_" + location.host.replace(/[^a-z0-9]/gi, "_") + "_" + consoleAppenderId + frameInfo;
- if (!useOldPopUp || !useDocumentWrite) {
- // Ensure a previous window isn't used by using a unique name
- windowName = windowName + "_" + uniqueId;
- }
-
- var checkPopUpClosed = function(win) {
- if (consoleClosed) {
- return true;
- } else {
- try {
- return bool(win) && win.closed;
- } catch(ex) {}
- }
- return false;
- };
-
- var popUpClosedCallback = function() {
- if (!consoleClosed) {
- appender.unload();
- }
- };
-
- function finalInit() {
- getConsoleWindow().setCloseIfOpenerCloses(!useOldPopUp || !useDocumentWrite);
- consoleWindowLoadHandler();
- consoleWindowLoaded = true;
- appendQueuedLoggingEvents();
- pollConsoleWindow(checkPopUpClosed, 500, popUpClosedCallback,
- "PopUpAppender.checkPopUpClosed: error checking pop-up window");
- }
-
- try {
- popUp = window.open(getConsoleUrl(), windowName, windowProperties);
- consoleClosed = false;
- consoleWindowCreated = true;
- if (popUp && popUp.document) {
- if (useDocumentWrite && useOldPopUp && isLoaded(popUp)) {
- popUp.mainPageReloaded();
- finalInit();
- } else {
- if (useDocumentWrite) {
- writeHtml(popUp.document);
- }
- // Check if the pop-up window object is available
- var popUpLoadedTest = function(win) { return bool(win) && isLoaded(win); };
- if (isLoaded(popUp)) {
- finalInit();
- } else {
- pollConsoleWindow(popUpLoadedTest, 100, finalInit,
- "PopUpAppender.init: unable to create console window");
- }
- }
- } else {
- isSupported = false;
- logLog.warn("PopUpAppender.init: pop-ups blocked, please unblock to use PopUpAppender");
- if (complainAboutPopUpBlocking) {
- handleError("log4javascript: pop-up windows appear to be blocked. Please unblock them to use pop-up logging.");
- }
- }
- } catch (ex) {
- handleError("PopUpAppender.init: error creating pop-up", ex);
- }
- };
-
- createWindow = function() {
- if (!initiallyMinimized) {
- open();
- }
- };
-
- init = function() {
- createWindow();
- initialized = true;
- };
-
- getConsoleWindow = function() {
- return popUp;
- };
-
- safeToAppend = function() {
- if (isSupported && !isUndefined(popUp) && !consoleClosed) {
- if (popUp.closed ||
- (consoleWindowLoaded && isUndefined(popUp.closed))) { // Extra check for Opera
- appender.unload();
- logLog.debug("PopUpAppender: pop-up closed");
- return false;
- }
- if (!consoleWindowLoaded && isLoaded(popUp)) {
- consoleWindowLoaded = true;
- }
- }
- return isSupported && consoleWindowLoaded && !consoleClosed;
- };
- }
-
- // Expose getConsoleWindow so that automated tests can check the DOM
- this.getConsoleWindow = getConsoleWindow;
- };
-
- ConsoleAppender.addGlobalCommandLineFunction = function(functionName, commandLineFunction) {
- defaultCommandLineFunctions.push([functionName, commandLineFunction]);
- };
-
- /* ------------------------------------------------------------------ */
-
- function PopUpAppender(lazyInit, initiallyMinimized, useDocumentWrite,
- width, height) {
- this.create(false, null, lazyInit, initiallyMinimized,
- useDocumentWrite, width, height, this.defaults.focusPopUp);
- }
-
- PopUpAppender.prototype = new ConsoleAppender();
-
- PopUpAppender.prototype.defaults = {
- layout: new PatternLayout("%d{HH:mm:ss} %-5p - %m{1}%n"),
- initiallyMinimized: false,
- focusPopUp: false,
- lazyInit: true,
- useOldPopUp: true,
- complainAboutPopUpBlocking: true,
- newestMessageAtTop: false,
- scrollToLatestMessage: true,
- width: "600",
- height: "400",
- reopenWhenClosed: false,
- maxMessages: null,
- showCommandLine: true,
- commandLineObjectExpansionDepth: 1,
- showHideButton: false,
- showCloseButton: true,
- useDocumentWrite: true
- };
-
- PopUpAppender.prototype.toString = function() {
- return "PopUpAppender";
- };
-
- log4javascript.PopUpAppender = PopUpAppender;
-
- /* ------------------------------------------------------------------ */
-
- function InPageAppender(container, lazyInit, initiallyMinimized,
- useDocumentWrite, width, height) {
- this.create(true, container, lazyInit, initiallyMinimized,
- useDocumentWrite, width, height, false);
- }
-
- InPageAppender.prototype = new ConsoleAppender();
-
- InPageAppender.prototype.defaults = {
- layout: new PatternLayout("%d{HH:mm:ss} %-5p - %m{1}%n"),
- initiallyMinimized: false,
- lazyInit: true,
- newestMessageAtTop: false,
- scrollToLatestMessage: true,
- width: "100%",
- height: "220px",
- maxMessages: null,
- showCommandLine: true,
- commandLineObjectExpansionDepth: 1,
- showHideButton: false,
- showCloseButton: false,
- showLogEntryDeleteButtons: true,
- useDocumentWrite: true
- };
-
- InPageAppender.prototype.toString = function() {
- return "InPageAppender";
- };
-
- log4javascript.InPageAppender = InPageAppender;
-
- // Next line for backwards compatibility
- log4javascript.InlineAppender = InPageAppender;
- })();
- /* ---------------------------------------------------------------------- */
- // Console extension functions
-
- function padWithSpaces(str, len) {
- if (str.length < len) {
- var spaces = [];
- var numberOfSpaces = Math.max(0, len - str.length);
- for (var i = 0; i < numberOfSpaces; i++) {
- spaces[i] = " ";
- }
- str += spaces.join("");
- }
- return str;
- }
-
- (function() {
- function dir(obj) {
- var maxLen = 0;
- // Obtain the length of the longest property name
- for (var p in obj) {
- maxLen = Math.max(toStr(p).length, maxLen);
- }
- // Create the nicely formatted property list
- var propList = [];
- for (p in obj) {
- var propNameStr = " " + padWithSpaces(toStr(p), maxLen + 2);
- var propVal;
- try {
- propVal = splitIntoLines(toStr(obj[p])).join(padWithSpaces(newLine, maxLen + 6));
- } catch (ex) {
- propVal = "[Error obtaining property. Details: " + getExceptionMessage(ex) + "]";
- }
- propList.push(propNameStr + propVal);
- }
- return propList.join(newLine);
- }
-
- var nodeTypes = {
- ELEMENT_NODE: 1,
- ATTRIBUTE_NODE: 2,
- TEXT_NODE: 3,
- CDATA_SECTION_NODE: 4,
- ENTITY_REFERENCE_NODE: 5,
- ENTITY_NODE: 6,
- PROCESSING_INSTRUCTION_NODE: 7,
- COMMENT_NODE: 8,
- DOCUMENT_NODE: 9,
- DOCUMENT_TYPE_NODE: 10,
- DOCUMENT_FRAGMENT_NODE: 11,
- NOTATION_NODE: 12
- };
-
- var preFormattedElements = ["script", "pre"];
-
- // This should be the definitive list, as specified by the XHTML 1.0 Transitional DTD
- var emptyElements = ["br", "img", "hr", "param", "link", "area", "input", "col", "base", "meta"];
- var indentationUnit = " ";
-
- // Create and return an XHTML string from the node specified
- function getXhtml(rootNode, includeRootNode, indentation, startNewLine, preformatted) {
- includeRootNode = (typeof includeRootNode == "undefined") ? true : !!includeRootNode;
- if (typeof indentation != "string") {
- indentation = "";
- }
- startNewLine = !!startNewLine;
- preformatted = !!preformatted;
- var xhtml;
-
- function isWhitespace(node) {
- return ((node.nodeType == nodeTypes.TEXT_NODE) && /^[ \t\r\n]*$/.test(node.nodeValue));
- }
-
- function fixAttributeValue(attrValue) {
- return attrValue.toString().replace(/&/g, "&").replace(/</g, "<").replace(/"/g, """);
- }
-
- function getStyleAttributeValue(el) {
- var stylePairs = el.style.cssText.split(";");
- var styleValue = "";
- for (var j = 0, len = stylePairs.length; j < len; j++) {
- var nameValueBits = stylePairs[j].split(":");
- var props = [];
- if (!/^\s*$/.test(nameValueBits[0])) {
- props.push(trim(nameValueBits[0]).toLowerCase() + ":" + trim(nameValueBits[1]));
- }
- styleValue = props.join(";");
- }
- return styleValue;
- }
-
- function getNamespace(el) {
- if (el.prefix) {
- return el.prefix;
- } else if (el.outerHTML) {
- var regex = new RegExp("<([^:]+):" + el.tagName + "[^>]*>", "i");
- if (regex.test(el.outerHTML)) {
- return RegExp.$1.toLowerCase();
- }
- }
- return "";
- }
-
- var lt = "<";
- var gt = ">";
- var i, len;
-
- if (includeRootNode && rootNode.nodeType != nodeTypes.DOCUMENT_FRAGMENT_NODE) {
- switch (rootNode.nodeType) {
- case nodeTypes.ELEMENT_NODE:
- var tagName = rootNode.tagName.toLowerCase();
- xhtml = startNewLine ? newLine + indentation : "";
- xhtml += lt;
- // Allow for namespaces, where present
- var prefix = getNamespace(rootNode);
- var hasPrefix = !!prefix;
- if (hasPrefix) {
- xhtml += prefix + ":";
- }
- xhtml += tagName;
- for (i = 0, len = rootNode.attributes.length; i < len; i++) {
- var currentAttr = rootNode.attributes[i];
- // Check the attribute is valid.
- if (! currentAttr.specified ||
- currentAttr.nodeValue === null ||
- currentAttr.nodeName.toLowerCase() === "style" ||
- typeof currentAttr.nodeValue !== "string" ||
- currentAttr.nodeName.indexOf("_moz") === 0) {
- continue;
- }
- xhtml += " " + currentAttr.nodeName.toLowerCase() + "=\"";
- xhtml += fixAttributeValue(currentAttr.nodeValue);
- xhtml += "\"";
- }
- // Style needs to be done separately as it is not reported as an
- // attribute in IE
- if (rootNode.style.cssText) {
- var styleValue = getStyleAttributeValue(rootNode);
- if (styleValue !== "") {
- xhtml += " style=\"" + getStyleAttributeValue(rootNode) + "\"";
- }
- }
- if (array_contains(emptyElements, tagName) ||
- (hasPrefix && !rootNode.hasChildNodes())) {
- xhtml += "/" + gt;
- } else {
- xhtml += gt;
- // Add output for childNodes collection (which doesn't include attribute nodes)
- var childStartNewLine = !(rootNode.childNodes.length === 1 &&
- rootNode.childNodes[0].nodeType === nodeTypes.TEXT_NODE);
- var childPreformatted = array_contains(preFormattedElements, tagName);
- for (i = 0, len = rootNode.childNodes.length; i < len; i++) {
- xhtml += getXhtml(rootNode.childNodes[i], true, indentation + indentationUnit,
- childStartNewLine, childPreformatted);
- }
- // Add the end tag
- var endTag = lt + "/" + tagName + gt;
- xhtml += childStartNewLine ? newLine + indentation + endTag : endTag;
- }
- return xhtml;
- case nodeTypes.TEXT_NODE:
- if (isWhitespace(rootNode)) {
- xhtml = "";
- } else {
- if (preformatted) {
- xhtml = rootNode.nodeValue;
- } else {
- // Trim whitespace from each line of the text node
- var lines = splitIntoLines(trim(rootNode.nodeValue));
- var trimmedLines = [];
- for (i = 0, len = lines.length; i < len; i++) {
- trimmedLines[i] = trim(lines[i]);
- }
- xhtml = trimmedLines.join(newLine + indentation);
- }
- if (startNewLine) {
- xhtml = newLine + indentation + xhtml;
- }
- }
- return xhtml;
- case nodeTypes.CDATA_SECTION_NODE:
- return "<![CDA" + "TA[" + rootNode.nodeValue + "]" + "]>" + newLine;
- case nodeTypes.DOCUMENT_NODE:
- xhtml = "";
- // Add output for childNodes collection (which doesn't include attribute nodes)
- for (i = 0, len = rootNode.childNodes.length; i < len; i++) {
- xhtml += getXhtml(rootNode.childNodes[i], true, indentation);
- }
- return xhtml;
- default:
- return "";
- }
- } else {
- xhtml = "";
- // Add output for childNodes collection (which doesn't include attribute nodes)
- for (i = 0, len = rootNode.childNodes.length; i < len; i++) {
- xhtml += getXhtml(rootNode.childNodes[i], true, indentation + indentationUnit);
- }
- return xhtml;
- }
- }
-
- function createCommandLineFunctions() {
- ConsoleAppender.addGlobalCommandLineFunction("$", function(appender, args, returnValue) {
- return document.getElementById(args[0]);
- });
-
- ConsoleAppender.addGlobalCommandLineFunction("dir", function(appender, args, returnValue) {
- var lines = [];
- for (var i = 0, len = args.length; i < len; i++) {
- lines[i] = dir(args[i]);
- }
- return lines.join(newLine + newLine);
- });
-
- ConsoleAppender.addGlobalCommandLineFunction("dirxml", function(appender, args, returnValue) {
- var lines = [];
- for (var i = 0, len = args.length; i < len; i++) {
- lines[i] = getXhtml(args[i]);
- }
- return lines.join(newLine + newLine);
- });
-
- ConsoleAppender.addGlobalCommandLineFunction("cd", function(appender, args, returnValue) {
- var win, message;
- if (args.length === 0 || args[0] === "") {
- win = window;
- message = "Command line set to run in main window";
- } else {
- if (args[0].window == args[0]) {
- win = args[0];
- message = "Command line set to run in frame '" + args[0].name + "'";
- } else {
- win = window.frames[args[0]];
- if (win) {
- message = "Command line set to run in frame '" + args[0] + "'";
- } else {
- returnValue.isError = true;
- message = "Frame '" + args[0] + "' does not exist";
- win = appender.getCommandWindow();
- }
- }
- }
- appender.setCommandWindow(win);
- return message;
- });
-
- ConsoleAppender.addGlobalCommandLineFunction("clear", function(appender, args, returnValue) {
- returnValue.appendResult = false;
- appender.clear();
- });
-
- ConsoleAppender.addGlobalCommandLineFunction("keys", function(appender, args, returnValue) {
- var keys = [];
- for (var k in args[0]) {
- keys.push(k);
- }
- return keys;
- });
-
- ConsoleAppender.addGlobalCommandLineFunction("values", function(appender, args, returnValue) {
- var values = [];
- for (var k in args[0]) {
- try {
- values.push(args[0][k]);
- } catch (ex) {
- logLog.warn("values(): Unable to obtain value for key " + k + ". Details: " + getExceptionMessage(ex));
- }
- }
- return values;
- });
-
- ConsoleAppender.addGlobalCommandLineFunction("expansionDepth", function(appender, args, returnValue) {
- var expansionDepth = parseInt(args[0], 10);
- if (isNaN(expansionDepth) || expansionDepth < 0) {
- returnValue.isError = true;
- return "" + args[0] + " is not a valid expansion depth";
- } else {
- appender.setCommandLineObjectExpansionDepth(expansionDepth);
- return "Object expansion depth set to " + expansionDepth;
- }
- });
- }
-
- function init() {
- // Add command line functions
- createCommandLineFunctions();
- }
-
- /* ------------------------------------------------------------------ */
-
- init();
- })();
-
- /* ---------------------------------------------------------------------- */
-
- function createDefaultLogger() {
- var logger = log4javascript.getLogger(defaultLoggerName);
- var a = new log4javascript.PopUpAppender();
- logger.addAppender(a);
- return logger;
- }
-
- /* ---------------------------------------------------------------------- */
- // Main load
-
- log4javascript.setDocumentReady = function() {
- pageLoaded = true;
- log4javascript.dispatchEvent("load", {});
- };
-
- if (window.addEventListener) {
- window.addEventListener("load", log4javascript.setDocumentReady, false);
- } else if (window.attachEvent) {
- window.attachEvent("onload", log4javascript.setDocumentReady);
- } else {
- var oldOnload = window.onload;
- if (typeof window.onload != "function") {
- window.onload = log4javascript.setDocumentReady;
- } else {
- window.onload = function(evt) {
- if (oldOnload) {
- oldOnload(evt);
- }
- log4javascript.setDocumentReady();
- };
- }
- }
-
- return log4javascript;
- }, this);