001: /**********************************************************************************
002: * $URL: https://source.sakaiproject.org/svn/jsf/tags/sakai_2-4-1/widgets/src/java/org/sakaiproject/jsf/renderer/InputDateRenderer.java $
003: * $Id: InputDateRenderer.java 9278 2006-05-10 23:29:21Z ray@media.berkeley.edu $
004: ***********************************************************************************
005: *
006: * Copyright (c) 2005 The Sakai Foundation.
007: *
008: * Licensed under the Educational Community License, Version 1.0 (the "License");
009: * you may not use this file except in compliance with the License.
010: * You may obtain a copy of the License at
011: *
012: * http://www.opensource.org/licenses/ecl1.php
013: *
014: * Unless required by applicable law or agreed to in writing, software
015: * distributed under the License is distributed on an "AS IS" BASIS,
016: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: * See the License for the specific language governing permissions and
018: * limitations under the License.
019: *
020: **********************************************************************************/package org.sakaiproject.jsf.renderer;
021:
022: import java.io.IOException;
023: import java.text.ParseException;
024: import java.text.SimpleDateFormat;
025: import java.util.Date;
026: import java.util.Map;
027: import javax.faces.component.EditableValueHolder;
028: import javax.faces.component.UIComponent;
029: import javax.faces.component.UIInput;
030: import javax.faces.component.ValueHolder;
031: import javax.faces.context.FacesContext;
032: import javax.faces.context.ResponseWriter;
033: import javax.faces.render.Renderer;
034:
035: import org.sakaiproject.jsf.util.ConfigurationResource;
036: import org.sakaiproject.jsf.util.RendererUtil;
037:
038: /**
039: * <p>Description: </p>
040: * <p>Render the custom color picker control.</p>
041: * <p>Copyright: Copyright (c) 2004</p>
042: * <p>Organization: Sakai Project</p>
043: * @author Ed Smiley
044: * @version $id: $
045: * @todo handle showSeconds
046: */
047:
048: public class InputDateRenderer extends Renderer {
049: // calendar popup configuration
050: private static final String HEIGHT = "16";
051: private static final String WIDTH = "16";
052: private static final String CURSORSTYLE;
053: private static final String CLICKALT;
054: private static final String CALENDAR_PATH;
055: private static final String CALENDAR_ICON;
056: // input date and time configuration, from global resources
057: private static final boolean inputMonthFirst;
058: private static final boolean inputTimeColon;
059: private static final boolean inputTime24;
060: private static final boolean inputTimeSeconds = true; //todo
061: private static final String DATE_FORMAT_STRING;
062: private static final String TIME_FORMAT_STRING;
063: private static final SimpleDateFormat dateFormat;
064: private static final SimpleDateFormat timeFormat;
065: private static final SimpleDateFormat dateTimeFormat;
066: private static final String DATE_HINT;
067: private static final String TIME_HINT;
068:
069: // an admittedly long static intializer block
070: // the spec calls for a global setting for each installation
071: // much of this is taken up in calculating that in these gory details
072: static {
073: ConfigurationResource cr = new ConfigurationResource();
074: String resources = cr.get("resources");
075: CURSORSTYLE = cr.get("picker_style");
076: CALENDAR_PATH = "/" + resources + "/"
077: + cr.get("inputDatePopup");
078: CALENDAR_ICON = "/" + resources + "/"
079: + cr.get("inputDateImage");
080: CLICKALT = cr.get("date_pick_alt");
081: inputMonthFirst = "true".equals((String) cr
082: .get("inputMonthFirst"));
083: inputTimeColon = "true".equals((String) cr
084: .get("inputTimeColon"));
085: inputTime24 = "true".equals((String) cr.get("inputTime24"));
086: DATE_HINT = cr.get("inputDateHint");
087: TIME_HINT = cr.get("inputTimeHint");
088:
089: if (inputMonthFirst) {
090: DATE_FORMAT_STRING = cr.get("inputMonthFirstFormat");
091: } else {
092: DATE_FORMAT_STRING = cr.get("inputDayFirstFormat");
093: }
094: if (inputTimeColon) {
095: if (inputTime24) {
096: TIME_FORMAT_STRING = cr.get("inputTimeColonFormat24");
097: } else {
098: TIME_FORMAT_STRING = cr.get("inputTimeColonFormatAMPM");
099: }
100: } else {
101: if (inputTime24) {
102: TIME_FORMAT_STRING = cr.get("inputTimeDotFormat24");
103: } else {
104: TIME_FORMAT_STRING = cr.get("inputTimeDotFormatAMPM");
105: }
106: }
107: dateFormat = new SimpleDateFormat(DATE_FORMAT_STRING);
108: timeFormat = new SimpleDateFormat(TIME_FORMAT_STRING);
109: dateTimeFormat = new SimpleDateFormat(DATE_FORMAT_STRING + " "
110: + TIME_FORMAT_STRING);
111: }
112:
113: public boolean supportsComponentType(UIComponent component) {
114: return (component instanceof UIInput);
115: }
116:
117: /**
118: * decode the value
119: * @param context
120: * @param component
121: */
122: public void decode(FacesContext context, UIComponent component) {
123: if (RendererUtil.isDisabledOrReadonly(context, component)) {
124: return;
125: }
126: // get request parameters
127: Map requestParameterMap = context.getExternalContext()
128: .getRequestParameterMap();
129: String clientId = component.getClientId(context);
130:
131: String dateStr = (String) requestParameterMap.get(clientId
132: + "_date");
133: String timeStr = (String) requestParameterMap.get(clientId
134: + "_time");
135: if (dateStr == null && timeStr == null)
136: return;
137:
138: EditableValueHolder ev = (EditableValueHolder) component;
139: // create holder for subcomponent values
140: // Map dateParts = new HashMap();
141: // // get the subcomponent values
142: // // the hidden clientId maintains all the values togethr
143: //
144: // dateParts.put("clientId", clientId);
145: // dateParts.put("date", date);
146: // dateParts.put("time", time);
147: // // set the submitted value to the subcomponent value map
148: // ev.setSubmittedValue(dateParts);
149: Date date = null;
150: if (dateStr == null && timeStr != null) {
151: try {
152: date = timeFormat.parse(timeStr);
153: } catch (ParseException ex) {
154: //leave null
155: }
156: } else if (dateStr != null && timeStr == null) {
157: try {
158: date = dateFormat.parse(dateStr);
159: } catch (ParseException ex) {
160: //leave null
161: }
162: } else {
163: try {
164: date = dateTimeFormat.parse(dateStr + " " + timeStr);
165: } catch (ParseException ex) {
166: //leave null
167: }
168:
169: }
170:
171: ev.setSubmittedValue(date);
172: }
173:
174: /**
175: * <p>Faces render output method .</p>
176: * @param context <code>FacesContext</code> for the current request
177: * @param component <code>UIComponent</code> being rendered
178: *
179: * @throws IOException if an input/output error occurs
180: */
181: public void encodeEnd(FacesContext context, UIComponent component)
182: throws IOException {
183: if (RendererUtil.isDisabledOrReadonly(context, component)
184: || !component.isRendered()) {
185: return;
186: }
187:
188: ResponseWriter writer = context.getResponseWriter();
189: String clientId = component.getClientId(context);
190:
191: /////////////////////////////////////////////////////////
192: // VALUE HOLDER AND ATTRIBUTES
193: /////////////////////////////////////////////////////////
194: String dateString = "";
195: String timeString = "";
196: Date date = null;
197:
198: Date submittedValue = (Date) ((EditableValueHolder) component)
199: .getSubmittedValue();
200: if (submittedValue != null) {
201: date = submittedValue;
202: } else {
203: Object value = ((ValueHolder) component).getValue();
204: if (value instanceof Date) {
205: date = (Date) value;
206: } else if (value instanceof String) {
207: try {
208: date = dateTimeFormat.parse((String) value);
209: } catch (ParseException ex) {
210: // leave alone
211: }
212: }
213: }
214:
215: if (date != null) {
216: dateString = dateFormat.format(date);
217: timeString = timeFormat.format(date);
218: }
219:
220: // display options attributes
221: boolean showDate;
222: boolean showTime;
223: boolean showSecond;
224:
225: showDate = "true".equals((String) RendererUtil.getAttribute(
226: context, component, "showDate"));
227: showTime = "true".equals((String) RendererUtil.getAttribute(
228: context, component, "showTime"));
229: showSecond = "true".equals((String) RendererUtil.getAttribute(
230: context, component, "showSecond"));
231:
232: /////////////////////////////////////////////////////////
233: // RENDER DATE INPUT
234: /////////////////////////////////////////////////////////
235: if (showDate) {
236: writer.write("<i> " + DATE_HINT + " </i>");
237: String dateId = clientId + "_date";
238:
239: String type = "text";
240: writer.write("<input type=\"" + type + "\"" + " size=\""
241: + DATE_FORMAT_STRING.length() + "\"" + " name=\""
242: + dateId + "\"" + " id=\"" + dateId + "\""
243: + " value=\"" + dateString + "\"> ");
244:
245: // script creates unique javascript popup calendar object
246: String calRand = "cal" + ("" + Math.random()).substring(2);
247: String calendar;
248: if (inputMonthFirst) {
249: calendar = "calendar2";
250: } else {
251: calendar = "calendar1";
252: }
253: String calScript = "var " + calRand + " = new calendar2("
254: + "document.getElementById('" + dateId + "'));"
255: + "" + calRand + ".year_scroll = true;" + ""
256: + calRand + ".time_comp = false;";
257: // calendar icon with onclick to script
258: writer.write(" <img");
259: writer.write(" id=\"" + clientId + "_datePickerPopup"
260: + "\"");
261: writer.write(" width=\"" + WIDTH + "\"\n");
262: writer.write(" height=\"" + HEIGHT + "\"\n");
263: writer.write(" style=\"" + CURSORSTYLE + "\" ");
264: writer.write(" src=\"" + CALENDAR_ICON + "\"\n");
265: writer.write(" border=\"0\"\n");
266: writer.write(" onclick=");
267: writer.write("\"javascript:" + calScript + calRand
268: + ".popup('','" + CALENDAR_PATH + "');\"\n");
269: writer.write(" alt=\"" + CLICKALT + "\"\n");
270: writer.write(" />  \n");
271: }
272:
273: /////////////////////////////////////////////////////////
274: // RENDER TIME INPUT
275: /////////////////////////////////////////////////////////
276: if (showTime) {
277: writer.write("<i> " + TIME_HINT + " </i>");
278: String timeId = clientId + "_time";
279: writer.write("<input type=\"text\"" + " size=\""
280: + (DATE_FORMAT_STRING.length() + 1) + "\""
281: + " name=\"" + timeId + "\"" + " id=\"" + timeId
282: + "\"" + " value=\"" + timeString + "\"> ");
283: }
284:
285: }
286:
287: }
|