Related
I have a <select> which I need to transform in more functional combobox.
<span class="combo_box">
<select id="state" name="state" tabindex="24">
<option value="" disabled selected style="display:none"></option>
<!-- Some JSP here -->
</select>
</span>
And I transformed it in to widget (so original <select> with id "state" is still there but hidden) like this $("#state").combobox(); What i need is to add an error highlight to this custom widget on form submission if combobox is empty. jQuery UI has a custom CSS class ui-state-error for this.
Validation script (works fine as I debug it)
function setComboboxClassBeforeSubmit(elementID) {
var flag = true;
var element = document.getElementById(elementID);
var combobox = $(element).combobox();
combobox.removeClass('ui-state-error');
if (isEmpty(element)) {
combobox.addClass('ui-state-error');
flag = false;
}
return flag;
}
But adding this CSS class seems like have no effect on widget look. Also tried hardcode like it was shown here, something like $("#state").addClass('ui-state-error') and still no luck.
Also tried this solution, works fine for selectmenu but not for combobox.
Possible solution: (thanks to nowhere)
Editing _createAutocomplete: function() like this:
_createAutocomplete: function() {
var selected = this.element.children( ":selected" ),
value = selected.val() ? selected.text() : "";
this.input = $( "<input>" )
.appendTo( this.wrapper )
.val( value )
.attr( "title", "" )
.attr( "id", "ui-" + this.element.attr("id") + "-input" )
...
Issue is - default API doesn't generate unique ID's for combobox's elements.
Can you try with the code I've made here? I operated by using the jqueryui example: http://jsfiddle.net/b5e83x2q/
function checkValue(item){
item.removeClass('ui-state-error');
if(item.val()==""){
item.addClass('ui-state-error');
}
}
checkValue($(".custom-combobox input"));
.ui-state-error{
background-color:red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span class="custom-combobox">
<input title="" class="custom-combobox-input ui-widget ui-widget-content ui-state-default ui-corner-left ui-autocomplete-input" autocomplete="off" value="">
</span>
EDIT:
if you need to identify a specific select you should give it a specific id: if you used the same code of the jqueryui example you should have:
_create: function() {
this.wrapper = $( "<span>" )
.addClass( "custom-combobox" )
.insertAfter( this.element );
this.element.hide();
this._createAutocomplete();
this._createShowAllButton();
}
there you might try to add something like:
this.attr('id', 'specificId');
or edit the span wrapper:
_create: function() {
this.wrapper = $( "<span>" )
.addClass( "custom-combobox" )
.insertAfter( this.element )
.attr('id', 'specificId');
this.element.hide();
this._createAutocomplete();
this._createShowAllButton();
}
After that you can use:
checkValue($("#specificId input"));
to change only 1 select.
EDIT: Doh! I should have placed my code here too! Here it is:
My code to call the combobox:
jQuery( "#select_performance" ).combobox();
jQuery( "#select_state" ).combobox();
jQuery( "#select_postcode" ).combobox();
jQuery( "#select_install" ).combobox();
jQuery( "#select_customer" ).combobox();
jQuery( "#select_address" ).combobox();
My code (as is from JQuery ui) to define the fields:
/*** Set up multiselect drop down lists ***/
(function( $ ) {
$.widget( "custom.combobox", {
_create: function() {
this.wrapper = $( "<span>" )
.addClass( "custom-combobox" )
.insertAfter( this.element );
this.element.hide();
this._createAutocomplete();
this._createShowAllButton();
},
_createAutocomplete: function() {
var selected = this.element.children( ":selected" ),
value = selected.val() ? selected.text() : "";
this.input = $( "<input>" )
.appendTo( this.wrapper )
.val( value )
.attr( "title", "" )
.addClass( "custom-combobox-input ui-widget ui-widget-content ui-state-default ui-corner-left" )
.autocomplete({
delay: 0,
minLength: 0,
source: $.proxy( this, "_source" )
})
.tooltip({
tooltipClass: "ui-state-highlight"
}).on('mouseup', function() {
$(this).select();
});
this._on( this.input, {
autocompleteselect: function( event, ui ) {
ui.item.option.selected = true;
this._trigger( "select", event, {
item: ui.item.option
});
},
autocompletechange: "_removeIfInvalid"
});
},
_createShowAllButton: function() {
var input = this.input,
wasOpen = false;
$( "<a>" )
.attr( "tabIndex", -1 )
.attr( "title", "Show All Items" )
.tooltip()
.appendTo( this.wrapper )
.button({
icons: {
primary: "ui-icon-triangle-1-s"
},
text: false
})
.removeClass( "ui-corner-all" )
.addClass( "custom-combobox-toggle ui-corner-right" )
.mousedown(function() {
wasOpen = input.autocomplete( "widget" ).is( ":visible" );
})
.click(function() {
input.focus();
// Close if already visible
if ( wasOpen ) {
return;
}
// Pass empty string as value to search for, displaying all results
input.autocomplete( "search", "" );
});
},
_source: function( request, response ) {
var matcher = new RegExp( $.ui.autocomplete.escapeRegex(request.term), "i" );
response( this.element.children( "option" ).map(function() {
var text = $( this ).text();
if ( this.value && ( !request.term || matcher.test(text) ) )
return {
label: text,
value: text,
option: this
};
}) );
},
_removeIfInvalid: function( event, ui ) {
// Selected an item, nothing to do
if ( ui.item ) {
return;
}
// Search for a match (case-insensitive)
var value = this.input.val(),
valueLowerCase = value.toLowerCase(),
valid = false;
this.element.children( "option" ).each(function() {
if ( $( this ).text().toLowerCase() === valueLowerCase ) {
this.selected = valid = true;
return false;
}
});
// Found a match, nothing to do
if ( valid ) {
return;
}
// Remove invalid value
this.input
.val( "" )
.attr( "title", value + " didn't match any item" )
.tooltip( "open" );
this.element.val( "" );
this._delay(function() {
this.input.tooltip( "close" ).attr( "title", "" );
}, 2500 );
this.input.data( "ui-autocomplete" ).term = "";
},
_destroy: function() {
this.wrapper.remove();
this.element.show();
}
});
})( jQuery );
I have 6 jQuery autocomplete comboboxes on a page. Each has selected a default item set up on load (first item of the list). When a user types in an invalid entry, (or blanks the input box) I get the tooltip saying "invalid entry". Is there a way to have the value be re-set to the initially selected / default entry (first list item)?
I cannot seem to find the answer to this (or perhaps I am asking the wrong way).
Thanks!
I don't know how you're setting your default value but here's a clue of how to go about it.
change: function (event, ui) {
if (ui.item === null) { // if value typed in the box doesn't exist then
$(this).val(""); // set value to empty string
$(this).val(list[0]).data('autocomplete')._trigger('select'); set new value here and then trigger reset. Assuming list is your array of items, select the first item
}
}
I have standard select which is turned into a combobox using jQuery.
<select name="Searchby" id="Searchby">
<option value="all" >All Departments</option>
<option value="music" >Music</option>
<option value="dvd" >DVD</option>
<option value="bluray" >Bluray</option>
<option value="Artist" >Artist</option>
</select>
Then I have an input which has jQuery's autocomplete on it with categories. When a person types into the input, it returns options to choose from in different categories. If they click on a option I want it to change what is selected in the select above. Here is my code that I tried.
$("#Search").catcomplete({
delay: 1000,
source: "Drop_Down_Search.php",
select: function(event, ui) {
if (ui.item.category = 'Artist') {
$('#Searchby').val('Artist');
console.log(ui.item.category);
}
}
});
The console is logging that it is working and it posts correctly to the search results page but doesn't change before you move off the page. It just stays as 'all departments'. I need it to change so a person who is searching can see they will only search for 'Artist' or 'Blu-Rays' before they move to the search results page.
EDIT:
Ok so as it turns out without the jquery combobox set on the select it does change the value, but when you use jquery's combobox it doesn't change.
What should I be using to change the value once a select has been changed into a combobox?
Here is the combobox code:
(function( $ ) {
$.widget( "ui.combobox", {
_create: function() {
var input,
that = this,
wasOpen = false,
select = this.element.hide(),
selected = select.children( ":selected" ),
value = selected.val() ? selected.text() : "",
wrapper = this.wrapper = $( "<span>" )
.addClass( "ui-combobox" )
.insertAfter( select );
function removeIfInvalid( element ) {
var value = $( element ).val(),
matcher = new RegExp( "^" + $.ui.autocomplete.escapeRegex( value ) + "$", "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
$( element )
.val( "" )
.attr( "title", value + " didn't match any item" )
.tooltip( "open" );
select.val( "" );
setTimeout(function() {
input.tooltip( "close" ).attr( "title", "" );
}, 2500 );
input.data( "ui-autocomplete" ).term = "";
}
}
input = $( "<input>" )
.appendTo( wrapper )
.val( value )
.attr( "title", "" )
.addClass( "ui-state-default ui-combobox-input" )
.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;
that._trigger( "selected", event, {
item: ui.item.option
});
},
change: function( event, ui ) {
if ( !ui.item ) {
removeIfInvalid( this );
}
}
})
.addClass( "ui-widget ui-widget-content ui-corner-left" );
input.data( "ui-autocomplete" )._renderItem = function( ul, item ) {
return $( "<li>" )
.append( "<a>" + item.label + "</a>" )
.appendTo( ul );
};
$( "<a>" )
.attr( "tabIndex", -1 )
.attr( "title", "Select A Critera to Search In " )
.appendTo( wrapper )
.button({
icons: {
primary: "ui-icon-triangle-1-s"
},
text: false
})
.removeClass( "ui-corner-all" )
.addClass( "ui-corner-right ui-combobox-toggle" )
.mousedown(function() {
wasOpen = input.autocomplete( "widget" ).is( ":visible" );
})
.click(function() {
input.focus();
// close if already visible
if ( wasOpen ) {
return;
}
// pass empty string as value to search for, displaying all results
input.autocomplete( "search", "" );
});
},
_destroy: function() {
this.wrapper.remove();
this.element.show();
}
});
})( jQuery );
$(function() {
$( "#Searchby" ).combobox();
$( "#toggle" ).click(function() {
$( "#Searchby" ).toggle();
}); });
mistake i found..
$( "#Search" ).catcomplete({
delay: 1000,
source: "Drop_Down_Search.php",
select: function( event, ui ) {
if (ui.item.category == 'Artist') {
-----^^-- missing `=` in if since your are comparing this
$('#Searchby').val('Artist');
console.log(ui.item.category);
}
}
});
//}); extra brakets..
I found what I was looking for in this answer
How to define selected value for jQuery UI combobox?
After some editing I came to this which worked.
$('.ui-autocomplete-input').val($("#Searchby").val("Artist").val());
The value you select is 'Artist' and Searchby is the select id
I have to use two jquery API's, "jquery-1.8.3.js" and "jquery-ui.js" in my code.
But there are already older versions of jquery. And because of this the form is not working properly.
So I search on net for solution and found, we can use
<script>
var jq13 = jQuery.noConflict(true);
</script>
But I have to api's, so I created two variables but still it is not working.
This is my code:-
<script>
(function( $ ) {
$.widget( "ui.combobox", {
_create: function() {
var input,
that = this,
select = this.element.hide(),
selected = select.children( ":selected" ),
value = selected.val() ? selected.text() : "",
wrapper = this.wrapper = $( "<span>" )
.addClass( "ui-combobox" )
.insertAfter( select );
function removeIfInvalid(element) {
var value = $( element ).val(),
matcher = new RegExp( "^" + $.ui.autocomplete.escapeRegex( value ) + "$", "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
$( element )
.val( "" )
.attr( "title", value + " didn't match any item" )
.tooltip( "open" );
select.val( "" );
setTimeout(function() {
input.tooltip( "close" ).attr( "title", "" );
}, 2500 );
input.data( "autocomplete" ).term = "";
return false;
}
}
input = $( "<input>" )
.appendTo( wrapper )
.val( value )
.attr( "title", "" )
.addClass( "ui-combobox-input" )
.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;
that._trigger( "selected", event, {
item: ui.item.option
});
},
change: function( event, ui ) {
if ( !ui.item )
return removeIfInvalid( this );
}
})
.addClass( "ui-widget ui-widget-content ui-corner-left" );
input.data( "autocomplete" )._renderItem = function( ul, item ) {
return $( "<li>" )
.data( "item.autocomplete", item )
.append( "<a>" + item.label + "</a>" )
.appendTo( ul );
};
$( "<a>" )
.attr( "tabIndex", -1 )
//.attr( "title", "Show All Items" )
.tooltip()
.appendTo( wrapper )
.button({
icons: {
primary: "ui-icon-triangle-1-s"
},
text: false
})
.removeClass( "ui-corner-all" )
.addClass( "ui-corner-right ui-combobox-toggle" )
.click(function() {
// close if already visible
if ( input.autocomplete( "widget" ).is( ":visible" ) ) {
input.autocomplete( "close" );
removeIfInvalid( input );
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.wrapper.remove();
this.element.show();
$.Widget.prototype.destroy.call( this );
}
});
})( jQuery );
$(function() {
$( "#driver_uuidHOS" ).combobox();
});
</script>
And I have declared two variables:-
<script src="js/new/jquery-1.8.3.js"></script>
<script>
var jq13 = jQuery.noConflict(true);
</script>
<script src="js/new/jquery-ui.js"></script>
<script>
var jq131 = jQuery.noConflict(true);
</script>
So please tell me where I have to use jq13 and where jq131 in my code. This code is for searchable autosuggest.
Thanks in advance.
After you load the first version, you can assign it to a variable.
var jq13 = jQuery.noConflict(true); // as you did
And then load your second jQuery version. The first one you load can be accessed with jq13(...) while the second one can be accessed with $(...).
No need for assgning variable to second script...
You want to load one version of jQuery, then all the plugins for that version, then turn on no conflict mode. You can repeat this process as many times as you'd like (once for each version of jQuery core that you need to load).
So, for your specific case what you want to do is:
<script src="js/new/jquery-1.8.3.js"></script>
<script src="js/new/jquery-ui.js"></script>
<script src="path/to/your/code.js"></script>
<script>jQuery.noConflict(true);</script>
The path/to/your/code.js refers to the block of code you have above which defines the combobox widget. In terms of supporting multiple jQuery version, it doesn't matter if this is included in-page as your example does, or as an external file as my example does. The anonymous function wrapper that you have (and all plugins should have), which stores the reference to jQuery is what makes this work. At the time those files are executed, jQuery points to the correct version, and the files stores a local reference to it as $. Later, when you can jQuery.noConflict(true), those files continue to hold their references, even though the global jQuery variable has changed. If you follow this pattern of invoking no conflict mode after loading all other files, you don't need to assign jQuery to a new variable, since all of your code will already have the necessary references. The benefit to this approach, is that you never end up with variable-specific names in your wrapper functions, and it's guaranteed to work with all existing plugins that were developed with this model, which is all official jQuery projects and likely any plugin that has thought about no conflict support.
One last thing: At the bottom of your script, you're referring to jQuery as $, but you're outside of the function wrapper that is storing the $ reference. If this is really two separate files in your app, make sure to include the wrapper in each file. If this is actually a single script as shown above, make sure to move the document ready block inside the wrapper.
I run into a problem with jQuery UI - Autocomplete and IE8.
I'm using combobox method which you can find on jQuery UI website - here
Basically, it is creating autocomplete input + select menu from select/option list.
I'm using jQuery 1.6.4 and jQuery UI 1.8.16; both from google server.
It is working perfectly on Chrome / FF / Opera, but does not work on IE8.
On IE8 - once you select something (after typing), or use dropdown button IE will reload the page. Please not that IE will not crash till you use arrows or try to select something.
res://ieframe.dll/acr_error.htm#, in the URL, in front of the actual path
or a message this tab has been reloaded; a problem with the page causes IE to close and reopen the page
Live example here
Any idea what is causing IE to act like that? Any suggestion much appreciated.
jQuery code:
<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({
text: false
})
.removeClass( "ui-corner-all" )
.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 );
$(document).ready( function() {
$("#combobox").combobox();
});
</script>
I'm still trying to work out why IE8 is crashing but it does work for me when you add a jQueryUI theme to the page, for example:
<link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/themes/cupertino/jquery-ui.css">
Edit: I think I know which line it is crashing on, but I still do not know why! In the jQueryUI code activate: function( event, item ) {
is the following code which adds style and an attribute to the active item.
this.active = item.eq(0)
.children("a")
.addClass("ui-state-hover")
.attr("id", "ui-active-menuitem")
.end();
For some reason, IE8 crashes here, although for me sometimes does not crash when I remove the .addClass and .attr lines.
Edit 2: OK, for some reason IE is crashing with your .ui-autocomplete style. If you change overflow:scroll; to overflow:auto; then IE8 does not crash. Alternatively change max-height to just height, which also fixes it. Guess it's a bug in IE either with max-height (maybe IE8 overflow:auto with max-height) or overflow.
From the first glance this line look strange to me:
if ( this.value && ( !request.term || matcher.test(text) ) )
return {
But its working fine for me in ie8, in ie7 its not working at all.
Try if(){return{...}}.
quick look finds your script tag is missing required type attribute
<script type="text/javascript">
I reproduced the issue, copied the file local with no CSS and no fails.
Odd, IF on the original page, I disable CSS using the IE developer tools, it does not crash.