javascriptjqueryordinals

Javascript: Ordinal suffix for numbers with specific CSS class


I am trying to display numbers within a particular table with ordinal suffixes. The table always shows three numbers which come from an XML file. The numbers show ranks, so for example they may be 6th, 120th, 131st. The output is a table that would look like this:

<table>
    <tr>
        <td class='ordinal'>6</td>
        <td class='ordinal'>120</td>
        <td class='ordinal'>131</td>
    </tr>
</table>

I would ideally like to use javascript and I found a few very good solutions on stackoverflow, for example this one. However, I am struggling to apply the function to all numbers within the table, rather than putting in each number individually. I tried using a CSS class so that my function looks like this:

<script type="text/javascript">
$(function(){
    $(".ordinal").each(function(){
        var j = i % 10;
        if (j == 1 && i != 11) {
            return i + "st";
        }
        if (j == 2 && i != 12) {
            return i + "nd";
        }
        if (j == 3 && i != 13) {
            return i + "rd";
        }
        return i + "th";
        });
})
</script>

but it's not working, probably because I screwed up the code somewhere. Maybe somebody here can help me out and tell me where I went wrong?

Thank you very much for your help!


Solution

  • My own suggestion, would be:

    $(".ordinal").text(function (i, t) {
        i++;
        var str = i.toString().slice(-1),
            ord = '';
        switch (str) {
            case '1':
                ord = 'st';
                break;
            case '2':
                ord = 'nd';
                break;
            case '3':
                ord = 'rd';
                break;
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
            case '0':
                ord = 'th';
                break;
        }
        return i + ord;
    });
    

    JS Fiddle demo.

    This effectively takes the incremented number (i++, in order to start from 1 not 0), converts it to a string, then looks at the last number of that string. This should work for any number, since the ordinal is based purely on that last number.

    You could also extend the Number prototype to implement this functionality:

    Number.prototype.ordinate = function(){
        var num = this + 1,
            last = num.toString().slice(-1),
            ord = '';
        switch (last) {
            case '1':
                ord = 'st';
                break;
            case '2':
                ord = 'nd';
                break;
            case '3':
                ord = 'rd';
                break;
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
            case '0':
                ord = 'th';
                break;
        }
        return num.toString() + ord;
    };
    
    $(".ordinal").text(function (i, t) {
        return i.ordinate();
    });
    

    JS Fiddle demo.

    Edited to offer a slight alternative:

    Number.prototype.ordinate = function(){
        var num = this,
            last = num.toString().slice(-1),
            ord = '';
        switch (last) {
            case '1':
                ord = 'st';
                break;
            case '2':
                ord = 'nd';
                break;
            case '3':
                ord = 'rd';
                break;
            default:
                ord = 'th';
                break;
        }
        return num.toString() + ord;
    };
    
    $(".ordinal").text(function (i,t) {
        return t.replace(/(\d+)/g, function(a){
            return parseInt(a, 10).ordinate();
        });
    });
    

    JS Fiddle demo.

    This essentially iterates over each .ordinal element, replacing the numbers present with the (same) numbers with the ordinal suffix added to it.


    Edited to address the problem, raised in the comments, below, that 11, 12 and 13 were receiving the ordinal suffix of st, nd and rd (respectively). This is now corrected to being th in all cases:

    Number.prototype.ordinate = function(){
        var num = this,
            numStr = num.toString(),
            last = numStr.slice(-1),
            len = numStr.length,
            ord = '';
        switch (last) {
            case '1':
                ord = numStr.slice(-2) === '11' ? 'th' : 'st';
                break;
            case '2':
                ord = numStr.slice(-2) === '12' ? 'th' : 'nd';
                break;
            case '3':
                ord = numStr.slice(-2) === '13' ? 'th' : 'rd';
                break;
            default:
                ord = 'th';
                break;
        }
        return num.toString() + ord;
    };
    

    JS Fiddle demo.

    References: