Sunday, 19 June 2011

A jQuery plugin to add icons to elements

In this article I present a simple jQuery plugin that adds suitable icons to a selection of elements based on the value of the rel attribute.

CSS3 :after selector not suitable?

If the target browser understands CSS3 we could add an icon with the help of the :after selector. This has a couple of disadvantages though:

  • Only the newest browsers support this,
  • Although it is possible to insert a url that points to an image, this element is magic, i.e. not visible in the DOM, so we cannot style it with CSS,
  • We can select elements based the contents of an attribute but we cannot construct and element based on the result of this selection.
Fortunately a flexible yet simple solution can be crafted in a few lines of Javascript with the help of the jQuery library.

The iconify plugin

The code presented below assumes that jQuery is already loaded. It is tested with jQuery 1.6.1 but should work with earlier versions just as well. Using the plugin is as simple as $("a").iconify();. This will add an icon (an <img> tag) to every link, if any of those links has a rel attribute. You need to provide a directory with suitable icons. For example, if you have links with rel="python", an icon will be added with a src attribute of src="Icons/python-icon.png"

The plugin can be broken down to a few simple steps. The first it does (in line 2) is to make sure the selection is a jQuery object. The next two lines make sure that if any of the parameters is missing the corresponding default is used.

In line 6 we then iterate over all elements of the selection and retrieve the rel attribute (line 8). If this attribute is present and not empty, we check if it can be found in the iconmap object, if not we construct a generic name (line 13). Next we construct an <img> element with a suitable src attribute and a meaningful alt attribute and add this element to the current element in the iteration. Finally (line 24) we return the original selection to allow this plugin to be chained just like most jQuery functions.

$.fn.iconify = function (icondir,iconmap) {
 var $this = $(this);
 icondir = icondir || $.fn.iconify.icondir;
 iconmap = iconmap || $.fn.iconify.iconmap;
 
 $this.each(function(i,e){
  e=$(e);
  var rel=e.attr('rel');
  var src="";
  var alt="";
  
  if(rel !== undefined && rel != ''){
   if(iconmap[rel]!==undefined){
    src='src="'+icondir+'/'+iconmap[rel]+'"';
   }else{
    src='src="'+icondir+'/'+rel+'-icon.png'+'"';
   }
   alt='alt="'+rel+' icon"';
   var img=$('');
   e.append(img);
  }
 });
 
 return $this;
};
$.fn.iconify.icondir='Icons';
$.fn.iconify.iconmap={
'python' :'python-logo-24.png',
'blender' :'blender-logo-24.png',
'photo'  :'camera-logo-24.png',
'wikipedia' :'wikipedia-logo-24.png'
};

The CSS rel attribute

Using the rel attribute for this purpose might be considered misuse (see for example this page) so you might consider rewriting the plugin to check another attribute, for instance class.

No comments:

Post a Comment