Search code examples
javascripthtmljqueryjquery-ui-autocomplete

How to force JS to ignore a li element


I have implemented jquery autocomplete

(this is just an example to simulate the real code)

let availableTags = [   
      undefined,    // this is only a header and its results to undefined due to a lack of Id
      "AppleScript",
      "Asp",
      "BASIC",
      "C",
      "C++",
      "Clojure",
      "COBOL",
      "ColdFusion",
      "Erlang",
      "Fortran",
      "Groovy",
      "Haskell",
      "Java",
      "JavaScript",
      "Lisp",
      "Perl",
      "PHP",
      "Python",
      "Ruby",
      "Scala",
      "Scheme"
    ];

    $('#tags').autocomplete({
            source: availableTags,
                                                    
              minLength: 0,
                        
              focus: function (event, ui) { 
                                              
                       if(!ui.item){ 

                          // add code here

                       }
                                                                                        
              },
                        
              select: function (event, ui) {                                            

                    //...    

              },
      })
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
  <link rel="stylesheet" href="/resources/demos/style.css">

 <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
 <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

<div class="ui-widget">
  <label for="tags">Tags: </label>
  <input id="tags">
</div>

The first li element of the ul is only a header (not a real li option) , therefore I don't want it to be selected at all.

I managed to prevent click events on it but it is still "sensitive" to other events like mouseenter mouseover and more I can activate those events by using the keyboard keydown

how can I force JS to ignore the first li element from been triggered at all not even via keyboard ?

EDIT: By the way, I can control the first li tag to be div \ span or any other tag (just remember that that tag will be enclosed in a ul)

EDIT-2: The header should only be displayed to actioned at all by no JS event (mouse, keyboard etc.) and the header should be undefined to match the real code


Solution

  • You need to define the data as object with category and label as attributes in availableTags data array; and also need to implement _renderMenu of your custom auto complete functionality.

    $.widget("custom.mycomplete", $.ui.autocomplete, {
      _create: function () {
        this._super();
        this.widget().menu("option", "items", "> :not(.ui-autocomplete-category)");
      },
      _renderMenu: function (ul, items) {
        var that = this,
          currentCategory = "";
        $.each(items, function (index, item) {
          var li;
          if (item.category != currentCategory) {
            ul.append("<li class='ui-autocomplete-category'>" + item.category + "</li>");
            currentCategory = item.category;
          }
          li = that._renderItemData(ul, item);
          if (item.category) {
            li.attr("aria-label", item.category + " : " + item.label);
          }
        });
      }
    });
    
    let availableTags = [
      { label: "AppleScript", category: "Langauges" },
      { label: "Asp", category: "Langauges" },
      { label: "BASIC", category: "Langauges" },
      { label: "C", category: "Langauges" },
      { label: "C++", category: "Langauges" },
      { label: "Clojure", category: "Langauges" },
      { label: "COBOL", category: "Langauges" },
      { label: "ColdFusion", category: "Langauges" },
      { label: "Erlang", category: "Langauges" },
      { label: "Fortran", category: "Langauges" },
      { label: "Groovy", category: "Langauges" },
      { label: "Haskell", category: "Langauges" },
      { label: "Java", category: "Langauges" },
      { label: "JavaScript", category: "Langauges" },
      { label: "Lisp", category: "Langauges" },
      { label: "Perl", category: "Langauges" },
      { label: "PHP", category: "Langauges" },
      { label: "Python", category: "Langauges" },
      { label: "Ruby", category: "Langauges" },
      { label: "Scala", category: "Langauges" },
      { label: "Scheme", category: "Langauges" }
    ];
    
    $('#tags').mycomplete({
      source: availableTags,
      minLength: 0,
      focus: function (event, ui) {
        if (!ui.item) {
          //code goes here
        }
      },
      select: function (event, ui) {
        //code goes here
      }
    });
    .ui-autocomplete-category {
        font-weight: bold;
        padding: .2em .4em;
        margin: .6em 0 .2em;
        line-height: 1.5;
      }
    <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
      <link rel="stylesheet" href="/resources/demos/style.css">
    
     <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
     <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
    
    <div class="ui-widget">
      <label for="tags">Tags: </label>
      <input id="tags">
    </div>