/* * Copyright 2004-2008 the Seasar Foundation and the Others. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. See the License for the specific language * governing permissions and limitations under the License. */ package org.seasar.teeda.extension.render.html; import java.io.IOException; import java.io.StringWriter; import java.text.DateFormatSymbols; import java.util.Calendar; import java.util.Date; import java.util.Locale; import javax.faces.component.UIComponent; import javax.faces.component.UIInput; import javax.faces.context.FacesContext; import javax.faces.context.ResponseWriter; import javax.faces.convert.DateTimeConverter; import org.seasar.teeda.core.JsfConstants; import org.seasar.teeda.core.context.html.HtmlResponseWriter; import org.seasar.teeda.core.render.RenderPreparableRenderer; import org.seasar.teeda.core.render.html.HtmlInputTextRenderer; import org.seasar.teeda.extension.component.html.THtmlPopupCalendar; import org.seasar.teeda.extension.util.DateFormatSymbolsUtil; import org.seasar.teeda.extension.util.VirtualResource; /** * @author higa */ public class THtmlPopupCalendarRenderer extends HtmlInputTextRenderer implements RenderPreparableRenderer { public static final String COMPONENT_FAMILY = "org.seasar.teeda.extension.HtmlPopupCalendar"; public static final String RENDERER_TYPE = "org.seasar.teeda.extension.HtmlPopupCalendar"; private static final String JAVASCRIPT_ENCODED = "org.seasar.teeda.extension.popupcalendar.JAVASCRIPT_ENCODED"; private static final String RESOURCE_ROOT = "org/seasar/teeda/extension/render/html/popupcalendar/"; public void encodeBefore(FacesContext context, UIComponent component) throws IOException { assertNotNull(context, component); if (!component.isRendered()) { return; } encodeHtmlPopupCalendarPrepare(context, (THtmlPopupCalendar) component); } protected void encodeHtmlPopupCalendarPrepare(final FacesContext context, final THtmlPopupCalendar htmlCalendar) throws IOException { if (context.getExternalContext().getRequestMap().containsKey( JAVASCRIPT_ENCODED)) { return; } Locale currentLocale = context.getViewRoot().getLocale(); Calendar timeKeeper = Calendar.getInstance(currentLocale); DateFormatSymbols symbols = new DateFormatSymbols(currentLocale); String[] months = DateFormatSymbolsUtil.getMonths(symbols); int firstDayOfWeek = timeKeeper.getFirstDayOfWeek(); VirtualResource .addCssResource(context, RESOURCE_ROOT + "css/theme.css"); VirtualResource.addJsResource(context, RESOURCE_ROOT + "js/popcalendar_init.js"); VirtualResource.addJsResource(context, RESOURCE_ROOT + "js/popcalendar.js"); StringBuffer script = new StringBuffer(); appendImageDirectory(context, script); script.append(JsfConstants.LINE_SP); script.append(getLocalizedLanguageScript(symbols, months, firstDayOfWeek, htmlCalendar)); script.append(JsfConstants.LINE_SP); script.append("loadPopupScript();"); VirtualResource.addInlineJsResource(context, JAVASCRIPT_ENCODED, script .toString()); context.getExternalContext().getRequestMap().put(JAVASCRIPT_ENCODED, Boolean.TRUE); } public void encodeEnd(FacesContext context, UIComponent component) throws IOException { super.encodeEnd(context, component); THtmlPopupCalendar htmlCalendar = (THtmlPopupCalendar) component; Locale currentLocale = context.getViewRoot().getLocale(); Date value = (Date) htmlCalendar.getValue(); Calendar timeKeeper = Calendar.getInstance(currentLocale); timeKeeper.setTime(value != null ? value : new Date()); DateTimeConverter converter = THtmlCalendarRendererUtil.getConverter( context, (UIInput) component); if (!htmlCalendar.isDisabled()) { ResponseWriter writer = context.getResponseWriter(); String dateFormat = converter.getPattern(); writer.startElement(JsfConstants.SCRIPT_ELEM, component); writer.writeAttribute(JsfConstants.TYPE_ATTR, JsfConstants.TEXT_JAVASCRIPT_VALUE, null); writer.writeText(getScriptBtn(context, htmlCalendar, dateFormat), null); writer.endElement(JsfConstants.SCRIPT_ELEM); } } private static void appendImageDirectory(FacesContext context, StringBuffer script) { script.append("jscalendarSetImageDirectory('"); script.append(VirtualResource.convertVirtualPath(context, RESOURCE_ROOT + "images/")); script.append("');"); } private static String getLocalizedLanguageScript(DateFormatSymbols symbols, String[] months, int firstDayOfWeek, THtmlPopupCalendar htmlCalendar) { int realFirstDayOfWeek = firstDayOfWeek - 1; String[] weekDays; if (realFirstDayOfWeek == 0) { weekDays = DateFormatSymbolsUtil .getWeekdaysStartingWithSunday(symbols); } else if (realFirstDayOfWeek == 1) { weekDays = DateFormatSymbolsUtil.getWeekdays(symbols); } else { throw new IllegalStateException( "Week may only start with sunday or monday."); } StringBuffer script = new StringBuffer(); defineStringArray(script, "jscalendarMonthName", months); defineStringArray(script, "jscalendarMonthName2", months); defineStringArray(script, "jscalendarDayName", weekDays); setIntegerVariable(script, "jscalendarStartAt", realFirstDayOfWeek); if (htmlCalendar.getPopupGotoString() != null) { setStringVariable(script, "jscalendarGotoString", htmlCalendar .getPopupGotoString()); } if (htmlCalendar.getPopupTodayString() != null) { setStringVariable(script, "jscalendarTodayString", htmlCalendar .getPopupTodayString()); } if (htmlCalendar.getPopupWeekString() != null) { setStringVariable(script, "jscalendarWeekString", htmlCalendar .getPopupWeekString()); } if (htmlCalendar.getPopupScrollLeftMessage() != null) { setStringVariable(script, "jscalendarScrollLeftMessage", htmlCalendar.getPopupScrollLeftMessage()); } if (htmlCalendar.getPopupScrollRightMessage() != null) { setStringVariable(script, "jscalendarScrollRightMessage", htmlCalendar.getPopupScrollRightMessage()); } if (htmlCalendar.getPopupSelectMonthMessage() != null) { setStringVariable(script, "jscalendarSelectMonthMessage", htmlCalendar.getPopupSelectMonthMessage()); } if (htmlCalendar.getPopupSelectYearMessage() != null) { setStringVariable(script, "jscalendarSelectYearMessage", htmlCalendar.getPopupSelectYearMessage()); } if (htmlCalendar.getPopupSelectDateMessage() != null) { setStringVariable(script, "jscalendarSelectDateMessage", htmlCalendar.getPopupSelectDateMessage()); } return script.toString(); } private static void setIntegerVariable(StringBuffer script, String name, int value) { script.append(name); script.append(" = "); script.append(value); script.append(";\n"); } private static void setStringVariable(StringBuffer script, String name, String value) { script.append(name); script.append(" = \""); script.append(value); script.append("\";\n"); } private static void defineStringArray(StringBuffer script, String arrayName, String[] array) { script.append(arrayName); script.append(" = new Array("); for (int i = 0; i < array.length; i++) { if (i != 0) { script.append(","); } script.append("\""); script.append(array[i]); script.append("\""); } script.append(");"); } private String getScriptBtn(FacesContext context, UIComponent component, String dateFormat) throws IOException { HtmlResponseWriter writer = new HtmlResponseWriter(); writer.setWriter(new StringWriter()); writer.write("document.write('"); writer.startElement(JsfConstants.IMG_ELEM, component); writer.writeAttribute(JsfConstants.SRC_ATTR, VirtualResource .convertVirtualPath(context, RESOURCE_ROOT + "images/calendar.gif"), null); writer.writeAttribute(JsfConstants.STYLE_ATTR, "vertical-align:bottom;", null); writeOnclickJsCalendarFunctionCall(writer, context, component, dateFormat); writer.endElement(JsfConstants.IMG_ELEM); writer.write("');\n"); return writer.toString(); } private void writeOnclickJsCalendarFunctionCall(ResponseWriter writer, FacesContext facesContext, UIComponent uiComponent, String dateFormat) throws IOException { String clientId = uiComponent.getId(); String jsCalendarFunctionCall = "jscalendarPopUpCalendar(this,document.getElementById(\\'" + clientId + "\\'),\\'" + dateFormat + "\\')"; writer.writeAttribute(JsfConstants.ONCLICK_ATTR, jsCalendarFunctionCall, null); } }