SitePoint Sponsor

User Tag List

Results 1 to 9 of 9
  1. #1
    SitePoint Zealot
    Join Date
    Aug 2011
    Posts
    118
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    How to make this table sorting script treat different tables differently?

    I found an in itself good table content sorting script. It can sort the contents of multiple tables and is lightweight. However, it makes the default sorting column, determined by one particular value in the script, the same for every table. While I have different tables with different characteristics, and thus with different default sorting columns.

    Is it possible to make this script assign different tables different default sorting colum numbers? This is the -- two-part -- script (see below for what I tried; I used PHP code tags for better highlighting):

    First part, separate file:
    PHP Code:
    function TSorter(){
        var 
    table Object;
        var 
    trs = Array;
        var 
    ths = Array;
        var 
    curSortCol Object;
        var 
    prevSortCol '3';
        var 
    sortType Object;

        function 
    get(){}

        function 
    getCell(index){
            return 
    trs[index].cells[curSortCol]
        }

        
    /*----------------------INIT------------------------------------*/
        // Initialize the variable
        // @param tableName - the name of the table to be sorted
        /*--------------------------------------------------------------*/
        
    this.init = function(tableName)
        {
            
    table document.getElementById(tableName);
            
    ths table.getElementsByTagName("th");
            for(var 
    0ths.length i++)
            {
                
    ths[i].onclick = function()
                {
                    
    sort(this);
                }
            }
            return 
    true;
        };

        
    /*----------------------SORT------------------------------------*/
        // Sorts a particular column. If it has been sorted then call reverse
        // if not, then use quicksort to get it sorted.
        // Sets the arrow direction in the headers.
        // @param oTH - the table header cell (<th>) object that is clicked
        /*--------------------------------------------------------------*/
        
    function sort(oTH)
        {
            
    curSortCol oTH.cellIndex;
            
    sortType oTH.abbr;
            
    trs table.tBodies[0].getElementsByTagName("tr");

            
    //set the get function
            
    setGet(sortType)

            
    // it would be nice to remove this to save time,
            // but we need to close any rows that have been expanded
            
    for(var j=0j<trs.lengthj++)
            {
                if(
    trs[j].className == 'detail_row')
                {
                    
    closeDetails(j+2);
                }
            }

            
    // if already sorted just reverse
            
    if(prevSortCol == curSortCol)
            {
                
    oTH.className = (oTH.className != 'descend' 'descend' 'ascend' ); // reversed from original
                
    reverseTable();
            }
            
    // not sorted - call quicksort
            
    else
            {
                
    oTH.className 'descend'// reversed from original
                
    if(ths[prevSortCol].className != 'exc_cell'){ths[prevSortCol].className '';}
                
    quicksort(0trs.length);
            }
            
    prevSortCol curSortCol;
        }

        
    /*--------------------------------------------------------------*/
        // Sets the GET function so that it doesnt need to be
        // decided on each call to get() a value.
        // @param: colNum - the column number to be sorted
        /*--------------------------------------------------------------*/
        
    function setGet(sortType)
        {
            switch(
    sortType)
            {
                case 
    "link_column":
                    
    get = function(index){
                        return  
    getCell(index).firstChild.firstChild.nodeValue;
                    };
                    break;
                default:
                    
    get = function(index){    return getCell(index).firstChild.nodeValue;};
                    break;
            };
        }

        
    /*-----------------------EXCHANGE-------------------------------*/
        //  A complicated way of exchanging two rows in a table.
        //  Exchanges rows at index i and j
        /*--------------------------------------------------------------*/
        
    function exchange(ij)
        {
            if(
    == j+1) {
                
    table.tBodies[0].insertBefore(trs[i], trs[j]);
            } else if(
    == i+1) {
                
    table.tBodies[0].insertBefore(trs[j], trs[i]);
            } else {
                var 
    tmpNode table.tBodies[0].replaceChild(trs[i], trs[j]);
                if(
    typeof(trs[i]) == "undefined") {
                    
    table.appendChild(tmpNode);
                } else {
                    
    table.tBodies[0].insertBefore(tmpNodetrs[i]);
                }
            }
        }

        
    /*----------------------REVERSE TABLE----------------------------*/
        //  Reverses a table ordering
        /*--------------------------------------------------------------*/
        
    function reverseTable()
        {
            for(var 
    1i<trs.lengthi++)
            {
                
    table.tBodies[0].insertBefore(trs[i], trs[0]);
            }
        }

        
    /*----------------------QUICKSORT-------------------------------*/
        // This quicksort implementation is a modified version of this tutorial:
        // http://www.the-art-of-web.com/javascript/quicksort/
        // @param: lo - the low index of the array to sort
        // @param: hi - the high index of the array to sort
        /*--------------------------------------------------------------*/
        
    function quicksort(lohi)
        {
            if(
    hi <= lo+1) return;

            if((
    hi lo) == 2) {
                if(
    get(hi-1) > get(lo)) exchange(hi-1lo);
                return;
            }

            var 
    lo 1;
            var 
    hi 1;

            if(
    get(lo) > get(i)) exchange(ilo);
            if(
    get(j) > get(lo)) exchange(loj);
            if(
    get(lo) > get(i)) exchange(ilo);

            var 
    pivot get(lo);

            while(
    true) {
                
    j--;
                while(
    pivot get(j)) j--;
                
    i++;
                while(
    get(i) > pivoti++;
                if(
    <= i) break;
                
    exchange(ij);
            }
            
    exchange(loj);

            if((
    j-lo) < (hi-j)) {
                
    quicksort(loj);
                
    quicksort(j+1hi);
            } else {
                
    quicksort(j+1hi);
                
    quicksort(loj);
            }
        }

    Second part, in the page with the tables:

    PHP Code:
    function init() {
        var 
    Table1Sorter = new TSorter;
        var 
    Table2Sorter = new TSorter;

        
    Table1Sorter.init('score-x-year-for-one-patho');
        
    Table2Sorter.init('score-x-patho-in-one-year');

    I tried putting this in several places:

    PHP Code:
    if (table.Id == 'score-x-year-for-one-patho')
                var 
    prevSortCol '0';
    else if (
    table.Id == 'score-x-patho-in-one-year')
                var 
    prevSortCol '3'
    but that doesn't work. I either get a Firebug report that prevSortCol is not defined, or it keeps having the same value for all tables.

    Anyone know how this should be done?

  2. #2
    GrŁŖe aus'm Pott gold trophysilver trophybronze trophy
    Pullo's Avatar
    Join Date
    Jun 2007
    Location
    Germany
    Posts
    5,940
    Mentioned
    215 Post(s)
    Tagged
    12 Thread(s)
    I'm not sure if this has much to do with your issue, but this is wrong:

    Code:
    table.Id == 'score-x-year-for-one-patho'
    The id attribute may not be capitalized.

    Better would be:

    Code:
    if (table.id === 'score-x-year-for-one-patho') {
      var prevSortCol = '0';
    } else if (table.id == 'score-x-patho-in-one-year') {
      var prevSortCol = '3';
    }
    Other than that, could you post a link to a page where I could see this problem?

  3. #3
    SitePoint Zealot
    Join Date
    Aug 2011
    Posts
    118
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks again for jumping in, Pullo.

    Correcting the capitalization makes some, but not enough difference. Now, Firebug no longer says that prevSortCol is not defined, but its value stays set to 3 for all tables. Here is the project I'm working on: http://www.gezondezorg.org/pzp.html. There will be more tables, with sometimes very different characteristics.

    The script is from this site: http://www.terrill.ca/sorting/. There is documentation available there, but that is beyond my understanding. If it it all offers the option to have a dynamic prevSortCol value.

  4. #4
    GrŁŖe aus'm Pott gold trophysilver trophybronze trophy
    Pullo's Avatar
    Join Date
    Jun 2007
    Location
    Germany
    Posts
    5,940
    Mentioned
    215 Post(s)
    Tagged
    12 Thread(s)
    Hi there,

    There is no obvious option you can pass in to the library with which to specify the column to sort by.
    But before we go pulling the library apart to try and make it do what we want, there is a little hack we could employ.

    What you do is set things up so that you have multiple sortable tables on the same page.
    Then, in your HTML you apply a class to the <th> element you want to sort by, e.g.:

    Code:
    <thead>
      <tr>
        <th abbr="link">ID</th>
        <th abbr="input_text">NAME</th>
        <th abbr="image_number" class="columnToSortBy">PRICE</th>
        <th>LATITUDE</th>
        <th>LONGITUDE</th>
        <th abbr="link">ADDRESS</th>
      </tr>
    </thead>
    Then, at the foot of your page, you get a reference to any elements that have this class applied to them and use JavaScript to simulate a click on them.

    That would look like this:

    Code JavaScript:
    var cols = document.querySelectorAll(".columnToSortBy");
    for(var i=0, len=cols.length; i<len; i++){
      cols[i].click();
    }

    Et voilŗ, the desired effect has been achieved

  5. #5
    SitePoint Zealot
    Join Date
    Aug 2011
    Posts
    118
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I did as you suggested (and I now uploaded the separate script file to my project, which I forgot previously). See http://www.gezondezorg.org/pzp.html. However, I am now getting a reference error report from Firebug. Also, it doesn't solve the problem, which I will describe in more practical terms:

    Scroll down to the first table with the orange header background. If you click on the first column header, which is the HTML-sorted column, you will see that nothing happens. You have to click once more to have the order of that column reversed. If you click the HTML-sorted column of the table below that, which is the fourth column, you will see that the sorting order is reversed immediately.

    Seemingly a minor problem, but it just looks odd if you have to click the default order column twice in some tables to have its sorting order reversed.

  6. #6
    GrŁŖe aus'm Pott gold trophysilver trophybronze trophy
    Pullo's Avatar
    Join Date
    Jun 2007
    Location
    Germany
    Posts
    5,940
    Mentioned
    215 Post(s)
    Tagged
    12 Thread(s)
    Hi,

    The reason why this was not working was that you had this in one of your <th> elements: onclick="alert(prevSortCol)" and the variable prevSortCol was not defined.

    However, this doesn't solve your other problem that you have to click twice on a column to sort it in reverse order.

    I have made a very simple example to demonstrate the problem:

    Code:
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>Zorg-performance-zoekpagina</title>
    </head>
    
    <body>
        <table id="score-x-year-for-one-patho" border="1" cellpadding="5">
            <thead>
                <tr>
                    <th>Jaar</th>
                    <th>PatiŽnttevredenheidsscore</th>
                    <th>Ziektelastscore</th>
                    <th>Gewogen totaalscore</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>2013</td>
                    <td>8,0</td>
                    <td>6,2</td>
                    <td>6,8</td>
                </tr>
                <tr>
                    <td>2012</td>
                    <td>7,4</td>
                    <td>6,1</td>
                    <td>6,5</td>
                </tr>
                <tr>
                    <td>2011</td>
                    <td>6,5</td>
                    <td>5,1</td>
                    <td>5,6</td>
                </tr>
                <tr>
                    <td>2010</td>
                    <td>5,9</td>
                    <td>5,2</td>
                    <td>5,9</td>
                </tr>
            </tbody>
        </table>
    
        <script src="http://www.terrill.ca/sorting/TSorter_1_example.js"></script>
        <script>
        function init() {
          var Table1Sorter = new TSorter;
          Table1Sorter.init('score-x-year-for-one-patho');
        }
        window.onload = init;
      </script>
    </body>
    </html>
    As you can see, "Jaar" is sorted in descending order (largest first) when the page loads.
    After the first click on "Jaar", the plugin sorts the column in descending order (largest first), which is why you see no change.
    I guess it is assuming that you maybe have 2013 - 2011 - 2012 - 2010 or something like that, where the years are not ordered.
    It needs to sort them in descending order once (obviously), but doesn't seem to be clever enough to realise that they are already in the correct order.

    You can see this illustrated if you click "Ziektelastscore"
    The first two numbers don't change, but the bottom two swap position.

    At this point, if you don't mind using jQuery, I would recommend using something like this, as it works as you want out of the box.

    Here's an example:

    Code:
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>Zorg-performance-zoekpagina</title>
        <style>table{ margin: 15px; }</style>
    </head>
    
    <body>
        <table id="table1" border="1" cellpadding="5">
            <thead>
                <tr>
                    <th>Jaar</th>
                    <th>PatiŽnttevredenheidsscore</th>
                    <th>Ziektelastscore</th>
                    <th>Gewogen totaalscore</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>2013</td>
                    <td>8,0</td>
                    <td>6,2</td>
                    <td>6,8</td>
                </tr>
                <tr>
                    <td>2012</td>
                    <td>7,4</td>
                    <td>6,1</td>
                    <td>6,5</td>
                </tr>
                <tr>
                    <td>2011</td>
                    <td>6,5</td>
                    <td>5,1</td>
                    <td>5,6</td>
                </tr>
                <tr>
                    <td>2010</td>
                    <td>5,9</td>
                    <td>5,2</td>
                    <td>5,9</td>
                </tr>
            </tbody>
        </table>
    
        <table id="table2" border="1" cellpadding="5">
            <thead>
                <tr>
                    <th>Jaar</th>
                    <th>PatiŽnttevredenheidsscore</th>
                    <th>Ziektelastscore</th>
                    <th>Gewogen totaalscore</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>2013</td>
                    <td>8,0</td>
                    <td>6,2</td>
                    <td>6,8</td>
                </tr>
                <tr>
                    <td>2012</td>
                    <td>7,4</td>
                    <td>6,1</td>
                    <td>6,5</td>
                </tr>
                <tr>
                    <td>2011</td>
                    <td>6,5</td>
                    <td>5,1</td>
                    <td>5,6</td>
                </tr>
                <tr>
                    <td>2010</td>
                    <td>5,9</td>
                    <td>5,2</td>
                    <td>5,9</td>
                </tr>
            </tbody>
        </table>
    
        <table id="table3" border="1" cellpadding="5">
            <thead>
                <tr>
                    <th>Jaar</th>
                    <th>PatiŽnttevredenheidsscore</th>
                    <th>Ziektelastscore</th>
                    <th>Gewogen totaalscore</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>2013</td>
                    <td>8,0</td>
                    <td>6,2</td>
                    <td>6,8</td>
                </tr>
                <tr>
                    <td>2012</td>
                    <td>7,4</td>
                    <td>6,1</td>
                    <td>6,5</td>
                </tr>
                <tr>
                    <td>2011</td>
                    <td>6,5</td>
                    <td>5,1</td>
                    <td>5,6</td>
                </tr>
                <tr>
                    <td>2010</td>
                    <td>5,9</td>
                    <td>5,2</td>
                    <td>5,9</td>
                </tr>
            </tbody>
        </table>
    
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
        <script src="http://tablesorter.com/__jquery.tablesorter.min.js"></script>
        
        <script>
            // Default initialization
            $("#table1").tablesorter();
    
            // Initially sorted by column 2 in ascending order
            $("#table2").tablesorter({sortList: [[1,0]]});
    
            // Initially sorted by column 2 in ascending order
            $("#table3").tablesorter({sortList: [[1,1]]});
        </script>
    </body>
    </html>

  7. #7
    SitePoint Zealot
    Join Date
    Aug 2011
    Posts
    118
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You is one great neighbor, Pullo!

    I indeed forgot to delete the onclicks in the <th> tags, which I had used to see where exactly it went wrong with the vanilla script. And which did not go well with your suggestion. Deleting them indeed solved the reference error.

    And I love your jQuery solution! I normally prefer vanilla script, but this clearly justifies using the jQuery library. If it were only because it works, and we could probably not easily have solved the problem with the vanilla script. I doubt even its maker could have.

    I already nominated you this year, but as soon as I have recovered from the New Year's Eve champagne, I will nominate you again in 2014! Cheers! :-D

    PS: to return the favor, in case you would ever have problems with vertical centering in CSS, I wrote a tutorial on it. (The tut on how to target IE will undergo a major update in a while, including how to target mobile browsers on the different platforms.)

  8. #8
    GrŁŖe aus'm Pott gold trophysilver trophybronze trophy
    Pullo's Avatar
    Join Date
    Jun 2007
    Location
    Germany
    Posts
    5,940
    Mentioned
    215 Post(s)
    Tagged
    12 Thread(s)
    Hi there,

    I'm glad it works for you. Thanks for taking the time to report back.

    Quote Originally Posted by Frank S View Post
    I already nominated you this year, but as soon as I have recovered from the New Year's Eve champagne, I will nominate you again in 2014! Cheers! :-D
    Thank you
    You could also show your appreciation by voting in the end of year awards (which are starting at the beginning of next week, I believe), not just for me, but for anyone you recognize who has helped you around the forums in the past year.

  9. #9
    SitePoint Zealot
    Join Date
    Aug 2011
    Posts
    118
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Will do.

    FYI: I found out another nice aspect of the jQuery script: it adds classes, rather than replace 'em like the other script did. That makes the HTML/CSS easier. And the fact that the default sorted column can be set with the script, rather than having to HTML-construct every sortable table differently, makes it easier for the back-end developers. Great stuff!


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •