This is default featured slide 1 title

Go to Blogger edit html and find these sentences.Now replace these sentences with your own descriptions.This theme is Bloggerized by Lasantha Bandara - Premiumbloggertemplates.com.

This is default featured slide 2 title

Go to Blogger edit html and find these sentences.Now replace these sentences with your own descriptions.This theme is Bloggerized by Lasantha Bandara - Premiumbloggertemplates.com.

This is default featured slide 3 title

Go to Blogger edit html and find these sentences.Now replace these sentences with your own descriptions.This theme is Bloggerized by Lasantha Bandara - Premiumbloggertemplates.com.

This is default featured slide 4 title

Go to Blogger edit html and find these sentences.Now replace these sentences with your own descriptions.This theme is Bloggerized by Lasantha Bandara - Premiumbloggertemplates.com.

This is default featured slide 5 title

Go to Blogger edit html and find these sentences.Now replace these sentences with your own descriptions.This theme is Bloggerized by Lasantha Bandara - Premiumbloggertemplates.com.

Hiển thị các bài đăng có nhãn jQyery. Hiển thị tất cả bài đăng
Hiển thị các bài đăng có nhãn jQyery. Hiển thị tất cả bài đăng

Thứ Năm, 24 tháng 12, 2015

jQuery Envent

Untitled Document

Trang chủ » Web Development » Javascript - jQuery » Jquery căn bản: Jquery Events
Jquery căn bản: Jquery Events
Cập nhật lần cuối ngày 05/01/2015 trong Javascript - jQuery
Các sự kiện sinh ra để phản ứng lại với tương tác của người dùng với trang web. Chúng ta đã khá quen thuộc với các sự kiện như onclick, onmousedown, onkeydown,…… trong javascript. Jquery tất nhiên cung cấp đầy đủ những sự kiện trong javascript. Không chỉ vậy, với cú pháp xử lý đơn giản, dễ hiểu nó còn làm được nhiều hơn thế.
$(document).ready()
Đây là bộ quản lý sự kiện cơ bản của Jquery. Hiểu đơn giản thì nó cũng là một sự kiện trong jquery, được kích hoạt khi tài liệu html của trang web được load xong và cây DOM được tạo thành.
Ngoài ra, Jquery còn có một bộ quản lý sự kiện khác đó là $(window).load(). Cái này hoàn toàn giống vớiwindow.onload() trong javascript. Window.onload() chỉ được kích hoạt khi toàn bộ tài liệu đã được load xong, bào gồm ảnh, css, object, các frame…. Rõ ràng $(document).ready() có ưu điểm rõ rệt hơn khi thời điểm kích hoạt sự kiện là sớm hơn, đặc biệt khi trang web có dung lượng lớn, chứa nhiều hình ảnh.
Tuy nhiên nếu bạn cần thao tác javascript với các hình ảnh thì sử dụng window.onload() là hợp lý.
Hàm $(document).ready() có thể được gọi nhiều lần, ngoài cách viết này chúng ta có thể viết$().ready(function(){……….}) hoặc $(function(){……..}) đều được.
Ví dụ minh họa
Hãy bắt đầu bằng một sự kiện đơn giản, đó là click:
Code html:


01

<button id="”target”">click here</button>

Code Jquery:


01
02
03
04
05

$(document).ready( function () {
   $('#target').click(function( e ){
      $(“body”).append(“bạn đã click”);
   });
});

Code trên sẽ hoạt động như sau: khi bạn click vào button có id là target thì một đoạn text sẽ được thêm vào cuối thẻ <body>. Hàm function() bên trong chính là eventHandler, có nhiệm vụ xử lý sự kiện click của chúng ta.
Bạn có thể xem kết quả ở đây: http://jsfiddle.net/Nbp4v/
Event Object
Quay lại với ví dụ ở phần minh họa trên, chúng ta thấy hàm eventHandler có một đối số e ở bên trong. Đó là Event Object, bạn có thể đặt một tên bất kỳ cho tham số sự kiện này. Ở đây nó không được sử dụng, tuy nhiên một số trường hợp lại cần thiết để lấy tọa độ con trỏ chuột hoặc ngăn hành vi mặc định của sự kiện,…..
Lấy một ví dụ:
Code jquery:


01
02
03

$(document).click( function ( e ){
        alert ( “pageX is: “+ e.pageX + “pageY is: “ +  e.pageY);
});

Với code trên, khi ta click vào một vị trí bất kỳ trên trang thì một hộp thông báo tọa độ theo trục X và trục Y của con trỏ chuột hiện ra.
Tọa độ theo trục X hiểu là khoảng cách từ con trỏ chuột tới lề trái của trang, còn tọa độ theo trục Y là khoảng cách tới Top của trang.
pageX, pageY là các thuộc tính của event object, ngoài ra còn có các thuộc tính và phương thức khác như:type, target, clientX, clientY, timestamp, preventDefault(), stopPropagation(),…… tùy thuộc vào từng sự kiện cụ thể.
Chú ý:
Bạn cần phân biệt pageY với clientY: clientY sẽ tính khoảng cách từ con trỏ chuột tới Top của cửa sổ trình duyệt còn pageY sẽ lấy khoảng cách từ con trỏ chuột tới Top(vị trí trên cùng) của trang web. Sự khác biệt này thể hiện rõ khi trang web của bạn dài và khi cuộn xuống, rõ ràng là pageY sẽ lớn hơn clientY ở cùng vị trí chuột. Tương tự với pageX và clientX.
preventDefault()
Đây là một phương thức của event Object ở trên. Nó không có tham số, dùng để ngăn chặn hành vi mặc định của sự kiện.
Ví dụ:


01
02
03
04
05
06

<pre>$(document).ready( function(){
   $(window).contextmenu( function( e ){
          //code ở đây
          e.preventDefault();
   });
});

Contextmenu() là sự kiện khi ta click chuột phải trên trang web. Hành vi mặc định của trình duyệt là một menu sẽ hiện ra với lựa chọn như “tải lại”, “mở tab mới”,….. . Tuy nhiên khi sử dụng e.preventDefault() thì không menu nào được hiện ra cả.
Hàm preventDefault() có tác dụng rõ rệt khi ta submit một form và ngăn nó không tự động chuyển trang.
Có thể sử dụng return false trong eventHandler để thay thế cho hàm preventDefault(). Chúng có tác dụng như nhau.
stopPropagation()
Đây cũng là một hàm của event Object. Nó ngăn quá trình nổi bọt của sự kiện trong DOM.
Ví dụ khi gán một sự kiện cho một phần tử. Mặc định các phần tử con của phần tử đó cũng được gán sự kiện. Nhưng khi e.stopPropagation() được gọi trong eventHandler của phần tử con thì nó không bị ảnh hưởng bởi sự kiện của phần tử cha, ông của nó.
Minh họa:
Code html:


01
02
03
04
05

<div id="first"><p>đoạn đầu</p>
    <div id="second"><p>đoạn 2</p>
        <p id="third">đoạn 3</p>
    </div>
</div>

Code jquery:


01
02
03
04
05
06
07
08
09
10
11
12

$(document).ready( function ( e ){
   $("#first").click(function(e) {
        alert("first");
   });
   $("#second").click(function(e) {
        alert("second");
   });
   $("#third").click(function(e) {
       alert("third");
       e.stopPropagation();
   });
});

Kết quả: http://jsfiddle.net/Z6kEN/
Chú ý là hàm này chỉ ngăn chặn được hành vi của sự kiện từ phần tử cha, còn các sự kiện khác trong phần tử đó đang chạy vẫn kích hoạt như thường.
Câu lệnh return false cũng có tác dụng như e.stopPropagation()
Ràng buộc các sự kiện
Đôi khi bạn muốn gắn một xử lý cho nhiều sự kiện khác nhau của một phần tử hoặc gắn xử lý đó cho một sự kiện của nhiều phần tử khác nhau thì làm thế nào? Cách đơn giản là bạn tách biệt chúng ra từng Handler riêng biệt. Tuy nhiên nó không thật thân thiện lắm, Jquery cung cấp các hàm để làm điều đó tốt hơn gọi làEvent Handler Attachment. Một số hàm phổ biến như bind(), delegate(), on(), one(),…..
Ví dụ với bind():


01
02
03
04
05
06
07
08

$ ( "# my-id" ) .bind ({
  click: function () {
    / / code ở đây
  },
  mouseup: function () {
    / / code ở đây
  }
});

Code trên xử lý 2 sự kiện mouseup và click cùng trong một ràng buộc.
Hàm bind() tương thích khá tốt trên các trình duyệt tuy nhiên nhược điểm của nó là eventHandler chỉ có tác dụng với các selector hiện tại trong DOM, các phần tử được thêm vào khớp với selector không bị ảnh hưởng. Hàmdelegate() và on() giúp ta giải quyết điều đó.
Ví dụ với on():


01
02
03

<ul id="comment-list">
        danh sách comment
        <li class="comment">comment 1</li></ul>

Code jquery:


01
02
03
04

$("#comment-list").on("click",".comment", function( e ){
    $(this).append("<li class='comment'>comment</li>");
    e.stopPropagation();
});

Xem kết quả: http://jsfiddle.net/4cuc5/
Với ví dụ trên vì phần tử lắng nghe sự kiện – listener chính là #comment-list các nên thành phần .comment được thêm vào vẫn kích hoạt được sự kiện. Điều này sẽ hoàn toàn khác nếu chúng ta dùng$(“#comment-list .comment”).on(“click”, function(){……}).. vì khi đó listener là các class .comment. Đây là một kỹ thuật được sử dụng nhiều trong AJAX khi mà trang web không load lại khi có phần tử mới thêm vào tài liệu.
Tùy biến sự kiện
Ngoài các sự kiện có sẵn của Jquery, nếu chúng vẫn chưa làm bạn hài lòng, bạn hoàn toàn có thể tạo một sự kiện riêng theo ý mình. Cách làm cũng thật đơn giản.
Đầu tiên định nghĩa một sự kiện mới cho phần tử nào đấy – ví dụ:


01
02
03
04
05

$ ( "# myid" ). on ( "mycustom" , function ( event, param1, param2 ) {

     alert (param1 + " n" + param2);

});

Sau đó cũng phần tử đó , kích hoạt sự kiện vừa tạo bằng hàm trigger() như những sự kiện bình thường khác:
$( "#myid" ).trigger( "mycustom" );
Tất nhiên là trên thực tế bạn cũng nên dùng một sự kiện sẵn có để kích hoạt sự kiện mới nào đó.
Một số loại sự kiện hay gặp

  • Sự kiện chuột: click(), hover(), mouseout(), mousedown(), mouseup(), mouseover()……
  • Sự kiện Form: blur(), focus(), change(), submit(), select(),….
  • Sự kiện bàn phím: là các sự kiện xảy ra khi ta nhấn một phím hay tổ hợp phím nào đó:keydown((), keyup(), keypress(),…..
  • Sự kiện trình duyệt: được kích hoạt khi ta tương tác với cửa sổ trình duyệt như scroll()– cuộn trang, hayresize() – kích thước cửa sổ thay đổi.

Lời kết
Trong phần này mình đã nói qua rất đầy đủ về Sự kiện (Event) trong jQuery và đó cũng là mấu chốt chìa khóa nếu bạn muốn tùy biến jQuery để thực hiện các công việc tạo hiệu ứng như ý muốn, kể cả nó không khó để sử dụng.
Nếu bạn cần góp ý hay thắc mắc gì về phần này, mình rất vui để xem nó ở phần bình luận.

Thứ Tư, 23 tháng 12, 2015

tabs in jQuery

Untitled Document

Bài 02: Tạo Tabs bằng jQuery
 0 
 Google +0 

  0
Đăng bởi: TheHalfHeart - Vào ngày: 07-11-2015 - Chuyên mục: jQuery - View: 476
Tiếp tục thực hành jQuery nào.
Trong bài này chúng ta sẽ xây dựng tabs bằng cách sử dụng CSS để xây dựng layout và jQuery để xây dựng hiệu ứng chuyển tab. Quy trình chúng ta thực hiện hai phần CSS và JS nhé.


1. Tạo giao diện tab bằng HTML và CSS

Chúng ta xây dựng HTML và CSS như sau:
HTML:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

<div class="tab-wrapper">
    <ul class="tab">
        <li>
            <a href="#tab-main-info">Thông tin chính</a>
        </li>
        <li>
            <a href="#tab-image">Hình ảnh</a>
        </li>
        <li>
            <a href="#tab-seo">SEO</a>
        </li>
    </ul>
    <div class="tab-content">
        <div class="tab-item" id="tab-main-info">
            Tab thông tin chinh
        </div>
        <div class="tab-item" id="tab-image">
            Tab hình ảnh
        </div>
        <div class="tab-item" id="tab-seo">
            Tab SEO
        </div>
    </div>
</div>

CSS:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

.tab-wrapper{
    width: 500px;
    margin: 50px auto;
    border: solid 1px #acacac;
}
.tab-wrapper ul{
    overflow: hidden;
    background: #aee655;
    margin: 0px;
    padding: 0px;
}
.tab-wrapper ul li{
    float: left;
    list-style: none;
    padding: 10px 20px;
    background: #348ec9;
    border-radius: 10px 10px 0px 0px;
    margin-right: 5px;
    margin-top: 5px;
}
.tab-wrapper ul li.active{
    background: #Fff;
}
.tab-wrapper ul li.active a{
    color: blue;
}
.tab-wrapper ul li a{
    color: #fff;
    text-transform: uppercase;
    text-decoration: none;
}
.tab-content{
    padding: 20px;
}
.tab-item{
    display: none;
}

Giao diện:
http://freetuts.net/upload/tut_post/images/2015/11/07/503/tao-tab-bang-jquery-1.png
Bạn có thể XEM DEMO.


2. Viết jQuery hiệu ứng chuyển tab

Trước tiên ta cùng phân tích ý tưởng chuyển tab.
Bạn hãy nhìn vào phần HTML thuộc tính href của các tab có giá trị dạng href="#tab-main-info", và phần nội dung tương ứng với tab đó sẽ có id="tab-main-info". Như vậy khi người dùng click vào tab thì ta sẽ biết được nên hiển thị nội dung nào.
http://freetuts.net/upload/tut_post/images/2015/11/07/503/tao-tab-bang-jquery-2.png
Trước tiên ta viết một hàm acitveTab với tham số truyền vào là thẻ li cần active.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

// Hàm active tab nào đó
function activeTab(obj)
{
    // Xóa class active tất cả các tab
    $('.tab-wrapper ul li').removeClass('active');

    // Thêm class active vòa tab đang click
    $(obj).addClass('active');

    // Lấy href của tab để show content tương ứng
    var id = $(obj).find('a').attr('href');

    // Ẩn hết nội dung các tab đang hiển thị
    $('.tab-item').hide();

    // Hiển thị nội dung của tab hiện tại
    $(id) .show();
}

Bây giờ ta gọi hàm này trong sự kiện click vào thẻ li của các tab.


1
2
3
4
5

// Sự kiện click đổi tab
$('.tab li').click(function(){
    activeTab(this);
    return false;
});

Chưa xong, chúng ta cần xử lý khi website được chạy lần đầu tiên thì tab thứ nhất sẽ được active, code như sau:


1
2

// Active tab đầu tiên khi trang web được chạy
activeTab($('.tab li:first-child'));

Và đây chính là toàn bộ code jQuery xử lý chuyển tab.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

$(document).ready(function()
{
    // Hàm active tab nào đó
    function activeTab(obj)
    {
        // Xóa class active tất cả các tab
        $('.tab-wrapper ul li').removeClass('active');

        // Thêm class active vòa tab đang click
        $(obj).addClass('active');

        // Lấy href của tab để show content tương ứng
        var id = $(obj).find('a').attr('href');

        // Ẩn hết nội dung các tab đang hiển thị
        $('.tab-item').hide();

        // Hiển thị nội dung của tab hiện tại
        $(id) .show();
    }

    // Sự kiện click đổi tab
    $('.tab li').click(function(){
        activeTab(this);
        return false;
    });

    // Active tab đầu tiên khi trang web được chạy
    activeTab($('.tab li:first-child'));
});

Chạy lên giao diện sẽ như sau (bạn có thể click vào để chuyển tab):
Bạn có thể XEM DEMO để xem toàn bộ code.


3. Lời kết

Qua bài tập tạo tab bằng jQuery này giúp bạn hiểu được một thủ thuật đơn giản để chuyển tab, đồng thời giúp bạn có thêm một kỹ năng mới trong việc phân tích HTML cho từng chức năng.
Bài này tương đối đơn giản nhưng cũng không phải là dễ với những bạn mới học. Hy vọng sẽ giúp được những bạn đang muốn tìm hiểu jQuery.

form in jQuery

Untitled Document

Bài 01: Validate form bằng jQuery
 0 
 Google +0 

  0
Đăng bởi: TheHalfHeart - Vào ngày: 06-11-2015 - Chuyên mục: jQuery - View: 429
Trong bài này chúng ta sẽ học jQuery qua bài tập validate form đơn giản, bài tập này giúp bạn làm quen với phương thức $('selector).val() và biết được cách sử dụng jQuery để thay thế Javascript.
Chúng ta sẽ làm bài tập validate form đăng ký thành viên.


1. Tạo form đăng ký đơn giản

Cách đơn giản nhất để thao tác với các đối tượng HTML là bạn sử dụng ID, vì vậy mình sẽ đặt ID cho từng thẻ input và cho cả thẻ form.
Đây là form HTML của chúng ta: XEM DEMO


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70

<!DOCTYPE html>
<html>
    <head>
        <title>jQuery Examples</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <script src="http://freetuts.net/public/javascript/jquery.min.js" ></script>
        <script language="javascript">
            $(document).ready(function(){
                $('#form_register').submit(function(){
                     
                    // Code validate form
                     
                });
            });
        </script>
    </head>
    <body>
        <form method="post" action="" id="form_register">
            <table border="1" cellspacing="0" cellpadding="5">
                <tr>
                    <td>Tên đăng nhập</td>
                    <td>
                        <input type="text" name="username" id="username" value="" />
                        <span id="username_error"></span>
                    </td>
                </tr>
                <tr>
                    <td>Mật khẩu:</td>
                    <td>
                        <input type="password" name="password" id="password" value="" />
                        <span id="password_error"></span>
                    </td>
                </tr>
                <tr>
                    <td>Nhập lại mật khẩu:</td>
                    <td>
                        <input type="password" name="re-password" id="re_password" value="" />
                        <span id="re_password_error"></span>
                    </td>
                </tr>
                <tr>
                    <td>Email:</td>
                    <td>
                        <input type="text" name="email" id="email" value="" />
                        <span id="email_error"></span>
                    </td>
                </tr>
                <tr>
                    <td>Điện thoại:</td>
                    <td>
                        <input type="text" name="phone" id="phone" value="" />
                        <span id="phone_error"></span>
                    </td>
                </tr>
                <tr>
                    <td>Địa chỉ:</td>
                    <td>
                        <input type="text" name="address" id="address" value=""  />
                        <span id="address_error"></span>
                    </td>
                </tr>
                <tr>
                    <td></td>
                    <td><input type="submit" name="register" id="register" value="Đăng ký" /></td>
                </tr>
            </table>
        </form>
    </body>
</html>

Giao diện:
http://freetuts.net/upload/tut_post/images/2015/11/06/502/jquery-example-jquery-1.png
Mỗi thẻ input mình có kèm theo một thẻ span bên dưới để xuất hiện lỗi.


2. Validate form bằng jQuery

Mỗi sự kiện trong Javascript nói chung và jQuery nói riêng sẽ return về TRUE hoặc FALSE. Nếu TRUE thì sự kiện đó sẽ được chạy và ngược lại nếu FALSE thì sự kiện đó không được chạy. Như vậy trong sự kiện submit form ta sẽ kiểm tra điều kiện nếu mọi thứ OK thì ta sẽ return TRUE, ngược lại nếu có lỗi thì ta sẽ return FALSE.
Để lấy giá trị của input thì ta sử dụng cú pháp sau: $('#input_id').val();. Lưu ý là ta sử dụng hàm $.trim() để xóa khoảng trắng hai đầu.
Để hiển thị lỗi cho ô input nào thì ta sẽ thêm thông báo vào thẻ span tương ướng. Ví dụ để hiển thị lỗi cho ô tên đăng nhập thì ta sẽ sử dụng cú pháp sau: 


1

$('#username_error').text('Bạn chưa nhập tên đăng nhập');

Ta sử dụng biến flag làm cờ hiệu để biết được dữ liệu có bị lỗi hay không.
Để các bạn newbie dễ hiểu thì mình sẽ validate với những điều kiện đơn giản thôi nhé vì mục đích là giúp bạn hiểu cách sử dụng jQuery để validate form:

  • Tên đăng nhập phải lớn hơn 4 ký tự
  • Mật khẩu không được trống
  • Mật khẩu nhập lại phải giống mật khẩu ở trên
  • Email không được trống và phải đúng định dạng.

Trong bài có sử dụng hàm kiểm tra định dạng email trong bài các hàm javascript validate dữ liệu nên bạn hãy đến bài đó tham khảo nhé.
Hàm kiểm tra định dạng Email:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

function isEmail(emailStr)
{
        var emailPat=/^(.+)@(.+)$/
        var specialChars="\\(\\)<>@,;:\\\\\\\"\\.\\[\\]"
        var validChars="\[^\\s" + specialChars + "\]"
        var quotedUser="(\"[^\"]*\")"
        var ipDomainPat=/^\[(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\]$/
        var atom=validChars + '+'
        var word="(" + atom + "|" + quotedUser + ")"
        var userPat=new RegExp("^" + word + "(\\." + word + ")*$")
        var domainPat=new RegExp("^" + atom + "(\\." + atom +")*$")
        var matchArray=emailStr.match(emailPat)
        if (matchArray==null) {
                return false
        }
        var user=matchArray[1]
        var domain=matchArray[2]

        // See if "user" is valid
        if (user.match(userPat)==null) {
            return false
        }
        var IPArray=domain.match(ipDomainPat)
        if (IPArray!=null) {
            // this is an IP address
                  for (var i=1;i<=4;i++) {
                    if (IPArray[i]>255) {
                        return false
                    }
            }
            return true
        }
        var domainArray=domain.match(domainPat)
        if (domainArray==null) {
            return false
        }

        var atomPat=new RegExp(atom,"g")
        var domArr=domain.match(atomPat)
        var len=domArr.length

        if (domArr[domArr.length-1].length<2 ||
            domArr[domArr.length-1].length>3) {
           return false
        }

        if (len<2)
        {
           return false
        }

        return true;
}

Bây giờ là đoạn code validate form của chúng ta:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

$(document).ready(function()
{
    $('#form_register').submit(function(){

        // BƯỚC 1: Lấy dữ liệu từ form
        var username    = $.trim($('#username').val());
        var password    = $.trim($('#password').val());
        var re_password = $.trim($('#re_password').val());
        var email       = $.trim($('#email').val());
        var phone       = $.trim($('#phone').val());
        var address     = $.trim($('#address').val());

        // BƯỚC 2: Validate dữ liệu
        // Biến cờ hiệu
        var flag = true;

        // Username
        if (username == '' || username.length < 4){
            $('#username_error').text('Tên đăng nhập phải lớn hơn 4 ký tự');
            flag = false;
        }
        else{
            $('#username_error').text('');
        }

        // Password
        if (password.length <= 0){
            $('#password_error').text('Bạn phải nhập mật khẩu');
            flag = false;
        }
        else{
            $('#password_error').text('');
        }

        // Re password
        if (password != re_password){
            $('#re_password_error').text('Mật khẩu nhập lại không đúng');
            flag = false;
        }
        else{
            $('#re_password_error').text('');
        }

        // Email
        if (!isEmail(email)){
            $('#email_error').text('Email không được để trống và phải đúng định dạng');
            flag = false;
        }
        else{
            $('#email_error').text('');
        }

        return flag;
    });
});

Các bạn có thểm XEM DEMO để hiểu rõ hơn.


3. Lời kết

Bài tập này rất đơn giản nên phù hợp với bạn đang học jQuery. Nếu bạn nào cảm thấy nó dễ và cách làm không hay thì mình xin giải thích rằng mỗi người có những cách code khác nhau và tùy vào từng bài toán khác nhau mà có những hướng giải khác nhau.

jQuery 12

Untitled Document

Bài 12: Search ajax autocomplete có phân trang
 0 
 Google +0 

  0
Đăng bởi: TheHalfHeart - Vào ngày: 25-08-2014 - Chuyên mục: jQuery - View: 4580
Download
Đây là bài thứ 12 trong loạt serie ajax toàn tập. Nếu như bạn đã đọc đến bài này thì tôi tin rằng bạn đã nắm vững được ajax jquery rồi, nên để nâng cao hơn xíu hôm nay tôi sẽ hướng dẫn làm chức năng search autocomplete ajax có phân trang.
Search autocomplete là gì? Nếu bạn chưa biết nó là gì thì tôi xin trích dẫn thế này, chắc hẳn bạn đã từng vào một số website có chức năng search và khi bạn nhập nội dung vào nó tự động lấy nội dung và hiển thị cho bạn mà không cần phải reload trang. Đây là chức năng rất thân thiện với người dùng nên nếu áp dụng vào website thì tuyệt cú mèo. 
Kết quả của bài này ta có form như hình sau:
search autocomplete


1. Xây dựng database

Trước tiên bạn cần tạo một database tên test và chạy nội dung sql bên dưới để tạo bảng và thêm một số data.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";

CREATE TABLE IF NOT EXISTS `member` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `username` varchar(30) DEFAULT NULL,
  `email` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=30 ;

INSERT INTO `member` (`id`, `username`, `email`) VALUES
(1, 'thehalfheart', 'thehalfheart@gmail.com'),
(2, 'freetuts', 'freetuts.net@gmail.com'),
(3, 'kingston', 'kingston@gmail.com'),
(4, 'cafeviet', 'cafeviet@gmail.com'),
(5, 'emailer', 'emailer@gmail.com'),
(6, 'domain', 'domain@gmail.com'),
(7, 'root', 'root@gmail.com'),
(8, 'admin', 'admin@gmail.com'),
(9, 'supper', 'supper@gmail.com'),
(10, 'hoconline', 'hoconline@gmail.com'),
(11, 'codon', 'codon@gmail.com'),
(12, 'thesky', 'thesky@gmail.com'),
(13, 'khoanguyen', 'khoanguyen@gmail.com'),
(14, 'trinhut', 'trinhut@gmail.com'),
(15, 'sanhot', 'sanhot@gmail.com'),
(16, 'nammoitetden', 'nammoitetden@gmail.com'),
(17, 'nhatkydoitoi', 'nhatkydoitoi@gmail.com'),
(18, 'freetutsonline', 'freetutsonline@gmail.com'),
(19, 'sinhthoi', 'sinhthoi@gmail.com'),
(20, 'xatoiradioco', 'xatoiradioco@gmail.com'),
(21, 'emailaothu1', 'emailaothu1@gmail.com'),
(22, 'emailaothu2', 'emailaothu2@gmail.com'),
(23, 'emailaothu3', 'emailaothu3@gmail.com'),
(24, 'emailaothu4', 'emailaothu4@gmail.com'),
(25, 'emailaothu5', 'emailaothu5@gmail.com'),
(26, 'emailaothu6', 'emailaothu6@gmail.com'),
(27, 'emailaothu7', 'emailaothu7@gmail.com'),
(28, 'emailaothu8', 'emailaothu8@gmail.com'),
(29, 'emailaothu9', 'emailaothu9@gmail.com');

2. Xây dựng thư viện phân trang

Vì trong bài search autocomplete ajax này tôi có phân trang nên bắt buộc phải xây dựng lớp phân trang rồi :D. Bạn tạo file pagination.phpvà copy nội dung bên dưới vào:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108

class Pagination {

    protected $_config = array(
        'current_page'  => 1, // Trang hiện tại
        'total_record'  => 1, // Tổng số record
        'total_page'    => 1, // Tổng số trang
        'limit'         => 10, // limit
        'start'         => 0, // start
        'link_full'     => '', // Link full có dạng như sau: domain/com/page/{page}
        'link_first'    => '', // Link trang đầu tiên
        'range'         => 9, // Số button trang bạn muốn hiển thị
        'min'           => 0, // Tham số min
        'max'           => 0  // tham số max, min và max là 2 tham số private
    );
     
    function init($config = array())
    {
        foreach ($config as $key => $val) {
            if (isset($this->_config[$key])) {
                $this->_config[$key] = $val;
            }
        }
         
        if ($this->_config['limit'] < 0) {
            $this->_config['limit'] = 0;
        }

        $this->_config['total_page'] = ceil($this->_config['total_record'] / $this->_config['limit']);

        if (!$this->_config['total_page']) {
            $this->_config['total_page'] = 1;
        }

        if ($this->_config['current_page'] < 1) {
            $this->_config['current_page'] = 1;
        }

        if ($this->_config['current_page'] > $this->_config['total_page']) {
            $this->_config['current_page'] = $this->_config['total_page'];
        }

        $this->_config['start'] = ($this->_config['current_page'] - 1) * $this->_config['limit'];

        $middle = ceil($this->_config['range'] / 2);

        if ($this->_config['total_page'] < $this->_config['range']) {
            $this->_config['min'] = 1;
            $this->_config['max'] = $this->_config['total_page'];
        }
        else {
            $this->_config['min'] = $this->_config['current_page'] - $middle + 1;

            $this->_config['max'] = $this->_config['current_page'] + $middle - 1;

            if ($this->_config['min'] < 1) {
                $this->_config['min'] = 1;
                $this->_config['max'] = $this->_config['range'];
            }

            else if ($this->_config['max'] > $this->_config['total_page']) {
                $this->_config['max'] = $this->_config['total_page'];
                $this->_config['min'] = $this->_config['total_page'] - $this->_config['range'] + 1;
            }
        }
    }
     
    function get_config($key){
        return $this->_config[$key];
    }
     
    private function __link($page) {
        if ($page <= 1 && $this->_config['link_first']) {
            return $this->_config['link_first'];
        }
        return str_replace('{page}', $page, $this->_config['link_full']);
    }

    function html() {
        $p = '';
        if ($this->_config['total_record'] > $this->_config['limit']) {
            $p = '<ul>';

            // Nút prev và first
            if ($this->_config['current_page'] > 1) {
                $p .= '<li><a href="' . $this->__link('1') . '" title="1">First</a></li>';
                $p .= '<li><a href="' . $this->__link($this->_config['current_page'] - 1) . '" title="'.($this->_config['current_page'] - 1).'">Prev</a></li>';
            }

            // lặp trong khoảng cách giữa min và max để hiển thị các nút
            for ($i = $this->_config['min']; $i <= $this->_config['max']; $i++) {
                // Trang hiện tại
                if ($this->_config['current_page'] == $i) {
                    $p .= '<li><span>' . $i . '</span></li>';
                } else {
                    $p .= '<li><a href="' . $this->__link($i) . '" title="'.$i.'">' . $i . '</a></li>';
                }
            }

            // Nút last và next
            if ($this->_config['current_page'] < $this->_config['total_page']) {
                $p .= '<li><a href="' . $this->__link($this->_config['current_page'] + 1) . '" title="'.($this->_config['current_page'] + 1).'">Next</a></li>';
                $p .= '<li><a href="' . $this->__link($this->_config['total_page']) . '" title="'.$this->_config['total_page'].'">Last</a></li>';
            }
            $p .= '</ul>';
        }
        return $p;
    }
}

Nếu bạn chưa biết cách viết thư viện phân trang thì có thể tham khảo hai bài sau:

3. Xây dựng model xử lý database

Để cho tiện lợi trong quá trình xử lý database để search autocomplete thì tôi sẽ xây dựng một file chuyên dùng để lấy danh sách và truy vấn theo tham số search truyền vào. Bạn tạo file database.php và copy nội dung bên dưới vào.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61

// Khai báo biến toàn cục kết nối
global $conn;

// Hàm kết nối database
function connect(){
    global $conn;
    $conn = mysqli_connect('localhost', 'root', 'vertrigo', 'test') or die ('{error:"bad_request"}');
}

// Hàm đóng kết nối
function disconnect(){
    global $conn;
    if ($conn){
        mysqli_close($conn);
    }
}

// Hàm đếm tổng số thành viên
function count_all_member($username = '')
{
    global $conn;
     
    if ($username){
        $query = mysqli_query($conn, 'select count(*) as total from member where username like \'%'.mysql_escape_string($username).'%\'');
    }
    else{
        $query = mysqli_query($conn, 'select count(*) as total from member');
    }
     
    if ($query){
        $row = mysqli_fetch_array($query, MYSQLI_ASSOC);
        return $row['total'];
    }
    return 0;
}

// Lấy danh sách thành viên
function get_all_member($username = '', $limit = 10, $start = 0)
{
    global $conn;
     
    if ($username){
        $sql = 'select * from member  where username like \'%'.mysql_escape_string($username).'%\' limit '.(int)$start . ','.(int)$limit;
    }
    else{
        $sql = 'select * from member limit '.(int)$start . ','.(int)$limit;
    }
     
    $query = mysqli_query($conn, $sql);
      
    $result = array();
      
    if ($query)
    {
        while ($row = mysqli_fetch_array($query, MYSQLI_ASSOC)){
            $result[] = $row;
        }
    }
      
    return $result;
}

Trong file tôi đã comment rất kỹ rồi nên ko giải thích gì thêm


4. Xây dựng hàm lấy danh sách search autocomplete và trả về chuỗi JSON

Bạn tạo file get_data.php và copy nội dung sau:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

// Require Lib
require "database.php";
require "pagination.php";

// Lấy thong tin lọc
$username = isset($_GET['username']) ? $_GET['username'] : '';

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

// Khởi tạo đối tượng Pagination mới
$pagination = new Pagination();

// Kết nối db
connect();

// Cấu hình thông số phân trang
$pagination->init(array(
    'current_page'  => $page,
    'total_record'  => count_all_member($username),
    'link_full'     => 'get_data.php?page={page}&username='.$username,
    'link_first'    => 'get_data.php'
));

// Lấy limit và Start
$limit = $pagination->get_config('limit');
$start = $pagination->get_config('start');

// Lấy danh sách người dùng
$data = get_all_member($username, $limit, $start);

// Ngắt kết nối
disconnect();

// Trả kết quả cho client
die (json_encode(array(
    'data' => $data,
    'paging' => $pagination->html()
)));

Các bạn lưu ý là tôi trả về kết quả là chuỗi JSON nên ở file xử lý ajax ta phải truyền dataType là JSON nhé.


5. Xây dựng trang hiển thị danh sách và search autocomplete

Bạn tạo file index.php và copy nội dung sau:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82

<!DOCTYPE html>
<html>
    <head>
        <title>Tìm kiếm theo ajax</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <script language="javascript" src="http://code.jquery.com/jquery-2.0.0.min.js"></script>
        <style>
            html{width:900px; margin:0px auto}
            input{padding: 5px}
            li{float:left; margin: 3px; border: solid 1px gray;}
            a{padding: 5px;}
            span{display:inline-block; padding: 0px 3px; background: blue; color:white}
            li{list-style: none; padding: 0px 5px}
        </style>
        <script language="javascript">
            $(document).ready(function()
            {
                // Biến lưu trữ thông số tìm kiếm
                var data = {
                    username : '', // tên đăng nhập
                    page : 1 // trang cần đến, dùng trong trường hợp có phân trang
                };
                 
                // Khi nhập dữ liệu thì gọi ajax
                $('#q').keyup(function(){  
                    data.username = $(this).val();
                    search();
                });
                 
                // Hàm xử lý khi click vào phân trang
                $('#content').on('click', 'a', function (){
                   data.page = $(this).attr('title');
                   search();
                   return false;
                });
                 
                // Hàm gửi ajax
                function search()
                {
                    $.ajax({
                        url : 'get_data.php',
                        data : data,
                        type : 'get',
                        dataType : 'json',
                        success : function (result)
                        {
                            // Nếu dữ liệu trả về đúng thì mới xử lý
                            if (result.hasOwnProperty('data') && result.hasOwnProperty('paging'))
                            {
                                var html = '<table border="1" cellspacing="0" cellpadding="5">';
                                    html += '<tr style="font-weight:bold">';
                                        html += '<td>Username</td>';
                                        html += '<td>Email</td>';
                                    html += '</tr>';
                                     
                                    // Lặp qua từng record và gán html
                                    $.each(result['data'], function (index, item){
                                        html += '<tr>';
                                            html += '<td>'+item.username+'</td>';
                                            html += '<td>'+item.email+'</td>';
                                        html += '</tr>';
                                    });

                                html += '</table>';
                                 
                                // Thêm html paging
                                html += result['paging'];
                                 
                                // Gán kết quả vào div#content
                                $('#content').html(html);
                            }
                        }
                    });
                }
            });
        </script>
    </head>
    <body>
        <input type="text" id="q" value="" placeholder="Nhập nội dung muốn tìm kiếm" size="50"/>
        <div id="content" style="margin-top: 20px;"></div>
    </body>
</html>

Trong file này thẻ div#content dùng để gán data vào, và tôi đã sử dụng hàm html() jquery để gán.
Trong đoạn ajax tôi có định nghĩa một hàm search dùng để gửi ajax và tôi cũng có gán 2 sự kiện khi keyUp vào ô search và khi click vào phân trang. Trong phần comment tôi đã trình bày rõ ràng rồi nên tôi cũng ko nói gì thêm nữa nhé.


6. Lời kết

Trong bài này quan trọng nhất là đoạn code xử lý jquery ajax search autocomplete, các bạn cố gắng gõ và làm theo nhé, copy nhưng cũng phải hiểu thì mới học tốt được. Còn một vấn đề tôi không trình bày, đó là khi ta nhập từ search nó gửi rất nhiều request, mỗi ký tự một request nên không được hay lắm, để giải quyết vấn đề này ta sẽ xây dựng hệ thống timer, nghĩa là khi người dùng dừng không gõ chừng 0.5 giây ta mới gửi, như vậy sẽ giảm được số request gửi lên server. Vấn đề này ta sẽ học ở bài tiếp they delay keyup event.

jQuery 9

Untitled Document

Bài 09: Phân trang ajax có thay đổi URL cho SEO
 0 
 Google +0 

  0
Đăng bởi: TheHalfHeart - Vào ngày: 12-08-2014 - Chuyên mục: jQuery - View: 3555
Download
Như bạn biết thường thì khi ta làm việc với ajax sẽ bị hạn chế với Search Engine, nhưng với công nghệ hiện nay thì có một kỹ thuật nho nhỏ giúp ta sử dụng ajax mà vẫn chạy được cho SEO, và đây cũng là lý do tôi mở ra bài này.
Trong bài nay tôi sẽ làm một ví dụ nhỏ nhỏ về phân trang ajax có thay đổi URL, trong bài tôi có sử dụng thư viện phân trang của bài "Thuật toán phân trang" nên nếu bạn chưa biết thuật toán phân trang thì quay lại và đọc bài đó nhé.


1. Tạo cơ sở dữ liệu

Bạn tạo một database mới tên là test và chạy đoạn code câu truy vấn sau:


CREATE TABLE IF NOT EXISTS `member` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(30) DEFAULT NULL,
`email` varchar(255) DEFAULT NULL,
`fullname` varchar(255) DEFAULT NULL,
`phone` varchar(30) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=10 ;

--
-- Contenu de la table `member`
--

INSERT INTO `member` (`id`, `username`, `email`, `fullname`, `phone`) VALUES
(1, 'thehalfheart', 'thehalfheart@gmail.com', 'Nguyen B', '1234567890'),
(2, 'freetuts', 'freetuts.net@gmail.com', 'Nguyen A', '5245234534'),
(3, 'kingston', 'kingston@gmail.com', 'Nguyen C', '4234234343'),
(4, 'cafeviet', 'cafeviet@gmail.com', 'Nguyen D', '4234324344'),
(5, 'emailer', 'emailer@gmail.com', 'Nguyen E', '4354354656'),
(6, 'domain', 'domain@gmail.com', 'Nguyen F', '4324234343'),
(7, 'root', 'root@gmail.com', 'Nguyen G', '4343253543'),
(8, 'admin', 'admin@gmail.com', 'Nguyen H', '5465465767'),
(9, 'supper', 'supper@gmail.com', 'Nguyen I', '3442342323');

2. Viết thư viện phân trang

Bạn tạo một trang pagination.php với nội dung như sau:


class Pagination
{
protected $_config = array(
'current_page'  => 1, // Trang hiện tại
'total_record'  => 1, // Tổng số record
'total_page'    => 1, // Tổng số trang
'limit'         => 10,// limit
'start'         => 0, // start
'link_full'     => '',// Link full có dạng như sau: domain/com/page/{page}
'link_first'    => '',// Link trang đầu tiên
'range'         => 9, // Số button trang bạn muốn hiển thị
'min'           => 0, // Tham số min
'max'           => 0  // tham số max, min và max là 2 tham số private
);

function get_config($key){
return $this->_config[$key];
}

/*
* Hàm khởi tạo ban đầu để sử dụng phân trang
*/
function init($config = array())
{
/*
* Lặp qua từng phần tử config truyền vào và gán vào config của đối tượng
* trước khi gán vào thì phải kiểm tra thông số config truyền vào có nằm
* trong hệ thống config không, nếu có thì mới gán
*/
foreach ($config as $key => $val){
if (isset($this->_config[$key])){
$this->_config[$key] = $val;
}
}

/*
* Kiểm tra thông số limit truyền vào có nhỏ hơn 0 hay không?
* Nếu nhỏ hơn thì gán cho limit = 0, vì trong mysql không cho limit bé hơn 0
*/
if ($this->_config['limit'] < 0){
$this->_config['limit'] = 0;
}

/*
* Tính total page, công tức tính tổng số trang như sau:
* total_page = ciel(total_record/limit).
* Tại sao lại như vậy? Đây là công thức tính trung bình thôi, ví
* dụ tôi có 1000 record và tôi muốn mỗi trang là 100 record thì
* đương nhiên sẽ lấy 1000/100 = 10 trang đúng không nào :D
*/
$this->_config['total_page'] = ceil($this->_config['total_record'] / $this->_config['limit']);

/*
* Sau khi có tổng số trang ta kiểm tra xem nó có nhỏ hơn 0 hay không
* nếu nhỏ hơn 0 thì gán nó băng 1 ngay. Vì mặc định tổng số trang luôn bằng 1
*/
if (!$this->_config['total_page']){
$this->_config['total_page'] = 1;
}

/*
* Trang hiện tại sẽ rơi vào một trong các trường hợp sau:
*  - Nếu người dùng truyền vào số trang nhỏ hơn 1 thì ta sẽ gán nó = 1
*  - Nếu trang hiện tại người dùng truyền vào lớn hơn tổng số trang
*    thì ta gán nó bằng tổng số trang
* Đây là vấn đề giúp web chạy trơn tru hơn, vì đôi khi người dùng cố ý
* thay đổi tham số trên url nhằm kiểm tra lỗi web của chúng ta
*/
if ($this->_config['current_page'] < 1){
$this->_config['current_page'] = 1;
}

if ($this->_config['current_page'] > $this->_config['total_page']){
$this->_config['current_page'] = $this->_config['total_page'];
}

/*
* Tính start, Như bạn biết trong mysql truy vấn sẽ có limit và start
* Muốn tính start ta phải dựa vào số trang hiện tại và số limit trên mỗi trang
* và áp dụng công tức start = (current_page - 1)*limit
*/
$this->_config['start'] = ($this->_config['current_page'] - 1) * $this->_config['limit'];

/*
* Bây giờ ta tính số trang ta show ra trang web
* Như bạn biết với những website có data lớn thì số trang có thể
* lên tới hàng trăm trang, chẵng nhẽ ta show hết cả 100 trang?
* Nên trong bài này tôi hướng dẫn bạn show trong một khoảng nào đó (range)
* giống website freetuts.net vậy
*/

// Trước tiên tính middle, đây chính là số nằm giữa trong khoảng tổng số trang
// mà bạn muốn hiển thị ra màn hình
$middle = ceil($this->_config['range'] / 2);

        // Ta sẽ lâm vào các trường hợp như bên dưới
// Trong trường hợp này thì nếu tổng số trang mà bé hơn range
// thì ta show hết luôn, không cần tính toán làm gì
// tức là gán min = 1 và max = tổng số trang luôn
if ($this->_config['total_page'] < $this->_config['range']){
$this->_config['min'] = 1;
$this->_config['max'] = $this->_config['total_page'];
}
// Trường hợp tổng số trang mà lớn hơn range
else
{
// Ta sẽ gán min = current_page - (middle + 1)
$this->_config['min'] = $this->_config['current_page'] - $middle + 1;

// Ta sẽ gán max = current_page + (middle - 1)
$this->_config['max'] = $this->_config['current_page'] + $middle - 1;

// Sau khi tính min và max ta sẽ kiểm tra
// nếu min < 1 thì ta sẽ gán min = 1  và max bằng luôn range
if ($this->_config['min'] < 1){
$this->_config['min'] = 1;
$this->_config['max'] = $this->_config['range'];
}

// Ngược lại nếu min > tổng số trang
// ta gán max = tổng số trang và min = (tổng số trang - range) + 1
else if ($this->_config['max'] > $this->_config['total_page'])
{
$this->_config['max'] = $this->_config['total_page'];
$this->_config['min'] = $this->_config['total_page'] - $this->_config['range'] + 1;
}
}
}

/*
* Hàm lấy link theo trang
*/
private function __link($page)
{
// Nếu trang < 1 thì ta sẽ lấy link first
if ($page <= 1 && $this->_config['link_first']){
return $this->_config['link_first'];
}
// Ngược lại ta lấy link_full
// Như tôi comment ở trên, link full có dạng domain.com/page/{page}.
// Trong đó {page} là nơi bạn muốn số trang sẽ thay thế vào
return str_replace('{page}', $page, $this->_config['link_full']);
}

/*
* Hàm lấy mã html
* Hàm này ban tạo giống theo giao diện của bạn
* tôi không có config nhiều vì rất rối
* Bạn thay đổi theo giao diện của bạn nhé
*/
function html()
{  
$p = '';
if ($this->_config['total_record'] > $this->_config['limit'])
{
$p = '<ul>';

// Nút prev và first
if ($this->_config['current_page'] > 1)
{
$p .= '<li><a href="'.$this->__link('1').'">First</a></li>';
$p .= '<li><a href="'.$this->__link($this->_config['current_page']-1).'">Prev</a></li>';
}

// lặp trong khoảng cách giữa min và max để hiển thị các nút
for ($i = $this->_config['min']; $i <= $this->_config['max']; $i++)
{
// Trang hiện tại
if ($this->_config['current_page'] == $i){
$p .= '<li><span>'.$i.'</span></li>';
}
else{
$p .= '<li><a href="'.$this->__link($i).'">'.$i.'</a></li>';
}
}

            // Nút last và next
if ($this->_config['current_page'] < $this->_config['total_page'])
{
$p .= '<li><a href="'.$this->__link($this->_config['current_page'] + 1).'">Next</a></li>';
$p .= '<li><a href="'.$this->__link($this->_config['total_page']).'">Last</a></li>';
}

$p .= '</ul>';
}
return $p;
}
}

Đây là thư viện mà tôi đã đề cập ở trên nên bạn hãy quay lại và xem bài đó để rõ hơn nhé.

3. Viết thư viện xử lý database

Trong phần này tôi sẽ viết một thư viện xử lý danh sách thành viên gồm 4 hàm chính, đó là hàm kết nối, ngắt kết nối, hàm lấy danh sách, hàm lấy tổng số record.
Bạn tạo file database.php với nọi dung như sau:


// Khai báo biến toàn cục kết nối
global $conn;

// Hàm kết nối database
function connect(){
global $conn;
$conn = mysqli_connect('localhost', 'root', 'vertrigo', 'test') or die ('{error:"bad_request"}');
}

// Hàm đóng kết nối
function disconnect(){
global $conn;
if ($conn){
mysqli_close($conn);
}
}

// Hàm đếm tổng số thành viên
function count_all_member()
{
global $conn;
$query = mysqli_query($conn, 'select count(*) as total from member');
if ($query){
$row = mysqli_fetch_array($query, MYSQLI_ASSOC);
return $row['total'];
}
return 0;
}

// Lấy danh sách thành viên
function get_all_member($limit, $start)
{
global $conn;
$sql = 'select * from member limit '.(int)$start . ','.(int)$limit;
$query = mysqli_query($conn, $sql);

$result = array();

if ($query)
{
while ($row = mysqli_fetch_array($query, MYSQLI_ASSOC)){
$result[] = $row;
}
}

return $result;
}

4. Xây dựng trang hiển thị danh sách phân trang

Đây là phân quan trọng nhất của ứng dụng này. Trước tiên bạn tạo file index.php và copy nội dung như sau:


<?php
// Import thư viện data vào
require_once 'database.php';

// Load thư viện phân trang
include_once 'pagination.php';

// Connect DB
connect();

// Phân trang
$config = array(
'current_page'  => isset($_GET['page']) ? $_GET['page'] : 1,
'total_record'  => count_all_member(), // tổng số thành viên
'limit'         => 3,
'link_full'     => 'index.php?page={page}',
'link_first'    => 'index.php',
'range'         => 9
);

$paging = new Pagination();
$paging->init($config);

// Lấy limit, start
$limit = $paging->get_config('limit');
$start = $paging->get_config('start');

// Lấy danh sách thành viên
$member = get_all_member($limit, $start);

// Kiểm tra nếu là ajax request thì trả kết quả
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
die (json_encode(array(
'member' => $member,
'paging' => $paging->html()
)));
}

// Disconnect DB
disconnect();

?>
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style>
li{float:left; margin: 3px; border: solid 1px gray; list-style: none}
a{padding: 5px;}
span{display:inline-block; padding: 0px 3px; background: blue; color:white }
</style>
<script language="javascript" src="http://code.jquery.com/jquery-2.0.0.min.js"></script>
</head>
<body>
<div id="content">
<div id="list">
<table border="1" cellspacing="0" cellpadding="5">
<?php foreach ($member as $item){ ?>
<tr>
<td>
<?php echo $item['id']; ?> 
</td>
<td>
<?php echo $item['username']; ?>
</td>
<td>
<?php echo $item['email']; ?> 
</td>
<td>
<?php echo $item['fullname']; ?> 
</td>
<td>
<?php echo $item['phone']; ?> 
</td>
</tr>
<?php } ?>
</table>
</div>
<div id="paging">
<?php echo $paging->html(); ?>
</div>
</div>
<script language="javascript">
$('#content').on('click','#paging a', function ()
{
var url = $(this).attr('href');

$.ajax({
url : url,
type : 'get',
dataType : 'json',
success : function (result)
{
//  kiểm tra kết quả đúng định dạng không
if (result.hasOwnProperty('member') && result.hasOwnProperty('paging'))
{
var html = '<table border="1" cellspacing="0" cellpadding="5">';
// lặp qua danh sách thành viên và tạo html
$.each(result['member'], function (key, item){
html += '<tr>';
html += '<td>'+item['id']+'</td>';
html += '<td>'+item['username']+'</td>';
html += '<td>'+item['email']+'</td>';
html += '<td>'+item['fullname']+'</td>';
html += '<td>'+item['phone']+'</td>';
html += '</tr>';
});

html += '</table>';

// Thay đổi nội dung danh sách thành viên
$('#list').html(html);

// Thay đổi nội dung phân trang
$('#paging').html(result['paging']);

// Thay đổi URL trên website
window.history.pushState({path:url},'',url);
}
}
});
return false;
});
</script>
</body>
</html>

Ở file này thì đoạn code php sau có nhiệm vụ là lấy danh sách thành viên và phân trang


// Import thư viện data vào
require_once 'database.php';

// Load thư viện phân trang
include_once 'pagination.php';

// Connect DB
connect();

// Phân trang
$config = array(
'current_page'  => isset($_GET['page']) ? $_GET['page'] : 1,
'total_record'  => count_all_member(), // tổng số thành viên
'limit'         => 3,
'link_full'     => 'index.php?page={page}',
'link_first'    => 'index.php',
'range'         => 9
);

$paging = new Pagination();
$paging->init($config);

// Lấy limit, start
$limit = $paging->get_config('limit');
$start = $paging->get_config('start');

// Lấy danh sách thành viên
$member = get_all_member($limit, $start);

// Kiểm tra nếu là ajax request thì trả kết quả
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
die (json_encode(array(
'member' => $member,
'paging' => $paging->html()
)));
}

// Disconnect DB
disconnect();

Nhưng có một điểm bạn cần chú ý đó là dòng:

// Kiểm tra nếu là ajax request thì trả kết quả
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
    die (json_encode(array(
        'member' => $member,
        'paging' => $paging->html()
    )));
}

Dòng này rất quan trọng, nó có nhiệm vụ kiểm tra nếu như là request là ajax thì nó sẽ trả về một chuỗi json gồm danh sách thành viên và mã html phân trang, còn không phải thì nó bỏ qua và đoạn mã html bên dưới sẽ hoạt động bình thường. Điều này sẽ giúp cho việc khi ta sử dụng ajax để phân trang và nhấn F5 thì nó vẫn lấy đúng dữ liệu
Đoạn code thứ hai bạn cần chú ý là đoạn xử lý ajax dưới đây:


$('#content').on('click','#paging a', function ()
{
var url = $(this).attr('href');

    $.ajax({
url : url,
type : 'get',
dataType : 'json',
success : function (result)
{
//  kiểm tra kết quả đúng định dạng không
if (result.hasOwnProperty('member') && result.hasOwnProperty('paging'))
{
var html = '<table border="1" cellspacing="0" cellpadding="5">';
// lặp qua danh sách thành viên và tạo html
$.each(result['member'], function (key, item){
html += '<tr>';
html += '<td>'+item['id']+'</td>';
html += '<td>'+item['username']+'</td>';
html += '<td>'+item['email']+'</td>';
html += '<td>'+item['fullname']+'</td>';
html += '<td>'+item['phone']+'</td>';
html += '</tr>';
});

                html += '</table>';

                // Thay đổi nội dung danh sách thành viên
$('#list').html(html);

                // Thay đổi nội dung phân trang
$('#paging').html(result['paging']);

                // Thay đổi URL trên website
window.history.pushState({path:url},'',url);
}
}
});
return false;
});

Trong đoạn code này tôi đã gắn sự kiện ON cho thẻ a ở dạng global, tức là dù thẻ a được thêm sau khi load trang thì đoạn code vẫn hoạt động. Nếu như ban không dùng sự kiện ON này thì đoạn mã phân trang sau khi bạn đổi bằng ajax sẽ không có tác dụng.
Nội dung bên trong file quá rõ ràng rồi nên tôi không giải thích gì thêm
Hình ảnh tham khảo:
http://freetuts.net/upload/tut_post/images/2014/08/11/101/phan-trang-ajax-tot-cho-seo.png


5. Lời kết

Như vậy là ta đã làm xong được chức năng phân trang bằng Ajax, đây là một module được sử dụng rất nhiều khi bạn làm các ứng dụng website vì Ajax sẽ giúp cho người dùng cảm thấy website hoạt động mượt mà hơn.
Đây cũng là bài thứ 9 rồi nên tôi hy vọng bạn đã có đủ kiến thúc để tự mình làm ra những ứng dụng khác, tuy nhiên bạn đừng lo vì trong serie mình vẫn còn đề cập đến nhiều kỹ thuật Ajax khác nữa.