001// Copyright 2010, 2011 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.Block;
018import org.apache.tapestry5.ComponentResources;
019import org.apache.tapestry5.MarkupWriter;
020import org.apache.tapestry5.annotations.AfterRender;
021import org.apache.tapestry5.annotations.BeginRender;
022import org.apache.tapestry5.annotations.Events;
023import org.apache.tapestry5.annotations.MixinAfter;
024import org.apache.tapestry5.ioc.annotations.Inject;
025
026/**
027 * This mixin triggers <em>component event</em> notifications when the
028 * attached component enters its {@link BeginRender} and {@link AfterRender}
029 * render phases. A common use of this is to handle the "afterRender"
030 * event to generate client-side JavaScript for content just rendered via a
031 * {@link Block} (this is a common Ajax use case related to partial page
032 * rendering). Since AJAX requests don't trigger afterRender or beforeRender
033 * render phase events in the containing component or page, this mixin provides
034 * a way of accessing those events as component events.
035 * <p>
036 * An example using the {@link org.apache.tapestry5.corelib.components.Any Any}
037 * component within a zone:
038 * <pre>
039 * &lt;div t:type="Zone" id="myZone"&gt;
040 *     &lt;t:any t:mixins="RenderNotification"&gt;
041 *              &lt;!-- zone content -&gt;
042 *      &lt;/div&gt;
043 * &lt;/div&gt;
044 * </pre>
045 * The {@link MarkupWriter} is passed as the event context to your event handler
046 * method(s), so your corresponding component or page class might look like:
047 * <pre>
048 * void onBeginRenderFromMyZone(MarkupWriter writer)
049 * {
050 *     writer.element("p");
051 *     writer.write("before item render");
052 *     writer.end();
053 * }
054
055 * void onAfterRenderFromMyZone(MarkupWriter writer)
056 * {
057 *     writer.element("p");
058 *     writer.write("after item render");
059 *     writer.end();
060 * }
061 * </pre>
062 * As an alternative, see the {@link org.apache.tapestry5.corelib.components.Trigger Trigger}
063 * component, which does something similar but as a component rather than a mixin.
064 * 
065 * @since 5.2.0
066 * @tapestrydoc
067 */
068@Events(
069{ "beginRender", "afterRender" })
070@MixinAfter
071public class RenderNotification
072{
073    @Inject
074    private ComponentResources resources;
075
076    void beginRender(MarkupWriter writer)
077    {
078        trigger(writer, "beginRender");
079    }
080
081    void afterRender(MarkupWriter writer)
082    {
083        trigger(writer, "afterRender");
084    }
085
086    private void trigger(MarkupWriter writer, String eventName)
087    {
088        resources.triggerEvent(eventName, new Object[]
089        { writer }, null);
090    }
091}