Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Append separator line after jQuery UI Autocomplete items except after the last item

I have a jQuery UI Autocomplete bound to an input element and a custom display of the items in the Autocomplete box. Each item has multiple lines and I want to separate the items clearly from each other, for example using a <hr /> element. The following works but it also renders a <hr /> element after the last item:

$(function () {
    $("#Customer").autocomplete({
        source: "/SomePath/SearchCustomers?term=ABC",
        select: function (event, ui) {
            $("#CustomerId").val(ui.item.customerId);
            return false;
        }
    })
    .data("autocomplete")._renderItem = function (ul, item) {
        var renderedItem = $("<li></li>")
            .data("item.autocomplete", item)
            .append("<a>" + item.customerId + ", " + item.name + "<br />"
                + item.addressLine1 + "<br />"
                + item.countryCode + ", " + item.city + "</a>");

        // if (IsNotTheLastItem(item))  <-- Is something like this possible?
            renderedItem = renderedItem.append("<hr />");

        renderedItem = renderedItem.appendTo(ul);

        return renderedItem;
    };
});

(The code is derived from the example here: http://jqueryui.com/demos/autocomplete/#custom-data (click on "View Source").)

Is it possible to determine if the item I am going to render is the last item (as indicated in the comment line above)? Or is there some alternative to add a separator between items, but not after the last item?

like image 303
Slauma Avatar asked Jun 05 '12 11:06

Slauma


2 Answers

Since you're clearly using the <hr> element only for a visual purpose, I think you could easily solve this problem with CSS only: instead of generating a <hr> element inside every <li> via javascript, just assign a border-top to every <li> except the first one with

ul li:not(:first-child) { border-top: 1px #ccc solid; padding: 2em 0; }

the resulting effect will be a line under each list item except the last one and you will avoid to inject markup via javascript and - more important - to insert unnecessary logic to detect your last item

like image 127
Fabrizio Calderan Avatar answered Sep 27 '22 23:09

Fabrizio Calderan


@F. Calderan's answer is 99% of the solution. The following is only a litte appendix to his answer:

I didn't find a good selector for the css style in his answer at once. The problem is that jQuery UI places the ul and li elements for the Autocomplete items at the bottom of the body element of the page:

<body>
    <input id="Customer" name="Customer" />

    // more stuff

    // jQuery UI puts the rendered search result here at the end of the page body
    <ul>
        <li>...</li>
        <li>...</li>
        <li>...</li>
    </ul>
</body>

Here is no class or id available to select the ul/li style and I don't want to define this style on body level since the page has other lists (like the main menu) as well which should not get this style applied.

But it is only the default that the result list is appended to the body element. It can be overwritten using the appendTo option of the Autocomplete widget:

$("#Customer").autocomplete({
    appendTo: "#CustomerWrapper",
    //...
})

Now the result list is appended to the element with id CustomerWrapper. I have wrapped the input element into a div with that id and applied an additional class style ui-autocomplete-multilineitems because I only want the separation line for Autocompletes where the items have multiple lines:

<div id="CustomerWrapper" class="ui-autocomplete-multilineitems">
    <input id="Customer" name="Customer" />
</div>

(The input element doesn't need to be wrapped into the div. The div can be placed anywhere else on the page.)

The rendered result is now:

<div id="CustomerWrapper" class="ui-autocomplete-multilineitems">
    <input id="Customer" name="Customer" />

    <ul>
        <li>...</li>
        <li>...</li>
        <li>...</li>
    </ul>
</div>

And I can define the styles for only those list elements in the css file:

.ui-autocomplete-multilineitems ul li {
    border-top: 1px #ccc solid;
    padding: 2em 0;
}

.ui-autocomplete-multilineitems ul li:first-child {
    border-top: none;
    padding-top: 0;
}
like image 20
Slauma Avatar answered Sep 27 '22 22:09

Slauma