    001// Licensed under the Apache License, Version 2.0 (the "License");
    002// you may not use this file except in compliance with the License.
    003// You may obtain a copy of the License at
    004//
    005//     http://www.apache.org/licenses/LICENSE-2.0
    006//
    007// Unless required by applicable law or agreed to in writing, software
    008// distributed under the License is distributed on an "AS IS" BASIS,
    009// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    010// See the License for the specific language governing permissions and
    011// limitations under the License.
    012
    013package org.apache.tapestry5.corelib.mixins;
    014
    015import org.apache.tapestry5.*;
    016import org.apache.tapestry5.annotations.AfterRender;
    017import org.apache.tapestry5.annotations.Events;
    018import org.apache.tapestry5.annotations.InjectContainer;
    019import org.apache.tapestry5.annotations.Parameter;
    020import org.apache.tapestry5.corelib.components.Zone;
    021import org.apache.tapestry5.http.Link;
    022import org.apache.tapestry5.internal.util.CaptureResultCallback;
    023import org.apache.tapestry5.ioc.annotations.Inject;
    024import org.apache.tapestry5.services.javascript.JavaScriptSupport;
    025
    026/**
    027 *
    028 * This mixin periodically refreshs a {@link org.apache.tapestry5.corelib.components.Zone zone}
    029 * by triggering an event on the server using ajax requests.
    030 *
    031 *
    032 * Server-side, the mixin triggers the "refresh" event with the mixin's context. A container may but
    033 * does not need to handle the event. If the event is handled and a value is returned, that value is
    034 * used to render the response. Otherwise, the Zone's body is re-rendered.
    035 *
    036 * <b>Note: </b> This mixin is only meant for a {@link org.apache.tapestry5.corelib.components.Zone zone}.
    037 *
    038 * @tapestrydoc
    039 */
    040@Events(EventConstants.REFRESH)
    041public class ZoneRefresh
    042{
    043    /**
    044     * Period between two consecutive refreshes (in seconds). If a new refresh occurs before the
    045     * previous refresh has completed, it will be skipped.
    046     */
    047    @Parameter(required = true, defaultPrefix = BindingConstants.LITERAL)
    048    private int period;
    049
    050    /**
    051     * Context passed to the event
    052     */
    053    @Parameter
    054    private Object[] context;
    055
    056    @InjectContainer
    057    private Zone zone;
    058
    059    @Inject
    060    private JavaScriptSupport javaScriptSupport;
    061
    062    @Inject
    063    private ComponentResources resources;
    064
    065    //For testing purpose
    066    ZoneRefresh(Object[] context, ComponentResources resources, JavaScriptSupport javaScriptSupport, Zone zone)
    067    {
    068        this.context = context;
    069        this.resources = resources;
    070        this.javaScriptSupport = javaScriptSupport;
    071        this.zone = zone;
    072    }
    073
    074    @AfterRender
    075    void addJavaScript()
    076    {
    077        Link link = resources.createEventLink("zoneRefresh", context);
    078
    079        javaScriptSupport.require("t5/core/zone-refresh").with(zone.getClientId(), period, link.toString());
    080    }
    081
    082    Object onZoneRefresh(EventContext eventContext)
    083    {
    084        CaptureResultCallback<Object> callback = new CaptureResultCallback<Object>();
    085        resources.triggerContextEvent(EventConstants.REFRESH, eventContext, callback);
    086
    087        if (callback.getResult() != null)
    088        {
    089            return callback.getResult();
    090        }
    091
    092        return zone.getBody();
    093    }
    094
    095}