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 }