001 // Copyright 2004, 2005 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
015 package org.apache.tapestry.contrib.link;
016
017 import org.apache.hivemind.ApplicationRuntimeException;
018 import org.apache.tapestry.IMarkupWriter;
019 import org.apache.tapestry.IRequestCycle;
020 import org.apache.tapestry.Tapestry;
021 import org.apache.tapestry.components.ILinkComponent;
022 import org.apache.tapestry.engine.ILink;
023 import org.apache.tapestry.link.ILinkRenderer;
024
025 /**
026 * An {@link ILinkRenderer} implementation that generates an HTML button.
027 * This is particularly useful for implementing cancel buttons.
028 *
029 * @author Paul Ferraro
030 * @since 4.0
031 */
032 public class ButtonLinkRenderer implements ILinkRenderer
033 {
034 public static final ILinkRenderer SHARED_INSTANCE = new ButtonLinkRenderer();
035
036 /**
037 * @see org.apache.tapestry.link.ILinkRenderer#renderLink(org.apache.tapestry.IMarkupWriter,
038 * org.apache.tapestry.IRequestCycle, org.apache.tapestry.components.ILinkComponent)
039 */
040 public void renderLink(IMarkupWriter writer, IRequestCycle cycle, ILinkComponent component)
041 {
042 if (cycle.getAttribute(Tapestry.LINK_COMPONENT_ATTRIBUTE_NAME) != null)
043 {
044 String message = Tapestry.getMessage("AbstractLinkComponent.no-nesting");
045 throw new ApplicationRuntimeException(message, component, null, null);
046 }
047
048 cycle.setAttribute(Tapestry.LINK_COMPONENT_ATTRIBUTE_NAME, component);
049
050 ILink link = component.getLink(cycle);
051
052 writer.begin("button");
053 writer.attribute("type", "button");
054
055 if (component.isDisabled())
056 {
057 writer.attribute("disabled", "disabled");
058 }
059
060 if (!cycle.isRewinding()) {
061 String url = link.getURL(component.getAnchor(), true);
062 String target = component.getTarget();
063 String onclick = (target == null) ? getScript(url) : getScript(url, target);
064
065 writer.attribute("onclick", onclick);
066 }
067
068 component.renderAdditionalAttributes(writer, cycle);
069
070 IMarkupWriter wrappedWriter = writer.getNestedWriter();
071
072 component.renderBody(wrappedWriter, cycle);
073
074 wrappedWriter.close();
075
076 writer.end();
077
078 cycle.removeAttribute(Tapestry.LINK_COMPONENT_ATTRIBUTE_NAME);
079 }
080
081 /**
082 * Generates the onclick event handler that opens the specified url in the current window.
083 * @param url the url generated by this link
084 * @return a JavaScript onclick event handler
085 */
086 protected String getScript(String url)
087 {
088 return "window.location='" + url + "'";
089 }
090
091 /**
092 * Generates the onclick event handler that opens the specified url in the specified window or frame.
093 * @param url the url generated by this link
094 * @param target the name of the target window or frame
095 * @return a JavaScript onclick event handler
096 */
097 protected String getScript(String url, String target)
098 {
099 return "window.open('" + url + "','" + target + "')";
100 }
101 }