Правильные числительные

javascript, 26.09.2009 Суббота, 17:58
Теги: для блога, скрипт, числа
     Меня уже давно занимала мысль о том, как некрасиво и не верно смотрятся такие записи: 100 комментарий, Ответов : 3 и так далее.
     Я нашел достаточно простой и быстрый способ решения этой проблемы. Мой скрипт поможет правильно расставить существительные в правильной форме и ваши записи превратятся в 100 комментариев и 3 ответа. Скрипт работает во всех браузерах. Пример использования скрипта можно посмотреть в моем блоге.
     Для установки скрипта, скажем, в ваш блог, поместите число комментариев в span* с соответствующим классом**. Пример:
Code
<!-- Было -->
Комментарии:<b>$COMMENTS_NUM$</b>
  <!-- Стало -->
<b><span class='comms'>$COMMENTS_NUM$</span></b>
Так же можно поступить и с другими величинами - голосами, прочтениями и так далее. Каждая из этих величин должна стоять в span с отдельным классом.
     Затем в конец страницы вставьте скрипт:
Code
<script type="text/javascript">
setNum = function(c,n){
  var a,b,i,d;
  a = document.all||document.getElementsByTagName('*');
  for(b=0;b<a.length;b++){if(new RegExp("(^|\\b)"+c+"(\\b|$)").test(a[b].className)){
  i = function(){
  d = parseFloat(a[b].innerHTML);
  if(!d){return n[2]}else
  if(d%1){return n[1]}else
  if(/(11|12|13|14|5|6|7|8|9|0)$/.test(d)){return n[2]}else
  if(/1$/.test(d)){return n[0]}else
  if(/(2|3|4)$/.test(d)){return n[1]}
  };
  a[b].innerHTML=i().replace(/\{N\}/,d||0);
  }}
  }
</script>
После того, как вы это сделали, нужно будет вызвать обработку чисел. Для каждой отдельной группы (комментарии, голоса, просмотры) она вызывается отдельно, вот таким образом:
Code
<script type="text/javascript">
// в квадратных скобках нужное существительное в 3 разных видах
// в именительном, родительном, и родительном в множественном числе
// в каждой строчке {N} заменяется на число
// не перепутайте последовательность!
   
setNum('comms',['<b>{N}</b> комментарий','<b>{N}</b> комментария','<b>{N}</b> комментариев']);
</script>
     Вот и всё! Надеюсь статья вам пригодилась.

* не обязательно span, можно и любой другой элемент.
** класс должен быть один для каждой отдельной группы. Например для комментариев - comms.


ВИДЕОДЕСЕРТ

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

Жми на пятую!
32, 14, 6452
№14
Aleko, вставил на страницу - не работает =(

Что-то еще что ли нужно сделать?

Ответ: Включить мозг и прочитать страницу сначала. Не парьтесь, у вас всё равно не получится.
№13
[sayto]Иван[/sayto], +1.
№12
[sayto]Aleko[/sayto], на not-uCoz сайтах эту работу должна выполнять CMS. Ибо делать что-то на клиенте когда это можно нормально реализовать server-side глупо.
№11
Дробное кол-во комментов / просмотров? Ололо. Если мыслить дальше, ни Ваша, ни моя функция не разбирает числа в словесной форме. Да еще и на разных языках.
Как Вы профилировали не знаю, но http://helper.ucoz.ru/scripts-porfiling.html в 90% случаев демонструет ожидаемое превосходство арифметических действий над разбором строки регулярными выражениями.
№10
http://weiss.teatronic.net/blog/2009-08-21-53 :-)
№9
Вот тесты скорости выполнения моей функции (i) и функции, которая была предложена в 11 комментарии (fromat). Моя функция была приведена к "голому" виду, так, чтобы её результат и вызов был аналогичен присланной функции.

Моя функция:

function i(d,n){d=d||0;if(!d){return d+n[2]}else if(d%1){return d+n[1]}else if(/(11|12|13|14|5|6|7|8|9|0)$/.test(d)){return d+n[2]}else if(/1$/.test(d)){return d+n[0]}else if(/(2|3|4)$/.test(d)){return d+n[1]}};

Присланная функция:

function format(g,d){if(typeof d.onlyroot=="undefined"){d.onlyroot=false}var c=parseInt((g%100)/10),e=g%10,f=(d.onlyroot?"":g+" ")+d.root;switch(e){case 0:case 5:case 6:case 7:case 8:case 9:f+=d.end[2];break;case 1:f+=c==1?d.end[2]:d.end[0];break;case 2:case 3:case 4:f+=c==1?d.end[2]:d.end[1];break}return f};

Тест скорости в миллисекундах:

Для 1000 элементов

FireFox format: 92ms, i: 89ms
Opera 10 format: 68ms, i: 71ms
Chrome format: 45ms, i: 46ms
Safari format: 45ms, i: 40ms
IE8 format: 566ms, i: 551ms

Для 10000 элементов

FireFox format: 4469ms, i: 4492ms
Opera 10 format: 15335ms, i: 13940ms
Chrome format: 3162ms, i: 2983ms
Safari format: 2278ms, i: 2304ms
IE8 format: 49926ms, i: 49490ms

Итоги: мнение о том, что регекспы работают медленнее - не оправдались. Обе функции в одних браузерах лидируют, в других проигрывают, но во всех случаях разница в скорости выполнения неощутимо мала.

Но мой вариант функции короче и лидирует в большем числе тестов.

№8
Ох ужас... Сколько регэкспов... Все делается в сотню раз проще, простыми арифметическими действиями.
function format(n,a){if(typeof a.onlyroot=='undefined')a.onlyroot=false;var b=parseInt((n%100)/10),_u=n%10,_r=(a.onlyroot?'':n+' ')+a.root;switch(_u){case 0:case 5:case 6:case 7:case 8:case 9:_r+=a.end[2];break;case 1:_r+=b==1?a.end[2]:a.end[0];break;case 2:case 3:case 4:_r+=b==1?a.end[2]:a.end[1];break};return _r}
Вызывать как format(колво_записей, {root:'корень',['окончание для одного','для двух, трех, четырех','для пяти и более']})
Ответ: Вы в скрипте ошибку допустили.

не format(колво_записей, {root:'корень',['окончание для одного','для двух, трех, четырех','для пяти и более']})

а format(колво_записей, {root:'корень',end:['окончание для одного','для двух, трех, четырех','для пяти и более']})

И кстати да, ваша кривая функция не работает с дробями. А моя это предусматривает.

№7
[sayto]Aleko[/sayto], облако тегов вообще сууупеер!!!
№6
[sayto]владислав[/sayto], рад, что нравится. Кстати сделал на блоге поиск, теги и облако тегов. Надеюсь теперь блог будет ещё удобнее и приятнее читать!
№5
Супер! Очень полезно! =)
№4
[sayto]Gleb[/sayto], спасибо.
№3
Мне кажется, что используя стандартные коды ucoz (if endif) можно сделать такое без js. Но скрипт воистину великолепен! Супер Aleko!
№2
Спасибо! Сделаю! Ты как всегда крут !!! :)
№1
Есть альтернатива :D
Комментариев: 666, голосов: 333
    © Блог StudioAD.ru 2024 год нашей эры. Не все права защищены... Копирование любой информации и материалов с обратной ссылкой приветствуется! Хостинг от uCoz.

    Если вам пришлись по душе материалы моего блога - подпишитесь на RSS дабы получать обновления незамедлительно! Я рад что вы читаете и комментируете мои экзерсисы, приятного времяпрепровождения.