001 // Copyright 2010, 2011 The Apache Software Foundation 002 // 003 // Licensed under the Apache License, Version 2.0 (the "License"); 004 // you may not use this file except in compliance with the License. 005 // You may obtain a copy of the License at 006 // 007 // http://www.apache.org/licenses/LICENSE-2.0 008 // 009 // Unless required by applicable law or agreed to in writing, software 010 // distributed under the License is distributed on an "AS IS" BASIS, 011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 012 // See the License for the specific language governing permissions and 013 // limitations under the License. 014 015 package org.apache.tapestry5.internal.services.javascript; 016 017 import java.text.DateFormatSymbols; 018 import java.util.Calendar; 019 import java.util.Collections; 020 import java.util.List; 021 import java.util.Locale; 022 023 import org.apache.tapestry5.Asset; 024 import org.apache.tapestry5.SymbolConstants; 025 import org.apache.tapestry5.func.F; 026 import org.apache.tapestry5.func.Mapper; 027 import org.apache.tapestry5.internal.TapestryInternalUtils; 028 import org.apache.tapestry5.ioc.annotations.Symbol; 029 import org.apache.tapestry5.ioc.services.ThreadLocale; 030 import org.apache.tapestry5.json.JSONArray; 031 import org.apache.tapestry5.json.JSONObject; 032 import org.apache.tapestry5.services.AssetSource; 033 import org.apache.tapestry5.services.javascript.JavaScriptStack; 034 import org.apache.tapestry5.services.javascript.StylesheetLink; 035 036 public class DateFieldStack implements JavaScriptStack 037 { 038 private final ThreadLocale threadLocale; 039 040 private final boolean compactJSON; 041 042 private final List<Asset> javaScriptStack; 043 044 private final List<StylesheetLink> stylesheetStack; 045 046 public DateFieldStack(ThreadLocale threadLocale, @Symbol(SymbolConstants.COMPACT_JSON) 047 boolean compactJSON, final AssetSource assetSource) 048 { 049 this.threadLocale = threadLocale; 050 this.compactJSON = compactJSON; 051 052 Mapper<String, Asset> pathToAsset = new Mapper<String, Asset>() 053 { 054 public Asset map(String path) 055 { 056 return assetSource.getExpandedAsset(path); 057 } 058 }; 059 060 Mapper<String, StylesheetLink> pathToStylesheetLink = F.combine(pathToAsset, 061 TapestryInternalUtils.assetToStylesheetLink); 062 063 javaScriptStack = F 064 .flow("${tapestry.datepicker}/js/datepicker.js", "org/apache/tapestry5/corelib/components/datefield.js") 065 .map(pathToAsset).toList(); 066 067 stylesheetStack = F.flow("${tapestry.datepicker}/css/datepicker.css").map(pathToStylesheetLink).toList(); 068 } 069 070 public String getInitialization() 071 { 072 Locale locale = threadLocale.getLocale(); 073 074 JSONObject spec = new JSONObject(); 075 076 DateFormatSymbols symbols = new DateFormatSymbols(locale); 077 078 spec.put("months", new JSONArray((Object[])symbols.getMonths())); 079 080 StringBuilder days = new StringBuilder(); 081 082 String[] weekdays = symbols.getWeekdays(); 083 084 Calendar c = Calendar.getInstance(locale); 085 086 int firstDay = c.getFirstDayOfWeek(); 087 088 // DatePicker needs them in order from monday to sunday. 089 090 for (int i = Calendar.MONDAY; i <= Calendar.SATURDAY; i++) 091 { 092 days.append(weekdays[i].substring(0, 1)); 093 } 094 095 days.append(weekdays[Calendar.SUNDAY].substring(0, 1)); 096 097 spec.put("days", days.toString().toLowerCase(locale)); 098 099 // DatePicker expects 0 to be monday. Calendar defines SUNDAY as 1, MONDAY as 2, etc. 100 101 spec.put("firstDay", firstDay == Calendar.SUNDAY ? 6 : firstDay - 2); 102 103 // TODO: Skip localization if locale is English? 104 105 return String.format("Tapestry.DateField.initLocalization(%s);", spec.toString(compactJSON)); 106 } 107 108 public List<Asset> getJavaScriptLibraries() 109 { 110 return javaScriptStack; 111 } 112 113 public List<StylesheetLink> getStylesheets() 114 { 115 return stylesheetStack; 116 } 117 118 public List<String> getStacks() 119 { 120 return Collections.emptyList(); 121 } 122 }