Getting the width of a hidden element with jQuery using width()

I recently ran into a problem with jQuery’s width().  The problem is an item that is hidden with display:none will return a value of 0 instead of its’ actual calculated width.  After messing around with it for a little bit I finally came up with a solution.  The method I used involved adding some CSS properties to the hidden element.  The CSS properties involved are position, visibility, and display.

$HiddenItem.css({
    position: "absolute",
    visibility: "hidden",
    display: "block"
})
$HiddenItem.width();

$HiddenItem.css({
    position: "",
    visibility: "",
    display: ""
})

After setting the above CSS properties on the element, you can then call width() and the correct value will be returned. After you call the width() method you should clear the properties in order to return the element to the way it was.

Setting the properties to an empty string is probably not the best way to do it though. What if there was a position value already set? Using this method would clear out that initial values of the CSS properties.

I found the swap() method to be handy in this situation. I found this method while looking through the jQuery source code.

// A method for quickly swapping in/out CSS properties to get correct calculations
swap: function( elem, options, callback ) {
     var old = {};

     // Remember the old values, and insert the new ones
     for ( var name in options ) {
          old[ name ] = elem.style[ name ];
          elem.style[ name ] = options[ name ];
     }

     callback.call( elem );

     // Revert the old values
     for ( var name in options )
          elem.style[ name ] = old[ name ];
     }
}

By using the swap method, the old CSS properties will be remembered and reapplied after finding the width of the element.

The swap method takes in 3 parameters:

  1. The element that you would like to swap the CSS properties on
  2. CSS key/value pairs that you want to change
  3. A callback function to call after the properties are set

To rewrite the above to use the swap method I would do the following:

var props = { position: "absolute", visibility: "hidden", display: "block" };
var hiddenItemWidth = 0;

$.swap($HiddenItem, props, function(){
     hiddenItemWidth = $HiddenItem.width();
});

//Use hiddenItemWidth
$HiddenItem.width();

jQuery Custom Selector for selecting elements by exact text :textEquals

I needed a way to find labels based on the text that they contained.  I thought about using :contains() for this, but in this particular case the text items I was searching on were names and I could have similar names that :contains() could incorrectly match on.  For instance, if I was searching for “Banks, Tim” and there was an item with the text “Banks, Timothy” I would get both items returned.  This is not the behavior I was looking for.

I decided to write a little custom selector to match on exact text.  Here is the code for the custom selector:

$.expr[':'].textEquals = function(a, i, m) {
return $(a).text().match("^" + m[3] + "$");
};

What is happening here is I am using a regular expression to test if the start and end of the element’s text matches the string passed in.  Now I could search for the name “Banks, Tim” on a label element like this:

$("label:textEquals('Banks, Tim')");

jQuery Extension: radioClass() method

I recently ran into a method in the Ext javascript library called radioClass.  This method will add one or more CSS classes to an element and remove the class(es) from the siblings of the element.  I found that this would be helpful in jQuery since I find myself doing something similar often:

$("li").addClass("selected").siblings().removeClass("selected");

I wrote the following extension method in jQuery to reduce the amount of code.

Code:

$.fn.extend({
     radioClass: function(c) {
     return $(this).addClass(c).siblings().removeClass(c).end();
}
});

Usage:

$("li").radioClass("selected");

View Demo