/**
* Redirects console output to an <ul> element
* @namespace
*/
var ConsoleLogHTML = (function (original, methods, console, Object, TYPE_UNDEFINED, TYPE_BOOLEAN, INSTANCE_OBJECT_OBJECT) {
'use strict';
for (var i = 0; i < methods.length; i++) {
if (TYPE_UNDEFINED !== typeof console[methods[i]]) {
original[methods[i]] = console[methods[i]];
}
}
var originalSkipHtml = console.skipHtml,
originalKeys = Object.keys(original),
originalClear = TYPE_UNDEFINED !== typeof console.clear ? console.clear : false,
jQueryIsUp = typeof jQuery !== TYPE_UNDEFINED ? jQuery : false,
extend = function () {
var out = {},
i = 0,
j, keys;
for (; i < arguments.length; i++) {
keys = Object.keys(arguments[i]);
for (j = 0; j < keys.length; j++) {
out[keys[j]] = arguments[i][keys[j]];
}
}
return out;
},
register = function (method, target, options, includeTimestamp, logToConsole, appendAtBottom) {
console.skipHtml[method] = function () {
original[method].apply(console, arguments);
};
console[method] = function () {
var finalMsg, msgPart, i, li;
finalMsg = "";
for (i = 0; i < arguments.length; i++) {
msgPart = arguments[i] + ""; // "safe toString()" (works with null & undefined)
if (msgPart === INSTANCE_OBJECT_OBJECT) {
try {
// Prefix with "Object" like in Firefox-, Chrome-, and node.js-output
msgPart = "Object " + JSON.stringify(arguments[i]);
} catch (e) {
}
}
finalMsg += (i > 0 ? " " : "") + msgPart;
}
finalMsg = (includeTimestamp ? "[" + (new Date()).toLocaleTimeString() + "] " : "") + finalMsg;
li = document.createElement("li");
li.setAttribute("data-level", method);
li.innerText = finalMsg;
if (options[method]) {
li.setAttribute("class", options[method]);
}
if (appendAtBottom){
target.appendChild(li);
} else {
target.insertBefore(li, target.firstChild);
}
if (logToConsole) {
console.skipHtml[method].apply(console, arguments);
}
};
};
return {
/**
* Default CSS classes
* @type Object
* @memberof ConsoleLogHTML
* @prop {?string} error=text-danger The default CSS class for error messages
* @prop {?string} warn=text-warning The default CSS class for warning messages
* @prop {?string} info=text-success The default CSS class for info messages
* @prop {?string} debug=text-info The default CSS class for debug messages
* @prop {?string} log=null The default CSS class for log messages
*/
DEFAULTS: {
error: "text-danger",
warn: "text-warning",
info: "text-success",
debug: "text-info",
log: ""
},
/**
* Disconnect our console overrides, reverting to the original state
* @memberof ConsoleLogHTML
*/
disconnect: function () {
console.skipHtml = originalSkipHtml;
for (var i = 0; i < originalKeys.length; i++) {
console[originalKeys[i]] = original[originalKeys[i]];
}
if (false !== originalClear) {
console.clear = originalClear;
}
},
/**
* Overwrite the original console.* methods and start outputting to screen
* @memberof ConsoleLogHTML
* @param {$|jQuery|HTMLUListElement} target The target <ul> element to output to. Can can either be a
* jQuery or vanilla JS HTMLUListElement.
* @param {Object} [options=ConsoleLogHTML.DEFAULTS] CSS class options. See {@link ConsoleLogHTML.DEFAULTS} for
* default values.
* @param {boolean} [includeTimestamp=true] Whether to include the log message timestamp in HTML
* @param {boolean} [logToConsole=true] Whether to continue logging to the console as well as HTML.
* @param {boolean} [appendAtBottom=false] Whether to append the log messages at the end of the ul-list
* @throws {Error} If target is not an <ul> element
*/
connect: function (target, options, includeTimestamp, logToConsole, appendAtBottom) {
if (jQueryIsUp && target instanceof jQueryIsUp) {
target = target[0];
}
if (typeof logToConsole !== TYPE_BOOLEAN) {
logToConsole = true;
}
if (typeof includeTimestamp !== TYPE_BOOLEAN) {
includeTimestamp = true;
}
if (!(target instanceof HTMLUListElement)) {
throw new Error("The target must be a HTML <ul> element");
} else {
options = extend(ConsoleLogHTML.DEFAULTS, options || {});
console.skipHtml = {};
for (var i = 0; i < originalKeys.length; i++) {
register(originalKeys[i], target, options, includeTimestamp, logToConsole, appendAtBottom);
}
if (false !== originalClear) {
console.clear = function () {
target.innerText = "";
originalClear.apply(console);
};
}
}
}
};
})({}, ["log", "debug", "info", "warn", "error"], console, Object, "undefined", "boolean", '[object Object]');
if (typeof module !== "undefined" && typeof module.exports !== "undefined") {
module.exports = ConsoleLogHTML;
}