I ran into an interesting issue with jQueryUI autocomplete in a dialog box.
My dialog HTML looks like this:
<div id="copy_dialog">
<table>
<tbody>
<tr>
<th>Title:</th>
<td><input type="text" class="title" name="title"></td>
</tr>
<tr>
<th>Number:</th>
<td><input type="text" name="number"></td>
</tr>
</tbody>
</table>
</div>
When I run the jQueryUI autocomplete on the above HTML, it works perfect.
When I open it up using dialog
$('#copy').click(function()
{
$('#copy_dialog').dialog({
autoOpen: true,
width: 500,
modal: false,
zIndex: 10000000,
title: 'Duplicate',
buttons: {
'Cancel': function()
{
$(this).dialog('close');
},
'Save': function()
{
$(this).dialog('close');
}
}
});
return false;
});
Then in FireBug, I can see autocomplete is still working. It's requesting and receiving results, but I no longer see a list of options below the input field.
My thought is that this has something to do with the zIndex on the dialog box being much greater than what the autocomplete menu gives, but I don't know for sure. I'm still researching exact details of what's happening, but I'm hoping someone here will have some idea for me.
Edit I tried removing the zIndex from the dialog and my autocomplete starts showing up. Unfortunately, I need that zIndex value to get over the dreadfully high zIndex of the menubar, which I can't change (don't have access to that area of the code). So if there's a way to add a zIndex to the autocomplete, that would be fantastic; until then, I'll probably just remove the zIndex from the dialog and make sure it doesn't show up around the menubar area.
Try setting the appendTo
option to "#copy_dialog"
:
$(/** autocomplete-selector **/)
.autocomplete("option", "appendTo", "#copy_dialog");
This option specifies which element the autocomplete menu is appended to. By appending the menu to the dialog, the menu should inherit the correct z-index.
appendTo: Which element the menu should be appended to. When the value is null, the parents of the input field will be checked for a class of "ui-front". If an element with the "ui-front" class is found, the menu will be appended to that element. Regardless of the value, if no element is found, the menu will be appended to the body.
This means that <div id="copy_dialog" class="ui-front">
will do the trick. No need to use the option appendTo
, that did not work for me.
The 'appendTo' option does not always work.
Most egregiously, it will not display past the height of the dialog, but also, if you are using a 3rd party utility (e.g. DataTables editor) you do not always have control over when a dialog, an input, etc. are being created, when they are attached to the DOM, what IDs they have, etc.
This seems to always work:
$(selector).autocomplete({
open: function(event, ui){
var dialog = $(this).closest('.ui-dialog');
if(dialog.length > 0){
$('.ui-autocomplete.ui-front').zIndex(dialog.zIndex()+1);
}
}
});
When using jQuery UI 1.10, you should not mess around with z-indexes (http://jqueryui.com/upgrade-guide/1.10/#removed-stack-option). The appendTo
option works, but will limit the display to the height of the dialog.
To fix it: make sure the autocomplete element is in the correct DOM order with: autocomplete.insertAfter(dialog.parent())
Example
var autoComplete,
dlg = $("#copy_dialog"),
input = $(".title", dlg);
// initialize autocomplete
input.autocomplete({
...
});
// get reference to autocomplete element
autoComplete = input.autocomplete("widget");
// init the dialog containing the input field
dlg.dialog({
...
});
// move the autocomplete element after the dialog in the DOM
autoComplete.insertAfter(dlg.parent());
Update for z-index problem after dialog click
The z-index of the autocomplete seems to change after a click on the dialog (as reported by MatteoC). The workaround below seems to fix this:
See fiddle: https://jsfiddle.net/sv9L7cnr/
// initialize autocomplete
input.autocomplete({
source: ...,
open: function () {
autoComplete.zIndex(dlg.zIndex()+1);
}
});
I recall having a similar issue with autocomplete and zIndex, and had to fix it by specifying the appendTo option: $(selector).autocomplete({appendTo: "#copy_dialog"})
This is also useful if you have an autocomplete inside a positioned element. The specific problem I had was an autocomplete inside a fixed position element that stayed in place while the main body scrolled. The autocomplete was displaying correctly but then scrolled with the body rather than staying fixed.
Through pursuing this problem myself I discovered that appendTo
has to be set before the dialog is opened. The same seems to apply to setting (or modifying) the source property.
$("#mycontrol").autocomplete({appendTo:"#myDialog",source:[..some values]})
$("#mycontrol").autocomplete("option","source",[...some different values]) // works
// doesn't work if the lines above come after
$("#myDialog").dialog("open")
This might just be a byproduct of what dialog open does, or not correctly addressing the element. But the order things happen seems to matter.
Changing the z-index only works the first time the drop-down is opened, once closed, the dialog window realizes it has been "tricked" and upgrades its z-index.
Also for me changing the order of creation of the dialog and auto-complete really was a hassle (think big web site, tons of pages) but by chance I had my own openPopup function that wrapped openedDialog. So I came up with the following hack
$("#dialog").dialog({ focus: function () {
var dialogIndex = parseInt($(this).parent().css("z-index"), 10);
$(this).find(".ui-autocomplete-input").each(function (i, obj) {
$(obj).autocomplete("widget").css("z-index", dialogIndex + 1)
});
});
Each time the dialog has the focus i.e. on 1st opening and when the auto-complete is closed, each auto-complete list's z-index gets updated.
user1357172's solution worked for me but in my opinion it needs two imprevements.
If appendTo
is set to null
, we can find the closest .ui-front
element instead of .ui-dialog
, because our autocomplete
should be already attached to it. Then we should change the z-index
only for related widget (related ul list) instead of changing all existing elements with class .ui-autocomplete.ui-front
. We can find related widget by using elem.autocomplete('widget')
Solution:
elem.autocomplete({
open: function(event, ui){
var onTopElem = elem.closest('.ui-front');
if(onTopElem.length > 0){
var widget = elem.autocomplete('widget');
widget.zIndex(onTopElem.zIndex() + 1);
}
}
});
BTW this solution works but it looks bit hacky, so it is not probably the best one.
- Create the dialog
- Activate auto-complete
This signals to jquery the auto-complete is in a dialog and it has the information available to handle z-indexes.
Super simple solution. Increase the z-index for the autocomplete. When it is active I am pretty sure you want it on top :)
.ui-autocomplete {
z-index: 2000;
}
This link worked for me.
https://github.com/taitems/Aristo-jQuery-UI-Theme/issues/39
Am using jquery-ui-1.10.3.
I configured the autocomplete combobox inside the "open" event of the jquery dialog.
Tried everything mentioned here (some failed whenever I hover over items and return again), but this is the only thing that worked for me in all cases:
$("selector").autocomplete({
...
appendTo: "body", // <-- do this
close: function (event, ui){
$(this).autocomplete("option","appendTo","body"); // <-- and do this
}
});
What worked for me was a combination of the post above. I added the myModal ID instead of body and added the close event as well.
$("selector").autocomplete({
...
appendTo: "#myModalId", // <-- do this
close: function (event, ui){
$(this).autocomplete("option","appendTo","#myModalId"); // <-- and do this
}
});
open:function(event){
var target = $(event.target);
var widget = target.autocomplete("widget");
widget.zIndex(target.zIndex() + 1);
},
来源:https://stackoverflow.com/questions/8685558/jqueryui-autocomplete-not-working-with-dialog-and-zindex