📄 datepicker.java
字号:
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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.apache.wicket.extensions.yui.calendar;import java.text.DateFormat;import java.text.DateFormatSymbols;import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.Calendar;import java.util.Date;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Locale;import java.util.Map;import java.util.Properties;import java.util.Map.Entry;import org.apache.wicket.Application;import org.apache.wicket.Component;import org.apache.wicket.RequestCycle;import org.apache.wicket.ResourceReference;import org.apache.wicket.Response;import org.apache.wicket.WicketRuntimeException;import org.apache.wicket.ajax.AjaxEventBehavior;import org.apache.wicket.ajax.AjaxRequestTarget;import org.apache.wicket.behavior.AbstractBehavior;import org.apache.wicket.datetime.markup.html.form.DateTextField;import org.apache.wicket.extensions.yui.YuiLib;import org.apache.wicket.markup.html.IHeaderContributor;import org.apache.wicket.markup.html.IHeaderResponse;import org.apache.wicket.markup.html.form.AbstractTextComponent.ITextFormatProvider;import org.apache.wicket.markup.html.resources.JavascriptResourceReference;import org.apache.wicket.util.convert.IConverter;import org.apache.wicket.util.convert.converters.DateConverter;import org.apache.wicket.util.lang.Objects;import org.apache.wicket.util.string.Strings;import org.apache.wicket.util.template.PackagedTextTemplate;import org.apache.wicket.util.template.TextTemplate;import org.joda.time.DateTime;/** * Pops up a YUI calendar component so that the user can select a date. On selection, the date is * set in the component it is coupled to, after which the popup is closed again. This behavior can * only be used with components that either implement {@link ITextFormatProvider} or that use * {@link DateConverter} configured with an instance of {@link SimpleDateFormat} (like Wicket's * default configuration has).<br/> * * To use, simply add a new instance to your component, which would typically a TextField, like * {@link DateTextField}.<br/> * * The CalendarNavigator can be configured by overriding {@link #configure(Map)} and setting the * property or by returning <code>true</code> for {@link #enableMonthYearSelection()}. * * @see http://developer.yahoo.com/yui/calendar/ * * @author eelcohillenius */public class DatePicker extends AbstractBehavior implements IHeaderContributor{ /** * Exception thrown when the bound component does not produce a format this date picker can work * with. */ private static final class UnableToDetermineFormatException extends WicketRuntimeException { private static final long serialVersionUID = 1L; public UnableToDetermineFormatException() { super("This behavior can only be added to components that either implement " + ITextFormatProvider.class.getName() + " AND produce a non-null format, or that use" + " converters that this datepicker can use to determine" + " the pattern being used. Alternatively, you can extend " + " the date picker and override getDatePattern to provide your own"); } } /** * Format to be used when configuring YUI calendar. Can be used when using the * "selected" property. */ public static final DateFormat FORMAT_DATE = new SimpleDateFormat("MM/dd/yyyy"); /** * For specifying which page (month/year) to show in the calendar, use this format for the date. * This is to be used together with the property "pagedate" */ public static final DateFormat FORMAT_PAGEDATE = new SimpleDateFormat("MM/yyyy"); private static final ResourceReference YUI = new JavascriptResourceReference(YuiLib.class, ""); private static final ResourceReference WICKET_DATE = new JavascriptResourceReference( DatePicker.class, "wicket-date.js"); private static final long serialVersionUID = 1L; /** The target component. */ private Component component; /** * Construct. */ public DatePicker() { } /** * @see org.apache.wicket.behavior.AbstractBehavior#bind(org.apache.wicket.Component) */ public void bind(Component component) { this.component = component; checkComponentProvidesDateFormat(component); component.setOutputMarkupId(true); } /** * @see org.apache.wicket.behavior.AbstractBehavior#onRendered(org.apache.wicket.Component) */ public void onRendered(Component component) { super.onRendered(component); // Append the span and img icon right after the rendering of the // component. Not as pretty as working with a panel etc, but works // for behaviors and is more efficient Response response = component.getResponse(); response.write("\n<span class=\"yui-skin-sam\"> <span style=\""); if (renderOnLoad()) { response.write("display:block;"); } else { response.write("display:none;"); response.write("position:absolute;"); } response.write("z-index: 99999;\" id=\""); response.write(getEscapedComponentMarkupId()); response.write("Dp\"></span><img style=\""); response.write(getIconStyle()); response.write("\" id=\""); response.write(getIconId()); response.write("\" src=\""); CharSequence iconUrl = getIconUrl(); response.write(Strings.escapeMarkup(iconUrl != null ? iconUrl.toString() : "")); response.write("\" alt=\"\"/>"); if (renderOnLoad()) { response.write("<br style=\"clear:left;\"/>"); } response.write("</span>"); } /** * @see org.apache.wicket.markup.html.IHeaderContributor#renderHead(org.apache.wicket.markup.html.IHeaderResponse) */ public void renderHead(IHeaderResponse response) { YuiLib.load(response); // variables for the initialization script Map variables = new HashMap(); String widgetId = getEscapedComponentMarkupId(); variables.put("componentId", getComponentMarkupId()); variables.put("widgetId", widgetId); variables.put("datePattern", getDatePattern()); variables.put("fireChangeEvent", Boolean.valueOf(notifyComponentOnDateSelected())); variables.put("alignWithIcon", Boolean.valueOf(alignWithIcon())); variables.put("hideOnSelect", Boolean.valueOf(hideOnSelect())); // variables for YUILoader variables.put("basePath", Strings.stripJSessionId(RequestCycle.get().urlFor(YUI))); variables.put("wicketDatePath", Strings.stripJSessionId(RequestCycle.get().urlFor( WICKET_DATE))); if (Application.DEVELOPMENT.equals(Application.get().getConfigurationType())) { variables.put("filter", "filter: \"RAW\","); variables.put("allowRollup", Boolean.FALSE); } else { variables.put("filter", ""); variables.put("allowRollup", Boolean.TRUE); } String script = getAdditionalJavascript(); if (script != null) { variables.put("additionalJavascript", Strings.replaceAll(script, "${calendar}", "YAHOO.wicket." + widgetId + "DpJs")); } // print out the initialization properties Properties p = new Properties(); configure(p); if (!p.containsKey("navigator") && enableMonthYearSelection()) { p.put("navigator", Boolean.TRUE); } if (enableMonthYearSelection() && p.containsKey("pages") && Objects.longValue(p.get("pages")) > 1) { throw new IllegalStateException( "You cannot use a CalendarGroup with month/year selection!"); } // ${calendarInit} StringBuffer calendarInit = new StringBuffer(); for (Iterator i = p.entrySet().iterator(); i.hasNext();) { Entry entry = (Entry)i.next(); calendarInit.append(entry.getKey()); Object value = entry.getValue(); if (value instanceof CharSequence) { calendarInit.append(":\""); calendarInit.append(Strings.toEscapedUnicode(value.toString())); calendarInit.append("\""); } else if (value instanceof CharSequence[]) { calendarInit.append(":["); CharSequence[] valueArray = (CharSequence[])value; for (int j = 0; j < valueArray.length; j++) { CharSequence tmpValue = valueArray[j]; if (j > 0) { calendarInit.append(","); } if (tmpValue != null) { calendarInit.append("\""); calendarInit.append(Strings.toEscapedUnicode(tmpValue.toString())); calendarInit.append("\""); } } calendarInit.append("]"); } else { calendarInit.append(":"); calendarInit.append(Strings.toEscapedUnicode(String.valueOf(value))); } if (i.hasNext()) { calendarInit.append(","); } } variables.put("calendarInit", calendarInit.toString()); // render initialization script with the variables interpolated TextTemplate datePickerJs = new PackagedTextTemplate(DatePicker.class, "DatePicker.js"); datePickerJs.interpolate(variables); response.renderOnDomReadyJavascript(datePickerJs.asString()); // remove previously generated markup (see onRendered) via javascript in // ajax requests to not render the yui calendar multiple times if (AjaxRequestTarget.get() != null) { final String javascript = "var e = Wicket.$('" + getEscapedComponentMarkupId() + "Dp" + "'); if (e != null && typeof(e.parentNode) != 'undefined' && " + "typeof(e.parentNode.parentNode != 'undefined')) " + "e.parentNode.parentNode.removeChild(e.parentNode);"; response.renderJavascript(javascript, null); } } /** * Check that this behavior can get a date format out of the component it is coupled to. It * checks whether {@link #getDatePattern()} produces a non-null value. If that method returns * null, and exception will be thrown * * @param component * the component this behavior is being coupled to * @throws UnableToDetermineFormatException * if this date picker is unable to determine a format. */ private final void checkComponentProvidesDateFormat(Component component) { if (getDatePattern() == null) { throw new UnableToDetermineFormatException(); } } /** * Set widget property if the array is null and has a length greater than 0. * * @param widgetProperties * @param key * @param array */ private void setWidgetProperty(Map widgetProperties, String key, String[] array) { if (array != null && array.length > 0) { widgetProperties.put(key, array); } } /** * Whether to position the date picker relative to the trigger icon. * * @return If true, the date picker is aligned with the left position of the icon, and with the * top right under. If false, the date picker will skip positioning and will let you do * the positioning yourself. Returns true by default. */ protected boolean alignWithIcon() { return true; } /**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -