Empêcher les options jQuery autocomplete de se fermer après chaque sélection
j'utilise Jquery UI autocomplete pour plusieurs valeurs sélectionnables. Tout est bon sauf la liste des options ferme après chaque sélection. Je voudrais que les options restent ouvertes jusqu'à ce que l'utilisateur décide qu'ils ont fait des sélections. J'ai examiné la documentation et je ne vois aucun moyen de garder les options ouvertes. Des idées?
<meta charset="utf-8">
<script>
$(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" ).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>
Tag langages de programmation:
13 réponses
Vous pouvez faire quelque chose comme ceci:
définissez d'abord une variable nommée readyToClose
et il faut le false
au début. Et quand vous voulez fermer votre menu sur la sélection suivante, définissez cette variable à la true
. Et nous devrions aussi réimposer le close
méthode de jQuery UI.
ici j'ai réimplémenté le close
méthode de jQuery UI dans votre code, pas dans le fichier source! C'est la même chose que nous faisons pour rendre la liste de manière personnalisée (par ex. http://jqueryui.com/demos/autocomplete/custom-data.html)
var readyToClose = false;
$( "#tags" ).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;
}
}).data( "autocomplete" ).close = function(e){
if(readyToClose)
clearTimeout(this.closing), this.menu.element.is(":visible") && (this.menu.element.hide(), this.menu.deactivate(), this._trigger("close", e));
else
return false;
};
Note: dans les versions plus récentes de jQuery (i.e. 1.9.0), remplacer "autocomplete" par "uiAutocomplete", comme dans:
$("#tags")
.autocomplete({...})
.data("uiAutocomplete").close = ...
je sais que c'est une vieille question qui ne sont plus pertinents pour l'OP, mais par souci d'exhaustivité, une solution plus propre serait d' extend
le widget de saisie semi-automatique et prioritaire _close
, ainsi que extend
ing de l'objet d'événement dans le select
gestionnaire d'événement. Cela vous permet d'effectuer une logique personnalisée pour déterminer si le menu doit être fermé ou non au cas par cas (cas par cas). Voir aussi http://learn.jquery.com/jquery-ui/widget-factory/extending-widgets/
//override the autocomplete widget
jQuery.widget( "ui.autocomplete", jQuery.ui.autocomplete, {
_close: function( event ) {
if(event!== undefined && event.keepOpen===true) {
//trigger new search with current value
this.search( null, event );
return true;
}
//otherwise invoke the original
return this._super( event );
}
});
$('ac').autocomplete(
{
...custom options...
select: function( event, ui ) {
...custom logic...
if(menu should remain open) {
//extend original event with special flag to keep dropdown open
//the o-event continues to be passed through the chain of listeners
//and will end up being processed during _close()
jQuery.extend(event.originalEvent,{keepOpen:true});
//modify value as required
jQuery(this).val(...);
return false; //prevent selected value from being set,
//i.e. keeping modified value above
}
}
}
);
au-dessus jQuery.étendre(événement.originalEvent, {keepOpen: true}); est utilisé pour ajouter un keepOpen
propriété event.originalEvent
. Depuis extend
modifie l'objet original( premier argument), toute utilisation ultérieure du même event.originalEvent
cette propriété disponible. Après avoir lu et traversai le code, il finit par être le même objet qui est référencé par event
dans _close
méthode.
Ce code se cassera si ce changement devait se produire à l'avenir, mais il est beaucoup plus simple à maintenir que l'équivalent de ce que ingredient_15939 a suggéré il y a 18 mois.
l'équipe de jQuery UI pense que c'est une mauvaise pratique UX: http://forum.jquery.com/topic/enhanced-autocomplete-interest-in-getting-this-into-jqueryui#14737000001125152
donc pas de manière intégrée pour l'annuler. Vous pouvez essayer de relancer l'autocomplete après les événements select & close. Et probablement vous devriez mettre en cache le tableau de résultats de sorte qu'aucune nouvelle requête ne soit faite (si C'est en mode Ajax).
N'est pas entré dans les détails cependant - j'ai convaincu mon UI designer que nous n'avons pas besoin de cela pour cette version :)
j'avais besoin de cette même capacité. IMO les auteurs auraient pu facilement nous donner l'option. Ce que j'ai fait, c'est exclure autocomplete du paquet D'UI, et inclure une copie éditée du fichier séparé: jquery.ui.autocomplete.js
(l'obtenir à partir du "développement-bundle\ui" dossier).
j'ai ajouté quelques nouvelles options,closeOnSelect
et updateElement
(les deux booléens par défaut true), comme suit (en haut du fichier):
$.widget("ui.autocomplete", {
options: {
...
closeOnSelect: true, // add this line - controls list closing.
updateElement: true // add this line - controls updating input box.
},
alors cherchez la chaîne":" dans le code (il n'y seront une seule occurrence). Dans cette fonction, remplacez ces dernières lignes:
if ( false !== self._trigger( "select", event, { item: item } ) ) {
self.element.val( item.value );
}
// reset the term after the select event
// this allows custom select handling to work properly
self.term = self.element.val();
self.close( event );
self.selectedItem = item;
Avec ceci:
if (false !== self._trigger("select", event, { item: item })) {
if (self.options.updateElement) {
self.element.val(item.value);
self.term = self.element.val(); // Ensure term string is same.
}
if (self.options.removeOnSelect) { // Remove menu item if option is true.
console.log(ui);
} else {
self.selectedItem = item;
}
if (self.options.closeOnSelect) self.close(event); // Close menu if option is true.
} else { // Returned false.
self.term = self.element.val(); // Ensure term string is same, in case callback changed element value.
}
puis Rechercher string"focus: la fonction" (encore une fois, une seule occurrence). Dans cette fonction, remplacer la ligne:
self.element.val(item.value);
Avec ceci:
if (self.options.updateElement) self.element.val(item.value);
maintenant, quand vous créez l'autocomplete, mettez simplement ces deux options comme vous voulez:
$("#txtsearch").autocomplete({
closeOnSelect: false, // Keep list open when item selected.
updateElement: false, // Don't change the input box contents.
// etc...
Cela fonctionne parfaitement pour moi. Indépendamment de que ce soit jugé "mauvaise pratique D'UI" par les auteurs originaux, les besoins de chacun sont différents et les options devraient être là! :)
vous aurez besoin d'éditer votre fichier javascript jquery-ui. Dans la section autocomplete, remplacer
close:function(a){clearTimeout(this.closing);if(this.menu.element.is(":visible")){this._trigger("close",a);this.menu.element.hide();this.menu.deactivate()}}
close:function(a){clearTimeout(this.closing);if(this.menu.element.is(":visible")){if(this._trigger("close",a)!==false){this.menu.element.hide();this.menu.deactivate()}}}
alors vous devriez être en mesure d'annuler l'événement de fermeture tel que décrit dans la réponse de Shaans.
Pas si bonne solution, mais j'ai réussi de cette façon:
var $input = $('input').autocomplete({
select: function(event, obj) {
var ac_data = $(event.target).data("autocomplete");
ac_data.instaSearch = true;
// Your action
return false;
}
});
$input.data("autocomplete")._close = function( event ) {
if ( this.menu.element.is( ":visible" )) {
this.menu.element.hide();
this.menu.blur();
this.isNewMenu = true;
this._trigger( "close", event );
if (this.instaSearch) {
this.search(this.term);
this.instaSearch = false;
}
}
};
Cette solution a fonctionné pour moi. J'utilisais Autocomplete pour afficher une liste des quatre premières possibilités de caractères pour les noms. Puis si l'utilisateur sélectionne l'un de ceux-ci, alors j'ai Autocomplete afficher les noms associés à la sélection. Le menu déroulant autocomplete reste ouvert après la première sélection et vous pouvez voir la liste changer pour les autres options. Espérons que cela aide avec ce fil.
select: function( event, ui ) {
// the number of chars was driving my decision for behavior, yours may be different
if (chars.length <= 4) {
jq.each(ui, function(key, value) {
jq.each(value, function(key1, value1) {
// put the selected value in the text area,
// since normal behavior will be prevented
jq("#mod_autocomplete").val(value1);
// trigger another search
jq("#mod_autocomplete").autocomplete("search");
// open the autocomplete dropdown
jq("#mod_autocomplete").autocomplete("open");
});
});
event.preventDefault();
} else {
// put whatever behavior you need here for next selection
}
}
vous pouvez gérer l'événement de fermeture automatique http://jqueryui.com/demos/autocomplete/#multiple
exemples de codes
fournir une fonction de rappel pour gérer l'événement de fermeture comme une option init.
$( ".selector" ).autocomplete({
close: function(event, ui) { ... }
});
Lier à la clôture de l'événement par type: autocompleteclose.
$( ".selector" ).bind( "autocompleteclose", function(event, ui) {
...
});
sélectionner: function(event,ui)
if (event.keyCode == 13) {
document.getElementById("#idofautocomplete").value = document.getElementById("#idofautocomplete").value;
} else if (event.keyCode == 27) {
$("#idofautocomplete").autocomplete("close"); }
fermer: function(event,ui)
document.getElementById("idofautocomplete").value = "";
ça a l'air idiot mais ça marche pour moi. l'utilisateur recherche des articles, sélectionne l'article avec la touche enter, autocomplete est toujours ouvert, l'utilisateur peut sélectionner plus d'options, à tout moment l'utilisateur peut appuyer sur le bouton ESC, fermer autocomplete, la fonction de fermeture efface le texte de autocomplete. je reçois toutes mes informations à partir d'une base de données
j'ai modifié la solution de jQuery UI pour répondre à l'événement de fermeture et ré-ouvrir le menu autocomplete si l'input a toujours la mise au point, l'escape n'a pas été pressée pour fermer le popup, et la valeur de l'input se termine en a', 'ou a' (espace):
close: function(e) {
if ($el.is(':focus') && e.keyCode !== $.ui.keyCode.ESCAPE && (this.value != null) && /[,\s]+$/.test(this.value)) {
return $el.autocomplete('search', '');
}
}
solution complète est ci-dessous:
var $el = $('#autocomplete-field');
$el.bind('keydown', function(e) {
if (e.keyCode === $.ui.keyCode.TAB && $(this).data('autocomplete').menu.active) {
e.preventDefault();
}
}).autocomplete({
delay: 0,
autoFocus: true,
minLength: 0,
source: function(req, resp) {
resp($.ui.autocomplete.filter(source, extractLast(req.term)));
},
focus: function() {
return false;
},
select: function(e, ui) {
var terms;
terms = regexSplit(this.value);
terms.pop();
terms.push(ui.item.value);
terms.push('');
this.value = terms.join(', ');
return false;
},
close: function(e) {
if ($el.is(':focus') && e.keyCode !== $.ui.keyCode.ESCAPE && (this.value != null) && /[,\s]+$/.test(this.value)) {
return $el.autocomplete('search', '');
}
}
}).focus(function() {
$el.autocomplete('search', '');
});
Rapide, seulement css et un peu de hacky solution est la suivante:
...
close: function() {
$('.ui-menu').css('display', 'block'); //or using #ui-id-x where x is number of autocomplete
}
...
je sais qu'il y a tellement de réponses déjà là, mais je fais quand même référence à une réponse qui est plus claire et directe. Jetez un oeil à cette réponse
Utilisez le même code à partir de la réponse qui gardera ouvert le menu et maintenant afin de cacher le menu de l'extérieur cliquez(sur le corps) puis utilisez le morceau de code ci-dessous.
$('body').on('click', function(e){
// click event will prevent for the input and for auto complete menu div
if($(e.target).hasClass('ui-autocomplete-input') || $(e.target).hasClass('ui-menu-item-wrapper')){
e.preventDefault();
return;
}
// in other case hide the menu
$("ul.ui-autocomplete").hide();
});
je sais que c'est une vieille Question , Mais qu'il est encore utile,
ci-dessous est la solution pour la version la plus récente de jquery UI.
$.ui.autocomplete.prototype._close = function(e){
return false;
};
OP peut modifier ce code selon ses besoins.