Changing An Image Based On A Checkbox Check Via jQuery / JavaScript

This question came via email earlier today:

Your Article: An Image-Based ‘Checkbox’
http://demo.dougv.com/js_imgswap_checked/example2.html

Awesome article and very informative. I was trying to get it to work for what I am trying to accomplish but I am having a hell of a time getting it to work I was hoping you can help me.

I have a selection form based on Check Boxes:

item 1 (box)
item 2 (box)
item 3 (box)
item 4 (box)

I have images that correspond to the check boxes, item1.png, item2.png, item3.png, item4.png that are located elsewhere on the page. I just need the image to change based on whether the check box is checked or not. It doesn’t matter if it is faded or an entirely new image, so long as the user notices which box they checked. My problem is there are a lot of little images so in your example you had the two set variables, on or off. How do I introduce multiple images???

I have early tests and the problems are that the default unchecked images do not show up until after the check box is checked…all of them and two whenever I try to add multiple images and or check boxes it breaks somewhere, perhaps the array or I am approaching this at the wrong end. I need your help.

To rephrase the question:

  • We have four checkboxes inside a form.
  • On the same page, we have four images. Each image is related to one of those checkboxes. That is, Checkbox 1 is related to Photo 1, Checkbox 2 is related to Image 2, etc.
  • When we click a checkbox, we want to change its associated image somehow, to indicate the checkbox’s state. (In this case, I am going to use a faded image if its related checkbox is unchecked, and a full-opacity image if its related checkbox is checked).

Easily enough accomplished.

For this exercise, I will use four pictures of Miss USA 2012 contestants, and ask users to pick which are their favorites. If a contestant is selected, her picture will be at full opacity; if the contestant is not selected, her image will be at reduced opacity (i.e., faded).

Step 1: Link to jQuery

I’ll power this with jQuery, since it has good cross-browser support not only for handling DOM events like clicks, but also because it has good cross-browser support for “fading” DOM objects, including pictures, in and out.

For those unfamiliar with jQuery, it’s a JavaScript library. What that means is, it’s already solved a number of common JavaScript needs into handy functions, which have been tested to work in most Web browsers.

If I have a very small, very straightforward JavaScript need — say, echo out an alert if something is clicked — I don’t bother using jQuery. But the more complicated the task I need to accomplish, and the more reliant I am on ensuring that the client properly process that task, the more likely I am to use jQuery.

I used to advise people to upload a copy of jQuery to your Web site and linking to it from there. Of late, however, I pretty much just link to a version of jQuery hosted by the Google Libraries API.

<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>

Step 2: The HTML

Next, we need to prepare our page to handle the effects we will create via jQuery / JavaScript.

The most important part of that process is ensuring we have some way to relate each checkbox to its related image. There are a few ways we can do that:

  1. Create a CSS class for each pairing, and assign both elements to that class;
  2. Create IDs for each checkbox and image that are closely related (for example, “item_1_checkbox” and “item_1_image”).
  3. Associate the value of the checkbox with some attribute of the image (for example, an image with the ID “foobar” and a checkbox with a checked value of “foobar”).

For this example, I am going to use a hybrid of options 2 and 3.

Specifically, I am going to assign each image the ID of “img_{value},” where {value} is the value of its associated checkbox. For example, if I have a checkbox with the value of “miss_maine_usa”, its associated image will have the id “img_miss_maine_usa.”

Like this:

<img id="img_miss_maine_usa" name="img_miss_maine_usa" src="miss_maine_usa.jpg" class="contestant_pic" alt="Rani Williamson, Miss Maine USA" title="Rani Williamson, Miss Maine USA" />
<input type="checkbox" id="cb_miss_maine_usa" name="favorite_contestant" value="miss_maine_usa" />

We’ll lay out the images and form separately, since that’s what the question implies is the case. However, you could put these images inside the form, if you want. It’s not necessary, but it can be done that way.

<div id="container-photos" class="container">
	<div id="column-1" class="column">
		<img id="img_miss_alabama_usa" name="img_miss_alabama_usa" src="miss_alabama_usa.jpg" class="contestant_pic" alt="Katherine Webb, Miss Alabama USA" title="Katherine Webb, Miss Alabama USA" />
		<a href="http://www.missuniverse.com/missusa/members/profile/651291/year:2012/" title="Katherine Webb, Miss Alabama USA" target="profile">
			<p class="caption">Katherine Webb, Miss Alabama USA</p>
		</a>
	</div>
	<div id="column-2" class="column">
		<img id="img_miss_maine_usa" name="img_miss_maine_usa" src="miss_maine_usa.jpg" class="contestant_pic" alt="Rani Williamson, Miss Maine USA" title="Rani Williamson, Miss Maine USA" />
		<a href="http://www.missuniverse.com/missusa/members/profile/651310/year:2012/" target="profile">
			<p class="caption">Rani Williamson, Miss Maine USA</p>
		</a>
	</div>
	<div id="column-3" class="column">
		<img id="img_miss_northcarolina_usa" name="img_miss_northcarolina_usa" src="miss_northcarolina_usa.jpg" class="contestant_pic" alt="Sydney Perry, Miss North Carolina USA" title="Sydney Perry, Miss North Carolina USA" />
		<a href="http://www.missuniverse.com/missusa/members/profile/651324/year:2012/" target="profile">
			<p class="caption">Sydney Perry, Miss North Carolina USA</p>
		</a>
	</div>
	<div id="column-4" class="column">
		<img id="img_miss_southdakota_usa" name="img_miss_southdakota_usa" src="miss_southdakota_usa.jpg" class="contestant_pic" alt="Taylor Neisen, Miss South Dakota USA" title="Taylor Neisen, Miss South Dakota USA" />
		<a href="http://www.missuniverse.com/missusa/members/profile/651332/year:2012/" target="profile">
			<p class="caption">Taylor Neisen, Miss South Dakota USA</p>
		</a>
	</div>
	<div id="column-5" class="column unrelated">
		<img id="img_bill_murray" name="img_bill_murray" src="bill_murray.jpg" class="another_class_altogether" alt="Bill Murray" title="Bill Murray" />
		<a href="http://www.imdb.com/name/nm0000195/" target="profile">
			<p class="caption">Bill Murray</p>
		</a>
	</div>
</div><!-- /photos -->

<br class="clearfix" />

<div id="container-form" class="container">
	<form id="myform" name="myform" method="get">
		<h4>Who are your favorite Miss USA 2012 contestants?</h4>
		<label><input type="checkbox" id="cb_miss_alabama_usa" name="favorite_contestant" value="miss_alabama_usa" />Katherine Webb, Miss Alabama USA</label>
		<br />
		<label><input type="checkbox" id="cb_miss_maine_usa" name="favorite_contestant" value="miss_maine_usa" checked="checked" />Rani Williamson, Miss Maine USA</label>
		<br />
		<label><input type="checkbox" id="cb_miss_northcarolina_usa" name="favorite_contestant" value="miss_northcarolina_usa" />Sydney Perry, Miss North Carolina USA</label>
		<br />
		<label><input type="checkbox" id="cb_miss_southdakota_usa" name="favorite_contestant" value="miss_southdakota_usa" />Taylor Neisen, Miss South Dakota USA</label>
		<br />
		<label><input type="checkbox" id="unrelated_checkbox" name="unrelated_checkbox" value="foobar" />This checkbox is not related to any of the pictures above.</label>
		<br />
		<input type="submit" id="submit" name="submit" value="Submit" />
	</form>
</div><!-- /form -->

Note that in this form, all the checkboxes that have a related image are named “favorite_contestant.” It may be that you need to relate checkboxes and images on a very specific basis. That’s outside the scope of this article; for most intents and purposes, this approach will suffice.

Step 3: The JavaScript

To make this work, we need to incorporate two steps:

  • Fade all the unchecked the images on page load. That is, some of our images may be prechecked in the form; we want those to be at full opacity. All unchecked images should be faded down.
  • Fade an image up if it is checked, and down if it is not.

Why do we set the initial fade state of images via JavaScript? Simple: Because not all visitors will have JavaScript enabled, or use a browser that understands our code. It’s better to assume this doesn’t work for any given visitor, than to assume it does.

A quick aside on checking for support of client-side script: Check out Ensuring JavaScript Is Enabled Before Displaying Content On A Web Page if your application must work with client-side scripting effects.

And remember: JavaScript and DOM elements can be altered by a user; always sanitize form variables before processing them.

First, we need to set some global variables: constants for full opacity, faded opacity, the rate at which we want the fade to take place and a simple string variable we’ll use to construct the image ID we want, based on the checked value of a box.

Also, note that we will wrap all of this script in $(document).ready(), which is how jQuery wires up DOM event handlers on page load.

//set global constants & variable
var full_opacity = 1;
var faded_opacity = 0.3;
var fade_speed = 'fast';				
var objid;

Next, we want to set the initial state for each checkbox.

I am selecting all the checkboxes with the name “favorite_contestant.”

If all the checkboxes on my page were related to an image, I could have used the selector ‘:checkbox’ to get them all; if the only input elements I had on the page were checkboxes, I could have used ‘input’. But in this case, I have an additional, unrelated checkbox on the page, so I need to be specific about which checkboxes have associated images.

$('input[name="favorite_contestant"]').each(function() {

	//we need the image associated with this checkbox
	//i am assuming the associated image tag has an ID of "img_" and whatever the value of the associated checkbox is
	//e.g., img_miss_alabama_usa is the id for the image associated with the checkbox that has the checked value miss_alabama_usa
	objid = "#img_" + $(this).val();
	
	if($(this).prop('checked')) {
		//full opacity for prechecked images
		$(objid).css('opacity', full_opacity);
	}
	else {
		//partial opacity for unchecked images
		$(objid).css('opacity', faded_opacity);
	}
});

With the initial fade state of each image set, we can now add the handler that will fade images up and down, depending on whether its related checkbox is clicked.

$('input[name="favorite_contestant"]').change(function() {
	//same method as above for associating a checkbox and its image
	objid = "#img_" + $(this).val();
	if($(this).prop('checked')) {
		//full opacity for image if associated checkbox is checked
		$(objid).fadeTo(fade_speed, full_opacity);
	}
	else {
		//partial opacity for image if associated checkbox is unchecked
		$(objid).fadeTo(fade_speed, faded_opacity);
	}
});
Note that I am using the .change() event to fire this handler. I could have used .click() instead; I’m using .change() to be explicit about when the event is firing.

(That is, “change” is more accurate about what is happening than “click” is. Although both the change and click events fire when either a checkbox or its label is clicked, I am using change so that my code is self-documenting.)

And with that, we have a fully functional solution. You can see it in action here: http://demo.dougv.com/ajax_checkbox_img_switch/

No code download this time; just save the HTML, since it all runs client-side.

4 Comments

  1. What background color? I meant the highlight, or more direct the opacity can it tint yellow?

    I looked at the script part and couldn’t find anything, is it a css thing? which line?

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

  • Check out the Commenting Guidelines before commenting, please!
  • Want to share code? Please put it into a GitHub Gist, CodePen or pastebin and link to that in your comment.
  • Just have a line or two of markup? Wrap them in an appropriate SyntaxHighlighter Evolved shortcode for your programming language, please!