Click here to Skip to main content
15,884,388 members
Articles / Programming Languages / Javascript
Tip/Trick

A jQuery Plug-in to Make Input Box Background Image Clickable

Rate me:
Please Sign up or sign in to vote.
5.00/5 (1 vote)
17 Jun 2012CPOL3 min read 16K   3   1
This plug-in enhances user experience of input boxes on a web page.

Introduction 

This plug-in makes an input box background image clickable and handles the click event by a callback function. It is useful when you want a good user experience of the web page.

Background

jQuery is a great JavaScript library. I have been long time looking forward to writing a plug-in to it. When I was developing a web application for a digital media advertising system, finally I got an opportunity to write one which is worthy of it. 

Adding background image to an input box is very simple, just use css. Making the image clickable is not difficult, either. Add a div element overlapping the image and attach a click event to the div element, then it is OK.

Though it looks that it is very easy, there are still issues to fix when it comes to browser compatibility and making a jQuery plug-in. 

The code of the plug-in 

Before going on, we have to get to know what a jQuery plug-in looks like. Here there is a good tutorial. 

According to jQuery, there are two kinds of structures:

JavaScript
$.fn.myPlugin = function() {
  
  // Do your awesome plugin stuff here

};
JavaScript
(function( $ ) {
  $.fn.myPlugin = function() {
  
    // Do your awesome plugin stuff here

  };
})( jQuery );

Personally I like the second structure. In this article I'll use the second one. 

Let's first take an overall look at the plug-in: 

JavaScript
(function($) {
    $.fn.addClickableBackgroundImage = function(params) {
        params = $.extend({ alignTo: 'right' }, params);
        this.each(function() {
           var input = $(this);
           if (input.is(':input[type=text]')) {
             var inputPos = input.position();
             var inputWidth = input.width();
             var inputOuterHeight = input.outerHeight();
             var imgWidth = input.height();
             var imgHeight = imgWidth;

             input.css({
	         'background': 'url(' + params.imageSrc + ') ' + params.alignTo + ' no-repeat',
	         'background-size': imgWidth + 'px ' + imgHeight + 'px'
	      });
 
              var div = $('<div/>').appendTo($('body'));
              var divLeft, divTop;
              if (params.alignTo.toLowerCase() == 'left') {
                 divLeft = inputPos.left + (inputOuterHeight - imgHeight) / 2;
              } else if (params.alignTo.toLowerCase() == 'center') {
                 divLeft = inputPos.left + (inputWidth - imgWidth) / 2
              } else {
                 divLeft = inputPos.left + inputWidth - imgWidth + (inputOuterHeight - imgHeight) / 2;
              }
 
              divTop = inputPos.top + (inputOuterHeight - imgHeight) / 2;
 
              var img = $('<img />');
              img.bind('load', function () {
                  div.width(imgWidth);
                  div.height(imgHeight);
                  div.offset({
                      left: divLeft,
                      top: divTop
                  }).css('cursor', 'pointer');
                  div.bind('click', function () {
                      if (typeof params.callback == 'function') {
                          params.callback.call(this, input.attr('id'));
                      } else if (eval('typeof ' + params.callback) == 'function') {
                          eval(params.callback + '.call(this, "' + input.attr('id') + '")');
                      } else {
                          alert('Callback "' + params.callback + '" is not a function, or does not exist.');
                      }
                  });
              });
 
              //refer to http://www.w3schools.com/css/css_image_transparency.asp
              //for visibility in different browsers
              var imgStyle = 'visibility:hidden;opacity=0';
              if ($.browser.msie) {
                  imgStyle = 'opacity=0;filter:alpha(opacity=0);'
              }
              img.appendTo(div).attr({
                  src: params.imageSrc,
                  width: imgWidth,
                  height: imgHeight,
                  style: imgStyle
              });
            }
        });
        return this;
    };
})(jQuery);

In the plugin, I first set the default position of the image to "right". If user sets the alignTo property of params object, it will be overidden. See How to Use section. 

Plug-in user may select more than one input box. This is the reason why I use this.each function to iterate each element in the user selection. User may also select all elements of input type by using $(':input'), which may include buttons, check boxes, etc. So it is necessary to use input.is(':input[type=text]')  to filter.

Attaching a background image can be done by simply changing its CSS background style. But it is not clickable right now. And background-size style applies to CSS3 and later. So it is safe to make an image that fits well into the input boxes.

Then I make a div element with the width and height being equal to the height of the input box, and move it to the position specified by property alignTo (left, right or center). For browsers  such as Firefox and Chrome, it is OK now if attaching a handler to the click event of the div element. But IE does not let it go, since IE seems to ignore the div if it contains nothing. 

There are 2 ways to fix this IE issue. The first one is add some &nbsp's into the div. But how many &nbsp's to add? It involves text metrics. The second one is add the same image into the div and make it invisible. I am going the second way. 

But there is browser compatibility issue in making the image inside the div invisible.  I tried display:none, but it does not work with IE. I tried visibility:hidden, again, it does not work with IE. Finally I came to the current solution, thanks to W3 Schools.

To bind the click event handler to the div element, it is needed to detect if user passes into the params the handler function object or function name, and detect if the function exists. 

How to use it  

The following code shows how to use the plug-in.

JavaScript
$(':input').addClickableBackgroundImage({
    imageSrc: 'add16x16.png',
    alignTo: 'right',
    callback: callbackFn
});
 

function callbackFn(inputId) {
    alert(inputId)
}

When the background image is clicked on, an alert box will popup, showing the relevant input box id with the help of the callback function. See the following screenshot:

Possible Issues 

  1. This plug-in is built with jQuery version 1.7.1, I did not test it on other versions.
  2. I tested it on Firefox 12.0, Chrome 19.0 and IE 8.0, all on Windows 7. I am not sure if it is working with other browsers on other operating systems.

Interested readers, please kindly let me know of any issues.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Canada Canada
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 5 Pin
Carsten V2.017-Jun-12 21:55
Carsten V2.017-Jun-12 21:55 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.