The single value autocomplete is working fine (thanks to people who helped me with it.) but when I tried the jQuery UI's multiple value example, it is not getting the source I need.
This is my controller.
def courseList = {
def cList = Course.withCriteria {
ilike 'course', params.term +'%'
}
render (cList.'course' as JSON)
}
This is my _form view.
<div class="fieldcontain ${hasErrors(bean: studentInstance, field: 'courses', 'error')} required" >
<label for="course">
<g:message code="student.courses.label" default="Courses" />
<span class="required-indicator">*</span>
</label>
<g:textField name="course" id="coursetags" required="" value="${course?.course}"/>
This is my jQuery script (exactly from jQuery UI demo).
function split( val ) {
return val.split( /,\s*/ );
}
function extractLast( term ) {
return split( term ).pop();
}
var courses = ["English", "Music", "Science"];
$( "#coursetags" )
// don't navigate away from the field on tab when selecting an item
.bind( "keydown", function( event ) {
if ( event.keyCode === $.ui.keyCode.TAB && $( this ).autocomplete( "instance" ).menu.active ) {
event.preventDefault();
}
})
.autocomplete({
minLength: 2,
source: function( request, response ) {
// delegate back to autocomplete, but extract the last term
response( $.ui.autocomplete.filter( courses, extractLast( request.term ) ) );
},
focus: function() {
// prevent value inserted on focus
return false;
},
select: function( event, ui ) {
var terms = split( this.value );
// remove the current input
terms.pop();
// add the selected item
terms.push( ui.item.value );
// add placeholder to get the comma-and-space at the end
terms.push( "" );
this.value = terms.join( ", " );
return false;
}
});
When I have var courses tag inside the script, the multiple-values-autocomplete works. How would I connect autocomplete's source to my controller?
For the single value, this is what I had in my script.
$("#coursetags").autocomplete({
source: "/myApp/student/courseList",
minLength: 2
});
Thank you in advance.
I found this demo. https://github.com/jquery/jquery-ui/blob/master/demos/autocomplete/multiple-remote.html
source: function( request, response ) {
$.getJSON( "/myApp/student/courseList",
{term: extractLast( request.term )},
response );},
I replaced source part and it works now.
Related
This is What I have :
I have a text box input element as below for loading cities autoloaded and a hidden field to list its ids:
<label class="col-sm-2 control-label" for="city_disp"> City</label>
<div class="col-sm-5">
<div class="input-group">
<input type="hidden" class="hidden_value" name="city" id="city" value="" />
<input type="text" name="city_disp" placeholder="City"
id="city_disp" data-request_type="cities" value=""
class="form-control autocomplete-input-field" autocomplete="off" />
</div>
</div>
jQuery UI AutoComplete which I use, the data array comes from Ajax response :
function split( val ) {
return val.split( /,\s*/ );
}
function extractLast( term ) {
return split( term ).pop();
}
$(".autocomplete-input-field").autocomplete({
source: function (request, response) {
$this = this.element;
var term = extractLast(request.term);
$.ajax({
url: myHome+'/my_ajax',
dataType: "json",
type: "POST",
data: {
term: term,
action_type: "getdata"
},
success: function (data) {
response(data);
}
});
},
minLength: 2,
select: function (event, ui) {
var tempval = $(this).val() ;
var terms = split( this.value );
var split_string = split(
$(this).closest('div').find('.hidden_value').val() );
split_string.pop();
terms.pop();
terms.push( ui.item.label );
split_string.push( ui.item.value );
terms.push( "" );
split_string.push( "" );
var labels = terms.join( ", " );
var new_vals = split_string.join( "," );
$(this).val(labels);
$(this).closest('div').find('.hidden_value').val(new_vals);
return false;
},
focus: function (event, ui) {
event.preventDefault();
}
});
Output I am getting currently:
Currently,autocomplete is working fine when I type atleast 2 characters in the text box name="city_disp" . If user selects 3 values from the autocomplete cities list: 'New York,Washington,London' and the ids corresponding to these cities '45,56,78' gets appended to the hidden html input field name="city".
Modification which I am trying to implement :
Suppose if user selects 'New York,Washington,London' and its id gets '45,56,78' gets appended to the hidden html input field name="city". and the user removes a Washington from the selected values . Then the hidden value must also change accordingly to '45,78'. Also when a user omits Washington to some absurd characters like 'dasdsad' ,then how to handle such situations with this jQuery UI AutoComplete?
There is not a good way to do this with two unique lists of text. there becomes no relationship between the two except for the positioning. When the User removes and item from List A, how do you identify in List B the change, and align the lists.
Consider moving the selected items to a new User interface with the ID attached.
Example: https://jsfiddle.net/Twisty/m3vfk0hg/
HTML
<label class="col-sm-2 control-label" for="city_disp"> City</label>
<div class="col-sm-5">
<div class="input-group">
<input type="hidden" class="hidden_value" name="city" id="city" />
<input type="text" name="city_disp" placeholder="City" id="city_disp" data-request_type="cities" class="form-control autocomplete-input-field" autocomplete="off" />
</div>
<div class="selected"></div>
</div>
Mostly the same HTML, yet now we have a section to display the Selected items, after they have been selected.
CSS
.selected {
margin: 3px;
}
.selected-item {
border: 1px solid #00f;
border-radius: 6px;
padding: 3px;
background: #ccf;
margin: 3px;
}
.selected-item .btn-close {
margin-left: 6px;
}
Giving us some Style.
JavaScript
$(function() {
var myAutoData = [{
label: "New York",
value: "45"
}, {
label: "Washington",
value: "56"
},
{
label: "London",
value: "78"
}
];
function newItem(it) {
var item = $("<span>", {
class: "selected-item",
"data-id": it.value
}).html(it.label);
$("<span>", {
class: "btn-close"
}).appendTo(item);
if ($("#city").val().length > 0) {
$("#city").val($("#city").val() + "," + it.value);
} else {
$("#city").val(it.value);
}
return item;
}
$(".autocomplete-input-field").autocomplete({
source: function(request, response) {
var term = request.term;
$.ajax({
url: "/echo/json/",
dataType: "json",
type: "POST",
data: {
json: JSON.stringify(myAutoData),
term: term
},
success: function(data) {
response(data);
}
});
},
minLength: 2,
select: function(event, ui) {
$(this).parent().parent().find(".selected").append(newItem(ui.item));
$(this).val("");
return false;
},
focus: function(event, ui) {
event.preventDefault();
}
});
$(".selected").on("click", ".btn-close", function() {
var id = $(this).parent().data("id");
$(this).parent().remove();
var sel = $("#city").val().split(",");
sel = sel.splice(sel.indexOf(id), 1);
$("#city").val(sel.join(","));
});
});
The example uses the JSFiddle options to Echo back JSON data Posted to it. You will want to use your own url and data. I also setup some basinc exmaple items based on your post.
When the User types in a option, wash, they get options they can select. When they click on a selection a new item is created.
<span class="selected-item" data-id="56">Washington<span class="btn-close"></span></span>
This element is appended to the .selected element. This help prevent the user from entering dasdsad, this would return no results, and they cannot select anything.
If the User decides to remove a previously selected item, they click the x and it is removed. Behind the scene, as they make selections, the value of #city is updated to a list of IDs, 56,45. When the User removes an item, the list is updated, and that entry is removed. This is done by converting the list into an Array and using Splice to remove the matching element.
I have a dialog box that pops up after hitting an Add button. There are 2 fields, MR ID and Supplier ID. MR ID is a dropdown and shouldn't need any sort of validation. The supplier id is a text input and needs validation. It needs to be numbers only and there also can be no 2 supplier ids that are the same. They must all be unique. The code I have so far does not work in validating the supplier id.
HTML/PHP for dialog box:
<div id="dialog-form" title="Add Supplier ID">
<p class="validateTips">All form fields are required.</p>
<!-- Dialog box displayed after add row button is clicked -->
<form>
<fieldset>
<label for="mr_id">MR_ID</label>
<select name="mr_id" id="mr_id_dialog" class="text ui-widget-content ui-corner-all" value="300">
<?php foreach($user->fetchAll() as $user1) { ?>
<option>
<?php echo $user1['MR_ID'];?>
</option>
<?php } ?>
</select><br><br>
<label for="supplier_id">Supplier ID</label>
<input type="text" name="supp_id" id="supplier_id" class="text ui-widget-content ui-corner-all" value="99">
<!-- Allow form submission with keyboard without duplicating the dialog button -->
<input type="submit" id="submit" tabindex="-1" style="position:absolute; top:-1000px">
</fieldset>
</form>
</div>
JavaScript:
// ----- Dialog Box for adding supplier id -----
$(document).ready( function() {
$("#insertButton").on('click', function(e){
e.preventDefault();
});
var dialog, form,
mr_id_dialog = $( "#mr_id_dialog" ),
supplier_id = $( "#supplier_id" ),
allFields = $( [] ).add( mr_id_dialog ).add( supplier_id ),
tips = $( ".validateTips" );
function updateTips( t ) {
tips
.text( t )
.addClass( "ui-state-highlight" );
setTimeout(function() {
tips.removeClass( "ui-state-highlight", 1500 );
}, 500 );
}
function checkRegexp( o, regexp, n ) {
if ( !( regexp.test( o.val() ) ) ) {
o.addClass( "ui-state-error" );
updateTips( n );
return false;
} else {
return true;
}
}
function addVendor() {
var valid = true;
allFields.removeClass( "ui-state-error" );
// ----- Validation for each input in add row dialog box -----
//valid = valid && checkRegexp( mr_id_dialog, /^(0|[1-9][0-9]*)$/, "Please enter a valid MR ID" );
valid = valid && checkRegexp( supplier_id, /^(0|[1-9][0-9]*)$/g, "Please enter a valid Supplier ID" );
if ( valid ) {
var $tr = $( "#index_table tbody tr" ).eq(0).clone();
var dict = {};
var errors = "";
$.each(allFields, function(){
$tr.find('.' + $(this).attr('id')).html( $(this).val()+"-"+supplier_id );
var type = $(this).attr('id');
var value = $(this).val();
// ----- Switch statement that provides validation for each table cell -----
switch (type) {
case "mr_id_dialog":
dict["MR_ID"] = value;
break;
case "supplier_id":
dict["Supp_ID"] = value;
break;
}
});
$( "#index_table tbody" ).append($tr);
dialog.dialog( "close" );
}
}
var dialog = $( "#dialog-form" ).dialog({
autoOpen: false,
height: 400,
width: 350,
modal: true,
buttons: {
"Add Supplier ID": addVendor,
Cancel: function() {
dialog.dialog( "close" );
}
},
close: function() {
form[ 0 ].reset();
allFields.removeClass( "ui-state-error" );
}
});
form = dialog.find( "form" ).on( "submit", function( event ) {
event.preventDefault();
addVendor();
});
$( "#insertButton" ).button().on( "click", function() {
dialog.dialog({
position: ['center', 'top'],
show: 'blind',
hide: 'blind'
});
dialog.dialog("open");
});
});
Samples that should pass:
349348
2
1234
Samples that should not pass:
01234
123 45 67
No hyphens, dashes, etc. Numbers only.
My jQuery UI Autocomplete suddenly stopped working. Apparently my table size is too big, because when I limit the available records to 2040 or any number beneath that, it works perfectly, but breaks then I limit it to 2041 or any number above that.
Here's the full code that doesn't work:
<head>
<meta charset="utf-8">
<title>jQuery UI Autocomplete - Multiple values</title>
<link rel="stylesheet" href="//code.jquery.com/ui/1.11.1/themes/smoothness/jquery-ui.css">
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script src="//code.jquery.com/ui/1.11.1/jquery-ui.js"></script>
<link rel="stylesheet" href="/resources/demos/style.css">
<script>
$(function() {
var availableTags = [
<%= raw(Page.pluck(:name).map { |name| "\"#{name}\"" }.join(",\n")) %>
];
function split( val ) {
return val.split( /,\s*/ );
}
function extractLast( term ) {
return split( term ).pop();
}
$( "#pages" )
// don't navigate away from the field on tab when selecting an item
.bind( "keydown", function( event ) {
if ( event.keyCode === $.ui.keyCode.TAB &&
$( this ).autocomplete( "instance" ).menu.active ) {
event.preventDefault();
}
})
.autocomplete({
minLength: 0,
source: function( request, response ) {
// delegate back to autocomplete, but extract the last term
response( $.ui.autocomplete.filter(
availableTags, extractLast( request.term ) ) );
},
focus: function() {
// prevent value inserted on focus
return false;
},
select: function( event, ui ) {
var terms = split( this.value );
// remove the current input
terms.pop();
// add the selected item
terms.push( ui.item.value );
// add placeholder to get the comma-and-space at the end
terms.push( "" );
this.value = terms.join( ", " );
return false;
}
});
});
</script>
</head>
<div class="ui-widget">
<textarea id="pages" name="pages" size="50"></textarea>
</div><br>
And here's an example of code that does work:
<head>
<meta charset="utf-8">
<title>jQuery UI Autocomplete - Multiple values</title>
<link rel="stylesheet" href="//code.jquery.com/ui/1.11.1/themes/smoothness/jquery-ui.css">
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script src="//code.jquery.com/ui/1.11.1/jquery-ui.js"></script>
<link rel="stylesheet" href="/resources/demos/style.css">
<script>
$(function() {
var availableTags = [
<%= raw(Page.limit(2040).pluck(:name).map { |name| "\"#{name}\"" }.join(",\n")) %>
];
function split( val ) {
return val.split( /,\s*/ );
}
function extractLast( term ) {
return split( term ).pop();
}
$( "#pages" )
// don't navigate away from the field on tab when selecting an item
.bind( "keydown", function( event ) {
if ( event.keyCode === $.ui.keyCode.TAB &&
$( this ).autocomplete( "instance" ).menu.active ) {
event.preventDefault();
}
})
.autocomplete({
minLength: 0,
source: function( request, response ) {
// delegate back to autocomplete, but extract the last term
response( $.ui.autocomplete.filter(
availableTags, extractLast( request.term ) ) );
},
focus: function() {
// prevent value inserted on focus
return false;
},
select: function( event, ui ) {
var terms = split( this.value );
// remove the current input
terms.pop();
// add the selected item
terms.push( ui.item.value );
// add placeholder to get the comma-and-space at the end
terms.push( "" );
this.value = terms.join( ", " );
return false;
}
});
});
</script>
</head>
<div class="ui-widget">
<textarea id="pages" name="pages" size="50"></textarea>
</div><br>
Why does the table size matter? Can I change the limit somehow?
IMO, the limit here is not from the jquery, but from the string that you have interpolate:
Page.limit(2040).pluck(:name).map { |name| "\"#{name}\"" }.join(",\n")
IIRC, the max length of a string in ruby is 65535 characters, so let say the average length of name is about 30 characters, 2040 is the limit it could reach.
Solution: You could try a loop and interpolate each name instead to see if it works.
let u as consider the value am having in textbox so now if we type in that it automatically
have to show word with multi-value by comma. I have tried but no result.
Can any body help out of this problem.
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<script>
$(function()
{
var val = document.getElementById('tags').value;
var availableTags = val == '' : [] ? val.split(',');
function split( val ) {
return val.split( /,\s*/ );
}
function extractLast( term ) {
return split( term ).pop();
}
$( "#tags" )
// don't navigate away from the field on tab when selecting an item
.bind( "keydown", function( event ) {
if ( event.keyCode === $.ui.keyCode.TAB &&
$( this ).data( "ui-autocomplete" ).menu.active ) {
event.preventDefault();
}
})
.autocomplete({
minLength: 0,
source: function( request, response ) {
// delegate back to autocomplete, but extract the last term
response( $.ui.autocomplete.filter(
availableTags, extractLast( request.term ) ) );
},
focus: function() {
// prevent value inserted on focus
return false;
},
select: function( event, ui ) {
var terms = split( this.value );
// remove the current input
terms.pop();
// add the selected item
terms.push( ui.item.value );
// add placeholder to get the comma-and-space at the end
terms.push( "" );
this.value = terms.join( ", " );
return false;
}
});
});
</script>
</head>
<body>
<div class="ui-widget">
<label for="tags">Tag programming languages: </label>
<input id="tags" size="25" value="ACCENTURE 1,
BPCL KORAMANGALA,
CUNNIGHAM ROAD,
HM TOWERS,
GREATER NOIDA,
INFOSYS 3,
JAYANAGAR T BLOCK,
MILLENIA,
OZONE,
BKC,
FUN REPUBLIC,
MATUNGA,
VFS UK,
CYBER GREEN,
PRABHADEVI,
VRINDAVAN"/>
</div>
As per my understanding, your autocomplete(which I have tested in fiddle) is not populating. The reason is you ternary operator syntax is wrong.
var availableTags = val == '' : [] ? val.split(','); //WRONG
Change this to
var availableTags = val == '' ? [] : val.split(','); //CORRECT
See it is working in JSFiddle
I placed all code below. My page works like that
Page's first scene
When i choose something from #menu it fires $("#menu").change(function () function and i'm getting scene like that
Radio buttons .parentcheck are located in div #options. They're like turn off (first one)/on (second one) select-box #parent.
When i turn #parentselectbox on, it fires genopts- ajax request and on success it transforms select-box into jquery-ui autocomplete combobox and places default value.
Now, the problem is following
I'm using input.val( $("#parent option:selected").text()); (in combobox configuration) to place default value. The problem is i want to remove this text onclick (something like html5 placeholder but i want crossbrowser support). How to modify the combobox configuration part to fix that problem?
HTML Markup
<table>
<tr>
<td><label for="menu" id="menu_label">Səhifə harada yerləşəcək?</label>
<select name="menu" id="menu">
<option value="" selected="selected">Birini seçin...</option>
<option value="1">Header menyuya əlavə et</option>
<option value="2">Footer menyuya əlavə et</option>
<option value="0">Bu səhhifənin menyuda adı olmayacaq</option>
</select></td>
<td><div id="options">
<input type="radio" class="parentcheck" name="parentcheck" value="0"/>
Ayrıca yoxsa
<input type="radio" class="parentcheck" name="parentcheck" value="1"/>
hansısa başlıq altında? </div>
<select name="parent" id="parent">
</select></td>
</tr>
</table>
The combobox configuration
(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.val( $("#parent option:selected").text());
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 );
1st problem answer:
http://forum.jquery.com/topic/disable-autocomplete
2nd problem answer:
You can put this text to the title attribute of the your input and then on focus check your value if it's the same as in title. Change your input.val( $("#parent option:selected").text()); to:
var emptyText = $("#parent option:selected").text();
input.attr('title', emptyText).val(emptyText);
input.focus(function() {
var $this = $(this);
if ($this.val() == $this.attr('title')) {
$this.val('');
}
});
input.blur(function() {
var $this = $(this);
if ($this.val() == '')
$this.val($this.attr('title'));
});