Opened 7 years ago

Closed 7 years ago

Last modified 7 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 7 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 7 years ago by ole

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

comment:4 Changed 7 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 7 years ago by Scott González

No, you should use a select.

Note: See TracTickets for help on using tickets.