2

I'm using this javascript code, to filter search items but i want to filter a div element not just plain text.

var searchBox = document.querySelector("input");
var resultList = document.getElementById("resultList");
var resultsArray = [
"Walt Disney",
"Which color do you like?",
"Where are we?",
"Which wells are the best?",
"Who's on first?",
"Cowboys wear white",
"Wells are awesome!",
"Whoooppppeeeeee",
"Which Witch is Which",
"What's going on?",
"Well look at that!"
];


searchBox.addEventListener('keyup', function() {
var searchTerm = searchBox.value.toLowerCase();

// reset ul by removing all li items
while (resultList.hasChildNodes()) {
    resultList.removeChild(resultList.lastChild);
}

// loop through array of sentences
for (var i = 0; i < resultsArray.length; i++) { 
    // if the array item starts with the search value AND the input box is not empty
    if(resultsArray[i].toLowerCase().startsWith(searchTerm) && searchTerm != "") {
        var li = document.createElement('li'); // create an li item
        li.innerHTML = resultsArray[i]; // add the sentence to the new li item
        resultList.append(li); // add new li item to resultList ul
    }
}

// if resultList is empty after going through loop display 'no results found'
if (!resultList.hasChildNodes() && searchTerm != "") {
    var li = document.createElement('li');
    li.innerHTML = "no results found";
    resultList.append(li);
}
});

i want to change var resultsArray items to div class items for example: "Walt Disney", to

 <div class="item"><a href="walt-disney.html"><img src="images/walt-disney.png" alt="walt disney" border="0" /></a>walt disney</div> 
6
  • Like a linked list? Commented Jul 6, 2018 at 22:54
  • Where do the URLs walt-disney.html and images/walt-disney.png come from? Commented Jul 6, 2018 at 22:59
  • 1
    And what does li elements have to do with your desired output? Commented Jul 6, 2018 at 23:01
  • 1
    @ScottMarcus It's apparently a simple search engine, the LI is the list of results. Commented Jul 6, 2018 at 23:02
  • Can you provide the full html as well? With that would be easy to put my solution in a jsfiddle code runner Commented Jul 6, 2018 at 23:08

3 Answers 3

1

Stop creating, appending, and deleting HTMLElement, it's a hassle

To avoid tons of for loops and using document.createElement, .appendChild, and .removeChild. I would suggest using .innerHTML. Along with this, there is no need to rewrite the list of items in resultArray as an object, just modify the strings to match each attribute's requirements, like so:

JavaScript Code:

const searchBox = document.querySelector("input");
const resultList = document.getElementById("resultList");
const resultsArray = [
  "Walt Disney",
  "Which color do you like?",
  "Where are we?",
  "Which wells are the best?",
  "Who's on first?",
  "Cowboys wear white",
  "Wells are awesome!",
  "Whoooppppeeeeee",
  "Which Witch is Which",
  "What's going on?",
  "Well look at that!"
]

String.prototype.removePunctuation = function() {
  return this.replace(/['"`,!?:;.]/g, '')
}

String.prototype.toSnakeCase = function() {
  return this.split(' ').join('-').removePunctuation().toLowerCase()
}

searchBox.addEventListener('keyup', function() {
  const searchTerm = searchBox.value.toLowerCase().trim()
  resultList.innerHTML = ''

  if (searchTerm) {
    const renderedHTML = resultsArray
      .filter(result => result.toLowerCase().indexOf(searchTerm) !== -1)
      .map(result => `
        <div class='item'>
          <a href='${result.toSnakeCase()}.html'>
            <img src='images/${result.toSnakeCase()}.png' alt='${result.removePunctuation()}' border='0'/>
          </a>
        </div>
      `)

    resultList.innerHTML = renderedHTML.length > 0 ? renderedHTML.join('') : 'No results found'
  }
})

HTML Code:

<input type='text' />
<ul id='resultList'>
</ul>

Here are the changes I've made to your code:

  • Remove all elements in <ul> with .innerHTML = ''
  • .trim() whitespace before searching.
  • Iterate over resultsArray with .filter
    • This allows us to determine whether or not an item should be displayed while keeping everything in an array.
  • Then we can use .map to generate the HTML.
    • How does that work? We are using template strings to insert the values into a string to be inserted into .innerHTML

You'll also have noticed that I've created String.prototype.removePunctuation and String.prototype.toSnakeCase. While I wouldn't always suggest modifying String.prototype it does make this code significantly more readable, in my opinion. It wouldn't be hard to convert this to regular functions.

Don't think it works? Test out a working version here on JSFiddle

FYI, in your question you ask for a div with an a that contains an img. The only text showing is the alt='...' attribute, so if you wanted to display the text of the resultsArray you should just use string interpolation: ${result}

Sign up to request clarification or add additional context in comments.

8 Comments

Thanks a lot chbchb55 please guide me on <img src='images/${result.toSnakeCase()} should the images have same names like aray items if "walt disney" <img src='images/walt-disney.png
That's my bad what you want is src='images/${result.toSnakeCase().toLowerCase()}.png which will render src='images/walt-disney.png'
Actually, .toSnakeCase can handle the .toLowerCase as well. I'll change that in the code above.
Lastly help me if array not found, display "no results found" please write it in the code because i'm new to programming. Thanks
For this all you want is another if statement to check the length of renderedHTML or a ternary: condition ? true result : false result
|
1

Change resultsArray to an array of objects with all the information needed to construct the resulting HTML.

var resultsArray = [
{string: "Walt Disney", url: "walt-disney.html", img: "walt-disney.png", alt: "walt disney" },
{string: "Which color do you like?", url: "which-color.html", img: "which-color.png", alt: "which color" },
...
];


if (searchTerm != "") {
    resultsArray.forEach(({string, url, img, alt} => {
        // if the array item starts with the search value AND the input box is not empty
        if(string.toLowerCase().startsWith(searchTerm)) {

            var li = document.createElement('li'); // create an li item
            li.innerHTML = `<div class="item"><a href="${url}"><img src="images/${img}" alt="${alt}" border="0" /></a>${string}</div>`
            resultList.append(li); // add new li item to resultList ul
        }
    }
}

Comments

0

The solution to filter an array of document elements is to look at their innerHTML property, which is a string that we can use to filter based on the search term.

Here's a working solution:

Notes:

  • To keep things simple, I have created the input resultsArray elements in the body and then grabbed them in my script using querySelectorAll() and then parsed them into an Array using Array.prototype.slice().
  • In the filter function, I am looking at the innerHTML property of this input element list array to find the matches.

var searchBox = document.querySelector("input");
var resultList = document.getElementById("resultList");
// Get the results nodes list
var resultsNodeList = document.querySelectorAll('#array-list>div');
// Parse the node list into an array list
var resultsArray = [].slice.call(resultsNodeList);


searchBox.addEventListener('keyup', function() {
  var searchTerm = searchBox.value.toLowerCase();

  // reset ul by removing all li items
  while (resultList.hasChildNodes()) {
    resultList.removeChild(resultList.lastChild);
  }

  // loop through array of sentences
  for (var i = 0; i < resultsArray.length; i++) { 
    // if the array item starts with the search value AND the input box is not empty
    if(searchTerm != "" && resultsArray[i].innerHTML.toLowerCase().indexOf(searchTerm) > -1) {
      var li = document.createElement('li'); // create an li item
      li.appendChild(resultsArray[i]); // add the sentence to the new li item
      resultList.append(li); // add new li item to resultList ul
    }
  }

  // if resultList is empty after going through loop display 'no results found'
  if (!resultList.hasChildNodes() && searchTerm != "") {
    var li = document.createElement('li');
    li.innerHTML = "no results found";
    resultList.append(li);
  }
});
#array-list{
 display: none; 
}
#resultList{
  list-style-type: none;
  -webkit-padding-start: 20px;
}
<div id="array-list">
  <div class="item"><a href="walt-disney.html"><img src="images/walt-disney.png" alt="walt disney" border="0" /></a>walt disney</div>
  <div class="item"><a href="which-color.html"><img src="images/color.png" alt="which color" border="0" /></a>which color</div>
  <div class="item"><a href="where.html"><img src="images/where.png" alt="where are we" border="0" /></a>where are we</div>
  <div class="item"><a href="best-wells.html"><img src="images/best-wells.png" alt="best wells" border="0" /></a>best wells</div>
</div>

<input type="text" placeholder="Type something to search">
<br><br>
<span>Suggestions:</span>
<ul id="resultList">

</ul>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.