1

This function is searching from a Json data the field "title". Please, how can I modify this to include multiple fields, like: "tags", "author" etc.? Thanks!

document.addEventListener('DOMContentLoaded', function(event) {
  const search = document.getElementById('search');
  const results = document.getElementById('results');
  let data = [];
  let search_term = '';

  fetch('/search.json')
    .then(response => response.json())
    .then(data_server => {
      data = data_server;
    });

  search.addEventListener('input', event => {
    search_term = event.target.value.toLowerCase();
    showList();
  });

  const showList = () => {
    results.innerHTML = '';
    if (search_term.length <= 0) return;
    const match = new RegExp(`${search_term}`, 'gi');
    let result = data.filter(name => match.test(name.title));
    if (result.length == 0) {
      const li = document.createElement('li');
      li.innerHTML = `No results found `;
      results.appendChild(li);
    }
    result.forEach(e => {
      const li = document.createElement('li');
      li.innerHTML = `<a href="${e.url}">${e.title}</a>`;
      results.appendChild(li);
    });
  };
});
rocco
  • 115
  • 1
  • 7
  • Your script only works because `showList()` is only executed after `fetch()` has done its job -> [How to return the response from an asynchronous call](https://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-asynchronous-call) – Andreas Sep 08 '21 at 07:48

2 Answers2

3

change

let result = data.filter(name => match.test(name.title));

to

let result = data.filter(name => match.test(name.title) || match.test(name.tags) || match.test(name.auther));
SirOneOfMany
  • 929
  • 5
  • 15
1

It may be an idea to filter on all entries of the objects within the Array retrieved from the json.

Here's a minimal reproducable example, using Event Delegation.

See also

document.addEventListener(`click`, handle);
const data = getJSONFakeData();

function handle(evt) {
  if (evt.target.id === `search`) {
    return searchJSON();
  }
}

function searchJSON() {
  const resultsDiv = document.querySelector(`#results`);
  resultsDiv.textContent = ``;
  const nothingFound = isEmpty => 
    resultsDiv.insertAdjacentHTML(
      `beforeend`, 
      `<h3>${isEmpty 
          ? ` No input`
          : `No results found `}</h3>` );
  const term = document.querySelector(`#term`).value.trim();
    
  if (term.length < 1) {
    return nothingFound(true);
  }
  const re = new RegExp(term, `gi`);
  
  // filter here
  const results = data
    .filter( entry => Object.entries(entry)
        .find( ([, value]) => re.test(value) )
  );
  
  if (results.length) {
    let elems = [];
    results.forEach( result => {
      const res = Object.entries(result)
        .reduce( (acc, [key, value]) => 
          acc.concat(`<i>${key}</i>: ${value};<br>`), ``);
      elems.push(`<li>${res}</li>`);
    });
    return resultsDiv.insertAdjacentHTML(
      `beforeend`,
      `<ul>${elems.join(``)}</ul>`);
   }
   
   return nothingFound();
}

function getJSONFakeData() {
  return [{
      title: `title1`,
      author: `author1`,
      tags: `science, medicine`,
      editor: `Springer Verlag`
    },
    {
      title: `title2`,
      author: `author2`,
      tags: `automotive, engine`,
      editor: `Elsevier`
    },
    {
      title: `title3`,
      author: `author3`,
      tags: `programming, functional, loops`,
      editor: `Elsevier`
    },
  ];
}
body {
  font: normal 12px/15px verdana, arial;
  margin: 2em;
}
<input type="text" id="term" value="Elsevier">
<button id="search">Find</button>

<div id="results"></div>
KooiInc
  • 119,216
  • 31
  • 141
  • 177