I have a simple search script and wanted when a user adds a search term that's not on the list to show: No items found.
JavaScript:
function mySearchFunction() {
// Declare variables
var input, filter, ul, li, item, i, txtValue;
// User Input
input = document.getElementById("myInput");
// Filter, makes search not case sensitive
filter = input.value.toUpperCase();
// Grabs the parent element by id
ul = document.getElementById("stateList");
// Individual item on list
li = ul.getElementsByTagName("li");
// Treats lists items like an array, where each item can be accessed through it's index
for (i = 0; i < li.length; i++) {
item = li[i];
// Iterate over each list item to see if the value of the input, ignoring case, matches the inner text or inner html of the item.
txtValue = item.textContent || item.innerText;
if (txtValue.toUpperCase().indexOf(filter) > -1) {
// Displays list items that are a match, and nothing if no match
li[i].style.display = "";
} else {
li[i].style.display = "none";
}
}
}
HTML:
<input type="text" id="myInput" onkeyup="mySearchFunction()" placeholder="Search">
<ul id="stateList">
<li>One</li>
<li>Two</li>
<li>Three</li>
<li>Four</li>
<li>Five</li>
</ul>
Original script found here: https://codepen.io/rachelhawa/pen/vYBjQMY
You could add a <p> for displaying no result, and have a flag as a condition to display it
Demo
function mySearchFunction() {
// Declare variables
var input, filter, ul, li, item, i, txtValue, noResultMsg;
// User Input
input = document.getElementById("myInput");
// Filter, makes search not case sensitive
filter = input.value.toUpperCase();
// Grabs the parent element by id
ul = document.getElementById("stateList");
// Individual item on list
li = ul.getElementsByTagName("li");
noResultMsg = document.getElementById('no-result-message')
noResultMsg.style.display = "none"
// Treats lists items like an array, where each item can be accessed through it's index
let noResult = true
for (i = 0; i < li.length; i++) {
item = li[i];
// Iterate over each list item to see if the value of the input, ignoring case, matches the inner text or inner html of the item.
txtValue = item.textContent || item.innerText;
if (txtValue.toUpperCase().indexOf(filter) > -1) {
// Displays list items that are a match, and nothing if no match
li[i].style.display = "";
noResult = false
} else {
li[i].style.display = "none";
}
}
if (noResult) {
noResultMsg.style.display = ""
}
}
<input type="text" id="myInput" onkeyup="mySearchFunction()" placeholder="Search">
<ul id="stateList">
<li>Alabama</li>
<li>Alaska</li>
<li>Arizona</li>
<li>Arkansas</li>
<li>California</li>
<li>Colorado</li>
<li>Connecticut</li>
<li>Delaware</li>
<li>Florida</li>
<li>Georgia</li>
<li>Hawaii</li>
<li>Idaho</li>
<li>Illinois</li>
<li>Indiana</li>
<li>Iowa</li>
<li>Kansas</li>
<li>Kentucky</li>
<li>Louisiana</li>
<li>Maine</li>
<li>Maryland</li>
<li>Massachusetts</li>
<li>Michigan</li>
<li>Minnesota</li>
<li>Mississippi</li>
<li>Missouri</li>
<li>Montana</li>
<li>Nebraska</li>
<li>Nevada</li>
<li>New Hampshire</li>
<li>New Jersey</li>
<li>New Mexico</li>
<li>New York</li>
<li>North Carolina</li>
<li>North Dakota</li>
<li>Ohio</li>
<li>Oklahoma</li>
<li>Oregon</li>
<li>Pennsylvania</li>
<li>Rhode Island</li>
<li>South Carolina</li>
<li>South Dakota</li>
<li>Tennessee</li>
<li>Texas</li>
<li>Utah</li>
<li>Vermont</li>
<li>Virginia</li>
<li>Washington</li>
<li>West Virginia</li>
<li>Wisconsin</li>
<li>Wyoming</li>
</ul>
<p id="no-result-message" style="display: none">No result found</p>
You can add one more <li style="display: none">No result</li>
Additionally, you should add:
if (txtValue.toUpperCase().indexOf(filter) > -1) {
// Displays list items that are a match, and nothing if no match
li[i].style.display = "";
li[indexOfNoResult].style.display="none";
} else {
li[i].style.display = "none";
li[indexOfNoResult].style.display="";
}
Related
I am new to Ionic Framwork and Cordova, and trying to add Filter/Search List functionality to a simple App (HTML shown below is served from the server side and accessed by the app). I have added the following pure JavaScript into the 'head' section of my index.html but it does not work in the App. What is the correct way to add it to Ionic App?
function myFunction() {
// Declare variables
var input, filter, ul, li, a, i, txtValue;
input = document.getElementById('myInput-A1');
filter = input.value.toUpperCase();
ul = document.getElementById("myList-A1");
li = ul.getElementsByTagName('li');
//li = ul.querySelectorAll("list-group-item");
// Loop through all list items, and hide those who don't match the search query
for (i = 0; i < li.length; i++) {
a = li[i].getElementsByTagName("a")[0];
txtValue = a.textContent || a.innerText;
if (txtValue.toUpperCase().indexOf(filter) > -1) {
li[i].style.display = "";
} else {
li[i].style.display = "none";
}
}
}
<div>
<input class="form-control" id="myInput-A1" type="text" onkeyup="myFunction()" placeholder="Search item..">
<div>
<div>
<ul class="list-group" id="myList-A1">
<li class="list-group-item">Google </li>
<li class="list-group-item">YouTube</li>
<li class="list-group-item">Microsoft</li>
<li class="list-group-item">Facebook</li>
</ul>
</div>
P.S. I am using Ionic-v3
It seems pure JavaScript works just fine. I have added it to HTML which also contains the ul, li list on server side. Sorry for this trouble.
I've been trying to get my search filter to work but can't get it to work. I'm a beginner but trying my best to make it work. Anyone out there that can help :)
The html
<div class="notes_search">
<input type="search" id="search_input" onkeyup="searchFilter()" placeholder="Search...">
</div>
<ul class="notes_list">
</ul>
<p class="notes_empty-msg">Nothing to show.</p>
</section>
</div>
The Script down bellow.
function searchFilter() {
// Declare variables
var input, filter, ul, li, a, i;
input = document.getElementsById('search');
filter = input.value.toUpperCase();
ul = document.getElementsById('search')[0];
li = ul.getElementsByTagName("li");
for (i = 0; i < li.length; i++) {
a = li[i].getElementsByTagName("a")[0];
if (a.innerHTML.toUpperCase().indexOf(filter)===0) {
li[i].style.display = "";
} else {
li[i].style.display = "none";
}
}
}
There are a number of issues with your code.
First, it's getElementById not getElementsById, but you might find using querySelector and querySelectorAll easier to use as they match to CSS selectors (similar to jQuery).
Second, you don't have an element with a search id.
Third, your HTML contains no list items so it can't search for anything.
Here's a working version with annotations (using some more modern JS methods with which you might not be familiar but which can make the code more succinct). Note: it uses a class to make the items visible or not, and searches within the text content rather than just checking to see if it's at the start of the content which makes it a little more flexible.
function searchFilter() {
// You might find `querySelector` easier to use as it
// allows you to correspond elements with CSS selectors
const input = document.querySelector('#search');
const filter = input.value.toUpperCase();
const ul = document.querySelector('ul');
const lis = ul.getElementsByTagName("li");
for (i = 0; i < lis.length; i++) {
const item = lis[i];
const itemContent = item.textContent.toUpperCase();
// `textContent` might be more appropriate here
// You can use the newer string method `includes`
// to see if `filter` appears in the text content
if (filter.length && itemContent.includes(filter)) {
// Here I've used `classList` as the more modern
// method way of adding and removing classes
item.classList.add('visible');
} else {
item.classList.remove('visible');
}
}
}
li { display: none; }
.visible { display: block }
<div class="notes_search">
<input type="search" id="search" onkeyup="searchFilter()" placeholder="Search...">
</div>
<ul class="notes_list">
<li>Bob</li>
<li>Sue</li>
<li>Rita</li>
<li>Rita and Bob</li>
<li>John</li>
</ul>
<p class="notes_empty-msg">Nothing to show.</p>
</div>
Further reading
classList
String.includes
textContent
You have several things here that are incorrect:
It should be getElementById rather than getElementsById (not plural)
Your input element has the id of "search_input", but you're trying to find an element with the name "search". When looking for an element, it should be the exact name of id, and not a partial word containing it. So try input=document.getElementById('search_input');
Try using innerText rather than innerHtml: innerHtml returns in html format rather than plain text as I remember.
index.html
<div class="notes_search">
<input type="search" id="search_input" onkeyup="searchFilter()" placeholder="Search...">
</div>
<ul class="notes_list">
<li>hi</li>
<li>hi</li>
<li>bye</li>
</ul>
<p class="notes_empty-msg">Nothing to show.</p>
</section>
</div>
index.js
function searchFilter() {
// Declare variables
var input, filter, ul, li, a, i, text;
input = document.getElementById('search_input');
filter = input.value.toUpperCase();
ul = document.getElementsByClassName('notes_list')[0];
li = ul.getElementsByTagName("li");
for (i = 0; i < li.length; i++) {
a = li[i].getElementsByTagName("a")[0];
text = a.textContent || a.innerText;
if (a.innerHTML.toUpperCase().indexOf(filter)===0) {
li[i].style.display = "";
} else {
li[i].style.display = "none";
}
}
}
I also added some li and a tag items to your html, since you didn't have them and it can't find tags that isn't on the html.
I am not fully sure what you are trying to achieve but would a simple html datalist work for your problem:
<input list="your-choices" id="search_input" placeholder="Search...">
<datalist id="your-choices">
<option value="car">
<option value="tree">
<option value="street">
<option value="sky">
<option value="whatever">
</datalist>
You Can search by Jquery
var searchRequest = null;
$(function () {
var minlength = 3;
$("#sample_search").keyup(function () {
var that = this,
value = $(this).val();
if (value.length >= minlength ) {
if (searchRequest != null)
searchRequest.abort();
searchRequest = $.ajax({
type: "GET",
url: "sample.php",
data: {
'search_keyword' : value
},
dataType: "text",
success: function(msg){
//we need to check if the value is the same
if (value==$(that).val()) {
//Receiving the result of search here
}
}
});
}
});
});
I'm trying to make a read out website, with a long text that we can only read out, without any possible scrolling. But I'm not really good with pure JS and I'm a little bit lost. I tried speech recognition and in a second time to make a filter/search list.
In an other side, I'm taking each words of a <p> to separate them in <spans>, because I suppose I have to make something like "When you
hear <span>1</span>, you wait to hear <span>2</span>" and so on...
But for the moment, I'm making a list and not span, like that :
<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Say something..." title="Type in a name">
<ul id="myUL">
<li>Hello world</li>
<li>Bye world</li>
<li>See you world</li>
</ul>
And JS :
function myFunction() {
var input, filter, ul, li, a, i;
input = document.getElementById("myInput");
filter = input.value.toUpperCase();
ul = document.getElementById("myUL");
li = ul.getElementsByTagName("li");
for (i = 0; i < li.length; i++) {
a = li[i].getElementsByTagName("a")[0];
if (a.innerHTML.toUpperCase().indexOf(filter) > -1) {
li[i].style.display = "";
} else {
li[i].style.display = "none";
}
}
}
Then, in a second time I tried to merge it with a speechRecognition input, without success :
<form>
<input type="button" id="btn" value="start" />
</form>
<div id="interimResult"></div>
<div id="finalResult">Let speak</div>
I did a fiddle where I separate the two function now because I didn't find anything...
But, Am I going in the good way... I have to manage long text and <li> are not good, when I'll make it with <span> or anything else, will it be the same method ?
You add a call to myFunction inside recognition.onresult, you also modify myFunction to accept recognized text as an argument, it will do the job:
function myFunction(filter) { // HERE WE TAKE FILTER AS AN ARGUMENT
var ul, li, a, i;
ul = document.getElementById("myUL");
li = ul.getElementsByTagName("li");
for (i = 0; i < li.length; i++) {
a = li[i].getElementsByTagName("a")[0];
if (a.innerHTML.toUpperCase().indexOf(filter) > -1) {
li[i].style.display = "";
} else {
li[i].style.display = "none";
}
}
}
recognition.onresult = function(event) {
var interimTranscript = "";
for (var i = event.resultIndex; i < event.results.length; i++) {
var _transcript = event.results[i][0].transcript;
if (event.results[i].isFinal) {
finalTranscript = StringUtils.capitalize(_transcript);
myFunction(finalTranscript); // <-- HERE IT FILTERS
// USING SPEECH RECOGNITION RESULT
}
It is better to give your function myFunction more meaningful name though, for example filterView is much better name.
I am trying to use this example by w3schools to add a search bar. I can't get it to work, I have changed it to match my elements but with no success. I have to have my js separate from the HTML document so no <script>
My issue is that It does not work, and I do not know how to debug it.
Here is my js file:
//search bar
function myFunction() {
// Declare variables
var input, filter, ul, div, li, a, span, i;
input = document.getElementById('myInput');
filter = input.value.toUpperCase();
ul = document.getElementById("container");
span = ul.getElementsByTagName('span');
// Loop through all list items, and hide those who don't match the search query
for (i = 0; i < li.length; i++) {
a = span[i].getElementsByTagName("a")[0];
if (a.innerHTML.toUpperCase().indexOf(filter) > -1) {
span[i].style.display = "";
} else {
span[i].style.display = "none";
}
}
}
document.getElementById('myInput').addEventListener('keyup', myFunction);
And my HTML file
<div class="container">
<input type="text" id="myInput" placeholder="Search for names..">
<div id="container">
<span>Nico Nico Nii!!</span>
<span>Childish Gambino - Redbone</span>
<span>America F*ck Yeah!</span>
</div>
</div>
Firstly, you have a lot of unnecessary variables. You only need two, one to get the values of the list and the other to get value of filter. If there are more than one element, use class instead. See the working code below:
//search bar
function myFunction() {
var input, filter;
input = document.getElementsByClassName('myLinks');
filter = document.getElementById('myInput').value.toUpperCase();
// Loop through all list items, and hide those who don't match the search query
for (i = 0; i < input.length; i++) {
var currentElem = input[i];
var currentElemChild = input[i].children[0]
if (currentElemChild.innerHTML.toUpperCase().indexOf(filter) > -1) {
currentElem.style.display = "";
} else {
currentElem.style.display = "none";
}
}
}
document.getElementById('myInput').addEventListener('keyup', myFunction);
<div>
<input type="text" id="myInput" placeholder="Search for names..">
<ul id="container">
<li class="myLinks">Nico Nico Nii!!</li>
<li class="myLinks">Childish Gambino - Redbone</li>
<li class="myLinks">America F*ck Yeah!</li>
</ul>
</div>
I am working on some line in JS to do a live search. I have been trying to modify this https://www.w3schools.com/howto/tryit.asp?filename=tryhow_js_filter_list
to do what I am looking for, how ever I cant seem to understand what I am doing wrong. any pointers or corrections are greatly appreciated.
JS it should hide any twit that does not contain the search
var navbarSearchbutton = document.getElementById('navbar-search-button')[0];
navbarSearchbutton.addEventListener('onkeyup', function() {
searchFunction();
});
function searchFunction() {
var input, filter, ul, li, a, i, foo;
foo = document.getElementsByClassName("twit");
input = document.getElementById("navbar-search-input");
filter = input.value.toUpperCase();
li = document.getElementsByClassName("twit-text");
for (i = 0; i < li.length; i++) {
a = li[i].getElementsByTagName("P")[0];
if (a.innerHTML.toUpperCase().indexOf(filter) > -1) {
li[i].style.display = "";
} else {
foo[i].style.display = "none";
}
}
}
HTML for the search box and what I am searching.
<li class="navitem navbar-search">
<input type="text" id="navbar-search-input" placeholder="Search...">
<button type="button" id="navbar-search-button"><i class="fa fa-search"></i></button>
</li>
</ul>
</nav>
</header>
<main class="twit-container">
<article class="twit">
<div class="twit-icon">
<i class="fa fa-bullhorn"></i>
</div>
<div class="twit-content">
<p class="twit-text">
A body in motion must remain in motion unless acted upon by an outside force.
</p>
<p class="twit-attribution">
NewtonRulez
</p>
</div>
First, you are getting ('navbar-search-button by id. So, it will not return an id.
Second, the logic of searching by class name will not work. Below is an updated search function. I kept the same logic you are following to search for items by class names. You will need to to set the class name as twit-attribution for any new entry.
function searchFunction() {
var input, filter, ul, li, a, i, foo;
foo = document.getElementsByClassName("twit");
input = document.getElementById("navbar-search-input");
filter = input.value.toUpperCase();
li = document.getElementsByClassName("twit-attribution");
for (i = 0; i < li.length; i++) {
a = li[i];
if (a.innerHTML.toUpperCase().indexOf(filter) > -1) {
a.style.display = "";
} else {
a.style.display = "none";
}
}
}