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}