How to sort tables with js/html












0















I have a table :



Name | Department | status 


I sorted the names alphabetically on click but now I created a dropdown in the status cell which displays values such as Inside/Outside and I want to sort the table when I click on one of those filters I want to only see the people who are in/out. my current JS function :



function sortStatusDesc() {
var table, rows, switching, i, x, y, shouldSwitch;
table = document.getElementById("myTable");
switching = true;

while (switching) {
switching = false;
rows = table.rows;

for (i = 1; i < (rows.length - 1); i++) {
shouldSwitch = false;
x = rows[i].getElementsByTagName("th")[2];
y = rows[i + 1].getElementsByTagName("th")[2];

if (x.innerHTML.toLowerCase() < y.innerHTML.toLowerCase()) {
shouldSwitch = true;
break;
}
}
if (shouldSwitch) {
rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
switching = true;
}
}
}


It sorts alphabeticaly.










share|improve this question




















  • 1





    Have you considered sorting the data and then rendering the sorted data? I'd imagine it would be a little faster as you wouldn't initially have to read all of the data from the DOM.

    – JO3-W3B-D3V
    Nov 21 '18 at 9:04






  • 2





    You usually don't actually sort rows. If you use a render() function that turns an array of data objects into a HTML table to render the table you have, you can just sort that array of source data using the array.sort() method and then just rerender the table.

    – Shilly
    Nov 21 '18 at 9:04











  • @Shilly I'm glad to see we're on the same page here!

    – JO3-W3B-D3V
    Nov 21 '18 at 9:05











  • I m new to javascript so any code would be useful

    – Em44
    Nov 21 '18 at 9:13











  • @Shilly are you going to post some code or ?

    – Em44
    Nov 22 '18 at 13:43
















0















I have a table :



Name | Department | status 


I sorted the names alphabetically on click but now I created a dropdown in the status cell which displays values such as Inside/Outside and I want to sort the table when I click on one of those filters I want to only see the people who are in/out. my current JS function :



function sortStatusDesc() {
var table, rows, switching, i, x, y, shouldSwitch;
table = document.getElementById("myTable");
switching = true;

while (switching) {
switching = false;
rows = table.rows;

for (i = 1; i < (rows.length - 1); i++) {
shouldSwitch = false;
x = rows[i].getElementsByTagName("th")[2];
y = rows[i + 1].getElementsByTagName("th")[2];

if (x.innerHTML.toLowerCase() < y.innerHTML.toLowerCase()) {
shouldSwitch = true;
break;
}
}
if (shouldSwitch) {
rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
switching = true;
}
}
}


It sorts alphabeticaly.










share|improve this question




















  • 1





    Have you considered sorting the data and then rendering the sorted data? I'd imagine it would be a little faster as you wouldn't initially have to read all of the data from the DOM.

    – JO3-W3B-D3V
    Nov 21 '18 at 9:04






  • 2





    You usually don't actually sort rows. If you use a render() function that turns an array of data objects into a HTML table to render the table you have, you can just sort that array of source data using the array.sort() method and then just rerender the table.

    – Shilly
    Nov 21 '18 at 9:04











  • @Shilly I'm glad to see we're on the same page here!

    – JO3-W3B-D3V
    Nov 21 '18 at 9:05











  • I m new to javascript so any code would be useful

    – Em44
    Nov 21 '18 at 9:13











  • @Shilly are you going to post some code or ?

    – Em44
    Nov 22 '18 at 13:43














0












0








0


1






I have a table :



Name | Department | status 


I sorted the names alphabetically on click but now I created a dropdown in the status cell which displays values such as Inside/Outside and I want to sort the table when I click on one of those filters I want to only see the people who are in/out. my current JS function :



function sortStatusDesc() {
var table, rows, switching, i, x, y, shouldSwitch;
table = document.getElementById("myTable");
switching = true;

while (switching) {
switching = false;
rows = table.rows;

for (i = 1; i < (rows.length - 1); i++) {
shouldSwitch = false;
x = rows[i].getElementsByTagName("th")[2];
y = rows[i + 1].getElementsByTagName("th")[2];

if (x.innerHTML.toLowerCase() < y.innerHTML.toLowerCase()) {
shouldSwitch = true;
break;
}
}
if (shouldSwitch) {
rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
switching = true;
}
}
}


It sorts alphabeticaly.










share|improve this question
















I have a table :



Name | Department | status 


I sorted the names alphabetically on click but now I created a dropdown in the status cell which displays values such as Inside/Outside and I want to sort the table when I click on one of those filters I want to only see the people who are in/out. my current JS function :



function sortStatusDesc() {
var table, rows, switching, i, x, y, shouldSwitch;
table = document.getElementById("myTable");
switching = true;

while (switching) {
switching = false;
rows = table.rows;

for (i = 1; i < (rows.length - 1); i++) {
shouldSwitch = false;
x = rows[i].getElementsByTagName("th")[2];
y = rows[i + 1].getElementsByTagName("th")[2];

if (x.innerHTML.toLowerCase() < y.innerHTML.toLowerCase()) {
shouldSwitch = true;
break;
}
}
if (shouldSwitch) {
rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
switching = true;
}
}
}


It sorts alphabeticaly.







javascript html






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 22 '18 at 19:29









kit

1,1063816




1,1063816










asked Nov 21 '18 at 9:02









Em44Em44

96




96








  • 1





    Have you considered sorting the data and then rendering the sorted data? I'd imagine it would be a little faster as you wouldn't initially have to read all of the data from the DOM.

    – JO3-W3B-D3V
    Nov 21 '18 at 9:04






  • 2





    You usually don't actually sort rows. If you use a render() function that turns an array of data objects into a HTML table to render the table you have, you can just sort that array of source data using the array.sort() method and then just rerender the table.

    – Shilly
    Nov 21 '18 at 9:04











  • @Shilly I'm glad to see we're on the same page here!

    – JO3-W3B-D3V
    Nov 21 '18 at 9:05











  • I m new to javascript so any code would be useful

    – Em44
    Nov 21 '18 at 9:13











  • @Shilly are you going to post some code or ?

    – Em44
    Nov 22 '18 at 13:43














  • 1





    Have you considered sorting the data and then rendering the sorted data? I'd imagine it would be a little faster as you wouldn't initially have to read all of the data from the DOM.

    – JO3-W3B-D3V
    Nov 21 '18 at 9:04






  • 2





    You usually don't actually sort rows. If you use a render() function that turns an array of data objects into a HTML table to render the table you have, you can just sort that array of source data using the array.sort() method and then just rerender the table.

    – Shilly
    Nov 21 '18 at 9:04











  • @Shilly I'm glad to see we're on the same page here!

    – JO3-W3B-D3V
    Nov 21 '18 at 9:05











  • I m new to javascript so any code would be useful

    – Em44
    Nov 21 '18 at 9:13











  • @Shilly are you going to post some code or ?

    – Em44
    Nov 22 '18 at 13:43








1




1





Have you considered sorting the data and then rendering the sorted data? I'd imagine it would be a little faster as you wouldn't initially have to read all of the data from the DOM.

– JO3-W3B-D3V
Nov 21 '18 at 9:04





Have you considered sorting the data and then rendering the sorted data? I'd imagine it would be a little faster as you wouldn't initially have to read all of the data from the DOM.

– JO3-W3B-D3V
Nov 21 '18 at 9:04




2




2





You usually don't actually sort rows. If you use a render() function that turns an array of data objects into a HTML table to render the table you have, you can just sort that array of source data using the array.sort() method and then just rerender the table.

– Shilly
Nov 21 '18 at 9:04





You usually don't actually sort rows. If you use a render() function that turns an array of data objects into a HTML table to render the table you have, you can just sort that array of source data using the array.sort() method and then just rerender the table.

– Shilly
Nov 21 '18 at 9:04













@Shilly I'm glad to see we're on the same page here!

– JO3-W3B-D3V
Nov 21 '18 at 9:05





@Shilly I'm glad to see we're on the same page here!

– JO3-W3B-D3V
Nov 21 '18 at 9:05













I m new to javascript so any code would be useful

– Em44
Nov 21 '18 at 9:13





I m new to javascript so any code would be useful

– Em44
Nov 21 '18 at 9:13













@Shilly are you going to post some code or ?

– Em44
Nov 22 '18 at 13:43





@Shilly are you going to post some code or ?

– Em44
Nov 22 '18 at 13:43












3 Answers
3






active

oldest

votes


















1














The folllowing snippet shown the sorting on any property.
Clicking on one of the property header changes the sorting.



In the same way, you can create the filtering. Instead of sorting the source_data on a particular property with data.sort(), you would data.filter() for all the entries that have the correct value.






//	Name of the data we're rendering.
const source_name = 'Locations';
// Source data we want to create a table from.
const source_data = [
{ "id": 1, "name": "production hall", "department": "production", "status": "inside" },
{ "id": 2, "name": "spare parts room", "department": "production", "status": "inside" },
{ "id": 3, "name": "warehouse", "department": "production", "status": "inside" },
{ "id": 4, "name": "loading bay", "department": "production", "status": "outside" },
{ "id": 5, "name": "offices HR", "department": "administration", "status": "inside" },
{ "id": 6, "name": "offices QA", "department": "administration", "status": "inside" },
{ "id": 7, "name": "security lounge", "department": "administration", "status": "outside" }
];
// Create the table.
// For this example, we'll use string manipulation to create the HTML.
// For complex layouts a templating system is better.
const render = ( name, data ) => {
// Always include a header for the name.
// When there's 0 rows, we'll still know what the table shows.
const labels = data.length
? '<tr>' + Object.keys( data[ 0 ]).map( name => `<th data-attr="${ name }">${ name }</th>` ).join( '' ) + '</tr>'
: '';
// Actual header for the properties of our data.
const header = `<tr><th colspan="${ data.length || 1 }">${ name }</th></tr>${ labels }`;
// One row for each entry in our data.
const rows = data.map( entry => (`<tr id="entry_${ entry.id }">` + Object.values( entry ).map( value => `<td>${ value }</td>` ).join( '' ) + '</tr>' )).join( '' );
// Merge it all together.
const table = `<table><thead>${ header }</thead><tbody>${ rows }</tbody></table>`;
// Render into the page.
document.querySelector( '#output' ).innerHTML = table;
};
// Sort of the property.
const sort = ( data, property ) => {
// Sort the data on the property in alphabetical order.
return data.sort(( first, second ) => {
if ( first[ property ] < second[ property ] ) return -1;
else if ( first[ property ] > second[ property ] ) return 1;
else return 0;
});
};
// Add click events to the header so that clicking a header will sort the rows.
const add_sorting = function( table ) {
Array
.from( table.querySelectorAll( 'th' ))
.forEach( header => header.addEventListener( 'click', create_table ));
};
// Main function
const create_table = event => {
// We'll reuse this function both manually and through clicking
const property = event && event.target
? event.target.getAttribute( 'data-attr' )
: event;
const collection = sort( source_data, property );
render( source_name, collection );
add_sorting( document.querySelector( 'table' ));
};
create_table( 'name' );

th, td {
border: 1px solid grey;
}

<div id="output"></div>








share|improve this answer

































    0














    A table section can easily be sorted according to a comparator function (e.g. "is this cell supposed to appear before that cell?", Math.min, for example) using any comparison sort algorithm, here demonstrating the insertion sort, less than 10 lines of actual table sorting code:



    class InsertionSort {
    static sort_children(parent, comparator) {
    for(let i = 0; i != parent.children.length; i++) {
    const current = parent.children[i];
    let element;
    for(element = current.previousElementSibling; element && comparator(current, element); element = element.previousElementSibling);
    parent.insertBefore(current, element ? element.nextElementSibling : parent.firstElementChild);
    }
    }
    }


    Having a table section (or a table) (the parent argument to sort_children above) with an amount of rows as children, you can sort it with the sort_children method defined above, as long as you yourself rightfully define how your rows should compare:



    InsertionSort.sort_children(your_table, (row_A, row_B) => row_A.cells[0].textContent < row_B.cells[0].textContent);


    The above sorts table rows so that the cells of the first column appear in lexicographical order.



    The second argument to sort_children is the aforementioned comparator function comparator(row_A, row_B), which is expected to return true for any two rows it is passed where row_A should appear before row_B, and false otherwise. Since you provide the comparator function, you decide how your rows are sorted.



    You can further adapt the comparator function by creating a function that returns a comparator which would be specific to a particular table column, according to a value format (text, number, etc), using the < operator automatically (which is defined for Number and String, among other types):



    const table_cell_comparator = (column_index, type) => ((row_A, row_B) => type(row_A.cells[column_index].textContent) < type(row_A.cells[column_index].textContent));


    Then invoking table sorting with a less verbose and more readable expression:



    InsertionSort.sort_children(your_table, table_cell_comparator(1, Number)); 


    The above sorts the rows so that cells of second column with lower numeric value appear before cells with higher numeric value.






    share|improve this answer

































      0














      "Filtering" a table, as it is called, with existing rows, can easily be done with class toggling, among other things:



      function filter_table(section, predicate) {
      for(const row of section.rows) row.classList.toggle("filtered", predicate(row));
      }


      What happens above is that rows of an entire table or table section (section above) that the predicate function considers "filtered", are marked as such by toggling the "filtered" class on these.



      The predicate function is a function of your own design and choosing that accepts a table row and returns true if the row should be filtered or false otherwise.



      Taking your use case with employee rows, for instance, where let's say the 3rd table cell of every row contains a select (drop-down) control with one option for "In" and one option for "Out":



      <tr><!-- ... --><td><select><option value="in">In</option><option value="out">Out</option></select></tr>


      You can write the predicate that will filter employee rows according to either "In" or "Out" status ("in" in the example), as follows:



      const predicate = row => row.cells[2].firstElementChild.value == "in";


      How you style filtered rows is up to you, you may want to simply hide them, of course:



      tr.filtered {
      display: none;
      }


      Since the status of each employee effectively changes with the change in drop-down selection, you would be wasting resources by invoking filter_table for every such change, which then would go through all the rows again. It is then a much better idea to listen on the "change" event that would be fired by the select control as it changes its value:



      table.addEventListener("change", event => {
      if(event.target instanceof HTMLSelectElement) {
      const row = event.target.parentElement.parentElement;
      row.classList.toggle("filtered", predicate(row));
      }
      })


      You only need to attach a single listener to the entire table -- "change" events bubble up the element tree. The predicate function defined above is reused, but for the single changed row only.



      P.S. Before anyone chooses to jump the wagon so to speak, and recommend use of the hidden attribute, I don't consider it appropriate here, without more information in the question -- a filtered row is not an invalid/inapplicable document node, it may only be filtered temporarily, for instance, to aid reading the table according to a variable. Unless you actually want to remove such rows, then it's different. I believe the question as it stands asks for "perceptive" filtering.






      share|improve this answer
























      • this is exactly what I've been looking for,but if you could only help me with the implementation of this certain code because functions are not working(begginer at js sorry)

        – Em44
        Nov 26 '18 at 12:41











      • Use MDN to learn JavaScript to a point where the answer makes sense -- the for ... of loop, the classList property, the HTMLTableElement, what the DOM is and how it works, etc. MDN is a great resource! Be careful with random blogs on Internet -- not all who write know their stuff.

        – amn
        Nov 26 '18 at 14:59











      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53408465%2fhow-to-sort-tables-with-js-html%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      3 Answers
      3






      active

      oldest

      votes








      3 Answers
      3






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      1














      The folllowing snippet shown the sorting on any property.
      Clicking on one of the property header changes the sorting.



      In the same way, you can create the filtering. Instead of sorting the source_data on a particular property with data.sort(), you would data.filter() for all the entries that have the correct value.






      //	Name of the data we're rendering.
      const source_name = 'Locations';
      // Source data we want to create a table from.
      const source_data = [
      { "id": 1, "name": "production hall", "department": "production", "status": "inside" },
      { "id": 2, "name": "spare parts room", "department": "production", "status": "inside" },
      { "id": 3, "name": "warehouse", "department": "production", "status": "inside" },
      { "id": 4, "name": "loading bay", "department": "production", "status": "outside" },
      { "id": 5, "name": "offices HR", "department": "administration", "status": "inside" },
      { "id": 6, "name": "offices QA", "department": "administration", "status": "inside" },
      { "id": 7, "name": "security lounge", "department": "administration", "status": "outside" }
      ];
      // Create the table.
      // For this example, we'll use string manipulation to create the HTML.
      // For complex layouts a templating system is better.
      const render = ( name, data ) => {
      // Always include a header for the name.
      // When there's 0 rows, we'll still know what the table shows.
      const labels = data.length
      ? '<tr>' + Object.keys( data[ 0 ]).map( name => `<th data-attr="${ name }">${ name }</th>` ).join( '' ) + '</tr>'
      : '';
      // Actual header for the properties of our data.
      const header = `<tr><th colspan="${ data.length || 1 }">${ name }</th></tr>${ labels }`;
      // One row for each entry in our data.
      const rows = data.map( entry => (`<tr id="entry_${ entry.id }">` + Object.values( entry ).map( value => `<td>${ value }</td>` ).join( '' ) + '</tr>' )).join( '' );
      // Merge it all together.
      const table = `<table><thead>${ header }</thead><tbody>${ rows }</tbody></table>`;
      // Render into the page.
      document.querySelector( '#output' ).innerHTML = table;
      };
      // Sort of the property.
      const sort = ( data, property ) => {
      // Sort the data on the property in alphabetical order.
      return data.sort(( first, second ) => {
      if ( first[ property ] < second[ property ] ) return -1;
      else if ( first[ property ] > second[ property ] ) return 1;
      else return 0;
      });
      };
      // Add click events to the header so that clicking a header will sort the rows.
      const add_sorting = function( table ) {
      Array
      .from( table.querySelectorAll( 'th' ))
      .forEach( header => header.addEventListener( 'click', create_table ));
      };
      // Main function
      const create_table = event => {
      // We'll reuse this function both manually and through clicking
      const property = event && event.target
      ? event.target.getAttribute( 'data-attr' )
      : event;
      const collection = sort( source_data, property );
      render( source_name, collection );
      add_sorting( document.querySelector( 'table' ));
      };
      create_table( 'name' );

      th, td {
      border: 1px solid grey;
      }

      <div id="output"></div>








      share|improve this answer






























        1














        The folllowing snippet shown the sorting on any property.
        Clicking on one of the property header changes the sorting.



        In the same way, you can create the filtering. Instead of sorting the source_data on a particular property with data.sort(), you would data.filter() for all the entries that have the correct value.






        //	Name of the data we're rendering.
        const source_name = 'Locations';
        // Source data we want to create a table from.
        const source_data = [
        { "id": 1, "name": "production hall", "department": "production", "status": "inside" },
        { "id": 2, "name": "spare parts room", "department": "production", "status": "inside" },
        { "id": 3, "name": "warehouse", "department": "production", "status": "inside" },
        { "id": 4, "name": "loading bay", "department": "production", "status": "outside" },
        { "id": 5, "name": "offices HR", "department": "administration", "status": "inside" },
        { "id": 6, "name": "offices QA", "department": "administration", "status": "inside" },
        { "id": 7, "name": "security lounge", "department": "administration", "status": "outside" }
        ];
        // Create the table.
        // For this example, we'll use string manipulation to create the HTML.
        // For complex layouts a templating system is better.
        const render = ( name, data ) => {
        // Always include a header for the name.
        // When there's 0 rows, we'll still know what the table shows.
        const labels = data.length
        ? '<tr>' + Object.keys( data[ 0 ]).map( name => `<th data-attr="${ name }">${ name }</th>` ).join( '' ) + '</tr>'
        : '';
        // Actual header for the properties of our data.
        const header = `<tr><th colspan="${ data.length || 1 }">${ name }</th></tr>${ labels }`;
        // One row for each entry in our data.
        const rows = data.map( entry => (`<tr id="entry_${ entry.id }">` + Object.values( entry ).map( value => `<td>${ value }</td>` ).join( '' ) + '</tr>' )).join( '' );
        // Merge it all together.
        const table = `<table><thead>${ header }</thead><tbody>${ rows }</tbody></table>`;
        // Render into the page.
        document.querySelector( '#output' ).innerHTML = table;
        };
        // Sort of the property.
        const sort = ( data, property ) => {
        // Sort the data on the property in alphabetical order.
        return data.sort(( first, second ) => {
        if ( first[ property ] < second[ property ] ) return -1;
        else if ( first[ property ] > second[ property ] ) return 1;
        else return 0;
        });
        };
        // Add click events to the header so that clicking a header will sort the rows.
        const add_sorting = function( table ) {
        Array
        .from( table.querySelectorAll( 'th' ))
        .forEach( header => header.addEventListener( 'click', create_table ));
        };
        // Main function
        const create_table = event => {
        // We'll reuse this function both manually and through clicking
        const property = event && event.target
        ? event.target.getAttribute( 'data-attr' )
        : event;
        const collection = sort( source_data, property );
        render( source_name, collection );
        add_sorting( document.querySelector( 'table' ));
        };
        create_table( 'name' );

        th, td {
        border: 1px solid grey;
        }

        <div id="output"></div>








        share|improve this answer




























          1












          1








          1







          The folllowing snippet shown the sorting on any property.
          Clicking on one of the property header changes the sorting.



          In the same way, you can create the filtering. Instead of sorting the source_data on a particular property with data.sort(), you would data.filter() for all the entries that have the correct value.






          //	Name of the data we're rendering.
          const source_name = 'Locations';
          // Source data we want to create a table from.
          const source_data = [
          { "id": 1, "name": "production hall", "department": "production", "status": "inside" },
          { "id": 2, "name": "spare parts room", "department": "production", "status": "inside" },
          { "id": 3, "name": "warehouse", "department": "production", "status": "inside" },
          { "id": 4, "name": "loading bay", "department": "production", "status": "outside" },
          { "id": 5, "name": "offices HR", "department": "administration", "status": "inside" },
          { "id": 6, "name": "offices QA", "department": "administration", "status": "inside" },
          { "id": 7, "name": "security lounge", "department": "administration", "status": "outside" }
          ];
          // Create the table.
          // For this example, we'll use string manipulation to create the HTML.
          // For complex layouts a templating system is better.
          const render = ( name, data ) => {
          // Always include a header for the name.
          // When there's 0 rows, we'll still know what the table shows.
          const labels = data.length
          ? '<tr>' + Object.keys( data[ 0 ]).map( name => `<th data-attr="${ name }">${ name }</th>` ).join( '' ) + '</tr>'
          : '';
          // Actual header for the properties of our data.
          const header = `<tr><th colspan="${ data.length || 1 }">${ name }</th></tr>${ labels }`;
          // One row for each entry in our data.
          const rows = data.map( entry => (`<tr id="entry_${ entry.id }">` + Object.values( entry ).map( value => `<td>${ value }</td>` ).join( '' ) + '</tr>' )).join( '' );
          // Merge it all together.
          const table = `<table><thead>${ header }</thead><tbody>${ rows }</tbody></table>`;
          // Render into the page.
          document.querySelector( '#output' ).innerHTML = table;
          };
          // Sort of the property.
          const sort = ( data, property ) => {
          // Sort the data on the property in alphabetical order.
          return data.sort(( first, second ) => {
          if ( first[ property ] < second[ property ] ) return -1;
          else if ( first[ property ] > second[ property ] ) return 1;
          else return 0;
          });
          };
          // Add click events to the header so that clicking a header will sort the rows.
          const add_sorting = function( table ) {
          Array
          .from( table.querySelectorAll( 'th' ))
          .forEach( header => header.addEventListener( 'click', create_table ));
          };
          // Main function
          const create_table = event => {
          // We'll reuse this function both manually and through clicking
          const property = event && event.target
          ? event.target.getAttribute( 'data-attr' )
          : event;
          const collection = sort( source_data, property );
          render( source_name, collection );
          add_sorting( document.querySelector( 'table' ));
          };
          create_table( 'name' );

          th, td {
          border: 1px solid grey;
          }

          <div id="output"></div>








          share|improve this answer















          The folllowing snippet shown the sorting on any property.
          Clicking on one of the property header changes the sorting.



          In the same way, you can create the filtering. Instead of sorting the source_data on a particular property with data.sort(), you would data.filter() for all the entries that have the correct value.






          //	Name of the data we're rendering.
          const source_name = 'Locations';
          // Source data we want to create a table from.
          const source_data = [
          { "id": 1, "name": "production hall", "department": "production", "status": "inside" },
          { "id": 2, "name": "spare parts room", "department": "production", "status": "inside" },
          { "id": 3, "name": "warehouse", "department": "production", "status": "inside" },
          { "id": 4, "name": "loading bay", "department": "production", "status": "outside" },
          { "id": 5, "name": "offices HR", "department": "administration", "status": "inside" },
          { "id": 6, "name": "offices QA", "department": "administration", "status": "inside" },
          { "id": 7, "name": "security lounge", "department": "administration", "status": "outside" }
          ];
          // Create the table.
          // For this example, we'll use string manipulation to create the HTML.
          // For complex layouts a templating system is better.
          const render = ( name, data ) => {
          // Always include a header for the name.
          // When there's 0 rows, we'll still know what the table shows.
          const labels = data.length
          ? '<tr>' + Object.keys( data[ 0 ]).map( name => `<th data-attr="${ name }">${ name }</th>` ).join( '' ) + '</tr>'
          : '';
          // Actual header for the properties of our data.
          const header = `<tr><th colspan="${ data.length || 1 }">${ name }</th></tr>${ labels }`;
          // One row for each entry in our data.
          const rows = data.map( entry => (`<tr id="entry_${ entry.id }">` + Object.values( entry ).map( value => `<td>${ value }</td>` ).join( '' ) + '</tr>' )).join( '' );
          // Merge it all together.
          const table = `<table><thead>${ header }</thead><tbody>${ rows }</tbody></table>`;
          // Render into the page.
          document.querySelector( '#output' ).innerHTML = table;
          };
          // Sort of the property.
          const sort = ( data, property ) => {
          // Sort the data on the property in alphabetical order.
          return data.sort(( first, second ) => {
          if ( first[ property ] < second[ property ] ) return -1;
          else if ( first[ property ] > second[ property ] ) return 1;
          else return 0;
          });
          };
          // Add click events to the header so that clicking a header will sort the rows.
          const add_sorting = function( table ) {
          Array
          .from( table.querySelectorAll( 'th' ))
          .forEach( header => header.addEventListener( 'click', create_table ));
          };
          // Main function
          const create_table = event => {
          // We'll reuse this function both manually and through clicking
          const property = event && event.target
          ? event.target.getAttribute( 'data-attr' )
          : event;
          const collection = sort( source_data, property );
          render( source_name, collection );
          add_sorting( document.querySelector( 'table' ));
          };
          create_table( 'name' );

          th, td {
          border: 1px solid grey;
          }

          <div id="output"></div>








          //	Name of the data we're rendering.
          const source_name = 'Locations';
          // Source data we want to create a table from.
          const source_data = [
          { "id": 1, "name": "production hall", "department": "production", "status": "inside" },
          { "id": 2, "name": "spare parts room", "department": "production", "status": "inside" },
          { "id": 3, "name": "warehouse", "department": "production", "status": "inside" },
          { "id": 4, "name": "loading bay", "department": "production", "status": "outside" },
          { "id": 5, "name": "offices HR", "department": "administration", "status": "inside" },
          { "id": 6, "name": "offices QA", "department": "administration", "status": "inside" },
          { "id": 7, "name": "security lounge", "department": "administration", "status": "outside" }
          ];
          // Create the table.
          // For this example, we'll use string manipulation to create the HTML.
          // For complex layouts a templating system is better.
          const render = ( name, data ) => {
          // Always include a header for the name.
          // When there's 0 rows, we'll still know what the table shows.
          const labels = data.length
          ? '<tr>' + Object.keys( data[ 0 ]).map( name => `<th data-attr="${ name }">${ name }</th>` ).join( '' ) + '</tr>'
          : '';
          // Actual header for the properties of our data.
          const header = `<tr><th colspan="${ data.length || 1 }">${ name }</th></tr>${ labels }`;
          // One row for each entry in our data.
          const rows = data.map( entry => (`<tr id="entry_${ entry.id }">` + Object.values( entry ).map( value => `<td>${ value }</td>` ).join( '' ) + '</tr>' )).join( '' );
          // Merge it all together.
          const table = `<table><thead>${ header }</thead><tbody>${ rows }</tbody></table>`;
          // Render into the page.
          document.querySelector( '#output' ).innerHTML = table;
          };
          // Sort of the property.
          const sort = ( data, property ) => {
          // Sort the data on the property in alphabetical order.
          return data.sort(( first, second ) => {
          if ( first[ property ] < second[ property ] ) return -1;
          else if ( first[ property ] > second[ property ] ) return 1;
          else return 0;
          });
          };
          // Add click events to the header so that clicking a header will sort the rows.
          const add_sorting = function( table ) {
          Array
          .from( table.querySelectorAll( 'th' ))
          .forEach( header => header.addEventListener( 'click', create_table ));
          };
          // Main function
          const create_table = event => {
          // We'll reuse this function both manually and through clicking
          const property = event && event.target
          ? event.target.getAttribute( 'data-attr' )
          : event;
          const collection = sort( source_data, property );
          render( source_name, collection );
          add_sorting( document.querySelector( 'table' ));
          };
          create_table( 'name' );

          th, td {
          border: 1px solid grey;
          }

          <div id="output"></div>





          //	Name of the data we're rendering.
          const source_name = 'Locations';
          // Source data we want to create a table from.
          const source_data = [
          { "id": 1, "name": "production hall", "department": "production", "status": "inside" },
          { "id": 2, "name": "spare parts room", "department": "production", "status": "inside" },
          { "id": 3, "name": "warehouse", "department": "production", "status": "inside" },
          { "id": 4, "name": "loading bay", "department": "production", "status": "outside" },
          { "id": 5, "name": "offices HR", "department": "administration", "status": "inside" },
          { "id": 6, "name": "offices QA", "department": "administration", "status": "inside" },
          { "id": 7, "name": "security lounge", "department": "administration", "status": "outside" }
          ];
          // Create the table.
          // For this example, we'll use string manipulation to create the HTML.
          // For complex layouts a templating system is better.
          const render = ( name, data ) => {
          // Always include a header for the name.
          // When there's 0 rows, we'll still know what the table shows.
          const labels = data.length
          ? '<tr>' + Object.keys( data[ 0 ]).map( name => `<th data-attr="${ name }">${ name }</th>` ).join( '' ) + '</tr>'
          : '';
          // Actual header for the properties of our data.
          const header = `<tr><th colspan="${ data.length || 1 }">${ name }</th></tr>${ labels }`;
          // One row for each entry in our data.
          const rows = data.map( entry => (`<tr id="entry_${ entry.id }">` + Object.values( entry ).map( value => `<td>${ value }</td>` ).join( '' ) + '</tr>' )).join( '' );
          // Merge it all together.
          const table = `<table><thead>${ header }</thead><tbody>${ rows }</tbody></table>`;
          // Render into the page.
          document.querySelector( '#output' ).innerHTML = table;
          };
          // Sort of the property.
          const sort = ( data, property ) => {
          // Sort the data on the property in alphabetical order.
          return data.sort(( first, second ) => {
          if ( first[ property ] < second[ property ] ) return -1;
          else if ( first[ property ] > second[ property ] ) return 1;
          else return 0;
          });
          };
          // Add click events to the header so that clicking a header will sort the rows.
          const add_sorting = function( table ) {
          Array
          .from( table.querySelectorAll( 'th' ))
          .forEach( header => header.addEventListener( 'click', create_table ));
          };
          // Main function
          const create_table = event => {
          // We'll reuse this function both manually and through clicking
          const property = event && event.target
          ? event.target.getAttribute( 'data-attr' )
          : event;
          const collection = sort( source_data, property );
          render( source_name, collection );
          add_sorting( document.querySelector( 'table' ));
          };
          create_table( 'name' );

          th, td {
          border: 1px solid grey;
          }

          <div id="output"></div>






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 22 '18 at 15:38

























          answered Nov 22 '18 at 15:33









          ShillyShilly

          5,4231616




          5,4231616

























              0














              A table section can easily be sorted according to a comparator function (e.g. "is this cell supposed to appear before that cell?", Math.min, for example) using any comparison sort algorithm, here demonstrating the insertion sort, less than 10 lines of actual table sorting code:



              class InsertionSort {
              static sort_children(parent, comparator) {
              for(let i = 0; i != parent.children.length; i++) {
              const current = parent.children[i];
              let element;
              for(element = current.previousElementSibling; element && comparator(current, element); element = element.previousElementSibling);
              parent.insertBefore(current, element ? element.nextElementSibling : parent.firstElementChild);
              }
              }
              }


              Having a table section (or a table) (the parent argument to sort_children above) with an amount of rows as children, you can sort it with the sort_children method defined above, as long as you yourself rightfully define how your rows should compare:



              InsertionSort.sort_children(your_table, (row_A, row_B) => row_A.cells[0].textContent < row_B.cells[0].textContent);


              The above sorts table rows so that the cells of the first column appear in lexicographical order.



              The second argument to sort_children is the aforementioned comparator function comparator(row_A, row_B), which is expected to return true for any two rows it is passed where row_A should appear before row_B, and false otherwise. Since you provide the comparator function, you decide how your rows are sorted.



              You can further adapt the comparator function by creating a function that returns a comparator which would be specific to a particular table column, according to a value format (text, number, etc), using the < operator automatically (which is defined for Number and String, among other types):



              const table_cell_comparator = (column_index, type) => ((row_A, row_B) => type(row_A.cells[column_index].textContent) < type(row_A.cells[column_index].textContent));


              Then invoking table sorting with a less verbose and more readable expression:



              InsertionSort.sort_children(your_table, table_cell_comparator(1, Number)); 


              The above sorts the rows so that cells of second column with lower numeric value appear before cells with higher numeric value.






              share|improve this answer






























                0














                A table section can easily be sorted according to a comparator function (e.g. "is this cell supposed to appear before that cell?", Math.min, for example) using any comparison sort algorithm, here demonstrating the insertion sort, less than 10 lines of actual table sorting code:



                class InsertionSort {
                static sort_children(parent, comparator) {
                for(let i = 0; i != parent.children.length; i++) {
                const current = parent.children[i];
                let element;
                for(element = current.previousElementSibling; element && comparator(current, element); element = element.previousElementSibling);
                parent.insertBefore(current, element ? element.nextElementSibling : parent.firstElementChild);
                }
                }
                }


                Having a table section (or a table) (the parent argument to sort_children above) with an amount of rows as children, you can sort it with the sort_children method defined above, as long as you yourself rightfully define how your rows should compare:



                InsertionSort.sort_children(your_table, (row_A, row_B) => row_A.cells[0].textContent < row_B.cells[0].textContent);


                The above sorts table rows so that the cells of the first column appear in lexicographical order.



                The second argument to sort_children is the aforementioned comparator function comparator(row_A, row_B), which is expected to return true for any two rows it is passed where row_A should appear before row_B, and false otherwise. Since you provide the comparator function, you decide how your rows are sorted.



                You can further adapt the comparator function by creating a function that returns a comparator which would be specific to a particular table column, according to a value format (text, number, etc), using the < operator automatically (which is defined for Number and String, among other types):



                const table_cell_comparator = (column_index, type) => ((row_A, row_B) => type(row_A.cells[column_index].textContent) < type(row_A.cells[column_index].textContent));


                Then invoking table sorting with a less verbose and more readable expression:



                InsertionSort.sort_children(your_table, table_cell_comparator(1, Number)); 


                The above sorts the rows so that cells of second column with lower numeric value appear before cells with higher numeric value.






                share|improve this answer




























                  0












                  0








                  0







                  A table section can easily be sorted according to a comparator function (e.g. "is this cell supposed to appear before that cell?", Math.min, for example) using any comparison sort algorithm, here demonstrating the insertion sort, less than 10 lines of actual table sorting code:



                  class InsertionSort {
                  static sort_children(parent, comparator) {
                  for(let i = 0; i != parent.children.length; i++) {
                  const current = parent.children[i];
                  let element;
                  for(element = current.previousElementSibling; element && comparator(current, element); element = element.previousElementSibling);
                  parent.insertBefore(current, element ? element.nextElementSibling : parent.firstElementChild);
                  }
                  }
                  }


                  Having a table section (or a table) (the parent argument to sort_children above) with an amount of rows as children, you can sort it with the sort_children method defined above, as long as you yourself rightfully define how your rows should compare:



                  InsertionSort.sort_children(your_table, (row_A, row_B) => row_A.cells[0].textContent < row_B.cells[0].textContent);


                  The above sorts table rows so that the cells of the first column appear in lexicographical order.



                  The second argument to sort_children is the aforementioned comparator function comparator(row_A, row_B), which is expected to return true for any two rows it is passed where row_A should appear before row_B, and false otherwise. Since you provide the comparator function, you decide how your rows are sorted.



                  You can further adapt the comparator function by creating a function that returns a comparator which would be specific to a particular table column, according to a value format (text, number, etc), using the < operator automatically (which is defined for Number and String, among other types):



                  const table_cell_comparator = (column_index, type) => ((row_A, row_B) => type(row_A.cells[column_index].textContent) < type(row_A.cells[column_index].textContent));


                  Then invoking table sorting with a less verbose and more readable expression:



                  InsertionSort.sort_children(your_table, table_cell_comparator(1, Number)); 


                  The above sorts the rows so that cells of second column with lower numeric value appear before cells with higher numeric value.






                  share|improve this answer















                  A table section can easily be sorted according to a comparator function (e.g. "is this cell supposed to appear before that cell?", Math.min, for example) using any comparison sort algorithm, here demonstrating the insertion sort, less than 10 lines of actual table sorting code:



                  class InsertionSort {
                  static sort_children(parent, comparator) {
                  for(let i = 0; i != parent.children.length; i++) {
                  const current = parent.children[i];
                  let element;
                  for(element = current.previousElementSibling; element && comparator(current, element); element = element.previousElementSibling);
                  parent.insertBefore(current, element ? element.nextElementSibling : parent.firstElementChild);
                  }
                  }
                  }


                  Having a table section (or a table) (the parent argument to sort_children above) with an amount of rows as children, you can sort it with the sort_children method defined above, as long as you yourself rightfully define how your rows should compare:



                  InsertionSort.sort_children(your_table, (row_A, row_B) => row_A.cells[0].textContent < row_B.cells[0].textContent);


                  The above sorts table rows so that the cells of the first column appear in lexicographical order.



                  The second argument to sort_children is the aforementioned comparator function comparator(row_A, row_B), which is expected to return true for any two rows it is passed where row_A should appear before row_B, and false otherwise. Since you provide the comparator function, you decide how your rows are sorted.



                  You can further adapt the comparator function by creating a function that returns a comparator which would be specific to a particular table column, according to a value format (text, number, etc), using the < operator automatically (which is defined for Number and String, among other types):



                  const table_cell_comparator = (column_index, type) => ((row_A, row_B) => type(row_A.cells[column_index].textContent) < type(row_A.cells[column_index].textContent));


                  Then invoking table sorting with a less verbose and more readable expression:



                  InsertionSort.sort_children(your_table, table_cell_comparator(1, Number)); 


                  The above sorts the rows so that cells of second column with lower numeric value appear before cells with higher numeric value.







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Nov 22 '18 at 23:53

























                  answered Nov 22 '18 at 17:01









                  amnamn

                  3,95053262




                  3,95053262























                      0














                      "Filtering" a table, as it is called, with existing rows, can easily be done with class toggling, among other things:



                      function filter_table(section, predicate) {
                      for(const row of section.rows) row.classList.toggle("filtered", predicate(row));
                      }


                      What happens above is that rows of an entire table or table section (section above) that the predicate function considers "filtered", are marked as such by toggling the "filtered" class on these.



                      The predicate function is a function of your own design and choosing that accepts a table row and returns true if the row should be filtered or false otherwise.



                      Taking your use case with employee rows, for instance, where let's say the 3rd table cell of every row contains a select (drop-down) control with one option for "In" and one option for "Out":



                      <tr><!-- ... --><td><select><option value="in">In</option><option value="out">Out</option></select></tr>


                      You can write the predicate that will filter employee rows according to either "In" or "Out" status ("in" in the example), as follows:



                      const predicate = row => row.cells[2].firstElementChild.value == "in";


                      How you style filtered rows is up to you, you may want to simply hide them, of course:



                      tr.filtered {
                      display: none;
                      }


                      Since the status of each employee effectively changes with the change in drop-down selection, you would be wasting resources by invoking filter_table for every such change, which then would go through all the rows again. It is then a much better idea to listen on the "change" event that would be fired by the select control as it changes its value:



                      table.addEventListener("change", event => {
                      if(event.target instanceof HTMLSelectElement) {
                      const row = event.target.parentElement.parentElement;
                      row.classList.toggle("filtered", predicate(row));
                      }
                      })


                      You only need to attach a single listener to the entire table -- "change" events bubble up the element tree. The predicate function defined above is reused, but for the single changed row only.



                      P.S. Before anyone chooses to jump the wagon so to speak, and recommend use of the hidden attribute, I don't consider it appropriate here, without more information in the question -- a filtered row is not an invalid/inapplicable document node, it may only be filtered temporarily, for instance, to aid reading the table according to a variable. Unless you actually want to remove such rows, then it's different. I believe the question as it stands asks for "perceptive" filtering.






                      share|improve this answer
























                      • this is exactly what I've been looking for,but if you could only help me with the implementation of this certain code because functions are not working(begginer at js sorry)

                        – Em44
                        Nov 26 '18 at 12:41











                      • Use MDN to learn JavaScript to a point where the answer makes sense -- the for ... of loop, the classList property, the HTMLTableElement, what the DOM is and how it works, etc. MDN is a great resource! Be careful with random blogs on Internet -- not all who write know their stuff.

                        – amn
                        Nov 26 '18 at 14:59
















                      0














                      "Filtering" a table, as it is called, with existing rows, can easily be done with class toggling, among other things:



                      function filter_table(section, predicate) {
                      for(const row of section.rows) row.classList.toggle("filtered", predicate(row));
                      }


                      What happens above is that rows of an entire table or table section (section above) that the predicate function considers "filtered", are marked as such by toggling the "filtered" class on these.



                      The predicate function is a function of your own design and choosing that accepts a table row and returns true if the row should be filtered or false otherwise.



                      Taking your use case with employee rows, for instance, where let's say the 3rd table cell of every row contains a select (drop-down) control with one option for "In" and one option for "Out":



                      <tr><!-- ... --><td><select><option value="in">In</option><option value="out">Out</option></select></tr>


                      You can write the predicate that will filter employee rows according to either "In" or "Out" status ("in" in the example), as follows:



                      const predicate = row => row.cells[2].firstElementChild.value == "in";


                      How you style filtered rows is up to you, you may want to simply hide them, of course:



                      tr.filtered {
                      display: none;
                      }


                      Since the status of each employee effectively changes with the change in drop-down selection, you would be wasting resources by invoking filter_table for every such change, which then would go through all the rows again. It is then a much better idea to listen on the "change" event that would be fired by the select control as it changes its value:



                      table.addEventListener("change", event => {
                      if(event.target instanceof HTMLSelectElement) {
                      const row = event.target.parentElement.parentElement;
                      row.classList.toggle("filtered", predicate(row));
                      }
                      })


                      You only need to attach a single listener to the entire table -- "change" events bubble up the element tree. The predicate function defined above is reused, but for the single changed row only.



                      P.S. Before anyone chooses to jump the wagon so to speak, and recommend use of the hidden attribute, I don't consider it appropriate here, without more information in the question -- a filtered row is not an invalid/inapplicable document node, it may only be filtered temporarily, for instance, to aid reading the table according to a variable. Unless you actually want to remove such rows, then it's different. I believe the question as it stands asks for "perceptive" filtering.






                      share|improve this answer
























                      • this is exactly what I've been looking for,but if you could only help me with the implementation of this certain code because functions are not working(begginer at js sorry)

                        – Em44
                        Nov 26 '18 at 12:41











                      • Use MDN to learn JavaScript to a point where the answer makes sense -- the for ... of loop, the classList property, the HTMLTableElement, what the DOM is and how it works, etc. MDN is a great resource! Be careful with random blogs on Internet -- not all who write know their stuff.

                        – amn
                        Nov 26 '18 at 14:59














                      0












                      0








                      0







                      "Filtering" a table, as it is called, with existing rows, can easily be done with class toggling, among other things:



                      function filter_table(section, predicate) {
                      for(const row of section.rows) row.classList.toggle("filtered", predicate(row));
                      }


                      What happens above is that rows of an entire table or table section (section above) that the predicate function considers "filtered", are marked as such by toggling the "filtered" class on these.



                      The predicate function is a function of your own design and choosing that accepts a table row and returns true if the row should be filtered or false otherwise.



                      Taking your use case with employee rows, for instance, where let's say the 3rd table cell of every row contains a select (drop-down) control with one option for "In" and one option for "Out":



                      <tr><!-- ... --><td><select><option value="in">In</option><option value="out">Out</option></select></tr>


                      You can write the predicate that will filter employee rows according to either "In" or "Out" status ("in" in the example), as follows:



                      const predicate = row => row.cells[2].firstElementChild.value == "in";


                      How you style filtered rows is up to you, you may want to simply hide them, of course:



                      tr.filtered {
                      display: none;
                      }


                      Since the status of each employee effectively changes with the change in drop-down selection, you would be wasting resources by invoking filter_table for every such change, which then would go through all the rows again. It is then a much better idea to listen on the "change" event that would be fired by the select control as it changes its value:



                      table.addEventListener("change", event => {
                      if(event.target instanceof HTMLSelectElement) {
                      const row = event.target.parentElement.parentElement;
                      row.classList.toggle("filtered", predicate(row));
                      }
                      })


                      You only need to attach a single listener to the entire table -- "change" events bubble up the element tree. The predicate function defined above is reused, but for the single changed row only.



                      P.S. Before anyone chooses to jump the wagon so to speak, and recommend use of the hidden attribute, I don't consider it appropriate here, without more information in the question -- a filtered row is not an invalid/inapplicable document node, it may only be filtered temporarily, for instance, to aid reading the table according to a variable. Unless you actually want to remove such rows, then it's different. I believe the question as it stands asks for "perceptive" filtering.






                      share|improve this answer













                      "Filtering" a table, as it is called, with existing rows, can easily be done with class toggling, among other things:



                      function filter_table(section, predicate) {
                      for(const row of section.rows) row.classList.toggle("filtered", predicate(row));
                      }


                      What happens above is that rows of an entire table or table section (section above) that the predicate function considers "filtered", are marked as such by toggling the "filtered" class on these.



                      The predicate function is a function of your own design and choosing that accepts a table row and returns true if the row should be filtered or false otherwise.



                      Taking your use case with employee rows, for instance, where let's say the 3rd table cell of every row contains a select (drop-down) control with one option for "In" and one option for "Out":



                      <tr><!-- ... --><td><select><option value="in">In</option><option value="out">Out</option></select></tr>


                      You can write the predicate that will filter employee rows according to either "In" or "Out" status ("in" in the example), as follows:



                      const predicate = row => row.cells[2].firstElementChild.value == "in";


                      How you style filtered rows is up to you, you may want to simply hide them, of course:



                      tr.filtered {
                      display: none;
                      }


                      Since the status of each employee effectively changes with the change in drop-down selection, you would be wasting resources by invoking filter_table for every such change, which then would go through all the rows again. It is then a much better idea to listen on the "change" event that would be fired by the select control as it changes its value:



                      table.addEventListener("change", event => {
                      if(event.target instanceof HTMLSelectElement) {
                      const row = event.target.parentElement.parentElement;
                      row.classList.toggle("filtered", predicate(row));
                      }
                      })


                      You only need to attach a single listener to the entire table -- "change" events bubble up the element tree. The predicate function defined above is reused, but for the single changed row only.



                      P.S. Before anyone chooses to jump the wagon so to speak, and recommend use of the hidden attribute, I don't consider it appropriate here, without more information in the question -- a filtered row is not an invalid/inapplicable document node, it may only be filtered temporarily, for instance, to aid reading the table according to a variable. Unless you actually want to remove such rows, then it's different. I believe the question as it stands asks for "perceptive" filtering.







                      share|improve this answer












                      share|improve this answer



                      share|improve this answer










                      answered Nov 23 '18 at 14:11









                      amnamn

                      3,95053262




                      3,95053262













                      • this is exactly what I've been looking for,but if you could only help me with the implementation of this certain code because functions are not working(begginer at js sorry)

                        – Em44
                        Nov 26 '18 at 12:41











                      • Use MDN to learn JavaScript to a point where the answer makes sense -- the for ... of loop, the classList property, the HTMLTableElement, what the DOM is and how it works, etc. MDN is a great resource! Be careful with random blogs on Internet -- not all who write know their stuff.

                        – amn
                        Nov 26 '18 at 14:59



















                      • this is exactly what I've been looking for,but if you could only help me with the implementation of this certain code because functions are not working(begginer at js sorry)

                        – Em44
                        Nov 26 '18 at 12:41











                      • Use MDN to learn JavaScript to a point where the answer makes sense -- the for ... of loop, the classList property, the HTMLTableElement, what the DOM is and how it works, etc. MDN is a great resource! Be careful with random blogs on Internet -- not all who write know their stuff.

                        – amn
                        Nov 26 '18 at 14:59

















                      this is exactly what I've been looking for,but if you could only help me with the implementation of this certain code because functions are not working(begginer at js sorry)

                      – Em44
                      Nov 26 '18 at 12:41





                      this is exactly what I've been looking for,but if you could only help me with the implementation of this certain code because functions are not working(begginer at js sorry)

                      – Em44
                      Nov 26 '18 at 12:41













                      Use MDN to learn JavaScript to a point where the answer makes sense -- the for ... of loop, the classList property, the HTMLTableElement, what the DOM is and how it works, etc. MDN is a great resource! Be careful with random blogs on Internet -- not all who write know their stuff.

                      – amn
                      Nov 26 '18 at 14:59





                      Use MDN to learn JavaScript to a point where the answer makes sense -- the for ... of loop, the classList property, the HTMLTableElement, what the DOM is and how it works, etc. MDN is a great resource! Be careful with random blogs on Internet -- not all who write know their stuff.

                      – amn
                      Nov 26 '18 at 14:59


















                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53408465%2fhow-to-sort-tables-with-js-html%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      404 Error Contact Form 7 ajax form submitting

                      How to know if a Active Directory user can login interactively

                      TypeError: fit_transform() missing 1 required positional argument: 'X'