Providing context help for drop downs with jQuery

This post is more than 2 years old.

I'm working on updating the UI to Adobe Gorups (don't worry - it's not my design) and I came across an interesting issue. I've got a simple drop down of options the user can chose from but I want to provide some contextual help as well. So if you select an option I want to describe the option in greater detail. Here is a quick solution I came up with that makes use of custom data attributes and jQuery.

For my option I decided to make use of custom data attributes. This is a HTML5 spec that describes the ability to add any additional attribute to an HTML attribute by simply prefixing it with data-. So for example:

<b data-coolness="verycool">Raymond</b>

What's cool is that jQuery provides support for reading and writing these values using the data() function. Oddly (and maybe I just misread the doc), you use data() as the root of the jQuery library and not in a selector. So this is not allowed:

$("some item").data(....);

Instead, you do:

$.data(somedom, "somekey", "option value to set");

I suppose since $(..) returns an array another way of working with data was necessary. EDIT: Ignore the last two sentences. I initially had this misconception when I was writing my tests, then quickly realized I was wrong. However, when it came time to write the blog entry, I had a brain fart. Sorry!

Anyway - here is what I did for my first draft:

<html>

<head> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> <script> $(document).ready(function() { $("#features").change(function() { $("#description").text(""); var option = $("option:selected",this); var desc = $(option).data("description"); $("#description").text(desc); }); }) </script>

</head>

<body>

<form> Select an option for your new car: <select name="features" id="features"> <option value=""></option> <option value="1" data-description="Turns on your wipers automatically when it rains.">Automatic Wipers</option> <option value="2" data-description="Helps ensure you get the best parking spot.">Machine Guns</option> <option value="3" data-description="Clears messy traffic jams.">Sidewinder Missiles</option> </select> </form> <div id="description"></div> </body>

</html>

Let's start at the bottom. Notice my drop down has additional attributes in the data scope called description. This will be completely ignored by the rendering of your browser. Now head up to the code. I've bound a change handler to the drop down that notices changes. I get the select option and then fetch the description data property. I then use this text within my div. You can test this code here: http://www.coldfusionjedi.com/demos/dec282010/test.cfm

So while that worked, it occurred to me that for a set of options, you most likely wanted to allow a person to select any number of options. How would we handle it if the select item allowed for multiple selections? Here is the code I came up with. Unfortunately, this code is a complete fail in Internet Explorer. It should run fine but it won't provide the help we want. I'll talk about what I tried after I show the code that worked in every other fracking browser.

<html>

<head> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> <script> $(document).ready(function() {

$("#features option").click(function() {
	$("#description").text("");
	if($(this).attr("selected")) {
		var desc = $(this).data("description");
		$("#description").text(desc);
	}
});

}) </script>

</head>

<body>

<form> Select an option for your new car:<br/> <select name="features" id="features" multiple size="5"> <option value="1" data-description="Turns on your wipers automatically when it rains.">Automatic Wipers</option> <option value="2" data-description="Helps ensure you get the best parking spot.">Machine Guns</option> <option value="3" data-description="Clears messy traffic jams.">Sidewinder Missiles</option> </select> </form> <div id="description"></div> </body>

</html>

So HTML wise the only change was the addition of multiple and size to the drop down. The JavaScript code is a bit different though. First - I changed my selector to include option. This ensures that if I click in the blank spaces after my option I won't have anything occur. Next - I need to see if the option was selected. If you ctrl-click on a selected item than it's going to disable the option. There is no point in describing the feature in that case. If it is selected then the rest of the code is the same. You can see this here: http://www.coldfusionjedi.com/demos/dec282010/test2.cfm

So - what about IE? First - IE never noticed the click event. Ok - so I switched to a click on the drop down, not the option. I then thought - I can look at the Event object and see if the target was on the select or the option. I found that this code worked great:

if(e.srcElement.tagName == "OPTION") {

Accept... once again... fracking iE just returned SELECT. I tried e.target, e.currentTarget, e.srcElement, and in all cases, IE wasn't able to detect that an option had been clicked on versus the select itself. In theory, one could keep a list of items clicked. You would then be able to check that list and if an item is gone now it meas a deselect. Screw that. This feature is meant to provide help to the end user but is not mission critical. Therefore I'm skipping over IE. If someone has a fix though I'd love to hear it.

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by Derek P. posted on 12/28/2010 at 11:55 PM

If you stick with the click method against the select box, can you rely on this.selectedIndex to get the options index and pull the data out that way?

More about that here:

http://msdn.microsoft.com/e...

Comment 2 by JCaito posted on 12/29/2010 at 12:04 AM

I got this to work in IE just fine and thought it would be nice to display the descriptions for all selected items.

<html>

<head>
<script type="text/javascript" src="http://ajax.googleapis.com/..."></script>
<script>
var desc = "";
$(document).ready(function() {
$("#features").click(function() {
desc = "";
$("#description").text("");
$(this).children().each(function(index,value){
if($(value).attr("selected")){
desc = desc + $(value).data("description") + "<br />";
}
$("#description").html(desc);
});
});
})
</script>

</head>

<body>

<form>
Select an option for your new car:<br/>
<select name="features" id="features" multiple size="5">
<option value="1" data-description="Turns on your wipers automatically when it rains.">Automatic Wipers</option>
<option value="2" data-description="Helps ensure you get the best parking spot.">Machine Guns</option>
<option value="3" data-description="Clears messy traffic jams.">Sidewinder Missiles</option>
</select>
</form>
<div id="description"></div>
</body>

</html>

Comment 3 by todd sharp posted on 12/29/2010 at 12:13 AM

Cool demo Ray. I agree that the data() method is very handy in jQuery! I take a bit of a lazier approach to provide contextual help for select options and just use the title attribute on the <option>. I'm pretty sure most browsers (even IE) support it and give you a tooltip.

Comment 4 by todd sharp posted on 12/29/2010 at 12:23 AM

Here's another cool option that looks like it's being planned for jQuery UI:

http://wiki.jqueryui.com/w/...

You can add additional formatted text, etc to the drop down.

Sorta OT, but it seems like there is a lot of cool stuff "planned" for jQuery UI but it seems like the dev cycle is a bit slow. Anyone know why?

Comment 5 by Roland Collins posted on 12/29/2010 at 12:41 AM

Ray, I believe that this is what you were looking for. You should contninue to use the change method of the select itself.

$(document).ready(function() {
$("#features").change(function() {
$("#description").text("");

var options = $("option:selected", this);
var desc = '';

options.each(function(i) {
desc = $(this).data("description");
$("#description").append(desc + '<br>');
});
});
})

Comment 6 by Raymond Camden posted on 12/29/2010 at 12:41 AM

Guys - I made a mistake in my blog post. I'm a bit rushed now and will respond to your comments later. In the beginning I said you must do $.data() and could not do $("...").data(). That was based on a mistake I made earlier in my code testing process. Unfortunately, I kept on to that mistake when I wrote the blog entry. If you read my blog post, you clearly see me doing $(...).data(). Sorry!

Comment 7 by Brian Swartzfager posted on 12/29/2010 at 12:42 AM

I was going to suggest something along the same lines as what JCaito did. Personally, I try to avoid using multi-select drop-downs these days: they're not pretty and most of my non-technical users have trouble selecting multiple items. A list of checkboxes can accomplish the same thing in most cases.

When I want to provide context or hints on a single selection drop-down, I tend to do what Todd does (use the title attribute) out of habit.

Comment 8 by Raymond Camden posted on 12/29/2010 at 12:52 AM

All: I added text to make sure folks know I was wrong about $.data - is it clear?

@DerekP: That goes back to my workaround of remembering what was selected. I'm trying to avoid it. It _would_ work - yes.

@JCaito: I had thought about showing them all too - but in my mind the detail should be for one item at a time. Obviously that's a UI decision and I probably shouldn't be making it. ;)

@todd: title - interesting. Didn't think about that. :)

@todd 2: No idea on that. Oddly jQuery Mobile seems to be moving super fast. Then again - look at how much more interest there is in mobile these days.

@Roland: Again, that goes back to showing _all_ the help where I wanted to show one at a time.

Comment 9 by JCaito posted on 12/29/2010 at 12:58 AM

Agreed on the UI decision ^__^

Changing the selector to '#features' as opposed to '#features option' and then using the 'children()' selector will fix your IE issue.

Comment 10 by Roland Collins posted on 12/29/2010 at 12:58 AM

@Ray,

Right - but why wouldn't you want to display the help for all selected items?

What if I select 3 items at once by using shift-click or click/drag? How would you determine which was the item I selected, when technically, I selected 3? If you're going to allow for users to select multiple items, you can't expect them to click each one individually. Maybe the issue is that you're using the wrong control for the job.

If your assumption is that they're going to select one at a time, then you should probably use checkboxes instead of a drop down.