JavaScript Logging

If you spend much time working with JavaScript, there will eventually come a day when you need to know the value of a variable (or an object’s field) as the execution of the script progresses, or why a script terminates unexpectedly. In simple scripts, you can accomplish this with JavaScript’s alert function, which instructs the browser to create a dialog box with the argument set as the box’s caption. The message can be anything that helps you understand your script’s operation.

Article Continues Below

For example, the statement:

alert(
"Node #" + i + "'s class is:" + nodes[ i ].getClass()
);

might produce something like the following when executed:

An example of using JavaScript's alert() function to display information about an executing JavaScript

When alert() is used only a few times throughout a script’s execution, it is easy for the author to keep track of exactly what is being displayed in the dialog boxes. However, once nested loops and other advanced techniques such as recursion are introduced to the script, using alert() to debug your script can quickly degrade into wasting your time clicking an “OK” button as quickly as possible to dismiss unnecessary dialog boxes while hunting for the one box that you’re interested in.

Tools for the job#section2

Several browsers include tools that can aid in debugging your code, including those from Opera and the Mozilla project. The Mozilla browsers and recent versions of Opera include JavaScript consoles that assist script authors in finding the error that caused a script to terminate unexpectedly:

Firefox's JavaScript console

To its credit, Internet Explorer on Windows can also notify the viewer of JavaScript errors (although its messages tend to be a little cryptic when compared to Mozilla’s and Opera’s consoles).

Firefox’s older brother, Mozilla, also includes a full-blown JavaScript debugger, dubbed Venkman, to assist scripters in finding out exactly what their code is doing. However, the art of setting breakpoints and stepping through your code function-by-function and instruction-by-instruction is more tedious and complicated than many would like it to be. Although there are several excellent tutorials that cover how to use Venkman, becoming familiar with the way a debugger works and how to use one effectively requires a large time commitment.

Mozilla's Venkman utility

The complexity and overhead of using a debugger isn’t unique to Venkman; nearly every IDE (Integrated Development Environment) includes some sort of debugger, but these are often ignored by developers due to the amount of effort that must be expended to actually use the debugger and step through their code.

However there is, in fact, a bigger problem in using the JavaScript consoles and debuggers: they don’t reveal why a script operates as expected in Browser A, but crashes and burns in Browser B, or vice-versa. The debugger/console will only let you know what’s happening in Browser A.

En vogue#section3

Another, simpler debugging method has come into fashion in recent years, although the principle behind it must be as old as the art of programming itself. This method is called logging, and it works by echoing as much information to the screen as is necessary to find out how your code and data structures are behaving. The echoed information can include everything from descriptive statements that are used to let the programmer know what is happening in the script to the value of a variable or the field of an object; it can be any information that will inform the author of what is happening in the code.

In fact, by using JavaScript’s alert function to display snapshots of our script as it executes, we are essentially using a very basic logging method; instead of displaying the information in a terminal window or appending it to a file on the hard drive, we are presenting it directly to the viewer. Yet using alert() proves to be more of a hinderance than a benefit when used often due to the amount of mouse clicks that are needed to dismiss the dialogs. What’s needed is a proper logging mechanism for JavaScript and the browsers that it runs in.

The concept of logging was popularized by Apache’s Log4J package for Java, and its essential ideas have since been ported to other languages, including but not limited to:

This article will introduce fvlogger (available for download here), a library that brings simple logging functionality to JavaScript and the browser.

Logging in JavaScript with fvlogger#section4

Whereas logging packages in the languages listed above provide a complex class/package structure built on top of inheritance and other object-oriented concepts, fvlogger borrows concepts from Log4J and its cousins, but eschews their complexity by providing a simple API and offloading the heavy lifting onto the DOM.

The library defines four basic functions (and provides a few others that can be considered optional), a few flags that can be set to define its behaviour, and several CSS classes that can be used to govern how the log will appear. It requires just one special element to be placed in the document, and including fvlogger in your pages is as easy as adding the following two lines to the head of your documents:

<script type="text/javascript"
src="/fvlogger/logger.js" />
<link rel="stylesheet" type="text/css"
href="/fvlogger/logger.css" />

Essentially, all fvlogger does is append new elements to a specific element in the document. These new elements contain the logging messages that will assist you in debugging your script(s). The four functions used to create the log messages are: debug(msg), info(msg), warn(msg), and error(msg). Each function expects a single string that will be appended to the document.

Logging levels and classes#section5

One of the fundamental ideas behind logging is the ability to set the granularity of what information will be logged: Should only errors be displayed? What about information to indicate which branches and/or loops are being executed?

While it is possible to get away with only using one function to log messages to the browser, by using all four you will be able to filter your log messages based on their importance; debug messages are the least critical and can often be dismissed, while error messages are the most important and should always be taken into consideration.

By default, all messages will be appended to the element whose id is “fvlogger” (although this can easily be changed). The log messages are wrapped in <p> elements—which, like the id, can be changed—and have a single class applied to them that corresponds to the logging function that was used to create it. Debug messages will have the debug class applied to them, error messages will have the error class applied to them, et cetera. These classes allow you to style your log messages any way you like using CSS; the project includes a default stylesheet and supporting images to get you started but you are, of course, free to change its appearance to your heart’s content.

The convenience functions mentioned above allow you to quickly filter which log messages are displayed in the browser:

  • showAll() shows all log messages,
  • showDebug() shows all debug messages, and hides all others,
  • showInfo() shows all info messages, and hides all others,
  • showWarn() shows all warn messages, and hides all others,
  • showError() shows all error messages, and hides all others,
  • eraseLog() will erase all messages from the log.

(The filter methods work by simply setting the display style of a log message to either be visible or invisible based on the message’s class.)

Getting started#section6

That being said, let’s take a look at the steps required to set up fvlogger. The following snippet of XHTML defines the elements that will be used to interact with fvlogger, although we could get a way with just a simple <div> if we really wanted to. You will notice that none of the log messages in the <div> below are shown; this is because the messages are created dynamically by fvlogger and apppended to the document after it was loaded into the browser.

<div id="fvlogger">
  <dl>
    <dt>fvlogger</dt>
    <dd class="all">
      <a href="#fvlogger" onclick="showAll();" 
        title="show all">all</a>
    </dd>
    <dd class="debug">
      <a href="#fvlogger" onclick="showDebug();" 
        title="show debug">debug</a>
    </dd>
    <dd class="info">
      <a href="#fvlogger" onclick="showInfo();" 
        title="show info">info</a>
    </dd>
    <dd class="warn">
      <a href="#fvlogger" onclick="showWarn();" 
        title="show warnings">warn</a>
    </dd>
    <dd class="error">
      <a href="#fvlogger" onclick="showError();" 
        title="show errors">error</a>
    </dd>
    <dd class="fatal">
      <a href="#fvlogger" onclick="showFatal();" 
        title="show fatals">fatal</a>
    </dd>
    <dd>
      <a href="#fvlogger" onclick="eraseLog(true);" 
        title="erase">erase</a>
      </dd>
  </dl>
</div>

Nothing too advanced, really. Although the markup required to get up and running could be as minimal as…

<div id="fvlogger" />

…if you don’t require all the bells and whistles. As for the log messages themselves, the following code snippet illustrates how to create log messages and outlines which level of severity should be used for your log messages.

debug('Scatter debug messages throughout your
  code to provide a high-level overview of
  what your code is doing, such as which
  function is currently in scope and the
  values of loop counters.');

info('Information messages are the meat and
  potatoes of logging messages; sprinkle them
  around to reveal more detailed information
  about your script's execution, such as the
  values of variables and function/method
  return values.');

warn('Warning messages are used to indicate
  potentially hazardous situations, such as
  missing function arguments...');

error('While error messages are used to
  indicate that something bad is about to
  happen; note that these kinds of errors
  are considered to be run-time errors,
  which are a different type of beast from
  the parse errors mentioned below.');

…and the following is how they appear after having the default fvlogger styles applied:

Note: For those developers who are testing their scripts in IE or one of the many Mozilla-based browsers, JavaScript parse errors will also be appended to the log as fatal errors. This feat is accomplished by simply overriding the <body>’s onerror handler to add another message to the log.

Now you’re probably asking what that other gunk in the log is. Those are the log messages generated by code included later in the article. Which brings me to the second half of the article. Now that you’re familiar with the theory and practice behind developing with fvlogger, I’ll walk through a real-life example—one that I came across in the development of the package—of the way logging can aid in debugging your scripts.

Developing with fvlogger#section7

Included in the styles of this page is the following rule:

.labrat { font-weight: bold; color: red; }

So, theoretically, any elements in the document whose class is “labrat”—whether they be a part of the document when the page is loaded into the browser or appended at some point thereafter—should appear in bold-faced red type, including the following two examples.

This is the first example.

This is the second example.

Easy-peasy, right? Almost, but not quite.

The problem#section8

The examples shown above are included in the document (ie: they were created when authoring the rest of this page), so it should come as no surprise that they appear as they should in every browser that supports CSS. However, with the cross-browser support of the DOM, dynamically creating elements and appending them to the document has become commonplace—even required—by many websites and applications, this article being one of them. Let’s make sure that we can apply classes to these dynamic elements as well.

The code to accomplish our task should look something like the following:

var p = document.createElement("p");
p.appendChild(
  document.createTextNode(
    "This paragraph (#3) is created dynamically and appears
    with the proper bold-faced red type in virtually all
    modern browsers except for Internet Explorer, where the
    paragraph is created and the text is appended, but the
    styles are not properly applied. Why?")
);
p.setAttribute("class", "labrat");
document.appendChild(p);

The above snippet of code works in all modern browser families—WebKit, Gecko, and Opera—except for IE. With Internet Explorer, the following paragraph will have the same font as all regular paragraphs, even though it has the “labrat” class applied (go ahead and load this page in IE and another browser and compare the differences).

After a little investigating, the cause is IE’s implementation of the setAttribute and createElement methods. Take a look at the following code (which contains the logging statements shown in bold) which is used to create example paragraph #4…

// create and append the paragraph to the document
var p2 = document.createElement("p");
p2.appendChild(
  document.createTextNode(
    "This is example paragraph #4.")
);
p2.setAttribute("class", "labrat");
var bottle = document.getElementById("bottle");
bottle.appendChild(p2);

// use fvlogger to log all attributes to the document
var i = 0; var attrs = p2.attributes;
for (i = 0; i < attrs.length; i++) {
  debug("attribute #" + i + ": " +
    attrs[i].name + "=" + attrs[i].value);
}

// display a summary of attrs length
if (i == 0) {
  error("new element has no attributes");
} else {
  info("p has " + i + " attribute(s)");
}

…and the log message that it generates, shown previously in the page. In Opera, Mozilla, and WebKit-based browsers, there are only two logging statements produced by this snippet of code: one debug statement that shows the class of the element that we created, and the other indicating the number of attributes belonging to the element. Because we are only assigning one attribute to the element (its class), the output is exactly what we would expect it to be: the paragraph has one attribute named—not surprisingly—“labrat.”

However, Internet Explorer is “special” in the way that it creates elements. Instead of having zero attributes (as one would expect) immediately after creation, new elements inherit all attributes and their default values as defined in Internet Explorer’s default DTD. So instead of our new element having a single attribute after setting its class, it actually has 84. Zoinks!

But what’s equally as odd is that when attempting to set the class of a new element through its setAttribute() method, IE will actually create another attribute node instead of replacing the value of the existing class attribute. Thus, we end up with two class attributes instead of one in IE (attributes #3 and #83 in the log statements shown above).

The solution#section9

Luckily, there is, a relatively simple fix for IE’s problem: instead of simply setting the value of an attribute based on its name, we can loop through all existing attributes until we find the one that we’re looking for and then set its value based on its numeric index in the node’s attributes array. The following snippet of JavaScript will get the job done:

var className = 'labrat';
var p3 = document.createElement('p');
p3.appendChild(
  document.createTextNode(
    "And guess what. It works!" 
  )
);

// if the node's class already exists
// then replace its value
if (p3.getAttributeNode("class")) {
  for (var i = 0; i < p3.attributes.length; i++) {
    var attrName = p3.attributes[i].name.toUpperCase();
    if (attrName == 'CLASS') {
      p3.attributes[i].value = className;
    }
  }
// otherwise create a new attribute
} else {
  p3.setAttribute("class", className);
}
    

The moral of the story#section10

In this article we saw how logging unveiled one of Internet Explorer’s many quirks. But more importantly, we saw how logging provides an easy way to create transparent code—you, the author, can stay on top of your data structures as they pass through each line of your code and know exactly what is happening inside the black box of a web browser’s JavaScript engine (or, similarly, your Dashboard widget). This transparency can prove invaluable since your code is likely to run in three or more different browsers that, while similar, are by no means identical.

About the Author

David F. Miller

David F. Miller has been dabbling with code, nodes, attributes, and elements since graduating from the University of Calgary in 2002. His personal site--three years out of date--should one day catch up to the work he's been doing in the meantime.

43 Reader Comments

  1. Can anyone tell me if the above method is better than simply using:

    p3.setAttribute(“class”,”labrat”, 0);
    p3.setAttribute(“className”,”labrat”, 0);

    Regards,

    Chris

  2. In my experience, yes — setting the “className” property of a DOM node will apply the class to the node in question in all modern browsers I’ve tried.

    I generally use that approach in my scripts; “class” itself is theoretically a reserved word for “JavaScript 2.0”, too.

  3. In my experience, setAttribute in IE will not compile the attribute’s actual action into the IE document model. For instance if you’ll try something like this:
    myElement.setAttribute(“onclick”, “doSomething()”, 0);

    IE won’t actually register this event to the object. To my surprise, Firefox will actually do this. So what I’m trying to say, that setAttribute in IE won’t do you any good with attributes like ‘class’, ‘style’, ‘maxlength’, ‘value’, etc..
    In my experience, you’ll have to use the “proper” procedure:
    myElement.className = “yourClassName”;

    Using setAttribute and getAttribute for your own custom attributes works perfectly on the latest browsers..

  4. Nice work! I’ll use it for sure. But there’s one improvement I’d make.
    I would add “return false;” to every onclick event in the menu to avoid annoying page leaping.
    So I’d rewrite:

    all

    as:

    all
  5. As someone just starting to dabble in the world of slightly more advanced Javascripting, I find the prospect of debugging scripts in non-FF browsers to be a very very scary one. So thanks for the tips.

    However, related to that awkward setAttribute loop, is object.className now a deprecated property?

  6. for (i = 0; i < attrs.length; i++) { debug(“attribute #” + i + “: ” +
    attrs[i].name + “=” + attrs[i].value);

    }

  7. Agreed, this is very clever. More importantly (now that it’s here), it’s available to those doing coding that are experiencing more cross-browser issues as the Ajax approach is becoming more common. This would have been a lifesaver on a project I completed recently, and my company hesitant about Ajax due to concerns about difficulties in maintenance and debugging.

    Thanks!

  8. Looping round the attributes after already calling getAttributeNode seems a bit wasteful, this should (and does) work:

    var attributeNode = p3.getAttributeNode(“class”);
    if (attributeNode) {
      attributeNode.value = className;
    } else {
      p3.setAttribute(“class”, className);
    }

  9. (apologies for this double-comment; ‘comment preview’ needs a few wrinkles ironing out.)

    This comment applies to the fvlogger code, as mentioned in the ‘Solution’ section of the article, and which appears in the fvlogger function @FVL_log@

    var attributeNode = p3.getAttributeNode(“class”?);
    if (attributeNode) {
    attributeNode.value = className;
    } else {
    p3.setAttribute(“class”?, className);
    }

    Similarly, for @getNodeClass@ you could do:
    var attributeNode = p3.getAttributeNode(“class”?);
    return attributeNode && attributeNode.value;

    The implementation’s good though. I’d fallen into the habbit of using .className, which seems to work, but isn’t part of the DOM spec. The approach in the article is more pure.

  10. I’m a bit confused.
    You cure the class element on IE, but when I looked at the logging, I still see the 84 attributes. I’m still learning javascript and would have trouble figuring out what is worth worrying about in those 84 attributes. Are they a problem? Is the logging example above the fix using the fix?

  11. I’m glad the article is being well-received; I’ve been using the code in several projects myself and have found it to be a pretty invaluable tool. Keep the thoughts/comments/improvements/suggestions/etc. coming; the more topics such as this one are discussed the better we will all be for it.

    As for the code itself… Yeah, there are a few different ways to deal with browsers and how they handle attributes and their values. Looping through the list of attributes and doing an exhaustive name comparison is by no means the most efficient (or elegant) method of finding the class name, but it does get the job done. Like most topics related to scripting browsers, it’s a matter of finding a balance between what works in every browser, what *should* work in every browser, and maintaining your sanity while cobbling together whatever hack you can come up with.

  12. Ted,

    The values of all the node’s attributes are being echoed to the debug log merely to illustrate the difference between how Internet Explorer and every other browser handles node attributes. Sorry for the confusion.

  13. Safari also has a javascript debugger. You need to enable the Debug menu in safari, which can be done by typing the following into terminal (make sure safari is closed):

    % defaults write com.apple.Safari IncludeDebugMenu 1

    Then relaunch safari, and from the debug menu you can open a js console.

  14. I myself tend to create an extra DIV on the page, style it with position:absolute; and fill its innerHTML with various debugging values. It’s a step up from the alert() in that it does not halt the script (allowing time-bugs to expose themselves) and does not require lots of clicks in case your bug is inside a loop.

    The downside is of course the numerous bugbox.innerHTML = ‘such and such’; spread across the script, which need cleaning up after bugs have been zapped.

    It’s always served me well, but maybe I’ll try ouy fvlogger. See if the glove fits.

    bq. Safari also has a javascript debugger. You need to enable the Debug menu in safari

    I think that should be a default, instead of a carefully hidden option. But then again, the JS engine of Safari does not behave strangely compared to the Gecko engine, at least not for my scripts. A Bbg fixed in Gecko equals a bug fixed in Safari.

  15. Yes, Safari and Firefox both include excellent JavaScript debuggers, but they only provide debugging information for that particular browser. To find out what your script is doing in another browser (typically IE), then the information gleaned from that debugger may or may not be totally useless.

  16. The article instructs us to use the following self-closing script tag to load the JavaScript source code:

    However, in my experience, Internet Explorer does not seem to "like" self-closing script tags and fails to load the script. Can anyone else confirm this or provide any additional information on the topic?

    On a side note, if you look at the actual source code of the article, you'll notice that they don't follow their own advice and instead use:

    Perhaps the article example should be corrected to use a closing script tag.

  17. first off, this makes me so happy. Stupidly simple and brilliant. Secondly, I hope someone will beat me to it (as I am a Javascript _hack_, but I will take a stab this weekend at implementing this as a popup window.

  18. At about line 43 of the index.html example, the line needs to be changed to:

    info

    The line needs the onclick to show the Info blocks.

    Thanks for a great little tool.

  19. IE has a JavaScript debugger too. Visual Interdev & VS.NET can be used for interactive JavaScript debugging in IE at about the same level of functionality as Venkman. There are a few options you have to enable in IE to turn on script debugging.

    Logging is powerful for tracking down problems you *didn’t* expect to happen, assuming logging is occuring in the right places and there’s a way to get at the log output. A nice feature for fvlogger would be “crash report” submission UI so users could report failures back to the site maintainer.

    When you know a problem exists interactive debuggers are often more efficient than trial-and-error logging, and are worth the effort spent learning thier quirks. Plus, you get to skip the frustrating “trial-and-error” step.

  20. This is very nice.

    A couple of features I would add:

    1) Date/Timestamps prefixing each log, – auto generated.

    2) A global switch to turn logging on and off.

    All up, – very sweet! Nice article.

    – James

  21. This logging script looks very nice and I’m certainly going to give it a try. If it’s of any use to anyone, there is another logging mechanism I have been using for several years. This is IE only, and only of use for debugging scripts running on your local box. Despite these limitations, if that’s the setup you are debugging, it is quite powerful. This is an activex dll, originally made available by Microsoft in the IIS 4 resource kit, called IISSamples.Tracer. It is a very light c++ wrapper round the printDebugString windows api call. All messages logged via this utility can be viewed in the (free) debugviewer utility from sysinternals. The main advantage of this mechanism is that the logging is very fast, particularly useful when debugging mousemovements etc where the overhead of javascript logging methods may interfere with the script you’re trying to debug. It also prints accurate timings with the messages. I don’t beleive this is available on the web anymore, and I have no means of posting it but if you want a copy, email me and I’ll send it to you.

  22. James,

    Thanks for your comments; you can turn logging on/off by setting the value of FVL_LOG_ON to false in logger.js. As for the timestamping of logging statements, I’ll definitely consider it for a future version, although it’s relatively simple to implement if you’re familiar with JavaScript. If you need a hand, let me know. Cheers!

    Dave

  23. Great article.

    I think that you could also use this technique to write out javascript errors to a logfile on the server. This would be a handy way to catch user-generated js errors in production. Instead of writing the errors to a document object, write them to a variable, and then pass that variable using XMLHttpRequest to a server-side script which then captures the message to a file. Only problem I can think of is that this script is then exposed to the public, and someone mischievous could write tons of messages to your server. But perhaps this would be something you would deploy only on a case-by-case basis when you want to track down elusive, idiosyncratic bugs.

  24. I enjoyed looking at your take on the javascript logger. If you are looking for something that acts more like Log4J, I wrote a quick logging class for some of my own projects called log4js – “http://log4js.sf.net”:http://log4js.sf.net . It is a little more robust in that it allows for multiple loggers per page (each is an object), and multiple targets, such as alerts, a popup dialog, or the safari javascript console…

    Then again, it is written by a java programmer returning to javascript after a long hiatus.

  25. Nice stuff. I have already started using it and find it quite useful.

    ALA, Keep such article coming. ALA has saved me so much time with such high class material.

    Thanks for the Good stuff,
    Venkat.

  26. I very much enjoyed this article, but I found the statement “__The concept of logging was popularized by Apache’s Log4J package for Java__” curious. I have heard of log4j but I was not aware that it has popularized the field of logging – is that to suggest that prior to log4j, logging was uncommonly used? Perhaps it depends what field you are in, but in UNIX we’ve enjoyed the syslog daemon (syslogd) for quite some time, and logging is standard practise in most applications.

  27. Noticed a couple bumps:

    1. Putting very simple function names like “show” and “hide” in the top-level namespace is bound to cause problems. I’m working on a web app that already has these functions defined, and adding the logger will override them. I had to change all the fvlogger functions to have a “fvl_” prefix to them.

    2. The logger won’t catch errors that occur as the page is parsed — for example, if you have a javascript in the BODY that just runs immediately (before the page finishes loading), fvlogger won’t catch it.

    What’s worse, if the offending code is placed AFTER the logger.js include, but BEFORE the fvlogger DIV, it becomes invisible, since the window.onerror is redirected: No error message shows up in the javascript console. This seems like a big flaw to me.

  28. I know Venkman has a cool Profile feature which I’ve used manually and which allows you to log data about which javascipt functions are being called and the min/max/avg process times per function. Is there any way to automate this in Venkman ?

    Is anyone aware of another tool that would do this ?

    Thx !

  29. The Dashboard widget API already has a great console logger built in. In fact, all alert()s go straight to the console. This works well: if you forget to remove your logging code before release users won’t be pestered by pop-up windows or other unsightly logging messages.

  30. We are stuck with a Javascript call creating a div and a class name. In FF it works great, but in IE it is not passing any of the class elements and as a result the effect we want, rows and columns, are lost and just one column is left.

    here is the code we are using:

    // This is the div that contains each image and it’s browse box.
    var newElement = document.createElement(‘div’);
    newElement.setAttribute(‘id’, ‘previewDiv’);
    newElement.setAttribute(‘class’, ‘uploadBox’);

    // This is the image!
    var imgDiv = document.createElement(‘div’);
    imgDiv.setAttribute(‘id’, ‘preview-img’);
    imgDiv.setAttribute(‘class’, ‘previewImgDiv’);

    I have gone through some articles here and tried some other ways of doing this and IE just won’t play nice. Any direction would be appreciated.

    thanks.

  31. I had been itting the problem of how to set the class attribute in Javascript and having IE render it. I found this discussion, which gave me a part of the solution.

    I had been trying to use
    el.classname = ‘someclass’;
    (el = document.getElementByID(‘divname’) was assumed here)
    But that created an attribute of classname – not class – so CSS rendering was not occurring. This discussion indicated that I could use the
    el.setAttribute(‘someclass’,’divname’);

    I would then appendChild to the divname and – no CSS rendering.
    But the el.innerHTML = “

    somehtml

    ” always worked.

    So I turned it on itself – el.innerHTML = el.innerHTML
    and it rendered.

    I have been getting back into Javascript to use some Ajax techniques so I feel like I am learning this again – and these problems could be my own lack of understanding.
    It was helpful to have this discussion available – thanks.

  32. http://jstracer.sourceforge.net/

    jsTracer performs similar logging functionality but also allows you to denote or highlight logged messages. It also provides a stack viewer and won’t cause slow script warnings on complex JavaScript code.

  33. http://www.timdown.co.uk/log4javascript

    log4javascript offers similar ease of logging to fvlogger but with far more flexibility. Logging may be done to a searchable, filterable pop-up/in-page console window and/or back to the server via Ajax. It is closely modelled on log4j and has been rigorously tested on all major browsers.

    Disclaimer: I am the author of log4javascript.

  34. in firefox 2.0, when I include fvlogger, it overrides my console errors, and doesn’t display them in the fvlogger div either, so I can’t see any javascript errors caught by the browser. To see them I have to comment out the inclusion of the fvlogger script, which breaks all the manual ‘debug’ and ‘info’ entries I’ve made.. darnit!

  35. in firefox 2.0, when I include fvlogger, it overrides my parse errors, but doesn’t display them in the fvlogger div either, so I can’t see any javascript errors caught by the browser anywhere. To see them I have to comment out the inclusion of the fvlogger script, which breaks all the manual ‘debug’ and ‘info’ entries I’ve made.. darnit!

  36. Hey David, thanks for fvlogger. I was using it to debug some Flash/Javascript integration, then, just for the hell of it, hooked up our Flash tracing to a separate window with fvlogger in it using the Flash ExternalInterface calls. Brilliant.

    We’ve had Flash debuggers inside Flash before… but at runtime they can’t really handle the volume of debug info that can come out. Hell, even the Flash IDE has the poorest output log ever.

    fvlogger was easy to get working.

    Thanks.

  37. Keep the great work going. The tips are really helpful, as are some of the discussions. Learnt a lot. Thank you.

    “tigi bed head”:http://www.salon-collective.co.uk/tigi_bed_head.php
    “tigi bed head dumb blonde”:http://www.salon-collective.co.uk/tigi_bed_head.php?query=dumb+blonde
    “tigi bed head shampoo”:http://www.salon-collective.co.uk/tigi_bed_head.php?query=shampoo
    “tigi bed head hair products”:http://www.salon-collective.co.uk/tigi_bed_head.php
    “tigi bed head control freak”:http://www.salon-collective.co.uk/tigi_bed_head.php?query=control+freak
    “tigi self absorbed”:http://www.salon-collective.co.uk/tigi_bed_head.php?query=self+absorbed

Got something to say?

We have turned off comments, but you can see what folks had to say before we did so.

More from ALA

I am a creative.

A List Apart founder and web design OG Zeldman ponders the moments of inspiration, the hours of plodding, and the ultimate mystery at the heart of a creative career.
Career