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