Skip to main content

Search and Top Navigation

#7897 closed bug (notabug)

Opened November 18, 2011 04:39AM UTC

Closed November 18, 2011 04:54AM UTC

Last modified November 18, 2011 05:57AM UTC

autocomplete combobox implementation is missing "required" validation

Reported by: ole Owned by:
Priority: minor Milestone: 1.9.0
Component: ui.core Version: 1.8.16
Keywords: Cc:
Blocked by: Blocking:
Description

Hi,

In this write up I have assumed that the goal of the autocomplete combobox is to provide the same functionality as a regular select element, in addition to filtering and jquery ui theme styling.

Jquery validation supports validating a regular select element by leaving the value attribute as an empty string for the option that is the "Placeholder" label of the select element.

http://stackoverflow.com/questions/1271640/validate-select-box

It would be great if the combobox implementation supported the same semantics. The text of the option that is the "Placeholder" label is also not shown in the combobox.

I'm pasting a minimal demo below (It includes the combobox plugin):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html style="background-color: white;">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.9/jquery-ui.min.js"></script>
<script src="http://ajax.aspnetcdn.com/ajax/jquery.validate/1.9/jquery.validate.min.js"></script>
<script src="http://ajax.microsoft.com/ajax/jquery.validate/1.9/additional-methods.js"></script>

<link 	rel="stylesheet"
		href="jquery-ui.css"/>

<style>
.ui-button { margin-left: -1px; }
.ui-button-icon-only .ui-button-text { padding: 0.35em; } 
.ui-autocomplete-input { margin: 0; padding: 0.48em 0 0.47em 0.45em; }
</style>


<script>
(function( $ ) {
	$.widget( "ui.combobox", {
		_create: function() {
			var self = this,
				select = this.element.hide(),
				selected = select.children( ":selected" ),
				value = selected.val() ? selected.text() : "";
			var input = this.input = $( "<input>" )
				.insertAfter( select )
				.val( value )
				.autocomplete({
					delay: 0,
					minLength: 0,
					source: function( request, response ) {
						var matcher = new RegExp( $.ui.autocomplete.escapeRegex(request.term), "i" );
						response( select.children( "option" ).map(function() {
							var text = $( this ).text();
							if ( this.value && ( !request.term || matcher.test(text) ) )
								return {
									label: text.replace(
										new RegExp(
											"(?![^&;]+;)(?!<[^<>]*)(" +
											$.ui.autocomplete.escapeRegex(request.term) +
											")(?![^<>]*>)(?![^&;]+;)", "gi"
										), "<strong>$1</strong>" ),
									value: text,
									option: this
								};
						}) );
					},
					select: function( event, ui ) {
						ui.item.option.selected = true;
						self._trigger( "selected", event, {
							item: ui.item.option
						});
					},
					change: function( event, ui ) {
						if ( !ui.item ) {
							var matcher = new RegExp( "^" + $.ui.autocomplete.escapeRegex( $(this).val() ) + "$", "i" ),
								valid = false;
							select.children( "option" ).each(function() {
								if ( $( this ).text().match( matcher ) ) {
									this.selected = valid = true;
									return false;
								}
							});
							if ( !valid ) {
								// remove invalid value, as it didn't match anything
								$( this ).val( "" );
								select.val( "" );
								input.data( "autocomplete" ).term = "";
								return false;
							}
						}
					}
				})
				.addClass( "ui-widget ui-widget-content ui-corner-left" );

			input.data( "autocomplete" )._renderItem = function( ul, item ) {
				return $( "<li></li>" )
					.data( "item.autocomplete", item )
					.append( "<a>" + item.label + "</a>" )
					.appendTo( ul );
			};

			this.button = $( "<button type='button'> </button>" )
				.attr( "tabIndex", -1 )
				.attr( "title", "Show All Items" )
				.insertAfter( input )
				.button({
					icons: {
						primary: "ui-icon-triangle-1-s"
					},
					text: false
				})
				.removeClass( "ui-corner-all" )
				.addClass( "ui-corner-right ui-button-icon" )
				.click(function() {
					// close if already visible
					if ( input.autocomplete( "widget" ).is( ":visible" ) ) {
						input.autocomplete( "close" );
						return;
					}

					// work around a bug (likely same cause as #5265)
					$( this ).blur();

					// pass empty string as value to search for, displaying all results
					input.autocomplete( "search", "" );
					input.focus();
				});
		},

		destroy: function() {
			this.input.remove();
			this.button.remove();
			this.element.show();
			$.Widget.prototype.destroy.call( this );
		}
	});
})( jQuery );
</script>

<script>
$(function()
{
	$("#button").button();
	$("#select1").combobox();
	$(function() {
		$("#form").validate(
			    {
			    	rules: 
			        {
				    	select0: { required: true},
				    	select1: { required: true}
			        },
			        messages:
			        {
				        select0: "Please select an option"
				    }
			    });

		$("#button").click(
				function(event)
				{
					result = $("#form").valid();
					console.log("valid: " + result);
				}); 
	});
});

</script>
</head>
<body>


<a id="button">validate</a>

<form id="form">
<select id="select0" name="select0">
	<option value="">Choose an option</option>
	<option value="option1">Option1</option>
	<option value="option2">Option2</option>
</select>
<br/>

<select id="select1" name="select1">
	<option value="">Choose an option</option>
	<option value="option1">Option1</option>
	<option value="option2">Option2</option>
</select>

</form>											
</body>
</html>
Attachments (0)
Change History (5)

Changed November 18, 2011 04:54AM UTC by scottgonzalez comment:1

resolution: → invalid
status: newclosed

That's not how it should work. There's defined behavior for a combobox and the current implementation matches that.

Changed November 18, 2011 05:31AM UTC by ole comment:2

Could you please point me to the location of the defined behaviour specification?

Changed November 18, 2011 05:33AM UTC by scottgonzalez comment:3

Changed November 18, 2011 05:47AM UTC by ole comment:4

Aha - Thanks - I see what you mean. Do you think having it as an option would be appropriate. Something like:

$("#myselect").combobox(validation: true);

Changed November 18, 2011 05:57AM UTC by scottgonzalez comment:5

No, you should use a select.