ページ全体をリフレッシュせずに、部分的に再表示を定期的に実行したり、停止したり再開する場合に、
どうしたらいいか悩んだ。
org.apache.wicket.ajax.AbstractAjaxTimerBehavior
この中の描画判定のための stop() が実行されたかの判定メソッド、isStopped() が、
final メソッドであることが AbstractAjaxTimerBehavior クラス継承を作成してリスタート機能を
作成することを困難にしている。
仕方ないので、基のAbstractDefaultAjaxBehavior から継承して用意する。
import org.apache.wicket.Component;
import org.apache.wicket.Page;
import org.apache.wicket.RequestCycle;
import org.apache.wicket.ajax.AbstractDefaultAjaxBehavior;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.markup.html.IHeaderResponse;
import org.apache.wicket.protocol.http.WebRequest;
import org.apache.wicket.util.time.Duration;
/**
* リスタート機能付与のAjaxTimerBehavior
*/
public class AjaxTimerBehavior extends AbstractDefaultAjaxBehavior{
private Component component;
private Duration updateInterval;
private boolean stopped;
private boolean headRendered;
public AjaxTimerBehavior(Duration updateInterval,Component component){
this.stopped = false;
this.headRendered = false;
this.component = component;
if (updateInterval == null || updateInterval.getMilliseconds() <= 0L){
throw new IllegalArgumentException("Invalid update interval");
}
this.updateInterval = updateInterval;
return;
}
public final void stop(){
this.stopped = true;
}
protected final void setUpdateInterval(Duration updateInterval){
if (updateInterval == null || updateInterval.getMilliseconds() <= 0L){
throw new IllegalArgumentException("Invalid update interval");
}
this.updateInterval = updateInterval;
return;
}
public final Duration getUpdateInterval(){
return this.updateInterval;
}
@Override
public void renderHead(IHeaderResponse response){
super.renderHead(response);
WebRequest request = (WebRequest)RequestCycle.get().getRequest();
if (!this.stopped && (!this.headRendered || !request.isAjax())){
this.headRendered = true;
response.renderOnLoadJavascript(getJsTimeoutCall(this.updateInterval));
}
}
protected final String getJsTimeoutCall(Duration updateinterval){
return (new StringBuilder()).append("setTimeout(\"")
.append(getCallbackScript()).append("\", ").append(updateinterval.getMilliseconds())
.append(");").toString();
}
@Override
protected CharSequence getCallbackScript(){
return generateCallbackScript*1
.append("wicketAjaxGet('").append(getCallbackUrl(onlyTargetActivePage()))
.append("'").toString());
}
@Override
protected CharSequence getPreconditionScript(){
String precondition = null;
if(!(getComponent() instanceof Page)){
String componentId = getComponent().getMarkupId();
precondition = (new StringBuilder())
.append("var c = Wicket.$('").append(componentId)
.append("'); return typeof(c) != 'undefined' && c != null").toString();
}
return precondition;
}
protected boolean onlyTargetActivePage(){
return true;
}
@Override
protected final void respond(AjaxRequestTarget target){
onTimer(target);
if (!this.stopped)
target.getHeaderResponse()
.renderOnLoadJavascript(getJsTimeoutCall(this.updateInterval));
}
public final boolean isStopped(){
return this.stopped;
}
protected void onTimer(AjaxRequestTarget target){
target.addComponent(this.component);
}
public final void restart(AjaxRequestTarget target){
this.stopped = false;
this.headRendered = false;
onTimer(target);
target.getHeaderResponse()
.renderOnLoadJavascript(getJsTimeoutCall(this.updateInterval));
}
}
------ HTMLのサンプル -------------------
form wicket:id="form"> /form>
table>
tr>
td> span wicket:id="time">HH:mm:ss /span> /td>
td> button wicket:id="switch">switch /button> /td>
/tr>
/table>
div wicket:id="timer"> /div>
------- WebPageサンプル-----------------------
public class SamplePage extends WebPage{
private AjaxTimerBehavior timebehavior;
private boolean isActiveTimelabel;
public TimeBehaviorPage(){
Form Void> form = new Form Void>("form");
add(form);
final Label timelabel = new Label("time",new AbstractReadOnlyModel String>(){
@Override
public String getObject(){
return DateUtils.dateToString(new Date(),"HH:mm:ss");
}
});
timelabel.setOutputMarkupId(true);
add(timelabel);
this.setAjaxTimerBehavior(new AjaxTimerBehavior(Duration.seconds(1),timelabel));
this.setActiveTimelabel(true);
final WebMarkupContainer timer = new WebMarkupContainer("timer");
timer.add(this.getAjaxTimerBehavior());
add(timer);
add(new AjaxButton("switch",form){
@Override
protected void onSubmit(AjaxRequestTarget target,Form ?> f){
if (isActiveTimelabel()){
getAjaxTimerBehavior().stop();
setActiveTimelabel(false);
}else{
getAjaxTimerBehavior().restart(target);
setActiveTimelabel(true);
}
}
});
}
protected AjaxTimerBehavior getAjaxTimerBehavior(){
return this.timebehavior;
}
protected void setAjaxTimerBehavior(AjaxTimerBehavior timebehavior){
this.timebehavior = timebehavior;
}
public boolean isActiveTimelabel(){
return this.isActiveTimelabel;
}
public void setActiveTimelabel(boolean isActiveTimelabel){
this.isActiveTimelabel = isActiveTimelabel;
}
}
*1:new StringBuilder(