answered
2013-10-11 09:02:30 +0800
benbai 2228 ● 6
http://www.zkoss.org
I've done ROD with ZK CE without paging:
test.zul
<zk xmlns:w="client">
<style>
.first,
.last {
background: none !important;
}
.first .z-listcell-cnt,
.last .z-listcell-cnt {
height: 0px;
}
.first .z-listcell,
.last .z-listcell {
border: 0;
padding: 0 !important;
}
</style>
<window apply="org.zkoss.bind.BindComposer"
viewModel="@id('vm') @init('test.TestVM')">
<listbox width="350px" height="200px"
onRefreshModel="@command('refreshModel')"
model="@load(vm.model) @template(forEachStatus.index eq vm.first ? 'model1' : forEachStatus.index eq vm.last ? 'model2' : 'model')">
<attribute w:name="_onScrollPos"><![CDATA[
function () {
this.$_onScrollPos();
if (!this._rodIng) {
var wgt = this;
// clear old timer
if (this._rodTimer)
clearTimeout(this._rodTimer);
// add a delay to make it more smooth
this._rodTimer = setTimeout(function () {
wgt._rodIng = true;
var body = wgt.$n('body');
wgt._topToRestore = body.scrollTop;
wgt.fire('onRefreshModel', {
top: body.scrollTop
}, {toServer: true});
this._rodTimer = null;
}, 500);
}
}
]]></attribute>
<attribute w:name="setModel"><![CDATA[
function (v) {
this.$setModel(v);
if (this._rodIng) {
var wgt = this;
setTimeout(function () {
wgt.$n('body').scrollTop = wgt._topToRestore;
}, 50);
setTimeout(function () {
wgt._rodIng = null;
}, 150);
}
}
]]></attribute>
<template name="model1" var="item">
<listitem sclass="first" height="@load(vm.topStyle)">
<listcell label="@load(item)" />
</listitem>
</template>
<template name="model" var="item">
<listitem>
<listcell label="@load(item)" />
</listitem>
</template>
<template name="model2" var="item">
<listitem sclass="last" height="@load(vm.bottomStyle)">
<listcell label="@load(item)" />
</listitem>
</template>
</listbox>
</window>
</zk>
TestVM.java
package test;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.zkoss.bind.annotation.Command;
import org.zkoss.bind.annotation.ContextParam;
import org.zkoss.bind.annotation.ContextType;
import org.zkoss.bind.annotation.NotifyChange;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zul.ListModel;
import org.zkoss.zul.ListModelList;
/**
* tested with ZK 6.5.3
*
* @author benbai
*
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public class TestVM {
private ListModelList _model = null;
private int _start = 1;
/** At most 48 items or will hits ZK built-in optimization
* and break this mechanism
*
*/
private int _viewSize = 48;
private int _total = 1000000;
public ListModel getModel () {
if (_model == null) {
updateModel();
}
return _model;
}
public int getFirst () {
return 0;
}
public int getLast () {
return _viewSize+1;
}
public String getTopStyle () {
return (_start-1)*30 + "px";
}
public String getBottomStyle () {
return (_total - _start - _viewSize + 1)*30 + "px";
}
@Command
@NotifyChange({"model", "topStyle", "bottomStyle"})
public void refreshModel (@ContextParam(ContextType.TRIGGER_EVENT) Event event) {
int top = (Integer)((Map)event.getData()).get("top");
if (top < ((_start-1) * 30)
|| top > ((_start+_viewSize-3) * 30)) {
_start = top/30 - 25;
if (_start < 1) {
_start = 1;
} else if (_start + _viewSize > _total) {
_start = _total - _viewSize + 1;
}
updateModel();
}
}
private void updateModel () {
// assume get data with start/end index from db here
List l = null;
l = new ArrayList();
l.add(""); // fake item to build scroll
for (int i = _start; i <= (_start + _viewSize - 1); i++) {
l.add("Item " + i);
}
l.add(""); // fake item to build scroll
_model = new ListModelList(l);
}
}
I found two different way of implementation here and here.
But i am not sure which is best. Any help ?
Senthilchettyin ( 2013-06-11 10:23:50 +0800 )editI suggest the official one
benbai ( 2013-06-17 10:23:49 +0800 )edit