Opened 10 years ago

Closed 10 years ago

Last modified 10 years ago

#7897 closed bug (notabug)

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'>&nbsp;</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>

Change History (5)

comment:1 Changed 10 years ago by Scott González

Resolution: invalid
Status: newclosed

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

comment:2 Changed 10 years ago by ole

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

comment:4 Changed 10 years ago by ole

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

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

comment:5 Changed 10 years ago by Scott González

No, you should use a select.

Note: See TracTickets for help on using tickets.