Javascript: ординарный суффикс для чисел с определенным классом CSS

Я пытаюсь отобразить числа в определенной таблице с порядковыми суффиксами. В таблице всегда отображаются три числа, которые поступают из файла 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>

но он не работает, возможно, потому, что я где-то прикрутил код. Может быть, кто-то здесь может помочь мне и сказать, где я ошибся?

Большое спасибо за вашу помощь!

Ответ 1

Мое собственное предложение было бы:

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

Это эффективно принимает добавочное число (i++, чтобы начать с 1 not 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 demo.

Отредактировано, чтобы предложить небольшую альтернативу:

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.

Это по существу повторяется через каждый элемент .ordinal, заменяя числа, присутствующие (такими же) числами, с добавленным к нему порядковым суффиксом.


Отредактированный, чтобы устранить проблему, поднятую в комментариях ниже, чтобы 11, 12 и 13 получали порядковый суффикс st, nd и rd (соответственно). Теперь это исправлено как 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 demo.

Литература:

Ответ 2

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';
    }
}

Вы можете позаботиться о подростках в своей собственной строке, другие целые числа следуют последним правилам цифр.

Ответ 3

Я создал два подхода, один из которых использует Prototype, другой - как плагин:

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/

Ответ 4

Он не работает, потому что вы возвращаете строки в $.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);
    });
});

Ответ 5

Порядковый суффикс в одной строке

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

конкатенация исходного числа и строка, представляющая порядковый номер, полученный из массива, проиндексированного результатом поиска регулярного выражения на этом количестве

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

Ответ 6

Я бы сделал что-то подобное, опираясь на Дэвида Томаса:

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 Demo

Ответ 7

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

Короткие, сладкие и эффективные, как и функции утилиты. Работает с любым подписанным /unsigned integer/float. (Несмотря на то, что я не могу представить себе необходимость упорядочивать поплавки)

Ответ 8

Это то, что я использую, и это работает для любого года, месяца, дня (високосный год):

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