/* * CPLog.j * Foundation * * Created by Thomas Robinson. * Copyright 2008, 280 North, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ window.CPLogDisable = false; var CPLogDefaultTitle = "Cappuccino"; var CPLogLevels = ["fatal", "error", "warn", "info", "debug", "trace"]; var CPLogDefaultLevel = CPLogLevels[0]; var CPLogLevelsInverted = {}; for (var i = 0; i < CPLogLevels.length; i++) CPLogLevelsInverted[CPLogLevels[i]] = i; var _CPLogRegistrations = {}; // helpers: var _CPFormatLogMessage = function(aString, aLevel, aTitle) { var now = new Date(), zero = function(number, zeros) { var digits = number.toString(); return zeros.substring(0, zeros.length - digits.length) + digits; } var level = aLevel ? " ["+aLevel+"]" : ""; var message = now.getFullYear() + "-" + zero(now.getMonth()+1, "00") + "-" + zero(now.getDate(), "00") + " " + zero(now.getHours(), "00") + ":" + zero(now.getMinutes(), "00") + ":" + zero(now.getSeconds(), "00") + "." + zero(now.getMilliseconds(), "000")+" " + aTitle + level + ": " + aString; return message; } // Register Functions: // Register a logger for all levels, or up to an optional max level function CPLogRegister(aProvider, aMaxLevel) { CPLogRegisterRange(aProvider, CPLogLevels[0], aMaxLevel || CPLogLevels[CPLogLevels.length-1]); } // Register a logger for a range of levels function CPLogRegisterRange(aProvider, aMinLevel, aMaxLevel) { var min = CPLogLevelsInverted[aMinLevel]; var max = CPLogLevelsInverted[aMaxLevel]; if (min != undefined && max != undefined) for (var i = 0; i <= max; i++) CPLogRegisterSingle(aProvider, CPLogLevels[i]); } // Regsiter a logger for function CPLogRegisterSingle(aProvider, aLevel) { if (_CPLogRegistrations[aLevel] == undefined) _CPLogRegistrations[aLevel] = [aProvider]; else _CPLogRegistrations[aLevel].push(aProvider); } // Main CPLog, which dispatches to individual loggers function CPLog(aString, aLevel, aTitle) { if (aTitle == undefined) aTitle = CPLogDefaultTitle; if (aLevel == undefined) aLevel = CPLogDefaultLevel; if (_CPLogRegistrations[aLevel]) for (var i = 0; i < _CPLogRegistrations[aLevel].length; i++) _CPLogRegistrations[aLevel][i](aString, aLevel, aTitle); } // Shortcuts for common log levels (CPLog.fatal(), CPLog.error(), etc) for (var i = 0; i < CPLogLevels.length; i++) CPLog[CPLogLevels[i]] = (function(level) { return function(message, title) { CPLog(message, level, title); }; })(CPLogLevels[i]); // Loggers: ANSI_ESC = String.fromCharCode(0x1B); ANSI_CSI = ANSI_ESC + '['; ANSI_TEXT_PROP = 'm'; ANSI_RESET = '0'; ANSI_BOLD = '1'; ANSI_FAINT = '2'; // unsupported? ANSI_NORMAL = '22'; ANSI_ITALIC = '3'; // unsupported? ANSI_UNDER = '4'; ANSI_UNDER_DBL = '21'; // unsupported? ANSI_UNDER_OFF = '24'; ANSI_BLINK = '5'; ANSI_BLINK_FAST = '6'; // unsupported? ANSI_BLINK_OFF = '25'; ANSI_REVERSE = '7'; ANSI_POSITIVE = '27'; ANSI_CONCEAL = '8'; ANSI_REVEAL = '28'; ANSI_FG = '3'; ANSI_BG = '4'; ANSI_FG_INTENSE = '9'; ANSI_BG_INTENSE = '10'; ANSI_BLACK = '0'; ANSI_RED = '1'; ANSI_GREEN = '2'; ANSI_YELLOW = '3'; ANSI_BLUE = '4'; ANSI_MAGENTA = '5'; ANSI_CYAN = '6'; ANSI_WHITE = '7'; var colorCodeMap = { "black" : ANSI_BLACK, "red" : ANSI_RED, "green" : ANSI_GREEN, "yellow" : ANSI_YELLOW, "blue" : ANSI_BLUE, "magenta" : ANSI_MAGENTA, "cyan" : ANSI_CYAN, "white" : ANSI_WHITE } ANSIControlCode = function(code, parameters) { if (parameters == undefined) parameters = ""; else if (typeof(parameters) == 'object' && (parameters instanceof Array)) parameters = parameters.join(';'); return ANSI_CSI + String(parameters) + String(code); } // simple text helpers: ANSITextApplyProperties = function(string, properties) { return ANSIControlCode(ANSI_TEXT_PROP, properties) + String(string) + ANSIControlCode(ANSI_TEXT_PROP); } ANSITextColorize = function(string, color) { if (colorCodeMap[color] == undefined) return string; return ANSITextApplyProperties(string, ANSI_FG + colorCodeMap[color]); } // CPLogPrint uses the print() functions present in many non-browser command line JavaScript interpreters var levelColorMap = { "fatal": "red", "error": "red", "warn" : "yellow", "info" : "green", "debug": "cyan", "trace": "blue" } function CPLogPrint(aString, aLevel, aTitle) { if (typeof print != "undefined") { if (aLevel == "fatal" || aLevel == "error" || aLevel == "warn") var message = ANSITextColorize(_CPFormatLogMessage(aString, aLevel, aTitle), levelColorMap[aLevel]); else var message = _CPFormatLogMessage(aString, ANSITextColorize(aLevel, levelColorMap[aLevel]), aTitle); print(message); } } // CPLogAlert uses basic browser alert() functions function CPLogAlert(aString, aLevel, aTitle) { if (typeof alert != "undefined" && !window.CPLogDisable) { var message = _CPFormatLogMessage(aString, aLevel, aTitle); window.CPLogDisable = !confirm(message + "\n\n(Click cancel to stop log alerts)"); } } // CPLogConsole uses the built in "console" object function CPLogConsole(aString, aLevel, aTitle) { if (typeof console != "undefined") { var message = _CPFormatLogMessage(aString, aLevel, aTitle); var logger = { "fatal": "error", "error": "error", "warn": "warn", "info": "info", "debug": "debug", "trace": "debug" }[aLevel]; if (logger && console[logger]) console[logger](message); else if (console.log) console.log(message); } } // CPLogPopup uses a slick popup window in the browser: var CPLogWindow = null; CPLogPopup = function(aString, aLevel, aTitle) { try { if (window.CPLogDisable || window.open == undefined) return; if (!CPLogWindow || !CPLogWindow.document) { CPLogWindow = window.open("", "_blank", "width=600,height=400,status=no,resizable=yes,scrollbars=yes"); if (!CPLogWindow) { window.CPLogDisable = !confirm(aString + "\n\n(Disable pop-up blocking for CPLog window; Click cancel to stop log alerts)"); return; } _CPLogInitPopup(CPLogWindow); } var logDiv = CPLogWindow.document.createElement("div"); logDiv.setAttribute("class", aLevel || "fatal"); var message = _CPFormatLogMessage(aString, null, aTitle); logDiv.appendChild(CPLogWindow.document.createTextNode(message)); CPLogWindow.log.appendChild(logDiv); if (CPLogWindow.focusEnabled.checked) CPLogWindow.focus(); if (CPLogWindow.blockEnabled.checked) CPLogWindow.blockEnabled.checked = CPLogWindow.confirm(message+"\nContinue blocking?"); if (CPLogWindow.scrollEnabled.checked) CPLogWindow.scrollToBottom(); } catch(e) { // TODO: some error handling/reporting } } var _CPLogInitPopup = function(logWindow) { var doc = logWindow.document; // HACK so that head is available below: doc.writeln("