0001: /*
0002: * Version: MPL 1.1/GPL 2.0/LGPL 2.1
0003: *
0004: * "The contents of this file are subject to the Mozilla Public License
0005: * Version 1.1 (the "License"); you may not use this file except in
0006: * compliance with the License. You may obtain a copy of the License at
0007: * http://www.mozilla.org/MPL/
0008: *
0009: * Software distributed under the License is distributed on an "AS IS"
0010: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
0011: * License for the specific language governing rights and limitations under
0012: * the License.
0013: *
0014: * The Original Code is ICEfaces 1.5 open source software code, released
0015: * November 5, 2006. The Initial Developer of the Original Code is ICEsoft
0016: * Technologies Canada, Corp. Portions created by ICEsoft are Copyright (C)
0017: * 2004-2006 ICEsoft Technologies Canada, Corp. All Rights Reserved.
0018: *
0019: * Contributor(s): _____________________.
0020: *
0021: * Alternatively, the contents of this file may be used under the terms of
0022: * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"
0023: * License), in which case the provisions of the LGPL License are
0024: * applicable instead of those above. If you wish to allow use of your
0025: * version of this file only under the terms of the LGPL License and not to
0026: * allow others to use your version of this file under the MPL, indicate
0027: * your decision by deleting the provisions above and replace them with
0028: * the notice and other provisions required by the LGPL License. If you do
0029: * not delete the provisions above, a recipient may use your version of
0030: * this file under either the MPL or the LGPL License."
0031: *
0032: */
0033: /* Original Copyright
0034: * Copyright 2004 The Apache Software Foundation.
0035: *
0036: * Licensed under the Apache License, Version 2.0 (the "License");
0037: * you may not use this file except in compliance with the License.
0038: * You may obtain a copy of the License at
0039: *
0040: * http://www.apache.org/licenses/LICENSE-2.0
0041: *
0042: * Unless required by applicable law or agreed to in writing, software
0043: * distributed under the License is distributed on an "AS IS" BASIS,
0044: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0045: * See the License for the specific language governing permissions and
0046: * limitations under the License.
0047: */
0048: package com.icesoft.faces.component.selectinputdate;
0049:
0050: import com.icesoft.faces.context.BridgeFacesContext;
0051: import com.icesoft.faces.context.effects.JavascriptContext;
0052: import com.icesoft.faces.component.CSS_DEFAULT;
0053: import com.icesoft.faces.component.ext.HtmlCommandLink;
0054: import com.icesoft.faces.component.ext.HtmlGraphicImage;
0055: import com.icesoft.faces.component.ext.HtmlOutputText;
0056: import com.icesoft.faces.component.ext.renderkit.FormRenderer;
0057: import com.icesoft.faces.component.util.CustomComponentUtils;
0058: import com.icesoft.faces.context.DOMContext;
0059: import com.icesoft.faces.renderkit.dom_html_basic.DomBasicInputRenderer;
0060: import com.icesoft.faces.renderkit.dom_html_basic.HTML;
0061: import com.icesoft.faces.renderkit.dom_html_basic.PassThruAttributeRenderer;
0062: import com.icesoft.faces.util.CoreUtils;
0063: import org.apache.commons.logging.Log;
0064: import org.apache.commons.logging.LogFactory;
0065: import org.w3c.dom.Element;
0066: import org.w3c.dom.NodeList;
0067: import org.w3c.dom.Text;
0068:
0069: import javax.faces.component.NamingContainer;
0070: import javax.faces.component.UIComponent;
0071: import javax.faces.component.UIInput;
0072: import javax.faces.component.UIParameter;
0073: import javax.faces.component.UIViewRoot;
0074: import javax.faces.context.FacesContext;
0075: import javax.faces.context.ResponseWriter;
0076: import javax.faces.convert.Converter;
0077: import javax.faces.convert.ConverterException;
0078: import java.io.IOException;
0079: import java.text.DateFormat;
0080: import java.text.DateFormatSymbols;
0081: import java.text.ParseException;
0082: import java.text.SimpleDateFormat;
0083: import java.util.Calendar;
0084: import java.util.Date;
0085: import java.util.Locale;
0086: import java.util.Map;
0087: import java.util.regex.Matcher;
0088: import java.util.regex.Pattern;
0089:
0090: /**
0091: * <p> The SelectInputDateRenderer class is an ICEfaces D2D renderer for the
0092: * SelectInputDate component. Note: This class originally was derived from the
0093: * MyFaces Calendar.</p>
0094: */
0095: public class SelectInputDateRenderer extends DomBasicInputRenderer {
0096: // add a static log member
0097: private static final Log log = LogFactory
0098: .getLog(SelectInputDateRenderer.class);
0099:
0100: private final String CALENDAR_TABLE = "_calendarTable";
0101: private final String CALENDAR_BUTTON = "_calendarButton";
0102: private final String CALENDAR_POPUP = "_calendarPopup";
0103: private final String HIDDEN_FIELD_NAME = "showPopup";
0104: private final String DATE_SELECTED = "dateSelected";
0105:
0106: // constants for navigation link ids
0107: private final String PREV_MONTH = "_prevmo";
0108: private final String NEXT_MONTH = "_nextmo";
0109: private final String PREV_YEAR = "_prevyr";
0110: private final String NEXT_YEAR = "_nextyr";
0111:
0112: // constant for selectinputdate links
0113: private final String CALENDAR = "_calendar";
0114:
0115: // arrays of week days and month names
0116: String[] weekdays = new String[7];
0117: String[] weekdaysLong = new String[7];
0118: String[] months = new String[12];
0119:
0120: // store the current locale
0121: Locale currentLocale = null;
0122:
0123: /* (non-Javadoc)
0124: * @see javax.faces.render.Renderer#getRendersChildren()
0125: */
0126: public boolean getRendersChildren() {
0127:
0128: return true;
0129: }
0130:
0131: /* (non-Javadoc)
0132: * @see javax.faces.render.Renderer#encodeChildren(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
0133: */
0134: public void encodeChildren(FacesContext facesContext,
0135: UIComponent uiComponent) {
0136:
0137: }
0138:
0139: private String getHiddenFieldName(FacesContext facesContext,
0140: UIComponent uiComponent) {
0141: UIComponent form = findForm(uiComponent);
0142: String formId = form.getClientId(facesContext);
0143: String clientId = uiComponent.getClientId(facesContext);
0144: String hiddenFieldName = formId
0145: + NamingContainer.SEPARATOR_CHAR
0146: + UIViewRoot.UNIQUE_ID_PREFIX + clientId
0147: + HIDDEN_FIELD_NAME;
0148: return hiddenFieldName;
0149: }
0150:
0151: /* (non-Javadoc)
0152: * @see com.icesoft.faces.renderkit.dom_html_basic.DomBasicRenderer#encodeEnd(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
0153: */
0154: public void encodeEnd(FacesContext facesContext,
0155: UIComponent uiComponent) throws IOException {
0156: validateParameters(facesContext, uiComponent,
0157: SelectInputDate.class);
0158: DOMContext domContext = DOMContext.attachDOMContext(
0159: facesContext, uiComponent);
0160: SelectInputDate selectInputDate = (SelectInputDate) uiComponent;
0161:
0162: // get the parentForm
0163: UIComponent parentForm = findForm(selectInputDate);
0164: // if there is no parent form - ERROR
0165: if (parentForm == null) {
0166: log.error("SelectInputDate::must be in a FORM");
0167: return;
0168: }
0169: String clientId;
0170: if (!domContext.isInitialized()) {
0171: Element root = domContext.createRootElement(HTML.DIV_ELEM);
0172: boolean popupState = selectInputDate.isShowPopup();
0173:
0174: setRootElementId(facesContext, root, uiComponent);
0175: clientId = uiComponent.getClientId(facesContext);
0176: if (selectInputDate.isRenderAsPopup()) {
0177: if (log.isTraceEnabled()) {
0178: log.trace("Render as popup");
0179: }
0180: Element dateText = domContext
0181: .createElement(HTML.INPUT_ELEM);
0182: dateText.setAttribute(HTML.VALUE_ATTR, selectInputDate
0183: .formatDate((Date) selectInputDate.getValue()));
0184: dateText.setAttribute(HTML.ID_ATTR, clientId
0185: + SelectInputDate.CALENDAR_INPUTTEXT);
0186: dateText.setAttribute(HTML.NAME_ATTR, clientId
0187: + SelectInputDate.CALENDAR_INPUTTEXT);
0188: dateText.setAttribute(HTML.CLASS_ATTR, selectInputDate
0189: .getCalendarInputClass());
0190: dateText.setAttribute(HTML.ONFOCUS_ATTR,
0191: "setFocus('');");
0192: dateText.setAttribute("onkeypress", this .ICESUBMIT);
0193: dateText.setAttribute(HTML.ONBLUR_ATTR, "setFocus('');"
0194: + this .ICESUBMITPARTIAL);
0195: if (selectInputDate.getAutocomplete() != null) {
0196: dateText.setAttribute("autocomplete",
0197: selectInputDate.getAutocomplete());
0198: }
0199: // extract the popupdate format and use it as a tooltip
0200: String tooltip = selectInputDate.getPopupDateFormat();
0201: dateText.setAttribute(HTML.TITLE_ATTR, "Date Format: "
0202: + tooltip);
0203: root.appendChild(dateText);
0204: Element calendarButton = domContext
0205: .createElement(HTML.INPUT_ELEM);
0206: calendarButton.setAttribute(HTML.ID_ATTR, clientId
0207: + CALENDAR_BUTTON);
0208: calendarButton.setAttribute(HTML.NAME_ATTR, clientId
0209: + CALENDAR_BUTTON);
0210: calendarButton.setAttribute(HTML.TYPE_ATTR, "image");
0211: calendarButton.setAttribute(HTML.ONFOCUS_ATTR,
0212: "setFocus('');");
0213: // render onclick to set value of hidden field to true
0214: String onClick = "document.forms['"
0215: + parentForm.getClientId(facesContext) + "']['"
0216: + this .getLinkId(facesContext, uiComponent)
0217: + "'].value='" + clientId + CALENDAR_BUTTON
0218: + "';" + "document.forms['"
0219: + parentForm.getClientId(facesContext) + "']['"
0220: + getHiddenFieldName(facesContext, uiComponent)
0221: + "'].value='toggle';"
0222: + "iceSubmitPartial( document.forms['"
0223: + parentForm.getClientId(facesContext)
0224: + "'], this,event); return false;";
0225: calendarButton.setAttribute(HTML.ONCLICK_ATTR, onClick);
0226: root.appendChild(calendarButton);
0227: // render a hidden field to manage the popup state; visible || hidden
0228: FormRenderer.addHiddenField(facesContext,
0229: getHiddenFieldName(facesContext, uiComponent));
0230: if (popupState) {
0231:
0232: String resolvedSrc = CoreUtils.resolveResourceURL(
0233: facesContext, selectInputDate.getImageDir()
0234: + selectInputDate
0235: .getClosePopupImage());
0236: calendarButton.setAttribute(HTML.SRC_ATTR,
0237: resolvedSrc);
0238: calendarButton.setAttribute(HTML.ALT_ATTR,
0239: "Close Popup Calendar");
0240: calendarButton.setAttribute(HTML.TITLE_ATTR,
0241: "Close Popup Calendar");
0242: } else {
0243: String resolvedSrc = CoreUtils.resolveResourceURL(
0244: facesContext, selectInputDate.getImageDir()
0245: + selectInputDate
0246: .getOpenPopupImage());
0247: calendarButton.setAttribute(HTML.SRC_ATTR,
0248: resolvedSrc);
0249: calendarButton.setAttribute(HTML.ALT_ATTR,
0250: "Open Popup Calendar");
0251: calendarButton.setAttribute(HTML.TITLE_ATTR,
0252: "Open Popup Calendar");
0253: FormRenderer.addHiddenField(facesContext,
0254: parentForm.getClientId(facesContext)
0255: + ":_idcl");
0256: domContext.stepOver();
0257: return;
0258: }
0259:
0260: if (!domContext.isStreamWriting()) {
0261: Text br = domContext.createTextNode("<br/>");
0262: root.appendChild(br);
0263: }
0264:
0265: Element calendarDiv = domContext
0266: .createElement(HTML.DIV_ELEM);
0267: calendarDiv.setAttribute(HTML.ID_ATTR, clientId
0268: + CALENDAR_POPUP);
0269: calendarDiv.setAttribute(HTML.NAME_ATTR, clientId
0270: + CALENDAR_POPUP);
0271: calendarDiv.setAttribute(HTML.STYLE_ELEM,
0272: "position:absolute;z-index:10;");
0273: calendarDiv
0274: .setAttribute(HTML.TITLE_ATTR,
0275: "A Popup Calendar where a date can be selected.");
0276: Element table = domContext
0277: .createElement(HTML.TABLE_ELEM);
0278: table.setAttribute(HTML.ID_ATTR, clientId
0279: + CALENDAR_TABLE);
0280: table.setAttribute(HTML.NAME_ATTR, clientId
0281: + CALENDAR_TABLE);
0282: table.setAttribute(HTML.CLASS_ATTR, selectInputDate
0283: .getStyleClass());
0284: table.setAttribute(HTML.STYLE_ATTR,
0285: "position:absolute;");
0286: table.setAttribute(HTML.CELLPADDING_ATTR, "0");
0287: table.setAttribute(HTML.CELLSPACING_ATTR, "0");
0288: // set mouse events on table bug 372
0289: String mouseOver = selectInputDate.getOnmouseover();
0290: table.setAttribute(HTML.ONMOUSEOVER_ATTR, mouseOver);
0291: String mouseOut = selectInputDate.getOnmouseout();
0292: table.setAttribute(HTML.ONMOUSEOUT_ATTR, mouseOut);
0293: String mouseMove = selectInputDate.getOnmousemove();
0294: table.setAttribute(HTML.ONMOUSEMOVE_ATTR, mouseMove);
0295: table
0296: .setAttribute(HTML.SUMMARY_ATTR,
0297: "This table contains a Calendar where a date can be selected.");
0298: calendarDiv.appendChild(table);
0299: Text iframe = domContext
0300: .createTextNode("<!--[if lte IE"
0301: + " 6.5]><iframe src='"
0302: + CoreUtils.resolveResourceURL(
0303: FacesContext
0304: .getCurrentInstance(),
0305: "/xmlhttp/blank")
0306: + "' class=\"iceSelInpDateIFrameFix\"></iframe><![endif]-->");
0307: calendarDiv.appendChild(iframe);
0308: root.appendChild(calendarDiv);
0309:
0310: } else {
0311: if (log.isTraceEnabled()) {
0312: log.trace("Select input Date Normal");
0313: }
0314: Element table = domContext
0315: .createElement(HTML.TABLE_ELEM);
0316: table.setAttribute(HTML.ID_ATTR, clientId
0317: + CALENDAR_TABLE);
0318: table.setAttribute(HTML.NAME_ATTR, clientId
0319: + CALENDAR_TABLE);
0320: table.setAttribute(HTML.CLASS_ATTR, selectInputDate
0321: .getStyleClass());
0322: table.setAttribute(HTML.CELLPADDING_ATTR, "0");
0323: table.setAttribute(HTML.CELLSPACING_ATTR, "0");
0324: // set mouse events on table bug 372
0325: String mouseOver = selectInputDate.getOnmouseover();
0326: table.setAttribute(HTML.ONMOUSEOVER_ATTR, mouseOver);
0327: String mouseOut = selectInputDate.getOnmouseout();
0328: table.setAttribute(HTML.ONMOUSEOUT_ATTR, mouseOut);
0329: String mouseMove = selectInputDate.getOnmousemove();
0330: table.setAttribute(HTML.ONMOUSEMOVE_ATTR, mouseMove);
0331: table
0332: .setAttribute(HTML.SUMMARY_ATTR,
0333: "This table contains a Calendar where a date can be selected.");
0334: root.appendChild(table);
0335: }
0336: }
0337: clientId = uiComponent.getClientId(facesContext);
0338: currentLocale = facesContext.getViewRoot().getLocale();
0339:
0340: Date value;
0341:
0342: if (selectInputDate.isNavEvent()) {
0343: if (log.isTraceEnabled()) {
0344: log.trace("Rendering Nav Event");
0345: }
0346: value = selectInputDate.getNavDate();
0347: } else {
0348: if (log.isTraceEnabled()) {
0349: log.trace("Logging non nav event");
0350: }
0351: try {
0352: Converter converter = getConverter(selectInputDate);
0353: if (converter instanceof DateConverter) {
0354: value = ((DateConverter) converter).getAsDate(
0355: facesContext, uiComponent);
0356: } else {
0357: value = CustomComponentUtils
0358: .getDateValue(selectInputDate);
0359: }
0360: } catch (IllegalArgumentException illegalArgumentException) {
0361: value = null;
0362: }
0363: }
0364:
0365: Calendar timeKeeper = Calendar.getInstance(currentLocale);
0366: timeKeeper.setTime(value != null ? value : new Date());
0367:
0368: DateFormatSymbols symbols = new DateFormatSymbols(currentLocale);
0369:
0370: weekdays = mapWeekdays(symbols);
0371: weekdaysLong = mapWeekdaysLong(symbols);
0372: months = mapMonths(symbols);
0373:
0374: // use the currentDay to set focus - do not set
0375: int lastDayInMonth = timeKeeper
0376: .getActualMaximum(Calendar.DAY_OF_MONTH);
0377: int currentDay = timeKeeper.get(Calendar.DAY_OF_MONTH); // starts at 1
0378:
0379: if (currentDay > lastDayInMonth) {
0380: currentDay = lastDayInMonth;
0381: }
0382:
0383: // get the current date value from the selectinputdate
0384: Object currentValue = selectInputDate.getValue();
0385:
0386: timeKeeper.set(Calendar.DAY_OF_MONTH, 1);
0387:
0388: int weekDayOfFirstDayOfMonth = mapCalendarDayToCommonDay(timeKeeper
0389: .get(Calendar.DAY_OF_WEEK));
0390:
0391: int weekStartsAtDayIndex = mapCalendarDayToCommonDay(timeKeeper
0392: .getFirstDayOfWeek());
0393:
0394: // do not require a writer - clean out all methods that reference a writer
0395: ResponseWriter writer = facesContext.getResponseWriter();
0396:
0397: Element root = (Element) domContext.getRootNode();
0398:
0399: if (selectInputDate.isRenderAsPopup()) {
0400: if (log.isTraceEnabled()) {
0401: log.trace("SelectInputDate as Popup");
0402: }
0403:
0404: // assumption input text is first child
0405: Element dateText = (Element) root.getFirstChild();
0406:
0407: if (currentValue != null) {
0408: dateText.setAttribute(HTML.VALUE_ATTR, selectInputDate
0409: .formatDate((Date) currentValue));
0410: }
0411:
0412: // get tables , our table is the first and only one
0413: NodeList tables = root
0414: .getElementsByTagName(HTML.TABLE_ELEM);
0415: // assumption we want the first table in tables. there should only be one
0416: Element table = (Element) tables.item(0);
0417:
0418: PassThruAttributeRenderer.renderAttributes(facesContext,
0419: uiComponent, null);
0420:
0421: Element tr1 = domContext.createElement(HTML.TR_ELEM);
0422:
0423: table.appendChild(tr1);
0424: writeMonthYearHeader(domContext, facesContext, writer,
0425: selectInputDate, timeKeeper, currentDay, weekdays,
0426: months, tr1, selectInputDate.getMonthYearRowClass());
0427:
0428: Element tr2 = domContext.createElement(HTML.TR_ELEM);
0429: table.appendChild(tr2);
0430:
0431: writeWeekDayNameHeader(domContext, weekStartsAtDayIndex,
0432: weekdays, facesContext, writer, selectInputDate,
0433: tr2, selectInputDate.getWeekRowClass());
0434:
0435: writeDays(domContext, facesContext, writer,
0436: selectInputDate, timeKeeper, currentDay,
0437: weekStartsAtDayIndex, weekDayOfFirstDayOfMonth,
0438: lastDayInMonth, weekdays, table);
0439:
0440: } else {
0441: if (log.isTraceEnabled()) {
0442: log.trace("renderNormal::endcodeEnd");
0443: }
0444: // assume table is the first child
0445: Element table = (Element) root.getFirstChild();
0446:
0447: PassThruAttributeRenderer.renderAttributes(facesContext,
0448: uiComponent, null);
0449:
0450: Element tr1 = domContext.createElement(HTML.TR_ELEM);
0451: table.appendChild(tr1);
0452:
0453: writeMonthYearHeader(domContext, facesContext, writer,
0454: selectInputDate, timeKeeper, currentDay, weekdays,
0455: months, tr1, selectInputDate.getMonthYearRowClass());
0456:
0457: Element tr2 = domContext.createElement(HTML.TR_ELEM);
0458:
0459: writeWeekDayNameHeader(domContext, weekStartsAtDayIndex,
0460: weekdays, facesContext, writer, selectInputDate,
0461: tr2, selectInputDate.getWeekRowClass());
0462:
0463: table.appendChild(tr2);
0464:
0465: writeDays(domContext, facesContext, writer,
0466: selectInputDate, timeKeeper, currentDay,
0467: weekStartsAtDayIndex, weekDayOfFirstDayOfMonth,
0468: lastDayInMonth, weekdays, table);
0469:
0470: }
0471:
0472: // purge child components as they have been encoded no need to keep them around
0473: selectInputDate.getChildren().removeAll(
0474: selectInputDate.getChildren());
0475:
0476: // steps to the position where the next sibling should be rendered
0477: domContext.stepOver();
0478: domContext.streamWrite(facesContext, uiComponent);
0479: }
0480:
0481: private void writeMonthYearHeader(DOMContext domContext,
0482: FacesContext facesContext, ResponseWriter writer,
0483: SelectInputDate inputComponent, Calendar timeKeeper,
0484: int currentDay, String[] weekdays, String[] months,
0485: Element headerTr, String styleClass) throws IOException {
0486:
0487: Element table = domContext.createElement(HTML.TABLE_ELEM);
0488: table.setAttribute(HTML.CELLPADDING_ATTR, "0");
0489: table.setAttribute(HTML.CELLSPACING_ATTR, "0");
0490: table.setAttribute(HTML.WIDTH_ATTR, "100%");
0491: table.setAttribute(HTML.SUMMARY_ATTR,
0492: "Month Year navigation header");
0493:
0494: Element tr = domContext.createElement(HTML.TR_ELEM);
0495:
0496: Element headertd = domContext.createElement(HTML.TD_ELEM);
0497: table.appendChild(tr);
0498: headertd.appendChild(table);
0499: headerTr.appendChild(headertd);
0500:
0501: headertd.setAttribute(HTML.COLSPAN_ATTR, "7"); // weekdays.length = 7
0502:
0503: // first render month with navigation back and forward
0504: Calendar cal = shiftMonth(facesContext, timeKeeper, currentDay,
0505: -1);
0506: writeCell(domContext, facesContext, writer, inputComponent,
0507: "<", cal.getTime(), styleClass, tr,
0508: ((SelectInputDate) inputComponent).getImageDir()
0509: + ((SelectInputDate) inputComponent)
0510: .getMovePreviousImage(), -1);
0511:
0512: Element td = domContext.createElement(HTML.TD_ELEM);
0513: td.setAttribute(HTML.CLASS_ATTR, styleClass);
0514: td.setAttribute(HTML.WIDTH_ATTR, "40%");
0515: Text text = domContext.createTextNode(months[timeKeeper
0516: .get(Calendar.MONTH)]
0517: + "");
0518: td.appendChild(text);
0519:
0520: tr.appendChild(td);
0521:
0522: cal = shiftMonth(facesContext, timeKeeper, currentDay, 1);
0523: int calYear = cal.get(Calendar.YEAR);
0524:
0525: if (inputComponent.getHightlightRules().containsKey(
0526: Calendar.YEAR + "$" + calYear)) {
0527: inputComponent.setHighlightYearClass(inputComponent
0528: .getHightlightRules().get(
0529: Calendar.YEAR + "$" + calYear)
0530: + " ");
0531: } else {
0532: inputComponent.setHighlightYearClass("");
0533: }
0534:
0535: int calMonth = cal.get(Calendar.MONTH);
0536: if (inputComponent.getHightlightRules().containsKey(
0537: Calendar.MONTH + "$" + calMonth)) {
0538: inputComponent.setHighlightMonthClass(inputComponent
0539: .getHightlightRules().get(
0540: Calendar.MONTH + "$" + calMonth)
0541: + " ");
0542: } else {
0543: inputComponent.setHighlightMonthClass("");
0544: }
0545: writeCell(domContext, facesContext, writer, inputComponent,
0546: ">", cal.getTime(), styleClass, tr,
0547: ((SelectInputDate) inputComponent).getImageDir()
0548: + ((SelectInputDate) inputComponent)
0549: .getMoveNextImage(), -1);
0550:
0551: // second add an empty td
0552: Element emptytd = domContext.createElement(HTML.TD_ELEM);
0553: emptytd.setAttribute(HTML.CLASS_ATTR, styleClass);
0554: Text emptytext = domContext.createTextNode("");
0555: emptytd.appendChild(emptytext);
0556:
0557: tr.appendChild(emptytd);
0558:
0559: // third render year with navigation back and forward
0560: cal = shiftYear(facesContext, timeKeeper, currentDay, -1);
0561:
0562: writeCell(domContext, facesContext, writer, inputComponent,
0563: "<<", cal.getTime(), styleClass, tr,
0564: ((SelectInputDate) inputComponent).getImageDir()
0565: + ((SelectInputDate) inputComponent)
0566: .getMovePreviousImage(), -1);
0567:
0568: Element yeartd = domContext.createElement(HTML.TD_ELEM);
0569: yeartd.setAttribute(HTML.CLASS_ATTR, styleClass);
0570: Text yeartext = domContext.createTextNode(""
0571: + timeKeeper.get(Calendar.YEAR));
0572: yeartd.appendChild(yeartext);
0573:
0574: tr.appendChild(yeartd);
0575:
0576: cal = shiftYear(facesContext, timeKeeper, currentDay, 1);
0577:
0578: writeCell(domContext, facesContext, writer, inputComponent,
0579: ">>", cal.getTime(), styleClass, tr,
0580: ((SelectInputDate) inputComponent).getImageDir()
0581: + ((SelectInputDate) inputComponent)
0582: .getMoveNextImage(), -1);
0583:
0584: }
0585:
0586: private Calendar shiftMonth(FacesContext facesContext,
0587: Calendar timeKeeper, int currentDay, int shift) {
0588: Calendar cal = copyCalendar(facesContext, timeKeeper);
0589:
0590: cal.set(Calendar.MONTH, cal.get(Calendar.MONTH) + shift);
0591:
0592: if (currentDay > cal.getActualMaximum(Calendar.DAY_OF_MONTH)) {
0593: currentDay = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
0594: }
0595:
0596: cal.set(Calendar.DAY_OF_MONTH, currentDay);
0597: return cal;
0598: }
0599:
0600: private Calendar shiftYear(FacesContext facesContext,
0601: Calendar timeKeeper, int currentDay, int shift) {
0602: Calendar cal = copyCalendar(facesContext, timeKeeper);
0603:
0604: cal.set(Calendar.YEAR, cal.get(Calendar.YEAR) + shift);
0605:
0606: if (currentDay > cal.getActualMaximum(Calendar.DAY_OF_MONTH)) {
0607: currentDay = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
0608: }
0609:
0610: cal.set(Calendar.DAY_OF_MONTH, currentDay);
0611: return cal;
0612: }
0613:
0614: private Calendar copyCalendar(FacesContext facesContext,
0615: Calendar timeKeeper) {
0616: Calendar cal = Calendar.getInstance(facesContext.getViewRoot()
0617: .getLocale());
0618: cal = (Calendar) timeKeeper.clone();
0619: return cal;
0620: }
0621:
0622: private void writeWeekDayNameHeader(DOMContext domContext,
0623: int weekStartsAtDayIndex, String[] weekdays,
0624: FacesContext facesContext, ResponseWriter writer,
0625: UIInput inputComponent, Element tr, String styleClass)
0626: throws IOException {
0627: // the week can start with Sunday (index 0) or Monday (index 1)
0628: for (int i = weekStartsAtDayIndex; i < weekdays.length; i++) {
0629: writeCell(domContext, facesContext, writer, inputComponent,
0630: weekdays[i], null, styleClass, tr, null, i);
0631: }
0632:
0633: // if week start on Sunday this block is not executed
0634: // if week start on Monday this block will run once adding Sunday to End of week.
0635: for (int i = 0; i < weekStartsAtDayIndex; i++) {
0636: writeCell(domContext, facesContext, writer, inputComponent,
0637: weekdays[i], null, styleClass, tr, null, i);
0638: }
0639: }
0640:
0641: private void writeDays(DOMContext domContext,
0642: FacesContext facesContext, ResponseWriter writer,
0643: SelectInputDate inputComponent, Calendar timeKeeper,
0644: int currentDay, int weekStartsAtDayIndex,
0645: int weekDayOfFirstDayOfMonth, int lastDayInMonth,
0646: String[] weekdays, Element table) throws IOException {
0647: Calendar cal;
0648:
0649: int space = (weekStartsAtDayIndex < weekDayOfFirstDayOfMonth) ? (weekDayOfFirstDayOfMonth - weekStartsAtDayIndex)
0650: : (weekdays.length - weekStartsAtDayIndex + weekDayOfFirstDayOfMonth);
0651:
0652: if (space == weekdays.length) {
0653: space = 0;
0654: }
0655:
0656: int columnIndexCounter = 0;
0657:
0658: Element tr1 = null;
0659: for (int i = 0; i < space; i++) {
0660: if (columnIndexCounter == 0) {
0661: tr1 = domContext.createElement(HTML.TR_ELEM);
0662: table.appendChild(tr1);
0663: }
0664:
0665: writeCell(domContext, facesContext, writer, inputComponent,
0666: "", null, inputComponent.getDayCellClass(), tr1,
0667: null, i);
0668: columnIndexCounter++;
0669: }
0670:
0671: Element tr2 = null;
0672: for (int i = 0; i < lastDayInMonth; i++) {
0673: if (columnIndexCounter == 0) {
0674: // don't create a new row until we have finished the last
0675: tr2 = domContext.createElement(HTML.TR_ELEM);
0676: table.appendChild(tr2);
0677: }
0678:
0679: cal = copyCalendar(facesContext, timeKeeper);
0680: cal.set(Calendar.DAY_OF_MONTH, i + 1); // i starts at 0 DAY_OF_MONTH start at 1
0681:
0682: // get day, month and year
0683: // use these to check if the currentDayCell style class should be used
0684: int day = 0;
0685: int month = 0;
0686: int year = 0;
0687: try {
0688: Date currentDate = (Date) inputComponent.getValue();
0689: Calendar current = Calendar.getInstance();
0690: current.setTime(currentDate);
0691:
0692: day = current.get(Calendar.DAY_OF_MONTH); // starts with 1
0693: month = current.get(Calendar.MONTH); // starts with 0
0694: year = current.get(Calendar.YEAR);
0695: } catch (Exception e) {
0696: // hmmm this should never happen
0697: }
0698:
0699: if (inputComponent.getHightlightRules().size() > 0) {
0700: int weekOfYear = cal.get(Calendar.WEEK_OF_YEAR);
0701: int weekOfMonth = cal.get(Calendar.WEEK_OF_MONTH);
0702: int date = cal.get(Calendar.DATE);
0703: int dayOfYear = cal.get(Calendar.DAY_OF_YEAR);
0704: int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
0705: int dayOfWeekInMonth = cal
0706: .get(Calendar.DAY_OF_WEEK_IN_MONTH);
0707:
0708: if (inputComponent.getHightlightRules().containsKey(
0709: Calendar.WEEK_OF_YEAR + "$" + weekOfYear)) {
0710: inputComponent.addHighlightWeekClass(String
0711: .valueOf(inputComponent
0712: .getHightlightRules().get(
0713: Calendar.WEEK_OF_YEAR + "$"
0714: + weekOfYear)));
0715: }
0716: if (inputComponent.getHightlightRules().containsKey(
0717: Calendar.WEEK_OF_MONTH + "$" + weekOfMonth)) {
0718: inputComponent
0719: .addHighlightWeekClass(String
0720: .valueOf(inputComponent
0721: .getHightlightRules()
0722: .get(
0723: Calendar.WEEK_OF_MONTH
0724: + "$"
0725: + weekOfMonth)));
0726: }
0727: if (inputComponent.getHightlightRules().containsKey(
0728: Calendar.DATE + "$" + date)) {
0729: inputComponent
0730: .addHighlightDayClass(String
0731: .valueOf(inputComponent
0732: .getHightlightRules().get(
0733: Calendar.DATE + "$"
0734: + date)));
0735: }
0736: if (inputComponent.getHightlightRules().containsKey(
0737: Calendar.DAY_OF_YEAR + "$" + dayOfYear)) {
0738: inputComponent.addHighlightDayClass(String
0739: .valueOf(inputComponent
0740: .getHightlightRules().get(
0741: Calendar.DAY_OF_YEAR + "$"
0742: + dayOfYear)));
0743: }
0744: if (inputComponent.getHightlightRules().containsKey(
0745: Calendar.DAY_OF_WEEK + "$" + dayOfWeek)) {
0746: inputComponent.addHighlightDayClass(String
0747: .valueOf(inputComponent
0748: .getHightlightRules().get(
0749: Calendar.DAY_OF_WEEK + "$"
0750: + dayOfWeek)));
0751: }
0752: if (inputComponent.getHightlightRules().containsKey(
0753: Calendar.DAY_OF_WEEK_IN_MONTH + "$"
0754: + dayOfWeekInMonth)) {
0755: inputComponent
0756: .addHighlightDayClass(String
0757: .valueOf(inputComponent
0758: .getHightlightRules()
0759: .get(
0760: Calendar.DAY_OF_WEEK_IN_MONTH
0761: + "$"
0762: + dayOfWeekInMonth)));
0763: }
0764: }
0765:
0766: String cellStyle = inputComponent
0767: .getHighlightDayCellClass()
0768: + inputComponent.getDayCellClass();
0769:
0770: if ((cal.get(Calendar.DAY_OF_MONTH) == day)
0771: && (cal.get(Calendar.MONTH) == month)
0772: && (cal.get(Calendar.YEAR) == year)) {
0773: cellStyle = inputComponent.getCurrentDayCellClass();
0774: }
0775:
0776: // do not automatically select date when navigating by month
0777: if ((cal.get(Calendar.DAY_OF_MONTH) == day)
0778: && (cal.get(Calendar.MONTH) == month)
0779: && (cal.get(Calendar.YEAR) == year)) {
0780: cellStyle = inputComponent.getCurrentDayCellClass();
0781: }
0782:
0783: if (tr2 == null) {
0784: // finish the first row
0785: writeCell(domContext, facesContext, writer,
0786: inputComponent, String.valueOf(i + 1), cal
0787: .getTime(), cellStyle, tr1, null, i);
0788: } else {
0789: // write to new row
0790: writeCell(domContext, facesContext, writer,
0791: inputComponent, String.valueOf(i + 1), cal
0792: .getTime(), cellStyle, tr2, null, i);
0793: }
0794:
0795: columnIndexCounter++;
0796:
0797: if (columnIndexCounter == weekdays.length) {
0798: columnIndexCounter = 0;
0799: }
0800: inputComponent.resetHighlightClasses(Calendar.WEEK_OF_YEAR);
0801: }
0802:
0803: if ((columnIndexCounter != 0) && (tr2 != null)) {
0804: for (int i = columnIndexCounter; i < weekdays.length; i++) {
0805: writeCell(domContext, facesContext, writer,
0806: inputComponent, "", null, inputComponent
0807: .getDayCellClass(), tr2, null, i);
0808: }
0809: }
0810:
0811: }
0812:
0813: private void writeCell(DOMContext domContext,
0814: FacesContext facesContext, ResponseWriter writer,
0815: UIInput component, String content, Date valueForLink,
0816: String styleClass, Element tr, String imgSrc,
0817: int weekDayIndex) throws IOException {
0818: Element td = domContext.createElement(HTML.TD_ELEM);
0819: tr.appendChild(td);
0820:
0821: if (styleClass != null) {
0822: td.setAttribute(HTML.CLASS_ATTR, styleClass);
0823: }
0824:
0825: if (valueForLink == null) {
0826: Text text = domContext.createTextNode(content);
0827: td
0828: .setAttribute(HTML.TITLE_ATTR,
0829: weekdaysLong[weekDayIndex]);
0830: td.appendChild(text);
0831: } else {
0832: // set cursor to render into the td
0833: domContext.setCursorParent(td);
0834: domContext.streamWrite(facesContext, component, domContext
0835: .getRootNode(), td);
0836: writeLink(content, component, facesContext, valueForLink,
0837: styleClass, imgSrc, td);
0838: // steps to the position where the next sibling should be rendered
0839: domContext.stepOver();
0840: }
0841:
0842: }
0843:
0844: private void writeLink(String content, UIInput component,
0845: FacesContext facesContext, Date valueForLink,
0846: String styleClass, String imgSrc, Element td)
0847: throws IOException {
0848:
0849: Converter converter = getConverter(component);
0850: HtmlCommandLink link = new HtmlCommandLink();
0851: Calendar cal = Calendar.getInstance(currentLocale);
0852: cal.setTime(valueForLink);
0853: String month = months[cal.get(Calendar.MONTH)];
0854: String year = String.valueOf(cal.get(Calendar.YEAR));
0855: int dayInt = cal.get(Calendar.DAY_OF_WEEK);
0856: dayInt = mapCalendarDayToCommonDay(dayInt);
0857: String day = weekdaysLong[dayInt];
0858: String altText = "";
0859: // assign special ids for navigation links
0860: if (content.equals("<")) {
0861: link.setId(component.getId() + this .PREV_MONTH);
0862: altText = "Move to previous month " + month;
0863: } else if (content.equals(">")) {
0864: link.setId(component.getId() + this .NEXT_MONTH);
0865: altText = "Move to next month " + month;
0866: } else if (content.equals(">>")) {
0867: link.setId(component.getId() + this .NEXT_YEAR);
0868: altText = "Move to next year " + year;
0869: } else if (content.equals("<<")) {
0870: link.setId(component.getId() + this .PREV_YEAR);
0871: altText = "Move to previous year " + year;
0872: } else {
0873: link.setId(component.getId() + "_" + content.hashCode()
0874: + this .CALENDAR);
0875: if (log.isDebugEnabled()) {
0876: log.debug("linkId=" + component.getId() + "_"
0877: + content.hashCode() + this .CALENDAR);
0878: }
0879: }
0880:
0881: link.setPartialSubmit(true);
0882: link.setTransient(true);
0883: link.setImmediate(component.isImmediate());
0884:
0885: if (imgSrc != null) {
0886: HtmlGraphicImage img = new HtmlGraphicImage();
0887: img.setUrl(imgSrc);
0888: img.setHeight("16");
0889: img.setWidth("17");
0890: img.setStyle("border:none;");
0891: img.setAlt(altText);
0892: img.setId(component.getId() + "_" + content.hashCode()
0893: + "_img");
0894: img.setTransient(true);
0895: link.getChildren().add(img);
0896: } else {
0897: HtmlOutputText text = new HtmlOutputText();
0898: text.setValue(content);
0899: text.setId(component.getId() + "_" + content.hashCode()
0900: + "_text");
0901: text.setTransient(true);
0902: text.setTitle(day);
0903: link.getChildren().add(text);
0904: }
0905: // links are focus aware
0906: UIParameter parameter = new UIParameter();
0907: parameter.setId(component.getId() + "_"
0908: + valueForLink.getTime() + "_param");
0909: parameter.setTransient(true);
0910: parameter.setName(component.getClientId(facesContext));
0911: parameter.setValue(converter.getAsString(facesContext,
0912: component, valueForLink));
0913:
0914: component.getChildren().add(link);
0915: link.getChildren().add(parameter);
0916:
0917: //don't add this parameter for next and previouse button/link
0918: if (!content.equals("<") && !content.equals(">")
0919: && !content.equals(">>") && !content.equals("<<")) {
0920: //this parameter would be use to close the popup selectinputdate after date selection.
0921: parameter = new UIParameter();
0922: parameter.setId(component.getId() + "_"
0923: + valueForLink.getTime() + "_" + DATE_SELECTED);
0924: parameter.setName(getHiddenFieldName(facesContext,
0925: component));
0926: parameter.setValue("false");
0927: link.getChildren().add(parameter);
0928: }
0929: link.encodeBegin(facesContext);
0930: link.encodeChildren(facesContext);
0931: link.encodeEnd(facesContext);
0932: td.setAttribute(HTML.ID_ATTR, link.getClientId(facesContext)
0933: + "td");
0934: try {
0935: Integer.parseInt(content);
0936: ((SelectInputDate) component).getLinkMap().put(
0937: link.getClientId(facesContext), td);
0938: if (styleClass.equals(CSS_DEFAULT.DEFAULT_CALENDAR
0939: + CSS_DEFAULT.DEFAULT_CURRENTDAYCELL_CLASS)) {
0940: ((SelectInputDate) component).setSelectedDayLink(link
0941: .getClientId(facesContext));
0942: }
0943: } catch (NumberFormatException e) {
0944:
0945: }
0946:
0947: }
0948:
0949: private Converter getConverter(UIInput component) {
0950: Converter converter = component.getConverter();
0951:
0952: if (converter == null) {
0953: converter = new CalendarDateTimeConverter();
0954: }
0955: return converter;
0956: }
0957:
0958: private int mapCalendarDayToCommonDay(int day) {
0959: switch (day) {
0960: case Calendar.TUESDAY:
0961: return 1;
0962: case Calendar.WEDNESDAY:
0963: return 2;
0964: case Calendar.THURSDAY:
0965: return 3;
0966: case Calendar.FRIDAY:
0967: return 4;
0968: case Calendar.SATURDAY:
0969: return 5;
0970: case Calendar.SUNDAY:
0971: return 6;
0972: default:
0973: return 0;
0974: }
0975: }
0976:
0977: private static String[] mapWeekdays(DateFormatSymbols symbols) {
0978: String[] weekdays = new String[7];
0979:
0980: String[] localeWeekdays = symbols.getShortWeekdays();
0981:
0982: weekdays[0] = localeWeekdays[Calendar.MONDAY];
0983: weekdays[1] = localeWeekdays[Calendar.TUESDAY];
0984: weekdays[2] = localeWeekdays[Calendar.WEDNESDAY];
0985: weekdays[3] = localeWeekdays[Calendar.THURSDAY];
0986: weekdays[4] = localeWeekdays[Calendar.FRIDAY];
0987: weekdays[5] = localeWeekdays[Calendar.SATURDAY];
0988: weekdays[6] = localeWeekdays[Calendar.SUNDAY];
0989:
0990: return weekdays;
0991: }
0992:
0993: private static String[] mapWeekdaysLong(DateFormatSymbols symbols) {
0994: String[] weekdays = new String[7];
0995:
0996: String[] localeWeekdays = symbols.getWeekdays();
0997:
0998: weekdays[0] = localeWeekdays[Calendar.MONDAY];
0999: weekdays[1] = localeWeekdays[Calendar.TUESDAY];
1000: weekdays[2] = localeWeekdays[Calendar.WEDNESDAY];
1001: weekdays[3] = localeWeekdays[Calendar.THURSDAY];
1002: weekdays[4] = localeWeekdays[Calendar.FRIDAY];
1003: weekdays[5] = localeWeekdays[Calendar.SATURDAY];
1004: weekdays[6] = localeWeekdays[Calendar.SUNDAY];
1005:
1006: return weekdays;
1007: }
1008:
1009: /**
1010: * @param symbols
1011: * @return months - String[] containing localized month names
1012: */
1013: public static String[] mapMonths(DateFormatSymbols symbols) {
1014: String[] months = new String[12];
1015:
1016: String[] localeMonths = symbols.getMonths();
1017:
1018: months[0] = localeMonths[Calendar.JANUARY];
1019: months[1] = localeMonths[Calendar.FEBRUARY];
1020: months[2] = localeMonths[Calendar.MARCH];
1021: months[3] = localeMonths[Calendar.APRIL];
1022: months[4] = localeMonths[Calendar.MAY];
1023: months[5] = localeMonths[Calendar.JUNE];
1024: months[6] = localeMonths[Calendar.JULY];
1025: months[7] = localeMonths[Calendar.AUGUST];
1026: months[8] = localeMonths[Calendar.SEPTEMBER];
1027: months[9] = localeMonths[Calendar.OCTOBER];
1028: months[10] = localeMonths[Calendar.NOVEMBER];
1029: months[11] = localeMonths[Calendar.DECEMBER];
1030:
1031: return months;
1032: }
1033:
1034: /**
1035: * @param facesContext
1036: * @param uiComponent
1037: * @return id - used for the commandlink hidden field in the form
1038: */
1039: public String getLinkId(FacesContext facesContext,
1040: UIComponent uiComponent) {
1041: //this is a fix for bug 340
1042: UIComponent form = findForm(uiComponent);
1043: String formId = form.getClientId(facesContext);
1044: return formId + ":_idcl";
1045: }
1046:
1047: private boolean checkLink(String clickedLink, String clientId) {
1048: if (clickedLink == null) {
1049: return false;
1050: }
1051: boolean found = false;
1052: String REGEX = clientId;
1053: String INPUT = clickedLink;
1054: Pattern pattern;
1055: Matcher matcher;
1056:
1057: pattern = Pattern.compile(REGEX);
1058: matcher = pattern.matcher(INPUT);
1059:
1060: while (matcher.find()) {
1061: found = true;
1062: }
1063:
1064: return found;
1065: }
1066:
1067: /* (non-Javadoc)
1068: * @see com.icesoft.faces.renderkit.dom_html_basic.DomBasicRenderer#decode(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
1069: */
1070: public void decode(FacesContext facesContext, UIComponent component) {
1071: validateParameters(facesContext, component,
1072: SelectInputDate.class);
1073: Map requestParameterMap = facesContext.getExternalContext()
1074: .getRequestParameterMap();
1075: Object linkId = getLinkId(facesContext, component);
1076: Object clickedLink = requestParameterMap.get(linkId);
1077: String clientId = component.getClientId(facesContext);
1078:
1079: Map parameter = facesContext.getExternalContext()
1080: .getRequestParameterMap();
1081: String param = (String) parameter.get(component
1082: .getClientId(facesContext));
1083: if (clickedLink != null) {
1084:
1085: if (log.isDebugEnabled()) {
1086: log.debug("linkId::" + linkId + " clickedLink::"
1087: + clickedLink + " clientId::" + clientId);
1088: }
1089:
1090: if (checkLink((String) clickedLink, clientId)) {
1091: if (log.isDebugEnabled()) {
1092: log.debug("---------------------------------");
1093: log.debug("----------START::DECODE----------");
1094: log.debug("---------------------------------");
1095: log.debug("decode::linkId::" + linkId + "="
1096: + clickedLink + " clientId::" + clientId);
1097: }
1098:
1099: if (((String) clickedLink).endsWith(this .PREV_MONTH)
1100: || ((String) clickedLink)
1101: .endsWith(this .NEXT_MONTH)
1102: || ((String) clickedLink)
1103: .endsWith(this .PREV_YEAR)
1104: || ((String) clickedLink)
1105: .endsWith(this .NEXT_YEAR)) {
1106: if (log.isDebugEnabled()) {
1107: log
1108: .debug("-------------Navigation Event-------------");
1109: }
1110: decodeNavigation(facesContext, component);
1111: } else if (((String) clickedLink)
1112: .endsWith(this .CALENDAR)) {
1113: if (log.isDebugEnabled()) {
1114: log
1115: .debug("-------------Select Date Event-------------");
1116: }
1117: decodeSelectDate(facesContext, component);
1118: } else if (((String) clickedLink)
1119: .endsWith(this .CALENDAR_BUTTON)) {
1120: if (log.isDebugEnabled()) {
1121: log
1122: .debug("-------------Popup Event-------------------");
1123: }
1124: decodePopup(facesContext, component);
1125: }
1126: } else {
1127: if (log.isDebugEnabled()) {
1128: log
1129: .debug("-------------InputText enterkey Event ??----");
1130: }
1131: decodeInputText(facesContext, component);
1132: }
1133:
1134: }
1135: }
1136:
1137: private void decodeNavigation(FacesContext facesContext,
1138: UIComponent component) {
1139: Map requestParameterMap = facesContext.getExternalContext()
1140: .getRequestParameterMap();
1141: SelectInputDate dateSelect = (SelectInputDate) component;
1142:
1143: // set the navDate on the Calendar
1144: if (log.isDebugEnabled()) {
1145: log.debug("setNavDate::");
1146: log.debug("#################################");
1147: }
1148: dateSelect.setNavEvent(true);
1149: dateSelect.setNavDate((Date) getConvertedValue(facesContext,
1150: dateSelect, requestParameterMap.get(dateSelect
1151: .getClientId(facesContext))));
1152: }
1153:
1154: private void decodePopup(FacesContext facesContext,
1155: UIComponent component) {
1156: Map requestParameterMap = facesContext.getExternalContext()
1157: .getRequestParameterMap();
1158: String popupState = getHiddenFieldName(facesContext, component);
1159: String showPopup = (String) requestParameterMap.get(popupState);
1160: SelectInputDate dateSelect = (SelectInputDate) component;
1161:
1162: if (log.isDebugEnabled()) {
1163: log.debug("decodePopup::" + showPopup);
1164: log.debug("#################################");
1165: }
1166: // check showPopup
1167: if (showPopup != null) {
1168:
1169: dateSelect.setShowPopup(!dateSelect.isShowPopup());
1170: }
1171: // not a nav event
1172: dateSelect.setNavEvent(false);
1173: }
1174:
1175: private void decodeSelectDate(FacesContext facesContext,
1176: UIComponent component) {
1177:
1178: Map requestParameterMap = facesContext.getExternalContext()
1179: .getRequestParameterMap();
1180: String popupState = getHiddenFieldName(facesContext, component);
1181: String showPopup = (String) requestParameterMap.get(popupState);
1182: SelectInputDate dateSelect = (SelectInputDate) component;
1183:
1184: if (log.isDebugEnabled()) {
1185: log.debug("selectDate::showPopup" + showPopup);
1186: log.debug("#################################");
1187: }
1188: if (showPopup != null) {
1189: if (showPopup.equalsIgnoreCase("true")) {
1190: dateSelect.setShowPopup(true);
1191: } else {
1192: dateSelect.setShowPopup(false);
1193: }
1194: }
1195: if (log.isDebugEnabled()) {
1196: log.debug("decodeUIInput::");
1197: log.debug("#################################");
1198: }
1199: String inputTextDateId = component.getClientId(facesContext)
1200: + SelectInputDate.CALENDAR_INPUTTEXT;
1201: if (requestParameterMap.containsKey(inputTextDateId)) {
1202: ((BridgeFacesContext) facesContext)
1203: .setFocusId(inputTextDateId);
1204: }
1205: CustomComponentUtils.decodeUIInput(facesContext, component);
1206: // not a navigation event
1207: dateSelect.setNavEvent(false);
1208: }
1209:
1210: private void decodeInputText(FacesContext facesContext,
1211: UIComponent component) {
1212: Map requestParameterMap = facesContext.getExternalContext()
1213: .getRequestParameterMap();
1214: String popupState = getHiddenFieldName(facesContext, component);
1215: String showPopup = (String) requestParameterMap.get(popupState);
1216: SelectInputDate dateSelect = (SelectInputDate) component;
1217: String clientId = dateSelect.getClientId(facesContext);
1218: Object linkId = getLinkId(facesContext, component);
1219: Object clickedLink = requestParameterMap.get(linkId);
1220:
1221: String inputTextDateId = component.getClientId(facesContext)
1222: + SelectInputDate.CALENDAR_INPUTTEXT;
1223: Object inputTextDate = requestParameterMap.get(inputTextDateId);
1224:
1225: // inputtext is only available in popup mode
1226: if (requestParameterMap.containsKey(inputTextDateId)
1227: && dateSelect.isRenderAsPopup()) {
1228: if (log.isDebugEnabled()) {
1229: log.debug("decoding InputText EnterKey::");
1230: log.debug("###################################");
1231: }
1232: if (showPopup != null) {
1233:
1234: if (checkLink((String) clickedLink, clientId)) {
1235: if (showPopup.equalsIgnoreCase("true")) {
1236: dateSelect.setShowPopup(true);
1237: } else {
1238: dateSelect.setShowPopup(false);
1239: }
1240: }
1241: if (String.valueOf(inputTextDate).equals("")) {
1242: dateSelect.setSubmittedValue("null");
1243: } else {
1244: dateSelect.setSubmittedValue(inputTextDate);
1245: }
1246: }
1247: }
1248: }
1249:
1250: /* (non-Javadoc)
1251: * @see com.icesoft.faces.renderkit.dom_html_basic.DomBasicInputRenderer#getConvertedValue(javax.faces.context.FacesContext, javax.faces.component.UIComponent, java.lang.Object)
1252: */
1253: public Object getConvertedValue(FacesContext facesContext,
1254: UIComponent uiComponent, Object submittedValue)
1255: throws ConverterException {
1256: validateParameters(facesContext, uiComponent,
1257: SelectInputDate.class);
1258: Converter converter;
1259:
1260: converter = new CalendarDateTimeConverter();
1261:
1262: if (!(submittedValue == null || submittedValue instanceof String)) {
1263: throw new IllegalArgumentException(
1264: "Submitted value of type String expected");
1265: }
1266: Object o = converter.getAsObject(facesContext, uiComponent,
1267: (String) submittedValue);
1268:
1269: return o;
1270: }
1271:
1272: /**
1273: *
1274: */
1275: public interface DateConverter extends Converter {
1276: public Date getAsDate(FacesContext facesContext,
1277: UIComponent uiComponent);
1278: }
1279:
1280: /**
1281: *
1282: */
1283: public static class CalendarDateTimeConverter implements Converter {
1284:
1285: /* (non-Javadoc)
1286: * @see javax.faces.convert.Converter#getAsObject(javax.faces.context.FacesContext, javax.faces.component.UIComponent, java.lang.String)
1287: */
1288: public Object getAsObject(FacesContext facesContext,
1289: UIComponent uiComponent, String s) {
1290:
1291: if (s == null || s.trim().length() == 0) {
1292: return null;
1293: } else if ("null".equals(s)) {
1294: return null;
1295: }
1296:
1297: DateFormat dateFormat = null;
1298:
1299: if (uiComponent instanceof SelectInputDate
1300: && ((SelectInputDate) uiComponent)
1301: .isRenderAsPopup()) {
1302: String popupDateFormat = ((SelectInputDate) uiComponent)
1303: .getPopupDateFormat();
1304: dateFormat = new SimpleDateFormat(popupDateFormat);
1305: } else {
1306: dateFormat = createStandardDateFormat(facesContext);
1307: }
1308:
1309: try {
1310: return dateFormat.parse(s);
1311: } catch (ParseException e) {
1312: ConverterException ex = new ConverterException(e);
1313: throw ex;
1314: }
1315: }
1316:
1317: /**
1318: * @param facesContext
1319: * @param popupDateFormat
1320: * @return jsPopupDateFormat
1321: */
1322: public static String createJSPopupFormat(
1323: FacesContext facesContext, String popupDateFormat) {
1324:
1325: if (popupDateFormat == null) {
1326: SimpleDateFormat defaultDateFormat = createStandardDateFormat(facesContext);
1327: popupDateFormat = defaultDateFormat.toPattern();
1328: }
1329:
1330: StringBuffer jsPopupDateFormat = new StringBuffer();
1331:
1332: for (int i = 0; i < popupDateFormat.length(); i++) {
1333: char c = popupDateFormat.charAt(i);
1334:
1335: if (c == 'M') {
1336: jsPopupDateFormat.append('M');
1337: } else if (c == 'd') {
1338: jsPopupDateFormat.append('d');
1339: } else if (c == 'y') {
1340: jsPopupDateFormat.append('y');
1341: } else if (c == ' ') {
1342: jsPopupDateFormat.append(' ');
1343: } else if (c == '.') {
1344: jsPopupDateFormat.append('.');
1345: } else if (c == '/') {
1346: jsPopupDateFormat.append('/');
1347: }
1348: }
1349: return jsPopupDateFormat.toString().trim();
1350: }
1351:
1352: /* (non-Javadoc)
1353: * @see javax.faces.convert.Converter#getAsString(javax.faces.context.FacesContext, javax.faces.component.UIComponent, java.lang.Object)
1354: */
1355: public String getAsString(FacesContext facesContext,
1356: UIComponent uiComponent, Object o) {
1357: Date date = (Date) o;
1358:
1359: if (date == null) {
1360: return null;
1361: }
1362:
1363: DateFormat dateFormat = null;
1364:
1365: if (uiComponent instanceof SelectInputDate
1366: && ((SelectInputDate) uiComponent)
1367: .isRenderAsPopup()) {
1368: String popupDateFormat = ((SelectInputDate) uiComponent)
1369: .getPopupDateFormat();
1370: dateFormat = new SimpleDateFormat(popupDateFormat);
1371: } else {
1372: dateFormat = createStandardDateFormat(facesContext);
1373: }
1374:
1375: return dateFormat.format(date);
1376: }
1377:
1378: private static SimpleDateFormat createStandardDateFormat(
1379: FacesContext facesContext) {
1380: DateFormat dateFormat;
1381: dateFormat = DateFormat.getDateTimeInstance(
1382: DateFormat.SHORT, DateFormat.SHORT, facesContext
1383: .getViewRoot().getLocale());
1384:
1385: if (dateFormat instanceof SimpleDateFormat) {
1386: // BUGFIX for FireFox always create a new dateFormat
1387: // FireFox was reversing the day and month
1388: return new SimpleDateFormat("dd.MM.yyyy");
1389: } else {
1390: return new SimpleDateFormat("dd.MM.yyyy");
1391: }
1392: }
1393:
1394: }
1395:
1396: }
|