Styling Checkboxes with JavaScript

I’ve been reading recently about how to do Styled Checkboxes. Well, this was something I was working on too – and naturally, I like my way more.

How it works
When the page loads, the JavaScript in checkbox.js checks all of the INPUT tags on the page. If they are a checkbox, and have BOTH and imgOn and an imgOff, then the INPUT tag has its style set to hidden, and the appropriate images are added to the DOM. They’re floating, though, and so are positioned where the checkbox was on the page.

When you click on one, it changes the state of the underlying checkbox (it’s still there, just hidden), and displays the image appropriate for that state.

When the form is submitted, the checkbox is submitted as normal.

As a user leaves the page, on unload the code in checkbox.js tries to tidy up after itself, although I’m a little concerned about memory leaks after some interesting articles I read recently.

Known Issues

  • These controls are not part of the tabindex. My friend Bruce Sandeman has been working on a version of this where the images are ‘tabable’, but is struggling to turn the border of the images off. I’ve included the code anyway – see checkbox2.js. I’ve not reviewed it yet, so user beware!
  • It’d be nice to hand all events on to the original checkbox for handling.
  • At the least, some sort of mouseover/mouseout? It’s not so obvious that these are checkboxes, at least with the demo images I’ve chosen.
  • I’m a little concerned about memory leaks given some things I’ve read recently and my use of closures. If anyone knows how to prove/prevent any leaks, let me know, that would be cool

How to Use

Real tricky this – include the checkbox.js file in your HTML page.
<script src="checkbox.js"></script>
Then, in the HTML for each of your checkboxes, add two new attributes – ‘imgOn’ and ‘imgOff’. The value of these attributes should be the path to the images you want to use for the checked (‘on’) and unchecked (‘off’) states.

<input type="checkbox" value='2' imgOn='tick.gif' imgOff='cross.gif' />

and with luck, that should be you done.

See the code below:

//**************************************************
// Copyright 2005 - Andrew Burns
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific
// language governing permissions and limitations under the License.
//**************************************************
//**************************************************
// CheckBox Control
// ---------------
// By Andrew Burns, June 2005
// Modified Bruce Sandeman, June 2005
//
// Javascript file for creating a 'Checkbox' using images.
// Degrades softly to normal checkboxes if JavaScript is unsupported.
//**************************************************
// Function to attach an event handler function to an object
function attachCheckEvent ( oTarget, cEvType, fnHandler, bForceOneFn ){
if( bForceOneFn == null ) {
bForceOneFn = false;
}
if( bForceOneFn ) {
oTarget["on" + cEvType] = fnHandler;
} else {
if (oTarget.addEventListener) {
oTarget.addEventListener( cEvType, fnHandler, true );
} else if (oTarget.attachEvent){
oTarget.attachEvent( "on" + cEvType, fnHandler );
}
}
// Note: No assignment of form below:
// oTarget["on" + cEvType] = fnHandler;
// I don't want to overwrite any other javascript that is applied, so instead
// I'll not do anything. This way, we just fail softly...
}
// Create a closed OnClick function. This will deal with changing the image, and the hidden CheckBox field
function createCheckClickEventHandler( oImg ) {
obj = function( e ) {
if( oImg.chkBox.checked == true ) {
oImg.chkBox.checked = false;
oImg.src = oImg.offImage.src;
} else {
oImg.chkBox.checked = true;
oImg.src = oImg.onImage.src;
}
};
return obj;
}
function createKeyEventHandler( o ) {
obj = function( e ) {
var bSpaceKey = false;
if( e ) {
if( e.which == 32) {
bSpaceKey = true;
}
} else {
if( window.event.keyCode ) {
bSpaceKey = true;
}
}
if( bSpaceKey ) {
var oImg = o.oImg;
if( oImg.chkBox.checked == true ) {
oImg.chkBox.checked = false;
oImg.src = oImg.offImage.src;
} else {
oImg.chkBox.checked = true;
oImg.src = oImg.onImage.src;
}
}
};
return obj;
}
// Function to create checkboxes. Reads the the DOM attributes of text input tags.
function prepareCheck () {
// Get Input elements
var x = document.getElementsByTagName('INPUT');

// For each input element, if it is a checkbox, and has replacement images…
for (var i=0;i
if( (x[i].type == ‘checkbox’) && x[i].getAttribute(‘imgOn’) && x[i].getAttribute(‘imgOff’) ){

// Find Checkbox Location on screen. Hide the Checkbox
xpos = 0;
obj = x[i];
if (obj.offsetParent) {
while (obj.offsetParent) {
xpos += obj.offsetLeft;
obj = obj.offsetParent;
}
} else if (obj.x) {
xpos += obj.x;
}

ypos = 0;
obj = x[i];
if (obj.offsetParent) {
while (obj.offsetParent) {
ypos += obj.offsetTop;
obj = obj.offsetParent;
}
} else if (obj.y) {
ypos += obj.y;
}

x[i].style.visibility = ‘hidden’;

// Add a new image, and cache ‘checked’ and ‘unchecked’ images.
var oAnchor = document.createElement( “A” );
oAnchor.tabIndex = i+1;
oAnchor.href=”null”;
var oImg = document.createElement( “IMG” );
oImg.onImage = new Image();
oImg.onImage.src = x[i].getAttribute(‘imgOn’);
oImg.offImage = new Image();
oImg.offImage.src = x[i].getAttribute(‘imgOff’);
// Make it visibile, and absolutely positioned, so we can replace the CheckBox
oAnchor.style.visibility = ‘visible’;
oAnchor.style.position = ‘absolute’;
// Link between Hidden Checkbox and Image
oImg.chkBox = x[i];
x[i].oImg = oImg;

// Decide on the Initial image used for the image
// IE and Opera

if( document.all ) {
bOn = !( x[i].getAttribute( “CHECKED” ) == false );
} else {
bOn = ( x[i].getAttribute(“CHECKED” ) == “”);
}

if( bOn ) {
oImg.src = oImg.onImage.src;
} else {
oImg.src = oImg.offImage.src;
}
// Attach the click event hander. This should swap the image and the checkbox state
oImg.style.left = xpos + ( ( x[i].offsetWidth – oImg.width ) / 2);
oImg.style.top = ypos + ( ( x[i].offsetHeight – oImg.height ) / 2);
attachCheckEvent( oImg, ‘click’, createCheckClickEventHandler( oImg ) );
oAnchor.oImg = oImg;
attachCheckEvent( oAnchor, ‘keydown’, createKeyEventHandler( oAnchor ), true );
attachCheckEvent( oAnchor, ‘click’, function (e) { return false; }, true );
oAnchor.style.left = xpos + ( ( x[i].offsetWidth – oImg.width ) / 2);
oAnchor.style.top = ypos + ( ( x[i].offsetHeight – oImg.height ) / 2);
oAnchor.appendChild( oImg );
document.body.appendChild( oAnchor );
}
// if
}
// for
}
// Clear the elements used on page exit
function clearCheck () {
var x = document.getElementsByTagName(‘INPUT’);
for (var i=0;i
if( (x[i].type == ‘checkbox’) && x[i].oImg ){
x[i].oImg.onclick = null;
x[i].oImg.onImage = null;
x[i].oImg.offImage = null;

x[i].oImg.chkBox = null;

x[i].oImg.src = null;
x[i].oImg.parentNode.removeChild( x[i].oImg );
x[i].oImg = null;
}
}
}
// Attach Events on page load to prepare the Checkboxes.
attachCheckEvent( window, ‘load’, prepareCheck);
attachCheckEvent( window, ‘unload’, clearCheck);

Advertisements
Styling Checkboxes with JavaScript

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s