Помогите сделать постраничный вывод сообщений в ajax-чате

verfaa

Профессор
Регистрация
29 Янв 2007
Сообщения
416
Реакции
49
Нужно прикрутить на сайт знакомств вебмессенджер, где пользователи могли бы общаться один на один. Покопавшись в нете, ничего подходящего толком не нашев, я решил взять за основу чат, который подробно описан в этих двух уроках:
Для просмотра ссылки Войди или Зарегистрируйся
Для просмотра ссылки Войди или Зарегистрируйся

Опыта в программировании у меня немного, а опыта работы с JS совсем мало, поэтому с доработкой скрипта до вебмессенджера возникли трудности. Скрипт с руселлера я немного переработал, убрал из него ненужные на мой взгляд куски кода, дописал свой код, в результате пользователи могут отправлять друг другу сообщения и получать их.
Но в руселлерском чате не сделана постраничная навигация сообщений, в результате чего все сообщения сразу подгружаются на страницу. А сообщений может быть много, 1000 например или больше и все они будут пытаться загрузиться на страницу, будет не очень хорошо, нужна постраничная навигация, как это сделано на mamba.ru или loveplanet.ru

Вот код, который я имею на данный момент:
HTML + JS
Код:
<div id="chatContainer">
 
    <div id="chatTopBar" class="rounded"></div>
    <div id="chatLineHolder"></div>
 
    <div id="chatBottomBar" class="rounded">
        <div class="tip"></div>
 
        <form id="submitForm" method="post" action="">
            <textarea id="chatText" name="chatText" class="rounded" maxlength="255"></textarea><br />
            <input type="submit" class="blueButton" value="Send msg!" />
        </form>
 
    </div>
 
</div>
 
<div id="num_pages"></div>
 
 
 
<script src="{$site_root}{$template_root}/js/im_jquery.mousewheel.js"></script>
<script src="{$site_root}{$template_root}/js/im_jScrollPane.min.js"></script>
 
<script type="text/javascript">
    $(document).ready(function(){
 
    // Запускаем метод init, когда документ будет готов:
    chat.init();
 
});
 
var chat = {
 
    // data содержит перменные для использования в классах:
 
    data : {
        lastID        : 0,
        noActivity    : 0
    },
 
    // Init привязывает обработчики событий и устанавливает таймеры:
 
    init : function(){
 
        // Конвертируем div #chatLineHolder в jScrollPane,
        // сохраняем API плагина в chat.data:
 
        chat.data.jspAPI = $('#chatLineHolder').jScrollPane({
            verticalDragMinHeight: 12,
            verticalDragMaxHeight: 12
        }).data('jsp');
 
        // Используем перменную working для предотвращения
        // множественных отправок формы:
 
        var working = false;
 
        // Отправляем данные новой строки чата:
 
        $('#submitForm').submit(function(){
 
            var text = $('#chatText').val();
 
            if(text.length == 0){
                return false;
            }
 
            if(working) return false;
            working = true;
 
            // Генерируем временный ID для чата:
            var tempID = 't'+Math.round(Math.random()*1000000),
                params = {
                    id            : tempID,
                    author        : chat.data.name,
                    gravatar    : chat.data.gravatar,
                    text        : text.replace(/</g,'&lt;').replace(/>/g,'&gt;')
                };
 
            // Используем метод addChatLine, чтобы добавить чат на экран
            // немедленно, не ожидая заверщения запроса AJAX:
 
            chat.addChatLine($.extend({},params));
 
            // Используем метод tzPOST, чтобы отправить чат
            // черех запрос POST AJAX:
 
            $.tzPOST('submitChat',$(this).serialize(),function(r){
                working = false;
     
                $('#chatText').val('');
                $('div.chat-'+tempID).remove();
     
                params['id'] = r.insertID;
                chat.addChatLine($.extend({},params));
            });
 
            return false;
        });
 
 
        // Самовыполняющиеся функции таймаута
 
        (function getChatsTimeoutFunction(){
            chat.getChats(getChatsTimeoutFunction);
        })();
 
 
 
    },
 
 
    // Метод render генерирует разметку HTML,
    // которая нужна для других методов:
 
    render : function(template,params){
 
        var arr = [];
        switch(template){
 
            case 'chatLine':
                arr = [
                    '<div class="chat chat-',params.id,' rounded"><span class="author">',params.author,
                    ':</span><span class="text">',params.text,'</span><span class="time">',params.time,'</span></div>'];
            break;
 
        }
 
        // Единственный метод join для массива выполняется
        // бысстрее, чем множественные слияния строк
 
        return arr.join('');
 
    },
 
    // Метод addChatLine добавляет строку чата на страницу
 
    addChatLine : function(params){
 
        // Все показания времени выводятся в формате временного пояса пользователя
 
        var d = new Date();
        if(params.time) {
 
            // PHP возвращает время в формате UTC (GMT). Мы используем его для формирования объекта date
            // и дальнейшего вывода в формате временного пояса пользователя.
            // JavaScript конвертирует его для нас.
 
            d.setUTCHours(params.time.hours,params.time.minutes);
        }
 
        params.time = (d.getHours() < 10 ? '0' : '' ) + d.getHours()+':'+
                      (d.getMinutes() < 10 ? '0':'') + d.getMinutes();
 
        var markup = chat.render('chatLine',params),
            exists = $('#chatLineHolder .chat-'+params.id);
 
        if(exists.length){
            exists.remove();
        }
 
        if(!chat.data.lastID){
            // Если это первая запись в чате, удаляем
            // параграф с сообщением о том, что еще ничего не написано:
 
            $('#chatLineHolder p').remove();
        }
 
        // Если это не временная строка чата:
        if(params.id.toString().charAt(0) != 't'){
            var previous = $('#chatLineHolder .chat-'+(+params.id - 1));
            if(previous.length){
                previous.after(markup);
            }
            else chat.data.jspAPI.getContentPane().append(markup);
        }
        else chat.data.jspAPI.getContentPane().append(markup);
 
        // Так как мы добавили новый контент, нужно
        // снова инициализировать плагин jScrollPane:
 
        chat.data.jspAPI.reinitialise();
        chat.data.jspAPI.scrollToBottom(true);
 
    },
 
    // Данный метод запрашивает последнюю запись в чате
    // (начиная с lastID), и добавляет ее на страницу.
 
    getChats : function(callback){
        $.tzGET('getChats',{lastID: chat.data.lastID},function(r){
 
            for(var i=0;i<r.chats.length;i++){
                chat.addChatLine(r.chats[i]);
            }
 
 
            if(r.chats.length){
                chat.data.noActivity = 0;
                chat.data.lastID = r.chats[i-1].id;
            }
            else{
                // Если нет записей в чате, увеличиваем
                // счетчик noActivity.
     
                chat.data.noActivity++;
            }
 
            if(!chat.data.lastID){
                chat.data.jspAPI.getContentPane().html('<p class="noChats">Ничего еще не написано</p>');
            }
 
            // Устанавливаем таймаут для следующего запроса
            // в зависимости активности чата:
 
            var nextRequest = 1000;
 
            // 2 секунды
            if(chat.data.noActivity > 3){
                nextRequest = 2000;
            }
 
            if(chat.data.noActivity > 10){
                nextRequest = 5000;
            }
 
            // 15 секунд
            if(chat.data.noActivity > 20){
                nextRequest = 15000;
            }
 
            setTimeout(callback,nextRequest);
        });
    },
 
    // Данный метод выводит сообщение об ошибке наверху страницы:
 
    displayError : function(msg){
        var elem = $('<div>',{
            id        : 'chatErrorMessage',
            html    : msg
        });
 
        elem.click(function(){
            $(this).fadeOut(function(){
                $(this).remove();
            });
        });
 
        setTimeout(function(){
            elem.click();
        },5000);
 
        elem.hide().appendTo('body').slideDown();
    }
};
 
// Формирование GET & POST:
 
$.tzPOST = function(action,data,callback){
    $.post('im_ajax.php?action='+action+'&resp={$respondent}',data,callback,'json');
}
 
$.tzGET = function(action,data,callback){
    $.get('im_ajax.php?action='+action+'&resp={$respondent}',data,callback,'json');
}
 
</script>

В скрипт айди пользователя, с которым общается юзер, я передаю в обычном GET-запросе, т.е. в анкете есть ссылка <a href='im.php?resp=29476'>написать сообщение</a> - юзер её кликает и попадает на страницу с чатом и начинает общение)

im_ajax.php
Код:
<?php
 
// Если к нам идёт Ajax запрос, то ловим его
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
 
// тут подключаем базу данных, стартуем сессию, включаем необходимые библиотеки...
 
$user = auth_index_user(); // Авторизуем юзера
$id_user = intval($user[0]); // Тут будет айди юзера
 
 
$response = array();
 
switch($_GET['action']){
//Добавляем сообщение в базу
case 'submitChat':
$strSQL = "INSERT INTO pro_im_lines (id_user, id_respondent, text)
            VALUES (
                '".$id_user."',
                '".mysql_real_escape_string($_REQUEST['resp'])."',
                '".mysql_real_escape_string($_POST['chatText'])."'     
        )";
        $dbconn->Execute($strSQL);
 
$rs = $dbconn->Execute("SELECT LAST_INSERT_ID() FROM pro_im_lines");
 
  $response = array(
            'status'    => 1,
            'insertID'  => $rs->fields[0]
        );
 
  break;
 
 
 
 
case 'getChats':
// Получаем сообщения из базы, которые мы отправляли
  // собеседнику и которые собеседник отправлял нам, только 10 последних!
$strSQL = "(SELECT * FROM pro_im_lines WHERE
                        ((id_user='".$id_user."' AND
                        id_respondent='".intval($_REQUEST['resp'])."') OR
                        (id_user='".intval($_REQUEST['resp'])."' AND
                        id_respondent='".$id_user."')) AND
                        id > '".intval($_GET['lastID'])."' ORDER BY id DESC LIMIT 10)
                        ORDER BY id ASC";
 
 
        $rs = $dbconn->Execute($strSQL);
 
$i = 0;
    $chats = array();
    while(!$rs->EOF){
        $row = $rs->GetRowAssoc(false);
        $chats[$i]["id"] = $row["id"];
        $chats[$i]["author"] = $row["id_respondent"];
        $chats[$i]["text"] = $row["text"];
        $chats[$i]["ts"] = $row["ts"];
        $chats[$i]["time"] = array(
                      'hours'    => gmdate('H',strtotime($chats[$i]["ts"])),
                      'minutes'  => gmdate('i',strtotime($chats[$i]["ts"]))
                        );
        $rs->MoveNext();
        $i++;
    }
  // В результате в массиве $chats окажутся все сообщения, которые мы отправляли
  // собеседнику и которые собеседник отправлял нам.
// Этот массив мы отправляем обратно в JS ниже - echo json_encode($response);
 
 
 
 
    // А тут я пытался сделать постраничный вывод:
// Выбираем все сообщения, которые мы отправляли друг другу
    $strSQL = "SELECT * FROM pro_im_lines WHERE
                        (id_user='".$id_user."' AND
                        id_respondent='".intval($_REQUEST['resp'])."') OR
                        (id_user='".intval($_REQUEST['resp'])."' AND
                        id_respondent='".$id_user."')";
    $rs = $dbconn->Execute($strSQL);         
    $row_count = $rs->RowCount(); //считаем число строк в таблице с сообщениями
    $pages = ceil($row_count/10);//определим количество страниц
    $pages_arr = array();
    if($pages>1){
    for($i=1;$i<=$pages;$i++){
    $pages_arr[] = "<a href=\"javascript:ajax_get_data('.$page-1.');\">'.$i.' </a>";
    }
  }
 
 
    $response = array('chats' => $chats, 'pages_arr' => $pages_arr);
    break;
 
}
 
echo json_encode($response);
 
}
...
?>

В результате в массив pages_arr попадают нужные элементы (вижу в файрбаге) - ссылки, но как их добавить на страницу ума не приложу. В JS в
возвратную функцию пытался добавить
for(var i=0;i<r. pages_arr.length;i++){
$("#num_pages").appendTo(r.pages_arr);


}
но ничего не добавляет, а в файрбаге в firefox только ошибку вываливает((
Подскажите плиз, как мне сделать постраничную навигацию в моем случае и чтобы когда пользователь кликает скажем на 5-ю страницу нужные сообщения через ajax подкружались в окно чата.
И в целом по коду, может его можно оптимизировать как-то, удалить ненужные части или добавить что-то? Понимаю что много написал, очень надеюсь на помощь и советы...
 
Назад
Сверху