Skip to content
View in the app

A better way to browse. Learn more.

Web Designer Forum

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

Search form on plain javascript

Featured Replies

Good night:)

For my current progect we don't use jQuery, so i need to rewrite this function on plain js.

$('#search').keyup(function () {
var yourtext = $(this).val();
if (yourtext.length > 0) {
var abc = $("li").filter(function () {
var str = $(this).text();
var re = new RegExp(yourtext, "i");
var result = re.test(str);
if (!result) {
return $(this);
}
}).hide();
} else {
$("li").show();
}
});

Working perfect but i don't want include jquery only for this in my app. I tried this solution but it seems not work.

 



(function () {
    var searchKey = document.getElementById("search_box"),
        booksFiltered = document.querySelectorAll(".text blocks");
    searchKey.addEventListener("keyup", function () {
        var yourtext = this.value;
        for (var i = 0; i < booksFiltered.length; i++) {
            var a = booksFiltered[i];
            if (yourtext.length > 0) {
                var abc = a.filter(function (el) {
                    var str = el.data;
                    var re = new RegExp(yourtext, "i");
                    var result = re.test(str);
                    if (!result) {
                        return el;
                    }
                    return result;
                });
                booksArray.classList.add(hid); //hidden
            } else {
                booksArray.classList.add(vis); // visible
            }
        }
    });
})();
Please, point me on my mistake. I have headache already:)))
Forget to say? that i need to search text only in one page. After searching only needed text have to be on the page,. Rest text articles need to be hidden. Thank you for any advice about my mistakes. :)

Edited by fleur

I am assuming your books are stored in a bunch of li elements? This seems a really strange way to get data. In reality you'd be using some kind of backend API that would be supplying you with some JSON data which you could then filter through (Assuming the API contained all the books in the DB, although again - the search function would be more of a task for the Backend, maybe look to doing this:

 

Store a json file and write a basic API in Node that loads that file and is called when you submit the search box - you can use ajax in your client side script to send the search request to the Node API, which can then load the json and use the query to filter out the results. And then send a response back to the client containing the filtered results.

Then in your client script you can collate the results into a HTML string and insert them into the DOM.

 

One thing to bear in mind with DOM insertions - they are costly, so don't do them inside of loops. You build up a html string using concatenation for each loop iterration, and then once the loop has exited then push the entire collection to the DOM. A single write to the DOM will be far more efficient than multiple smaller insertions.

 

This whole thing sounds like it would make for an interesting blog post. If I get time at the weekend I'll write something like I am describing here (But the Ajax request will be using jQuery, there's a number of issues doing Ajax with the native DOM API that jQuery has smoothed over.)

It sounds like you're looking to do more of a list style search. I think JS is suitable for this. Where client-side JS wouldn't be suitable, is any advanced searching and relational data lookups. This is typically backend work, and depending on how many results you're searching through, can be difficult to optimise.

 

I've used List JS on quite a few projects. It's great for dashboards and similar UI where you only need basic searching and filtering. This plugin is well built, the developer has good experience with JS, and it has been performance tested on 1000's of rows. Depending on how many item's you could be searching through, it's worth running some tests first http://www.listjs.com/performance.

That list.js does look very well written.

My argument is (although may not stand in all cases) is: Whatever was used to populate the DOM initially with the list of items should store that data before it inserts it to the DOM, then when you make some kind of query, filter, search you then use the stored data rather than doing lots of DOM lookups, which no matter how well written are many times slower than accessing an object / array in JS.

This principle is one of the reasons why React is so fast - manipulating a virtual DOM, is many times faster than the real one. I've have always wondered though, why is the DOM so slow..?

 

On second thought you probably don't need to use the backend to do the searching, if the servers get a lot of traffic it's kind of nice to let the client side deal with searching if they already have the data stored somewhere (assuming it's not many megaybtes in size).. but as a bit of a side project it would be interesting to build anyway.

 

I'm just thinking out aloud though -- as if I were building the whole thing from scratch, of course if you cannot do that then something like list.js would definitley be a good option.

Edited by rbrtsmith

I think it depends on what you need to do. The last time I used List, it was to search about 50 or so documents on a dashboard grid. It's much faster than querying a DB and returning the results, but in cases where you have larger data sets, you would want to handle this on the server.

 

(function () {
    var searchKey = document.getElementById("search_box"),
        booksFiltered = document.querySelectorAll(".text blocks");
    searchKey.addEventListener("keyup", function () {
        var yourtext = this.value;
        for (var i = 0; i < booksFiltered.length; i++) {
            var a = booksFiltered[i];
            if (yourtext.length > 0) {
                var abc = a.filter(function (el) {
                    var str = el.data;
                    var re = new RegExp(yourtext, "i");
                    var result = re.test(str);
                    if (!result) {
                        return el;
                    }
                    return result;
                });
                booksArray.classList.add(hid); //hidden
            } else {
                booksArray.classList.add(vis); // visible
            }
        }
    });
})();

Shouldn't "el" be declared somewhere ? Or is it a parameter definition that will point to an object created by the filter method, how can that work ???

Edited by Nillervision

Shouldn't "el" be declared somewhere ? Or is it a parameter definition that will point to an object created by the filter method, how can that work ???

 

the filter function is a callback, and el refers to the current element on the array that filter is looping over.

I think it depends on what you need to do. The last time I used List, it was to search about 50 or so documents on a dashboard grid. It's much faster than querying a DB and returning the results, but in cases where you have larger data sets, you would want to handle this on the server.

 

I don't mean to query the db everytime you do some kind of filtering, i mean when the page first renders the backend must get the data from the database.. so before pushing all that to the Dom, it can be stored as a variable or in localStorage to be later referenced.

I think using the DOM as a far as data storage / retreval should be an absolute last resort.

 

I agree that we should do things differently for much larger chunks of data.

 

I don't mean to query the db everytime you do some kind of filtering, i mean when the page first renders the backend must get the data from the database.. so before pushing all that to the Dom, it can be stored as a variable or in localStorage to be later referenced.

I think using the DOM as a far as data storage / retreval should be an absolute last resort.

 

I agree that we should do things differently for much larger chunks of data.

 

I sort of get that idea of storing the data to use later on. I don't really know enough about it though.

 

I think in this case the data would already be there, and loaded into the DOM. Let's say you're outputting a list of 50 documents on a page into a list, the data is already there to work with, you just have to show/hide items based on a value entered. In some cases, users might not even use the search, so there won't be any performance hit.

  • Author

Shouldn't "el" be declared somewhere ? Or is it a parameter definition that will point to an object created by the filter method, how can that work ???

 

No, it's not parameter. I tried to write "this" instead of el, but it doesn't work. I spend several houres for nothing. Can't understand where is my mistake.

 

rbrtsmith

rbrtsmith said:"the filter function is a callback, and el refers to the current element on the array that filter is looping over." Yes. But it is not working with it. I write for loop, also doesn't work.

Edited by fleur

  • Author

I am assuming your books are stored in a bunch of li elements? This seems a really strange way to get data. In reality you'd be using some kind of backend API that would be supplying you with some JSON data which you could then filter through (Assuming the API contained all the books in the DB, although again - the search function would be more of a task for the Backend, maybe look to doing this:

 

Store a json file and write a basic API in Node that loads that file and is called when you submit the search box - you can use ajax in your client side script to send the search request to the Node API, which can then load the json and use the query to filter out the results. And then send a response back to the client containing the filtered results.

Then in your client script you can collate the results into a HTML string and insert them into the DOM.

 

One thing to bear in mind with DOM insertions - they are costly, so don't do them inside of loops. You build up a html string using concatenation for each loop iterration, and then once the loop has exited then push the entire collection to the DOM. A single write to the DOM will be far more efficient than multiple smaller insertions.

 

This whole thing sounds like it would make for an interesting blog post. If I get time at the weekend I'll write something like I am describing here (But the Ajax request will be using jQuery, there's a number of issues doing Ajax with the native DOM API that jQuery has smoothed over.)

 

Not li, books is div. And whole app works fine. JSON already here. Everything is fine! Function working in iQuery. I simply need to rewrite this function in vanilla JS. Nothing more:) Ajax maybe used here for loading rest pages into one. But now i have only task that i told.

Edited by fleur

  • Author

 

I sort of get that idea of storing the data to use later on. I don't really know enough about it though.

 

I think in this case the data would already be there, and loaded into the DOM. Let's say you're outputting a list of 50 documents on a page into a list, the data is already there to work with, you just have to show/hide items based on a value entered. In some cases, users might not even use the search, so there won't be any performance hit.

 

Yes. you are write. But if your load lots of text block, searching must be here. I don't want to load whole jquery only for one search function :(

Edited by fleur

I see. Thanks

 

If you want any further info on filter then MDN is a good place https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

 

Their documentation for things like map, reduce and so on are very thorough.

 

also:

 

 

These high order array methods are really elegant, there's literally no need to use loops when dealing with arrays now, these can be substituted in any instance, their names make things a lot more clear of what is going on :)

Edited by rbrtsmith

fleur, querySelectorAll returns a nodeList not an Array. You can't use Array methods on a nodeList you first need to convert it into an Array.

Array.prototype.slice.call(document.querySelectorAll('.text_blocks'));

$.filter is different as it's a custom function designed to work on any collection.

I'm not sure what your HTML structure is. You say you're working with divs not a list, but your jQuery is filtering a list?

Anyway, I typed this out, maybe it'll help.
http://jsfiddle.net/p5f7vjfu/

^Ah! Well spotted. That would confuse me to because of the similarities between the two types of collections. Eg. they both have the .lenght property that we always use in loops.

 

Speaking of querySelectorAll: If your elements just have a single class wouldn't getElementsByClassName (which would return the same nodelist) be faster?

 

I remember when both these "selectors" was introduced I was warned about performance isues with both and it was recomended to use getElementsByTagName and filter out the class names in a loop. But that was a long time ago and I guess browser implementation for the "new" selectors have improved.

 

What are your experience with performance for the different methods?

 

EDIT: I guess jQuery and other libraries will choose the best method depending on what you pass as selector argument

Edited by Nillervision

Yeah the node list is an array like object. As Wynn pointed out you can borrow functions from the Array prototype and pass in the node-list as the this argument:

[].forEach.call(document.querySelectorAll('.text_blocks'), function(node) {
   // do stuff with each node
});

It's pretty horrible to have to do this, I'm sure there's a good reason why node-lists and the arguments parameter are not true arrays but I'm not seeing it!

Edited by rbrtsmith

Technically getElements... returns a HTMLCollection, while querySelector... returns a NodeList.

What the differences are I'm not entirely sure, I usually end up converting them to an array anyway.

But I find querySelector more 'one size fits all'.

There will always be a slight performance hit when using anything that's newer, because most of the time one is just an abstraction of the other, such as Array.forEach vs a for loop. But the difference isn't noticeable unless you micro analyze with tools such as JSPerf.

Hm... Yet another collection. Like Robert said: it's difficult to see the reason why. At least the arrays you declare your self are the same type in JS though they can be in {object} notation or [squarebracket] notation, with key value pairs or numeric indexes, they would technically be the same type of object (with same methods) Or am I wrong?

In some languages there are different type arrays eg. for fixed indexes. You can not push data into a C# Array because the number of indexes can only be set on creation. If you want to add to a collection must use ArrayList or a List. CRAZY :crazy:

@@fleur : Sorry for getting off topic here. Sometimes my mind just wanders off

Edited by Nillervision

  • Author

Wynn, awesome solution, million thanks, of cause, it works! :) I didn't think that filter can be replaced with ? operator, very elegant solution!

 

PS. I tried to typing it not a one time. Because google blocked me (I don't know why!) and now i use internet from IE. Crasy day:) So.. i understand Niller very well, i have the same mind now because today i got so much problems at the same time and i don't know how live till tomorrow :) Hope i will :)

 

PS1. And how much time i should wait when google return me ability to use Chrome again? I can't develop my app with IE!

Edited by fleur

  • Author

Robert, thank you for video! I like Mattias video very much too!

 

PS2. Quote don't working in IE.

Edited by fleur

^Totally share @@fleur s gratitude. I'm so happy that the JS experts here at WDF are so helpful and willing to share their knowledge. As JavaScript is becomming more and more prominent in modern web development, it is really nice for an oldtimer like me to have someone that are so willing to answer my questions. So times things can go a bit fast though. But in the last few months I've learned the concepts of closures, @@rbrtsmith have finaly made me understand some of the advantages of Object.create() without constructers and without the new keyword, @@Lyndsey taught me event delegation and now I see this super slick aproach to replace my clumsy for loops. I love WDF :)

Edited by Nillervision

  • Author

 

 

I love WDF

 

Yes, me too:)

Create an account or sign in to comment

Account

Navigation

Search

Search

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.