客户端可滚动数据集






3.50/5 (4投票s)
2005年4月4日
3分钟阅读

44954

518
如何使用 JavaScript 实现数据集的滚动效果。
引言
Web 应用程序中的富客户端似乎是构建用户界面的“潮流”方式。为了追求无缝的用户体验,避免传统 webapps 的启动-停止性质,需要对做事方式施加各种“限制”。
我不得不为 Web 应用程序构建一个 UI,而且它必须很快,至少这是我想达到的目标。直到最后我才意识到,我试图用各种 JavaScript 技巧实现的“UI 响应”效果被从服务器加载数据的漫长耗时所破坏。在大数据集中使用分页会更快,但很明显,没有桌面应用程序在其表格中使用分页。
我认为有一个滚动条并且每次只加载总记录集的一小部分会很棒。这将给用户带来我想要体验,因为他可以以任何速度滚动表格,而不必在开始时等待几秒钟......
解决方案
但是,在 HTML 页面中没有可以使用的滚动条小部件,并且只有一种方法可以在 HTML 页面中显示滚动条,那就是通过 overflow
CSS 属性。 为了显示滚动条,我们需要类似下面的 HTML 代码
<div id="scrollBar" style="overflow:scroll;height:100px;width:17px">
<div id=”valueBar” style=”height=200px”></div>
</div>
然后可以在 scrollBar
的 onscroll
事件上附加一个事件处理程序,我们可以计算滚动的百分比。我创建了一个 JavaScript 来做到这一点
VerticalScrollBar.prototype.attach = function (oId) {
if (document.getElementById(oId)!=null) {
elem = document.getElementById(oId);
if (elem.tagName!="DIV") {
alert("VerticalScrollBar Init : Please attach me to a div");
return;
}
elem.onscroll = this._onScroll;
elem.object = this;
this.scrollBar = elem;
vbar = document.createElement('div');
vbar.style.height = elem.style.pixelHeight*this.maxValue;
elem.appendChild(vbar);
}
};
oId
是父 div
ID。父 div
应该将其样式设置为 “overflow:scroll;width:17px;height:someValue”
。
然后我创建第二个 div
,其大小为 parentSize*maxValue
,并将其附加到父 div
中,并在父级的 onscroll
事件上附加一个事件处理程序。
VerticalScrollBar.prototype._onScroll = function () {
st = event.srcElement.scrollTop ;
sh = event.srcElement.scrollHeight ;
//calculating the % percentage of the position
sp = st * (100/sh);
s = (event.srcElement.object.maxValue)*(sp/100);
event.srcElement.object.value=Math.round(s);
if (event.srcElement.object.onScroll!=null)
event.srcElement.object.onScroll.call();
};
这里唯一值得关注的是以下代码片段
sp = st * (100/sh);
s = (event.srcElement.object.maxValue)*(sp/100);
其中计算了滚动百分比并乘以滚动条的最大值。 我必须在此处注意,即使滚动条已完全滚动,scrollHeight
也大于 scrollTop
(我原本期望它们是相同的)。 我不知道为什么会这样,真的很想知道。
因此,创建滚动条后,我们可以使用它来获取滚动位置并请求记录集的相应部分。
Web 服务
返回记录集的 Web 服务应该是这样的
public struct QueryResult
{
public int offset;
public int count;
public int totalCount;
public string[] result;
}
/// <summary>
/// A webservice method that returns the data
/// takes two parameters
/// </summary>
/// <param name="s">From where to start fetching records</param>
/// <param name="count">The recordcount</param>
/// <returns></returns>
[WebMethod(EnableSession=true)]
public QueryResult GetRecords(int s,int count)
{
QueryResult qres = new QueryResult();
string[] ar = GetRecordset();
qres.totalCount = ar.Length;
string[] res = new string[count];
for (int i=0;i<count;i++)
{
if ((i+s)<ar.Length)
res[i]=ar[i+s];
else
{
qres.count = i;
qres.offset = s;
qres.result = res;
return qres;
}
}
qres.count = count;
qres.offset = s;
qres.result = res;
return qres;
}
完整的记录集存储在会话中,并且根据提供的参数,我们仅获取其中的一部分。 使用 struct
是为了避免创建第二个返回记录总数的方法。
客户端代码
我习惯了 Web 服务的行为,因此我将使用它来创建与 Web 服务交互的客户端代码。对 GetRecords
的方法调用将是同步的,因为我们不想处理异步调用的处理。因此,我们创建一个 JavaScript 函数 _getRecords
,该函数同步调用 Web 服务并返回结果集。
function _getRecords(s,count)
{
//creating the call object for the synch call to the W/S
var callObj = new Object();
callObj.funcName = "GetRecords"; // Name of the remote function.
callObj.async = false; // A Boolean that specifies the type of call
callObj.timeout = 5; // Timeout value for the method call (seconds)
callObj.SOAPHeader = ""; callObj.SOAPHeader += "";
callObj.SOAPHeader += 5;
callObj.SOAPHeader += ""; callObj.SOAPHeader += "";
result = service.Service.callService(callObj, s,count);
if (!result.error) {
return result.value;
} else {
alert("Error:"+result.errorDetail.string);
}
}
在 body 的 onload
事件上,我们分配一个事件处理程序来初始化 Web 服务的行为和滚动条。 当 Web 服务可用时,将执行 setup()
函数来初始化滚动条。
function setup(){
res1 = _getRecords(0,0);
totalRecords =res1.totalCount;
vb = new VerticalScrollBar(totalRecords);
vb.onScroll = vbscroll; vb.attach('sbar');
};
之后,滚动事件的处理程序就很简单了。
function vbscroll() {
getRecords(vb.value);
};
我无法解决的唯一问题是如何根据表格的大小自动确定请求的行数。 这就是为什么请求的行数被手动设置为一个不会大量扩展表格的数字。 经过几次尝试,我发现对于我指定的表格高度来说,16 就可以了。
结论
由于媒介的性质,很多时候我们不得不放弃像这样的解决方法来实现一些特定的效果。
因此,我怀疑这是否是创建所需效果的优雅方式,但它非常吸引人,尤其是从用户的角度来看,因为它提供了用户从富客户端中要求的响应能力。
就这样。