I can't go anywhere without having this UX nightmare on my hands. How many times have you started typing in these drop downs, then tab away expecting the same UX you have, LIKE EVERYWHERE ELSE ON THE INTERNET? The problem is, these drop downs are inconsistent in their behavior and even render completely different in Internet Explorer. If there are 20+ items within the list, you can guarantee calls to your helpdesk. I've spent enough time working on this problem; enough to offer up some code so you can handle this yourself too. Hopefully, you find it useful.
This has been blogged about a bunch... Consider this horse completely beaten and dead at this point, but nothing I've seen out there handles SharePoint drop downs the way I do with this code. Without further adieu, the codez:
<link type="text/css" rel="stylesheet" href="//code.jquery.com/ui/1.10.2/themes/smoothness/jquery-ui.min.css">
<script src="//code.jquery.com/jquery-1.8.3.min.js"></script>
<script src="//code.jquery.com/ui/1.10.2/jquery-ui.min.js"></script>
<script>
function getFormDDL( columnName ) {
var $ddl = $("select[title='" + columnName + "']"),
choices,
choiceArray,
index = 1
; //local vars
if ( $ddl.length > 0 ) {
$ddl.SPOptions = $ddl.find("option").map(function() {
var $el = $(this);
return {
label: $el.text(),
id: $el.val()
};
}).get();
$ddl.SPComplexDdl = false;
} else {
$ddl = $("input[title='" + columnName + "']");
choices = $ddl.attr("choices");
choiceArray = choices.split("|");
$ddl.SPOptions = [];
for ( ; index < choiceArray.length; index = index + 2 ) {
$ddl.SPOptions.push({
label: choiceArray[ index - 1 ],
id: choiceArray[ index ]
});
}
$ddl.SPComplexDdl = true;
}
return $ddl;
}
function setFormDdl( $ddl, lookupVal ) {
var choices,
choiceArray,
hiddenInput,
index
;
if ( $ddl.SPComplexDdl ) {
choices = $ddl.attr("choices");
hiddenInput = $ddl.attr("optHid");
$("input[id='" + hiddenInput + "']").val( lookupVal );
choiceArray = choices.split("|");
for ( index = 1; index < choiceArray.length; index = index + 2 ) {
if ( choiceArray[ index ] == lookupVal ) {
$ddl.val( choiceArray[ index - 1 ] );
}
}
} else {
$ddl.val( lookupVal );
}
}
/*****
*
* Main processing
*
******/
$( document ).ready(function() {
// To use this, just add as many Display Names you want that are Drop Downs on your form!
var columnNames = [ "Full Name", "City" ]
;
// Don't touch... It works as is. :)
$.each( columnNames, function( index, columnName ) {
var $ddl = getFormDDL( columnName ),
$wrapper = $("<div class='sp-planet-autocomplete'>"),
idName = columnName.replace(/ /g, "-"),
$input = $("<input class='ms-long' id='" + idName + "' />")
; //local vars
// debugger;
// When ddl is complex, we need to hide the whole shebang. Might as well do it for a simple ddl too.
$ddl.closest("span[dir='none']").hide();
$wrapper.append( $input );
$ddl.closest("td").prepend( $wrapper );
// Find autocomplete options here.
// http://jqueryui.com/autocomplete/
$input.autocomplete({
source: $ddl.SPOptions,
minLength: 0,
select: function( event, ui ) {
setFormDdl( $ddl, ui.item.id );
}
});
// If selection is made and then text is deleted, this will prevent that. This ain't my first rodeo...
$input.on("blur", function( el ) {
// debugger;
if( el.currentTarget.value.trim() === "" ) {
setFormDdl( $ddl, 0 );
}
});
});
});
</script>
Now this is a cool alternative to the standard ho-hum. It's safe to say that users know exactly what they are looking for when there are 20+ options to choose from. With that in mind, providing a search by type UX feels natural. Also as an added bonus, jQueryUI gives you: up and down keyboard navigation and enter/tab selection. Having this enabled just FEELS good!
Search by Type Usage
The columNames variable is the only variable you have to change. Everything else is handled by jQuery/jQueryUI magic under the hood. The only caveat to my code is that it currently doesn't handle multiple selections. My current needs haven't forced me to pursue this, but if you find it necessary, I may revisit it. I'd be more inclined to do so, *if* it was profitable. :-)
Feel free to let me know how this code works out for you. It *should* just work.