Andryushkin.ru
Блог им. alex-borisi (Александра Андрюшкина)

Динамическое обновление времени постов на jQuery

Сегодня расскажу как динамически обновлять время у комментариев, постов и т.п. при помощи jQuery.

Думаю многие видели что у социальной сети Вконтаке (а может и еще где), время меняется примерно каждые 5-10 сек 10 секунд назад, вот по этой схеме и будем писать наш скрипт обновления.
Что будет уметь плагин?
1. Собирать данные элементов, содержащих в себе время. (в формате timestamp)
2. Через заданный интервал времени, обновлять его у элементов, которых оно было собрано.
3. Секунды, минуты, часы будут в формате (столько то N назад), остальное (дд.мм.гггг в чч.мм)
К делу
Для начала нам понадобится сформировать HTML обертку у времени, для этого нам нужно поместить его в html контейнер, например в span, div, a и т.п. (не важно).

<span class="time" data-time="Время timestamp">Время</span>

Пример с PHP

<span class="time" data-time="<? echo time(); ?>"><? echo MyFunctionTime(); ?></span>

Описание атрибутов: 
class — Для выборки по названию класса.
data-time — Будет хранить время в секундах с начала Эпохи Unix.
Собственно ВК, почти так же помечает время в комментариях. 
Пишем и разбираем код
Для начала напишем функцию «Parser» которая соберет интересующие нас элементы, и поместит данные из них в массив.

function JPTimeMap(selector, maximum) 
{
    // Массив обновляемых элементов
    var timeMapArr = [];
    
    // Текущая дата
    var Time = new Date(); 

    // Время в формате timestamp
    var phptime = Math.floor(Time.getTime() / 1000);

    // Выбираем все элементы с указанным селектором
    $(selector).each(function() { 
    
        // Время в формате timestamp
        var uid = $(this).attr('data-time'); 
        
        // Помещаем время за последние 24 часа
        if (uid > (phptime - maximum))
            timeMapArr[uid] = uid;
    });
    
    return timeMapArr;   
}

Входящие параметры
selector — Селектор элемента в котором находится наше время (в примере это .time у class)
maximum — число секунд прошедшего времени, за которое будем собирать данные (в примере будет 86400 = 24 часа)
Далее пишем код который будет работать с этими данными, и инициализировать всю работу нашего плагина.

function JPTime(option) 
{
    // Копия текущего объекта
    var parent = this;
    
    // Опции работы скрипта
    var options = $.extend({
        interval: 5000,
        selector: '.time',
        maximum: 86400,
        autoInterval: false,
        timex: 60,
    }, option);
    
    /**
    * Cклонение слов по типу 
    * 1 секунда, 2 секунды, 5 секунд
    */
    this.case_number = function(num, one, two, more) {
        var l2 = num.substr(num.length - 2, 2);
        if ((l2 >= 5) && (l2 <= 20))
            return more;
        
        var l = num.substr(num.length - 1, 1);
        switch (l) {
            case '1':
                return one;
            case '2':
                return two;
            case '3':
                return two;
            case '4':
                return two;
            default:
                return more;
        }
    };
    
    /**
    * Формат времени (сек / мин / час назад)
    */
    this.timeOut = function(time) {
        var mTime = new Date();
        
        // Текущее время
        var realtime = Math.floor(mTime.getTime() / 1000 + 22);
        
        // Шаблон текста
        var text = {2: 'две', 3: 'три', 4: 'четыре'};
        
        // Время по секундам, минутам, часам и дате
        if (time == realtime) 
            return 'только что';
        else if (time > (realtime - 60)) {
            var sec = Math.floor(realtime - time);
            return (text[sec] ? text[sec] : sec) + ' секунд' + parent.case_number(String(sec), 'а', 'ы', '') + ' назад';
        } else if (time > (realtime - 3600)) {
            var minutes = Math.floor((realtime - time) / 60);
            return (text[minutes] ? text[minutes] : minutes) + ' минут' + parent.case_number(String(minutes), 'у', 'ы', '') + ' назад';
        } else if (time > (realtime - 86400)) {
            text = {2: 'два', 3: 'три', 4: 'четыре'};
            var hours = Math.floor((realtime - time) / 3600);
            return hours + ' час' + parent.case_number(String(hours), '', 'а', 'ов') + ' назад';
        } else {
            var t = new Date();
            t.setTime(time * 1000);
            return t.getDate()+'.'+
                   t.getMonth()+'.'+
                   t.getFullYear()+' в '+
                   t.getHours()+':'+
                   t.getMinutes()+':'+
                   t.getSeconds();
        }
    };
    
    /**
    * Запуск скрипта
    */
    this.start = function() {
        
        // Массив обновляемых элементов
        var timeMap = JPTimeMap(options.selector, options.maximum); 
        
        // Если есть что то в массиве, то запускаем обновление
        if (parent.count(timeMap) > '0') {
            interval = setInterval(function() {
                
                // Текущая метка времени
                jtime = Math.floor(new Date().getTime() / 1000 + 22);
                
                // Исполняющий цикл
                for(var p in timeMap) {
                    var newTime = parent.timeOut(p);
                    $('[data-time = "' + p + '"]').text(newTime);
                    endTime = p; 
                }
                
                // Наименьшее время из массива
                end = (jtime - endTime);
                
                // Корректировка интервала
                if (options.autoInterval === true) 
                    if (end > options.timex) 
                        options.interval = 60000, options.timex += end;             
                
            }, options.interval);
        }
    };
    
    /**
    * Псевдоним php функции count()
    */
    this.count = function(arr) {
        var cnt = 0;
        for (var i in arr) {
            if (i) 
               cnt++;
        }
        return cnt;
    };
}

Теперь когда все написали, сохраняем это все в js файл, например jptime.js и подключаем в шапку сайта, или страницу с выводом обновляемого времени.
Инициализация: 

var JPTime = new JPTime({
  interval: 5000, 
  selector: '.time',
  maximum: 86400,
  autoInterval: true,
});

JPTime.start();

Параметры: 
interval — Колличество миллисекунд, через которое будут обновляться элементы времени.
selector — метка атрибута, для идентификации элемента времени, я выбирал по .time в class
maximum — Максимальное колличество секунд, за которое будет выбираться элемент для создания массива.
autoInterval — Принимает значение false или true (по умолчанию false), если true, то при достижении минимального времени в 60 сек. интервал обновления становится 1 раз в минуту, если false, по заданному интервалу.

Ну, собственно, это все, что хотел написать.
Пример можно увидеть здесь, скачать готовый jptime.js можно по этой ссылке, полный пример demo можно скачать по этой ссылке.
Всем благ, и удачных разработок!