Tag: Javascript

  • Limiting the contents of a string via RegEx

    Often, you will need to prevent users from entering data that doesn’t conform to a specific pattern. For example, you may want to allow users to enter only numbers or only valid email addresses. To this end, I’ve written a little utility function that returns the “standardised” version of a string, according to the regex you supply.

    [sourcecode language=”javascript”]String.implement({
    limitContent: function(allowedRegex) {
    return $splat(this.match(allowedRegex)).join(”);
    }
    });[/sourcecode]

    Basically, the function takes the result of evaluating the regular expression on the string, converts it into an array if it isn’t one, and then joins the array’s elements together with an empty string.

    Examples:

    [sourcecode language=”javascript”]console.log(“12345”.limitContent(/.{4}/)); // Only allow four characters
    console.log(“joe@mail.com”.limitContent(/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}/)); // Only allow email addresses
    [/sourcecode]

  • MooTools object messaging

    Events

    In JavaScript, we often tend to use events all over the place. In MooTools, the custom ‘domready’ event is particularly prevalent. However, events suffer from a few drawbacks:

    You can’t attach events to non-existent objects.

    Pretty self-explanatory, really. What this means in practice, though, is that you can’t easily let object A know when object B exists.

    If an object starts to listen for an event after it’s already fired, it’ll never hear it.

    Because content on the web isn’t always delivered in perfect order (especially when you’re loading scripts synchronously), it’s possible for an object to try to listen for an event after it’s already been fired. Obviously, this means that your listener object will never run the code that’s dependent on that event, which could be Bad Thing™.

    It’s not particularly easy to know which object is listening for which events.

    There are ways around this, but you can’t just dir() the listeners in Firebug.

    A messaging system

    For all of these reasons (and probably a few more that I’ve forgotten about), a messaging system can be an invaluable addition to your arsenal when writing JavaScript. How does a messaging system work? Well, interested objects ‘register’ themselves as listeners for particular message ‘handles’, and other objects can send messages using those ‘handles’. Below is a very simple MooTools messaging system that I knocked up, which has a few cool features, including:

    • When you register() a listener, you can have its callback immediately fire if that message has ever been sent before.
    • You can very easily see which callbacks are associated with which messages by simply dir()-ing the ‘listeners’ member.
    • You can unregister() a listener at any time (provided you’ve got a reference to the function and the handle).
    • Handles can be any valid JavaScript type — Strings, Numbers, even Objects.

    Feel free to use and extend this system — as I mentioned, this is a very simple system. If you do extend it, let me know in the comments!

    Let me know what you think about this system in the comments.

    [sourcecode language=”javascript”]
    barryvan.base.Messaging = new Class({
    listeners: $H(),
    sentMessages: [],

    initialize: function() {

    },

    /**
    * Register a listener for a particular handle.
    * handle [String]: The message ‘handle’ to listen for.
    * callback [Function]: The function to be called when the handle is sent a message. The contents of the messages will be included in the function call.
    * dontCheck [Boolean]: If falsey and the handle has had a message sent to it, immediately call the callback function (without contents), and continue to add the listener as normal.
    */
    register: function(handle, callback, dontCheck) {
    if ($type(callback) !== ‘function’) return;

    if (!dontCheck && this.sentMessages[handle]) {
    callback();
    }

    if (!this.listeners.has(handle)) this.listeners[handle] = [];
    this.listeners[handle].push(callback);
    },

    /**
    * Unregister a listener for a particular handle.
    * handle [String]: The message ‘handle’ to cease listening for.
    * callback [Function]: The function which was earlier assigned as the callback for the messages.
    */
    unregister: function(handle, callback) {
    if (this.listeners.has(handle)) {
    this.listeners[handle].erase(callback);
    }
    },

    /**
    * Send a message to the given handle with the given contents — send the contents to all the registered listeners for that handle.
    * handle [String]: The message ‘handle’ to transmit to.
    * contents [Mixed]: The contents to be sent to the listeners.
    */
    send: function(handle, contents) {
    this.sentMessages.include(handle);
    if (this.listeners.has(handle)) {
    this.listeners[handle].each(function(callback) {
    callback(contents);
    });
    }
    }
    });
    [/sourcecode]

  • Quicksort an array of objects

    Often, you will need to sort an array of objects in Javascript. The inbuilt sort() function can’t do this, but here is a Quicksort implementation for doing just this.

    Parameters

    array The array to be sorted. (See below for an implementation on the Array Native itself, which makes this variable unnecessary).

    key The key to sort by. Make sure every object in your array has this key.

    Examples

    [sourcecode language=’javascript’]
    var objs = [
    {fruit:”cherry”},
    {fruit:”apple”},
    {fruit:”banana”}
    ];

    console.log(objs.sortObjects(‘fruit’));
    // Logs [{fruit:”apple”},{fruit:”banana”},{fruit:”cherry”}] to the console
    [/sourcecode]

    The code

    [sourcecode language=’javascript’]
    sortObjects: function(array, key) {
    for (var i = 0; i < array.length; i++) { var currVal = array[i][key]; var currElem = array[i]; var j = i - 1; while ((j >= 0) && (array[j][key] > currVal)) {
    array[j + 1] = array[j];
    j–;
    }
    array[j + 1] = currElem;
    }
    }
    [/sourcecode]

    Implemented on the Array native:

    [sourcecode language=’javascript’]
    Array.implement({
    sortObjects: function(key) {
    for (var i = 0; i < this.length; i++) { var currVal = this[i][key]; var currElem = this[i]; var j = i - 1; while ((j >= 0) && (this[j][key] > currVal)) {
    this[j + 1] = this[j];
    j–;
    }
    this[j + 1] = currElem;
    }
    }
    });
    [/sourcecode]

  • Javascript string ellipsising

    Putting ellipses into strings that are too long has been around for a very long time. Unfortunately, Javascript doesn’t offer a native method of doing this, so below is a little function that’ll do it for you.

    This function returns a copy of the string it’s called on, ellipsised, and takes three parameters:

    toLength (required) The number of characters to truncate the string to (or 0 to disable ellipsising)

    where (optional, default ‘end’) A string representing where the ellipsis should be placed — ‘front’, ‘middle’, or ‘end’

    ellipsis (option, default ‘\u2026’) A string to be used as the ellipsis.

    Examples

    [sourcecode language=’javascript’]
    // Our clichéd string
    var s = ‘Jackdaws love my great big sphinx of quartz’;

    alert(s.ellipsise(10));
    // Alerts “Jackdaws l…”

    alert(s.ellipsise(10, ‘front’));
    // Alerts “… of quartz”

    alert(s.ellipsise(10, ‘middle’, ‘pony’));
    // Alerts “Jackdponyuartz”[/sourcecode]

    The code

    [sourcecode language=’javascript’]String.implement({
    ellipsise: function(toLength, where, ellipsis) { // Where is one of [‘front’,’middle’,’end’] — default is ‘end’
    if (toLength < 1) return this; ellipsis = ellipsis || '\u2026'; if (this.length < toLength) return this; switch (where) { case 'front': return ellipsis + this.substr(this.length - toLength); break; case 'middle': return this.substr(0, toLength / 2) + ellipsis + this.substr(this.length - toLength / 2) break; case 'end': default: return this.substr(0, toLength) + ellipsis; break; } } });[/sourcecode]If you're not using MooTools, you can use this variant instead:[sourcecode language='javascript']String.prototype.ellipsise = function(toLength, where, ellipsis) { // Where is one of ['front','middle','end'] -- default is 'end' if (toLength < 1) return this; ellipsis = ellipsis || '\u2026'; if (this.length < toLength) return this; switch (where) { case 'front': return ellipsis + this.substr(this.length - toLength); break; case 'middle': return this.substr(0, toLength / 2) + ellipsis + this.substr(this.length - toLength / 2) break; case 'end': default: return this.substr(0, toLength) + ellipsis; break; } }[/sourcecode]

  • Avoid Javascript’s ‘with’ keyword

    Javascript is a fantastic language — in fact, it’s become the language that I do most of my programming in nowadays. It’s flexible, fast, and powerful. Unfortunately, though, it suffers from a few flaws, which, although not critical, can be frustrating. One of the potentially most confusing features is the with keyword, which promises a lot, but can really just make life difficult.

    The with keyword might appear to be harmless enough: it allows you to avoid typing long references; instead of
    [sourcecode language=’javascript’]ah.woom.ba.weh.lyric = ‘In the jungle’;[/sourcecode]
    we can type
    [sourcecode language=’javascript’]with (ah.woom.ba.weh) {
    lyric = ‘In the jungle’;
    }[/sourcecode]

    But what happens if we happen to have a variable in scope named lyric? In the example below, which lyric should be modified?
    [sourcecode language=’javascript’]var lyric = ‘In the jungle’;
    with (ah.woom.ba.weh) {
    lyric = ‘The mighty jungle’;
    }[/sourcecode]
    The simplest way to deal with this issue is to use a variable:
    [sourcecode language=’javascript’]var a = ah.woom.ba.weh;
    a.lyric = ‘The mighty jungle’;[/sourcecode]
    Now there is no ambiguity.

    Based on a post by Douglas Crockford at the YUI Blog.

  • Javascript-generated tables and rowspan

    At work, I’ve recently been putting together a nice little calendar-like utility using Javascript. Basically, it has to generate a table consisting of cells which may span multiple rows. Surely the solution is simple enough: just set the rowspan on each td as we create it. Unfortunately, that doesn’t work, at least not in Firefox.

    It appears that in Firefox, if you create a td and set its rowspan to some value when there are no rows for it to expand into, the attribute will be completely ignored, even if you add rows afterwards! Needless to say, this is very annoying. The solution? Build your table backwards.

    The code I have now is something like this (note that I’m developing using the Mootools framework):

    [sourcecode language=’javascript’]var tbl = new Element(‘table’);
    var trs = [];

    for (var i = 0; i < 4; i++) { var tr = new Element('tr'); tr.grab(new Element('td', { 'html': 'Cell ' + i })); if (i % 2 == 0) { tr.grab(new Element('td', { 'rowspan': 2, 'html': 'Span ' + (i / 2) })); } trs.push(tr); }for (var i = trs.length - 1; i >= 0; i–) {
    tbl.grab(trs[i], ‘top’);
    }[/sourcecode]

    What does this code do? Well basically, we’re creating a table with ten rows and two columns; the cells in the right-hand column each occupy two rows. The result will be something like this:

    Cell 1Span 1
    Cell 2
    Cell 3Span 2
    Cell 4
  • MooTools and OO Javascript development

    I’ve started work on a new project at my job — a fairly complex AJAX application for the education sector. For this project, I’ve been allowed to essentially choose my own direction, and I’ve chosen to implement the clientside Javascript using the MooTools framework. I’ll say it right here: I’m absolutely loving it.

    What I’m really enjoying about MooTools is the object-orientedness it brings to development. Although syntactically it’s a little bit weird at first, the ability to create, extend, and implement classes makes my development progress much more quickly, and in a more efficient way. Add to that the plethora of utilities (like the .each prototype for arrays) and shorthand functions (like $ to replace document.getElementById), and all of a sudden Javascript development becomes a bit more, well, flexible.

    I’m not saying that you can’t accomplish cool things in Javascript outside of MooTools (or other frameworks, for that matter); my point is that I believe you can accomplish cool things in Javascript more quickly using a good framework, which should really come as no surprise. Perhaps the reason I’m so enjoying this type of development, to the point of blogging about it, is that up till now, I’ve been stuck working in a non-frameworked, very non-OO Javascript development paradigm.

    I mentioned the curious syntax that accompanies MooTools.  To create a new class, for example, you would probably write something like this:
    [sourcecode language=’javascript’]var myClass = new Class({
    Implements: Options,
    options: {
    optionA: ‘monkey’,
    optionB: ‘pony’
    },
    initializer: function(options) {
    this.setOptions(options);
    this.doSomeStuff();
    },
    doSomeStuff: function() {
    alert(this.options.optionA + ‘ eats ‘ + this.options.optionsB);
    }
    });[/sourcecode]
    And then you would initialise it like this:
    [sourcecode language=’javascript’]var myInstance = new myClass({
    optionA: ‘Big Pony’
    });[/sourcecode]
    Although it looks a bit weird, it’s actually not too bad. There are really only two problems I have with it:

    1. Remembering to put commas in all the right spots.
    2. Geany, my preferred IDE (cf. Geany IDE: Tango dark colour scheme) can’t pick up classes and members properly (actually, at all) in this style.

    Other than that, though, I’m really enjoying it.

  • Web developer tools

    In this post, I’ll outline some of the web developer tools available in the major browsers: Firefox, Internet Explorer, Opera and Safari. This is a wholly subjective post, based on my experience as one of two developers on a very large AJAX application at Saron Education.

    Firefox

    Firefox has arguably got the best web development tools available, all of which can be downloaded from the Firefox Addons site. The two which I find most useful are the Web Developer Toolbar, by Chris Pederick, and the often-copied Firebug (official website), which itself sports a variety of addons.

    Web Developer Toolbar

    The web developer toolbar is useful for quickly enabling and disabling features of your site, checking CSS, emulating mobile browser rendering, and controlling Firefox more precisely. Personally, I find its most useful features are the ability to:

    • Disable the browser cache entirely, which removes the need for Control-Refresh or cache-clearing;
    • Outline deprecated elements, or any particular set of elements in a variety of fashions, which is very useful for updating old sites;
    • Extract colour information from the current website; and
    • View the cookie information for the current site.

    Download the Web Developer Toolbar

    Firebug

    I sometimes wonder how I ever managed to develop web applications without Firebug. Firebug allows you to alter CSS styles on the fly, edit the HTML contents of the page on the fly, visually watch the DOM being changed by your scripts, debug your scripts, type and run JavaScript straight from the browser, visualise network activity, inspect XMLHttpRequests, and much much more besides. Firebug is, in my experience, the most mature, stable, and efficient of all the tools in this survey.

    The features of Firebug which I find most useful are:

    • The ability to ‘inspect’ the DOM visually (by clicking on elements within the page), then alter their attributes, styles, and even their content dynamically;
    • The ability to watch the effects of DOM alterations by running scripts;
    • The console, with which you can craft and run JavaScript which is run as though it were part of the page itself;
    • The network monitor, which allows you to view all the POSTs and GETs your XMLHttpRequests create.

    Download Firebug

    Internet Explorer

    Until IE 8, the tools available to developers in IE were woeful at best. Fortunately, however, Microsoft has got their act together, and mimicked Firebug for version 8. The features made available in this tool include

    • The ability to interrogate the DOM to view style information about elements (changing attributes and styles hardly ever seems to work in the latest Beta, so viewing them is all you can really achieve);
    • A console, with which you can craft and run Javascript as though it were embedded in the page;
    • Javascript debugging.

    Unfortunately, these tools are still very much in beta, and are very buggy. As I mentioned, altering element attributes and styles hardly has any effect. Also, the CSS inspection system is poorly laid out and often just plain wrong. The console is well-implemented. The entire system is definitely a step in the right direction, but it suffers from bugs and lack of innovation. Also, it seems to slow down and destabilise the entire browser.

    Internet Explorer 8’s developer tools are built in; access them with the F12 key.

    Opera

    Opera’s developer tools, codenamed ‘Dragonfly’, sit between Firebug and IE in terms of functionality and facility. The DOM inspection and manipulation tools work really well (as well as Firebug), and are more immediately configurable, thanks to a variety of toolbar buttons. Dragonfly doesn’t have a console; rather, it uses a ‘command line’ interface. The difference is that where the console in Firebug and IE has seperate areas for input and output (what you type and what it does), the command line mixes these two together, much like a Unix shell or DOS. Personally, I prefer the console paradigm, but it’s much of a muchness.

    Opera’s Dragonfly is built in; access it by going to Tools -> Advanced -> Developer tools.

    Safari

    As with most Apple products, the developer tools in Safari are very pretty. There is a console akin to that in Firebug and IE, and you can inspect and manipulate the DOM. Unfortunately, however, the tools are quite buggy, and often fall down. Whilst the tools are very pretty, they don’t seem to be as stable even as IE 8’s.

    Safari’s web developer tools are built in; access them enabling the develop menu from the Advanced tab of the config, then choosing the appropriate menu item from the Develop menu.

    Conclusions

    Whilst Firebug is still by far the best tool available for web developers, the widespread development of tools by browser developers means that cross-browser debugging and development is becoming ever easier. Hopefully the tools will foster competition, so that feature sets and stability improve in all the tools.

  • Cross-browser div focus and blur

    Internet Explorer has for some time supported giving ‘focus’ to non-focussable elements such as divs. Firefox, by contrast, does not. Whilst this makes sense semantically, it’s often still very useful to use these triggers. For example, you can use onfocus to show a popup when a div is clicked, and close the popup when anything else is clicked on the page (in the onblur event).

    There are many, many workarounds which provide this functionality, using such tricks as hidden input elements, global onclick handlers, and so on, but the simplest is simply this: give your div a tabIndex attribute. For example,

    [sourcecode language=”html”]

    Click to show another div.

    [/sourcecode]
    works perfectly in Firefox, Internet Explorer, and Chrome as shown in the example below:

    Click to show another div.

    You can also achieve a similar effect purely with CSS:

    [sourcecode language=”html”]

    Focus me!
    Hooray!

    [/sourcecode]

    Focus me!
    Hooray!

    Because the second example shows or hides a child element, the parent element will remain focussed if the user interacts with the child element, or its children. This allows you to embed links, forms, videos, and so on in the child element.

    The value of tabIndex can have significance, too:

    • -1: The user can’t tab to the element, but it can be given focus programmatically (element.focus()) or by being clicked on.
    • 0: The user can tab to the element, and its order in the tabbing is automatically determined.
    • >0: Give the element a priority, with ‘1’ being the highest priority.

    I originally discovered this technique on this CodingForums.com thread.