Sort multiple html tables with multiple sorts

I have several html tables on my page, and I want to be able to sort them based on the value of one of the values ​​of my cells. Here is an example of my tables

<div id="tables"> <table class="sortable"> <tr> <td>Comic Book Name</td> <td id="comic">Batman</td> </tr> <tr> <td>Main Character</td > <td ="character">Bruce Wayne</td> </tr> <tr> <td>Hero Name</td> <td id="hero">Batman</td> </tr> <tr> <td>Published</td> <td id="publish">05/01/1940</td> </tr> </table> <table class="sortable"> <tr> <td>Comic Book Name</td> <td id="comic">Green Arrow</td> </tr> <tr> <td>Main Character</td > <td ="character">Oliver Queen</td> </tr> <tr> <td>Hero Name</td> <td id="hero">Green Arrow</td> </tr> <tr> <td>Published</td> <td id="publish">11/01/1941</td> </tr> </table> </div> 

I provide the following snapshot to allow users to filter.

 <select id="OrderBy"> <option selected="selected" value="comic">Comic Name</option> <option value="character">Character Name</option> <option value="hero">Hero Name</option> <option value="publish">Earliest Publish Date</option> </select> 

My hopes here are to sort the tables alphabetically by the name of the comics when they select the Comic Name, in alphabetical order by the name of the character, when they choose the name of the character, etc. etc.

Here is the javascript / jquery with which I have come so far. I'm sure this can be done better, but I am new to Javascript and JQuery.

 $('#OrderBy').on('change', function () { _order = $('#OrderBy').val(); switch (_order) { case "comic": $('#sortable').sort(function () { }); break; case "character": $('#sortable').children().sort(function (a, b) { }); break; case "publish": $('#sortable').sort(function () { }); break; case "publish": $('#sortable').sort(function () { if ($(b).children().find('#Hours').text() - $(a).children().find('#publish').text() <= 0) { return $(a) - $(b); } return $(b) - $(a); }); break; } }); 

In any case, I see that someone is offering Sorttables or tableSorter, but I only saw how they work for a single table whose rows are sorted. I know what everyone is thinking at this moment, do not use tables this way. My problem is that there is already a bunch of jquery and javascript supporting tables, and I'm not experienced enough in languages ​​to rewrite all of this.

I like the idea of ​​pushing everything onto the stack as described here , but I always generated an error about how my array / stack was not defined.

+5
source share
2 answers

Firstly, you should not put the same identifier several times, but use classes instead:

 <div id="tables"> <table class="sortable"> <tr> <td>Comic Book Name</td> <td class="comic">Green Arrow</td> </tr> <tr> <td>Main Character</td > <td class="character">Oliver Queen</td> </tr> <tr> <td>Hero Name</td> <td class="hero">Green Arrow</td> </tr> <tr> <td>Published</td> <td class="publish">11/01/1941</td> </tr> </table> <table class="sortable"> <tr> <td>Comic Book Name</td> <td class="comic">Batman</td> </tr> <tr> <td>Main Character</td > <td class="character">Bruce Wayne</td> </tr> <tr> <td>Hero Name</td> <td class="hero">Batman</td> </tr> <tr> <td>Published</td> <td class="publish">05/01/1940</td> </tr> </table> </div> 

For your problem, I would use the native Array.prototype.sort method

 var tables = []; var $tables = $("table.sortable"); var container = $("#tables"); // this is the only specific case, as the date does not start by the year // it will be used to sort by publish date function sortByDate(a, b) { return new Date(a.publish).getTime() - new Date(b.publish).getTime(); } function sortTables(order) { var sort; if (order === "publish") { tables = tables.sort(sortByDate); } else { tables = tables.sort(function(a, b) { return a[order] < b[order] ? -1 : 1; }); } tables.forEach(function(data,i) { tables[i].$el.detach() container.append(tables[i].el); }); } function init() { //populate the tables array that will be sorted $tables.each(function(i, val) { var $this = $(this); tables.push({ $el: $this, el: this, comic: $this.find(".comic").text(), character: $this.find(".character").text(), hero: $this.find(".hero").text(), publish: $this.find(".publish").text() }); }); $("#OrderBy").on("change", function(event) { sortTables(event.currentTarget.value); }); //by default sort by Hero sortTables("hero"); } init(); 
+1
source

First of all, Sorting cannot happen when you have data in two different tables. To make this possible, you need to put an identifier, not just classes, because your main problem is not CSS. Again, if you put the same identifier in different content, it cannot be defined specifically. Thus, the debugged code will look like this:

 <div id="tables"> <table id="tbl1" class="sortable"> <tr> <td>Comic Book Name</td> <td class="comic">Batman</td> </tr> <tr> <td>Main Character</td > <td class="character">Bruce Wayne</td> </tr> <tr> <td>Hero Name</td> <td class="hero">Batman</td> </tr> <tr> <td>Published</td> <td class="publish">05/01/1940</td> </tr> </table> <table id="tbl2" class="sortable"> <tr> <td>Comic Book Name</td> <td class="comic">Green Arrow</td> </tr> <tr> <td>Main Character</td > <td class="character">Oliver Queen</td> </tr> <tr> <td>Hero Name</td> <td class="hero">Green Arrow</td> </tr> <tr> <td>Published</td> <td class="publish">11/01/1941</td> </tr> </table> 

Your drop-down menu (filter) is correctly defined. Now there are some syntax errors in the js code. for example, class identifier ".", identifier "id" is "#", you used "#" instead of ".". in some places:

 switch (_order) { case "comic": $('#sortable').sort(function () {}); 

debugged code:

 $('#OrderBy').on('change', function () { _order = $('#OrderBy').val(); switch (_order) { case "comic": $('.sortable').sort(function () {}); break; case "character": $('.sortable').children().sort(function (a, b) { }); break; case "publish": $('.sortable').sort(function () { }); break; case "publish": $('.sortable').sort(function () { if ($(b).children().find('#Hours').text() - $(a).children().find('#publish').text() <= 0) { return $(a) - $(b); } return $(b) - $(a); }); break; }}); 

There is no official sorting table () for the jquery library function. It will only work for an array, but there will be no array here. Therefore, we do the sorting function ourselves. We can call it "sortTable ()". The code for this should be:

 <!-- -------------------------------------------------------------- --> <!-- Secondary functions --> <!-- Creates a new table to display the sorted Table --> function createEmptyTable(){ var outerDiv = document.createElement('div'); outerDiv.setAttribute('id','ResultTable'); var innerTable = doucment.createElement('table'); innerTable.setAttribute('id','sortedTable'); var newRows = new Array(); var recordIndex = document.getElementsByClassName('comic'); innerTable.innerHTML = "<tr> <th>Comic Book Name </th> <th>Main Character</th> <th>Hero Name</th> <th>Published</th> </tr>"; for(var i=0; i<recordIndex.Length;i++){ newRows[i]= document.createElement('tr'); outerDiv.appendChild(innerTable).appendChild(newRows[i]); } } <!-- ------------------------------------------------------------- --> <!-- function to find out in which table chosen filter belongs --> function recordSearch(keyWord){ var sortableTables = document.getElementsByClassName('sortable'); for( var i=0; i<sortableTables.length;i++){ if($(sortableTables[i]).find(keyword)){ return sortableTable[i]; } } <!-- ------------------------------------------------------------- --> <!-- Primary function to sort the Table --> function sortTable(filtered_option){ <!-- first we delete any existing sorted table --> if(document.getElementById('ResultTable')){ var existingSortedTable = document.getElementbyId('ResultTable'); existingSortedTable.removeChild(document.getElementById('sortedTable'); } <!-- now we create new table & put the result --> createEmptyTable(); var comicNames = document.getElementsByClassName('comic'); var characterNames = document.getElementsByClassName('character'); var heroNames = document.getElementsByClassName('hero'); var publishDates = document.getElementsByClassName('publish'); switch (filtered_option) { case 'comic' : var sortedComicNames = comicNames.sort(); for(var i=0;i<sortedComicNames.length;i++){ var foundRecord = recordSearch(sortedComicNames[i]); var allFields = foundRecord.getElementByTagName('tr').getElementsByClassName('td'); var emptyRows = document.getElementById('sortedTable').getElementsByTagName('tr'); for(var j=0;j<allFields.length;j++){ emptyRows[i+1].innerHTML = "<td>" + allFields[j].value + "</td>" ; }} break; case 'character' : var sortedCharacterNames= characterNames.sort(); for(var i=0;i<characterNames.length;i++){ var foundRecord = recordSearch(sortedCharacterNames[i]); var allFields = foundRecord.getElementByTagName('tr').getElementsByClassName('td'); var emptyRows = document.getElementById('sortedTable').getElementsByTagName('tr'); for(var j=0;j<allFields.length;j++){ emptyRows[i+1].innerHTML = "<td>" + allFields[j].value + "</td>" ; }} break; case 'hero' : var sortedHeroNames= heroNames.sort(); for(var i=0;i<heroNames.length;i++){ var foundRecord = recordSearch(heroNames[i]); var allFields = foundRecord.getElementByTagName('tr').getElementsByClassName('td'); var emptyRows = document.getElementById('sortedTable').getElementsByTagName('tr'); for(var j=0;j<allFields.length;j++){ emptyRows[i+1].innerHTML = "<td>" + allFields[j].value + "</td>" ; }} break; case 'publish' : var sortedPublishedDates= publishedDates.sort(); for(var i=0;i<publishedDates.length;i++){ var foundRecord = recordSearch(publishedDates[i]); var allFields = foundRecord.getElementByTagName('tr').getElementsByClassName('td'); var emptyRows = document.getElementById('sortedTable').getElementsByTagName('tr'); for(var j=0;j<allFields.length;j++){ emptyRows[i+1].innerHTML = "<td>" + allFields[j].value + "</td>" ; }} break; } } <!-- -------------------------------------------------------------------- --> 

Put them together and try. Let me know if this works.

0
source

Source: https://habr.com/ru/post/1232763/


All Articles