Show independent autocomeple options for text fields in java script

Viewed 154

I have a dummy html code where I’m testing the JS code.

This code has three textboxes: 

dynamic
static
both

For each of these I want to show different auto-complete options:

var dynamic = ["JavaScript", "Python", "Ruby"]
var static = ["C", "C++", "Java"]
var both = ["JavaScript", "Python", "Ruby", "C", "C++", "Java"]

What I'm currently doing is to call a function, which has the ID and options as parameters, three times, once for each case: 

function show_options(field_id, available_options) {

  $(`[id*=${field_id}]`).autocomplete({
      source: available_options,
      minLength: 0
    })
    .focus(function() {
      $(this).autocomplete("search", $(this).val())
    });
};


var dynamic = ["JavaScript", "Python", "Ruby"]
var static = ["C", "C++", "Java"]
var both = ["JavaScript", "Python", "Ruby", "C", "C++", "Java"]


show_options("dynamic", dynamic)
show_options("static", static)
show_options("both", both)
<div class="ui-widget">
  <label for=“tags”>Input1: </label>
  <input id="dynamic">
</div>
<div class="ui-widget">
  <label for="tags">Input2: </label>
  <input id="static">
</div>
<div class="ui-widget">
  <label for="input3">Input3: </label>
  <input id="both">
</div>

<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>

This kind of works, but it does look as a very bad practice to me.

The reason I'm doing it this way is because I will not know the IDs beforehand, and the options will be received from and external server.

4 Answers

How about adding same class to those inputs and then create a new function that's able to attach autocomplete event to all inputs which has same class, and it's id is for data-placeholder detection (detect which data would be used for placeholder of input). So with this approach, you don't have to worry about id any more. All you need to do is just after getting data from external server, assign it to the variable name which is the same as id of input you want to use it for

function show_options(selector) {
  // check if exist selector
  if ($(selector).length > 0){
    $(selector).each(function(){
      // check if exist data relevant to the id of input
      if (Array.isArray(window[$(this).attr('id')])) {
        available_options = window[$(this).attr('id')];
        $(this).autocomplete({
          source: available_options,
          minLength: 0
        })
        .focus(function() {
          $(this).autocomplete("search", $(this).val())
        });
      }
    });
  }
};

// get data from external server
// and assign it to variable which has the same name with the id in input 
var dynamic = ["JavaScript", "Python", "Ruby"]
var static = ["C", "C++", "Java"]
var both = ["JavaScript", "Python", "Ruby", "C", "C++", "Java"]

show_options(".auto-complete");
<div class="ui-widget">
  <label for=“tags”>Input1: </label>
  <input class="auto-complete" id="dynamic">
</div>
<div class="ui-widget">
  <label for="tags">Input2: </label>
  <input class="auto-complete" id="static">
</div>
<div class="ui-widget">
  <label for="input3">Input3: </label>
  <input class="auto-complete" id="both">
</div>

<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>

Hope this would help. Please correct me if I were wrong

Datalist is much better than jquery. it is possible to embedded with javascript

here is an example for dynamic:

const dynamics = ["JavaScript", "Python", "Ruby"];

function addOptions(inputID, list) {
    var container = document.getElementById(inputID),
    data = document.createElement('datalist');

    data.id = 'dynamics';
    for (const el of list) {
      const option = document.createElement('option');
        option.value = el;
        data.appendChild(option);
    }

    container.appendChild(data);
}

addOptions('dynamic', dynamics);
<input id="dynamic" list="dynamics"/>

How about turning your code into a plugin! Plugin's plugin ;) that will encapsulate your autocomplete plugin in your own custom one with facility to pass configuration options and data.

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

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

<div class="ui-widget">
  <label for="input3">Input3: </label>
  <input id="both">
</div>

<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>

<script>
  (function() {
    $.fn.myPlugin = function(o) {

      var o = $.extend({
        // These are the defaults.
        source: [],
        minLength: 0
      }, o);

      //why each? because you might want to run on multiple elements like - $('.myclass, #me, #metoo').myPlugin();
      this.each(function() {
        //--your original code 
        $(this).autocomplete({
            source: o.source,
            minLength: o.minLength
          })
          .focus(function() {
            $(this).autocomplete("search", $(this).val())
          });

      });
    };
  })();
  
  //Plugin is ready - use it now!

  $('#dynamic').myPlugin({
    source: ["JavaScript", "Python", "Ruby"],
    minLength: 0
  });
  $('#static').myPlugin({
    source: ["C", "C++", "Java"],
    minLength: 0
  });
  $('#both').myPlugin({
    source: ["JavaScript", "Python", "Ruby", "C", "C++", "Java"],
    minLength: 0
  });
</script>

You can use a hash map to store the relation between your data and your inputs like so:

// This will be your data structure for the autocomplete
//
// The keys of this object are the input selectors,
// the values are the autocomplete values
//
// In your app you will probably be creating this object dynamically 
// from some extrenal data
const dataBySelector = {
  '#dynamic': ["JavaScript", "Python", "Ruby"],
  '#static': ["C", "C++", "Java"],
  '#both': ["JavaScript", "Python", "Ruby", "C", "C++", "Java"],
  // Now you can also do some silly stuff like this :)
  'input:not(:disabled):visible': ["JavaScript", "Python", "Ruby"]
};

// Your function will accept the data object from above and initialize the autocompletes
function show_options(data) {
  Object.keys(data).forEach(function(selector) {
    // First we grab the data for this selector
    const dataForAutocomplete = data[selector];
    
    // Then we initialize the autocomplete and store the jQuery object
    // so that you don't need to call $(this) all the time (a little performance optimization)
    const $autocomplete = $(selector).autocomplete({
      source: dataForAutocomplete,
      minLength: 0
    })
    .focus(function() {
      $autocomplete.autocomplete("search", $autocomplete.val())
    });
  })
}

// Then you call the function when necessary
show_options(dataBySelector);

Here is a working JSFiddle link

Related