TwitterCounter for @bigclick_dean

dBlog.com.au

My Development Blog

I have been working on a clients project recently and really didn’t like the way the standard selects looked on the page and as we all know they are impossible to style consistently across all browsers. Being a jQuery fan I knew that there must have been an existing plugin to help…but alas there were many plugins that kind of worked, some of them didn’t include a full feature set, some didn’t work in all browsers and some didn’t degrade back to regular selects when needed (e.g. GoogleBot, Screen Readers, no JavaScript, etc).

I did however manage to find a reasonable good custom select over at http://www.adelaidewebdesigns.com/2008/08/01/adelaide-web-designs-releases-customselect-with-icons (even happened to be a fellow aussie!). It wasn’t perfect and it wouldn’t allow for multiple selects on the one page and the icons weren’t really what I needed. Reading through the comments I found that someone else (http://www.ildavid.com/dblog/selectcustomizer/) had made some modifications to allow for multiple selects on the one page. This was great I was getting closer to the solution that I needed, but there were still some issues like keyboard navigation and the ability to click anywhere in the window to close the select just like a regular select.

So I set out to further modify the code and put in some of my own requirements and then re-share it, I have managed to get the drop-down to close when you click outside it, I have also introduced keyboard navigation (up, down and enter). To get the keyboard navigation working I needed to use the scrollTo plugin to allow smooth scrolling up and down in the select.

There are still a few minor bugs that need to be fixed but it works enough for me, one bug is that in IE you need to click in the drop-down area if you don’t want the page to jump when using the keys.

I would also like to get the menu to activate when a user is tabbing around the site, but that’s a job for another rainy day!

$.fn.SelectCustomizer = function(){
    // Select Customizer jQuery plug-in
	// based on customselect by Ace Web Design http://www.adelaidewebdesigns.com/2008/08/01/adelaide-web-designs-releases-customselect-with-icons/
	// modified by David Vian http://www.ildavid.com/dblog
	// and then modified AGAIN be Dean Collins http://www.dblog.com.au
    return this.each(function(){
        var obj = $(this);
		var name = obj.attr('id');
		var id_slc_options = name+'_options';
		var id_icn_select = name+'_iconselect';
		var id_holder = name+'_holder';
		var custom_select = name+'_customselect';
        obj.after("<div id=\""+id_slc_options+"\" class=\"optionswrapper\"> </div>");
        obj.find('option').each(function(i){
            $("#"+id_slc_options).append("<div title=\"" + $(this).attr("value") + "\" class=\"selectitems\"><span>" + $(this).html() + "</span></div>");
        });
        obj.before("<input type=\"hidden\" value =\"\" name=\"" + this.name + "\" id=\""+custom_select+"\"/><div id=\""+id_icn_select+"\">" + this.title + "</div><div id=\""+id_holder+"\" class=\"selectwrapper\"> </div>").remove();
        $("#"+id_icn_select).click(function(a){
			if($("#"+id_holder).css('display') == 'none') {
				$("#"+id_holder).fadeIn(200);
				$("#"+id_holder).focus();
				a.stopPropagation();
				$(document).keypress(function(e) {
					if(!e) var e = window.event;
					e.cancelBubble = true;
					e.returnValue = false;
					if (e.stopPropagation) {
						e.stopPropagation();
						e.preventDefault();
					}
				});
				$(document).keyup(function(e) {

					if(e.which == 40) {
						var lastSelected = $("#"+id_holder+" .selectedclass");
						if(lastSelected.size() == 0) {
							var nextSelected =  $("#"+id_slc_options+" div:first:");
						} else {
							var nextSelected = lastSelected.next(".selectitems");
						}
						if(nextSelected.size() == 1) {
							lastSelected.removeClass("selectedclass");
							nextSelected.addClass("selectedclass");
							$("#"+custom_select).val(nextSelected.title);
           					$("#"+id_icn_select).html(nextSelected.html());
							var rowOffset = (nextSelected.offset().top - $("#"+id_holder).offset().top);
							if(rowOffset > 130) {
								$("#"+id_slc_options).scrollTo(($("#"+id_slc_options).scrollTop() + 27) +  "px");
							}
						}

					} else if(e.which == 38) {
						var lastSelected = $("#"+id_holder+" .selectedclass");
						var nextSelected = lastSelected.prev(".selectitems");
						if(nextSelected.size() == 1) {
							lastSelected.removeClass("selectedclass");
							nextSelected.addClass("selectedclass");
							$("#"+custom_select).val(nextSelected.title);
           					$("#"+id_icn_select).html(nextSelected.html());
							var rowOffset = (nextSelected.offset().top - $("#"+id_holder).offset().top);
							if(rowOffset > 0) {
								$("#"+id_slc_options).scrollTo(($("#"+id_slc_options).scrollTop() - 27) +  "px");
							}
						}
					} else if(e.which == 13) {
						$("#"+id_holder).fadeOut(250);
						$(document).unbind('keyup');
						$(document).unbind('keypress');
						$('body').unbind('click');
					}

				});
				$('body').click(function(){
					$("#"+id_holder).fadeOut(200);
					$('body').unbind('click');
					$(document).unbind('keyup');
					$(document).unbind('keypress');
				});
			} else {
				$("#"+id_holder).fadeOut(200);
				$('body').unbind('click');
				$(document).unbind('keyup');
				$(document).unbind('keypress');
			}

        });
        $("#"+id_holder).append($("#"+id_slc_options)[0]);
		$("#"+id_holder).append("<div class=\"selectfooter\"></div>");
		$("#"+id_slc_options+" > div:last").addClass("last");
        $("#"+id_holder+ " .selectitems").mouseover(function(){
            $(this).addClass("hoverclass");
        });
        $("#"+id_holder+" .selectitems").mouseout(function(){
            $(this).removeClass("hoverclass");
        });
        $("#"+id_holder+" .selectitems").click(function(){
            $("#"+id_holder+" .selectedclass").removeClass("selectedclass");
            $(this).addClass("selectedclass");
            var thisselection = $(this).html();
            $("#"+custom_select).val(this.title);
            $("#"+id_icn_select).html(thisselection);
            $("#"+id_holder).fadeOut(250);
			$(document).unbind('keyup');
			$(document).unbind('keypress');
			$('body').unbind('click');
        });
    });
}


You can see a working demo here

You can also download a full working example here

Popularity: 2% [?]

Comments

There are 7 comments for this post.

  1. an on March 22, 2009 3:56 am

    hey! hello from Russia!
    come from search Google to you -)))

    thx for work! but…

    how about onchange in select?
    and how about

    best regards, sergey

  2. an on March 22, 2009 3:58 am

    and option selected… (select active option)

  3. Peter simmons on June 30, 2009 3:28 pm

    I made some minor modifications so that it would work for me.

    1. Wrapped the plugin in an enclosure to make it compatible with using other libraries such as prototype.js mootools.js
    2. Added a hide any selectwrapper lists on line 22 before showing the one that was clicked. This fixed a bug which you can see on the demo if you click the second drop down and then click the first drop down (without clicking anywhere else) the second drop down still shows and it shows above the first one.

    Here is the updated code

    (function($){ // hide the jquery namespace and make it compatible with other libs
    $.fn.SelectCustomizer = function(){
    // Select Customizer jQuery plug-in
    // based on customselect by Ace Web Design http://www.adelaidewebdesigns.com/2008/08/01/adelaide-web-designs-releases-customselect-with-icons/
    // modified by David Vian http://www.ildavid.com/dblog
    // and then modified AGAIN be Dean Collins http://www.dblog.com.au
    // and then by Pete Simmons for BrightTALK for http://www.investment-intelligence.co.uk/
    return this.each(function(){
    var obj = $(this);
    var name = obj.attr(’id’);
    var id_slc_options = name + ‘_options’;
    var id_icn_select = name + ‘_iconselect’;
    var id_holder = name + ‘_holder’;
    var custom_select = name + ‘_customselect’;
    obj.after(” “);
    obj.find(’option’).each(function(i){
    $(”#” + id_slc_options).append(”" + $(this).html() + “”);
    });
    obj.before(”" + this.title + ” “).remove();
    $(”#” + id_icn_select).click(function(a){
    // hide any other custom selects’ list
    $(’.selectwrapper’).hide();
    if ($(”#” + id_holder).css(’display’) == ‘none’) {
    $(”#” + id_holder).fadeIn(200);
    $(”#” + id_holder).focus();
    a.stopPropagation();
    $(document).keypress(function(e){
    if (!e)
    var e = window.event;
    e.cancelBubble = true;
    e.returnValue = false;
    if (e.stopPropagation) {
    e.stopPropagation();
    e.preventDefault();
    }
    });
    $(document).keyup(function(e){

    if (e.which == 40) {
    var lastSelected = $(”#” + id_holder + ” .selectedclass”);
    if (lastSelected.size() == 0) {
    var nextSelected = $(”#” + id_slc_options + ” div:first:”);
    }
    else {
    var nextSelected = lastSelected.next(”.selectitems”);
    }
    if (nextSelected.size() == 1) {
    lastSelected.removeClass(”selectedclass”);
    nextSelected.addClass(”selectedclass”);
    $(”#” + custom_select).val(nextSelected.title);
    $(”#” + id_icn_select).html(nextSelected.html());
    var rowOffset = (nextSelected.offset().top – $(”#” + id_holder).offset().top);
    if (rowOffset > 130) {
    $(”#” + id_slc_options).scrollTo(($(”#” + id_slc_options).scrollTop() + 27) + “px”);
    }
    }

    }
    else if (e.which == 38) {
    var lastSelected = $(”#” + id_holder + ” .selectedclass”);
    var nextSelected = lastSelected.prev(”.selectitems”);
    if (nextSelected.size() == 1) {
    lastSelected.removeClass(”selectedclass”);
    nextSelected.addClass(”selectedclass”);
    $(”#” + custom_select).val(nextSelected.title);
    $(”#” + id_icn_select).html(nextSelected.html());
    var rowOffset = (nextSelected.offset().top – $(”#” + id_holder).offset().top);
    if (rowOffset > 0) {
    $(”#” + id_slc_options).scrollTo(($(”#” + id_slc_options).scrollTop() – 27) + “px”);
    }
    }
    }
    else if (e.which == 13) {
    $(”#” + id_holder).fadeOut(250);
    $(document).unbind(’keyup’);
    $(document).unbind(’keypress’);
    $(’body’).unbind(’click’);
    }

    });
    $(’body’).click(function(){
    $(”#” + id_holder).fadeOut(200);
    $(’body’).unbind(’click’);
    $(document).unbind(’keyup’);
    $(document).unbind(’keypress’);
    });
    }
    else {
    $(”#” + id_holder).fadeOut(200);
    $(’body’).unbind(’click’);
    $(document).unbind(’keyup’);
    $(document).unbind(’keypress’);
    }

    });
    $(”#” + id_holder).append($(”#” + id_slc_options)[0]);
    $(”#” + id_holder).append(”");
    $(”#” + id_slc_options + ” > div:last”).addClass(”last”);
    $(”#” + id_holder + ” .selectitems”).mouseover(function(){
    $(this).addClass(”hoverclass”);
    });
    $(”#” + id_holder + ” .selectitems”).mouseout(function(){
    $(this).removeClass(”hoverclass”);
    });
    $(”#” + id_holder + ” .selectitems”).click(function(){
    $(”#” + id_holder + ” .selectedclass”).removeClass(”selectedclass”);
    $(this).addClass(”selectedclass”);
    var thisselection = $(this).html();
    $(”#” + custom_select).val(this.title);
    $(”#” + id_icn_select).html(thisselection);
    $(”#” + id_holder).fadeOut(250);
    $(document).unbind(’keyup’);
    $(document).unbind(’keypress’);
    $(’body’).unbind(’click’);
    });
    });
    }

    })(jQuery); // pass jQuery in as the value for the $ parameter in the closure function

  4. Peter simmons on June 30, 2009 3:37 pm

    In answer to the an from Russia. The value get’s put into an input tag. So you should be able to attach an onchange event to this to get the desired effect or get the value from here for working out what the selected option is.

  5. Sergiu on July 1, 2009 11:06 pm

    Hello, thank you for your plugin, but i have a problem with it, the form never sends data in FF, in IE it works…ca you give me a solution please..i realy cannot find any solution for it.

  6. Sergiu on July 2, 2009 9:38 pm

    and the onChange function does’nt work too( i wanted to manipulate with data from value using java script but it doesn’t work too((((

  7. brian on July 9, 2009 7:50 am

    great work! I especially love the fact that when clicking off of the menu it now closes up — a behavior that mimics real form dropdown select menus. Any insight on how you accomplished that?
    thanks again (and to Paul and David before you).

Trackbacks

  • There are no trackbacks for this post

Write a Comment