001// Copyright 2008-2014 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.base;
016
017import org.apache.tapestry5.BindingConstants;
018import org.apache.tapestry5.MarkupWriter;
019import org.apache.tapestry5.annotations.Environmental;
020import org.apache.tapestry5.annotations.Parameter;
021import org.apache.tapestry5.http.Link;
022import org.apache.tapestry5.http.services.Request;
023import org.apache.tapestry5.ioc.annotations.Inject;
024import org.apache.tapestry5.services.javascript.JavaScriptSupport;
025
026/**
027 * Base class for link-generating components that are based on a component event request. Such events have an event
028 * context and may also update a {@link org.apache.tapestry5.corelib.components.Zone}.
029 */
030public abstract class AbstractComponentEventLink extends AbstractLink
031{
032    /**
033     * The context for the link (optional parameter). This list of values will be converted into strings and included in
034     * the URI. The strings will be coerced back to whatever their values are and made available to event handler
035     * methods.
036     */
037    @Parameter
038    private Object[] context;
039
040    /**
041     * Binding the zone parameter turns the link into a an Ajax control that causes the related zone to be updated.
042     */
043    @Parameter(defaultPrefix = BindingConstants.LITERAL)
044    private String zone;
045
046    /**
047     * When true, the the link will trigger an asynchronous request (via XmlHttpRequest); the event handler method
048     * can make use of the {@link org.apache.tapestry5.services.ajax.AjaxResponseRenderer} in order to force content
049     * updates to the client.  This is used as an alternative to placing the link inside a {@link org.apache.tapestry5.corelib.components.Zone}
050     * and binding the {@code zone} parameter.
051     *
052     * @since 5.4
053     */
054    @Parameter
055    private boolean async = false;
056
057    @Inject
058    private Request request;
059
060    @Environmental
061    private JavaScriptSupport javaScriptSupport;
062
063    void beginRender(MarkupWriter writer)
064    {
065        if (isDisabled()) return;
066
067        Link link = createLink(context);
068
069        writeLink(writer, link);
070
071        writer.attributes("data-update-zone", zone);
072
073        if (async)
074        {
075            javaScriptSupport.require("t5/core/zone");
076            writer.attributes("data-async-trigger", true);
077        }
078    }
079
080    /**
081     * Invoked to create the Link that will become the href attribute of the output.
082     *
083     * @param eventContext
084     *         the context as an object array, possibly null
085     * @return the link, not null
086     */
087    protected abstract Link createLink(Object[] eventContext);
088
089    void afterRender(MarkupWriter writer)
090    {
091        if (isDisabled()) return;
092
093        writer.end(); // <a>
094    }
095}