Follow me: @D_mitar

Most read posts recently



Feb 15th 2010 × Creating a wrapper namespace for the FireBug console.log function for IE and other browsers

Most web application/AJAX development takes place within the confines of either FireFox + Firebug or Webkit browsers and their consoles (firebug is now available on chrome?). However, other browsers (such as IE) lack console functionality and this presents a problem.

When in a hurry / under pressure, I have been known to forget to take out a console reference out of code that sneaks it’s way into the production environment. If not immediately noticeable, tucked away behind a loop / if statement, you’d never know about it… That is, until the error reports start flooding in.

Not wanting to find myself in such position again, I decided to write a little wrapper that can cater for nearly all of firebug’s console methods. The most common ones, such as console.log, console.info, console.clear and console.count are pre-defined but you can use the model and add others into the singleton. Check this fine firebug cheatsheet for more ideas on other methods you may want to port.

this.$C = {
    // console wrapper by D. Christoff @ http://fragged.org/
    _version: 2.4,
    debug: true, // global debug on|off
    quietDismiss: true, // may want to just drop, or alert instead,
    method: "log",
    _hasConsole: function(_method) {
        var _method = _method || "log";
        return typeof(console) == 'object' && typeof(console[_method]) != "undefined";
    },
    _consoleMethod: function() {
        if (!this.debug) return false;

        if (this._hasConsole(this.method)) {
            console[this.method].apply(console, arguments);
        } else if(!this.quietDismiss && arguments.length) {
            var result = "";
            for (var i = 0, l = arguments.length; i < l; i++)
                result += arguments[i] + " ("+typeof arguments[i]+") ";

            alert(result);

        }
    },
    log: function() {
        this.method = "log";
        this._consoleMethod.apply(this, arguments);
    },
    info: function() {
        this.method = "info";
        this._consoleMethod.apply(this, arguments);
    },
    warn: function() {
        this.method = "warn";
        this._consoleMethod.apply(this, arguments);
    },
    clear: function() {
        this.method = "clear";
        this._consoleMethod.apply(this);
    },
    count: function() {
        this.method = "count";
        this._consoleMethod.apply(this, arguments);
    },
    trace: function() {
        this.method = "trace";
        this._consoleMethod.apply(this, arguments);
    },
    assert: function() {
        this.method = "assert";
        this._consoleMethod.apply(this, arguments);
    },
    dir: function() {
        this.method = "dir";
        this._consoleMethod.apply(this, arguments);
    }
}; // end console wrapper.

// example data and object
$C.clear();

var foo = "foo", bar = document.getElementById("divImage");
$C.log(foo, bar);
$C.count("loop");
$C.info("we are inside a loop!");
$C.count("loop");
$C.assert(parseInt("07") === 7)
$C.warn("please use radix 10 when using parseInt");

// enable debugging of a function, eg, finding a hoisting bug...
var consoleTesting = function() {
    $C.info("starting function debugging");
    $C.trace();

    $C.warn("a should be undefined but it is not, actually assigned to the function already:");
    $C.info(a); // undefined?
    function a() {
        alert("hi");
    }

    var a;
    $C.log(a.toString()); // the function
}();

Here's a link to this in action on jsFiddle

The interface is simple, just use the "$C" namespace (name it what you like) instead of "console" will have the preserved functionality / results within FireFox, whereas IE users can either see an alert pop-up dialogue or nothing at all (if $C.quietDismiss = true).

// To disable the alerts in IE, do
$C.quietDimiss = true;
// To disable debug completely:
$C.debug = false;

I hope somebody finds this useful...

update history

*update* thanks to divide by zero for the improvement - in this post.

*update again* this is a fix from the previous update, seems that safari's console cannot accept scoping through apply so I added a try {} catch {} block where it reverts to the old loop

*update again (15/02/10)* modded to support any possible console method with ease

*update again (08/04/10)* changes to the firebug API have resulted in certain console methods being dropped and others changed (for example, .debug no longer sets a breakpoint), the methods that are in the current version are: log, debug, info, warn, error, exception, assert, dir, dirxml, trace, group, groupEnd, groupCollapsed, time, timeEnd, profile, profileEnd, count, clear. More here: http://getfirebug.com/wiki/index.php/Console_API

*update again (17/02/11)* fixed to console.method.apply(console, arguments); as opposed to .apply(this, arguments) which fixes webkit and removes the need for a try block / iteration fallback. added console.dir


Sep 21st 2009 × jsPrintSetup: an AMAZING plugin for firefox that gives extended javascript controls to the printer

This is not a tool you can rely on for customer-facing development, but I found it invaluable nevertheless. jsPrintSetup is a small fireFox add-on that hands you a controlling object in javascript. You get FULL access to any print-related function you could think of: list printers, select default printers, print silently, control spool, headers… There’s just too much to mention. Very useful when coding a CMS that needs to print specific things to specific printers (for example, invoices on printer #1 and labels on printer #2).

Here is an example that fetches a list of printers and remembers the user’s preference for future use:

// only do something if the plugin is live
if ($type(jsPrintSetup)) {
    var printers = jsPrintSetup.getPrintersList().split(","); // get a list of installed printers

    // no print dialogue boxes needed
    jsPrintSetup.setSilentPrint(true);

    // create a dropdown
    var printList = new Element("select", {
        id: "printerList",
        events: {
            change: function() {
                Cookie.write("defaultPrinter", this.get("value"), {
                    path: "/admin/",
                    duration: 365
                });

                // save the new printer selection
                jsPrintSetup.setPrinter(this.get("value"));
            }
        }
    }).injectTop($("printSetup"));

    // get default by preference if any
    var defaultPrinter = Cookie.read("defaultPrinter");

    printers.each(function(el) {
        new Element("option", {
            value: el,
            text: el,
            selected: (defaultPrinter == el) ? "selected" : false
        }).inject(printList);

    });

    // attach an event that prints from an element called goPrint
    $("goPrint").addEvents({
        click: function() {
            jsPrintSetup.print();
        }
    });
}