AJAX và một số kỹ thuật liên quan - Phần 1

Nói đến công nghệ AJAX , người ta thường nghĩ ngay đến đối tượng XMLHttpRequest, nhưng thực ra AJAX không chỉ có vậy. Và chúng ta cũng không chỉ có AJAX. Bài viết này
xin giới thiệu một số kỹ thuật tải dữ liệu mà các nhà phát triển web đang khai thác trong nỗ lực kéo các ứng dụng web lại gần hơn với các ứng dụng desktop.

Trong các ví dụ minh họa kèm theo, PHP được dùng làm server script. Do kiến thức có hạn, rất mong nhận được sự góp ý của các bạn về những điểm chưa chính xác.

Nào, chúng ta bắt đầu.



I. Dùng Iframe làm bộ đệm.

Ngay từ phiên bản 4.0, Microsoft đã đưa vào IE một đối tượng gọi là Iframe cho phép nhúng 1 trang web vào trong 1 trang khác. Phiên bản Netscape 4 cũng bắt đầu sử dụng đối tượng Layer để quản lý trang web theo nhiều tầng. Cả Iframe và Layer đều có 1 thuộc tính src liên kết với 1 địa chỉ web bên ngoài, và thông qua Java Script, có thể lấy dữ liệu từ đây để chèn cập nhật nội dung trang chính.

Sau đó, vì IE không hỗ trợ Layer, trong khi Netscape lại hỗ trợ Iframe nên Iframe trở nên phổ biến hơn. Dưới đây, chúng ta sẽ thử làm 1 ví dụ về cách tải trang thông qua 1 iframe để cập nhật nội dung cho trang web chính mà không cần tải lại nó.

Nhưng trước hết bạn hãy hình dung 1 Iframe, nó là 1 inline frame, nằm trong trang web chính, có 1 kích thước cụ thể được quy định bằng CSS. Nếu kích thước của nó là 0x0, người sử dụng sẽ không thấy được nó, dù rằng nó vẫn hiện diện như 1 thành phần của trang web.

Mặt khác, theo cấu trúc DOM và cách xử lý của nhân Java Script trong trình duyệt, thì quan hệ giữa trang chính và iframe là parent - child. Do đó, 1 script trên trang chính có thể truyền các tham số vào 1 script trong Iframe, và ngược lại, miễn là chúng tuân thủ nguyên tắc an toàn dữ liệu theo cơ chế cùng nguồn gốc, nghĩa là trang nằm trong iframe và trang chứa nó phải xuất phát từ cùng một domain.

Như vậy, nếu iframe load 1 trang mới, dưới dạng 1 đoạn HTML, chúng ta có thể gán đoạn HTML này vào 1 phần tử nằm trên parent, để thay đổi nội dung cho parent, thông qua phương thức innerHTML.

Vấn đề đặt ra là nếu chuỗi trả về nằm trên nhiều dòng, script có thể gây ra lỗi. Cho nên tôi đề nghị giải pháp đặt tất cả chuỗi trả về vào trong 1 textArea, sau khi iframe load hoàn chỉnh, chúng ta gọi 1 hàm JavaScript để lấy dữ liệu từ textArea này vào 1 biến, sau đó gửi ngược lên parent.

Tiến trình cụ thể gồm các bước sau :

1. Người sử dụng nhấn vào 1 liên kết có đích là iframe.
2. Iframe tải nội dung trang chứa trong liên kết
3. Iframe tải hoàn chỉnh, 1 script trong iframe chuyển dữ liệu lên parent.
4. Parent cập nhật nội dung vào các phần tử trình bày.
5. Người sử dụng tiếp cận với thông tin vừa cập nhật.


Để làm điều này, đầu tiên chúng ta tạo 1 trang web đơn giản với 2 hàm JavaScript nhỏ trên header :
<script type="text/javascript">
  function rel(ob){return document.getElementById(ob);}
  function gTxt(ob,txt){rel(ob).innerHTML=txt;}
</script>

Hàm rel lấy vào tham số là định danh của 1 phần tử trên trang, và trả về phân tử đó. Hàm gTxt có tác dụng gán 1 chuỗi vào 1 phần tử.

Và phần trình bày là 1 bảng gồm 2 phần. Bên trái chứa các liên kết đến từng chủ đề, khi nhấn vào đây, nội dung chủ đề sẽ được tải vào trang bên phải. Lưu ý là không phải chúng ta đặt 2 iframe 2 bên. Như vậy quá thô thiển và chẳng có gì thú vị ! Đây sẽ chỉ là 2 nửa của 1 bảng :
     <table  width="550" height="350" border="0" cellspacing="0" cellpadding="10">
            <tr>
                <td valign="top" width="150" style="background-color:#fffff4;color:blue;">

<h3>News</h3>
- <a href="load.php?page=1" target="ifr">Cha đẻ World Wide Web nhận Huy chương từ Nữ hoàng Anh</a><br>
- <a href="load.php?page=2" target="ifr">Sự thật chiến dịch giảm giá "kinh hoàng" của Intel</a><br>
- <a href="load.php?page=3" target="ifr">VNPT, EVN, Viettel "chung tay" ứng cứu kênh cáp quang quốc tế</a><br>
- <a href="load.php?page=4" target="ifr">Google xâm nhập Trung Quốc theo "đường vòng"</a><br>
                </td>

Nửa trái liệt kê các liên kết, thuộc tính target thiết lập là ifr cho trình duyệt biết đích của liên kết. Phần bên phải có 1 thẻ DIV được định danh là news để tham chiếu bằng JavaScript, thẻ div này sẽ chứa nội dung các bài viết :
     <td valign="top" width="400" style="background-color:#f4ffff;color:blue;">
                        <div id="news"></div>
                </td>
            </tr>
        </table>

Cuối cùng chúng ta thêm 1 Iframe ẩn :
 <iframe
  id="ifr" name="ifr"
  style="width:0px;height:0px;border:0px;"
  src="load.php?page=1">
</iframe>

Trang load.php được code đơn giản như sau :

 <html>
  <head>
<script type="text/javascript">
function setTxt(){
    var txt=document.cache.news.value;
    parent.gTxt('news',txt);
}
</script>
  </head>
<body onload="setTxt();">
<form name="cache">
  <textArea name="news" style="width:0px;height:0px;">
<?
$page=addslashes($_GET['page']);
$str="";
    $sql="Select * FROM tblNews WHERE NewsID='".$page."'";

// kết nối cơ sở dữ liệu MySQL từ localhostt, với username là root, password rỗng :

$conn = mysql_connect("localhost","root","");
    if(!$conn){
        die('Could not connect database in this time ! ');
        exit();
    }

// Mở cơ sở dữ liệu có tên  News để làm việc

mysql_select_db("News", $conn);

      $result=mysql_query($sql);

  if(mysql_num_rows($result)>0){
      $row=mysql_fetch_array($result);
      $str=$row['Story'];
  }
mysql_free_result($result);
mysql_close($conn);

?>
    <?=$str?>
    </textArea>
</form>
</body>
</html>


Như vậy, bạn sẽ cần tạo 1 bảng tblNews đơn giản gồm 2 cột :

CREATE TABLE `tblNews` (
`NewsID` INT( 5 ) NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`Story` TEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
) ;

Chúng ta truy vấn cơ sở dữ liệu, tìm phần tin theo giá trị page trên chuỗi GET. Và nếu có mẩu tin tương ứng, chúng ta lấy giá trị Story gán vào biến $str. Nêu không tìm thấy mẩu tin nào, $str sẽ rỗng như khi nó được khởi tạo. sau cùng nó được gán vào trong textArea có tên news trong form cache.

Hàm setTxt được gọi trong biến cố onload, lấy giá trị trong textArea, và truyền như tham số vào hàm gTxt trên parent để gTxt gán chuỗi txt cho phần tử news. Tất cả chỉ có vậy.