1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.apache.struts2.dojo.components;
23
24 import javax.servlet.http.HttpServletRequest;
25 import javax.servlet.http.HttpServletResponse;
26
27 import org.apache.struts2.views.annotations.StrutsTag;
28 import org.apache.struts2.views.annotations.StrutsTagAttribute;
29 import org.apache.struts2.views.annotations.StrutsTagSkipInheritance;
30
31 import com.opensymphony.xwork2.util.ValueStack;
32
33 /***
34 * <!-- START SNIPPET: notice -->
35 * The "head" tag renders required JavaScript code to configure Dojo and is required in order to use
36 * any of the tags included in the Dojo plugin.</p>
37 * <!-- END SNIPPET: notice -->
38 *
39 * <!-- START SNIPPET: javadoc -->
40 * <p></p>
41 *
42 * <p>To debug javascript errors set the "debug" attribute to true, which will display Dojo
43 * (and Struts) warning and error messages at the bottom of the page. Core Dojo files are by default
44 * compressed, to improve loading time, which makes them very hard to read. To debug Dojo and Struts
45 * widgets, set the "compressed" attribute to true. Make sure to turn this option off before
46 * moving your project into production, as uncompressed files will take longer to download.
47 * </p>
48 * <p>For troubleshooting javascript problems the following configuration is recommended:</p>
49 * <pre>
50 * <sx:head debug="true" cache="false" compressed="false" />
51 * </pre>
52 *
53 * <p>Dojo files are loaded as required by the Dojo loading mechanism. The problem with this
54 * approach is that the files are not cached by the browser, so reloading a page or navigating
55 * to a different page that uses the same widgets will cause the files to be reloaded. To solve
56 * this problem a custom Dojo profile is distributed with the Dojo plugin. This profile contains
57 * the files required by the tags in the Dojo plugin, all in one file (524Kb), which is cached
58 * by the browser. This file will take longer to load by the browser but it will be downloaded
59 * only once. By default the "cache" attribute is set to false.</p>
60 *
61 * <p>Some tags like the "datetimepicker" can use different locales, to use a locale
62 * that is different from the request locale, it must be specified on the "extraLocales"
63 * attribute. This attribute can contain a comma separated list of locale names. From
64 * Dojo's documentation:</p>
65 *
66 * <p>
67 * The locale is a short string, defined by the host environment, which conforms to RFC 3066
68 * (http://www.ietf.org/rfc/rfc3066.txt) used in the HTML specification.
69 * It consists of short identifiers, typically two characters
70 * long which are case-insensitive. Note that Dojo uses dash separators, not underscores like
71 * Java (e.g. "en-us", not "en_US"). Typically country codes are used in the optional second
72 * identifier, and additional variants may be specified. For example, Japanese is "ja";
73 * Japanese in Japan is "ja-jp". Notice that the lower case is intentional -- while Dojo
74 * will often convert all locales to lowercase to normalize them, it is the lowercase that
75 * must be used when defining your resources.
76 * </p>
77 *
78 * <p>The "locale" attribute configures Dojo's locale:</p>
79 *
80 * <p>"The locale Dojo uses on a page may be overridden by setting djConfig.locale. This may be
81 * done to accomodate applications with a known user profile or server pages which do manual
82 * assembly and assume a certain locale. You may also set djConfig.extraLocale to load
83 * localizations in addition to your own, in case you want to specify a particular
84 * translation or have multiple languages appear on your page."</p>
85 *
86 * <p>To improve loading time, the property "parseContent" is set to false by default. This property will
87 * instruct Dojo to only build widgets using specific element ids. If the property is set to true
88 * Dojo will scan the whole document looking for widgets.</p>
89 *
90 * <p>Dojo 0.4.3 is distributed with the Dojo plugin, to use a different Dojo version, the
91 * "baseRelativePath" attribute can be set to the URL of the Dojo root folder on your application.
92 * </p>
93 * <!-- END SNIPPET: javadoc -->
94 *
95 * <p/> <b>Examples</b>
96 *
97 * <pre>
98 * <!-- START SNIPPET: example1 -->
99 * <%@ taglib prefix="sx" uri="/struts-dojo-tags" %>
100 * <head>
101 * <title>My page</title>
102 * <sx:head/>
103 * </head>
104 * <!-- END SNIPPET: example1 -->
105 * </pre>
106 *
107 * <pre>
108 * <!-- START SNIPPET: example3 -->
109 * <%@ taglib prefix="sx" uri="/struts-dojo-tags" %>
110 * <head>
111 * <title>My page</title>
112 * <sx:head debug="true" extraLocales="en-us,nl-nl,de-de"/>
113 * </head>
114 * <!-- END SNIPPET: example3 -->
115 * </pre>
116 *
117 */
118 @StrutsTag(name="head", tldBodyContent="empty", tldTagClass="org.apache.struts2.dojo.views.jsp.ui.HeadTag",
119 description="Render a chunk of HEAD for your HTML file")
120 @StrutsTagSkipInheritance
121 public class Head extends org.apache.struts2.components.Head {
122 public static final String TEMPLATE = "head";
123 public static final String PARSE_CONTENT = "struts.dojo.head.parseContent";
124
125 private String debug;
126 private String compressed;
127 private String baseRelativePath;
128 private String extraLocales;
129 private String locale;
130 private String cache;
131 private String parseContent;
132
133 public Head(ValueStack stack, HttpServletRequest request, HttpServletResponse response) {
134 super(stack, request, response);
135 }
136
137 protected String getDefaultTemplate() {
138 return TEMPLATE;
139 }
140
141 public void evaluateParams() {
142 super.evaluateParams();
143
144 if (this.debug != null)
145 addParameter("debug", findValue(this.debug, Boolean.class));
146 if (this.compressed != null)
147 addParameter("compressed", findValue(this.compressed, Boolean.class));
148 if (this.baseRelativePath != null)
149 addParameter("baseRelativePath", findString(this.baseRelativePath));
150 if (this.extraLocales != null) {
151 String locales = findString(this.extraLocales);
152 addParameter("extraLocales", locales.split(","));
153 }
154 if (this.locale != null)
155 addParameter("locale", findString(this.locale));
156 if (this.cache != null)
157 addParameter("cache", findValue(this.cache, Boolean.class));
158 if (this.parseContent != null) {
159 Boolean shouldParseContent = (Boolean) findValue(this.parseContent, Boolean.class);
160 addParameter("parseContent", shouldParseContent);
161 stack.getContext().put(PARSE_CONTENT, shouldParseContent);
162 } else {
163 addParameter("parseContent", false);
164 stack.getContext().put(PARSE_CONTENT, false);
165 }
166 }
167
168 @Override
169 @StrutsTagSkipInheritance
170 public void setTheme(String theme) {
171 super.setTheme(theme);
172 }
173
174 @Override
175 public String getTheme() {
176 return "ajax";
177 }
178
179 public boolean isDebug() {
180 return debug != null && Boolean.parseBoolean(debug);
181 }
182
183 @StrutsTagAttribute(description="Enable Dojo debug messages", defaultValue="false", type="Boolean")
184 public void setDebug(String debug) {
185 this.debug = debug;
186 }
187
188 @StrutsTagAttribute(description="Use compressed version of dojo.js", defaultValue="true", type="Boolean")
189 public void setCompressed(String compressed) {
190 this.compressed = compressed;
191 }
192
193 @StrutsTagAttribute(description="Context relative path of Dojo distribution folder", defaultValue="/struts/dojo")
194 public void setBaseRelativePath(String baseRelativePath) {
195 this.baseRelativePath = baseRelativePath;
196 }
197
198 @StrutsTagAttribute(description="Comma separated list of locale names to be loaded by Dojo, locale names must be specified as in RFC3066")
199 public void setExtraLocales(String extraLocales) {
200 this.extraLocales = extraLocales;
201 }
202
203 @StrutsTagAttribute(description="Default locale to be used by Dojo, locale name must be specified as in RFC3066")
204 public void setLocale(String locale) {
205 this.locale = locale;
206 }
207
208 @StrutsTagAttribute(description="Use Struts Dojo profile, which contains all Struts widgets in one file, making it possible to be chached by " +
209 "the browser", defaultValue="true", type="Boolean")
210 public void setCache(String cache) {
211 this.cache = cache;
212 }
213
214 @StrutsTagAttribute(description="Parse the whole document for widgets", defaultValue="false", type="Boolean")
215 public void setParseContent(String parseContent) {
216 this.parseContent = parseContent;
217 }
218 }