JQuery UI Autocomplete and hidden field - jquery-ui

I have implemented the JQuery UI Autocomplete widgets in my form so when the user selects an item from the autocomplete, a hidden field is populated with the id and the textbox with the user friendly text.
I have also implemented a remote validation so if the user after selecting an item from the list (hidden field already set) decides to delete or change the text it will fail and force the user to select an item again.
I do want to allow the user to delete the field so if all content of the textbox is deleted I want to reset the hidden field, but I don't know how to do this...
Thanks in advance.

Typically, you can catch certain events on the input field that is the Autocomplete widget. The main ones would be blur where the input field loses focus and or keyup where someone has hit enter inside the input field (maybe trying to submit the form).
The following example shows how a "hidden" field could be updated in these two scenarios:
$(function() {
var availableTags = [
"ActionScript",
"AppleScript",
"Asp",
"BASIC",
"C",
"C++",
"Clojure",
"COBOL",
"ColdFusion",
"Erlang",
"Fortran",
"Groovy",
"Haskell",
"Java",
"JavaScript",
"Lisp",
"Perl",
"PHP",
"Python",
"Ruby",
"Scala",
"Scheme"
];
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 ).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( ", " );
$("#hiddenField").val(terms.join( ", "));
return false;
}
});
});
$("#tags").blur(function() {
$("#hiddenField").val(this.value);
});
$("#tags").keyup(function (e) {
if (e.keyCode == 13) {
$("#hiddenField").val(this.value);
}
});
.hiddenFields {
margin-bottom: 30px;
}
.hiddenF {
color: gray;
}
.hiddenI {
color: gray;
border: 1px dotted gray;
opacity: 50%;
}
<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>
<div class="hiddenFields">
<label for="hiddenField" class="hiddenF">Hidden Field: </label>
<input id="hiddenField" class="hiddenI" size="50" readonly/>
</div>
<div class="ui-widget">
<label for="tags">Tag programming languages: </label>
<input id="tags" size="50">
</div>

Related

Lack of selecting capacity with if statement / append method

I want to propose an autocomplete list (jquery ui 1.8) with some words in bold font.
The JSON source looks like :
{"especes":[{"fk_sp":number,"nom_espece":name,"nom_valide":0 or 1}].
My script is like that :
$(function(){
$('#id').autocomplete({
source: function(request, response) {
$.getJSON("fichier.php", {
term: request.term
}, function(data) {
var array = data.error ? [] : $.map(data.especes, function(m) {
return {
label: m.nom_espece,
value: m.fk_sp,
valid: m.nom_valide
};
});
response(array);
});
},
select: function (event, ui) {
$("#espece").val(ui.item.label);
$("#fk_sp").val(ui.item.value);
}
}).data( "ui-autocomplete" )._renderItem = function( ul, item ) {
return $( "<li></li>" )
.data( "item.autocomplete", item )
.append( item.valid == '1' ? "<b>" + item.label + "</b>" : item.label)
.appendTo( ul );
};
});
If I use :
.data( "ui-autocomplete" ) => I have the good selectable list without the bold lines,
.data( "ui-Autocomplete" ) ou .data( "uiAutocomplete" ) => nothing works,
and if I juste write ._renderItem without .data( "ui-autocomplete" ) => I have a pretty list with the good names in bold, but I can't select any name of the list !
I don't find where is my error (I suppose it is somwhere with the "select :" part).

Angular ui grid disable sorting after cell edit

For display tabular data , I am using angular ui-grid
if a column is sorted and then if we edit the cell, the sorting gets kicked in and moves the row. I would like to disable sorting on cell edit, is there any way to do this?
Plnkr http://plnkr.co/edit/17H5K6nOEz9gf4Keeap9?p=preview
<div id="grid1" ui-grid="gridOptions" class="grid" ui-grid-edit >
</div>
var app = angular.module('app', ['ngAnimate', 'ngTouch', 'ui.grid','ui.grid.edit',
'ui.grid.selection',
'ui.grid.rowEdit', 'ui.grid.cellNav']);
app.controller('MainCtrl', function($scope) {
$scope.gridOptions = {
enableSorting: true,
columnDefs: [
{ field: 'A' },
{ field: 'B' },
{ field: 'C', enableSorting: false }
],
onRegisterApi: function( gridApi ) {
$scope.gridApi = gridApi;
}
};
$scope.gridOptions.data = [{'A':'a1', 'B':'b1', 'C':'c1'}, {'A':'a3', 'B':'b3', 'C':'c3'}, {'A':'a2', 'B':'b2', 'C':'c2'}];
});

Select2 v4.0 make optgroups selectable

I'm using the latest version of select2 (4.0.0) and I can't find the option to make optgroups selectable.
An optgroup is used to group different options of the dropdown, as shown in their basic examples:
I need this optgoup to be selectable too! It was possible in 3.5.1 but it isn't the default setting in 4.0.0 anymore.
My Code Looks like this:
$(document).ready(function() {
$('#countrySelect').select2({
data: [{
text: "group",
"id": 1,
children: [{
"text": "Test 2",
"id": "2"
}, {
"text": "Test 3",
"id": "3",
"selected": true
}]
}]
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://select2.github.io/dist/js/select2.full.js"></script>
<link href="https://select2.github.io/dist/css/select2.min.css" rel="stylesheet" />
<select id="countrySelect" style="width: 380px;" placeholder="Select regions..."></select>
I manage to achieve this by using the templateResult property and attaching click events to the optgroups in this way:
$('#my-select').select2({
templateResult: function(item) {
if(typeof item.children != 'undefined') {
var s = $(item.element).find('option').length - $(item.element).find('option:selected').length;
// My optgroup element
var el = $('<span class="my_select2_optgroup'+(s ? '' : ' my_select2_optgroup_selected')+'">'+item.text+'</span>');
// Click event
el.click(function() {
// Select all optgroup child if there aren't, else deselect all
$('#my-select').find('optgroup[label="' + $(this).text() + '"] option').prop(
'selected',
$(item.element).find('option').length - $(item.element).find('option:selected').length
);
// Trigger change event + close dropdown
$('#my-select').change();
$('#my-select').select2('close');
});
// Hover events to properly manage display
el.mouseover(function() {
$('li.select2-results__option--highlighted').removeClass('select2-results__option--highlighted');
});
el.hover(function() {
el.addClass('my_select2_optgroup_hovered');
}, function() {
el.removeClass('my_select2_optgroup_hovered');
});
return el;
}
return item.text;
}
});
And the associated css:
.my_select2_optgroup_selected {
background-color: #ddd;
}
.my_select2_optgroup_hovered {
color: #FFF;
background-color: #5897fb !important;
cursor: pointer;
}
strong.select2-results__group {
padding: 0 !important;
}
.my_select2_optgroup {
display: block;
padding: 6px;
}
This was requested over on GitHub, but realistically it is not actually possible. It was previously possible with a <input />, but the switch to a <select> meant that we now explicitly disallow a selectable <optgroup>.
There is a technical barrier here that Select2 will likely never be able to tackle: A standard <optgroup> is not selectable in the browser. And because a data object with children is converted to an <optgroup> with a set of nested <option> elements, the problem applies in your case with the same issue.
The best possible solution is to have an <option> for selecting the group, like you would have with a standard select. Without an <option> tag, it's not possible to set the selected value to the group (as the value doesn't actually exist). Select2 even has a templateResult option (formatResult in 3.x) so you can style it as a group consistently across browsers.
Well, I came across this issue and I found that every time the select2 (Select2 4.0.5) opens it adds a span element before the closing body element. In addition, inside the span element adds a ul with the id: select2-X-results, where X is the select2 id.
So I found the following workaround (jsfiddle):
var countries = [{
"id": 1,
"text": "Greece",
"children": [{
"id": "Athens",
"text": "Athens"
}, {
"id": "Thessalonica",
"text": "Thessalonica"
}]
}, {
"id": 2,
"text": "Italy",
"children": [{
"id": "Milan",
"text": "Milan"
}, {
"id": "Rome",
"text": "Rome"
}]
}];
$('#selectcountry').select2({
placeholder: "Please select cities",
allowClear: true,
width: '100%',
data: countries
});
$('#selectcountry').on('select2:open', function(e) {
$('#select2-selectcountry-results').on('click', function(event) {
event.stopPropagation();
var data = $(event.target).html();
var selectedOptionGroup = data.toString().trim();
var groupchildren = [];
for (var i = 0; i < countries.length; i++) {
if (selectedOptionGroup.toString() === countries[i].text.toString()) {
for (var j = 0; j < countries[i].children.length; j++) {
groupchildren.push(countries[i].children[j].id);
}
}
}
var options = [];
options = $('#selectcountry').val();
if (options === null || options === '') {
options = [];
}
for (var i = 0; i < groupchildren.length; i++) {
var count = 0;
for (var j = 0; j < options.length; j++) {
if (options[j].toString() === groupchildren[i].toString()) {
count++;
break;
}
}
if (count === 0) {
options.push(groupchildren[i].toString());
}
}
$('#selectcountry').val(options);
$('#selectcountry').trigger('change'); // Notify any JS components that the value changed
$('#selectcountry').select2('close');
});
});
li.select2-results__option strong.select2-results__group:hover {
background-color: #ddd;
cursor: pointer;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.5/css/select2.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.5/js/select2.full.min.js"></script>
<h1>Selectable optgroup using select2</h1>
<select id="selectcountry" name="country[]" class="form-control" multiple style="width: 100%"></select>
Had the same problem today. This is certainly not my nicest solution, but beggars can't be choosers:
$(document).on('click', '.select2-results__group', function(event) {
let select2El = $('#mySelect2');
var setValues = [];
//Add existing Selection
var selectedValues = select2El.select2('data');
for ( var i = 0, l = selectedValues.length; i < l; i++ ) {
setValues.push(selectedValues[i].id);
}
//Add Group Selection
$(this).next('ul').find('li').each(function(){
let pieces = $(this).attr('data-select2-id').split('-');
setValues.push(pieces[pieces.length-1]);
});
select2El.val(setValues).trigger('change').select2("close");
});
$(document).ready(function() {
$('#countrySelect').select2({
data: [{
text: "group",
"id": 1,
children: [{
"text": "Test 2",
"id": "2"
}, {
"text": "Test 3",
"id": "3",
"selected": true
}]
}]
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://select2.github.io/dist/js/select2.full.js"></script>
<link href="https://select2.github.io/dist/css/select2.min.css" rel="stylesheet" />
<select id="countrySelect" style="width: 380px;" placeholder="Select regions..."></select>

How to make jQuery UI Tooltip stay on, on hover

Does anybody know how can I make jQuery UI tooltip to stay visible on hover. That is- I want it to stay visible when I move mouse from p element to tooltip.
Have tried on fiddle, but it seems there's a problem with :hover.
$("p").tooltip({
hide: {
effect: 'explode'
}
}).mouseleave(function () {
if ($('p').is(':hover')) {
ui.tooltip.preventDefault();
$('p').tooltip('open');
}
}).focusout(function () {
$('p').tooltip('close');
});
jsFiddle
That was a little tricky...
This script extends the standard jQuery UI 1.12.1, so that you get two extra options, allowing you to keep the tooltip open, while hover (the mouse stays on) it.
(function($) {
var uiTooltipTmp = {
options: {
hoverTimeout: 200,
tooltipHover: false // to have a regular behaviour by default. Use true to keep the tooltip while hovering it
},
// This function will check every "hoverTimeout" if the original object or it's tooltip is hovered. If not, it will continue the standard tooltip closure procedure.
timeoutHover: function (event,target,tooltipData,obj){
var TO;
var hov=false, hov2=false;
if(target !== undefined) {
if(target.is(":hover")){
hov=true;}
}
if(tooltipData !== undefined) {
if($(tooltipData.tooltip).is(":hover")){
hov=true;}
}
if(target !== undefined || tooltipData !== undefined) {hov2=true;}
if(hov) {
TO = setTimeout(obj.timeoutHover,obj.options.hoverTimeout,event,target,tooltipData,obj);
}else{
target.data('hoverFinished',1);
clearTimeout(TO);
if(hov2){
obj.closing = false;
obj.close(event,true);}
}
},
// Changed standard procedure
close: function(event) {
var tooltip,
that = this,
target = $( event ? event.currentTarget : this.element ),
tooltipData = this._find( target );
if(that.options.tooltipHover && (target.data('hoverFinished')===undefined || target.data('hoverFinished') === 0)){
target.data('hoverFinished',0);
setTimeout(that.timeoutHover, that.options.hoverTimeout,event, target, tooltipData, that);
}
else
{
if(that.options.tooltipHover){
target.data('hoverFinished',0);}
// The rest part of standard code is unchanged
if ( !tooltipData ) {
target.removeData( "ui-tooltip-open" );
return;
}
tooltip = tooltipData.tooltip;
if ( tooltipData.closing ) {
return;
}
clearInterval( this.delayedShow );
if ( target.data( "ui-tooltip-title" ) && !target.attr( "title" ) ) {
target.attr( "title", target.data( "ui-tooltip-title" ) );
}
this._removeDescribedBy( target );
tooltipData.hiding = true;
tooltip.stop( true );
this._hide( tooltip, this.options.hide, function() {
that._removeTooltip( $( this ) );
} );
target.removeData( "ui-tooltip-open" );
this._off( target, "mouseleave focusout keyup" );
if ( target[ 0 ] !== this.element[ 0 ] ) {
this._off( target, "remove" );
}
this._off( this.document, "mousemove" );
if ( event && event.type === "mouseleave" ) {
$.each( this.parents, function( id, parent ) {
$( parent.element ).attr( "title", parent.title );
delete that.parents[ id ];
} );
}
tooltipData.closing = true;
this._trigger( "close", event, { tooltip: tooltip } );
if ( !tooltipData.hiding ) {
tooltipData.closing = false;
}
}
}
};
// Extending ui.tooltip. Changing "close" function and adding two new parameters.
$.widget( "ui.tooltip", $.ui.tooltip, uiTooltipTmp);
})(jQuery);
jQuery(document).ready(function($) {
$("h3").tooltip({hoverTimeout: 250, tooltipHover: true});
});
body {
background-color: #f3f3f3;
}
h3 {
display: inline-block;
margin: 1em 0 0 1em;
padding: 1em;
background-color: #FF7E6B;
color: #fff;
}
<script src="https://code.jquery.com/jquery-3.1.0.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<link href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" rel="stylesheet"/>
<div>
<h3 title="I'll be here while you are hovering me or my creator.">
Hover me</h3>
</div>
$('[data-toggle="popover"]').popover({ trigger: "manual" }).on(
{
mouseenter: function () {
var $this = $(this);
$this.popover("show");
$(".popover").on("mouseleave", function () {
$this.popover('hide');
});
},
mouseleave: function () {
var $this = $(this);
setTimeout(function () {
if (!$(".popover:hover").length) {
$this.popover("hide");
}
}, 350);
}
});
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span type="button" role="button" class="glyphicon glyphicon-question-sign" data-toggle="popover" data-trigger="hover" data-placement="auto" data-html="true" data-content="For instance enter a link here <a href='https://google.com' target='_blank'>Almost know everything</a>"></span>

jQueryUI tooltip Widget to show tooltip on Click

How the new jQueryUI's tooltip widget can be modified to open the tooltip on click event on certain element's on document, while the others are still showing their tootip on mouseover event. In click-open case the tooltip should be closed by clicking somewhere else on the document.
Is this possible at all?
Using jqueryui:
HTML:
<div id="tt" >Test</div>
JS:
$('#tt').on({
"click": function() {
$(this).tooltip({ items: "#tt", content: "Displaying on click"});
$(this).tooltip("open");
},
"mouseout": function() {
$(this).tooltip("disable");
}
});
You can check it using
http://jsfiddle.net/adamovic/A44EB/
Thanks Piradian for helping improve the code.
This code creates a tooltip that stays open until you click outside the tooltip. It works even after you dismiss the tooltip. It's an elaboration of Mladen Adamovic's answer.
Fiddle: http://jsfiddle.net/c6wa4un8/57/
Code:
var id = "#tt";
var $elem = $(id);
$elem.on("mouseenter", function (e) {
e.stopImmediatePropagation();
});
$elem.tooltip({ items: id, content: "Displaying on click"});
$elem.on("click", function (e) {
$elem.tooltip("open");
});
$elem.on("mouseleave", function (e) {
e.stopImmediatePropagation();
});
$(document).mouseup(function (e) {
var container = $(".ui-tooltip");
if (! container.is(e.target) &&
container.has(e.target).length === 0)
{
$elem.tooltip("close");
}
});
This answer is based on working with different classes. When the click event takes place on an element with class 'trigger' the class is changed to 'trigger on' and the mouseenter event is triggered in order to pass it on to jquery ui.
The Mouseout is cancelled in this example to make everything based on click events.
HTML
<p>
<input id="input_box1" />
<button id="trigger1" class="trigger" data-tooltip-id="1" title="bla bla 1">
?</button>
</p>
<p>
<input id="input_box2" />
<button id="trigger2" class="trigger" data-tooltip-id="2" title="bla bla 2">
?</button>
</p>
jQuery
$(document).ready(function(){
$(function () {
//show
$(document).on('click', '.trigger', function () {
$(this).addClass("on");
$(this).tooltip({
items: '.trigger.on',
position: {
my: "left+15 center",
at: "right center",
collision: "flip"
}
});
$(this).trigger('mouseenter');
});
//hide
$(document).on('click', '.trigger.on', function () {
$(this).tooltip('close');
$(this).removeClass("on")
});
//prevent mouseout and other related events from firing their handlers
$(".trigger").on('mouseout', function (e) {
e.stopImmediatePropagation();
});
})
})
http://jsfiddle.net/AK7pv/111/
I have been playing with this issue today, I figured I would share my results...
Using the example from jQueryUI tooltip, custom styling and custom content
I wanted to have a hybrid of these two. I wanted to be able to have a popover and not a tooltip, and the content needed to be custom HTML. So no hover state, but instead a click state.
My JS is like this:
$(function() {
$( document ).tooltip({
items: "input",
content: function() {
return $('.myPopover').html();
},
position: {
my: "center bottom-20",
at: "center top",
using: function( position, feedback ) {
$( this ).css( position );
$( "<div>" )
.addClass( "arrow" )
.addClass( feedback.vertical )
.addClass( feedback.horizontal )
.appendTo( this );
}
}
});
$('.fireTip').click(function () {
if(!$(this).hasClass('open')) {
$('#age').trigger('mouseover');
$(this).addClass('open');
} else {
$('#age').trigger('mouseout');
$(this).removeClass('open');
}
})
});
The first part is more or less a direct copy of the code example from UI site with the addition of items and content in the tooltip block.
My HTML:
<p>
<input class='hidden' id="age" />
Click me ya bastard
</p>
<div class="myPopover hidden">
<h3>Hi Sten this is the div</h3>
</div>
Bacially we trick the hover state when we click the anchor tag (fireTip class), the input tag that holds the tooltip has a mouseover state invoked, thus firing the tooltip and keeping it up as long as we wish... The CSS is on the fiddle...
Anyways, here is a fiddle to see the interaction a bit better:
http://jsfiddle.net/AK7pv/
This version ensures the tooltip stays visible long enough for user to move mouse over tooltip and stays visible until mouseout. Handy for allowing the user to select some text from tooltip.
$(document).on("click", ".tooltip", function() {
$(this).tooltip(
{
items: ".tooltip",
content: function(){
return $(this).data('description');
},
close: function( event, ui ) {
var me = this;
ui.tooltip.hover(
function () {
$(this).stop(true).fadeTo(400, 1);
},
function () {
$(this).fadeOut("400", function(){
$(this).remove();
});
}
);
ui.tooltip.on("remove", function(){
$(me).tooltip("destroy");
});
},
}
);
$(this).tooltip("open");
});
HTML
Test
Sample: http://jsfiddle.net/A44EB/123/
Update Mladen Adamovic answer has one drawback. It work only once. Then tooltip is disabled. To make it work each time the code should be supplement with enabling tool tip on click.
$('#tt').on({
"click": function() {
$(this).tooltip({ items: "#tt", content: "Displaying on click"});
$(this).tooltip("enable"); // this line added
$(this).tooltip("open");
},
"mouseout": function() {
$(this).tooltip("disable");
}
});
jsfiddle
http://jsfiddle.net/bh4ctmuj/225/
This may help.
<!-- HTML -->
Click me to see Tooltip
<!-- Jquery code-->
$('a').tooltip({
disabled: true,
close: function( event, ui ) { $(this).tooltip('disable'); }
});
$('a').on('click', function () {
$(this).tooltip('enable').tooltip('open');
});

Resources