SitePoint Sponsor

User Tag List

Results 1 to 8 of 8
  1. #1
    SitePoint Addict D3V4's Avatar
    Join Date
    May 2010
    Posts
    370
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Change order of table rows

    I use PHP to create an HTML table with information from a database, ordered by date. Some of the rows of the table have a class named "new", while the others don't have any class. What I would like to do is to have all the rows with class "new" shown as last rows of that specific date.

    So for example:

    Code:
    <tr>...<td>01-01-2011</td>...</tr>
    <tr>...<td>01-01-2011</td>...</tr>
    <tr class="new">...<td>01-01-2011</td>...</tr>
    <tr class="new">...<td>01-01-2011</td>...</tr>
    Is this possible using javascript/jquery?

  2. #2
    SitePoint Evangelist speda1's Avatar
    Join Date
    Jan 2002
    Posts
    550
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    One solution would be to tag the <tr>'s with an id attribute and use jquery's sortable behavior.

  3. #3
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,729
    Mentioned
    104 Post(s)
    Tagged
    4 Thread(s)
    Quote Originally Posted by D3V4 View Post
    I use PHP to create an HTML table with information from a database, ordered by date. Some of the rows of the table have a class named "new", while the others don't have any class. What I would like to do is to have all the rows with class "new" shown as last rows of that specific date.
    Normally a sort function looks like this:

    Code javascript:
    function (a, b) {
        if (a < b) {
            return -1;
        }
        if (a > b) {
            return 1;
        }
        return 0;
    }

    So, we can take that and modify it to work the way you want.

    First we'll need to get the table rows in to an array, so that w can then use the array sort features.
    Then with the sort function, a and b are going to be table rows, so if they're not table rows we should just exit the function. We get the date from the table data, and sort based on that.
    If the dates are the same we compare the class name instead. If one of the classes is "new" and the other isn't, we can immediately return that new one as the preferred sort.

    Let's try that out.

    I'm going to get the innerHTML of the first TD element, so depending on your table structure, you may need to use some other technique to retrieve the date.

    Code javascript:
    function compareTRDates(a, b) {
        aDate = Date.parse(a.getElementsByTagName('td')[0].innerHTML);
        bDate = Date.parse(b.getElementsByTagName('td')[0].innerHTML);
        if (aDate < bDate) {
            return -1;
        }
        if (aDate > bDate) {
            return 1;
        }
        return 0;
    }

    Comparing the new class name is straight-forward by comparison:

    Code javascript:
    function compareNewClass(a, b) {
        if (a.className !== 'new' && b.className === 'new') {
            return -1;
        }
        if (a.className === 'new' && b.className !== 'new') {
            return 1;
        }
        return 0;
    }

    Lastly, you'll want to compare the dates, and if the dates are equal, to compare by the new class name instead.

    Code javascript:
    function compareTRDatesThenNew(a, b) {
        return compareTRDates(a, b) || compareNewClass(a, b);
    }

    Here's a simple test page that lets you test the sorting.

    Code javascript:
    <html>
    <style type="text/css">
    .new {
        background: lightgreen;
    }
    </style>
    </head>
    <body>
    <table id="databaseInfo">
        <tr class="new">...<td>01-01-2011</td>...</tr>
        <tr>...<td>10-01-2011</td>...</tr>
        <tr>...<td>01-01-2011</td>...</tr>
        <tr>...<td>01-10-2010</td>...</tr>
        <tr>...<td>01-01-2011</td>...</tr>
        <tr class="new">...<td>01-01-2011</td>...</tr>
    </table>
    <button id="sortbydate">Sort by Date</button>
    <button id="sortbynew">Sort by New</button>
    <button id="sortbydatethennew">Sort by Date then New</button>
    <script>
    function compareTRDates(a, b) {
        aDate = Date.parse(a.getElementsByTagName('td')[0].innerHTML);
        bDate = Date.parse(b.getElementsByTagName('td')[0].innerHTML);
        if (aDate < bDate) {
            return -1;
        }
        if (aDate > bDate) {
            return 1;
        }
        return 0;
    }
    function compareNewClass(a, b) {
        if (a.className !== 'new' && b.className === 'new') {
            return -1;
        }
        if (a.className === 'new' && b.className !== 'new') {
            return 1;
        }
        return 0;
    }
    function compareTRDatesThenNew(a, b) {
        return compareTRDates(a, b) || compareNewClass(a, b);
    }
    function sortTableRows(compareFunction) {
        var table = document.getElementById('databaseInfo'),
            rows = table.getElementsByTagName('tr');
        rows = Array.prototype.splice.call(rows, 0);
        rows.sort(compareFunction);
     
        while (table.hasChildNodes()) {
            table.removeChild(table.firstChild);
        }
        for (i = 0; i < rows.length; i += 1) {
            table.appendChild(rows[i]);
        }
    }
     
    document.getElementById('sortbydate').onclick = function () {
        sortTableRows(compareTRDates);
    };
    document.getElementById('sortbynew').onclick = function () {
        sortTableRows(compareNewClass);
    };
    document.getElementById('sortbydatethennew').onclick = function () {
        sortTableRows(compareTRDatesThenNew);
    };
    </script>
    </body>
    </html>
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  4. #4
    SitePoint Addict D3V4's Avatar
    Join Date
    May 2010
    Posts
    370
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by speda1 View Post
    One solution would be to tag the <tr>'s with an id attribute and use jquery's sortable behavior.
    Isn't that used for dragging and dropping elements?

    Quote Originally Posted by paul_wilkins View Post
    .
    .
    .
    Do you have any idea why Firebug gives me a "getElementsByTagName is not defined" error?

  5. #5
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,729
    Mentioned
    104 Post(s)
    Tagged
    4 Thread(s)
    Quote Originally Posted by D3V4 View Post
    Do you have any idea why Firebug gives me a "getElementsByTagName is not defined" error?
    I've just tried it in Firefox and found that Firefox has trouble parsing dates in a dd-mm-yyyy or mm-dd-yyyy format, so we'll have to interpret those dates ourself manually.

    You don't mention whether the dates you are using are dd-mm-yyyy or mm-dd-yyyy so I will presume that you are in the majority who use dd-mm-yyyy

    Because some web browsers aren't as good at parsing dates, we have to break up those dates in to their component parts and give them to the parse function in a way that the web browser can understand.

    Code javascript:
    // take dates from dd-mm-yyyy format and parse as yyyy-mm-dd
    var aText = a.getElementsByTagName('td')[0].innerHTML,
        bText = b.getElementsByTagName('td')[0].innerHTML,
        aMatch = aText.match(/(\d*)-(\d*)-(\d*)/),
        bMatch = bText.match(/(\d*)-(\d*)-(\d*)/),
        aDate = Date.parse(aMatch[3] + '-' + aMatch[2] + '-' + aMatch[1]),
        bDate = Date.parse(bMatch[3] + '-' + bMatch[2] + '-' + bMatch[1]);

    Also with Internet Explorer, there can be some troubles with updating the table, so we're going to work with the tbody element itself to keep IE happier.

    Code html4strict:
    <table id="databaseInfo">
        <tbody>
            ...
        </tbody>
    </table>

    The following sample code should now work more consistently across multiple web browsers.

    Code javascript:
    <html>
    <style type="text/css">
    .new {
        background: lightgreen;
    }
    </style>
    </head>
    <body>
    <table id="databaseInfo">
        <tbody>
            <tr class="new"><td>01-01-2011</td></tr>
            <tr><td>10-01-2011</td></tr>
            <tr><td>01-01-2011</td></tr>
            <tr><td>01-10-2011</td></tr>
            <tr><td>01-01-2011</td></tr>
            <tr class="new"><td>01-01-2011</td></tr>
        </tbody>
    </table>
    <button id="sortbydate">Sort by Date</button>
    <button id="sortbynew">Sort by New</button>
    <button id="sortbydatethennew">Sort by Date then New</button>
    <script>
    Array.fromSequence = function (seq) {
        var arr = [],
            i;
        for (i = 0; i < seq.length; i += 1) {
            if (seq[i]) {
                arr[i] = seq[i];
            }
        }
        return arr;
    };
    function compareTRDates(a, b) {
        // take dates from dd-mm-yyyy format and parse as yyyy-mm-dd
        var aText = a.getElementsByTagName('td')[0].innerHTML,
            bText = b.getElementsByTagName('td')[0].innerHTML,
            aMatch = aText.match(/(\d*)-(\d*)-(\d*)/),
            bMatch = bText.match(/(\d*)-(\d*)-(\d*)/),
            aDate = Date.parse(aMatch[3] + '-' + aMatch[2] + '-' + aMatch[1]),
            bDate = Date.parse(bMatch[3] + '-' + bMatch[2] + '-' + bMatch[1]);
        if (aDate < bDate) {
            return -1;
        }
        if (aDate > bDate) {
            return 1;
        }
        return 0;
    }
    function compareNewClass(a, b) {
        if (a.className !== 'new' && b.className === 'new') {
            return -1;
        }
        if (a.className === 'new' && b.className !== 'new') {
            return 1;
        }
        return 0;
    }
    function compareTRDatesThenNew(a, b) {
        return compareTRDates(a, b) || compareNewClass(a, b);
    }
    function sortTableRows(compareFunction) {
        var table = document.getElementById('databaseInfo'),
            tbody = table.getElementsByTagName('tbody')[0],
            rows = tbody.getElementsByTagName('tr'),
            i;
        rows = Array.fromSequence(rows);
        rows.sort(compareFunction);
        while (tbody.hasChildNodes()) {
            tbody.removeChild(tbody.firstChild);
        }
        for (i = 0; i < rows.length; i += 1) {
            tbody.appendChild(rows[i]);
        }
    }
     
    document.getElementById('sortbydate').onclick = function () {
        sortTableRows(compareTRDates);
    };
    document.getElementById('sortbynew').onclick = function () {
        sortTableRows(compareNewClass);
    };
    document.getElementById('sortbydatethennew').onclick = function () {
        sortTableRows(compareTRDatesThenNew);
    };
    </script>
    </body>
    </html>
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  6. #6
    SitePoint Addict D3V4's Avatar
    Join Date
    May 2010
    Posts
    370
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Now it works, thanks a lot

    I just have one question though: why do you use

    Code:
    return -1
    and

    Code:
    return 1
    to sort the values? I thought that you had to use arrays to separate values

  7. #7
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,729
    Mentioned
    104 Post(s)
    Tagged
    4 Thread(s)
    Quote Originally Posted by D3V4 View Post
    Now it works, thanks a lot

    I just have one question though: why do you use

    Code:
    return -1
    and

    Code:
    return 1
    to sort the values?
    That's how the sort function determines which order the values are in. -1 means that the a value is smaller than the b value. 1 means that the a value is greater than the b value.

    If you were sorting numbers, you could return a-b instead.

    See the sort documentation for the full details about that.
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  8. #8
    SitePoint Addict D3V4's Avatar
    Join Date
    May 2010
    Posts
    370
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Now I understand, thank you


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
  •