/*==========================================================================*\ | $Id: WCDateTextBox.java,v 1.2 2011/07/29 17:55:33 aallowat Exp $ |*-------------------------------------------------------------------------*| | Copyright (C) 2006-2009 Virginia Tech | | This file is part of Web-CAT. | | Web-CAT is free software; you can redistribute it and/or modify | it under the terms of the GNU Affero General Public License as published | by the Free Software Foundation; either version 3 of the License, or | (at your option) any later version. | | Web-CAT is distributed in the hope that it will be useful, | but WITHOUT ANY WARRANTY; without even the implied warranty of | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | GNU General Public License for more details. | | You should have received a copy of the GNU Affero General Public License | along with Web-CAT; if not, see <http://www.gnu.org/licenses/>. \*==========================================================================*/ package org.webcat.ui; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.TimeZone; import org.webcat.ui._base.DojoFormElement; import org.webcat.ui.util.DojoUtils; import org.webcat.ui.util.JSHash; import com.webobjects.appserver.WOAssociation; import com.webobjects.appserver.WOContext; import com.webobjects.appserver.WOElement; import com.webobjects.appserver.WOResponse; import com.webobjects.foundation.NSDictionary; import com.webobjects.foundation.NSMutableDictionary; import com.webobjects.foundation.NSTimestamp; // ------------------------------------------------------------------------ /** * A text box that lets the user enter the text representation of a date, and * also provides a pop-up calendar when clicked that can be navigated. * <p> * Corresponds to Dojo type {@code dijit.form.DateTextBox}. * * <h2>Bindings</h2> * <ul> * <li> {@code value}: An {@link NSTimestamp} object representing the date to be * displayed in the text box * <li> {@code dateformat}: A date format string, as described in * {@link NSTimestampFormatter} * <li> {@code timeZone}: A {@link TimeZone} object defining the time zone * for localizing the date * </ul> * * @author Tony Allevato * @author Last changed by $Author: aallowat $ * @version $Revision: 1.2 $, $Date: 2011/07/29 17:55:33 $ */ public class WCDateTextBox extends DojoFormElement { //~ Constructor ........................................................... // ---------------------------------------------------------- public WCDateTextBox(String name, NSDictionary<String, WOAssociation> someAssociations, WOElement template) { super("input", someAssociations, template); _dateformat = _associations.removeObjectForKey("dateformat"); _timeZone = _associations.removeObjectForKey("timeZone"); } //~ Methods ............................................................... // ---------------------------------------------------------- public String inputTypeInContext(WOContext context) { return "text"; } // ---------------------------------------------------------- @Override public String dojoType() { return "dijit.form.DateTextBox"; } // ---------------------------------------------------------- @Override protected String stringValueForObject(Object value, WOContext context) { // Append the date set in the value binding, if it exists. Dojo // requires that this be string in ISO date format, so we convert it // before writing it out. synchronized (ISO_DATE_FORMAT) { if (_timeZone != null) { TimeZone tz = (TimeZone)_timeZone.valueInComponent(context.component()); if (tz != null) { ISO_DATE_FORMAT.setTimeZone(tz); } else { ISO_DATE_FORMAT.setTimeZone(TimeZone.getDefault()); } } else { ISO_DATE_FORMAT.setTimeZone(TimeZone.getDefault()); } return ISO_DATE_FORMAT.format(value); } } // ---------------------------------------------------------- @Override protected Object objectForStringValue(String stringValue, WOContext context) { // When Dojo populates the shadowed text field with the selected date, // it always formats it in ISO date format. Object object; if (stringValue == null) { object = null; } else { synchronized (ISO_DATE_FORMAT) { if (_timeZone != null) { TimeZone tz = (TimeZone)_timeZone.valueInComponent( context.component()); if (tz != null) { ISO_DATE_FORMAT.setTimeZone(tz); } else { ISO_DATE_FORMAT.setTimeZone(TimeZone.getDefault()); } } else { ISO_DATE_FORMAT.setTimeZone(TimeZone.getDefault()); } try { object = new NSTimestamp( ISO_DATE_FORMAT.parse(stringValue)); } catch (ParseException e) { object = null; } } } return object; } // ---------------------------------------------------------- @Override public JSHash additionalConstraints(WOContext context) { // Append constraints based on the date format, if one was provided. JSHash manualConstraints = new JSHash(); if (_dateformat != null) { String dateFormat = (String)_dateformat.valueInComponent(context.component()); if (dateFormat != null) { manualConstraints.put("datePattern", dateFormatToDatePattern(dateFormat)); } } return manualConstraints; } // ---------------------------------------------------------- /** * Converts an NSTimestampFormatter string into a JavaScript date format * string. This allows the dateformat binding to be used by Dojo for * validation. * * Only the following format tokens from NSTimestampFormatter are * translatable to a JavaScript format, and are therefore the only ones that * can be reliably used in a DateTextBox dateformat: %%, %a, %A, %b, %B, %d, * %e, %H, %I, %m, %M, %p, %y, %Y * * @param dateFormat * the NSTimestampFormatter date format string * @return a JavaScript date format string that is as close as possible to * the specified NSTimestampFormatter string */ protected static String dateFormatToDatePattern(String dateFormat) { StringBuilder datePattern = new StringBuilder(32); int i = 0; while (i < dateFormat.length()) { char ch = dateFormat.charAt(i); if (ch == '%') { i++; ch = dateFormat.charAt(i); switch (ch) { // Literal percent case '%': datePattern.append('%'); break; // Abbreviated weekday name case 'a': datePattern.append('E'); break; // Full weekday name case 'A': datePattern.append("EE"); break; // Abbreviated month name case 'b': datePattern.append("MMM"); break; // Full month name case 'B': datePattern.append("MMMM"); break; // Day of the month as a decimal number, leading 0 case 'd': datePattern.append("dd"); break; // Day of the month as a decimal number, no leading 0 case 'e': datePattern.append('d'); break; // 24-hour clock, 00-23 case 'H': datePattern.append("HH"); break; // 12-hour clock, 01-12 case 'I': datePattern.append('h'); break; // Month as decimal number, 01-12 case 'm': datePattern.append('M'); break; // Minute as decimal number, 00-59 case 'M': datePattern.append("mm"); break; // AM/PM designation case 'p': datePattern.append('a'); break; // Year without century, 00-99 case 'y': datePattern.append("yy"); break; // Yeah with century case 'Y': datePattern.append("yyyy"); break; } } else { datePattern.append(ch); } i++; } return datePattern.toString(); } //~ Static/instance variables ............................................. protected static final SimpleDateFormat ISO_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); protected WOAssociation _dateformat; protected WOAssociation _timeZone; }