Tooltips on disabled buttons with Dojo

Saturday, 23 May 2009

Here’s how to add tooltips to disabled form controls using Dojo. The technique could be adapted for use in other frameworks or standalone JavaScript code.

I recently needed to add tooltips to a web application. The specific requirement was that when a button was disabled, there should be a tooltip explaining why. We were using Dojo 1.2. Now Dojo includes a Tooltip class, but it doesn’t work on disabled elements.

Fortunately, Dojo’s complex implementation came to the rescue. Dojo injects quite a lot of extra markup around its buttons; in particular the buttons are wrapped with spans. So it occurred to me that I could attach the tooltip to one of the wrappers instead of the button itself. Then even if the button were disabled, the wrapper would still be enabled and the tooltip would appear. The simplest way is just to attach the tooltip to the button’s parents.

And it worked! Even better, it worked on both Firefox and Internet Explorer. I only tested on FF3 and IE6, but it may well also work on IE7, IE8, Chrome, Safari et al.

Here’s some code, with an example. It’s self-explanatory if you have some familiarity with Dojo.

dojo.require("dijit.Tooltip");

// Some examples of my tooltip functions    
dojo.addOnLoad(function() {
    // Add a tooltip to the button whose ID is "save-button"; only works
    // if it's enabled
    addTooltip("save-button", "Save the information to the database.");
    // Add an appropriate tooltip to the Delete button that works
    // even if it's disabled
    var deleteButton = dojo.byId("delete-button");
    var deleteTip = "Delete the information from the database.";
    if (deleteButton.attr("disabled")) {
        deleteTip += " Unavailable because it's too dangerous.";
    }
    addParentTooltip(deleteButton, deleteTip);
    // There are two Next buttons with no IDs: add tooltips to
    // them that work even if disabled
    addParentTooltipByName("next-button", "Go to the next page.");
});

/** Add a tooltip to any number of nodes passed directly or as IDs. */
function addTooltip(/*node or string or array*/nodes, /*string*/text) {
    if (!dojo.isArray(nodes)) {
        nodes = [nodes];
    }
    // connectId can be an id or a node (not that you'd know from the
    // documentation) or an array of ids and nodes
    new dijit.Tooltip({connectId: nodes, label: text});
}
/** Add a tooltip to all form elements with the given name. */
function addTooltipByName(/*string*/name, /*string*/text) {
    addTooltip(dojo.query('[name="' + name + '"]'), text);
}
/** Add a tooltip to the parents of all form elements with the given
    name. The tooltips will show even if the element is disabled,
    provided the parent is not disabled. */
function addParentTooltip(/*string*/name, /*string*/text) {
    var nodes = dojo.query('[name="' + name + '"]');
    var parents = dojo.map(nodes, function(node) {
        return node.parentNode;
    });
    addTooltip(parents, text);
}
/** Add a tooltip to the parents of all nodes passed either directly
    or as IDs. The tooltips will show even if the element is disabled,
    provided the parent is not disabled. */
function addParentTooltipByName(/*node or string or array*/nodes, /*string*/text) {
    var parents = dojo.map(nodes, function(node) {
        return dojo.byId(node).parentNode;
    });
    addTooltip(parents, text);
}

You could extend this in lots of ways:

  • Put it in some fancy namespace
  • Extend the Tooltip class itself to add these functions
  • Automatically wrap the control (in case it’s not a Dojo button)
  • Use jQuery instead of Dojo 🙂

When this problem first came up, my colleague David googled for a solution but couldn’t find one. Hopefully this post has filled the gap.

Tags: ,

4 comments

You can leave a comment, or trackback from your own site.

  1. AWESOME AWESOME AWESOME PLUG IN . . . . exactly what i’ve been looking for and saves a task with my automated content!

    thanks!

  2. really cool… thank you very much!!!

    a quick question, would you happen to know why the tooltip works perfectly well in IE, but, acts very weird in Firefox (by weird, I mean, it takes a longer time to load, even after loading, sometimes, it just freezes on the scree.)

  3. @newbie, I haven’t noticed that. I must say that working with Dojo is quite nice when it works, but it’s a nightmare to debug when it doesn’t work.

Leave a comment