sf.wicklet.ext.behaviors.ajax.AjaxRefreshTimerBehavior.java Source code

Java tutorial

Introduction

Here is the source code for sf.wicklet.ext.behaviors.ajax.AjaxRefreshTimerBehavior.java

Source

/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You should have received a copy of  the license along with this library.
 * You may also obtain a copy of the License at
 *         http://www.apache.org/licenses/LICENSE-2.0.
 */
package sf.wicklet.ext.behaviors.ajax;

import org.apache.wicket.Component;
import org.apache.wicket.ajax.AbstractDefaultAjaxBehavior;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.core.util.string.JavaScriptUtils;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.JavaScriptHeaderItem;
import org.apache.wicket.markup.head.OnLoadHeaderItem;
import org.apache.wicket.request.http.WebRequest;
import org.apache.wicket.util.time.Duration;

/**
 * A behavior that generates an AJAX update callback at a regular interval but start as stopped.
 */
public abstract class AjaxRefreshTimerBehavior extends AbstractDefaultAjaxBehavior {
    private static final long serialVersionUID = 1L;
    private static final String TIMERS_ID = AjaxRefreshTimerBehavior.class.getSimpleName() + "-timers";
    private Duration updateInterval;
    private boolean stopped = true;
    private boolean headRendered = false;

    /**
     * Construct.
     *
     * @param updateInterval
     *            Duration between AJAX callbacks
     */
    public AjaxRefreshTimerBehavior(final Duration updateInterval) {
        setUpdateInterval(updateInterval);
    }

    /**
     * Sets the update interval duration. This method should only be called within the
     * {@link #onTimer(AjaxRequestTarget)} method.
     *
     * @param updateInterval
     */
    protected final void setUpdateInterval(final Duration updateInterval) {
        if (updateInterval == null || updateInterval.getMilliseconds() <= 0) {
            throw new IllegalArgumentException("Invalid update interval");
        }
        this.updateInterval = updateInterval;
    }

    /**
     * Returns the update interval
     *
     * @return The update interval
     */
    public final Duration getUpdateInterval() {
        return updateInterval;
    }

    @Override
    public void renderHead(final Component component, final IHeaderResponse response) {
        super.renderHead(component, response);
        response.render(JavaScriptHeaderItem.forScript(
                "if (typeof(Wicket.TimerHandles) === 'undefined') {Wicket.TimerHandles = {}}", TIMERS_ID));
        final WebRequest request = (WebRequest) component.getRequest();
        if (!isStopped() && (!headRendered || !request.isAjax())) {
            headRendered = true;
            response.render(OnLoadHeaderItem.forScript(getJsTimeoutCall(updateInterval)));
        }
    }

    /**
     * @param updateInterval
     *            Duration between AJAX callbacks
     * @return JS script
     */
    protected final String getJsTimeoutCall(final Duration updateInterval) {
        CharSequence js = getCallbackScript();
        js = JavaScriptUtils.escapeQuotes(js);
        final String timeoutHandle = getTimeoutHandle();
        // this might look strange, but it is necessary for IE not to leak :(
        return timeoutHandle + " = setTimeout('" + js + "', " + updateInterval.getMilliseconds() + ')';
    }

    /**
     * @return the name of the handle that is used to stop any scheduled timer
     */
    private String getTimeoutHandle() {
        return "Wicket.TimerHandles['" + getComponent().getMarkupId() + "']";
    }

    /**
     *
     * @see org.apache.wicket.ajax.AbstractDefaultAjaxBehavior#respond(AjaxRequestTarget)
     */
    @Override
    protected final void respond(final AjaxRequestTarget target) {
        if (!isStopped() && isEnabled(getComponent())) {
            onTimer(target);
            target.getHeaderResponse().render(OnLoadHeaderItem.forScript(getJsTimeoutCall(updateInterval)));
        }
    }

    /**
     * Listener method for the AJAX timer event.
     *
     * @param target
     *            The request target
     */
    protected abstract void onTimer(final AjaxRequestTarget target);

    /**
     * @return {@code true} if has been stopped via {@link #stop(AjaxRequestTarget)}
     */
    public final boolean isStopped() {
        return stopped;
    }

    /**
     * Re-enables the timer if already stopped
     *
     * @param target
     */
    public final void restart(final AjaxRequestTarget target) {
        if (isStopped()) {
            stopped = false;
            headRendered = false;
            target.add(getComponent());
        }
    }

    /**
     * Stops the timer
     */
    public final void stop(final AjaxRequestTarget target) {
        stopped = true;
        final String timeoutHandle = getTimeoutHandle();
        target.prependJavaScript("clearTimeout(" + timeoutHandle + "); delete " + timeoutHandle + ";");
    }
}