3. Quick Search in List View
This article the first of The Power of Content Editor WebPart series. Other parts:
Search is becoming more and more important. Even though SharePoint has pretty powerful search capability, I’m missing an inline quick search/filter for lists. And this is what we’ll do in this article.
A special note before we begin: This quick search is searching only between items in current view and current page, not in the whole list (for example if you have a view limited to 100 items and list contains more than 100 items, the quick search will “filter” only rows in current view.
Our goal and how we’ll do it
Our goal is as follows:
Because the list view is a table, we’ll simply make a script that will look in each row of the list view and check if it contains the search string. If it does, it will set its display css property to table-row, otherwise it will set it to none. Let’s do this sample in a simple contacts list.
Let’s do it
After we insert content editor web part and link to the script as we can see below in the Hello world sample. (How to insert CEWP and manage code are described in earlier parts of this article series).
Hello world works and now we’re ready to start writing our code. Don’t forget to delete the Hello world if you’ve also used it for testing
.
Discovering the DOM object
First we need to discover the HTML DOM object that holds our rows to be filtered with search. As always IE Developer tools to the rescue. Fire up the IE Developer tools and using the HTML selector, click on any of the element in the List View rows.
Next in HTML DOM tree find the object’s parent table. When selected the table will be outlined in the page.
Now let’s verify if this table has any useful ID, name or CSS class that is unique enough. In IE Developer toolbar switch to Attributes sub-tab:
The table has an ID defined by List GUID or View GUID ({D7C5F383-C0B5-4E6C-AB08-C27E1A65EC3B}-{31DFC207-90E8-4A43-8655-4CB90B30AC77}). That may be a bit too specific and we’d have to always modify this for other lists. We need something that is not bound to any List, web, item or site ID. It also has a CSS class ms-listviewtable. This looks promising. So in our source we insert the following code:
<script type="text/javascript">
function getElementsByCssClass(sTagName, sClassName) {
var results = new Array();
var allTagElements = document.getElementsByTagName(sTagName);
for (i = 0; i < allTagElements.length; i++) {
if(allTagElements[i].className == sClassName) results.push(allTagElements[i]);
}
return results;
}
</script>
Save and test the script and table. Reload the page and in browser’s address bar type:
javascript:alert(getElementsByCssClass(“table”,”ms-listviewtable”).length)
If you see an alert like the one below
this means that the script is inserted, works ok and we have only one table with CSS class ms-listviewtable. Good start.
The Search function
Our search function will need to iterate through all rows (except header rows) of the table that we just got and check for content. If content contains our search string, it will show the row, if not it will hide it.
Our JavaScript function will take the term as an parameter for comparing to LV rows.
First let’s put our table in a variable for easier referencing. We’ll use the code from above to get the table by CSS class.
function quickSearch(term) {
var lvTable = getElementsByCssClass("table","ms-listviewtable")[0];
}
Note in the second line above we have to add an index to result, because the getElementsByCssClass function returns an Array of objects.
Next we need to get an array of all table rows. We get those by traversing the DOM tree by using childNodes property which contains an array of all child elements.
var lvRows = lvTable.childNodes[0].childNodes;
In the line above by using lvTable.childNodes[0] we got to TBODY element (even if you don’t have the tbody element in your HTML source, browser renders it). And the lvTable.childNodes[0].childNodes returns an array of all table rows.
To preview results of a function let’s add a temp alert here:
alert(lvRows.length);
Our quickSearch function until now looks as follows:
function quickSearch(term) {
var lvTable = getElementsByCssClass("table","ms-listviewtable")[0];
var lvRows = lvTable.childNodes[0].childNodes;
alert(lvRows.length);
}
We can test it in the bowser, by refreshing URL and typing the following in the addressbar:
javascript:quickSearch()
In the example above we now know that we have 101 table rows – 100 rows of a data view + 1 table headers.
Now it’s time to iterate through rows and compare their texts. The problem here arises in IE / FF compatibility. In IE you get the element’s text with innerText property. In FF you get it with textContent property. So for avoiding this issue we’ll prepare a small helper function:
function getTxt(obj) {
if(obj.innerText) return obj.innerText;
else return obj.textContent;
}
Now we update our quickSearch function. First delete the alert we’ve had for debugging and add a for loop for all rows but the first:
for(i = 1; i < lvRows.length; i++) {
}
and in that loop we’ll compare the search term to row’s inner text:
if(getTxt(lvRows[i]).toLowerCase().indexOf(term.toLowerCase()) > -1)
and in this condition we set the table row’s display property to “table-row”.
Our quickSearch function now looks as follows:
function quickSearch(term) {
var lvTable = getElementsByCssClass("table","ms-listviewtable")[0];
var lvRows = lvTable.childNodes[0].childNodes;
for(i = 1; i < lvRows.length; i++) {
if(getTxt(lvRows[i]).toLowerCase().indexOf(term.toLowerCase()) > -1) {
lvRows[i].style.display = "table-row";
}
else lvRows[i].style.display = 'none';
}
}
Adding a search box
Now that we have the function ready, we need a search box that will be calling this function.
Outside of JavaScript block in the source code add the following:
Quick Search: <input class="ms-long" type="text" onkeyup="quickSearch(this.value)" />
This will add a textbox with SharePoint’s native ms-long css style class (for styling purposes) and with an event after key has been pressed – to call the quick search function with its typed value.
Optimizing code a bit
Now the quick search is ready and can already be used. But if we look at the code, we can see that each time the key is pressed the quicksearch function will query the getElementsByCssName to find the table and the getElementsByCssName searches through entire DOM. We can optimize this code by putting lvRows variable ouside the function and populate it only once. This way we’ll have table rows always available and we won’t need to query them over and over again.
Our modified function looks as follows:
var lvRows = null;
function quickSearch(term) {
if(lvRows == null) {
var lvTable = getElementsByCssClass("table","ms-listviewtable")[0];
lvRows = lvTable.childNodes[0].childNodes;
}
...
To sum it all up:
As always if you don’t want to look at bits of the code through this article and just get the entire code, the entire code is below:
<script type="text/javascript">
function getElementsByCssClass(sTagName, sClassName) {
var results = new Array();
var allTagElements = document.getElementsByTagName(sTagName);
for (i = 0; i < allTagElements.length; i++) {
if(allTagElements[i].className == sClassName) results.push(allTagElements[i]);
}
return results;
}
function getTxt(obj) {
if(obj.innerText) return obj.innerText;
else return obj.textContent;
}
var lvRows = null;
function quickSearch(term) {
if(lvRows == null) {
var lvTable = getElementsByCssClass("table","ms-listviewtable")[0];
lvRows = lvTable.childNodes[0].childNodes;
}
for(i = 1; i < lvRows.length; i++) {
if(getTxt(lvRows[i]).toLowerCase().indexOf(term.toLowerCase()) > -1) {
lvRows[i].style.display = "table-row";
}
else lvRows[i].style.display = 'none';
}
}
</script>
Quick Search: <input class="ms-long" type="text" onkeyup="quickSearch(this.value)" />
Other articles from this series:



Ran across this and thought it was a great solution. However, I have run across issues when a user is using IE6 or IE7. For some reason they receive the dreaded “Could not get the display property.” error. I will admit that I am not as proficient with JS as I should and therefore thought it had to do with the double quotes used on line 25. No dice though. When I test using IE8, it works like a charm.
I also had to modify the getElementsByCssClass function, replacing line 6 with the code below to allow for multiple class names — class=”aClass bClass”.
var className=allTagElements[i].className;
if(className.match(sClassName)) results.push(allTagElements[i]);
Any ideas what could be going on?
Hello, MJM. Thanks for sharing this. It’s true. IE7 and prior don’t know how to handle the display property if it isn’t explicitly specified as an element attribute. I’ll have to modify the script a bit. Also thanks for pointing out the getelementsbycssclass method. True it’s matching only if Css class is exactly the same. I’ll modify this also.
Hello Boris.
I’m a beginner in SharePoint and in JS as well. I found your script very interesting but unfortunately I use IE7 and when I implemented your script I got JS errors. I assume that is the same thing as MGM is talking about. Can you give some hint how to fix this script that will work for IE7 ?
Thank you very much. I learned a lot of things from your site!
Best Regards.
To get it working in ie6 I had to change any
…style.display = “table-row”;
to
…style.display = “block”;
This is just a wonderful tutorial. I’ve modified it to only filter on enter, added a clear search results button and allowed it to search for wildcard style for multiple terms separated by spaces.
I am wondering, however, if there is a way to have this functionality on all the rows, including the ones not in view, or on metadata that is not in view. I don’t suppose there is anyway you know of doing this, hm?
Hello, Krit! I was wondering, since you manipulated the code so well, is it possible to make the filter point to a specific webpart? I am asking because I have a page with many wbeparts, and need teh search to filter just one webpart.
Thanks!
Rudy
Can something like this ever work with dataview or does it require direct list view?
If you’re working with SharePoint Designer’s Data View Webpart you can. It’s even easier, because you can completely customize table, rows’ ids and properties.
@Krit: Yes, I was using the style.display = “block” too. But browsers like FireFox or Chrome don’t like this display property for table rows. If you’re using IE, then there is no problem. Otherwise yes, you can make this on all rows. You’d have to get all rows in document. But the script gets a bit more complex here because if you hide a parent table row all the child table rows get hidden.
@Alex: The problem in IE7 is that it’s unable to get the “display” property of an HTML element if it doesn’t have it explicitly declared. A better alternative is to use CSS classes to ensure it would work also in IE7. For the fastest I’d recomend updating to IE8, but I’ll also update this article to be working with CSS classes instead of directly display properties.
What a super tool!!!! And so simple to deploy!
Boris, thank you very much for that thing!!!!!
Excellent tool – it worked straight out of the box.
Thanks
Iain
Great script and easy to follow for us “non-coders”. Can you show me how to narrow down my search to only look in say, the “user” column? Thanks.
Hey, we “non-coders” aren’t so dumb after all!
var lvTable = getElementsByCssClass(“table”,”ms-listviewtable”,”user”)[0];
searched only the “user” column.
thanks again.
how can I use this for link list. I created Link list for team sites( 123 team sites) and add to page (web part) I want to use this quick search feature to search that list.
The above code dosen’t work for link list. Appreciate any solution for above issue.
Thanks
venu
Hi I’m using internet explorer 8 and i’m not able get any results after i hit enter after putting my strings
please help
thanks
Boris.
I would like to use this view to filter 1 webpart list in a page that has 5 or 6 other wbepart lists. Is it possible to use a table-specific designator (like GUID) to enable this filter to this?
Thanks!
Nice code you got there, unfortunately….
1) This code wont work with grouped list.
Is there any workaround on how to settle this one?
2) You won’t get the same searched result if you move to next result page. Let say you got limit 50 rows per-view & the result return you with 3 page of result (150 rows), the 2nd(51-100 rows) & 3rd(101-150 rows) result page wont display the correct result as it should.