JavaScript:带有特定CSS类的数字序数后缀

12

我想在一个特定的表格中显示带序数后缀的数字。该表格始终显示来自XML文件的三个数字。这些数字显示排名,例如它们可能是第6、第120、第131名。输出是一个看起来像这样的表:

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

我希望最好使用JavaScript,并在stackoverflow上找到了一些非常好的解决方案,例如这个。然而,我无法将该函数应用于表中的所有数字,而不是逐个输入每个数字。我尝试使用CSS类,使我的函数看起来像这样:

<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>

但是它没有起作用,可能是因为我在代码的某个地方搞砸了。也许这里的某个人可以帮助我找出我哪里出错了?

非常感谢您的帮助!

8个回答

13

我的建议是:

$(".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演示

这段代码的作用是将增量数字(i++,以便从1开始而不是从0开始)转换为字符串,然后查看该字符串的最后一个数字。由于序数纯粹基于最后一个数字,因此这应该适用于任何数字。

您还可以扩展Number原型以实现此功能:

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演示

稍作修改,提供另一种选择:

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演示

这个程序遍历每个.ordinal元素,用序数后缀替换其中的数字。


编辑以解决下面评论中提出的问题: 111213分别被赋予了stndrd序数后缀。现已更正为所有情况都是th

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演示

参考资料:


这看起来很有趣,谢谢David,但它似乎没有将“第1行”,“第2行”,“第3行”等附加到第1行,第2行,第3行等。我希望“st”,“nd”,“rd”附加到表格单元中的数字上。我无法让它工作,有什么办法可以做到这一点吗? - rf2012
是的,这正是我遇到的情况,在Chrome 25 / Win XP下。你使用哪个浏览器/平台失败了?(我无法使用IE进行测试,因为IE <8整个JS Fiddle都会失败。) - David Thomas
哦,天啊,我重新读了一下我的评论,它非常令人困惑,我很抱歉。这句话本来应该是“似乎附加...”。然而,重点是我不想让表格的单元格按顺序编号,而只是将单元格内的数字显示为序数。这样更清楚吗?对于我之前不清楚的评论,我深表歉意。我在Chrome 26 / Win 7上进行了测试。 - rf2012
好的,我认为现在已经修复了,对吗? - David Thomas
在你的最后一个例子中,你没有使用变量 len - vsync
显示剩余3条评论

4
function nth(n){
    if(isNaN(n) || n%1) return n;   
    var s= n%100;
    if(s>3 && s<21) return n+'th';
    switch(s%10){
        case 1: return n+'st';
        case 2: return n+'nd';
        case 3: return n+'rd';
        default: return n+'th';
    }
}

你可以按照青少年的规则处理他们自己的行,其他整数遵循最后一位数字的规则。

2

它没有起作用是因为您将字符串返回给了$.each,而不是实际使用它们。使用方法取决于您的HTML,但这里有一个例子,可以将.ordinal文本设置为相应值。

您还在事件处理程序上缺少i参数,您可以递增i以从1st开始而不是从0th开始。

jsFiddle(译者注:该链接未提供)

$(".ordinal").each(function (i) {
    i++;
    var j = i % 10,
        str;
    if (j == 1 && i != 11) {
        str = i + "st";
    } else if (j == 2 && i != 12) {
        str = i + "nd";
    } else if (j == 3 && i != 13) {
        str = i + "rd";
    } else {
        str = i + "th";
    }
    $(this).text(str);
});

如果您的元素中已经有数字,那么最好不要依赖索引,而是检查数字,然后将字符串附加到末尾。

jsFiddle

$(document).ready(function () {
    $(".ordinal").each(function (i) {
        var j = parseInt($('ordinal').text(), 10) % 10,
            str;
        if (j == 1 && i != 11) {
            str = "st";
        } else if (j == 2 && i != 12) {
            str = "nd";
        } else if (j == 3 && i != 13) {
            str = "rd";
        } else {
            str = "th";
        }
        var elem = $(this)
        elem.text(elem.text() + str);
    });
});

太棒了,谢谢,它起作用了!但是现在我有一个问题,每个数字(例如132)都被返回为第17个,而不是第132个。我的数字超过200。你知道这个错误可能出在哪里吗? - rf2012
对我来说运行正常 http://jsfiddle.net/Tyriar/gWnUJ/,你的代码里有什么漏掉了吗? - Daniel Imms
啊,我在看到i++之前就问了这个问题,很抱歉。然而,现在它只返回数字的序数形式,比如1st、2nd、3rd,而不是像17th、132nd、146th那样。我是通过XML文档输入这些数字的,不知道这会不会有影响?所以代码应该是这样的:<table> <tr><td class='ordinal'>4</td></tr> </table>并且应该返回4th... - rf2012
更新了一个更适合包含数字元素的解决方案。 - Daniel Imms
太棒了,谢谢!!!我正在更新我的原始问题。现在唯一的问题是1返回为1th。是否可能保留所有以1、2或3结尾的数字的“st”、“nd”和“rd”结尾,但不包括11、12、13? - rf2012

2

我创造了两种方法,一种使用原型,另一种作为插件:

Number.prototype.between = function(n,m){ return this > n && this < m }
Number.prototype.ORDINATE_INDEX = ["th","st","nd","rd"];
Number.prototype.toOrdinate = function(){
    var
        nthMod = (this % 10),
        index =  nthMod > 3 || this.between(10,20) ? 0 : nthMod
    ;

    return this + this.ORDINATE_INDEX[index];
};

$(".ordinal").text(function (index, element) {
    return parseInt(element).toOrdinate();
});

这是一个Jquery插件:

(function($){
    var numberTool = new (function(){
        var private = {};

        private.ORDINATE_INDEX = ["th","st","nd","rd"];

        private.parseOrdinary = function(number)
        {
            var
                nthMod = (number % 10),
                index =  nthMod > 3 || private.between(number, 10,20) ? 0 : nthMod
            ;

            return number + private.ORDINATE_INDEX[index];
        }

        private.between = function(number, n,m){
            return number > n && number < m
        }

        this.isNumeric = function(number)
        {
            return !isNaN(parseFloat(number)) && isFinite(number);
        }

        this.toOrdinary = function(number)
        {
            return this.isNumeric(number) ? private.parseOrdinary(number) : number;
        }
    });


    $.fn.toOrdinary = function(){
        return this.each(function(){
            $element = $(this);
            $element.text(numberTool.toOrdinary($element.text()));
        }); 
    };
})(jQuery);

$(".ordinal").toOrdinary();
$(".ordinal").toOrdinary();
$(".ordinal").toOrdinary();

在JSFIDDLE上测试过:

原型版本示例:http://jsfiddle.net/f8vQr/6/

JQuery版本示例:http://jsfiddle.net/wCdKX/27/


1

一行中的序数后缀

var integerWithSuffix=originalInteger+(['st','nd','rd'][( originalInteger +'').match(/1?\d\b/)-1]||'th');

原始数字与由一个数组派生的序数所表示的字符串连接,该数组由对该数字进行正则表达式搜索的结果索引。

http://jsfiddle.net/thisishardcoded/DbSMB/


你能更详细地解释一下 RegExp,或者提供你找到这个信息的来源链接吗? - yckart
正则表达式将选择单个数字(如果给出单个数字)或数字集合中的最后一个数字。例如,1 将选择 1,而 123 将选择 3,以确定后缀。也许开头的 1 不是必需的,因为 \d\b 可以捕获单个数字或数字集合中的最后一个数字。 - Danny

0
我会像David Thomas的回答一样做这件事:
Number.prototype.ordinate = function(){
    var num = this,
        ones = num % 10, //gets the last digit
        tens = num % 100, //gets the last two digits
        ord = ["st","nd","rd"][ tens > 10 && tens < 20 ? null : ones-1 ] || 'th';
    return num.toString() + ord;
};

它实现了相同的功能。如果一个数字的最后两位在11-19范围内,或者最后一位在4-0之间,则默认为“th”,否则它将根据个位数从数组中提取“st”、“nd”或“rd”。

我非常喜欢创建原型函数的想法,但我肯定会将索引的递增放在原型函数之外,以使其更加通用:

$(".ordinal").text(function (i, t) {
    return (++i).ordinate();
});

JS Fiddle演示


0

function ordsfx(a){return["th","st","nd","rd"][(a=~~(a<0?-a:a)%100)>10&&a<14||(a%=10)>3?0:a]}

请参考https://gist.github.com/furf/986113#file-annotated-js中的注释版本。

简短、精炼、高效,正如实用函数应该具备的特点。适用于任何有符号/无符号整数/浮点数。(尽管我无法想象需要将浮点数转换为序数的情况)


0

这是我使用的方法,适用于任何年份、月份和日期(包括闰年):

// panelyear, panelmonth and panelday are passed as parameters

var PY01 = parseInt(panelyear); var PM01 = (parseInt(panelmonth) - 1); PD01 = parseInt(panelday);

var now = new Date(PY01, PM01, PD01);
var start = new Date(PY01, 0, 0);
var diff = (now - start) + ((start.getTimezoneOffset() - now.getTimezoneOffset()) * 60 * 1000);
var oneDay = 1000 * 60 * 60 * 24;
var day = Math.floor(diff / oneDay);

function getNumberWithOrdinal(n) { var s = ["th","st","nd","rd"], v = n % 100; return n + (s[(v - 20) % 10] || s[v] || s[0]); }

使用

<script> document.write(getNumberWithOrdinal(day)); </script>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接