0

I have this function which filters a list from a Web Part on my SharePoint page which works great, the only feature I need now if possible is to search only a specified column for the value, as it's currently searching everything within the table. Could someone help as to what I need to add to the below please?

$(document).ready(function () {

    var list = $("table.ms-listviewtable"); // Variable for the list
    var listItems = $("table.ms-listviewtable tr:not(.ms-viewheadertr)"); // Variable for the items within the list
    var input = $("input#filterInput"); // Variable for the users input
    var searchColumn = ("Created By"); // I want to search within this column only

    input.keyup(function () { // When typing the search box, the function runs...
        listItems.each(function () { // For every item in the list...
            var text = $(this).text().toLowerCase(); // Load all the text values...

            if (text.indexOf(input.val().toLowerCase()) != -1) { // Compare the user input to the text value            
                $(this).show(); // If it matches, show it....
            }
            else {
                $(this).hide(); // If not, hide it
            }
        });
    });
});
1
  • Quick question: Are you using IE? And are you required to use jQuery or will vanilla JS be sufficient?
    – KGlasier
    Nov 26, 2019 at 16:53

1 Answer 1

0

Assuming you're using IE and can use vanilla JS rather than jQuery I have a solution that may work. I've tried to comment it so it's easier to follow and removed the bulky jquery that now just slows your browser down. The only real downside right now of not using jQuery is that IE doesn't support most of ES6+ or some functionality of ES5.

The premise you were missing was just finding the column number you're interested in and searching just in that cell. You can use element.querySelectorAll() to get all nodes that meet your criteria then index them like any array. In this case, we used the native attribute for table elements element.cellIndex to get the index of our column and then use that to select the proper column within the table... Which should have the same number of columns as the table header.

I've also added a few checks to see if items returned null. Like the list, or the input box, etc.

If you need the jQuery version of this, let me know and I can convert it, however I would strongly recommend leaving that library behind as many of its functionalities now work in modern browsers natively.

If you need further explanation, let me know.

function searchKey() {
    // Get the list and each item row from current view
    // You can use vanilla JS to use CSS Selectors now. Instead of searching
    // for the list, then for the list and its content, try looking for
    // the content after you've selected the list. 
    var selector = "table.ms-listviewtable";
    var list = document.querySelector(selector);
    if (!list) {
        console.warn('No list found with the selector "' + selector + '" was found.');
        return;
    };
    var listItems = list.querySelectorAll("tr:not(.ms-viewheadertr)");

    // Define the column we're looking for, and make a placeholder variable for it.
    // We will be searching for this column.
    var searchColumnName = 'Created By';
    var searchColumn;

    // Incase you use IE, IE doesn't support forEach on 'NodeLists' which you get back
    // from a querySelector. It's effectively a weaker array. headerRow.forEach(...) will
    // work in modern browsers.
    // Find the column who's text is in `searchColumnName`
    var headerRow = list.querySelectorAll('th');
    for (var i = 0; i < headerRow.length; i++) {
        if (headerRow[i].innerText.trim() === searchColumnName) {
            searchColumn = headerRow[i]
            break;
        }
    }
    if (!searchColumn) {
        console.warn('No column by the name "' + searchColumnName + '" was found.');
        return;
    }

    // Now find all text within that row that has text similar to that searched.
    var searchCell;
    var searchCellText;
    var inputText = this.value.trim().toLocaleLowerCase();
    // Again, listItems.forEach() should work in modern browsers.
    for (var i = 0; i < listItems.length; i++) {
        // The HTMLElement we found has an index on the table. Use that to find the index in
        // our list, assuming that the list has the same number of columns as the header.
        searchCell = listItems[i].querySelectorAll('td')[searchColumn.cellIndex]
        searchCellText = searchCell.innerText
        // If the text exists (ie not null), format it.
        if (searchCellText)
            searchCellText = searchCellText.trim().toLocaleLowerCase();

        // If it's not found, hide... Otherwise place back to Table-Row format.
        if (searchCellText.indexOf(inputText) === -1)
            listItems[i].style.display = 'none'
        else
            listItems[i].style.display = 'table-row'
    }
}

// Wait for the Window to load, then add the keyup event listener to your input
window.addEventListener('load', function () {
    var input = document.querySelector("input#filterInput");
    // incase Input isn't present, don't add the event listener to null object.
    if (input)
        input.addEventListener('keyup', searchKey)
});

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.