In a post just a week or two ago I covered the topic of searching select dropdowns on key events. It seemed to work ok, but could use a bit of polishing. However for the project I was working on I ended up needing something a little more… “Obvious”. So the solution I came up with involved one of my favorite jQuery plugins.. Impromptu, and just some handy jQuery magic. So what did I come up with?

Well for obvious reasons the way to interact with a dropdown are relatively limited. Key events will need to be allowed for native browser functionality. A click event will need to open the dropdown. Double click just doesn’t seem to fire correctly (I guess since the first click opens the dropdown). And surely not use the focus event to open a search. Well jQuery comes with one nice little event named “contextmenu”. Essentially its a right click or ctrl click. And I got to thinking, you know, that would be a perfect place for such. To me a right click indicates “I need some extra help on this item”. So thats where we are. We will be opening a slick search prompt on right click. Lets see it:

function showDropdownSearch(e){
	var $t = $(this),
		$o = $('option:enabled',$t),
		tval = $t.val(),
		html = '<div id="optionsearch">'+
				'<h3>Search Options</h3>'+
				'<div class="textinput"><label for="">Search <span>type your search term and press Enter</span><span id="optionsearchstatus">Searching, please wait..</span></label><input type="search" id="searchquery" name="searchquery" value="" placeholder="Search.."></div>'+
				'<div id="searchoptionswrapper"><table id="searchoptions" class="radioTable" cellpadding="0" cellspacing="0"><tbody></tbody></table></div>'+
			'</div>';
			
	e.preventDefault();
	
	var $imp = $.prompt(html, {
			buttons: { Ok:true,Cancel:false },
			submit: function(v,m,f){
				if(v){
					$t.val(f.searchanswer).change();
				}
			}
		});

	var $so = $('#searchoptions', $imp);

	$so.delegate('input', 'click', function(){
		$('tr.checked', $so).removeClass('checked');
		$(this).parent().parent().addClass('checked');
	});

	$('#searchquery', $imp).focus().keydown(function(event){
		var $i = $(this),
			query = $i.val(),
			re = new RegExp(query,"i"),
			html = "",
			counter = 0,
			$sos = $('#optionsearchstatus',$imp);

		if(event.which == 13 || event.keyCode == 13 && $.trim(query) !== ''){

			$sos.css('display','inline');

			$o.each(function(i,obj){
				var $currt = $(this),
					currval = $currt.attr('value'),
					currtxt = $currt.text(),
					currterm = currval + currtxt;

				if(re.test(currterm) && currtxt !== '' && currval !== ''){
					html += '<tr class="row'+ (counter++ % 2) + (currval == tval? ' checked':'')+'">'+
							'<td class="td-radio"><input type="radio" name="searchanswer" id="searchanswer_'+ counter +'" value="'+ currval +'"'+ (currval == tval? ' checked':'') +'></td>'+
							'<td class="td-label"><label for="searchanswer_'+ counter +'">'+ currtxt +'</label></td>'+
						'</tr>';
				}

			});

			$so.find('tbody').html(html);
			$so.find('tr:eq(0)').addClass('checked').find('input').attr('checked',true);

			$('#searchoptionswrapper',$imp).slideDown('slow', function(){
				$sos.hide();
			});

			event.preventDefault();
			return false;
		}// end if enter key

	});
	
	return false;
}

Thats the function. Now here is how you fire the contextmenu event on a select with jQuery:

// by direct event
$('select').bind('contextmenu', showDropdownSearch);

// or by delegation
$('#select_container').delegate('select','contextmenu',showDropdownSearch);

Lets see the demo of it in action.

Now of course there is some extra css to go with it. I will let you view the source on the demo page and grab it from there. It just seems like too much bloat for a blog post. So there you have a nice, hidden, discreet option search for your dropdowns. This could also be wrapped up nicely in a jquery wrapper to be more jQuery-like, but I’ll leave that for another post. Enjoy!