Hướng dẫn

Nếu bạn lần đầu ghé thăm blog của mình, bạn có thể vào phần hướng dẫn để biết thêm thông tin và cách sử dụng blog này.

Thứ Ba, 26 tháng 10, 2010

Tạo plugin cho jQuery dùng để kiểm tra sự hợp lệ của form (Phần 3)

Trở lại nhiệm vụ lần trước, chúng ta đã tìm hiểu qua những khái niệm: gọi liên hoàn / không liên hoàn, cấu hình dành cho plugin... Hôm nay công việc sẽ khó "nhai" hơn, nào bắt đầu thôi.

Giới thiệu những thẻ tương tác dữ liệu
Trước khi bắt tay vào việc "code kiếc" chúng ta cần biết những phần tử (element) nào cần / được kiểm tra. Hiện tại HTML có những phần tử sau chứa giá trị khả dĩ có thể chuyển dữ liệu về máy chủ hoặc có thể tương tác với người sử dụng:
Trong những thẻ trên, thẻ input có thuộc tính value dùng để nhận / gán giá trị, riêng thẻ hình ảnh input type="image" thì sử dụng thuộc tính src.


Định nghĩa những cấu hình trên thẻ
Dựa vào đặc điểm có thể thêm tùy biến những thuộc tính mới vào thẻ, chúng ta quy ước rằng những thuộc tính sau đây sẽ sử dụng cho plugin. Chúng ta sẽ đặt tên những thuộc tính có tiền tố là "val-"  (viết tắt validation):

val-type
Chỉ định kiểu kiểm tra, ta có thể quy ước rằng có những kiểu kiểm tra như sau: required(bắt buộc), length(độ dài), range(giới hạn)...
<input type="text" name="user-name" val-type="required"/>

val-message
Chỉ định thông điệp khi kiểm tra không hợp lệ chúng ta sẽ xuất thông điệp này
<input type="text" name="user-name" val-type="required" val-message="Vui lòng nhập tên đăng nhập"/>

val-options
Chỉ định những tùy chọn kèm theo một số sự kiểm tra, ví dụ khi kiểm tra range ta cần biết 2 thông số là min và max
<input type="text" name="quantity" val-type="required" val-message="Số lượng không hợp lệ" val-options="min: 1, max: 100"/>
Nội dung của thuộc  tính val-options cần tuân theo cú pháp khởi tạo object trong javascript, cú pháp đó như sau:
{ name1: value1, name2: value2, name3: value3 }
Với value1, value2, value3... là những hằng, biến số của javascript:
{ name: "anhchanghaudau", age: 100, birthday: new Date(1910, 0, 1) }
Lưu ý, chúng ta sẽ lược bỏ bớt 2 dấu {} để cho ngắn gọn và phòng khi quên điền vào sẽ sai cú pháp, vì vậy cấu trúc đầy đủ là:
<input type="text" name="test" val-type="required" val-message="test" val-options="name: "anhchanghaudau", age: 100, birthday: new Date(1910, 0, 1)"/>

Lập trình
Khâu chuẩn bị vật liệu đã xong, bây giờ bắt tay vào khâu chính. 
(function ($) {
    var validatorLibrary = {};
    $.fn.validate = function () {
    };
})(jQuery);
Dòng 2 ta tiến hành khai báo biến validatorLibrary có kiểu Object, biến này dùng để lưu trữ những loại kiểm tra mà ta định nghĩa ở trên (required, length...)
(function ($) {
    var validatorLibrary = {};

    validatorLibrary.required = function (value, options) {
    };
    validatorLibrary.length = function (value, options) {
    };
    validatorLibrary.range = function (value, options) {
    };
    $.fn.validate = function () {
    };
})(jQuery);
Những dòng tiếp theo chúng ta khai báo thông tin cho từng thuộc tính required, length, range của đối tượng validatorLibrary. Mỗi thông tin này chính là một hàm, mỗi hàm này cần 2 tham số là value, options. Tham số value chính là giá trị cần kiểm tra, options chính là những tùy chọn (thông tin mở rộng) khi kiểm tra.

Việc viết thông tin xử lý cho từng thuộc tính required, length, range như sau:
var validatorLibrary = {};

validatorLibrary.required = function (value, options) {
    return value.length > 0;
};
validatorLibrary.length = function (value, options) {
    return value.length >= options.min && value.length <= options.max;
};
validatorLibrary.range = function (value, options) {
    var number = parseFloat(value);
    return number >= options.min && number <= options.max;
};
Mình giải thích sơ qua ở mỗi hàm. Hàm required đơn giản kiểm tra giá trị nhập vào có độ dài lớn hơn 0 là hợp lệ, ngược lại là không return value.length > 0. Hàm length thì kiểm tra giá trị chuỗi có độ dài phải lớn hơn hoặc bằng tùy chọn min (options.min) và nhỏ hơn hoặc bằng tùy chọn max(options.max). Hàm range kiểm tra giá trị chuỗi có phải là giá trị số, muốn chuyển chuỗi thành số ta dùng hàm parseFloat(), kiểm tra giá trị số có lớn hơn hoặc bằng min (options.min) và nhỏ hơn hoặc bằng max (options.max)

Chúng ta sẽ đi vào phần xử lý chính của plugin
$.fn.validate = function () {
    var valid = true;
    this.each(function () {
    });
};
Chúng ta khai báo biến valid và gán giá trị true, biến này lưu trữ trạng thái hợp lệ hay không hợp lệ của form. Sau đó ta dùng vòng lặp duyệt qua tất cả những đối tượng được jQuery truy vấn, để duyệt ta dùng phương thức each của jQuery (this trong ngữ cảnh này chính là đối tượng jQuery).
$.fn.validate = function () {
    var valid = true;
    this.each(function () {
        var type = $(this).attr('val-type');
        var message = $(this).attr('val-message');
        var options = $(this).attr('val-options');
        var value = $(this).val();
    });
};
Khi duyệt qua vòng lặp ta lầ lượt tạo từng biến để lưu thông tin loại kiểm tra (type lấy từ thuộc tính val-type), thông báo(val-message), tùy chọn(val-options), để lấy thuộc tính của thẻ ta sử dụng phương thức attr ($(<thẻ>).attr(<thuộc tính>)). Chú ý: trong ngữ cảnh này, this chính là thẻ đang được duyệt, khác với this ở dòng 3 là đối tượng jQuery, nên dòng 4 được hiểu là lấy thuộc tính val-type của thẻ đang duyệt lưu vào biến type. Biến value chứa giá trị của thẻ, ví dụ nếu thẻ là input type="text" thì value chính là nội dung văn bản. Lấy thuộc tính value bằng hàm val() không tham số của jQuery.
Sau khi có 3 thuộc tính cần thiết, chúng ta tiến hành kiểm tra.
Chúng ta sẽ kiểm tra giá trị type có khác null hay không, type sẽ null khi thẻ không cấu hình thuộc tính val-type, vì vậy ta hiểu là sẽ không kiểm tra những thẻ không có val-type
$.fn.validate = function () {
    var valid = true;
    this.each(function () {
        var type = $(this).attr('val-type');
        var message = $(this).attr('val-message');
        var options = $(this).attr('val-options');
        var value = $(this).val();
        if (type != null) {
            // kiểm tra tại đây
        }
    });
};
Sau đó chúng ta kiểm tra options nếu bằng null (do thẻ không có cấu hình val-options) thì chúng ta gán options bằng một giá trị mặc định nào đó
if (type != null) {
    if (options == null) options = new Object();
    // kiểm tra tại đây
}
Ở đây mình sử dụng new Object() để tạo một đối tượng rỗng (không có thông tin gì cả) làm giá trị mặc định cho options. Ngược lại, nếu options khác null chúng ta sẽ biên dịch nội dung options thành những tham số bằng hàm eval()
if (options == null)
    options = new Object();
else
    options = eval('({' + options + '})');
Do ban đầu chúng ta quy ước val-options là lệnh khởi tạo object được lược bỏ đi 2 dấu {} nên bây giờ chúng ta phải thêm vào cho đúng cú pháp

Công đoạn tiếp theo là dựa vào những thông tin đó, chúng ta sẽ gọi hàm xử lý tương ứng từ thư viện hàm kiểm tra chúng ta đã định nghĩa phía trên.
// kiểm tra tại đây
var results = validatorLibrary[type](value, options);
Lệnh này có ý nghĩa là lấy một thuộc tính của validatorLibrary có tên bằng đúng giá trị của type, nếu type có giá trị là "length" thì validatorLibrary[type] sẽ tương đương validatorLibrary.length.
Sau khi lấy thuộc tính đó ta tiến hành gọi hàm với 2 tham số value và options:
validatorLibrary[type](value, options)
Kết quả trả về của hàm sẽ lưu vào biến results

Chúng ta sẽ xét xem biến results chứa giá trị true hay false để mà "định đoạt"
// kiểm tra tại đây
var results = validatorLibrary[type](value, options);
if (results == true) {
    // nếu hợp lệ thì không làm gì cả
}
else {
    // chỉ định trạng thái của form là không hợp lệ
    valid = false;
    // xuất câu thông báo
    alert(message);
    // thoát khỏi vòng duyệt của jQuery bằng cách return false
    return false;
}
Nếu kiểm tra hợp lệ (results = true) thì chúng ta không thực hiện gì cả, khi không hợp lệ (results = false) chúng ta sẽ xác định valid = false và xuất câu thông báo ra màn hình bằng lệnh alert(message), sau đó chúng ta sẽ kết thúc vòng duyệt của jQuery bằng lệnh return false.

Hoàn chỉnh
Sau đây là đoạn mã hoàn chỉnh và dùng để kiểm tra thử thành quả của chúng ta
<form onsubmit="return $('input, select, textarea', this).validate();">
    <label>Tên đăng nhập</label><input type="text" val-type="required" val-message="Vui lòng nhập tên đăng nhập" /><br />
    <label>Mật khẩu</label><input type="text" val-type="length" val-message="Mật khẩu không hợp lệ. Mật khẩu có độ dài từ 6 - 10 ký tự" val-options="min: 6, max: 10" /><br />
    <input type="submit" value="Đăng nhập" />
</form>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.4.3.min.js"></script>
<script type="text/javascript">
(function ($) {
    var validatorLibrary = {};

    validatorLibrary.required = function (value, options) {
        return value.length > 0;
    };

    validatorLibrary.length = function (value, options) {
        return value.length >= options.min && value.length <= options.max;
    };

    validatorLibrary.range = function (value, options) {
        var number = parseFloat(value);
        return number >= options.min && number <= options.max;
    };

    $.fn.validate = function () {
        var valid = true;
        this.each(function () {
            var type = $(this).attr('val-type');
            var message = $(this).attr('val-message');
            var options = $(this).attr('val-options');
            var value = $(this).val();
            if (type != null) {
                if (options == null)
                    options = new Object();
                else
                    options = eval('({' + options + '})');
                // kiểm tra tại đây
                var results = validatorLibrary[type](value, options);
                if (results == true) {
                    // nếu hợp lệ thì không làm gì cả
                }
                else {
                    // chỉ định trạng thái của form là không hợp lệ
                    valid = false;
                    // xuất câu thông báo
                    alert(message);
                    // thoát khỏi vòng duyệt của jQuery bằng cách return false
                    return false;
                }
            }
        });
        return valid;
    };
})(jQuery);
</script>


Đoạn mã trên, tạo một form mẫu có 2 hộp nhập với nội dung cần nhập là tên đăng nhập và mật khẩu, ở 2 hộp nhập này có sự kiểm tra tên đăng nhập phải được nhập và mật khẩu phải có độ dài lớn hơn hoặc bằng 6 và nhỏ hơn hoặc bằng 10. Ở sự kiện submit của form ta gọi đoạn mã
onsubmit="return $('input, select, textarea', this).validate();"
Nhằm mục đích kiểm tra những thẻ input, select, textarea có trong form, nếu kiểm tra thành công validate() trả về true thì form được submit, ngược lại validate() trả về false thì thao tác submit của form sẽ bị hủy.

Tổng kết và ý tưởng phát triển
Trên đây chỉ là một đoạn khoảng 40 dòng mã, không thể gọi là toàn vẹn, bạn cần hoàn thiện những yếu tố sau:
  1. "Cải cách" kiểm tra độ dài (length), giới hạn (range) khi không chỉ định min thì chỉ kiểm tra giá trị có lớn hơn max hay không và khi không chỉ định max thì chỉ kiểm tra giá trị có lớn hơn min hay không.
  2. Thêm nhiều loại kiểm tra khác: kiểm tra bằng biểu thức chính quy, kiểm tra giá trị ngày tháng hợp lệ...
  3. Nâng cao khả năng kiểm tra bằng cách cho phép chỉ định kiểm tra required, range (từ 2 kiểm tra trở lên thay vì hiện tại là 1) trên cùng một thẻ.
  4. Thêm tính năng đặt con trỏ văn bản (focus) tại thẻ không hợp lệ sau khi xuất thông báo lỗi

Nếu bạn có những câu hỏi hoặc trao đổi về cách phát triển plugin này thì có thể gửi góp ý bên dưới bài viết.

Không có nhận xét nào:

Đăng nhận xét

Related Posts Plugin for WordPress, Blogger...

Hãy nói không với 4T

Hướng dẫn sử dụng chức năng góp ý
Bạn có thể sử dụng những thẻ <b>, <i>, <a>. Để chú thích đoạn mã bạn có thể sử dụng thẻ [code=type]  [/code], với type là những loại mã sau js, css, html. Chú ý: Khi sử dụng thẻ [code=html] bạn cần theo thế những ký tự < , > thành [] hoặc bạn có thể sử dụng bộ chuyển đổi. Những loại mã khác thì bạn thay thế < , > thành &lt;&gt; hoặc bạn cũng có thể sử dụng bộ chuyển đổi