Bài 14: jQuery Ajax scrolling pagination với PHP và MYSQL

DOWNLOAD DEMO

Hiện nay có một số website khi các bạn kéo xuống phía dưới cùng thì nó tự động load thêm dữ liệu. Facebook là một ví dụ nhưng nó khác ở chỗ là nó thực hiện hai thao tác, thứ nhất là kéo xuống sẽ load thêm, thứ hai là nó thiết lập sau một thời gian sẽ load thêm. Chức năng này người ta gọi là Ajax Scrolling Pagination.

1. Ajax Scrolling Pagination với PHP và MYSQL

Chúng ta sẽ đi từng phần một để các bạn dễ hiểu bài hơn, quy trình như sau:

  • Tạo CSDL và thêm một số record để test
  • Tạo file hiển thị danh sách 
  • Dùng jQuery xử lý sự kiện Scrolling và gọi ajax

Mỗi bước chúng ta sẽ có những đoạn code liên kết với nhau nên các bạn đọc kỹ bài viết nhé.

Tạo database để phân trang khi scrolling

Tạo database:

CREATE TABLE IF NOT EXISTS `tb_customer` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `website` VARCHAR(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  UNIQUE KEY `id` (`id`)
) ENGINE=INNODB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=11 ;
Thêm một vài record:

INSERT INTO `tb_customer` (`id`, `name`, `website`) VALUES
(1, 'Nguyễn Văn Cường', 'freetuts.net'),
(2, 'Trương Phúc Hoài Minh', 'freetuts.net'),
(3, 'Đặng Văn Chương', 'freetuts.net'),
(4, 'Trương Tấn Thành', 'freetuts.net'),
(5, 'Lâm văn Lang', 'demo.com'),
(6, 'Nguyễn Văn Kiệt', 'ajax.com'),
(7, 'Nguyễn Thị Nở', 'thimau.com'),
(8, 'Đặng Thị Thoa', 'scrolling.com'),
(9, 'Trương Văn Kiệt', 'ajaxscrolling.com'),
(10, 'Đặng Thị Tâm', 'nono.com');

Tạo file hiển thị kết quả phân trang khi scrolling

Bạn tạo file list.php với nội dung như sau:

<!DOCTYPE html>
<html>
    <head>
        <title></title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <script language="javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js" ></script>
        <script language="javascript" src="ajax.js" ></script>
        <style type="text/css">
            #loadding {color:red; font-size: 20px; font-weight: bold; text-align: center}
            .item {height: 500px; border: solid 2px blue; background: #CCCCCC; 
                  line-height: 500px; color: blue; text-align: center; font-weight: bold; margin: 20px 0px;}
            .hidden {display: none}
        </style>
    </head>
    <body>
        <div id="content">
            <?php require('data.php'); ?>
        </div>
        <div id="loadding" class="hidden">
            LOADDING ...
        </div>
    </body>
</html>
Trong file này tôi có thêm thư viện jQuery, file ajax.js  và tạo hai thẻ div như sau:

  • <div id="content"> dùng để hiển thị danh sách, trong này tôi có require  file data.php mà chúng ta sẽ tạo ở bước tiếp theo
  • <div id="loadding" class="hidden"> dùng để hiển thị chữ loadding khi gửi ajax

Viết jQuery Ajax Scrolling Pagination

Bạn tạo file ajax.js với nội dung như sau, lưu ý là file này mình đã import vào file list.php ở bước trên.

// Biến dùng kiểm tra nếu đang gửi ajax thì ko thực hiện gửi thêm
var is_busy = false;
    
// Biến lưu trữ trang hiện tại
var page = 1;

// Biến lưu trữ rạng thái phân trang 
var stopped = false;

$(document).ready(function()
{    
    // Khi kéo scroll thì xử lý
    $(window).scroll(function() 
    {
        // Element append nội dung
        $element = $('#content');
        
        // ELement hiển thị chữ loadding
        $loadding = $('#loadding');
        
        // Nếu màn hình đang ở dưới cuối thẻ thì thực hiện ajax
        if($(window).scrollTop() + $(window).height() >= $element.height()) 
        {
            // Nếu đang gửi ajax thì ngưng
            if (is_busy == true){
                return false;
            }
            
            // Nếu hết dữ liệu thì ngưng
            if (stopped == true){
                return false;
            }
            
            // Thiết lập đang gửi ajax
            is_busy = true;
            
            // Tăng số trang lên 1
            page++;
            
            // Hiển thị loadding
            $loadding.removeClass('hidden');
            
            // Gửi Ajax
            $.ajax(
            {
                type        : 'get',
                dataType    : 'text',
                url         : 'data.php',
                data        : {page : page},
                success     : function (result)
                {
                    $element.append(result);
                }
            })
            .always(function()
            {
                // Sau khi thực hiện xong ajax thì ẩn hidden và cho trạng thái gửi ajax = false
                $loadding.addClass('hidden');
                is_busy = false;
            });
            return false;
        }
    });
});
File này tôi đã comment rất kỹ rồi, chung quy lại ý tưởng như sau:

  • Tạo các biến is_busy, pagestopped để lưu các thông số kiểm tra khi phân trang
  • Thực hiện phân trang khi màn hình kéo xuống dưới cùng 
  • Trước khi gửi phải kiểm tra các giá trị các biến toàn cục để quyết định gửi ajax hay không, đồng thời hiển thị chữ loadding nếu cho phép gửi ajax
  • Sau khi gửi ajax thì ẩn nút loadding
  • Sử dụng sử dụng phương thức GET trong jquery ajax để gửi.

Tạo file data.php để thực hiện truy vấn dữ liệu

File này khá là quan trọng đấy, nó có hai nhiệm vụ là :

  • Import vào file list.php trong div có id  = content.
  • Ajax sẽ gọi đến file này

Nội dung như sau:

<?php

// Bước này dùng để kiểm tra thôi chứ ko có tác dụng gì
// Mục đích là ngưng xử lý 3 giây để mình xem dòng chữ loadding 
// Sau khi test xong bạn xóa đi nhé
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest'){
    sleep(1);
}

// Thiết lập kết quả trả về là html và charset là utf8 để khỏi lỗi font
header('Content-Type: text/html; charset=utf-8');

// Kết nối database
$conn = mysqli_connect('localhost', 'root', 'vertrigo', 'demo') or die ('Không thể kết nối đến CSDL');
mysqli_set_charset($conn, 'utf8');

// Lấy trang hiện tại
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;

// Kiểm tra trang hiện tại có bé hơn 1 hay không
if ($page < 1) {
    $page = 1;
}

// Số record trên một trang
$limit = 3;

// Tìm start
$start = ($limit * $page) - $limit;

// Câu truy vấn
// Trong câu truy vấn này chúng ta sẽ lấy limit tăng lên 1
// Lý do là vì ta không có viết code đếm record nên dựa vào tổng số kết quả trả về để:
// - Nếu kết quả trả về bằng $limit + 1 thì còn phân trang
// - Nếu kết quả trả về bé hơn $limit + 1 thì nghĩa là hết dữ liệu nên ngưng phân trang
$sql = "select * from tb_customer limit $start,".($limit + 1);

// Thực hiện câu truy vấn
$query = mysqli_query($conn, $sql) or die ('Lỗi câu truy vấn');

// Duyệt kết quả rồi đưa vào mảng result
$result = array();
while ($row = mysqli_fetch_array($query))
{
    // Thêm vào result
    array_push($result, $row);
}

// Hiển thị dữ liệu
$total = count($result);
// Bỏ đi kết quả cuối cùng vì kết quả này dùng để check phân trang thôi
// Tuy nhiên chỉ bỏ ở trường hợp ($total > $limit) nếu không ở trang cuối cùng sẽ mất một row
if ($total > $limit){
    for ($i = 0; $i < $total - 1; $i++)
    {
        echo '<div class="item">';
            echo $result[$i]['id'].' - '.$result[$i]['name'].' - '.$result[$i]['website'];
        echo '</div>';
    }
}
else{
    for ($i = 0; $i < $total; $i++)
    {
        echo '<div class="item">';
            echo $result[$i]['id'].' - '.$result[$i]['name'].' - '.$result[$i]['website'];
        echo '</div>';
    }
}

// Nếu hết dữ liệu thì stop không phan trang nữa
// Ta chỉ cần kiểm tra xem tổng số record có nhiều hơn limit hay không
// vì trong câu truy vấn mình select với limit = limit + 1
if ($total <= $limit){
    echo '<script language="javascript">stopped = true; </script>';
}
?>

Trong file này các bạn cần lưu ý các vấn đề như sau:

  • Ở trên cùng mình có sử dụng hàm sleep để ngưng xủ lý 1 giây mục đích là cho dòng chữ loadding được hiển thị ra để test, nếu không nó xử lý nhanh quá chúng ta không thấy.
  • Ở đây ta không cần đếm tổng số record mà sử dụng một mẹo đơn giản đó là lấy dư thêm 1 record, nếu kết quả trả về có số record dư 1 thì nghĩa là còn data, ngược lại hết data.
  • Ở đoạn code dưới cùng mình có check nếu hết data thì xuất một đoạn mã javascript gán biến stopped = true, biến này chính là biên mà ta khai báo toàn cục ở file ajax.js

Như vậy là hết rồi, bạn chạy lên và xem thành quả của mình nhé.

2. Lời kết

Bài này cũng hơi ngắn và mình viết ở dạng jquery thuần chứ không đưa nó vào jquery plugin, nếu bạn rành jquery thì có thể đưa nó vào mọt plugin để sử dụng cho tiện. Hy vọng qua bài jQuery Ajax Scrolliing Pagination sẽ giúp các bạn thực hiện được thao tác phân trang ajax scrolling rất hay này.

Hãy để lại link bài viết gốc khi chia sẻ bài viết này, mình sẽ report DMCA với những website lấy nội dung mà không để nguồn hoặc copy bài với số lượng lớn.

Nguồn: freetuts.net

Profile photo of adminTheHalfHeart

TheHalfHeart

Có sở thích viết tuts nên đã từng tham gia viết ở một số diễn đàn, đến năm 2014 mới có điều kiện sáng lập ra freetuts.net. Sinh năm 90 và có 1 vợ 2 con, thích ca hát và lập trình.

ĐĂNG BÌNH LUẬN: Đăng câu hỏi trên Group Facebook để được hỗ trợ nhanh nhất.