Autocomplete text of an input based on data stored in Local Storage

3

Hi, I would like to know if there is any way that by entering characters in a input of type text a bar with previously entered suggestions is displayed, using JQuery , javascript , etc. I clarify that I do not want to obtain data from a database. I've been looking for this for some time but I can not find a solution. Thanks in advance.

    
asked by Ccccccccc 01.03.2017 в 19:48
source

2 answers

1

You can do something like the following: Every time the user makes submit in the form or take the action you want, you save the data in localStorage and at the beginning of the application you read the data previously saved:

  

Note: I used autocomplete of jQuery ui , you can use the library you want.

HTML code

<input id="search" type="search" />
<input id="button" type="button" value="Buscar" />

JavaScript code

var storage = window.localStorage;
var results = (storage.getItem("searches")) ? JSON.parse(storage.getItem("searches")) : [];
var search = $("#search");
var button = $("#button");

search.autocomplete({
    source: results
});

button.on("click", function () {

    var str = search.val();

    if (results.indexOf(str) < 0) {

        results.push(search.val());

        storage.setItem("searches", JSON.stringify(results));

    }

    search.val("");

});

Here is a Codepen so you can try the functionality.

    
answered by 01.03.2017 / 20:47
source
4

One way is this:

  • In the event focus of the input: load list of suggestions
  • In the event blur : delete list of suggestions
  • In the event input : iterate the list of nodes and check if each node contains a part of the entered text. If yes, it shows the suggestion and if not, it hides it.

This code does not only work with local/sessionStorage , but you can also get the list of suggestions from an API, for example.

let suggestions = [
  'javascript',
  'css',
  'scss',
  'jquery',
  'php',
  'python',
  'node.js',
  'html5'
];

let input = document.querySelector('.search input');
let searchBox = document.querySelector('.search-box');
let suggestionList = document.querySelector('.suggestions');

input.addEventListener('focus', function(e) {
  //let suggestions = JSON.parse(sessionStorage.getItem('suggestions'));
  fillSuggestionList(suggestions);
  searchBox.classList.add('visible');
});

input.addEventListener('blur', function(e) {
  searchBox.classList.remove('visible');
  clearSuggestionList();
});

input.addEventListener('input', function(e) {
  let enteredText = this.value.toLowerCase();
  let suggestions = suggestionList.children;

  [].forEach.call(suggestions, function(suggestion) {
    let suggestionContent = suggestion.textContent;

    if (enteredText.length && suggestionContent.includes(enteredText)) {
      suggestion.style.display = 'block';
    } else {
      suggestion.style.display = 'none';
    }
  });
});

function fillSuggestionList(suggestions) {
  suggestions.forEach(function(suggestion) {
    let li = document.createElement('li');
    li.textContent = suggestion;
    suggestionList.appendChild(li);
  });
}

function clearSuggestionList() {
  while (suggestionList.firstChild) {
    suggestionList.removeChild(suggestionList.firstChild);
  }
}
@import url('https://fonts.googleapis.com/css?family=Noto+Sans:400,700');


*,
*:before,
*:after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

body {
  background-color: #fff;
}

.input {
  border: 1px solid #ccc;
  border-radius: 3px;
  box-shadow: 0 1px 3px 0 rgba(0, 0, 0, .1) inset;
  color: #555;
  font-size: 14px;
  height: 35px;
  padding: 0 .75rem;
  transition: all .25s var(--ease);
  width: 100%;
}

.input:focus {
  border-color: rgba(0, 100, 255, .5);
  outline: none;
}

.input-addon {
  display: flex;
  flex-direction: row-reverse;
}

.input-addon .icon {
  align-items: center;
  border: 1px solid #ccc;
  border-right: 0;
  border-radius: 3px 0 0 3px;
  box-shadow: inset 0 0.0625rem 0.1875rem 0 rgba(0, 0, 0, .1);
  display: flex;
  flex: 0 0 35px;
  height: 35px;
  justify-content: center;
  margin: 0;
  position: relative;
  transition: all .25s var(--ease);
}

.input-addon .icon:after {
  background-color: #fff;
  bottom: 1px;
  content: "";
  height: 95%;
  position: absolute;
  right: -1px;
  width: 2px;
}

.input-addon .icon i {
  color: #777;
}

.input-addon .input {
  border-left: none;
  border-radius: 0 3px 3px 0;
  flex: 1;
}

.search {
  margin: 20px auto;
  position: relative;
  width: 80%;
}

.input-addon .input:focus+.icon {
  border-color: rgba(0, 100, 250, .5);
}

.search-box {
  border-radius: 3px;
  box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .23), 0 -1px 1px 0 rgba(0, 0, 0, .1);
  padding: 8px;
  opacity: 0;
  position: absolute;
  top: 100%;
  transition: all .25s linear;
  visibility: hidden;
  width: 100%;
}

.search-box.visible {
  opacity: 1;
  top: 140%;
  visibility: visible;
}

.suggestions {
  list-style: none;
  padding: 0;
}

.suggestions li {
  color: #555;
  display: none;
  font-family: 'Noto Sans';
  font-size: 14px;
  padding: 10px 12px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" />

<div class="search">
  <div class="input-addon">
    <input type="search" class="input">
    <figure class="icon">
      <i class="fa fa-search"></i>
    </figure>
  </div>
  <div class="search-box">
    <ul class="suggestions">

    </ul>
  </div>
</div>

Note: the code uses ES6, so if you support ES5 change let by var e includes by indexOf(str) !== -1 .

    
answered by 01.03.2017 в 21:08