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 org.apache.hivemind.Resource;
018 import org.apache.tapestry.AbstractComponent;
019 import org.apache.tapestry.IMarkupWriter;
020 import org.apache.tapestry.IRequestCycle;
021 import org.apache.tapestry.PageRenderSupport;
022 import org.apache.tapestry.TapestryUtils;
023 import org.apache.tapestry.asset.AssetFactory;
024 import org.apache.tapestry.util.PageRenderSupportImpl;
025 import org.apache.tapestry.web.WebResponse;
026
027 /**
028 * The body of a Tapestry page. This is used since it allows components on the page access to an
029 * initialization script (that is written the start, just inside the <body> tag). This is
030 * currently used by {@link Rollover}and {@link Script}components. [ <a
031 * href="../../../../../ComponentReference/Body.html">Component Reference </a>]
032 *
033 * @author Howard Lewis Ship
034 */
035
036 public abstract class Body extends AbstractComponent implements PageRenderSupport
037 {
038 private PageRenderSupportImpl _pageRenderSupport;
039
040 /**
041 * Adds to the script an initialization for the named variable as an Image(), to the given URL.
042 * <p>
043 * Returns a reference, a string that can be used to represent the preloaded image in a
044 * JavaScript function.
045 *
046 * @since 1.0.2
047 */
048
049 public String getPreloadedImageReference(String URL)
050 {
051 return _pageRenderSupport.getPreloadedImageReference(URL);
052 }
053
054 /**
055 * Adds other initialization, in the form of additional JavaScript code to execute from the
056 * <body>'s <code>onLoad</code> event handler. The caller is responsible for adding a
057 * semicolon (statement terminator). This method will add a newline after the script.
058 */
059
060 public void addInitializationScript(String script)
061 {
062 _pageRenderSupport.addInitializationScript(script);
063 }
064
065 /**
066 * Adds additional scripting code to the page. This code will be added to a large block of
067 * scripting code at the top of the page (i.e., the before the <body> tag).
068 * <p>
069 * This is typically used to add some form of JavaScript event handler to a page. For example,
070 * the {@link Rollover}component makes use of this.
071 * <p>
072 * Another way this is invoked is by using the {@link Script}component.
073 * <p>
074 * The string will be added, as-is, within the <script> block generated by this
075 * <code>Body</code> component. The script should <em>not</em> contain HTML comments, those
076 * will be supplied by this Body component.
077 * <p>
078 * A frequent use is to add an initialization function using this method, then cause it to be
079 * executed using {@link #addInitializationScript(String)}.
080 */
081
082 public void addBodyScript(String script)
083 {
084 _pageRenderSupport.addBodyScript(script);
085 }
086
087 /**
088 * Used to include a script from an outside URL (the scriptLocation is a URL, probably obtained
089 * from an asset. This adds an <script src="..."> tag before the main <script> tag.
090 * The Body component ensures that each URL is included only once.
091 *
092 * @since 1.0.5
093 */
094
095 public void addExternalScript(Resource scriptLocation)
096 {
097 _pageRenderSupport.addExternalScript(scriptLocation);
098 }
099
100 /**
101 * Retrieves the <code>Body</code> that was stored into the request cycle. This allows
102 * components wrapped by the <code>Body</code> to locate it and access the services it
103 * provides.
104 *
105 * @deprecated To be removed in 4.1. Use
106 * {@link org.apache.tapestry.TapestryUtils#getPageRenderSupport(IRequestCycle)}
107 * instead.
108 */
109
110 public static Body get(IRequestCycle cycle)
111 {
112 return (Body) TapestryUtils.getOptionalPageRenderSupport(cycle);
113 }
114
115 protected void prepareForRender(IRequestCycle cycle)
116 {
117 super.prepareForRender(cycle);
118
119 _pageRenderSupport = new PageRenderSupportImpl(getAssetFactory(), getResponse()
120 .getNamespace(), getLocation());
121 }
122
123 protected void renderComponent(IMarkupWriter writer, IRequestCycle cycle)
124 {
125 TapestryUtils.storePageRenderSupport(cycle, this);
126
127 IMarkupWriter nested = writer.getNestedWriter();
128
129 renderBody(nested, cycle);
130
131 // Start the body tag.
132 writer.println();
133 writer.begin(getElement());
134 renderInformalParameters(writer, cycle);
135
136 writer.println();
137
138 // Write the page's scripting. This is included scripts
139 // and dynamic JavaScript.
140
141 _pageRenderSupport.writeBodyScript(writer, cycle);
142
143 // Close the nested writer, which dumps its buffered content
144 // into its parent.
145
146 nested.close();
147
148 // Any initialization should go at the very end of the document
149 // just before the close body tag. Older version of Tapestry
150 // would create a window.onload event handler, but this is better
151 // (it doesn't have to wait for external images to load).
152
153 _pageRenderSupport.writeInitializationScript(writer);
154
155 writer.end(); // <body>
156 }
157
158 protected void cleanupAfterRender(IRequestCycle cycle)
159 {
160 super.cleanupAfterRender(cycle);
161
162 _pageRenderSupport = null;
163
164 TapestryUtils.removePageRenderSupport(cycle);
165 }
166
167 /**
168 * Parameter.
169 */
170 public abstract String getElement();
171
172 /**
173 * Injected
174 *
175 * @since 4.0
176 */
177 public abstract AssetFactory getAssetFactory();
178
179 /**
180 * Injected
181 *
182 * @since 4.0
183 */
184
185 public abstract WebResponse getResponse();
186
187 /** @since 3.0 */
188
189 public String getUniqueString(String baseValue)
190 {
191 return _pageRenderSupport.getUniqueString(baseValue);
192 }
193
194 }