jQuery UI Autocomplete Width Not Set Correctly
Asked Answered
C

20

80

I have implemented a jQuery UI Autocomplete box, and rather than being the width of the textbox, the dropdown options are expanding to fill the remaining width of the page.

Have a look at this example to see it for yourself: http://jsbin.com/ojoxa4

I have tried setting the width of the list immediately after creating it, like so:

$('.ui-autocomplete:last').css('width',
                               $('#currentControlID').width()
                              );

This appears to do nothing.

I have also tried setting the width using on-page styles:

ui-autocomplete { width: 500px; }

This DOES work, amazingly, however it would mean that all autocompletes on a page would have to be the same width, which is not ideal.

Is there a way to set the width of each menu individually? Or better, can anyone explain why the widths are not working correctly for me?

Cysteine answered 13/4, 2011 at 2:30 Comment(1)
The answer by @Abisha further down should be the accepted answer.Snicker
C
65

It turns out the problem is that the menu is expanding to fill the width of its parent element, which by default is the body. This can be corrected by giving it a containing element of the correct width.

First I added a <div> like so:

<div id="menu-container" style="position:absolute; width: 500px;"></div>

The absolute positioning allows me to place the <div> immediately after the input without interrupting the document flow.

Then, when I invoke the autocomplete, I specify an appendTo argument in the options, causing the menu to be appended to my <div>, and thus inherit its width:

$('#myInput').autocomplete({ source: {...}, appendTo: '#menu-container'});

This fixes the problem. However, I'd still be interested to know why this is necessary, rather than the plug-in working correctly.

Cysteine answered 13/4, 2011 at 15:31 Comment(6)
I'm having exactly the same issue. Looking at the examples on the Jquery UI site and trying to replicate I can't see what I am doing different. Is it me or is the "new" official autocomplete worse than Jorn's old one?Denial
Would recommend using the appendTo option even if the width isn't an issue. It will allow you to reuse the widget with different styles and options and not have them all floating at the bottom of your document.Tyrocidine
Sorry, voted this down, Arnaud's answer's just so much better.Griselgriselda
@DavidGrenier I don't believe down voting an answer because another answer is better is fair. Unless you have a specific reason that this answer is not useful. I think it is better to show your preference to the other question by up voting it but i am sure you have already done that :) stackoverflow.com/help/privileges/vote-downStatic
This is the best solutionSkillet
For me, this is clearly a bug! I would expect, that the dropdown box is appended automatically to the parent element of the input AND that it is absolute positioned instead of relative, which currently breaks the flow of following elements. In that way, it would be easy to style different autocompletes depending on their context and there would be no false width.Paraphrastic
C
131

I use this drop-in solution:

jQuery.ui.autocomplete.prototype._resizeMenu = function () {
  var ul = this.menu.element;
  ul.outerWidth(this.element.outerWidth());
}

That's basically @madcapnmckay's solution, but that doesn't need to change the original source.

Commercial answered 7/8, 2012 at 12:13 Comment(5)
this should be the accepted solution - since it's easiest and most non-intrusiveMeitner
I thinks it's the best answer because applies to all jquery autocomplete declarations, and it's clear!Dex
no idea what exactly this code does - but it "magically" sizes the autocomplete-width to the width of the regarding input-box; just like it should work originally but doesn't under many circumstances.Surfacetosurface
Hey, thanks for this answer. Can you give some more insight into what the code does exactly so that I can figure out what the optimal placement for it is? Is it overriding the _resizeMenu function? I placed it in a script that is run once on every page on my web application, do you have any suggestions for better placement? Thanks.Heptateuch
element.autocomplete('instance')._resizeMenu is better as you can override just the instance. Rather than overwriting for any other autocompletes on the same page.Endomorph
C
65

It turns out the problem is that the menu is expanding to fill the width of its parent element, which by default is the body. This can be corrected by giving it a containing element of the correct width.

First I added a <div> like so:

<div id="menu-container" style="position:absolute; width: 500px;"></div>

The absolute positioning allows me to place the <div> immediately after the input without interrupting the document flow.

Then, when I invoke the autocomplete, I specify an appendTo argument in the options, causing the menu to be appended to my <div>, and thus inherit its width:

$('#myInput').autocomplete({ source: {...}, appendTo: '#menu-container'});

This fixes the problem. However, I'd still be interested to know why this is necessary, rather than the plug-in working correctly.

Cysteine answered 13/4, 2011 at 15:31 Comment(6)
I'm having exactly the same issue. Looking at the examples on the Jquery UI site and trying to replicate I can't see what I am doing different. Is it me or is the "new" official autocomplete worse than Jorn's old one?Denial
Would recommend using the appendTo option even if the width isn't an issue. It will allow you to reuse the widget with different styles and options and not have them all floating at the bottom of your document.Tyrocidine
Sorry, voted this down, Arnaud's answer's just so much better.Griselgriselda
@DavidGrenier I don't believe down voting an answer because another answer is better is fair. Unless you have a specific reason that this answer is not useful. I think it is better to show your preference to the other question by up voting it but i am sure you have already done that :) stackoverflow.com/help/privileges/vote-downStatic
This is the best solutionSkillet
For me, this is clearly a bug! I would expect, that the dropdown box is appended automatically to the parent element of the input AND that it is absolute positioned instead of relative, which currently breaks the flow of following elements. In that way, it would be easy to style different autocompletes depending on their context and there would be no false width.Paraphrastic
F
43

I know this has long since been answered, but i think there is a better solution

$(".autocomplete").autocomplete({
    ...
    open: function() {
        $("ul.ui-menu").width( $(this).innerWidth() );
        ...
    }
    ...
});

It worked fine for me.

Fathometer answered 30/4, 2014 at 9:24 Comment(3)
Very nice solution! Thanks!Mignonne
Nice solution, for notice, it accept input arguments so read manual before use - for example if you writing function when NOT ONE autocomplete on one page.Lex
this should be the default behaviorExalted
D
38

I had a dig around in the autocomplete code and the culprit is this little blighter

_resizeMenu: function() {
    var ul = this.menu.element;
    ul.outerWidth( Math.max(
        ul.width( "" ).outerWidth(),
        this.element.outerWidth()
    ) );
},

I'm not sure what ul.width("") is suppose to be doing but ui.width("").outWidth() always returns the width of the body because that's what the ul is appended to. Hence the width is never set to the elements width....

Anyway. To fix simply add this to your code

$element.data("autocomplete")._resizeMenu = function () {
        var ul = this.menu.element;
        ul.outerWidth(this.element.outerWidth());
}

Is this a bug?

EDIT: In case anyone wants to see a reduced test case for the bug here it is.

Denial answered 9/5, 2011 at 2:7 Comment(4)
Someone closed it...not sure why. I'm still getting this issue in the latest JQuery UI.Pericarp
He said that apparently we should be including certain css files. It's not documented and seems a little silly to me since it could work out the width based on the input without the need to external styles.Denial
Just spent some time digging into this myself and found a couple of things: 1. The ul.width( "") call is to remove any explicit width settings made to the menu element previously. 2. The CSS must be included to work properly because the base CSS sets float: left on .ui-menu elements thus, when calculating the width, ul.width( "" ).outerWidth() takes into account the width of any extra long results, otherwise it takes the width of the input element.Loudermilk
@Denial A yet simpler approach would be to use your technic in a drop-in fashion: https://mcmap.net/q/258938/-jquery-ui-autocomplete-width-not-set-correctlyCommercial
A
27

Set the css in the open event!

$('#id').autocomplete({
    minLength: 3,
    source: function(request, response) {
        $.ajax({
                    url: "myurl",
                    dataType: "json",
                    type: 'POST',
                    data: {
                        'q': request.term,

                        'maxRows': 15
                    },
                    success: function(data) {

                        response($.map(data, function(item) {
                            return {
                                label: item.name,
                            }
                        })),
                    }
                })
            },
            select: function(event, ui) {
                $("#id").val(ui.item.label);
            },
            focus: function ( event, ui ){
                $form.find('#id').val(ui.item.label);
                return false;
            },
            open: function(){
                $('.ui-autocomplete').css('width', '300px'); // HERE
            }
        })
Abisha answered 4/2, 2012 at 20:16 Comment(2)
I did this, I actually put the results in a div and set the position. It works on other browsers except IE7 and IE9 compatibility view. Why is that? Here's how I did it, appendTo: "#results", open: function(){ var position = $("#results").position(), left = position.left, top = position.top; $("#results > ul").css({left: (left + 15) + "px", top: (top + 30) + "px", width: (206) + "px" }); },Postulant
You may also have to reset the max-width.Decarbonize
B
25

I know this has been answered long ago, but I ran into same problem. My solution was to add position:absolute

Bowery answered 23/11, 2011 at 12:34 Comment(4)
To clarify for others: .ui-autocomplete { position: absolute; }Sparid
This totally worked for me. Literally hacked in a !important and bingo bango, happy boss. #dontVoteTrump #actuallyMakeAmericaGreatAgainQuicklime
This answer should have way more votes. Some other responses seem like pretty hacky solutions to me.Intrench
This is the best answer.Vinificator
S
16

I ran into this issue as well but realized that I just forgot to include a reference to the jquery.ui.autocomplete.css style sheet. Did you include that style sheet in your layout/master page?

Subtractive answered 19/8, 2011 at 20:40 Comment(3)
This was the issue for me - and I suspect it was for most people as well. Do you all think jQ UI is so broken by default? ;)Serum
Or add the following to your CSS as this is all whats inside that file: .ui-autocomplete { position: absolute; top: 0; left: 0; cursor: default; }Emmer
Some may have forgotten it, but some actually ran into the bug/issue explained in other answersAuricula
C
4

$("#autocompleteID").autocomplete({
source: "http://myhost/magento/js/jquery/ui/php/ville.php",
minLength: 1,
open: function(event, ui)
{
   $("#autocompleteID").autocomplete ("widget").css("width","300px");  
} 
});
Cusp answered 21/12, 2015 at 6:33 Comment(0)
B
2

If you like to use css try this:

.ui-widget-content.ui-autocomplete {
    width: 350px;
}

It will work on every autocomplete input.

Batten answered 16/1, 2017 at 14:40 Comment(0)
W
0

If you are using the official jQuery ui autocomplete (i'm on 1.8.16) and would like to define the width manually, you can do so.

If you're using the minified version (if not then find manually by matching _resizeMenu), find...

_resizeMenu:function(){var a=this.menu.element;a.outerWidth(Math.max(a.width("").outerWidth(),this.element.outerWidth()))}

...and replace it with (add this.options.width|| before Math.max) ...

_resizeMenu:function(){var a=this.menu.element;a.outerWidth(this.options.width||Math.max(a.width("").outerWidth(),this.element.outerWidth()))}

... you can now include a width value into the .autocomplete({width:200}) function and jQuery will honour it. If not, it will default to calculating it.

Whiteley answered 15/9, 2011 at 13:44 Comment(0)
P
0

I know this has long since been answered, but the easiest way I find is to use the id of the autocomplete, and to set the width to 100px you would call

$('.ui-autocomplete-input#MyId').css('width', '100px');

after you finish your $('#MyId').autocomplete(...); call. This way you don't end up tying the order of your autocomplete textboxes in your DOM to your script.

Photoreceptor answered 15/10, 2011 at 1:21 Comment(0)
P
0

In case you not are able to set the width dynamically and nothing at all works try to include this

http://code.google.com/p/jquery-ui/source/browse/trunk/themes/base/jquery.ui.autocomplete.css?spec=svn3882&r=3882

either in a linked sheet or hardcoded and set the parameters here.

It worked for me after trying everything else

Persinger answered 18/2, 2012 at 16:54 Comment(1)
The meaningful part of the jquery.ui.autocomplete.css file you linked to is the position:absolute which @andrius-chamentauskas pointed out above. The following fixed it for me: .ui-autocomplete { position: absolute; }Sparid
L
0

Well, Ender. I don't know if my solution can help you or not, but with Jqueryui remote-with-cache.html it worked. I just put in the size property in the text box.

Please see the code below:

<div class="demo">
    <div class="ui-widget">
        <label for="birds">Birds: </label>
        <input id="birds" size="30"/>
    </div>
</div>
Leaved answered 22/6, 2012 at 10:27 Comment(0)
A
0

My solution was to append the autocomplete to a div with an id, and they set CSS for that specific ul:

jQuery/JavaScript:

$("input[name='search-text]").autocomplete({
    appendTo: "#item-search-autocomplete",
    source: ....
});

CSS:

#item-search-autocomplete .ui-autocomplete {
    width: 315px;
}

Works like a charm.

Appetency answered 12/12, 2012 at 16:48 Comment(0)
S
0

My issue solved (in jQuery UI version 1.13.1) by just adding these two lines in .ui-autocomplete class

.ui-autocomplete {
    position: absolute;
    top: 0;
    left: 0;
    cursor: default;
    /* my added style */
    word-wrap: break-word;
    width: 0;
    /* my added style */
}
Scolecite answered 11/8, 2022 at 10:54 Comment(0)
H
0

As I had a complex layout and cannot append the autocompletion menu directly to the relevant DOM node, I adopted this approach:

jQuery.ui.autocomplete.prototype._resizeMenu = function () {
  this.menu.element.css('max-width', $('#searchbar').width());
}

This is to force the menu to stay as large as the search bar, despite any width or position calculated by jQueryUI itself.

Inspired by this other answer in the question.

Hyperbolize answered 12/12, 2023 at 16:33 Comment(0)
H
0

I appreciate this is an old question, but I just tripped over this as well! Arnauld's answer is probably the best one, but has the issue that it (as with all the CSS based answers) in that it affects all the autocompletes on the same page, something I didn't want.

So I extended Arnauld's answer and changed it so that it looks for an attribute against the element (i.e. the input box that is the autocomplete element), if not found, it uses the default implementation, if found, it will use that value as the width for the menu.

jQuery.ui.autocomplete.prototype._resizeMenu = function () {
var ul = this.menu.element;

// Do we have an attribute with dropdown width set?
if (this.element.attr('data-ac-list-width') === undefined) {
    // This is the default implementation
    ul.outerWidth( Math.max(
        // Firefox wraps long text (possibly a rounding bug)
        // so we add 1px to avoid the wrapping (#7513)
        ul.width( "" ).outerWidth() + 1,
        this.element.outerWidth()
    ) );
} else {
    ul.outerWidth(this.element.attr('data-ac-list-width'));
}

}

So with the input element, you just need to add an extra attribute into the HTML...

<input id="txtAwesomeAC" data-ac-list-width="800" />

This has the benefit of using the default width, but allowing you to override it on a case by case basis.

Hutchinson answered 16/4 at 9:44 Comment(0)
L
-1

I faced the same issue and resolved it by using this piece of code, though it is a little hit and trial kind of thing, but it works, I was not being able to set the width so I decided to set the max-width property.

  $('.ui-autocomplete').css('margin-left','25%') //center align
  $('.ui-autocomplete').css('max-width','38%') //hit and trial
  $('.ui-autocomplete').css('min-width','38%') //hit and trial

See what works best for you.Hope this helps.

Lingua answered 13/2, 2017 at 10:40 Comment(0)
A
-2

There is a width option for the autocomplete. I use it for 1.3.2.

$('#mytextbox').autocomplete(url, {  
        width: 280,
        selectFirst: false,
        matchSubset: false,
        minChars: 1,
        extraParams:{myextraparam:myextraparam},
        max: 100
    });
Attend answered 13/4, 2011 at 16:3 Comment(2)
You must be using some other autocomplete plug-in. jQuery UI has no such option: jqueryui.com/demos/autocomplete/#optionsCysteine
Actually, I am using jquery 1.3.2 with jquery.autocomplete.min.js 1.0.2. If you look in the jquery.autocomplete.min.js for width, you will see this line: if(options.width>0)element.css("width",options.width); This sets the width of the autocomplete.Attend
K
-2

I have this in my css file, so the autocomplete takes the width of the styled span:

 span input.ui-autocomplete-input {
     width: 100%;
 }
K answered 7/10, 2014 at 12:38 Comment(1)
Note, that you post not enough information about your implementation. Author has his own html and your style won't fit his requirements.Ladysmith

© 2022 - 2024 — McMap. All rights reserved.