Author: ffacon Date: Sat Jul 2 10:14:25 2011 New Revision: 1142187 URL: http://svn.apache.org/viewvc?rev=1142187&view=rev Log: TAP5-746 : Zone should include an option to periodically update itself >From Taha Hafeez
Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/mixins/ZoneRefresh.java tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/mixins/zone-refresh.js tapestry/tapestry5/trunk/tapestry-core/src/test/app1/ZoneRefreshDemo.tml tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/corelib/mixins/ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/corelib/mixins/ZoneRefreshTest.java tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/ZoneRefreshTest.java tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/ZoneRefreshDemo.java Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/EventConstants.java tapestry/tapestry5/trunk/tapestry-core/src/test/app1/Index.tml tapestry/tapestry5/trunk/tapestry-core/src/test/conf/testng.xml Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/EventConstants.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/EventConstants.java?rev=1142187&r1=1142186&r2=1142187&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/EventConstants.java (original) +++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/EventConstants.java Sat Jul 2 10:14:25 2011 @@ -224,5 +224,13 @@ public class EventConstants * @since 5.3.1 */ public static final String NODE_UNSELECTED = "nodeUnselected"; + + /** + * Event triggered by {@link org.apache.tapestry5.corelib.mixins.ZoneRefresh ZoneRefresh} to refresh the + * {@link org.apache.tapestry5.corelib.components.Zone Zone} + * + * @since 5.3.1 + */ + public static final String REFRESH = "refresh"; } Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/mixins/ZoneRefresh.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/mixins/ZoneRefresh.java?rev=1142187&view=auto ============================================================================== --- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/mixins/ZoneRefresh.java (added) +++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/mixins/ZoneRefresh.java Sat Jul 2 10:14:25 2011 @@ -0,0 +1,107 @@ +// Copyright 2011 The Apache Software Foundation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package org.apache.tapestry5.corelib.mixins; + +import org.apache.tapestry5.BindingConstants; +import org.apache.tapestry5.ComponentResources; +import org.apache.tapestry5.EventConstants; +import org.apache.tapestry5.Link; +import org.apache.tapestry5.annotations.AfterRender; +import org.apache.tapestry5.annotations.Import; +import org.apache.tapestry5.annotations.InjectContainer; +import org.apache.tapestry5.annotations.Parameter; +import org.apache.tapestry5.corelib.components.Zone; +import org.apache.tapestry5.internal.util.CaptureResultCallback; +import org.apache.tapestry5.ioc.annotations.Inject; +import org.apache.tapestry5.json.JSONObject; +import org.apache.tapestry5.services.javascript.InitializationPriority; +import org.apache.tapestry5.services.javascript.JavaScriptSupport; + +/** + * <p> + * This mixin periodically refreshs a @{link org.apache.tapestry5.corelib.components.Zone zone} + * by triggering an event on the server using ajax requests. + * </p> + * + * <b>Note: </b> This mixin is only meant for a @{link org.apache.tapestry5.corelib.components.Zone zone} + */ +@Import(library = "zone-refresh.js") +public class ZoneRefresh +{ + /** + * Period between two consecutive refreshes (in seconds) + */ + @Parameter(required = true, defaultPrefix = BindingConstants.LITERAL) + private int period; + + /** + * Context passed to the event + */ + @Parameter + private Object[] context; + + @InjectContainer + private Zone zone; + + @Inject + private JavaScriptSupport javaScriptSupport; + + @Inject + private ComponentResources resources; + + public ZoneRefresh() + { + } + + //For testing purpose + ZoneRefresh(Object [] context, ComponentResources resources, JavaScriptSupport javaScriptSupport, Zone zone) + { + this.context = context; + this.resources = resources; + this.javaScriptSupport = javaScriptSupport; + this.zone = zone; + } + + @AfterRender + void addJavaScript() + { + JSONObject params = new JSONObject(); + + params.put("period", period); + params.put("id", zone.getClientId()); + params.put("URL", createEventLink()); + + javaScriptSupport.addInitializerCall(InitializationPriority.LATE, "zoneRefresh", params); + } + + private Object createEventLink() + { + Link link = resources.createEventLink("zoneRefresh", context); + return link.toAbsoluteURI(); + } + + Object onZoneRefresh() + { + CaptureResultCallback<Object> callback = new CaptureResultCallback<Object>(); + resources.triggerEvent(EventConstants.REFRESH, context, callback); + + if(callback.getResult() != null){ + return callback.getResult(); + } + + return zone; + } + +} \ No newline at end of file Added: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/mixins/zone-refresh.js URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/mixins/zone-refresh.js?rev=1142187&view=auto ============================================================================== --- tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/mixins/zone-refresh.js (added) +++ tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/mixins/zone-refresh.js Sat Jul 2 10:14:25 2011 @@ -0,0 +1,75 @@ +// +// Copyright 2011 The Apache Software Foundation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +if (!Tapestry.ZoneRefresh) +{ + Tapestry.ZoneRefresh = {}; +} + +Tapestry.Initializer.zoneRefresh = function(params) +{ + // Ensure a valid period. Not required as PeriodicalUpdater already takes care of it + // but will will skip unnecessary steps + if(params.period <= 0) + { + return; + } + + // If the timer is already present, don't create a new one + if (Tapestry.ZoneRefresh[params.id]) + { + // Timer already in use + return; + } + + // Set zone + var element = $(params.id); + $T(element).zoneId = params.id; + + // Function to be called for each refresh + var keepUpdatingZone = function(e) + { + try + { + var zoneManager = Tapestry.findZoneManager(element); + zoneManager.updateFromURL(params.URL); + } + catch(e) + { + e.stop(); + Tapestry.error(Tapestry.Messages.invocationException, { + fname : "Tapestry.Initializer.zoneRefresh", + params : params, + exception : e + }); + } + }; + + // Create and store the executor + Tapestry.ZoneRefresh[params.id] = new PeriodicalExecuter(keepUpdatingZone, params.period); +}; + +// Before unload clear all the timers +Event.observe(window, "beforeunload", function() +{ + if (Tapestry.ZoneRefresh) + { + for ( var propertyName in Tapestry.ZoneRefresh) + { + var property = Tapestry.ZoneRefresh[propertyName]; + property.stop(); + } + } +}); Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/app1/Index.tml URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/app1/Index.tml?rev=1142187&r1=1142186&r2=1142187&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-core/src/test/app1/Index.tml (original) +++ tapestry/tapestry5/trunk/tapestry-core/src/test/app1/Index.tml Sat Jul 2 10:14:25 2011 @@ -130,6 +130,10 @@ -- error reporting for adding a duplicate mixin to a component </li> <li> + <a href="ZoneRefreshDemo">Zone Refresh Demo</a> + -- refreshes zone after 5 seconds + </li> + <li> <a href="UnsupportedParameterBlockDemo">Unsupported Parameter Block Demo</a> -- informal block parameter to a component that does not support informal parameters </li> Added: tapestry/tapestry5/trunk/tapestry-core/src/test/app1/ZoneRefreshDemo.tml URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/app1/ZoneRefreshDemo.tml?rev=1142187&view=auto ============================================================================== --- tapestry/tapestry5/trunk/tapestry-core/src/test/app1/ZoneRefreshDemo.tml (added) +++ tapestry/tapestry5/trunk/tapestry-core/src/test/app1/ZoneRefreshDemo.tml Sat Jul 2 10:14:25 2011 @@ -0,0 +1,20 @@ +<html xmlns:t='http://tapestry.apache.org/schema/tapestry_5_1_0.xsd'> + <head> + </head> + + <body> + Counter 1: + <span t:type='zone' t:mixins='zonerefresh' t:period='1' id='zone' t:id='zone'> + ${counter} + </span> + + <br /> + Counter 2 : + <span t:type='zone' t:mixins='zonerefresh' t:period='1' t:id='zone2' id='zone2'>${counter2}</span> + <br /> + Counter 3 : + <span t:type='zone' t:mixins='zonerefresh' t:period='1' t:id='zone3' id='zone3'>${counter3}</span> + and + <span t:type='zone' t:id='zone4' id='zone4'>${counter3}</span> + </body> +</html> \ No newline at end of file Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/conf/testng.xml URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/conf/testng.xml?rev=1142187&r1=1142186&r2=1142187&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-core/src/test/conf/testng.xml (original) +++ tapestry/tapestry5/trunk/tapestry-core/src/test/conf/testng.xml Sat Jul 2 10:14:25 2011 @@ -13,6 +13,7 @@ <package name="org.apache.tapestry5.integration.pagelevel"/> <package name="org.apache.tapestry5.corelib.base"/> <package name="org.apache.tapestry5.corelib.components"/> + <package name="org.apache.tapestry5.corelib.mixins"/> <package name="org.apache.tapestry5.corelib.internal"/> </packages> </test> Added: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/corelib/mixins/ZoneRefreshTest.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/corelib/mixins/ZoneRefreshTest.java?rev=1142187&view=auto ============================================================================== --- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/corelib/mixins/ZoneRefreshTest.java (added) +++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/corelib/mixins/ZoneRefreshTest.java Sat Jul 2 10:14:25 2011 @@ -0,0 +1,70 @@ +// Copyright 2011 The Apache Software Foundation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package org.apache.tapestry5.corelib.mixins; + +import org.apache.tapestry5.ComponentResources; +import org.apache.tapestry5.Link; +import org.apache.tapestry5.corelib.components.Zone; +import org.apache.tapestry5.json.JSONObject; +import org.apache.tapestry5.services.javascript.InitializationPriority; +import org.apache.tapestry5.services.javascript.JavaScriptSupport; +import org.apache.tapestry5.test.TapestryTestCase; +import org.testng.annotations.Test; + +public class ZoneRefreshTest extends TapestryTestCase +{ + + @Test + public void check_add_javascript_calls_component_resources_to_create_url() + { + Object [] context = new Object[]{ "something", "somewhere" }; + ComponentResources resources = mockComponentResources(); + JavaScriptSupport javaScriptSupport = mockJavaScriptSupport(); + Link link = mockLink(); + + Zone zone = mockZone(); + + ZoneRefresh zoneRefresh = new ZoneRefresh(context, resources, javaScriptSupport, zone); + + expect(resources.createEventLink("zoneRefresh", context)).andReturn(link); + expect(link.toAbsoluteURI()).andReturn("mylink"); + + JSONObject params = new JSONObject(); + params.put("period", 0); + params.put("id", zone.getClientId()); + params.put("URL", "mylink"); + javaScriptSupport.addInitializerCall(InitializationPriority.LATE, "zoneRefresh", params); + + replay(); + + zoneRefresh.addJavaScript(); + + verify(); + } + + private Zone mockZone() + { + return new Zone() + { + @Override + public String getClientId() + { + return "zoneId"; + } + + }; + } + +} Added: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/ZoneRefreshTest.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/ZoneRefreshTest.java?rev=1142187&view=auto ============================================================================== --- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/ZoneRefreshTest.java (added) +++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/ZoneRefreshTest.java Sat Jul 2 10:14:25 2011 @@ -0,0 +1,57 @@ +// Copyright 2011 The Apache Software Foundation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package org.apache.tapestry5.integration.app1; + +import org.apache.tapestry5.test.SeleniumTestCase; +import org.testng.annotations.Test; + +public class ZoneRefreshTest extends SeleniumTestCase +{ + @Test + public void test_if_zone_with_void_event_handler_works() throws Exception + { + openBaseURL(); + clickAndWait("link=Zone Refresh Demo"); + checkZoneValues("zone", 3); + } + + @Test + public void test_if_zone_with_single_zone_event_handler_works() throws Exception + { + openBaseURL(); + clickAndWait("link=Zone Refresh Demo"); + checkZoneValues("zone2", 3); + } + + @Test + public void test_if_zone_with_multiple_zone_event_handler_works() throws Exception + { + openBaseURL(); + clickAndWait("link=Zone Refresh Demo"); + checkZoneValues("zone4", 3); + } + + + private void checkZoneValues(String zone, int times) throws Exception + { + Thread.sleep(300); + for(int i = 0; i < times; ++i) + { + assertText(zone, String.valueOf(i)); + Thread.sleep(1000); + } + } + +} Added: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/ZoneRefreshDemo.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/ZoneRefreshDemo.java?rev=1142187&view=auto ============================================================================== --- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/ZoneRefreshDemo.java (added) +++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/ZoneRefreshDemo.java Sat Jul 2 10:14:25 2011 @@ -0,0 +1,69 @@ +// Copyright 2011 The Apache Software Foundation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package org.apache.tapestry5.integration.app1.pages; + +import org.apache.tapestry5.ajax.MultiZoneUpdate; +import org.apache.tapestry5.annotations.InjectComponent; +import org.apache.tapestry5.annotations.Persist; +import org.apache.tapestry5.annotations.Property; +import org.apache.tapestry5.corelib.components.Zone; + +public class ZoneRefreshDemo +{ + @Persist + @Property + private int counter; + + @Persist + @Property + private int counter2; + + @Persist + @Property + private int counter3; + + @InjectComponent + private Zone zone2; + + @InjectComponent + private Zone zone3; + + @InjectComponent + private Zone zone4; + + void setupRender() + { + counter = 0; + counter2 = 0; + counter3 = 0; + } + + void onRefreshFromZone() + { + counter++; + } + + Zone onRefreshFromZone2() + { + counter2++; + return zone2; + } + + Object onRefreshFromZone3(){ + counter3++; + return new MultiZoneUpdate(zone3).add(zone4); + } + +} +