almost at 1.2
This commit is contained in:
parent
6b9f6de931
commit
b386089544
|
@ -3,6 +3,9 @@ version 1.2
|
||||||
- cssClass attribute for CalEvents
|
- cssClass attribute for CalEvents
|
||||||
- multiple event sources (using an array for the 'events' option)
|
- multiple event sources (using an array for the 'events' option)
|
||||||
- the 'events' option for fullCalendar() and gcalFullCalendar() is now optional
|
- the 'events' option for fullCalendar() and gcalFullCalendar() is now optional
|
||||||
|
- bugs w/ month date formatting
|
||||||
|
- change behavior for parsing number strings (now as unix timestamp)
|
||||||
|
- allow multiple classes in cssClass
|
||||||
|
|
||||||
version 1.1 (5/10/09)
|
version 1.1 (5/10/09)
|
||||||
- Added the following options:
|
- Added the following options:
|
||||||
|
|
|
@ -188,3 +188,6 @@ latex_documents = [
|
||||||
|
|
||||||
# If false, no module index is generated.
|
# If false, no module index is generated.
|
||||||
#latex_use_modindex = True
|
#latex_use_modindex = True
|
||||||
|
|
||||||
|
highlight_language = 'javascript'
|
||||||
|
|
||||||
|
|
455
docs/index.txt
455
docs/index.txt
|
@ -1,31 +1,21 @@
|
||||||
|
|
||||||
.. highlight:: javascript
|
Main Usage
|
||||||
|
==========
|
||||||
|
|
||||||
Usage
|
The following code initializes a FullCalendar within an element with ID 'calendar'::
|
||||||
=====
|
|
||||||
|
|
||||||
.. code-block:: javascript
|
$('#calendar').fullCalendar({
|
||||||
|
|
||||||
$('#myCalendar').fullCalendar({
|
|
||||||
// initializes a calendar
|
|
||||||
// see options, data provider, and triggered events below
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#myCalendar').fullCalendar('nextMonth'); // move ahead one month
|
// put your options here
|
||||||
|
|
||||||
$('#myCalendar').fullCalendar('currentMonth'); // go to current month
|
})
|
||||||
|
|
||||||
$('#myCalendar').fullCalendar('prevMonth'); // move back one month
|
|
||||||
|
|
||||||
$('#myCalendar').fullCalendar('gotoMonth', year, month);
|
|
||||||
// go to an arbitrary month. 'month' is zero-based
|
|
||||||
|
|
||||||
$('#myCalender').fullCalendar('refresh');
|
|
||||||
// re-fetch events for the current month
|
|
||||||
|
|
||||||
|
|
||||||
Options
|
.. _GeneralOptions:
|
||||||
=======
|
|
||||||
|
General Options
|
||||||
|
===============
|
||||||
|
|
||||||
**year**, **month**: integers
|
**year**, **month**: integers
|
||||||
The month that will be displayed when the calendar first loads.
|
The month that will be displayed when the calendar first loads.
|
||||||
|
@ -35,18 +25,11 @@ Options
|
||||||
Determines if all events on the calendar can be dragged & dropped. If
|
Determines if all events on the calendar can be dragged & dropped. If
|
||||||
``true``, requires `jQuery UI <http://jqueryui.com/>`_ core and draggables.
|
``true``, requires `jQuery UI <http://jqueryui.com/>`_ core and draggables.
|
||||||
Can be overridden on a per-event basis with the ``draggable`` property of
|
Can be overridden on a per-event basis with the ``draggable`` property of
|
||||||
each :ref:`CalEvent <CalEvent>` object.
|
each :ref:`CalEvent <CalEvents>`.
|
||||||
|
|
||||||
**fixedWeeks**: boolean, default:``true``
|
**fixedWeeks**: boolean, default:``true``
|
||||||
If ``true``, the calendar will always be 6 weeks tall. If ``false``, the
|
If ``true``, the calendar will always be 6 weeks tall. If ``false``, the
|
||||||
calendar's height will vary per month.
|
calendar's height will vary per month.
|
||||||
|
|
||||||
**weekStart**: integer, default:``0``
|
|
||||||
The day-of-week each week begins. 0 = Sunday (default),
|
|
||||||
1 = Monday (for UK users), 2 = Tuesday, etc.
|
|
||||||
|
|
||||||
**rightToLeft**: boolean, default:``false``
|
|
||||||
Displays the calendar right-to-left (for Arabic and Hebrew languages)
|
|
||||||
|
|
||||||
**abbrevDayHeadings**: boolean, default:``true``
|
**abbrevDayHeadings**: boolean, default:``true``
|
||||||
Whether to display "Sun" versus "Sunday" for days of the week.
|
Whether to display "Sun" versus "Sunday" for days of the week.
|
||||||
|
@ -55,42 +38,28 @@ Options
|
||||||
Determines whether a title such as "January 2009" will be displayed at the
|
Determines whether a title such as "January 2009" will be displayed at the
|
||||||
top of the calendar.
|
top of the calendar.
|
||||||
|
|
||||||
**titleFormat**: string, default:``"Y F"``
|
**titleFormat**: string, default:``"F Y"``
|
||||||
A string defining format of the title above the calendar. The default
|
A string defining the format of the title above the calendar. The default
|
||||||
"Y F" creates strings such as "January 2009". Use the following
|
"F Y" creates strings such as "January 2009". Consult the
|
||||||
codes in your format string (similar to the PHP's date function):
|
:ref:`$.fullCalendar.formatDate <formatDate>` documentation for a full
|
||||||
|
list of commands.
|
||||||
* **F** - January through December
|
|
||||||
* **m** - 01 through 12 (leading zeros)
|
|
||||||
* **M** - Jan through Dec
|
|
||||||
* **n** - 1 through 12
|
|
||||||
* **Y** - Examples: 1999 or 2003
|
|
||||||
* **y** - Examples: 99 or 03
|
|
||||||
|
|
||||||
**buttons**: boolean/hash, default:``true``
|
**buttons**: boolean/hash, default:``true``
|
||||||
Determines whether navigation buttons will be displayed at the top of the
|
Determines whether navigation buttons will be displayed at the top of the
|
||||||
calendar. A hash with keys 'today', 'prev', and 'next' will determine if
|
calendar. A hash such as ``{today:false, prev:true, next:true}`` can be
|
||||||
each individual button is displayed. Strings can be provided to change
|
provided to display only certain buttons. A hash such as
|
||||||
each button's text.
|
``{today:false, prev:"Last Month", next:"Next Month"}`` can be provided
|
||||||
|
to display only certain buttons AND change a button's text.
|
||||||
|
|
||||||
**showTime**: boolean/ ``"guess"``, default:``"guess"``
|
**showTime**: boolean/ ``"guess"``, default:``"guess"``
|
||||||
Determines if times will be displayed before each event's title.
|
Determines if times will be displayed before each event's title.
|
||||||
``"guess"`` displays times only for events with non-zero start or end times.
|
``"guess"`` displays times only for events with non-zero start or end times.
|
||||||
|
|
||||||
**timeFormat**: string, default: ``"gx"``
|
**timeFormat**: string, default: ``"gx"``
|
||||||
A string defining the format of dislayed of event times. The default "gx"
|
A string defining the format of dislayed event times. The default "gx"
|
||||||
creates a string such as "9a". Use the following codes in your format
|
creates a string such as "9a". Consult the
|
||||||
string (similar to PHP's date function):
|
:ref:`$.fullCalendar.formatDate <formatDate>`
|
||||||
|
documentation for a full list of commands.
|
||||||
* **a** - am or pm
|
|
||||||
* **A** - AM or PM
|
|
||||||
* **x** - a or p
|
|
||||||
* **X** - A or P
|
|
||||||
* **g** - 1 through 12 (hour)
|
|
||||||
* **G** - 0 through 23 (hour, military time)
|
|
||||||
* **h** - 01 through 12 (hour, leading zeros)
|
|
||||||
* **H** - 00 through 23 (hour, military time and leading zeros)
|
|
||||||
* **i** - 00 to 59 (minute, leading zeros)
|
|
||||||
|
|
||||||
**eventDragOpacity**: float
|
**eventDragOpacity**: float
|
||||||
The opacity of an event element while it is being dragged (0.0 - 1.0)
|
The opacity of an event element while it is being dragged (0.0 - 1.0)
|
||||||
|
@ -99,21 +68,91 @@ Options
|
||||||
Controls the duration (in milliseconds) of the animation of an event
|
Controls the duration (in milliseconds) of the animation of an event
|
||||||
snapping back into place.
|
snapping back into place.
|
||||||
|
|
||||||
|
|
||||||
.. _EventDataProvider:
|
|
||||||
|
.. _TriggeredActions:
|
||||||
|
|
||||||
Event Data Provider
|
Triggered Actions
|
||||||
===================
|
=================
|
||||||
|
|
||||||
|
The following options are *functions* that get executed every time something
|
||||||
|
special happens:
|
||||||
|
|
||||||
|
**monthDisplay**: function(year, month, monthTitle)
|
||||||
|
Triggered once when the calendar loads and every time the
|
||||||
|
calendar's month is changed. ``month`` is zero-based. ``monthTitle``
|
||||||
|
contains the new title of the month (ex: "January 2009")
|
||||||
|
|
||||||
|
**loading**: function(isLoading)
|
||||||
|
Triggered with a ``true`` argument when the calendar begins fetching
|
||||||
|
events via AJAX. Triggered with ``false`` when done.
|
||||||
|
|
||||||
|
**resize**: function()
|
||||||
|
Triggered after the calendar has recovered from a resize (due to the window
|
||||||
|
being resized).
|
||||||
|
|
||||||
|
``this`` is set to the main element
|
||||||
|
|
||||||
|
**dayClick**: function(dayDate)
|
||||||
|
Triggered when the user clicks on a day. ``dayDate`` is a Date object with
|
||||||
|
it's time set to 00:00:00.
|
||||||
|
|
||||||
|
``this`` is set to the TD element of the clicked day.
|
||||||
|
|
||||||
|
**eventRender**: function(calEvent, element)
|
||||||
|
Triggered before an element is rendered for the given :ref:`CalEvent <CalEvents>`.
|
||||||
|
``element`` is the jQuery element that will be used by default. You can modify
|
||||||
|
this element or return a brand new element that will be used instead.
|
||||||
|
|
||||||
|
This function is great for attaching other jQuery plugins to each event
|
||||||
|
element, such as a `qTip <http://craigsworks.com/projects/qtip/docs/>`_
|
||||||
|
tooltip effect.
|
||||||
|
|
||||||
|
**eventClick**, **eventMouseover**, **eventMouseout**: function(calEvent, jsEvent)
|
||||||
|
Triggered on click/mouseover/mouseout actions for an event.
|
||||||
|
``calEvent`` holds that event's information (date, title, etc).
|
||||||
|
``jsEvent`` holds the native javascript event (with information about click position, etc).
|
||||||
|
|
||||||
|
``this`` is set to the event's element
|
||||||
|
|
||||||
|
For ``eventClick``, return ``false`` to prevent the browser from going to
|
||||||
|
the event's URL.
|
||||||
|
|
||||||
|
**eventDragStart**, **eventDragStop**: function(calEvent, jsEvent, ui)
|
||||||
|
Triggered before/after an event is dragged (but not necessarily moved to a new day).
|
||||||
|
``calEvent`` holds that event's information (date, title, etc).
|
||||||
|
``jsEvent`` holds the native javascript event (with information about click position, etc).
|
||||||
|
``ui`` holds the jQuery UI object.
|
||||||
|
|
||||||
|
``this`` is set to the event's element
|
||||||
|
|
||||||
|
**eventDrop**: function(calEvent, dayDelta, jsEvent, ui)
|
||||||
|
Triggered when dragging stops and the event has moved to a *different* day.
|
||||||
|
``dayDelta`` holds the number of days the event was moved forward (a positive number)
|
||||||
|
or backwards (a negative number).
|
||||||
|
|
||||||
|
``dayDelta`` is elegant for dealing with multi-day and repeating events.
|
||||||
|
If updating a remote database, just add the ``dayDelta`` to the start
|
||||||
|
and end times of all events with the given ``calEvent.id``
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.. _EventSources:
|
||||||
|
|
||||||
|
Event Feeds and Sources
|
||||||
|
=======================
|
||||||
|
|
||||||
|
The following options determine *how* events get on the calendar:
|
||||||
|
|
||||||
**events**: array/string/function
|
**events**: array/string/function
|
||||||
An array of :ref:`CalEvent` can be used to hardcode events into the
|
An array of :ref:`CalEvents <CalEvents>` can be used to hardcode events into the
|
||||||
calendar.
|
calendar.
|
||||||
|
|
||||||
Or, a URL can be provided. This URL should return JSON for an array of
|
Or, a URL can be provided. This URL should return JSON for an array of
|
||||||
:ref:`CalEvent`. GET parameters, determined by the ``startParam`` and
|
:ref:`CalEvents <CalEvents>`. GET parameters, determined by the
|
||||||
``endParam`` options, will be inserted into the URL. These parameters
|
``startParam`` and ``endParam`` options, will be inserted into the URL.
|
||||||
indicate the UNIX timestamp of the start of the first visible day
|
These parameters indicate the UNIX timestamp of the start of the first
|
||||||
(inclusive) and the end of the last visible day (exclusive).
|
visible day (inclusive) and the end of the last visible day (exclusive).
|
||||||
|
|
||||||
Or, a function can be provided for custom fetching. The function is
|
Or, a function can be provided for custom fetching. The function is
|
||||||
queried every time event data is needed. The function is passed a ``start``
|
queried every time event data is needed. The function is passed a ``start``
|
||||||
|
@ -140,91 +179,48 @@ Event Data Provider
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
**eventSources**: array
|
||||||
|
Similar to the ``events`` options, except one may specify *multiple* sources.
|
||||||
|
For example, one may specify an array of JSON URL's, an array of custom
|
||||||
|
functions, an array of hardcoded event arrays, or any combination.
|
||||||
|
|
||||||
**startParam**: string, default:``"start"``
|
**startParam**: string, default:``"start"``
|
||||||
A GET parameter of this name will be inserted into the URL when fetching
|
A GET parameter of this name will be inserted into the URL when fetching
|
||||||
events from a JSON script (when ``event`` is a URL string). The value
|
events from a JSON script. The value of this GET parameter will be a UNIX
|
||||||
of this GET parameter will be a UNIX timestamp denoting the start of the
|
timestamp denoting the start of the first visible day (inclusive).
|
||||||
first visible day (inclusive).
|
|
||||||
|
|
||||||
**endParam**: string, default:``"end"``
|
**endParam**: string, default:``"end"``
|
||||||
A GET parameter of this name will be inserted into the URL when fetching
|
A GET parameter of this name will be inserted into the URL when fetching
|
||||||
events from a JSON script (when ``event`` is a URL string). The value
|
events from a JSON script. The value of this GET parameter will be a UNIX
|
||||||
of this GET parameter will be a UNIX timestamp denoting the end of the
|
timestamp denoting the end of the last visible day (exclusive).
|
||||||
last visible day (exclusive).
|
|
||||||
|
|
||||||
**cacheParam**: string, default:``"_"``
|
**cacheParam**: string, default:``"_"``
|
||||||
When using a JSON url, a parameter of this name will
|
When using a JSON url, a parameter of this name will
|
||||||
automatically be inserted into the URL to prevent the browser from
|
automatically be inserted into the URL to prevent the browser from
|
||||||
caching the response. The value will be the current millisecond time.
|
caching the response. The value will be the current millisecond time.
|
||||||
|
|
||||||
.. _TriggeredEvents:
|
The following methods can be called on a FullCalendar that has already
|
||||||
|
been initialized:
|
||||||
Triggered Events
|
|
||||||
================
|
|
||||||
|
|
||||||
**monthDisplay**: function(year, month, monthTitle)
|
**.fullCalendar(** ``'addEventSource'``, **source)**
|
||||||
Triggered once when the calendar loads and every time the
|
Adds an event source. ``source`` may be an array/string/function just as in
|
||||||
calendar's month is changed. ``month`` is zero-based. ``monthTitle``
|
the ``events`` option. Events will be immediately fetched from this source
|
||||||
contains the new title of the month (ex: "January 2009")
|
and placed on the calendar.
|
||||||
|
|
||||||
|
**.fullCalendar(** ``'removeEventSource'``, **source)**
|
||||||
|
Remove an event source. ``source`` must be the original array/string/function.
|
||||||
|
|
||||||
**loading**: function(isLoading)
|
|
||||||
Triggered with a ``true`` argument when the calendar begins fetching
|
|
||||||
events via AJAX. Triggered with ``false`` when done.
|
.. _CalEvents:
|
||||||
|
|
||||||
**resize**: function()
|
|
||||||
Triggered after the calendar has recovered from a resize (due to the window
|
|
||||||
pane being resized).
|
|
||||||
|
|
||||||
``this`` is set to the main element
|
|
||||||
|
|
||||||
**dayClick**: function(dayDate)
|
|
||||||
Triggered when the user clicks on a day. ``dayDate`` is a Date object with
|
|
||||||
it's time set to 00:00:00.
|
|
||||||
|
|
||||||
``this`` is set to the TD element of the clicked day.
|
|
||||||
|
|
||||||
**eventRender**: function(calEvent, element)
|
|
||||||
Triggered before an element is rendered for the given ``calEvent``.
|
|
||||||
``element`` is the jQuery element that will be used by default. You can modify
|
|
||||||
this element or return a brand new element that will be used instead.
|
|
||||||
|
|
||||||
**eventClick**, **eventMouseover**, **eventMouseout**: function(calEvent, domEvent)
|
|
||||||
Triggered on click/mouseover/mouseout actions for an event.
|
|
||||||
``calEvent`` holds that event's information (date, title, etc).
|
|
||||||
``domEvent`` holds the native DOM event (with information about click position, etc).
|
|
||||||
|
|
||||||
``this`` is set to the event's TABLE element
|
|
||||||
|
|
||||||
For ``eventClick``, return ``false`` to prevent the browser from going to
|
|
||||||
calEvent's URL.
|
|
||||||
|
|
||||||
**eventDragStart**, **eventDragStop**: function(calEvent, domEvent, ui)
|
|
||||||
Triggered before/after an event is dragged (but not necessarily moved to a new day).
|
|
||||||
``calEvent`` holds that event's information (date, title, etc).
|
|
||||||
``domEvent`` holds the native DOM event (with information about click position, etc).
|
|
||||||
``ui`` holds the jQuery UI object.
|
|
||||||
|
|
||||||
``this`` is set to the event's TABLE element
|
|
||||||
|
|
||||||
**eventDrop**: function(calEvent, dayDelta, domEvent, ui)
|
|
||||||
Triggered when dragging stops and the event has moved to a *different* day.
|
|
||||||
``dayDelta`` holds the number of days the event was moved forward (a positive number)
|
|
||||||
or backwards (a negative number).
|
|
||||||
|
|
||||||
``dayDelta`` is elegant for dealing with multi-day and repeating events.
|
|
||||||
If updating a remote database, just add the ``dayDelta`` to the start
|
|
||||||
and end times of all events with the given ``calEvent.id``
|
|
||||||
|
|
||||||
|
|
||||||
.. _CalEvent:
|
|
||||||
|
|
||||||
CalEvent Objects
|
CalEvent Objects
|
||||||
================
|
================
|
||||||
|
|
||||||
A ``CalEvent`` is a data structure that frequents FullCalendar's API. It is
|
A CalEvent is a data structure that frequents FullCalendar's API. It is the
|
||||||
used when a custom event-fetcher needs to report to the :ref:`EventDataProvider`.
|
standardized currency used in :ref:`EventSources`. It is also passed to various
|
||||||
It is also used in various :ref:`TriggeredEvents`. Here are the properties of a
|
:ref:`Triggered Actions <TriggeredActions>`. Here are the properties of a
|
||||||
``CalEvent``\:
|
CalEvent:
|
||||||
|
|
||||||
**id**: integer/string,
|
**id**: integer/string,
|
||||||
Uniquely identifies the given event. Absolutely essential for multi-day
|
Uniquely identifies the given event. Absolutely essential for multi-day
|
||||||
|
@ -240,7 +236,7 @@ It is also used in various :ref:`TriggeredEvents`. Here are the properties of a
|
||||||
A javascript Date object indicating the date/time an event begins.
|
A javascript Date object indicating the date/time an event begins.
|
||||||
Events with ambiguous time-of-day should use 00:00:00.
|
Events with ambiguous time-of-day should use 00:00:00.
|
||||||
|
|
||||||
When reporting to the :ref:`EventDataProvider`, for convenience,
|
In an :ref:`Event Source <EventSources>`, for convenience,
|
||||||
one can also use a string in IETF format (ex: "Wed, 18 Oct 2009 13:00:00 EST"),
|
one can also use a string in IETF format (ex: "Wed, 18 Oct 2009 13:00:00 EST"),
|
||||||
a string in ISO8601 format (ex: "2009-11-05T13:15:30Z") or an integer
|
a string in ISO8601 format (ex: "2009-11-05T13:15:30Z") or an integer
|
||||||
UNIX timestamp.
|
UNIX timestamp.
|
||||||
|
@ -249,9 +245,9 @@ It is also used in various :ref:`TriggeredEvents`. Here are the properties of a
|
||||||
A javascript Date object indicating the date/time an event ends
|
A javascript Date object indicating the date/time an event ends
|
||||||
(exclusively). If an event has an ambiguous end time, ``end`` should be
|
(exclusively). If an event has an ambiguous end time, ``end`` should be
|
||||||
set to midnight of the next day. This is implied if ``end`` is omitted.
|
set to midnight of the next day. This is implied if ``end`` is omitted.
|
||||||
(For convenience with the :ref:`EventDataProvider`).
|
(For convenience with an :ref:`Event Source <EventSources>`).
|
||||||
|
|
||||||
IETF and ISO8601 strings can be used for the :ref:`EventDataProvider`.
|
IETF and ISO8601 strings can be used with an :ref:`Event Source <EventSources>`.
|
||||||
|
|
||||||
**draggable**: boolean (optional)
|
**draggable**: boolean (optional)
|
||||||
Overrides the master ``draggable`` property for this single event.
|
Overrides the master ``draggable`` property for this single event.
|
||||||
|
@ -259,20 +255,189 @@ It is also used in various :ref:`TriggeredEvents`. Here are the properties of a
|
||||||
**showTime**: boolean/ ``"guess"`` (optional)
|
**showTime**: boolean/ ``"guess"`` (optional)
|
||||||
Overrides the master ``showTime`` property for this single event.
|
Overrides the master ``showTime`` property for this single event.
|
||||||
|
|
||||||
When giving events to the :ref:`EventDataProvider`, one can include other
|
**className**: string/array (optional)
|
||||||
properties beyond the ones listed. This is useful if you want to earmark your
|
A CSS class (or array of classes) that will be attached to this event's
|
||||||
events with additional data to be retrieved later during a
|
element.
|
||||||
:ref:`Triggered Event <TriggeredEvents>`.
|
|
||||||
|
**source**: array/string/function (automatic)
|
||||||
|
A reference to the original array, JSON URL, or function the event
|
||||||
|
came from. Do not worry about populating this value, FullCalendar will
|
||||||
|
do this automatically.
|
||||||
|
|
||||||
|
The following methods can be called on a FullCalendar that has already been
|
||||||
|
initialized. These methods get/add/remove/update the event elements that
|
||||||
|
currently reside on the calendar. Note that when you are using a JSON feed or custom
|
||||||
|
event source, your event is never *permanently* deleted, because it may be
|
||||||
|
refetched from the source at a later time. It is up to the developer to delete
|
||||||
|
the event(s) from any database.
|
||||||
|
|
||||||
|
**.fullCalendar(** ``'addEvent'``, **calEvent)**
|
||||||
|
Add an event to the current month on-the-fly. ``calEvent`` is an object
|
||||||
|
containing at least an id, title, and start date.
|
||||||
|
|
||||||
|
**.fullCalendar(** ``'updateEvent'``, **calEvent)**
|
||||||
|
Report modifications to the given :ref:`CalEvent <CalEvents>` and redraw.
|
||||||
|
``calEvent`` must be the *actual CalEvent object*, as retrieved from a
|
||||||
|
:ref:`Triggered Action <TriggeredActions>` or ``getEventsById`` (see below).
|
||||||
|
A set of repeating events will all be affected.
|
||||||
|
|
||||||
|
**.fullCalendar(** ``'removeEvent'``, **calEventOrId)**
|
||||||
|
Remove elements belonging to the given :ref:`CalEvent <CalEvents>`. If the
|
||||||
|
event is repeating, all occurences of the event will be removed. The
|
||||||
|
second argument may be a CalEvent's ID, or the CalEvent object itself.
|
||||||
|
|
||||||
|
**.fullCalendar(** ``'getEventsById'`` , **eventId)**
|
||||||
|
Returns a list of :ref:`CalEvents <CalEvents>` with the given ID that are
|
||||||
|
currently being displayed.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Navigation Methods
|
||||||
|
==================
|
||||||
|
|
||||||
Extras
|
The following methods may be called on a FullCalendar that has already been
|
||||||
|
initialized:
|
||||||
|
|
||||||
|
**.fullCalendar(** ``'prevMonth'`` **)**
|
||||||
|
Visits the previous month.
|
||||||
|
|
||||||
|
**.fullCalendar(** ``'nextMonth'`` **)**
|
||||||
|
Visits the next month.
|
||||||
|
|
||||||
|
**.fullCalendar(** ``'gotoMonth'``, **year, month)**
|
||||||
|
Visits an arbitrary month. ``month`` is zero-based (0 is January, 1 is
|
||||||
|
February, etc).
|
||||||
|
|
||||||
|
**.fullCalendar(** ``'today'`` **)**
|
||||||
|
Visits the current month.
|
||||||
|
|
||||||
|
**.fullCalendar(** ``'refresh'`` **)**
|
||||||
|
Refetch and redraw the events for the current month.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Locale
|
||||||
======
|
======
|
||||||
|
|
||||||
FullCalendar provides some extra date utilities\:
|
Use the following options to change the calendar's locale:
|
||||||
|
|
||||||
|
**weekStart**: integer, default:``0``
|
||||||
|
The day-of-week each week begins. 0 = Sunday (default),
|
||||||
|
1 = Monday (for UK users), 2 = Tuesday, etc.
|
||||||
|
|
||||||
|
**rightToLeft**: boolean, default:``false``
|
||||||
|
Displays the calendar right-to-left (for Arabic and Hebrew)
|
||||||
|
|
||||||
|
The following *variables* may be reassigned or modified to globally change the
|
||||||
|
text for months and days:
|
||||||
|
|
||||||
|
**$.fullCalendar.monthNames**
|
||||||
|
Default: ``['January', 'February', 'March', ...]``
|
||||||
|
|
||||||
|
**$.fullCalendar.monthAbbrevs**
|
||||||
|
Default: ``['Jan', 'Feb', 'Mar', ...]``
|
||||||
|
|
||||||
|
**$.fullCalendar.dayNames**
|
||||||
|
Default: ``['Sunday', 'Monday', 'Tuesday', ...]``
|
||||||
|
|
||||||
|
**$.fullCalendar.dayAbbrevs**
|
||||||
|
Default: ``['Sun', 'Mon', 'Tue', ...]``
|
||||||
|
|
||||||
|
Notice these variables are attached to the main **$** jQuery object.
|
||||||
|
|
||||||
|
The :ref:`GeneralOptions` ``titleFormat`` and ``timeFormat`` may also be of
|
||||||
|
interest to those wanting to change locale.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
**$.parseISO8601(string, ignoreTimezone)**
|
Date Parsing and Formatting
|
||||||
Parses an ISO8601 string and returns a ``Date`` object
|
===========================
|
||||||
|
|
||||||
|
The following utilities are always available. These typically come in handy
|
||||||
|
when creating a custom event source:
|
||||||
|
|
||||||
|
.. _formatDate:
|
||||||
|
|
||||||
|
**$.fullCalendar.formatDate(date, format)**
|
||||||
|
Format a javascript Date object into a string. ``format`` may contain
|
||||||
|
one or more of the following commands (similar to PHP's date function):
|
||||||
|
|
||||||
|
* **F** - January through December
|
||||||
|
* **M** - Jan through Dec
|
||||||
|
* **n** - 1 through 12 (month)
|
||||||
|
* **m** - 01 through 12 (month, leading zeros)
|
||||||
|
* **Y** - Examples: 1999 or 2003
|
||||||
|
* **y** - Examples: 99 or 03
|
||||||
|
* **a** - am or pm
|
||||||
|
* **A** - AM or PM
|
||||||
|
* **x** - a or p
|
||||||
|
* **X** - A or P
|
||||||
|
* **g** - 1 through 12 (hour)
|
||||||
|
* **G** - 0 through 23 (hour, military time)
|
||||||
|
* **h** - 01 through 12 (hour, leading zeros)
|
||||||
|
* **H** - 00 through 23 (hour, military time and leading zeros)
|
||||||
|
* **i** - 00 to 59 (minute, leading zeros)
|
||||||
|
|
||||||
**$.ISO8601String(date)**
|
**$.fullCalendar.parseDate(string)**
|
||||||
Takes a ``Date`` object and returns an ISO8601 string
|
Parse a string and return a javascript Date object. The string may be
|
||||||
|
in ISO8601 format, IETF format, or a UNIX timestamp.
|
||||||
|
|
||||||
|
**$.fullCalendar.parseISO8601(string, ignoreTimezone)**
|
||||||
|
Parse an ISO8601 string into a javascript Date object.
|
||||||
|
|
||||||
|
Notice these functions are attached to the main **$** jQuery object.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Google Calendar
|
||||||
|
===============
|
||||||
|
|
||||||
|
To integrate with your Google Calendar, you must first **make your calendar public**:
|
||||||
|
|
||||||
|
#. In the Google Calendar interface, locate the "My Calendar" box on the left.
|
||||||
|
|
||||||
|
#. Click the arrow next to the calendar you need.
|
||||||
|
|
||||||
|
#. A menu will appear. Click "Share this calendar."
|
||||||
|
|
||||||
|
#. Check "Make this calendar public."
|
||||||
|
|
||||||
|
#. Make sure "Share only my free/busy information" is *unchecked*.
|
||||||
|
|
||||||
|
#. Click "Save."
|
||||||
|
|
||||||
|
Then, you must obtain your calendar's **XML feed URL**.
|
||||||
|
|
||||||
|
#. In the Google Calendar interface, locate the "My Calendar" box on the left
|
||||||
|
|
||||||
|
#. Click the arrow next to the calendar you need.
|
||||||
|
|
||||||
|
#. A menu will appear. Click "Calendar settings."
|
||||||
|
|
||||||
|
#. In the "Calendar Address" section of the screen, click the XML badge.
|
||||||
|
|
||||||
|
#. Your feed's URL will appear.
|
||||||
|
|
||||||
|
The API for integrating a Google Calendar feed has changed since
|
||||||
|
FullCalendar 1.1. The ``$.fullCalendar.gcalFeed`` function now produces
|
||||||
|
an event source that can be passed to the ``events`` or ``eventSources``
|
||||||
|
option::
|
||||||
|
|
||||||
|
$('#calendar').fullCalendar({
|
||||||
|
|
||||||
|
events: $.fullCalendar.gcalFeed(
|
||||||
|
"http://www.google.com/calendar/feeds/...", // feed URL
|
||||||
|
{ className: 'gcal-events' } // optional options
|
||||||
|
)
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
Here is a list of available options:
|
||||||
|
|
||||||
|
* **className** - CSS class to attach to each event from this Google Calendar
|
||||||
|
|
||||||
|
* **draggable** - whether to allow dragging (default: ``false``)
|
||||||
|
|
||||||
|
See *gcal.html* in the *examples* directory for a complete example.
|
||||||
|
|
||||||
|
|
7
docs/templates/layout.html
vendored
7
docs/templates/layout.html
vendored
|
@ -3,6 +3,13 @@
|
||||||
<? fullcalendar_nav() ?>
|
<? fullcalendar_nav() ?>
|
||||||
<? begin_content() ?>
|
<? begin_content() ?>
|
||||||
|
|
||||||
|
<div id='toc'>
|
||||||
|
<h1>Table of Contents</h1>
|
||||||
|
{{ toc }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='clear'></div>
|
||||||
|
|
||||||
{% block body %}{% endblock %}
|
{% block body %}{% endblock %}
|
||||||
|
|
||||||
<? end_content() ?>
|
<? end_content() ?>
|
||||||
|
|
|
@ -30,9 +30,12 @@
|
||||||
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
|
||||||
$('#calendar').gcalFullCalendar({
|
$('#calendar').fullCalendar({
|
||||||
// US Holidays
|
// US Holidays
|
||||||
events: 'http://www.google.com/calendar/feeds/usa__en%40holiday.calendar.google.com/public/basic',
|
events: $.fullCalendar.gcalFeed(
|
||||||
|
'http://www.google.com/calendar/feeds/usa__en%40holiday.calendar.google.com/public/basic',
|
||||||
|
{draggable: false, className: 'mygcal'}
|
||||||
|
),
|
||||||
eventClick: function(event) {
|
eventClick: function(event) {
|
||||||
window.open(event.url, 'gcalevent', 'width=700,height=600');
|
window.open(event.url, 'gcalevent', 'width=700,height=600');
|
||||||
return false;
|
return false;
|
||||||
|
|
660
fullcalendar.js
660
fullcalendar.js
|
@ -17,19 +17,30 @@
|
||||||
(function($) {
|
(function($) {
|
||||||
|
|
||||||
$.fn.fullCalendar = function(options) {
|
$.fn.fullCalendar = function(options) {
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Calls methods of a pre-existing instance
|
||||||
|
//
|
||||||
|
|
||||||
if (typeof options == 'string') {
|
if (typeof options == 'string') {
|
||||||
var args = Array.prototype.slice.call(arguments, 1);
|
var args = Array.prototype.slice.call(arguments, 1);
|
||||||
var ret; // ugly
|
var res;
|
||||||
this.each(function() {
|
this.each(function() {
|
||||||
var r = $.data(this, 'fullCalendar')[options].apply(this, args);
|
var r = $.data(this, 'fullCalendar')[options].apply(this, args);
|
||||||
if (typeof ret == 'undefined') ret = r;
|
if (typeof res == 'undefined') res = r;
|
||||||
});
|
});
|
||||||
if (typeof ret == 'undefined')
|
if (typeof res != 'undefined')
|
||||||
return this;
|
return res;
|
||||||
return ret;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Process options
|
||||||
|
//
|
||||||
|
|
||||||
options = options || {};
|
options = options || {};
|
||||||
|
|
||||||
var r2l = options.rightToLeft;
|
var r2l = options.rightToLeft;
|
||||||
|
@ -48,77 +59,94 @@
|
||||||
var weekStart = (options.weekStart || 0) % 7;
|
var weekStart = (options.weekStart || 0) % 7;
|
||||||
var timeFormat = options.timeFormat || 'gx';
|
var timeFormat = options.timeFormat || 'gx';
|
||||||
var titleFormat = options.titleFormat || (r2l ? 'Y F' : 'F Y');
|
var titleFormat = options.titleFormat || (r2l ? 'Y F' : 'F Y');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Rendering bug detection variables
|
||||||
|
//
|
||||||
|
|
||||||
var tdTopBug, trTopBug, tbodyTopBug, sniffBugs = true;
|
var tdTopBug, trTopBug, tbodyTopBug, sniffBugs = true;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
this.each(function() {
|
this.each(function() {
|
||||||
|
|
||||||
var date = options.year ? new Date(options.year, options.month || 0, 1) : new Date();
|
|
||||||
var start, end, today, numWeeks;
|
//
|
||||||
|
// Instance variables
|
||||||
|
//
|
||||||
|
|
||||||
|
var date = options.year ? // holds the year & month of current month
|
||||||
|
new Date(options.year, options.month || 0, 1) :
|
||||||
|
new Date();
|
||||||
|
var start, end; // first & last VISIBLE dates
|
||||||
|
var today;
|
||||||
|
var numWeeks;
|
||||||
var ignoreResizes = false;
|
var ignoreResizes = false;
|
||||||
|
|
||||||
var events = [];
|
var events = [];
|
||||||
|
var eventSources = options.eventSources || [];
|
||||||
|
if (options.events) eventSources.push(options.events);
|
||||||
|
|
||||||
var eventSources;
|
|
||||||
var eo = options.events;
|
|
||||||
if (eo) {
|
|
||||||
if (typeof eo == 'string' || $.isFunction(eo)) {
|
|
||||||
eventSources = [eo];
|
|
||||||
}else{
|
|
||||||
var item = eo[0];
|
|
||||||
if (item) {
|
|
||||||
if (typeof item == 'string' || $.isFunction(item))
|
|
||||||
eventSources = eo;
|
|
||||||
else {
|
|
||||||
eventSources = [eo];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else eventSources = [];
|
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Month navigation functions
|
||||||
|
//
|
||||||
|
|
||||||
function updateMonth() {
|
function refreshMonth() {
|
||||||
clearEvents();
|
clearEventElements();
|
||||||
render();
|
render();
|
||||||
}
|
}
|
||||||
|
|
||||||
function today() {
|
|
||||||
date = new Date();
|
|
||||||
updateMonth();
|
|
||||||
}
|
|
||||||
|
|
||||||
function prevMonth() {
|
function prevMonth() {
|
||||||
addMonths(date, -1);
|
addMonths(date, -1);
|
||||||
updateMonth();
|
refreshMonth();
|
||||||
}
|
}
|
||||||
|
|
||||||
function nextMonth() {
|
function nextMonth() {
|
||||||
addMonths(date, 1);
|
addMonths(date, 1);
|
||||||
updateMonth();
|
refreshMonth();
|
||||||
|
}
|
||||||
|
|
||||||
|
function gotoToday() {
|
||||||
|
date = new Date();
|
||||||
|
refreshMonth();
|
||||||
}
|
}
|
||||||
|
|
||||||
function gotoMonth(year, month) {
|
function gotoMonth(year, month) {
|
||||||
date = new Date(year, month, 1);
|
date = new Date(year, month, 1);
|
||||||
updateMonth();
|
refreshMonth();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Publicly accessible methods
|
||||||
|
//
|
||||||
|
|
||||||
$.data(this, 'fullCalendar', {
|
$.data(this, 'fullCalendar', {
|
||||||
today: today,
|
refresh: refreshMonth,
|
||||||
prevMonth: prevMonth,
|
prevMonth: prevMonth,
|
||||||
nextMonth: nextMonth,
|
nextMonth: nextMonth,
|
||||||
|
today: gotoToday,
|
||||||
gotoMonth: gotoMonth,
|
gotoMonth: gotoMonth,
|
||||||
refresh: updateMonth,
|
|
||||||
|
|
||||||
// event crud
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Event CRUD
|
||||||
|
//
|
||||||
|
|
||||||
addEvent: function(event) {
|
addEvent: function(event) {
|
||||||
events.push(normalizeEvent(event));
|
events.push(normalizeEvent(event));
|
||||||
clearEvents();
|
clearEventElements();
|
||||||
renderEvents();
|
renderEvents();
|
||||||
},
|
},
|
||||||
|
|
||||||
updateEvent: function(event) {
|
updateEvent: function(event) {
|
||||||
event.start = cleanDate(event.start);
|
event.start = $.fullCalendar.parseDate(event.start);
|
||||||
event.end = cleanDate(event.end);
|
event.end = $.fullCalendar.parseDate(event.end);
|
||||||
var startDelta = event.start - event._start;
|
var startDelta = event.start - event._start;
|
||||||
var msLength = event.end - event.start;
|
var msLength = event.end - event.start;
|
||||||
event._start = cloneDate(event.start);
|
event._start = cloneDate(event.start);
|
||||||
|
@ -126,8 +154,8 @@
|
||||||
var e = events[i];
|
var e = events[i];
|
||||||
if (e.id === event.id && e !== event) {
|
if (e.id === event.id && e !== event) {
|
||||||
e.start = new Date(e.start.getTime() + startDelta);
|
e.start = new Date(e.start.getTime() + startDelta);
|
||||||
e.end = new Date(e.start.getTime() + msLength);
|
|
||||||
e._start = cloneDate(e.start);
|
e._start = cloneDate(e.start);
|
||||||
|
e.end = new Date(e.start.getTime() + msLength);
|
||||||
for (var k in event) {
|
for (var k in event) {
|
||||||
if (k && k != 'start' && k != 'end' && k.charAt(0) != '_') {
|
if (k && k != 'start' && k != 'end' && k.charAt(0) != '_') {
|
||||||
e[k] = event[k];
|
e[k] = event[k];
|
||||||
|
@ -135,14 +163,16 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
clearEvents();
|
clearEventElements();
|
||||||
renderEvents();
|
renderEvents();
|
||||||
},
|
},
|
||||||
|
|
||||||
removeEvent: function(eventId) {
|
removeEvent: function(eventId) {
|
||||||
if (typeof eventId == 'object') {
|
if (typeof eventId == 'object') {
|
||||||
eventId = eventId.id;
|
eventId = eventId.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// remove from the 'events' array
|
||||||
var newEvents = [];
|
var newEvents = [];
|
||||||
for (var i=0; i<events.length; i++) {
|
for (var i=0; i<events.length; i++) {
|
||||||
if (events[i].id !== eventId) {
|
if (events[i].id !== eventId) {
|
||||||
|
@ -150,6 +180,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
events = newEvents;
|
events = newEvents;
|
||||||
|
|
||||||
// remove from static event sources
|
// remove from static event sources
|
||||||
for (var i=0; i<eventSources.length; i++) {
|
for (var i=0; i<eventSources.length; i++) {
|
||||||
var src = eventSources[i];
|
var src = eventSources[i];
|
||||||
|
@ -163,10 +194,11 @@
|
||||||
eventSources[i] = newSrc;
|
eventSources[i] = newSrc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
clearEvents();
|
|
||||||
|
clearEventElements();
|
||||||
renderEvents();
|
renderEvents();
|
||||||
},
|
},
|
||||||
|
|
||||||
getEventsById: function(eventId) {
|
getEventsById: function(eventId) {
|
||||||
var res = [];
|
var res = [];
|
||||||
for (var i=0; i<events.length; i++) {
|
for (var i=0; i<events.length; i++) {
|
||||||
|
@ -177,15 +209,23 @@
|
||||||
return res;
|
return res;
|
||||||
},
|
},
|
||||||
|
|
||||||
// event source crud
|
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Event Source CRUD
|
||||||
|
//
|
||||||
|
|
||||||
addEventSource: function(src) {
|
addEventSource: function(src) {
|
||||||
eventSources.push(src);
|
eventSources.push(src);
|
||||||
clearEvents();
|
fetchEventSource(src, function() {
|
||||||
renderEvents();
|
clearEventElements();
|
||||||
|
renderEvents();
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
removeEventSource: function(src) {
|
removeEventSource: function(src) {
|
||||||
|
|
||||||
|
// remove from 'eventSources' array
|
||||||
var newSources = [];
|
var newSources = [];
|
||||||
for (var i=0; i<eventSources.length; i++) {
|
for (var i=0; i<eventSources.length; i++) {
|
||||||
if (src !== eventSources[i]) {
|
if (src !== eventSources[i]) {
|
||||||
|
@ -193,7 +233,17 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
eventSources = newSources;
|
eventSources = newSources;
|
||||||
clearEvents();
|
|
||||||
|
// remove events from 'events' array
|
||||||
|
var newEvents = [];
|
||||||
|
for (var i=0; i<events.length; i++) {
|
||||||
|
if (events[i].source !== src) {
|
||||||
|
newEvents.push(events[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
events = newEvents;
|
||||||
|
|
||||||
|
clearEventElements();
|
||||||
renderEvents();
|
renderEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,16 +253,26 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************/
|
||||||
|
//
|
||||||
|
// Header & Table Rendering
|
||||||
|
//
|
||||||
|
/*******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Build one-time DOM elements (header, month container)
|
||||||
|
//
|
||||||
|
|
||||||
var titleElement, todayButton, monthElement, monthElementWidth;
|
var titleElement, todayButton, monthElement, monthElementWidth;
|
||||||
var header = $("<div class='full-calendar-header'/>").appendTo(this);
|
var header = $("<div class='full-calendar-header'/>").appendTo(this);
|
||||||
|
|
||||||
if (bo) {
|
if (bo) { // "button options"
|
||||||
var buttons = $("<div class='full-calendar-buttons'/>").appendTo(header);
|
var buttons = $("<div class='full-calendar-buttons'/>").appendTo(header);
|
||||||
var prevButton, nextButton;
|
var prevButton, nextButton;
|
||||||
if (bo == true || bo.today != false) {
|
if (bo == true || bo.today != false) {
|
||||||
todayButton = $("<input type='button' class='full-calendar-today' value='today'/>")
|
todayButton = $("<input type='button' class='full-calendar-today' value='today'/>")
|
||||||
.click(today);
|
.click(gotoToday);
|
||||||
if (typeof bo.today == 'string') todayButton.val(bo.today);
|
if (typeof bo.today == 'string') todayButton.val(bo.today);
|
||||||
buttons.append(todayButton);
|
buttons.append(todayButton);
|
||||||
}
|
}
|
||||||
|
@ -237,14 +297,13 @@
|
||||||
|
|
||||||
monthElement = $("<div class='full-calendar-month' style='position:relative'/>")
|
monthElement = $("<div class='full-calendar-month' style='position:relative'/>")
|
||||||
.appendTo($("<div class='full-calendar-month-wrap'/>").appendTo(this));
|
.appendTo($("<div class='full-calendar-month-wrap'/>").appendTo(this));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Build the TABLE cells for the current month. (calls event fetch+render code)
|
||||||
|
//
|
||||||
|
|
||||||
|
var thead, tbody, glass;
|
||||||
|
|
||||||
|
|
||||||
var thead, tbody, glass, monthTitle;
|
|
||||||
|
|
||||||
function render() {
|
function render() {
|
||||||
|
|
||||||
|
@ -253,7 +312,7 @@
|
||||||
clearTime(date);
|
clearTime(date);
|
||||||
var year = date.getFullYear();
|
var year = date.getFullYear();
|
||||||
var month = date.getMonth();
|
var month = date.getMonth();
|
||||||
monthTitle = formatTitle(date);
|
var monthTitle = $.fullCalendar.formatDate(date, titleFormat);
|
||||||
if (titleElement) titleElement.text(monthTitle);
|
if (titleElement) titleElement.text(monthTitle);
|
||||||
|
|
||||||
clearTime(date);
|
clearTime(date);
|
||||||
|
@ -276,9 +335,14 @@
|
||||||
todayButton.css('visibility', 'visible');
|
todayButton.css('visibility', 'visible');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var dayNames = $.fullCalendar.dayNames;
|
||||||
|
var dayAbbrevs = $.fullCalendar.dayAbbrevs;
|
||||||
|
|
||||||
if (!tbody) {
|
if (!tbody) {
|
||||||
|
|
||||||
|
// first time, build all cells from scratch
|
||||||
|
|
||||||
var table = $("<table style='width:100%'/>").appendTo(monthElement);
|
var table = $("<table style='width:100%'/>").appendTo(monthElement);
|
||||||
|
|
||||||
thead = "<thead><tr>";
|
thead = "<thead><tr>";
|
||||||
|
@ -313,6 +377,8 @@
|
||||||
}
|
}
|
||||||
tbody = $(tbody + "</tbody>").appendTo(table);
|
tbody = $(tbody + "</tbody>").appendTo(table);
|
||||||
|
|
||||||
|
// a protective coating over the TABLE
|
||||||
|
// intercepts mouse clicks and prevents text-selection
|
||||||
glass = $("<div style='position:absolute;top:0;left:0;z-index:1;width:100%' />")
|
glass = $("<div style='position:absolute;top:0;left:0;z-index:1;width:100%' />")
|
||||||
.appendTo(monthElement)
|
.appendTo(monthElement)
|
||||||
.click(function(ev, ui) {
|
.click(function(ev, ui) {
|
||||||
|
@ -324,9 +390,12 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
|
|
||||||
|
// NOT first time, reuse as many cells as possible
|
||||||
|
|
||||||
var diff = numWeeks - tbody.find('tr').length;
|
var diff = numWeeks - tbody.find('tr').length;
|
||||||
if (diff < 0) {
|
if (diff < 0) {
|
||||||
|
// remove extra rows
|
||||||
tbody.find('tr:gt(' + (numWeeks-1) + ')').remove();
|
tbody.find('tr:gt(' + (numWeeks-1) + ')').remove();
|
||||||
}
|
}
|
||||||
else if (diff > 0) {
|
else if (diff > 0) {
|
||||||
|
@ -347,6 +416,7 @@
|
||||||
if (trs) tbody.append(trs);
|
if (trs) tbody.append(trs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// re-label and re-class existing cells
|
||||||
var d = cloneDate(start);
|
var d = cloneDate(start);
|
||||||
tbody.find('tr').each(function() {
|
tbody.find('tr').each(function() {
|
||||||
for (var i=0; i<7; i++) {
|
for (var i=0; i<7; i++) {
|
||||||
|
@ -368,9 +438,11 @@
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resizeTable();
|
setCellSizes();
|
||||||
|
|
||||||
if (sniffBugs) {
|
if (sniffBugs) {
|
||||||
|
// nasty bugs in opera 9.25
|
||||||
|
// position() returning relative to direct parent
|
||||||
var tr = tbody.find('tr');
|
var tr = tbody.find('tr');
|
||||||
var td = tr.find('td');
|
var td = tr.find('td');
|
||||||
var trTop = tr.position().top;
|
var trTop = tr.position().top;
|
||||||
|
@ -381,37 +453,7 @@
|
||||||
sniffBugs = false;
|
sniffBugs = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fetchEvents(renderEvents);
|
||||||
events = [];
|
|
||||||
var completed = eventSources.length;
|
|
||||||
var reportEvents = function(a) {
|
|
||||||
for (var i=0; i<a.length; i++) normalizeEvent(a[i]);
|
|
||||||
events = events.concat(a);
|
|
||||||
if (--completed == 0) {
|
|
||||||
if (options.loading) options.loading(false);
|
|
||||||
renderEvents(events);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if (options.loading) options.loading(true);
|
|
||||||
for (var i=0; i<eventSources.length; i++) {
|
|
||||||
var src = eventSources[i];
|
|
||||||
if (typeof src == 'string') {
|
|
||||||
var params = {};
|
|
||||||
params[options.startParam || 'start'] = Math.round(start.getTime() / 1000);
|
|
||||||
params[options.endParam || 'end'] = Math.round(end.getTime() / 1000);
|
|
||||||
params[options.cacheParam || '_'] = (new Date()).getTime();
|
|
||||||
$.getJSON(src, params, reportEvents);
|
|
||||||
}
|
|
||||||
else if ($.isFunction(src)) {
|
|
||||||
src(start, end, reportEvents);
|
|
||||||
}
|
|
||||||
else if (src) {
|
|
||||||
reportEvents(src);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ignoreResizes = false;
|
ignoreResizes = false;
|
||||||
|
|
||||||
|
@ -421,10 +463,38 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Adjust dimensions of the cells, based on container's width
|
||||||
|
//
|
||||||
|
|
||||||
|
function setCellSizes() {
|
||||||
|
var tbodyw = tbody.width();
|
||||||
|
var cellw = Math.floor(tbodyw / 7);
|
||||||
|
var cellh = Math.round(cellw * .85);
|
||||||
|
thead.find('th')
|
||||||
|
.filter(':lt(6)').width(cellw).end()
|
||||||
|
.filter(':eq(6)').width(tbodyw - cellw*6);
|
||||||
|
tbody.find('td').height(cellh);
|
||||||
|
glass.height(monthElement.height());
|
||||||
|
monthElementWidth = monthElement.width();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************/
|
||||||
|
//
|
||||||
|
// Event Rendering
|
||||||
|
//
|
||||||
|
/*******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Render the 'events' array. First, break up into segments
|
||||||
|
//
|
||||||
|
|
||||||
var eventMatrix = [];
|
var eventMatrix = [];
|
||||||
|
|
||||||
function renderEvents() {
|
function renderEvents() {
|
||||||
|
@ -493,7 +563,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Do the REAL rendering of the segments
|
||||||
|
//
|
||||||
|
|
||||||
var eventElements = []; // [[event, element], ...]
|
var eventElements = []; // [[event, element], ...]
|
||||||
|
|
||||||
|
@ -535,7 +607,14 @@
|
||||||
roundE = seg.isEnd;
|
roundE = seg.isEnd;
|
||||||
}
|
}
|
||||||
left2 = left2.position().left + left2.width();
|
left2 = left2.position().left + left2.width();
|
||||||
var element = $("<table class='event' />")
|
var cl = event.className;
|
||||||
|
if (typeof cl == 'string') {
|
||||||
|
cl = ' ' + cl;
|
||||||
|
}
|
||||||
|
else if (typeof cl == 'object') {
|
||||||
|
cl = ' ' + cl.join(' ');
|
||||||
|
}
|
||||||
|
var element = $("<table class='event" + (cl || '') + "' />")
|
||||||
.append("<tr>" +
|
.append("<tr>" +
|
||||||
(roundW ? "<td class='nw'/>" : '') +
|
(roundW ? "<td class='nw'/>" : '') +
|
||||||
"<td class='n'/>" +
|
"<td class='n'/>" +
|
||||||
|
@ -549,7 +628,6 @@
|
||||||
"<td class='s'/>" +
|
"<td class='s'/>" +
|
||||||
(roundE ? "<td class='se'/>" : '') + "</tr>");
|
(roundE ? "<td class='se'/>" : '') + "</tr>");
|
||||||
buildEventText(event, element.find('td.c'));
|
buildEventText(event, element.find('td.c'));
|
||||||
if (event.cssClass) element.addClass(event.cssClass);
|
|
||||||
if (options.eventRender) {
|
if (options.eventRender) {
|
||||||
var res = options.eventRender(event, element);
|
var res = options.eventRender(event, element);
|
||||||
if (typeof res != 'undefined') {
|
if (typeof res != 'undefined') {
|
||||||
|
@ -576,9 +654,33 @@
|
||||||
innerDiv.height(height);
|
innerDiv.height(height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// create the text-contents of an event segment
|
||||||
|
//
|
||||||
|
|
||||||
|
function buildEventText(event, element) {
|
||||||
|
$("<span class='event-title' />")
|
||||||
|
.text(event.title)
|
||||||
|
.appendTo(element);
|
||||||
|
var st = typeof event.showTime == 'undefined' ? showTime : event.showTime;
|
||||||
|
if (st != false) {
|
||||||
|
if (st == true || st == 'guess' &&
|
||||||
|
(event.start.getHours() || event.start.getMinutes() ||
|
||||||
|
event.end.getHours() || event.end.getMinutes())) {
|
||||||
|
var timeStr = $.fullCalendar.formatDate(event.start, timeFormat);
|
||||||
|
var timeElement = $("<span class='event-time' />");
|
||||||
|
if (r2l) element.append(timeElement.text(' ' + timeStr));
|
||||||
|
else element.prepend(timeElement.text(timeStr + ' '));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Attach event handlers to an event segment
|
||||||
|
//
|
||||||
|
|
||||||
function initEventElement(event, element) {
|
function initEventElement(event, element) {
|
||||||
element.click(function(ev) {
|
element.click(function(ev) {
|
||||||
|
@ -607,10 +709,35 @@
|
||||||
}
|
}
|
||||||
eventElements.push([event, element]);
|
eventElements.push([event, element]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Remove all event segments from DOM
|
||||||
|
//
|
||||||
|
|
||||||
|
function clearEventElements() {
|
||||||
|
for (var i=0; i<eventElements.length; i++)
|
||||||
|
eventElements[i][1].remove();
|
||||||
|
eventElements = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************/
|
||||||
|
//
|
||||||
|
// Drag & Drop (and cell-coordinate stuff)
|
||||||
|
//
|
||||||
|
/*******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Attach jQuery UI draggable
|
||||||
|
//
|
||||||
|
|
||||||
var dragStartTD, dragTD;
|
var dragStartTD, dragTD;
|
||||||
var dayOverlay;
|
var dayOverlay;
|
||||||
|
|
||||||
|
@ -658,7 +785,7 @@
|
||||||
}
|
}
|
||||||
if (options.eventDrop)
|
if (options.eventDrop)
|
||||||
options.eventDrop.call(this, event, delta, ev, ui);
|
options.eventDrop.call(this, event, delta, ev, ui);
|
||||||
clearEvents();
|
clearEventElements();
|
||||||
renderEvents();
|
renderEvents();
|
||||||
}
|
}
|
||||||
dayOverlay.hide();
|
dayOverlay.hide();
|
||||||
|
@ -667,6 +794,11 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Called DURING dragging, on every mouse move
|
||||||
|
//
|
||||||
|
|
||||||
function eventDrag(node, ev, ui) {
|
function eventDrag(node, ev, ui) {
|
||||||
var oldTD = dragTD;
|
var oldTD = dragTD;
|
||||||
|
@ -690,9 +822,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Record positions & dimensions of each TD
|
||||||
|
//
|
||||||
|
|
||||||
var dayX, dayY, dayX0, dayY0;
|
var dayX, dayY, dayX0, dayY0;
|
||||||
var currTD, currR, currC;
|
var currTD, currR, currC;
|
||||||
|
@ -717,6 +849,10 @@
|
||||||
dayX.push(dayX[dayX.length-1] + td.width());
|
dayX.push(dayX[dayX.length-1] + td.width());
|
||||||
currTD = null;
|
currTD = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Returns TD underneath coordinate (optimized)
|
||||||
|
//
|
||||||
|
|
||||||
function dayTD(x, y) {
|
function dayTD(x, y) {
|
||||||
var r=-1, c=-1;
|
var r=-1, c=-1;
|
||||||
|
@ -737,115 +873,128 @@
|
||||||
}
|
}
|
||||||
return currTD;
|
return currTD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get a TD's date
|
||||||
|
//
|
||||||
|
|
||||||
function dayDate(node) {
|
function dayDate(td) {
|
||||||
var i, tds = tbody.get(0).getElementsByTagName('td');
|
var i, tds = tbody.get(0).getElementsByTagName('td');
|
||||||
for (i=0; i<tds.length; i++) {
|
for (i=0; i<tds.length; i++) {
|
||||||
if (tds[i] == node) break;
|
if (tds[i] == td) break;
|
||||||
}
|
}
|
||||||
var d = cloneDate(start);
|
var d = cloneDate(start);
|
||||||
return addDays(d, i);
|
return addDays(d, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Return the # of days between 2 TD's
|
||||||
|
//
|
||||||
|
|
||||||
function dayDelta(node1, node2) {
|
function dayDelta(td1, td2) {
|
||||||
var i1, i2, trs = tbody.get(0).getElementsByTagName('tr');
|
var i1, i2, trs = tbody.get(0).getElementsByTagName('tr');
|
||||||
for (var i=0; i<trs.length; i++) {
|
for (var i=0; i<trs.length; i++) {
|
||||||
var tr = trs[i];
|
var tr = trs[i];
|
||||||
for (var j=0; j<7; j++) {
|
for (var j=0; j<7; j++) {
|
||||||
var td = tr.childNodes[j];
|
var td = tr.childNodes[j];
|
||||||
if (td == node1) i1 = i*7 + j*dis + dit;
|
if (td == td1) i1 = i*7 + j*dis + dit;
|
||||||
if (td == node2) i2 = i*7 + j*dis + dit;
|
if (td == td2) i2 = i*7 + j*dis + dit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return i2 - i1;
|
return i2 - i1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function resizeTable() {
|
|
||||||
var tbodyw = tbody.width();
|
|
||||||
var cellw = Math.floor(tbodyw / 7);
|
|
||||||
var cellh = Math.round(cellw * .85);
|
|
||||||
thead.find('th')
|
|
||||||
.filter(':lt(6)').width(cellw).end()
|
|
||||||
.filter(':eq(6)').width(tbodyw - cellw*6);
|
|
||||||
tbody.find('td').height(cellh);
|
|
||||||
glass.height(monthElement.height());
|
|
||||||
monthElementWidth = monthElement.width();
|
|
||||||
}
|
|
||||||
|
|
||||||
function clearEvents() {
|
|
||||||
for (var i=0; i<eventElements.length; i++)
|
|
||||||
eventElements[i][1].remove();
|
|
||||||
eventElements = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function buildEventText(event, element) {
|
|
||||||
$("<span class='event-title' />")
|
|
||||||
.text(event.title)
|
/*******************************************************************/
|
||||||
.appendTo(element);
|
//
|
||||||
var st = typeof event.showTime == 'undefined' ? showTime : event.showTime;
|
// Event Sources & Fetching
|
||||||
if (st != false) {
|
//
|
||||||
var h = event.start.getHours();
|
/*******************************************************************/
|
||||||
var m = event.start.getMinutes();
|
|
||||||
if (st == true || st == 'guess' && (h || m || event.end.getHours() || event.end.getMinutes())) {
|
|
||||||
var s = '';
|
//
|
||||||
for (var i=0; i<timeFormat.length; i++) {
|
// Fetch from ALL sources. Clear 'events' array and populate
|
||||||
var c = timeFormat.charAt(i);
|
//
|
||||||
if (c == 'a') s += h<12 ? 'am' : 'pm';
|
|
||||||
else if (c == 'A') s += h<12 ? 'AM' : 'PM';
|
function fetchEvents(callback) {
|
||||||
else if (c == 'x') s += h<12 ? 'a' : 'p';
|
events = [];
|
||||||
else if (c == 'X') s += h<12 ? 'A' : 'P';
|
var queued = eventSources.length;
|
||||||
else if (c == 'g') s += h%12 || 12;
|
var sourceDone = function() {
|
||||||
else if (c == 'G') s += h;
|
if (--queued == 0) {
|
||||||
else if (c == 'h') s += zeroPad(h%12 || 12);
|
if (options.loading) {
|
||||||
else if (c == 'H') s += zeroPad(h);
|
options.loading(false);
|
||||||
else if (c == 'i') s += zeroPad(m);
|
}
|
||||||
else s += c;
|
if (callback) {
|
||||||
|
callback(events);
|
||||||
}
|
}
|
||||||
var timeElement = $("<span class='event-time' />");
|
|
||||||
if (r2l) element.append(timeElement.text(' ' + s));
|
|
||||||
else element.prepend(timeElement.text(s + ' '));
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
if (options.loading) {
|
||||||
|
options.loading(true);
|
||||||
|
}
|
||||||
|
for (var i=0; i<eventSources.length; i++) {
|
||||||
|
fetchEventSource(eventSources[i], sourceDone);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatTitle(d) {
|
|
||||||
var m = d.getMonth();
|
//
|
||||||
var s = '';
|
// Fetch from a particular source. Append to the 'events' array
|
||||||
for (var i=0; i<titleFormat.length; i++) {
|
//
|
||||||
var c = titleFormat.charAt(i);
|
|
||||||
if (c == 'F') s += monthNames[m];
|
function fetchEventSource(src, callback) {
|
||||||
else if (c == 'm') s += zeroPad(m);
|
var reportEvents = function(a) {
|
||||||
else if (c == 'M') s += monthAbbrevs[m];
|
for (var i=0; i<a.length; i++) {
|
||||||
else if (c == 'n') s += m;
|
normalizeEvent(a[i]);
|
||||||
else if (c == 'Y') s += d.getFullYear();
|
a[i].source = src;
|
||||||
else if (c == 'y') s += (d.getFullYear()+'').substring(2);
|
}
|
||||||
else s += c;
|
events = events.concat(a);
|
||||||
|
if (callback) {
|
||||||
|
callback(a);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (typeof src == 'string') {
|
||||||
|
var params = {};
|
||||||
|
params[options.startParam || 'start'] = Math.round(start.getTime() / 1000);
|
||||||
|
params[options.endParam || 'end'] = Math.round(end.getTime() / 1000);
|
||||||
|
params[options.cacheParam || '_'] = (new Date()).getTime();
|
||||||
|
$.getJSON(src, params, reportEvents);
|
||||||
|
}
|
||||||
|
else if ($.isFunction(src)) {
|
||||||
|
src(start, end, reportEvents);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
reportEvents(src);
|
||||||
}
|
}
|
||||||
return s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************/
|
||||||
|
//
|
||||||
|
// Begin "Main" Execution
|
||||||
|
//
|
||||||
|
/*******************************************************************/
|
||||||
|
|
||||||
var e = this;
|
var e = this;
|
||||||
var resizeID = 0;
|
var resizeID = 0;
|
||||||
$(window).resize(function() {
|
$(window).resize(function() { // re-render table on window resize
|
||||||
if (!ignoreResizes) {
|
if (!ignoreResizes) {
|
||||||
var rid = ++resizeID;
|
var rid = ++resizeID; // add a delay
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
if (rid == resizeID) {
|
if (rid == resizeID) {
|
||||||
|
// if the month width changed
|
||||||
if (monthElement.width() != monthElementWidth) {
|
if (monthElement.width() != monthElementWidth) {
|
||||||
clearEvents();
|
clearEventElements();
|
||||||
resizeTable();
|
setCellSizes();
|
||||||
_renderEvents();
|
_renderEvents();
|
||||||
if (options.resize) options.resize.call(e);
|
if (options.resize) options.resize.call(e);
|
||||||
}
|
}
|
||||||
|
@ -854,7 +1003,10 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
render();
|
render(); // let's begin...
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -863,24 +1015,26 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// string utilities
|
|
||||||
|
|
||||||
function zeroPad(n) {
|
|
||||||
return (n < 10 ? '0' : '') + n;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
//
|
||||||
|
// Utilities
|
||||||
|
//
|
||||||
|
/***************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
// event utils
|
// event utils
|
||||||
|
//
|
||||||
|
|
||||||
function normalizeEvent(event) {
|
function normalizeEvent(event) {
|
||||||
if (event.date) {
|
if (event.date) {
|
||||||
event.start = event.date;
|
event.start = event.date;
|
||||||
event.date = undefined; // can i do this?
|
delete event.date;
|
||||||
}
|
}
|
||||||
event.start = cleanDate(event.start);
|
event.start = $.fullCalendar.parseDate(event.start);
|
||||||
event._start = cloneDate(event.start);
|
event._start = cloneDate(event.start);
|
||||||
event.end = cleanDate(event.end);
|
event.end = $.fullCalendar.parseDate(event.end);
|
||||||
if (!event.end) event.end = addDays(cloneDate(event.start), 1);
|
if (!event.end) event.end = addDays(cloneDate(event.start), 1);
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
@ -890,13 +1044,18 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// string utils
|
||||||
|
//
|
||||||
|
|
||||||
|
function zeroPad(n) {
|
||||||
|
return (n < 10 ? '0' : '') + n;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
// date utils
|
// date utils
|
||||||
|
//
|
||||||
var monthNames = ['January','February','March','April','May','June','July','August','September','October','November','December'];
|
|
||||||
var monthAbbrevs = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
|
||||||
var dayNames = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
|
|
||||||
var dayAbbrevs = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'];
|
|
||||||
|
|
||||||
function addMonths(d, n, keepTime) {
|
function addMonths(d, n, keepTime) {
|
||||||
d.setMonth(d.getMonth() + n);
|
d.setMonth(d.getMonth() + n);
|
||||||
|
@ -922,48 +1081,99 @@
|
||||||
return new Date(+d);
|
return new Date(+d);
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanDate(d) {
|
|
||||||
if (typeof d == 'string')
|
|
||||||
return $.parseISO8601(d, true) || Date.parse(d) || new Date(parseInt(d));
|
|
||||||
if (typeof d == 'number')
|
|
||||||
return new Date(d * 1000);
|
|
||||||
return d;
|
|
||||||
}
|
|
||||||
|
|
||||||
$.parseISO8601 = function(s, ignoreTimezone) {
|
//
|
||||||
// derived from http://delete.me.uk/2005/03/iso8601.html
|
// globally accessible date formatting & parsing
|
||||||
var regexp = "([0-9]{4})(-([0-9]{2})(-([0-9]{2})" +
|
//
|
||||||
"(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?" +
|
|
||||||
"(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?";
|
$.fullCalendar = {
|
||||||
var d = s.match(new RegExp(regexp));
|
|
||||||
if (!d) return null;
|
monthNames: ['January','February','March','April','May','June','July','August','September','October','November','December'],
|
||||||
var offset = 0;
|
monthAbbrevs: ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'],
|
||||||
var date = new Date(d[1], 0, 1);
|
dayNames: ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],
|
||||||
if (d[3]) { date.setMonth(d[3] - 1); }
|
dayAbbrevs: ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'],
|
||||||
if (d[5]) { date.setDate(d[5]); }
|
|
||||||
if (d[7]) { date.setHours(d[7]); }
|
formatDate: function(d, format) {
|
||||||
if (d[8]) { date.setMinutes(d[8]); }
|
var f = $.fullCalendar.dateFormatters;
|
||||||
if (d[10]) { date.setSeconds(d[10]); }
|
var s = '';
|
||||||
if (d[12]) { date.setMilliseconds(Number("0." + d[12]) * 1000); }
|
for (var i=0; i<format.length; i++) {
|
||||||
if (!ignoreTimezone) {
|
var c = format.charAt(i);
|
||||||
if (d[14]) {
|
if (f[c]) {
|
||||||
offset = (Number(d[16]) * 60) + Number(d[17]);
|
s += f[c](d);
|
||||||
offset *= ((d[15] == '-') ? 1 : -1);
|
}else{
|
||||||
|
s += c;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
offset -= date.getTimezoneOffset();
|
return s;
|
||||||
|
},
|
||||||
|
|
||||||
|
dateFormatters: {
|
||||||
|
'a': function(d) { return d.getHours() < 12 ? 'am' : 'pm' },
|
||||||
|
'A': function(d) { return d.getHours() < 12 ? 'AM' : 'PM' },
|
||||||
|
'x': function(d) { return d.getHours() < 12 ? 'a' : 'p' },
|
||||||
|
'X': function(d) { return d.getHours() < 12 ? 'A' : 'P' },
|
||||||
|
'g': function(d) { return d.getHours() % 12 || 12 },
|
||||||
|
'G': function(d) { return d.getHours() },
|
||||||
|
'h': function(d) { return zeroPad(d.getHours() %12 || 12) },
|
||||||
|
'H': function(d) { return zeroPad(d.getHours()) },
|
||||||
|
'i': function(d) { return zeroPad(d.getMinutes()) },
|
||||||
|
'F': function(d) { return $.fullCalendar.monthNames[d.getMonth()] },
|
||||||
|
'm': function(d) { return zeroPad(d.getMonth() + 1) },
|
||||||
|
'M': function(d) { return $.fullCalendar.monthAbbrevs[d.getMonth()] },
|
||||||
|
'n': function(d) { return d.getMonth() + 1 },
|
||||||
|
'Y': function(d) { return d.getFullYear() },
|
||||||
|
'y': function(d) { return (d.getFullYear()+'').substring(2) },
|
||||||
|
'c': function(d) {
|
||||||
|
// ISO8601. derived from http://delete.me.uk/2005/03/iso8601.html
|
||||||
|
return d.getUTCFullYear() +
|
||||||
|
"-" + zeroPad(d.getUTCMonth() + 1) +
|
||||||
|
"-" + zeroPad(d.getUTCDate()) +
|
||||||
|
"T" + zeroPad(d.getUTCHours()) +
|
||||||
|
":" + zeroPad(d.getUTCMinutes()) +
|
||||||
|
":" + zeroPad(d.getUTCSeconds()) +
|
||||||
|
"Z";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
parseDate: function(s) {
|
||||||
|
if (typeof s == 'object')
|
||||||
|
return s; // already a Date object
|
||||||
|
if (typeof s == 'undefined')
|
||||||
|
return null;
|
||||||
|
if (typeof s == 'number')
|
||||||
|
return new Date(s * 1000);
|
||||||
|
return $.fullCalendar.parseISO8601(s, true) ||
|
||||||
|
Date.parse(s) ||
|
||||||
|
new Date(parseInt(s) * 1000);
|
||||||
|
},
|
||||||
|
|
||||||
|
parseISO8601: function(s, ignoreTimezone) {
|
||||||
|
// derived from http://delete.me.uk/2005/03/iso8601.html
|
||||||
|
var regexp = "([0-9]{4})(-([0-9]{2})(-([0-9]{2})" +
|
||||||
|
"(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?" +
|
||||||
|
"(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?";
|
||||||
|
var d = s.match(new RegExp(regexp));
|
||||||
|
if (!d) return null;
|
||||||
|
var offset = 0;
|
||||||
|
var date = new Date(d[1], 0, 1);
|
||||||
|
if (d[3]) { date.setMonth(d[3] - 1); }
|
||||||
|
if (d[5]) { date.setDate(d[5]); }
|
||||||
|
if (d[7]) { date.setHours(d[7]); }
|
||||||
|
if (d[8]) { date.setMinutes(d[8]); }
|
||||||
|
if (d[10]) { date.setSeconds(d[10]); }
|
||||||
|
if (d[12]) { date.setMilliseconds(Number("0." + d[12]) * 1000); }
|
||||||
|
if (!ignoreTimezone) {
|
||||||
|
if (d[14]) {
|
||||||
|
offset = (Number(d[16]) * 60) + Number(d[17]);
|
||||||
|
offset *= ((d[15] == '-') ? 1 : -1);
|
||||||
|
}
|
||||||
|
offset -= date.getTimezoneOffset();
|
||||||
|
}
|
||||||
|
return new Date(Number(date) + (offset * 60 * 1000));
|
||||||
}
|
}
|
||||||
return new Date(Number(date) + (offset * 60 * 1000));
|
|
||||||
};
|
|
||||||
|
|
||||||
$.ISO8601String = function(date) {
|
|
||||||
// derived from http://delete.me.uk/2005/03/iso8601.html
|
|
||||||
return date.getUTCFullYear() +
|
|
||||||
"-" + zeroPad(date.getUTCMonth() + 1) +
|
|
||||||
"-" + zeroPad(date.getUTCDate()) +
|
|
||||||
"T" + zeroPad(date.getUTCHours()) +
|
|
||||||
":" + zeroPad(date.getUTCMinutes()) +
|
|
||||||
":" + zeroPad(date.getUTCSeconds()) +
|
|
||||||
"Z";
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// additional FullCalendar "extensions" should be attached to $.fullCalendar
|
||||||
|
|
||||||
})(jQuery);
|
})(jQuery);
|
||||||
|
|
83
gcal.js
83
gcal.js
|
@ -21,56 +21,45 @@
|
||||||
|
|
||||||
(function($) {
|
(function($) {
|
||||||
|
|
||||||
$.fn.gcalFullCalendar = function(options) {
|
$.fullCalendar.gcalFeed = function(feedUrl, options) {
|
||||||
|
|
||||||
var feedURL;
|
feedUrl = feedUrl.replace(/\/basic$/, '/full');
|
||||||
if (options && typeof options.events == 'string') {
|
options = options || {};
|
||||||
feedURL = options.events;
|
var draggable = options.draggable || false;
|
||||||
}
|
|
||||||
else return this.fullCalendar(options);
|
|
||||||
|
|
||||||
feedURL = feedURL.replace(/\/basic$/, '/full');
|
return function(start, end, callback) {
|
||||||
|
$.getJSON(feedUrl + "?alt=json-in-script&callback=?",
|
||||||
$.extend(options, {
|
{
|
||||||
|
'start-min': $.fullCalendar.formatDate(start, 'c'),
|
||||||
events: function(start, end, callback) {
|
'start-max': $.fullCalendar.formatDate(end, 'c'),
|
||||||
$.getJSON(feedURL + "?alt=json-in-script&callback=?",
|
'singleevents': true
|
||||||
{
|
},
|
||||||
'start-min': $.ISO8601String(start),
|
function(data) {
|
||||||
'start-max': $.ISO8601String(end),
|
var events = [];
|
||||||
'singleevents': true
|
if (data.feed.entry)
|
||||||
},
|
$.each(data.feed.entry, function(i, entry) {
|
||||||
function(data) {
|
var url;
|
||||||
var events = [];
|
$.each(entry['link'], function(j, link) {
|
||||||
if (data.feed.entry)
|
if (link.type == 'text/html') url = link.href;
|
||||||
$.each(data.feed.entry, function(i, entry) {
|
|
||||||
var url;
|
|
||||||
$.each(entry['link'], function(j, link) {
|
|
||||||
if (link.type == 'text/html') url = link.href;
|
|
||||||
});
|
|
||||||
events.push({
|
|
||||||
id: entry['gCal$uid']['value'],
|
|
||||||
url: url,
|
|
||||||
title: entry['title']['$t'],
|
|
||||||
start: $.parseISO8601(entry['gd$when'][0]['startTime'], true),
|
|
||||||
end: $.parseISO8601(entry['gd$when'][0]['endTime'], true),
|
|
||||||
location: entry['gd$where'][0]['valueString'],
|
|
||||||
description: entry['content']['$t'],
|
|
||||||
allDay: entry['gd$when'][0]['startTime'].indexOf('T') == -1,
|
|
||||||
draggable: false
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
callback(events);
|
var showTime = entry['gd$when'][0]['startTime'].indexOf('T') != -1;
|
||||||
});
|
events.push({
|
||||||
},
|
id: entry['gCal$uid']['value'],
|
||||||
|
url: url,
|
||||||
|
title: entry['title']['$t'],
|
||||||
|
start: $.fullCalendar.parseDate(entry['gd$when'][0]['startTime']),
|
||||||
|
end: $.fullCalendar.parseDate(entry['gd$when'][0]['endTime']),
|
||||||
|
location: entry['gd$where'][0]['valueString'],
|
||||||
|
description: entry['content']['$t'],
|
||||||
|
showTime: showTime,
|
||||||
|
className: [showTime ? 'nobg' : null, options.className],
|
||||||
|
draggable: draggable
|
||||||
|
});
|
||||||
|
});
|
||||||
|
callback(events);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
eventRender: function(event, element) {
|
}
|
||||||
if (!event.allDay) element.addClass('nobg');
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
return this.fullCalendar(options);
|
|
||||||
};
|
|
||||||
|
|
||||||
})(jQuery);
|
})(jQuery);
|
||||||
|
|
Loading…
Reference in a new issue