Commit 7f8bc29c149eb0b9587d18f2efbbecd785d8e071

Authored by bernard
1 parent 327ce896

Added internationalization support.

Added new version of fullcalendar.
Added listeners for dateRangeSelectedEvent.
... ... @@ -177,6 +177,41 @@
177 177 <description>The fully qualified Java class name for the listener</description>
178 178 </property>
179 179 </listener>
  180 +<listener>
  181 + <name>dateRangeSelectedListener</name>
  182 + <property existintag="true" exist="true" el="true" elonly="true">
  183 + <name>binding</name>
  184 + <classname>org.richfaces.scheduleDateRangeChangedListener</classname>
  185 + <description>The attribute takes a value-binding expression for a component property of
  186 + a backing bean
  187 + </description>
  188 + </property>
  189 + <listenerclass>
  190 + org.richfaces.component.event.ScheduleDateRangeSelectedListener
  191 + </listenerclass>
  192 + <componentclass>
  193 + org.richfaces.component.event.ScheduleListenerEventsProducer
  194 + </componentclass>
  195 + <eventclass>
  196 + org.richfaces.component.event.ScheduleDateRangeSelectedEvent
  197 + </eventclass>
  198 + <taghandler generate="true">
  199 + <classname>
  200 + org.richfaces.taglib.ScheduleDateRangeSelectedListenerTagHandler
  201 + </classname>
  202 + </taghandler>
  203 + <tag generate="true">
  204 + <classname>
  205 + org.richfaces.taglib.DateRangeSelectedListenerTag
  206 + </classname>
  207 + </tag>
  208 +
  209 + <property existintag="true" exist="true" el="false">
  210 + <name>type</name>
  211 + <classname>java.lang.String</classname>
  212 + <description>The fully qualified Java class name for the listener</description>
  213 + </property>
  214 +</listener>
180 215
181 216 <listener>
182 217 <name>dateSelectedListener</name>
... ...
... ... @@ -364,6 +364,56 @@
364 364 <defaultvalue>null</defaultvalue>
365 365 </property>
366 366 <property>
  367 + <name>selectable</name>
  368 + <classname>java.lang.Boolean</classname>
  369 + <description>
  370 + Allows a user to highlight multiple days or timeslots by clicking and dragging.
  371 + To let the user make selections by clicking and dragging, this option must be set to true.
  372 + default: false
  373 + </description>
  374 + <defaultvalue>null</defaultvalue>
  375 + </property>
  376 + <property>
  377 + <name>selectHelper</name>
  378 + <classname>java.lang.Boolean</classname>
  379 + <description>
  380 + Whether to draw a "placeholder" event while the user is dragging.
  381 + A value of true will draw a "placeholder" event while the user
  382 + is dragging (similar to what Google Calendar does for its week
  383 + and day views). A value of false (the default) will draw
  384 + the standard highlighting over each cell.
  385 + default: false
  386 + </description>
  387 + <defaultvalue>null</defaultvalue>
  388 + </property>
  389 + <property>
  390 + <name>unselectAuto</name>
  391 + <classname>java.lang.Boolean</classname>
  392 + <description>
  393 + Whether clicking elsewhere on the page will cause the current
  394 + selection to be cleared.
  395 + This option can only take effect when selectable is set to true.
  396 + default: true
  397 + </description>
  398 + <defaultvalue>null</defaultvalue>
  399 + </property>
  400 + <property>
  401 + <name>unselectCancel</name>
  402 + <classname>java.lang.String</classname>
  403 + <description>
  404 + A way to specify elements that will ignore the unselectAuto option.
  405 + Clicking on elements that match this jQuery selector will prevent
  406 + the current selection from being cleared (due to the unselectAuto option).
  407 + This option is useful if you have a "Create an event" form that
  408 + shows up in response to the user making a selection. When the user
  409 + clicks on this form, you probably don't want to the current selection
  410 + to go away. Thus, you should add a class to your form such as "my-form",
  411 + and set the unselectAuto option to ".my-form".
  412 + default: ''
  413 + </description>
  414 + <defaultvalue>null</defaultvalue>
  415 + </property>
  416 + <property>
367 417 <name>disableDragging</name>
368 418 <classname>java.lang.Boolean</classname>
369 419 <description>
... ... @@ -491,6 +541,14 @@
491 541 <defaultvalue>null</defaultvalue>
492 542 </property>
493 543 <property>
  544 + <name>onDateRangeSelected</name>
  545 + <classname>java.lang.String</classname>
  546 + <description>
  547 + <!--TODO add description here-->
  548 + </description>
  549 + <defaultvalue>null</defaultvalue>
  550 + </property>
  551 + <property>
494 552 <name>styleClass</name>
495 553 <classname>java.lang.String</classname>
496 554 <description>
... ... @@ -527,6 +585,11 @@
527 585 </property>
528 586
529 587 <property elonly="true" attachedstate="true">
  588 + <name>dateRangeSelectedListener</name>
  589 + <classname>javax.faces.el.MethodBinding</classname>
  590 + </property>
  591 +
  592 + <property elonly="true" attachedstate="true">
530 593 <name>dateSelectedListener</name>
531 594 <classname>javax.faces.el.MethodBinding</classname>
532 595 </property>
... ...
1 1 package org.richfaces.component;
2 2
3   -import org.richfaces.component.event.ScheduleViewChangedEvent;
4   -import org.richfaces.component.event.ScheduleDateRangeChangedEvent;
5   -import org.richfaces.component.event.ScheduleItemResizeEvent;
6   -import org.richfaces.component.event.ScheduleItemSelectedEvent;
7 3 import org.ajax4jsf.context.AjaxContext;
8 4 import org.ajax4jsf.model.DataVisitor;
9 5 import org.ajax4jsf.model.ExtendedDataModel;
  6 +import org.richfaces.component.event.*;
  7 +import org.richfaces.component.model.DateRange;
10 8
11 9 import javax.el.ELContext;
12 10 import javax.el.ValueExpression;
... ... @@ -24,17 +22,6 @@ import java.text.DateFormat;
24 22 import java.text.SimpleDateFormat;
25 23 import java.util.*;
26 24
27   -import org.richfaces.component.event.ScheduleDateRangeChangedListener;
28   -import org.richfaces.component.event.ScheduleDateSelectedEvent;
29   -import org.richfaces.component.event.ScheduleDateSelectedListener;
30   -import org.richfaces.component.event.ScheduleItemSelectedListener;
31   -import org.richfaces.component.event.ScheduleItemMoveEvent;
32   -import org.richfaces.component.event.ScheduleItemMoveListener;
33   -import org.richfaces.component.event.ScheduleItemResizeListener;
34   -import org.richfaces.component.event.ScheduleListenerEventsProducer;
35   -import org.richfaces.component.event.ScheduleViewChangedListener;
36   -import org.richfaces.component.model.DateRange;
37   -
38 25 public abstract class UISchedule extends UIComponentBase implements ScheduleCommonViewAttributes, ScheduleListenerEventsProducer {
39 26
40 27 public static final String COMPONENT_TYPE = "org.richfaces.Schedule";
... ... @@ -147,6 +134,22 @@ public abstract class UISchedule extends UIComponentBase implements ScheduleComm
147 134
148 135 public abstract void setEditable(Boolean editable);
149 136
  137 + public abstract Boolean getSelectable();
  138 +
  139 + public abstract void setSelectable(Boolean selectable);
  140 +
  141 + public abstract Boolean getSelectHelper();
  142 +
  143 + public abstract void setSelectHelper(Boolean selectHelper);
  144 +
  145 + public abstract Boolean getUnselectAuto();
  146 +
  147 + public abstract void setUnselectAuto(Boolean unselectAuto);
  148 +
  149 + public abstract String getUnselectCancel();
  150 +
  151 + public abstract void setUnselectCancel(String unselectCancel);
  152 +
150 153 public abstract Boolean getDisableDragging();
151 154
152 155 public abstract void setDisableDragging(Boolean disableDragging);
... ... @@ -211,7 +214,12 @@ public abstract class UISchedule extends UIComponentBase implements ScheduleComm
211 214
212 215 public abstract void setOnDateSelected(String onDaySelected);
213 216
  217 + public abstract String getOnDateRangeSelected();
  218 +
  219 + public abstract void setOnDateRangeSelected(String onDateRangeSelected);
  220 +
214 221 // TODO do we use MethodBinding or MethodExpression?
  222 +
215 223 public abstract MethodBinding getItemMoveListener();
216 224
217 225 public abstract void setItemMoveListener(MethodBinding listener);
... ... @@ -232,6 +240,10 @@ public abstract class UISchedule extends UIComponentBase implements ScheduleComm
232 240
233 241 public abstract void setDateRangeChangedListener(MethodBinding listener);
234 242
  243 + public abstract MethodBinding getDateRangeSelectedListener();
  244 +
  245 + public abstract void setDateRangeSelectedListener(MethodBinding listener);
  246 +
235 247 public abstract MethodBinding getDateSelectedListener();
236 248
237 249 public abstract void setDateSelectedListener(MethodBinding listener);
... ... @@ -295,6 +307,13 @@ public abstract class UISchedule extends UIComponentBase implements ScheduleComm
295 307 if (expression != null) {
296 308 expression.invoke(facesContext, new Object[]{event});
297 309 }
  310 + } else if (event instanceof ScheduleDateRangeSelectedEvent) {
  311 + super.broadcast(event);
  312 + FacesContext facesContext = getFacesContext();
  313 + MethodBinding expression = getDateRangeSelectedListener();
  314 + if (expression != null) {
  315 + expression.invoke(facesContext, new Object[]{event});
  316 + }
298 317 }
299 318 }
300 319
... ... @@ -316,7 +335,7 @@ public abstract class UISchedule extends UIComponentBase implements ScheduleComm
316 335 DataModel dataModel = getDataModel();
317 336 if (dataModel instanceof ExtendedDataModel) {
318 337 DataVisitor visitor = new DataVisitor() {
319   - //TODO Is this fine? or should we stack rowKeys and not use dataModel later on. I'don't know business rules of extendedDataModel, just used it to did once pagination with underlying EntityQuery from Seam
  338 + //TODO Is this fine? or should we stack rowKeys and not use dataModel later on. I'don't know business rules of extendedDataModel, just used it once to do pagination with underlying EntityQuery from Seam
320 339
321 340 public void process(FacesContext context, Object rowKey, Object argument) throws IOException {
322 341 }
... ... @@ -595,6 +614,18 @@ public abstract class UISchedule extends UIComponentBase implements ScheduleComm
595 614 return (ScheduleDateRangeChangedListener[]) getFacesListeners(ScheduleDateRangeChangedListener.class);
596 615 }
597 616
  617 + public void addDateRangeSelectedListener(ScheduleDateRangeSelectedListener listener) {
  618 + addFacesListener(listener);
  619 + }
  620 +
  621 + public void removeDateRangeSelectedListener(ScheduleDateRangeSelectedListener listener) {
  622 + removeFacesListener(listener);
  623 + }
  624 +
  625 + public ScheduleDateRangeSelectedListener[] getDateRangeSelectedListeners() {
  626 + return (ScheduleDateRangeSelectedListener[]) getFacesListeners(ScheduleDateRangeSelectedListener.class);
  627 + }
  628 +
598 629 public void addDateSelectedListener(ScheduleDateSelectedListener listener) {
599 630 addFacesListener(listener);
600 631 }
... ...
  1 +package org.richfaces.component.event;
  2 +
  3 +import javax.faces.component.UIComponent;
  4 +import javax.faces.event.FacesEvent;
  5 +import javax.faces.event.FacesListener;
  6 +import java.util.Date;
  7 +
  8 +public class ScheduleDateRangeSelectedEvent extends FacesEvent {
  9 +
  10 + private Date startDate;
  11 + private Date endDate;
  12 + private boolean allDay;
  13 +
  14 + public ScheduleDateRangeSelectedEvent(UIComponent component, Date startDate, Date endDate, boolean allDay) {
  15 + super(component);
  16 + this.startDate = startDate;
  17 + this.endDate = endDate;
  18 + this.allDay = allDay;
  19 + }
  20 +
  21 + public boolean isAppropriateListener(FacesListener facesListener) {
  22 + return facesListener instanceof ScheduleDateSelectedListener;
  23 + }
  24 +
  25 + public void processListener(FacesListener facesListener) {
  26 + ((ScheduleDateRangeSelectedListener) facesListener).dateRangeSelected(this);
  27 + }
  28 +
  29 + public Date getStartDate() {
  30 + return startDate;
  31 + }
  32 +
  33 + public Date getEndDate() {
  34 + return endDate;
  35 + }
  36 +
  37 + public boolean isAllDay() {
  38 + return allDay;
  39 + }
  40 +
  41 + @Override
  42 + public String toString() {
  43 + return getClass().getSimpleName() + "[startDate=" + startDate + ";endDate=" + endDate + ";allDay=" + allDay + "]";
  44 + }
  45 +}
... ...
  1 +package org.richfaces.component.event;
  2 +
  3 +import javax.faces.event.FacesListener;
  4 +
  5 +public interface ScheduleDateRangeSelectedListener extends FacesListener {
  6 +
  7 + void dateRangeSelected(ScheduleDateRangeSelectedEvent event);
  8 +}
... ...
... ... @@ -3,26 +3,44 @@ package org.richfaces.component.event;
3 3 public interface ScheduleListenerEventsProducer {
4 4
5 5 void addItemSelectedListener(ScheduleItemSelectedListener listener);
  6 +
6 7 void removeItemSelectedListener(ScheduleItemSelectedListener listener);
  8 +
7 9 ScheduleItemSelectedListener[] getItemSelectedListeners();
8 10
9 11 void addItemMoveListener(ScheduleItemMoveListener listener);
  12 +
10 13 void removeItemMoveListener(ScheduleItemMoveListener listener);
  14 +
11 15 ScheduleItemMoveListener[] getItemMoveListeners();
12 16
13 17 void addItemResizeListener(ScheduleItemResizeListener listener);
  18 +
14 19 void removeItemResizeListener(ScheduleItemResizeListener listener);
  20 +
15 21 ScheduleItemResizeListener[] getItemResizeListeners();
16 22
17 23 void addViewChangedListener(ScheduleViewChangedListener listener);
  24 +
18 25 void removeViewChangedListener(ScheduleViewChangedListener listener);
  26 +
19 27 ScheduleViewChangedListener[] getViewChangedListeners();
20 28
21 29 void addDateRangeChangedListener(ScheduleDateRangeChangedListener listener);
  30 +
22 31 void removeDateRangeChangedListener(ScheduleDateRangeChangedListener listener);
  32 +
23 33 ScheduleDateRangeChangedListener[] getDateRangeChangedListeners();
24 34
  35 + void addDateRangeSelectedListener(ScheduleDateRangeSelectedListener listener);
  36 +
  37 + void removeDateRangeSelectedListener(ScheduleDateRangeSelectedListener listener);
  38 +
  39 + ScheduleDateRangeSelectedListener[] getDateRangeSelectedListeners();
  40 +
25 41 void addDateSelectedListener(ScheduleDateSelectedListener listener);
  42 +
26 43 void removeDateSelectedListener(ScheduleDateSelectedListener listener);
  44 +
27 45 ScheduleDateSelectedListener[] getDateSelectedListeners();
28 46 }
... ...
1 1 package org.richfaces.renderkit;
2 2
3   -import java.util.Locale;
4   -import org.richfaces.component.event.ScheduleViewChangedEvent;
5   -import org.richfaces.component.event.ScheduleDateRangeChangedEvent;
6   -import org.richfaces.component.event.ScheduleItemResizeEvent;
7   -import org.richfaces.component.event.ScheduleItemSelectedEvent;
8 3 import org.ajax4jsf.javascript.JSFunction;
9 4 import org.ajax4jsf.javascript.JSFunctionDefinition;
10 5 import org.ajax4jsf.javascript.JSObject;
... ... @@ -12,21 +7,15 @@ import org.ajax4jsf.javascript.JSReference;
12 7 import org.ajax4jsf.renderkit.AjaxComponentRendererBase;
13 8 import org.ajax4jsf.renderkit.AjaxRendererUtils;
14 9 import org.richfaces.component.*;
  10 +import org.richfaces.component.event.*;
15 11
  12 +import javax.faces.FacesException;
16 13 import javax.faces.component.NamingContainer;
17 14 import javax.faces.component.UIComponent;
18 15 import javax.faces.context.FacesContext;
19 16 import javax.faces.context.ResponseWriter;
20 17 import java.io.IOException;
21   -import java.util.Calendar;
22   -import java.util.Date;
23   -import java.util.HashMap;
24   -import java.util.Map;
25   -
26   -import javax.faces.FacesException;
27   -
28   -import org.richfaces.component.event.ScheduleDateSelectedEvent;
29   -import org.richfaces.component.event.ScheduleItemMoveEvent;
  18 +import java.util.*;
30 19
31 20 public abstract class ScheduleRendererBase extends AjaxComponentRendererBase {
32 21
... ... @@ -36,6 +25,7 @@ public abstract class ScheduleRendererBase extends AjaxComponentRendererBase {
36 25 public static final String DATE_RANGE_CHANGED_EVENT = "dateRangeChanged";
37 26 public static final String VIEW_CHANGED_EVENT = "viewChanged";
38 27 public static final String DATE_SELECTED_EVENT = "dateSelected";
  28 + public static final String DATE_RANGE_SELECTED_EVENT = "dateRangeSelected";
39 29 public static final String AJAX_MODE = "ajax";
40 30 public static final String SERVER_MODE = "server";
41 31 public static final String CLIENT_MODE = "client";
... ... @@ -50,7 +40,7 @@ public abstract class ScheduleRendererBase extends AjaxComponentRendererBase {
50 40 private static final String VIEW_PARAM = "view";
51 41
52 42 protected Object createSubmitEventFunction(FacesContext context, UISchedule component) {
53   - JSFunction jsFunction = null;
  43 + JSFunction jsFunction;
54 44 Map<String, Object> params = new HashMap<String, Object>();
55 45 params.put(getFieldId(context, component, START_DATE_PARAM), new JSReference(START_DATE_PARAM));
56 46 params.put(getFieldId(context, component, END_DATE_PARAM), new JSReference(END_DATE_PARAM));
... ... @@ -115,6 +105,11 @@ public abstract class ScheduleRendererBase extends AjaxComponentRendererBase {
115 105 Date startDate = new Date(Long.parseLong(startDateParam) * 1000);
116 106 boolean allDay = Boolean.parseBoolean(allDayParam);
117 107 new ScheduleDateSelectedEvent(component, startDate, allDay).queue();
  108 + } else if (DATE_RANGE_SELECTED_EVENT.equals(eventTypeParam)) {
  109 + Date startDate = new Date(Long.parseLong(startDateParam) * 1000);
  110 + Date endDate = new Date(Long.parseLong(endDateParam) * 1000);
  111 + boolean allDay = Boolean.parseBoolean(allDayParam);
  112 + new ScheduleDateRangeSelectedEvent(component, startDate, endDate, allDay).queue();
118 113 }
119 114 } catch (NumberFormatException ex) {
120 115 throw new FacesException("Cannot convert request parmeters", ex);
... ... @@ -126,7 +121,7 @@ public abstract class ScheduleRendererBase extends AjaxComponentRendererBase {
126 121 ResponseWriter writer = context.getResponseWriter();
127 122 String clientId = component.getClientId(context);
128 123 Locale locale = context.getViewRoot().getLocale();
129   - writer.writeText(new JSObject("RichFaces.Schedule", clientId, locale.getLanguage(),
  124 + writer.writeText(new JSObject("RichFaces.Schedule", clientId, locale.toString(),
130 125 getOptions(component),
131 126 DATE_RANGE_CHANGED_EVENT,
132 127 ITEM_SELECTED_EVENT,
... ... @@ -134,6 +129,7 @@ public abstract class ScheduleRendererBase extends AjaxComponentRendererBase {
134 129 ITEM_RESIZE_EVENT,
135 130 VIEW_CHANGED_EVENT,
136 131 DATE_SELECTED_EVENT,
  132 + DATE_RANGE_SELECTED_EVENT,
137 133 createSubmitEventFunction(context, component)).toScript(),
138 134 null);
139 135 }
... ... @@ -190,6 +186,10 @@ public abstract class ScheduleRendererBase extends AjaxComponentRendererBase {
190 186 addOptionIfSet("minTime", schedule.getMinTime(), options);
191 187 addOptionIfSet("maxTime", schedule.getMaxTime(), options);
192 188 addOptionIfSet("editable", schedule.getEditable(), options);
  189 + addOptionIfSet("selectable", schedule.getSelectable(), options);
  190 + addOptionIfSet("selectHelper", schedule.getSelectHelper(), options);
  191 + addOptionIfSet("unselectAuto", schedule.getUnselectAuto(), options);
  192 + addOptionIfSet("unselectCancel", schedule.getUnselectCancel(), options);
193 193 addOptionIfSet("disableDragging", schedule.getDisableDragging(), options);
194 194 addOptionIfSet("disableResizing", schedule.getDisableResizing(), options);
195 195 addOptionIfSet("dragRevertDuration", schedule.getDragRevertDuration(), options);
... ... @@ -216,6 +216,7 @@ public abstract class ScheduleRendererBase extends AjaxComponentRendererBase {
216 216 addOptionIfSet("onItemMouseout", schedule.getOnItemMouseout(), options);
217 217 addOptionIfSet("onViewDisplay", schedule.getOnViewDisplay(), options);
218 218 addOptionIfSet("onDateSelected", schedule.getOnDateSelected(), options);
  219 + addOptionIfSet("onDateRangeSelected", schedule.getOnDateRangeSelected(), options);
219 220 if (schedule.getDate() != null) {
220 221 Calendar calendar = Calendar.getInstance();
221 222 calendar.setTime(schedule.getDate());
... ...
1 1 package org.richfaces.renderkit.html.scripts;
2 2
  3 +import org.ajax4jsf.resource.ClientScript;
  4 +import org.ajax4jsf.resource.ResourceContext;
  5 +import org.apache.commons.logging.Log;
  6 +import org.apache.commons.logging.LogFactory;
  7 +
  8 +import javax.faces.application.Application;
  9 +import javax.faces.context.FacesContext;
3 10 import java.io.ByteArrayInputStream;
4 11 import java.io.InputStream;
  12 +import java.io.UnsupportedEncodingException;
5 13 import java.util.Locale;
6 14 import java.util.MissingResourceException;
7 15 import java.util.ResourceBundle;
8   -import javax.faces.FactoryFinder;
9   -import javax.faces.context.ExternalContext;
10   -import javax.faces.context.FacesContext;
11   -import javax.faces.context.FacesContextFactory;
12   -import org.ajax4jsf.resource.InternetResourceBase;
13   -import org.ajax4jsf.resource.ResourceContext;
14 16
15   -public class ScheduleMessages extends InternetResourceBase {
  17 +public class ScheduleMessages extends ClientScript {
  18 +
  19 + public static final String BUNDLE_NAME = "org.richfaces.component.UIScheduleMessages";
  20 + private static final String MESSAGE_KEY_BASE = "org.richfaces.component.UISchedule.";
  21 + private static final Log log = LogFactory.getLog(ClientScript.class);
  22 +// private Locale recentLocale;
16 23
17 24 @Override
18 25 public InputStream getResourceAsStream(ResourceContext context) {
19 26 //TODO how to access messages from here if user keeps them somewhere else?
20   - String language = "pl";
21   - Locale locale = new Locale(language);
22 27 ClassLoader loader = Thread.currentThread().getContextClassLoader();
23   -//TODO load default locale if specific is null
24   - ResourceBundle bundle = ResourceBundle.getBundle("org.richfaces.component.scheduleMessages", locale, loader);
  28 + FacesContext facesContext = FacesContext.getCurrentInstance();
  29 + Application application = facesContext.getApplication();
  30 + Locale locale = application.getViewHandler().calculateLocale(facesContext);
  31 +// recentLocale = locale;
  32 + ResourceBundle applicationBundle = ResourceBundle.getBundle(application.getMessageBundle(), locale, loader);
  33 + ResourceBundle stockBundle = ResourceBundle.getBundle(BUNDLE_NAME, locale, loader);
  34 + String[] months = new String[]{"JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE", "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER"};
  35 + String[] days = new String[]{"SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY"};
25 36 StringBuilder out = new StringBuilder();
26   - out.append("RichFaces.Schedule.prototype.messages=jQuery.extend(RichFaces.Schedule.prototype.messages,{").append("'").append(locale).append("':{").append("monthNames:[");
27   - String[] months = new String[]{"JANUARY","FEBRUARY"};
28   - for (int i = 0; i < months.length; i++) {
29   - out.append("'");
30   -//TODO Handle MissingResourceException
31   -//TODO Escape message strings
32   - try {
33   - out.append(escape(bundle.getString("org.richfaces.component.UISchedule.monthNames." + months[i])));
34   - } catch (MissingResourceException e) {
35   - out.append(escape(months[i]));
  37 + out.append("RichFaces.Schedule.prototype.messages=jQuery.extend(RichFaces.Schedule.prototype.messages,{").append("'").append(locale.toString()).append("':{");
  38 + out.append("allDayText:'").append(escape(getMessageFromBundle(MESSAGE_KEY_BASE + "allDay", applicationBundle, stockBundle))).append("',");
  39 + appendArray(out, applicationBundle, stockBundle, "monthNames", "monthNames", months);
  40 + out.append(",");
  41 + appendArray(out, applicationBundle, stockBundle, "monthNamesShort", "monthNamesShort", months);
  42 + out.append(",");
  43 + appendArray(out, applicationBundle, stockBundle, "dayNames", "dayNames", days);
  44 + out.append(",");
  45 + appendArray(out, applicationBundle, stockBundle, "dayNamesShort", "dayNamesShort", days);
  46 + out.append(",");
  47 + appendMap(out, applicationBundle, stockBundle, "buttonText", "buttonTexts", new String[]{"prev", "next", "prevYear", "nextYear", "today", "month", "day", "week"});
  48 + out.append("}").append("})");
  49 + try {
  50 +// TODO where to get encoding from? It should match properties file's encoding, but probably be converted to response encoding
  51 + return new ByteArrayInputStream(out.toString().getBytes(application.getViewHandler().calculateCharacterEncoding(facesContext)));
  52 + } catch (UnsupportedEncodingException e) {
  53 + throw new RuntimeException(e);
  54 + }
  55 + }
  56 +
  57 + private void appendArray(StringBuilder out, ResourceBundle applicationBundle, ResourceBundle stockBundle, String jsPropertyName, String prefix, String[] keys) {
  58 + String key;
  59 + out.append(jsPropertyName).append(":[");
  60 + for (int i = 0; i < keys.length; i++) {
  61 + key = MESSAGE_KEY_BASE + prefix + "." + keys[i];
  62 + out.append("'").append(escape(getMessageFromBundle(key, applicationBundle, stockBundle))).append("'");
  63 + if (i + 1 < keys.length) {
  64 + out.append(",");
36 65 }
37   - out.append("'");
38   - if (i + 1 < months.length) {
  66 + }
  67 + out.append("]");
  68 + }
  69 +
  70 + private void appendMap(StringBuilder out, ResourceBundle applicationBundle, ResourceBundle stockBundle, String jsPropertyName, String prefix, String[] keys) {
  71 + String key;
  72 + out.append(jsPropertyName).append(":{");
  73 + for (int i = 0; i < keys.length; i++) {
  74 + key = MESSAGE_KEY_BASE + prefix + "." + keys[i];
  75 + out.append(keys[i]).append(":").append("'").append(escape(getMessageFromBundle(key, applicationBundle, stockBundle))).append("'");
  76 + if (i + 1 < keys.length) {
39 77 out.append(",");
40 78 }
41 79 }
42   - out.append("]").append("}").append("})");
43   - return new ByteArrayInputStream(out.toString().getBytes());
  80 + out.append("}");
  81 + }
  82 +
  83 + private String getMessageFromBundle(String key, ResourceBundle applicationBundle, ResourceBundle stockBundle) {
  84 + try {
  85 + return applicationBundle.getString(key);
  86 + } catch (MissingResourceException e) {
  87 + try {
  88 + return stockBundle.getString(key);
  89 + } catch (MissingResourceException e1) {
  90 + if (log.isWarnEnabled()) {
  91 + log.warn("Cannot find resource " + e1.getKey() + " in bundle " + e1.getClassName());
  92 + }
  93 + return "";
  94 + }
  95 + }
44 96 }
45 97
46 98 private String escape(String message) {
47   - return message.replaceAll("'", "\\'");
  99 + return message.replaceAll("'", "\\\\'");
  100 + }
  101 +
  102 + @Override
  103 + public String getJavaScript() {
  104 + return getClass().getCanonicalName();
  105 + }
  106 +
  107 + @Override
  108 + public boolean requireFacesContext() {
  109 + return true;
48 110 }
  111 +//TODO if locale changes then recreate this resource
  112 +// @Override
  113 +// public boolean isCacheable(ResourceContext resourceContext) {
  114 +// if (resourceContext instanceof FacesResourceContext) {
  115 +// FacesContext facesContext = ((FacesResourceContext) resourceContext).getFacesContext();
  116 +// Locale locale = facesContext.getApplication().getViewHandler().calculateLocale(facesContext);
  117 +
  118 + // if (locale != null && !locale.equals(recentLocale)) {
  119 +// return false;
  120 +// }
  121 +// }
  122 +// return super.isCacheable(resourceContext);
  123 +// }
  124 + public boolean isCacheable(ResourceContext resourceContext) {
  125 + return false;
  126 + }
  127 +
49 128 }
... ...
  1 +org.richfaces.component.UISchedule.allDay=All day
  2 +org.richfaces.component.UISchedule.monthNames.JANUARY=January
  3 +org.richfaces.component.UISchedule.monthNames.FEBRUARY=Fabruary
  4 +org.richfaces.component.UISchedule.monthNames.MARCH=March
  5 +org.richfaces.component.UISchedule.monthNames.APRIL=April
  6 +org.richfaces.component.UISchedule.monthNames.MAY=May
  7 +org.richfaces.component.UISchedule.monthNames.JUNE=June
  8 +org.richfaces.component.UISchedule.monthNames.JULY=July
  9 +org.richfaces.component.UISchedule.monthNames.AUGUST=August
  10 +org.richfaces.component.UISchedule.monthNames.SEPTEMBER=September
  11 +org.richfaces.component.UISchedule.monthNames.OCTOBER=October
  12 +org.richfaces.component.UISchedule.monthNames.NOVEMBER=November
  13 +org.richfaces.component.UISchedule.monthNames.DECEMBER=December
  14 +org.richfaces.component.UISchedule.monthNamesShort.JANUARY=Jan
  15 +org.richfaces.component.UISchedule.monthNamesShort.FEBRUARY=Feb
  16 +org.richfaces.component.UISchedule.monthNamesShort.MARCH=Mar
  17 +org.richfaces.component.UISchedule.monthNamesShort.APRIL=Apr
  18 +org.richfaces.component.UISchedule.monthNamesShort.MAY=May
  19 +org.richfaces.component.UISchedule.monthNamesShort.JUNE=Jun
  20 +org.richfaces.component.UISchedule.monthNamesShort.JULY=Jul
  21 +org.richfaces.component.UISchedule.monthNamesShort.AUGUST=Aug
  22 +org.richfaces.component.UISchedule.monthNamesShort.SEPTEMBER=Sep
  23 +org.richfaces.component.UISchedule.monthNamesShort.OCTOBER=Oct
  24 +org.richfaces.component.UISchedule.monthNamesShort.NOVEMBER=Nov
  25 +org.richfaces.component.UISchedule.monthNamesShort.DECEMBER=Dec
  26 +org.richfaces.component.UISchedule.dayNames.SUNDAY=Sunday
  27 +org.richfaces.component.UISchedule.dayNames.MONDAY=Monday
  28 +org.richfaces.component.UISchedule.dayNames.TUESDAY=Tuesday
  29 +org.richfaces.component.UISchedule.dayNames.WEDNESDAY=Wednesday
  30 +org.richfaces.component.UISchedule.dayNames.THURSDAY=Thursday
  31 +org.richfaces.component.UISchedule.dayNames.FRIDAY=Friday
  32 +org.richfaces.component.UISchedule.dayNames.SATURDAY=Saturday
  33 +org.richfaces.component.UISchedule.dayNamesShort.SUNDAY=Sun
  34 +org.richfaces.component.UISchedule.dayNamesShort.MONDAY=Mon
  35 +org.richfaces.component.UISchedule.dayNamesShort.TUESDAY=Tue
  36 +org.richfaces.component.UISchedule.dayNamesShort.WEDNESDAY=Wed
  37 +org.richfaces.component.UISchedule.dayNamesShort.THURSDAY=Thu
  38 +org.richfaces.component.UISchedule.dayNamesShort.FRIDAY=Fri
  39 +org.richfaces.component.UISchedule.dayNamesShort.SATURDAY=Sat
  40 +org.richfaces.component.UISchedule.buttonTexts.prev=&nbsp;&#9668;&nbsp;
  41 +org.richfaces.component.UISchedule.buttonTexts.next=&nbsp;&#9658;&nbsp;
  42 +org.richfaces.component.UISchedule.buttonTexts.prevYear=&nbsp;&lt;&lt;&nbsp;
  43 +org.richfaces.component.UISchedule.buttonTexts.nextYear=&nbsp;&gt;&gt;&nbsp;
  44 +org.richfaces.component.UISchedule.buttonTexts.today=today
  45 +org.richfaces.component.UISchedule.buttonTexts.month=month
  46 +org.richfaces.component.UISchedule.buttonTexts.week=week
  47 +org.richfaces.component.UISchedule.buttonTexts.day=day
\ No newline at end of file
... ...
  1 +org.richfaces.component.UISchedule.allDay=Ca\u0142y dzie\u0144
  2 +org.richfaces.component.UISchedule.monthNames.JANUARY=Stycze\u0144
  3 +org.richfaces.component.UISchedule.monthNames.FEBRUARY=Luty
  4 +org.richfaces.component.UISchedule.monthNames.MARCH=Marzec
  5 +org.richfaces.component.UISchedule.monthNames.APRIL=Kwiecie\u0144
  6 +org.richfaces.component.UISchedule.monthNames.MAY=Maj
  7 +org.richfaces.component.UISchedule.monthNames.JUNE=Czerwiec
  8 +org.richfaces.component.UISchedule.monthNames.JULY=Lipiec
  9 +org.richfaces.component.UISchedule.monthNames.AUGUST=Sierpie\u0144
  10 +org.richfaces.component.UISchedule.monthNames.SEPTEMBER=Wrzesie\u0144
  11 +org.richfaces.component.UISchedule.monthNames.OCTOBER=Pa\u017Adziernik
  12 +org.richfaces.component.UISchedule.monthNames.NOVEMBER=Listopad
  13 +org.richfaces.component.UISchedule.monthNames.DECEMBER=Grudzie\u0144
  14 +org.richfaces.component.UISchedule.monthNamesShort.JANUARY=Sty
  15 +org.richfaces.component.UISchedule.monthNamesShort.FEBRUARY=Lut
  16 +org.richfaces.component.UISchedule.monthNamesShort.MARCH=Mar
  17 +org.richfaces.component.UISchedule.monthNamesShort.APRIL=Kwi
  18 +org.richfaces.component.UISchedule.monthNamesShort.MAY=Maj
  19 +org.richfaces.component.UISchedule.monthNamesShort.JUNE=Cze
  20 +org.richfaces.component.UISchedule.monthNamesShort.JULY=Lip
  21 +org.richfaces.component.UISchedule.monthNamesShort.AUGUST=Sie
  22 +org.richfaces.component.UISchedule.monthNamesShort.SEPTEMBER=Wrz
  23 +org.richfaces.component.UISchedule.monthNamesShort.OCTOBER=Pa\u017A
  24 +org.richfaces.component.UISchedule.monthNamesShort.NOVEMBER=Lis
  25 +org.richfaces.component.UISchedule.monthNamesShort.DECEMBER=Gru
  26 +org.richfaces.component.UISchedule.dayNames.SUNDAY=Niedziela
  27 +org.richfaces.component.UISchedule.dayNames.MONDAY=Poniedzia\u0142ek
  28 +org.richfaces.component.UISchedule.dayNames.TUESDAY=Wtorek
  29 +org.richfaces.component.UISchedule.dayNames.WEDNESDAY=\u015Aroda
  30 +org.richfaces.component.UISchedule.dayNames.THURSDAY=Czwartek
  31 +org.richfaces.component.UISchedule.dayNames.FRIDAY=Pi\u0105tek
  32 +org.richfaces.component.UISchedule.dayNames.SATURDAY=Sobota
  33 +org.richfaces.component.UISchedule.dayNamesShort.SUNDAY=Nie
  34 +org.richfaces.component.UISchedule.dayNamesShort.MONDAY=Pon
  35 +org.richfaces.component.UISchedule.dayNamesShort.TUESDAY=Wto
  36 +org.richfaces.component.UISchedule.dayNamesShort.WEDNESDAY=\u015Aro
  37 +org.richfaces.component.UISchedule.dayNamesShort.THURSDAY=Czw
  38 +org.richfaces.component.UISchedule.dayNamesShort.FRIDAY=Pi\u0105
  39 +org.richfaces.component.UISchedule.dayNamesShort.SATURDAY=Sob
  40 +org.richfaces.component.UISchedule.buttonTexts.prev=&nbsp;&#9668;&nbsp;
  41 +org.richfaces.component.UISchedule.buttonTexts.next=&nbsp;&#9658;&nbsp;
  42 +org.richfaces.component.UISchedule.buttonTexts.prevYear=&nbsp;&lt;&lt;&nbsp;
  43 +org.richfaces.component.UISchedule.buttonTexts.nextYear=&nbsp;&gt;&gt;&nbsp;
  44 +org.richfaces.component.UISchedule.buttonTexts.today=Dzi\u015B
  45 +org.richfaces.component.UISchedule.buttonTexts.month=Miesi\u0105c
  46 +org.richfaces.component.UISchedule.buttonTexts.week=Tydzie\u0144
  47 +org.richfaces.component.UISchedule.buttonTexts.day=Dzie\u0144
\ No newline at end of file
... ...
1   -org.richfaces.component.UISchedule.monthNames.JANUARY=January
\ No newline at end of file
... ... @@ -4,14 +4,15 @@ window.RichFaces.Schedule = (function() {
4 4 return Math.round(date.getTime() / 1000);
5 5 };
6 6
7   - return function(id, locale, options, loadItemsEventName, itemSelectedEventName, itemMovedEventName, itemResizedEventName, viewChangedEventName, daySelectedEventName, submitEventFunction) {
  7 + return function(id, locale, options, loadItemsEventName, itemSelectedEventName, itemMovedEventName, itemResizedEventName, viewChangedEventName, daySelectedEventName, dateRangeSelectedEventName, submitEventFunction) {
8 8 this.id = id;
  9 + var component;
9 10 /**
10 11 * submitEventFunction should have following params:
11 12 * event,view,eventType,itemId,startDate,endDate,dayDelta,minuteDelta,allDay,callback
12 13 */
13 14 this.submitEventFunction = submitEventFunction;
14   - options = jQuery.extend(options, this.messages[locale]);
  15 + options = jQuery.extend(this.messages[locale], options);
15 16 var elt = document.getElementById(id);
16 17 if (!elt) {
17 18 throw "No element with id '" + id + "' found.";
... ... @@ -190,6 +191,30 @@ window.RichFaces.Schedule = (function() {
190 191 }
191 192 selectedView = view;
192 193 };
  194 + var onDateRangeSelected = function(startDate, endDate, allDay) {
  195 + if (!component.fullCalendar('option', 'selectable')) {
  196 + return;
  197 + }
  198 + if (options.onDateRangeSelected != null) {
  199 + var result = eval("(function(){" + options.onDateRangeSelected + "})()");
  200 + if (result != null) {
  201 + return;
  202 + }
  203 + }
  204 + if (_this.submitEventFunction != null) {
  205 + _this.submitEventFunction({},
  206 + null,
  207 + dateRangeSelectedEventName,
  208 + null, formatDateParam(startDate), formatDateParam(endDate), null, null, allDay,
  209 + function(request, event, data) {
  210 + component.fullCalendar('refetchEvents');
  211 + component.fullCalendar('unselect');
  212 + }
  213 + );
  214 + } else {
  215 + component.fullCalendar('unselect');
  216 + }
  217 + };
193 218 options = jQuery.extend({
194 219 events: fillCalendarFunction,
195 220 eventDragStart: itemDragStart,
... ... @@ -202,11 +227,13 @@ window.RichFaces.Schedule = (function() {
202 227 eventMouseover: itemMouseover,
203 228 eventMouseout: itemMouseout,
204 229 viewDisplay: viewDisplay,
205   - dayClick: dayClick
  230 + dayClick: dayClick,
  231 + select: onDateRangeSelected
206 232 }, options);
207 233 jQuery(document).ready(function() {
208   - jQuery(elt).fullCalendar(options);
  234 + component = jQuery(elt).fullCalendar(options);
209 235 });
210 236 };
211 237
212 238 }());
  239 +window.RichFaces.Schedule.prototype.messages = {};
\ No newline at end of file
... ...
1 1 <?xml version="1.0" encoding="UTF-8"?>
2 2 <f:root
3   - xmlns:f="http://jsf.exadel.com/template"
4   - xmlns:vcp=" http://jsf.exadel.com/vcp"
5   - xmlns:ui=" http://jsf.exadel.com/ui"
6   - xmlns:x=" http://jsf.exadel.com/vcp"
7   - xmlns:u="http://jsf.exadel.com/util"
8   - xmlns:h="http://jsf.exadel.com/header"
9   - xmlns:jsp="http://java.sun.com/JSP/Page"
10   - xmlns:c="http://java.sun.com/jstl/core"
11   - class="org.richfaces.renderkit.html.ScheduleRenderer"
12   - baseclass="org.richfaces.renderkit.ScheduleRendererBase"
13   - component="org.richfaces.component.UISchedule">
  3 + xmlns:f="http://jsf.exadel.com/template"
  4 + xmlns:vcp=" http://jsf.exadel.com/vcp"
  5 + xmlns:ui=" http://jsf.exadel.com/ui"
  6 + xmlns:x=" http://jsf.exadel.com/vcp"
  7 + xmlns:u="http://jsf.exadel.com/util"
  8 + xmlns:h="http://jsf.exadel.com/header"
  9 + xmlns:jsp="http://java.sun.com/JSP/Page"
  10 + xmlns:c="http://java.sun.com/jstl/core"
  11 + class="org.richfaces.renderkit.html.ScheduleRenderer"
  12 + baseclass="org.richfaces.renderkit.ScheduleRendererBase"
  13 + component="org.richfaces.component.UISchedule">
14 14 <f:clientid var="clientId"/>
15 15 <h:styles>/org/richfaces/renderkit/html/css/fullcalendar.css</h:styles>
16 16 <h:scripts>org.ajax4jsf.javascript.AjaxScript,
... ... @@ -21,18 +21,18 @@
21 21 /org/richfaces/renderkit/html/scripts/ui.draggable.js,
22 22 /org/richfaces/renderkit/html/scripts/ui.resizable.js,
23 23 /org/richfaces/renderkit/html/scripts/fullcalendar.js,
24   - /org/richfaces/renderkit/html/scripts/richfaces.schedule.js
  24 + /org/richfaces/renderkit/html/scripts/richfaces.schedule.js,
  25 + org.richfaces.renderkit.html.scripts.ScheduleMessages
25 26 </h:scripts>
26   - <jsp:directive.page import="org.ajax4jsf.renderkit.AjaxRendererUtils"/>
27   - <jsp:directive.page import="org.ajax4jsf.javascript.JSFunction"/>
28   - <jsp:directive.page import="org.ajax4jsf.javascript.JSLiteral"/>
29   - <jsp:directive.page import="org.ajax4jsf.renderkit.RendererUtils.HTML"/>
30 27 <jsp:scriptlet>
31   - <![CDATA[org.richfaces.component.util.FormUtil.throwEnclFormReqExceptionIfNeed(context,component);]]>
  28 + <![CDATA[org.richfaces.component.util.FormUtil.throwEnclFormReqExceptionIfNeed(context, component);]]>
32 29 </jsp:scriptlet>
33   - <div id="#{clientId}" class="rich-schedule #{component.attributes['styleClass']}" x:passThruWithExclusions="value,name,type,id"></div>
  30 + <div id="#{clientId}" class="rich-schedule #{component.attributes['styleClass']}"
  31 + x:passThruWithExclusions="value,name,type,id"></div>
34 32 <input type="hidden" name="#{clientId}" id="#{clientId}"/>
35 33 <script type="text/javascript">
36   - <f:call name="writeInitFunction"/>
  34 + <
  35 + f:call
  36 + name = "writeInitFunction" / >
37 37 </script>
38 38 </f:root>
\ No newline at end of file
... ...
Please register or login to post a comment