用Ajax实现表格动态滚动

一、概述

    在本文中将讨论如何实现一个基于Ajax的可滚动的表格,在这个表格中,每一行都是从服务器动态获得的,当用户滚动时,整个页并不刷新,而只是局部刷新。这项技术对于实现拥有很多动态数据的表格页是非常有效和便利的。例如,当重表调整页的尺寸后,表格数据将会平滑地滚动。这是由于表格中的数据是通过AJAX从服务端异步获得的,然后由JavaScript对数据进行分析,并动态地插入每一行,而XMLHttpRequest对象用于向服务端发送请求,最后由CSS控制显示风格。
    动态滚动表格的实现主要得意于现代的浏览器引入了XMLHttpRequest对象。这使得JavaScript对象可以使用异步的方式向服务端发送请求,并从服务端接收响应,而这一切都不需要刷新整个网页。更在很多的Web2.0站点都使用了很多AJAX技术来使界面变得更丰富多彩,其中XMLHttpRequest在这些站点和这些动态的网页中被广泛地使用。
    可滚动的表单是一个非常好的富客户端接口,它使用了Web2.0的技术来为用户展现Web内容。动态滚动技术的实现从某种程度上也取决于最新的CSS2标准的推出,这个新的CSS标准现在已经被很多流行的浏览器支持。在本文提供的代码中,我将介绍如何在屏幕的一部分实现可动态滚动的表格,但如果读者所使用的浏览器不动态最新的CSS标准,而只动态AJAX,这个动态表格将变成充满整个页面,而不是屏幕的一部分。
    图1是一个Google读者网站的一个动态表格的例子。要注意的是在图1的截屏上一100项记录,通过移动垂直滚动条可看以更多的记录,当显示到140条时(如图2所示),滚动条的大小开始变化 。这时,所有其他的记录仍然保持在本页的同样的位置。



                一个显示100条记录的动态滚动表单



     图在表单后又新加了40条记录,注意滚动条的位置
二、如保实现动态表单
    为了使任何HTML元素(在本文中是表格)可滚动,需要使用一个可滚动的区域,在这里是DIV,这个元素应该比表格的实际高度小。如一个DIV的高度为100px,包含一个高度为200px的表格,这样才可以使表格滚动。下面的代码演示了div和table的使用:

<div style="height:100px; width:50px;
            overflow:auto; overflow-x:hidden;">
   <table style="height:200px;">
      <tr><td>vlad</td></tr>
   </table>
</div>



图3 产生滚动行为的例子代码

    要注意的是,如果我们将table和div分开写,那么就只有div滚动,而不是表在滚动。让我们先看看如下的代码:
<table style="height:50px; width:100px; overflow:auto;overflow-x:hidden;"> <tr><td><p>vlad 1</p></td></tr> <tr><td><p>vlad 2</p></td></tr> <tr><td><p>vlad 3</p></td></tr> <tr><td><p>vlad 4</p></td></tr> <tr><td><p>vlad 5</p></td></tr> </table>

<hr/> <div style="height:100px; width:100px; overflow:auto;overflow-x:hidden;"> <p>Vlad 1 </p> <p>Vlad 2</p> <p>Vlad 3</p> <p>Vlad 4</p> <p>Vlad 5</p> </div>
4显示了上述代码的运行结果:

图4 

我们注意到table的高度是50,但它仍然不滚动。
 
    上面代码的两个CSS属性:overflow auto和overflow-x:hidden,实际上是将滚动条显示在div的右侧。不过浏览器的CSS引擎必须支持这两个属性,否则,这个表将不会有滚动条。
    如果div中的内容落在了div的外面,可能的原因很多,如margin为负、使用了绝对位置、内容超过了width/height等等,而overflowoverflow-x属性只是描述了内容超过div的宽度应该如何去做。
   
这些CSS属性仅仅定义了divtable的外观,而不是带有滚动属性的JavaScript API接口。为了充分理解一个动态表单的实现,我们需要知道测量HTML元素在网页中的尺寸和位置的属性。这些属性可以通过JavaScript用可编程的方式来操作,更值得庆幸的是,这些API在目前的主要浏览器中都可以使用。
三、HTML元素属性
 
在网页的中心是HTML元素属性的表单,代码位于页中心的HTML BODYDIV中。我们从图5看出,这页有很多这类东西,但是我们最感兴趣的是scrollTopscrollHeightclientHeight




图5 Div的属性的可视化描述

    这个scrollTop属性指定了可视区域(被div的height和width定义的)的内容的上边界的位置,当用户滚动时,scrollTop将确定内容移动的距离(单位是像素)。这个scrollHeight属性指定了inner元素的实际高度(单位是像素),而clientHeight指定了可视区域的实际高度。在本文的例子中,可视区域是outer div元素,而内容是inner表。Height和Top属性并不能解决元素的border、margin或padding,如果我们的元素有这些属性的任何一个,可以使用其他类似的属性代替。和height类似,由width属性来处理水平滚动计算。
    第一个被放置在页上的元素都有这些属性,以及使用这种方式的元素看起来都以来于这些属性。图6显示了一个关于div属性的简单例子。


                                   图6 有滚动功能 的div


四、实现动态滚动表格
    为了实现一个动态表格,我现在已经将表格的显示部分放到了叫"scrolltable"CSS中,将建立了一个id"new_items_div"div和一个id"new_items"table。叫"status"div的目的是为了显示不同的信息。这段html代码如下:

<div id='status'></div> <div id="new_items_div" style="height:500px;" class="scrolltable"> <table id="new_items" border="0" cellpadding="0" cellspacing="0" > <tbody> </tbody> </table> </div>

实现滚动逻辑的代码的第一部分是自动追加更多的行,这些行包括用户已经滚动过的行。为了实现这个功能,我建立了一个JavaScript函数detectScroll(),这个函数每0.5秒执行一次。除了这种方法,还可以为滚动事件建立一个处理事件的函数,并和div绑定。这个startPolling函数当整个页面装载时被调用,并开始周期性地调用detectScroll()函数。

    在这个算法中,将探测滚动位置,并检查所滚动的距离是否大于等于可视区域高度。我还加了20个象素来将滚动条的尺寸计算在内,以确保滚动条可以在适当的位置出现。
    如果用户在向下滚动后向上滚动,并没有新行出现,而只是将已经显示过的数据重新显示。下面是完整的JavaScript代码:
function startPolling(){ pollID = setInterval("detectScroll()",500); } function detectScroll(){ var intElemScrollHeightOuter = document.getElementById("new_items_div").clientHeight; var intElemScrollHeightInner = document.getElementById("new_items").scrollHeight; var intElemScrolled = document.getElementById("new_items_div").scrollTop; var height = intElemScrollHeightInner - intElemScrollHeightOuter; if (intElemScrolled >= height-20) { //alert("You are at " + document.getElementById("new_items").scrollTop + " pixels. adding rows..."); document.getElementById('status').innerHTML = "Showing&nbsp;<b>"+(viewCnt+5)+"</b>&nbsp;items"; fetchAction(viewCnt); viewCnt +=5; } return true; } fetchAction(0); startPolling(); </script>

 

如果当detectScroll执行时返回true。那么会有一个新的JavaScript函数fetchAction被调用。而且还需要使用整个行数来更新div的"status"。

fetchAction函数通过异步的方式访问服务器,并使用XMLHttpRequest对象来分派一个回调函数readFeed来处理服务端的响应。我们在这里不用管服务端是如何实现的,只要知道服务端返回了一个合法的XML就可以了,服务端可以使用任何语言来完成这个任务。在本例中使用了PHP来实现服务端,读者也可以根据自己的喜好使用Java.NETfetchAction()函数的代码如下:

 


 

function fetchAction(si) { var xmlHttp = getXmlHttpObject(); if (xmlHttp==null) { alert('警告,浏览器不支持XmlHttpObject()'); return; } xmlHttp.onreadystatechange=function(){ if (xmlHttp.readyState==4 || xmlHttp.readyState=="complete"){ readFeed(xmlHttp); xmlHttp = null; } } try{ url = 'fetch_items.php?ri='+(Math.floor(Math.random()*10000000))+'&si='+si; xmlHttp.open("GET",url,true); xmlHttp.send(null); } catch (ex){ document.getElementById("status").innerHTML = ex; clearInterval(pollID); } }
1
五、动态分析和插入数据
    下面我们来对服务端返回的XML数据进行分析和动态地向table中插入数据行,下面是返回的XML的代码:

<?xml version='1.0' encoding='ISO-8859-1'?> <channel> <item> <title>Vlad</title> <body><![CDATA[some text]]></body> </item> </channel>
    当服务端响应XML数据时,回调函数readFeed()被调用。这个函数首先获得了这个XMLhandlexmlHttp.responseXML.documentElement。然后获得这个XML的所有叫"item"的元素,并用循环扫描它们,然后去处titlebody。然后将bodytitle传递给helper函数,由addRow函数来向表中增加数据。addRow方法可以获得table对象,在最后插入一个新行,并插入titlebody HTML。下面是readFeed函数的实现:

function readFeed(xmlHttp) { try { if (xmlHttp.responseText.indexOf('invalid') == -1) { var node = xmlHttp.responseXML.documentElement; var items = node.getElementsByTagName('item'); if (items.length == 0){ // hmm still 0 - something is wrong with the stream document.getElementById("status").innerHTML = "nothing was returned..."; } for (var n=0; n < items.length; n++) { var itemTitle = items[n].getElementsByTagName('title').item(0).firstChild.data; var itemBody = items[n].getElementsByTagName('body').item(0).firstChild.data; addRow("new_items",itemTitle, itemBody); } } } catch (e) { document.getElementById("status").innerHTML = e; } }

    下面是addRow函数的实现的源代码:

function addRow(table_id, dtitle, dbody){ pTable = document.getElementById(table_id); row1 = pTable.insertRow(pTable.rows.length); cell1 = row1.insertCell(0); cell1.innerHTML = dtitle; cell2 = row1.insertCell(1); cell2.innerHTML = dbody; }



 在本文的例子页中,一开始有10行,当用户向下滚动时,就会显示超过10行的数据。最终结果如下图所示:


 

 
六、结论
   在本文中,为读者展现了一个基于Ajax的动态滚动表的实现。这个滚动表可以用异步的方式从服务端获取数据,并无刷新地加到表格中。这一切都是由JavaScript实现。这种实现方式的好处是将已经显示过的数据都保存在客户端,这样减小了数据在网络之间的传输。读者可以将这种技术加到自己的系统中,以实现更丰富的Web界面。
 
发布了83 篇原创文章 · 获赞 0 · 访问量 11万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章