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.html;
016
017 import java.util.HashMap;
018 import java.util.Map;
019
020 import org.apache.hivemind.ApplicationRuntimeException;
021 import org.apache.tapestry.AbstractComponent;
022 import org.apache.tapestry.IAsset;
023 import org.apache.tapestry.IMarkupWriter;
024 import org.apache.tapestry.IRequestCycle;
025 import org.apache.tapestry.IScript;
026 import org.apache.tapestry.PageRenderSupport;
027 import org.apache.tapestry.Tapestry;
028 import org.apache.tapestry.TapestryUtils;
029 import org.apache.tapestry.components.ILinkComponent;
030 import org.apache.tapestry.components.LinkEventType;
031
032 /**
033 * Combines a link component (such as {@link org.apache.tapestry.link.DirectLink}) with an
034 * <img> and JavaScript code to create a rollover effect that works with both Netscape
035 * Navigator and Internet Explorer. [ <a
036 * href="../../../../../ComponentReference/Rollover.html">Component Reference </a>]
037 *
038 * @author Howard Lewis Ship
039 */
040
041 public abstract class Rollover extends AbstractComponent
042 {
043 /**
044 * Converts an {@link IAsset}binding into a usable URL. Returns null if the binding does not
045 * exist or the binding's value is null.
046 */
047
048 protected String getAssetURL(IAsset asset)
049 {
050 if (asset == null)
051 return null;
052
053 return asset.buildURL();
054 }
055
056 protected void renderComponent(IMarkupWriter writer, IRequestCycle cycle)
057 {
058 // No body, so we skip it all if not rewinding (assumes no side effects on
059 // accessors).
060
061 if (cycle.isRewinding())
062 return;
063
064 String imageURL = null;
065 String mouseOverURL = null;
066 String mouseOutURL = null;
067 boolean dynamic = false;
068 String imageId = null;
069
070 PageRenderSupport pageRenderSupport = TapestryUtils.getPageRenderSupport(cycle, this);
071
072 ILinkComponent serviceLink = (ILinkComponent) cycle
073 .getAttribute(Tapestry.LINK_COMPONENT_ATTRIBUTE_NAME);
074
075 if (serviceLink == null)
076 throw new ApplicationRuntimeException(Tapestry
077 .getMessage("Rollover.must-be-contained-by-link"), this, null, null);
078
079 boolean linkDisabled = serviceLink.isDisabled();
080
081 if (linkDisabled)
082 {
083 imageURL = getAssetURL(getDisabled());
084
085 if (imageURL == null)
086 imageURL = getAssetURL(getImage());
087 }
088 else
089 {
090 imageURL = getAssetURL(getImage());
091 mouseOverURL = getAssetURL(getMouseOver());
092 mouseOutURL = getAssetURL(getMouseOut());
093
094 dynamic = (mouseOverURL != null) || (mouseOutURL != null);
095 }
096
097 if (imageURL == null)
098 throw Tapestry.createRequiredParameterException(this, "image");
099
100 writer.beginEmpty("img");
101
102 writer.attribute("src", imageURL);
103
104 if (dynamic)
105 {
106 if (mouseOverURL == null)
107 mouseOverURL = imageURL;
108
109 if (mouseOutURL == null)
110 mouseOutURL = imageURL;
111
112 imageId = writeScript(cycle, pageRenderSupport, serviceLink, mouseOverURL, mouseOutURL);
113
114 writer.attribute("id", imageId);
115 }
116
117 renderInformalParameters(writer, cycle);
118
119 writer.closeTag();
120
121 }
122
123 // Injected
124
125 public abstract IScript getScript();
126
127 private String writeScript(IRequestCycle cycle, PageRenderSupport pageRenderSupport,
128 ILinkComponent link, String mouseOverImageURL, String mouseOutImageURL)
129 {
130 String imageId = pageRenderSupport.getUniqueString(getId());
131 String preloadedMouseOverImageURL = pageRenderSupport
132 .getPreloadedImageReference(mouseOverImageURL);
133 String preloadedMouseOutImageURL = pageRenderSupport
134 .getPreloadedImageReference(mouseOutImageURL);
135
136 Map symbols = new HashMap();
137
138 symbols.put("imageId", imageId);
139 symbols.put("mouseOverImageURL", preloadedMouseOverImageURL);
140 symbols.put("mouseOutImageURL", preloadedMouseOutImageURL);
141
142 getScript().execute(cycle, pageRenderSupport, symbols);
143
144 // Add attributes to the link to control mouse over/out.
145 // Because the script is written before the <body> tag,
146 // there won't be any timing issues (such as cause
147 // bug #113893).
148
149 link.addEventHandler(LinkEventType.MOUSE_OVER, (String) symbols.get("onMouseOverName"));
150 link.addEventHandler(LinkEventType.MOUSE_OUT, (String) symbols.get("onMouseOutName"));
151
152 return imageId;
153 }
154
155 public abstract IAsset getMouseOut();
156
157 public abstract IAsset getDisabled();
158
159 public abstract IAsset getMouseOver();
160
161 public abstract IAsset getImage();
162 }