Xử lí “Back” cho AJAX

AJAX là kỹ thuật thời thượng, tạo nên thế hệ ứng dụng web đáp ứng nhanh, tiết kiệm nhiều thời gian cho người dùng khi lướt web. Tuy nhiên, nếu là người viết ứng dụng web, chắc hẳn bạn cũng đã biết một số khuyết điểm của các ứng dụng trên nền AJAX. Một trong số đó là tính năng Back. Khi bạn xem các trang của một website dùng kỹ thuật AJAX, nếu nhấn nút Back trên thanh công cụ của trình duyệt thì bạn sẽ bị “đá văng” khỏi website thay vì được đưa về trang trước đó. Bài viết này trình bày một trong số những cách khắc phục khuyết điểm trên.

Ta xét một website, trang web chính có 3 liên kết đến 3 trang nội dung. Đây là liên kết giả vì không dùng tag <A HREF> mà dùng XMLHttpRequest để lấy nội dung từ 3 file t1.xml, t2.xml, t3.xml đưa vào trang chính, làm cho người dùng tưởng mình được đưa tới 3 trang web khác nhau của website.

Tạo 3 trang nội dung như sau:

t1.xml

<xml>Day la noi dung cua trang so 1.</xml>

t2.xml

<xml>Day la noi dung cua trang so 2.</xml>

t3.xml

<xml>Day la noi dung cua trang so 3.</xml>

Đặt 3 file xml vào thư mục gốc của website (giả sử là http://localhost/).

Tiếp theo, tạo trang web chính index.html nội dung như sau:

<html>

<div>Xem trang 1</div>

<div>Xem trang 2</div>

<div>Xem trang 3</div>

<div id=nd></div>

</html>

Trang web chính gồm 3 liên kết là 3 phần tử <div>, và một phần tử <div> có nhiệm vụ chứa nội dung của 3 trang. Để lấy dữ liệu và đưa ra trang chính, ta viết hàm xreq()ghi().

Bổ sung đoạn mã sau vào file index.html:

<script>

function xreq(file,func){

var req

if(window.XMLHttpRequest){

req=new XMLHttpRequest();

if (req.overrideMimeType) {

req.overrideMimeType(text/xml);

}

}else{

try{

req=new ActiveXObject(“Msxml2.XMLHTTP”);

}catch(e){

req=new ActiveXObject(“Microsoft.XMLHTTP”);

}

}

req.onreadystatechange = function(){

if(req.readyState==4){

func(req.responseXML.childNodes[0].text)

}

}

req.open(GET,file,true);

req.send(null);

}

function ghi(noi_dung){

nd.innerHTML=noi_dung

}

</script>

Gắn hàm xreq() và hàm ghi() vào sự kiện onclick của 3 <div> liên kết.

<div onclick=”xreq(t1.xml,ghi);”>Xem trang 1</div>

<div onclick=”xreq(t2.xml,ghi);”>Xem trang 2</div>

<div onclick=”xreq(t3.xml,ghi)”>Xem trang 3</div>

Truy cập vào địa chỉ http://localhost/ (hoặc địa chỉ web trên máy chủ của bạn), sau đó nhấn vào các liên kết Xem trang 1… Bạn sẽ thấy nội dung trang web thay đổi tương ứng.

Bây giờ thử nhấn nút Back của trình duyệt, bạn sẽ bị đưa ra khỏi website ngay. Đó chính là điều ta sẽ giải quyết. Ý tưởng là “lừa” trình duyệt, hướng nó về một trang web khác, để khi nhấn Back hay Forward, trình duyệt sẽ thực hiện lệnh đó trên trang web này chứ không phải là trang web chính.

Để làm điều này, đầu tiên bạn hãy chèn đoạn mã sau vào trang chính:

<iframe id=”ifr” src=”f.htm”></iframe>

Sau đó, tạo một trang phụ là f.htm trong thư mục gốc với nội dung như sau:

<script>

window.onload=function (){

if(location.search!=){

var loc=unescape(location.search)

var mdl=(loc.substring(1,loc.length)).split(/&|=/)

var str=parent.+mdl[1]+(

for(var i=3;i<mdl.length;i+=2){

if(mdl[i].charAt(0)!=”){

str+=parent.

}

str+=mdl[i]+,

}

str=str.substring(0,str.length-1)+)

eval(str)

}

}

</script>

Bây giờ, bạn thêm hàm xu_li() với nhiệm vụ xử lí kết quả trả về của hàm xreq(), và hàm url() với nhiệm vụ thay đổi địa chỉ của <IFRAME> vào trong nội dung trang chính.

function xu_li(ket_qua){

url(ghi,ket_qua)

}

function url(){

var str=?func=+arguments[0]

for(var y=1;y<arguments.length;y++){

str+=&arg+y+=

if(typeof(arguments[y])==string){

str+=”+arguments[y]+”

}else{

if(typeof(arguments[y])==object){

str+=arguments[y].id

}else{

str+=arguments[y]

}

}

}

if(ifr.location.search!=str){

ifr.location=f.htm+str

}

}

Đến đây chắc bạn cũng hiểu được phần nào ý tưởng trên.

Thay sự kiện onclick của 3 <div> liên kết, gọi tới hàm xreq() nhưng hàm xử lí bây giờ sẽ là xu_li() chứ không còn là hàm ghi() như trên.

<div onclick=”xreq(t1.xml,xu_li);”>Xem trang 1</div>

<div onclick=”xreq(t2.xml,xu_li);”>Xem trang 2</div>

<div onclick=”xreq(t3.xml,xu_li)”>Xem trang 3</div>

Cuối cùng, thêm thuộc tính display vào style của <IFRAME> với giá trị là none để không cho phép <IFRAME> phụ này hiện ra trong trang chính.

<iframe id=”ifr” src=”f.htm” style=”display:none;”></iframe>

Mọi việc đã hoàn tất! Hãy truy cập website vừa tạo để xem kết quả.

Hãy thử nhấn các liên kết Xem trang 1, Xem trang 2, Xem trang 3, sau đó nhấn nút Back, bạn sẽ thấy bây giờ mình không bị “đá” ra khỏi website nữa, mà được đưa về các “trang” trước vừa xem.

Trên đây là một cách khắc phục khuyết điểm nút Back của ứng dụng AJAX, bạn có thể phát triển thêm, hoặc sửa đổi để phù hợp với ứng dụng của mình.