Skip to content

Commit

Permalink
Extended AjaxDatePicker with support for localization via ERXLocalize…
Browse files Browse the repository at this point in the history
…r and start day through the current Locale in the current localizer.
  • Loading branch information
frelin authored and Pascal Robert committed Mar 16, 2012
1 parent 4ffe13a commit c8b999c
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 11 deletions.
4 changes: 3 additions & 1 deletion Frameworks/Ajax/Ajax/Components/AjaxDatePicker.api
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<wodefinitions>
<wo class="AjaxDatePicker.java" wocomponentcontent="false">

Expand Down Expand Up @@ -32,5 +32,7 @@
<binding name="calendarCSSFramework"/>
<binding name="onDateSelect"/>
<binding defaults="Boolean" name="disabled"/>

<binding name="locale"/>
</wo>
</wodefinitions>
53 changes: 47 additions & 6 deletions Frameworks/Ajax/Ajax/Sources/er/ajax/AjaxDatePicker.java
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
package er.ajax;

import java.text.Format;

import java.text.SimpleDateFormat;
import java.util.GregorianCalendar;
import java.util.Locale;

import com.webobjects.appserver.WOActionResults;
import com.webobjects.appserver.WOAssociation;
import com.webobjects.appserver.WOContext;
import com.webobjects.appserver.WORequest;
import com.webobjects.appserver.WOResponse;
import com.webobjects.foundation.NSArray;
import com.webobjects.foundation.NSMutableArray;
import com.webobjects.foundation.NSMutableDictionary;
import com.webobjects.foundation.NSTimestampFormatter;

import er.extensions.appserver.ERXResponseRewriter;
import er.extensions.formatters.ERXJodaFormat;
import er.extensions.localization.ERXLocalizer;

/**
* Shameless port and adoption of Rails Date Kit. This input understands the format symbols
Expand All @@ -28,6 +31,8 @@
* the initial display in the input, the format of the value that the date picker places into the input, and
* validation of the input contents on form submission. The use of formatter over format is
* preferred for reasons of efficiency and localization.</p>
* <p>FL: The component uses the default Locale to determine the start day of the week. It also uses the current
* language in ERXLocalizer to translate the day and month names (you must set up the localizations).</p>
*
* <p><b>NOTE</b>: the AjaxDatePicker does <b>NOT</b> play nice with the AjaxModalDialogOpener. There is some sort of
* initialization conflict (I think) with Prototype that leaves you with a blank page and the browser waiting
Expand Down Expand Up @@ -57,7 +62,8 @@
* @binding dayNames list of day names (Sunday to Saturday) for localization, English is the default
* @binding monthNames list of month names for localization, English is the default
* @binding imagesDir directory to take images from, takes them from Ajax.framework by default
*
* @binding locale FL: locale can be set if ERXLocalizer returns the wrong one. IE the English localizer returns a US Locale. If you want the UK one then set this binding.
*
* @binding calendarCSS name of CSS resource with classed for calendar, defaults to "calendar.css"
* @binding calendarCSSFramework name of framework (null for application) containing calendarCSS resource, defaults to "Ajax"
*
Expand All @@ -70,7 +76,10 @@
*/
public class AjaxDatePicker extends AjaxComponent {

private static String defaultImagesDir;
private static final NSArray<String> _dayNames = new NSArray<String>(new String[] {"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"});
private static final NSArray<String> _monthNames = new NSArray<String>(new String[] {"January","February","March","April","May","June","July","August","September","October","November","December"});

private static String defaultImagesDir;

private NSMutableDictionary<String, String> options;
private Format formatter;
Expand Down Expand Up @@ -107,7 +116,7 @@ public boolean isStateless() {
*/
public void awake() {
super.awake();

if ( ! (hasBinding("formatter") || hasBinding("format"))) {
format = "%m %d %Y"; // Default
formatter = new NSTimestampFormatter(format);
Expand Down Expand Up @@ -144,6 +153,35 @@ public void reset() {
format = null;
super.reset();
}

public Locale locale() {
return (Locale)valueForBinding("locale", ERXLocalizer.currentLocalizer().locale());
}

public Integer startDay() {
// Get first day of week from current localizer Locale.
return new Integer(new GregorianCalendar(locale()).getFirstDayOfWeek() - 1);
}

private NSArray<String> localizeStringArray(NSArray<String> strings) {
NSMutableArray<String> localizedStrings = new NSMutableArray<String>(strings.count());
ERXLocalizer l = ERXLocalizer.currentLocalizer();
for (String string : strings)
localizedStrings.add(l.localizedStringForKeyWithDefault(string));
return localizedStrings.immutableClone();
}

public NSArray<String> dayNames() {
if (hasBinding("dayNames"))
return (NSArray<String>)valueForBinding("dayNames");
return localizeStringArray(_dayNames);
}

public NSArray<String> monthNames() {
if (hasBinding("monthNames"))
return (NSArray<String>)valueForBinding("monthNames");
return localizeStringArray(_monthNames);
}

/**
* Sets up AjaxOptions prior to rendering.
Expand All @@ -154,8 +192,11 @@ public void appendToResponse(WOResponse res, WOContext ctx) {

// The "constant" form of AjaxOption is used so that we can rename the bindings or convert the values
ajaxOptionsArray.addObject(new AjaxConstantOption("format", "format", format(), AjaxOption.STRING));
ajaxOptionsArray.addObject(new AjaxOption("month_names", "monthNames", null, AjaxOption.ARRAY));
ajaxOptionsArray.addObject(new AjaxOption("day_names", "dayNames", null, AjaxOption.ARRAY));
ajaxOptionsArray.addObject(new AjaxOption("month_names", "monthNames", monthNames(), AjaxOption.ARRAY));
ajaxOptionsArray.addObject(new AjaxOption("day_names", "dayNames", dayNames(), AjaxOption.ARRAY));

// FL Added to support start day, defaults to 0 (Sunday - choice made in calendar.js).
ajaxOptionsArray.addObject(new AjaxOption("start_day", "startDay", startDay(), AjaxOption.NUMBER));

ajaxOptionsArray.addObject(new AjaxOption("onDateSelect", AjaxOption.SCRIPT));
ajaxOptionsArray.addObject(new AjaxOption("fireEvent", AjaxOption.BOOLEAN));
Expand Down
24 changes: 20 additions & 4 deletions Frameworks/Ajax/Ajax/WebServerResources/calendar.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
AUTHOR:
Stuart Rackham <srackham@methods.co.nz>
Chuck Hill: minor extensions and Wonder compatability
Fredrik Lindren: added start day
LICENSE:
This source code is released under the MIT license.
Expand Down Expand Up @@ -329,6 +330,11 @@ function calendar_update() {
var m = calendar.month_date.getMonth();
var y = calendar.month_date.getFullYear();
var day1 = calendar.month_date.getDay(); // Day of week: 0..6 of first day of the month.
if (day1 - calendar.start_day < 0) // FL Adjust for start_day
day1 = 7 + day1 - calendar.start_day;
else
day1 = day1 - calendar.start_day;

get_element('calendar_header').innerHTML = calendar.month_names[m].substr(0,3).toUpperCase()+ ' ' + y;
get_element('calendar_prev_month').onclick = calendar_prev_month;
get_element('calendar_next_month').onclick = calendar_next_month;
Expand All @@ -347,8 +353,11 @@ function calendar_update() {
styles = 'selected';
if (dates_equal(date, new Date()))
styles += ' today';
if ( i % 7 == 0 || i % 7 == 1)
styles += ' weekend';
var dayIndex=(((i-1) % 7)+calendar.start_day) % 7; // FL Adjust for start_day
if ( dayIndex == 0 || dayIndex == 6)
styles += ' weekend ';
if ( dayIndex == 0 ) // FL Added class holiday to sundays
styles += 'holiday ';
el.onmouseover = calendar_over;
el.onmouseout = calendar_out;
el.onclick = calendar_click;
Expand Down Expand Up @@ -396,6 +405,11 @@ function calendar_open(input_element, options) {
if(options.fireEvent == false) {
calendar.fireEvent = false;
}

// FL Added to support diffrent start days. Defaults to 0 (Sunday).
if (options.start_day) {
calendar.start_day = options.start_day
}
// CH: Done add init of new options

if (options.day_names) {
Expand All @@ -408,8 +422,9 @@ function calendar_open(input_element, options) {
// Set day name cells.
var day_names = calendar.element.getElementsByTagName('tr')[1].childNodes;
for (var i=0; i < day_names.length; i++) {
day_names[i].innerHTML = calendar.day_names[i].substr(0,3);
if ( i == 0 || i == 6)
var dayIndex=(i+calendar.start_day) % 7; // FL Adjust for start_day
day_names[i].innerHTML = calendar.day_names[dayIndex].substr(0,3);
if ( dayIndex == 0 || dayIndex == 6)
day_names[i].className += ' weekend';
}
var images_dir = options.images_dir || '.';
Expand Down Expand Up @@ -523,6 +538,7 @@ calendar = { // Calendar properties.
input_element: undefined, // Calendar input element, set by calendar_show().
onDateSelect: undefined, // CH: add function called when user selects a date
fireEvent: true, // CH: add should event listener for text field be fired upon date select?
start_day: 0, // FL: Start day, defaults to 0 Sunday.
input_date: undefined, // Date value of input element, set by calendar_show().
month_date: undefined, // First day of calendar month.
format: undefined, // The date display format, set by calendar_show().
Expand Down

0 comments on commit c8b999c

Please sign in to comment.