1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.struts2.components;
22
23 import java.text.ParseException;
24 import java.text.MessageFormat;
25 import java.text.SimpleDateFormat;
26 import java.util.Calendar;
27 import java.util.Date;
28
29 import javax.servlet.http.HttpServletRequest;
30 import javax.servlet.http.HttpServletResponse;
31
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34 import org.apache.struts2.views.annotations.StrutsTag;
35 import org.apache.struts2.views.annotations.StrutsTagAttribute;
36
37 import com.opensymphony.xwork2.util.ValueStack;
38
39 /***
40 * <!-- START SNIPPET: javadoc -->
41 * <p>
42 * Renders a date/time picker in a dropdown container.
43 * </p>
44 * <p>
45 * A stand-alone DateTimePicker widget that makes it easy to select a date/time, or increment by week, month,
46 * and/or year.
47 * </p>
48 *
49 * <p>
50 * It is possible to customize the user-visible formatting with either the
51 * 'formatLength' (long, short, medium or full) or 'displayFormat' attributes. By defaulty current
52 * locale will be used.</p>
53 * </p>
54 *
55 * Syntax supported by 'displayFormat' is (http://www.unicode.org/reports/tr35/tr35-4.html#Date_Format_Patterns):-
56 * <table border="1">
57 * <tr>
58 * <td>Format</td>
59 * <td>Description</td>
60 * </tr>
61 * <tr>
62 * <td>d</td>
63 * <td>Day of the month</td>
64 * </tr>
65 * <tr>
66 * <td>D</td>
67 * <td>Day of year</td>
68 * </tr>
69 * <tr>
70 * <td>M</td>
71 * <td>Month - Use one or two for the numerical month, three for the abbreviation, or four for the full name, or 5 for the narrow name.</td>
72 * </tr>
73 * <tr>
74 * <td>h</td>
75 * <td>Hour [1-12].</td>
76 * </tr>
77 * <tr>
78 * <td>H</td>
79 * <td>Hour [0-23].</td>
80 * </tr>
81 * <tr>
82 * <td>m</td>
83 * <td>Minute. Use one or two for zero padding.</td>
84 * </tr>
85 * <tr>
86 * <td>s</td>
87 * <td>Second. Use one or two for zero padding.</td>
88 * </tr>
89 * </table>
90 *
91 * <p>
92 * The value sent to the server is
93 * typically a locale-independent value in a hidden field as defined by the name
94 * attribute. RFC3339 representation is the format used.
95 * </p>
96 *
97 * <p/>
98 *
99 * <!-- END SNIPPET: javadoc -->
100 *
101 * <b>Examples</b>
102 *
103 * <pre>
104 * <!-- START SNIPPET: expl1 -->
105 *
106 * Example 1:
107 * <s:datetimepicker name="order.date" label="Order Date" />
108 * Example 2:
109 * <s:datetimepicker name="delivery.date" label="Delivery Date" format="yyyy-MM-dd" />
110 *
111 * <!-- END SNIPPET: expl1 -->
112 * </pre>
113 * <p/>
114 *
115 * <!-- START SNIPPET: expldesc2 -->
116 *
117 * The css could be changed by using the following :-
118 *
119 * <!-- END SNIPPET: expldesc2 -->
120 *
121 * <pre>
122 * <!-- START SNIPPET: expl2 -->
123 *
124 * <s:datetimepicker name="birthday" label="Birthday" templateCss="...." />
125 *
126 * <!-- END SNIPPET: expl2 -->
127 * </pre>
128 *
129 */
130 @StrutsTag(name="datetimepicker", tldTagClass="org.apache.struts2.views.jsp.ui.DateTimePickerTag", description="Render datetimepicker")
131 public class DateTimePicker extends UIBean {
132
133 final public static String TEMPLATE = "datetimepicker";
134
135
136 final private static String RFC3339_FORMAT = "yyyy-MM-dd'T'HH:mm:ss";
137 final private static String RFC3339_PATTERN = "{0,date," + RFC3339_FORMAT + "}";
138 final protected static Log LOG = LogFactory.getLog(DateTimePicker.class);
139
140 protected String iconPath;
141 protected String formatLength;
142 protected String displayFormat;
143 protected String toggleType;
144 protected String toggleDuration;
145 protected String type;
146
147 protected String displayWeeks;
148 protected String adjustWeeks;
149 protected String startDate;
150 protected String endDate;
151 protected String weekStartsOn;
152 protected String staticDisplay;
153 protected String dayWidth;
154 protected String language;
155 protected String templateCssPath;
156
157 public DateTimePicker(ValueStack stack, HttpServletRequest request, HttpServletResponse response) {
158 super(stack, request, response);
159 }
160
161 protected String getDefaultTemplate() {
162 return TEMPLATE;
163 }
164
165 public void evaluateParams() {
166 super.evaluateParams();
167
168 if(displayWeeks != null)
169 addParameter("displayWeeks", findString(displayWeeks));
170 if(adjustWeeks != null)
171 addParameter("adjustWeeks", findValue(adjustWeeks, Boolean.class));
172 if(startDate != null)
173 addParameter("startDate", findString(startDate));
174 if(endDate != null)
175 addParameter("endDate", findString(endDate));
176 if(weekStartsOn != null)
177 addParameter("weekStartsOn", findString(weekStartsOn));
178 if(staticDisplay != null)
179 addParameter("staticDisplay", findValue(staticDisplay, Boolean.class));
180 if(dayWidth != null)
181 addParameter("dayWidth", findValue(dayWidth, Integer.class));
182 if(language != null)
183 addParameter("language", findString(language));
184 if(value != null)
185 addParameter("value", findString(value));
186 if(iconPath != null)
187 addParameter("iconPath", findString(iconPath));
188 if(formatLength != null)
189 addParameter("formatLength", findString(formatLength));
190 if(displayFormat != null)
191 addParameter("displayFormat", findString(displayFormat));
192 if(toggleType != null)
193 addParameter("toggleType", findString(toggleType));
194 if(toggleDuration != null)
195 addParameter("toggleDuration", findValue(toggleDuration,
196 Integer.class));
197 if(type != null)
198 addParameter("type", findString(type));
199 else
200 addParameter("type", "date");
201 if(templateCssPath != null)
202 addParameter("templateCssPath", findString(templateCssPath));
203
204
205 if(parameters.containsKey("value")) {
206 parameters.put("nameValue", format(parameters.get("value")));
207 } else {
208 if(name != null) {
209 String expr = name;
210 if(altSyntax()) {
211 expr = "%{" + expr + "}";
212 }
213 addParameter("nameValue", format(findValue(expr)));
214 }
215 }
216 }
217
218 @StrutsTagAttribute(description="If true, weekly size of calendar changes to acomodate the month if false," +
219 " 42 day format is used", type="Boolean", defaultValue="false")
220 public void setAdjustWeeks(String adjustWeeks) {
221 this.adjustWeeks = adjustWeeks;
222 }
223
224 @StrutsTagAttribute(description="How to render the names of the days in the header(narrow, abbr or wide)", defaultValue="narrow")
225 public void setDayWidth(String dayWidth) {
226 this.dayWidth = dayWidth;
227 }
228
229 @StrutsTagAttribute(description="Total weeks to display", type="Integer", defaultValue="6")
230 public void setDisplayWeeks(String displayWeeks) {
231 this.displayWeeks = displayWeeks;
232 }
233
234 @StrutsTagAttribute(description="Last available date in the calendar set", type="Date", defaultValue="2941-10-12")
235 public void setEndDate(String endDate) {
236 this.endDate = endDate;
237 }
238
239 @StrutsTagAttribute(description="First available date in the calendar set", type="Date", defaultValue="1492-10-12")
240 public void setStartDate(String startDate) {
241 this.startDate = startDate;
242 }
243
244 @StrutsTagAttribute(description="Disable all incremental controls, must pick a date in the current display", type="Boolean", defaultValue="false")
245 public void setStaticDisplay(String staticDisplay) {
246 this.staticDisplay = staticDisplay;
247 }
248
249 @StrutsTagAttribute(description="Adjusts the first day of the week 0==Sunday..6==Saturday", type="Integer", defaultValue="0")
250 public void setWeekStartsOn(String weekStartsOn) {
251 this.weekStartsOn = weekStartsOn;
252 }
253
254 @StrutsTagAttribute(description="Language to display this widget in", defaultValue="brower's specified preferred language")
255 public void setLanguage(String language) {
256 this.language = language;
257 }
258
259 @StrutsTagAttribute(description="A pattern used for the visual display of the formatted date, e.g. dd/MM/yyyy")
260 public void setDisplayFormat(String displayFormat) {
261 this.displayFormat = displayFormat;
262 }
263
264 @StrutsTagAttribute(description="Type of formatting used for visual display. Possible values are " +
265 "long, short, medium or full", defaultValue="short")
266 public void setFormatLength(String formatLength) {
267 this.formatLength = formatLength;
268 }
269
270 @StrutsTagAttribute(description="Path to icon used for the dropdown")
271 public void setIconPath(String iconPath) {
272 this.iconPath = iconPath;
273 }
274
275 @StrutsTagAttribute(description="Duration of toggle in milliseconds", type="Integer", defaultValue="100")
276 public void setToggleDuration(String toggleDuration) {
277 this.toggleDuration = toggleDuration;
278 }
279
280 @StrutsTagAttribute(description="Defines the type of the picker on the dropdown. Possible values are 'date'" +
281 " for a DateTimePicker, and 'time' for a timePicker", defaultValue="date")
282 public void setType(String type) {
283 this.type = type;
284 }
285
286 @StrutsTagAttribute(description="oggle type of the dropdown. Possible values are plain,wipe,explode,fade", defaultValue="plain")
287 public void setToggleType(String toggleType) {
288 this.toggleType = toggleType;
289 }
290
291 @StrutsTagAttribute(description="Template css path")
292 public void setTemplateCssPath(String templateCssPath) {
293 this.templateCssPath = templateCssPath;
294 }
295
296 private String format(Object obj) {
297 if(obj == null)
298 return null;
299
300 if(obj instanceof Date) {
301 return MessageFormat.format(RFC3339_PATTERN, (Date) obj);
302 } else if(obj instanceof Calendar) {
303 return MessageFormat.format(RFC3339_PATTERN, ((Calendar) obj).getTime());
304 } else {
305
306 String dateStr = obj.toString();
307 if(dateStr.equalsIgnoreCase("today"))
308 return MessageFormat.format(RFC3339_PATTERN, new Date());
309
310 try {
311 Date date = null;
312 if(this.displayFormat != null) {
313 SimpleDateFormat format = new SimpleDateFormat(
314 (String) getParameters().get("displayFormat"));
315 date = format.parse(dateStr);
316 return MessageFormat.format(RFC3339_PATTERN, date);
317 } else {
318
319 return dateStr;
320 }
321 } catch (ParseException e) {
322 LOG.error("Could not parse date", e);
323 return dateStr;
324 }
325 }
326 }
327
328 }