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