From b3860895442289b0b469daf851d49a6092d60f76 Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Sat, 30 May 2009 05:54:53 +0000 Subject: [PATCH] almost at 1.2 --- changelog.txt | 3 + docs/conf.py | 3 + docs/index.txt | 455 +++++++++++++++++-------- docs/templates/layout.html | 7 + examples/gcal.html | 7 +- fullcalendar.js | 660 ++++++++++++++++++++++++------------- gcal.js | 83 ++--- 7 files changed, 799 insertions(+), 419 deletions(-) diff --git a/changelog.txt b/changelog.txt index ff8d311..e0c766f 100644 --- a/changelog.txt +++ b/changelog.txt @@ -3,6 +3,9 @@ version 1.2 - cssClass attribute for CalEvents - multiple event sources (using an array for the 'events' option) - 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) - Added the following options: diff --git a/docs/conf.py b/docs/conf.py index cf7a292..9658915 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -188,3 +188,6 @@ latex_documents = [ # If false, no module index is generated. #latex_use_modindex = True + +highlight_language = 'javascript' + diff --git a/docs/index.txt b/docs/index.txt index 8d7481e..8edf66b 100644 --- a/docs/index.txt +++ b/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 - - $('#myCalendar').fullCalendar({ - // initializes a calendar - // see options, data provider, and triggered events below - }); + $('#calendar').fullCalendar({ - $('#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 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 ``true``, requires `jQuery UI `_ core and draggables. Can be overridden on a per-event basis with the ``draggable`` property of - each :ref:`CalEvent ` object. + each :ref:`CalEvent `. **fixedWeeks**: boolean, default:``true`` If ``true``, the calendar will always be 6 weeks tall. If ``false``, the 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`` 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 top of the calendar. - **titleFormat**: string, default:``"Y F"`` - A string defining format of the title above the calendar. The default - "Y F" creates strings such as "January 2009". Use the following - codes in your format string (similar to the PHP's date function): - - * **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 + **titleFormat**: string, default:``"F Y"`` + A string defining the format of the title above the calendar. The default + "F Y" creates strings such as "January 2009". Consult the + :ref:`$.fullCalendar.formatDate ` documentation for a full + list of commands. **buttons**: boolean/hash, default:``true`` Determines whether navigation buttons will be displayed at the top of the - calendar. A hash with keys 'today', 'prev', and 'next' will determine if - each individual button is displayed. Strings can be provided to change - each button's text. + calendar. A hash such as ``{today:false, prev:true, next:true}`` can be + provided to display only certain buttons. A hash such as + ``{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"`` Determines if times will be displayed before each event's title. ``"guess"`` displays times only for events with non-zero start or end times. **timeFormat**: string, default: ``"gx"`` - A string defining the format of dislayed of event times. The default "gx" - creates a string such as "9a". Use the following codes in your format - string (similar to PHP's date function): - - * **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) + A string defining the format of dislayed event times. The default "gx" + creates a string such as "9a". Consult the + :ref:`$.fullCalendar.formatDate ` + documentation for a full list of commands. **eventDragOpacity**: float 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 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 `. + ``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 `_ + 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 - An array of :ref:`CalEvent` can be used to hardcode events into the + An array of :ref:`CalEvents ` can be used to hardcode events into the calendar. Or, a URL can be provided. This URL should return JSON for an array of - :ref:`CalEvent`. GET parameters, determined by the ``startParam`` and - ``endParam`` options, will be inserted into the URL. These parameters - indicate the UNIX timestamp of the start of the first visible day - (inclusive) and the end of the last visible day (exclusive). + :ref:`CalEvents `. GET parameters, determined by the + ``startParam`` and ``endParam`` options, will be inserted into the URL. + These parameters indicate the UNIX timestamp of the start of the first + visible day (inclusive) and the end of the last visible day (exclusive). 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`` @@ -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"`` 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 - of this GET parameter will be a UNIX timestamp denoting the start of the - first visible day (inclusive). + events from a JSON script. The value of this GET parameter will be a UNIX + timestamp denoting the start of the first visible day (inclusive). **endParam**: string, default:``"end"`` 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 - of this GET parameter will be a UNIX timestamp denoting the end of the - last visible day (exclusive). + events from a JSON script. The value of this GET parameter will be a UNIX + timestamp denoting the end of the last visible day (exclusive). **cacheParam**: string, default:``"_"`` When using a JSON url, a parameter of this name will automatically be inserted into the URL to prevent the browser from caching the response. The value will be the current millisecond time. -.. _TriggeredEvents: - -Triggered Events -================ +The following methods can be called on a FullCalendar that has already +been initialized: - **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") + **.fullCalendar(** ``'addEventSource'``, **source)** + Adds an event source. ``source`` may be an array/string/function just as in + the ``events`` option. Events will be immediately fetched from this source + 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. - - **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: + + +.. _CalEvents: CalEvent Objects ================ -A ``CalEvent`` is a data structure that frequents FullCalendar's API. It is -used when a custom event-fetcher needs to report to the :ref:`EventDataProvider`. -It is also used in various :ref:`TriggeredEvents`. Here are the properties of a -``CalEvent``\: +A CalEvent is a data structure that frequents FullCalendar's API. It is the +standardized currency used in :ref:`EventSources`. It is also passed to various +:ref:`Triggered Actions `. Here are the properties of a +CalEvent: **id**: integer/string, 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. Events with ambiguous time-of-day should use 00:00:00. - When reporting to the :ref:`EventDataProvider`, for convenience, + In an :ref:`Event Source `, for convenience, 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 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 (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. - (For convenience with the :ref:`EventDataProvider`). + (For convenience with an :ref:`Event Source `). - IETF and ISO8601 strings can be used for the :ref:`EventDataProvider`. + IETF and ISO8601 strings can be used with an :ref:`Event Source `. **draggable**: boolean (optional) 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) Overrides the master ``showTime`` property for this single event. -When giving events to the :ref:`EventDataProvider`, one can include other -properties beyond the ones listed. This is useful if you want to earmark your -events with additional data to be retrieved later during a -:ref:`Triggered Event `. + **className**: string/array (optional) + A CSS class (or array of classes) that will be attached to this event's + element. + + **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 ` and redraw. + ``calEvent`` must be the *actual CalEvent object*, as retrieved from a + :ref:`Triggered Action ` or ``getEventsById`` (see below). + A set of repeating events will all be affected. + + **.fullCalendar(** ``'removeEvent'``, **calEventOrId)** + Remove elements belonging to the given :ref:`CalEvent `. 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 ` 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)** - Parses an ISO8601 string and returns a ``Date`` object +Date Parsing and Formatting +=========================== + +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)** - Takes a ``Date`` object and returns an ISO8601 string + **$.fullCalendar.parseDate(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. + diff --git a/docs/templates/layout.html b/docs/templates/layout.html index 3524703..30f5226 100644 --- a/docs/templates/layout.html +++ b/docs/templates/layout.html @@ -3,6 +3,13 @@ +
+

Table of Contents

+{{ toc }} +
+ +
+ {% block body %}{% endblock %} diff --git a/examples/gcal.html b/examples/gcal.html index 6760aaf..ca7b505 100644 --- a/examples/gcal.html +++ b/examples/gcal.html @@ -30,9 +30,12 @@ $(document).ready(function() { - $('#calendar').gcalFullCalendar({ + $('#calendar').fullCalendar({ // 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) { window.open(event.url, 'gcalevent', 'width=700,height=600'); return false; diff --git a/fullcalendar.js b/fullcalendar.js index 36279ba..1411dad 100644 --- a/fullcalendar.js +++ b/fullcalendar.js @@ -17,19 +17,30 @@ (function($) { $.fn.fullCalendar = function(options) { + + + // + // Calls methods of a pre-existing instance + // if (typeof options == 'string') { var args = Array.prototype.slice.call(arguments, 1); - var ret; // ugly + var res; this.each(function() { 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') - return this; - return ret; + if (typeof res != 'undefined') + return res; + return this; } + + + // + // Process options + // + options = options || {}; var r2l = options.rightToLeft; @@ -48,77 +59,94 @@ var weekStart = (options.weekStart || 0) % 7; var timeFormat = options.timeFormat || 'gx'; var titleFormat = options.titleFormat || (r2l ? 'Y F' : 'F Y'); + + + + // + // Rendering bug detection variables + // + var tdTopBug, trTopBug, tbodyTopBug, sniffBugs = true; + + 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 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() { - clearEvents(); + function refreshMonth() { + clearEventElements(); render(); } - function today() { - date = new Date(); - updateMonth(); - } - function prevMonth() { addMonths(date, -1); - updateMonth(); + refreshMonth(); } function nextMonth() { addMonths(date, 1); - updateMonth(); + refreshMonth(); + } + + function gotoToday() { + date = new Date(); + refreshMonth(); } function gotoMonth(year, month) { date = new Date(year, month, 1); - updateMonth(); + refreshMonth(); } + + + // + // Publicly accessible methods + // + $.data(this, 'fullCalendar', { - today: today, + refresh: refreshMonth, prevMonth: prevMonth, nextMonth: nextMonth, + today: gotoToday, gotoMonth: gotoMonth, - refresh: updateMonth, - // event crud + // + // Event CRUD + // + addEvent: function(event) { events.push(normalizeEvent(event)); - clearEvents(); + clearEventElements(); renderEvents(); }, - + updateEvent: function(event) { - event.start = cleanDate(event.start); - event.end = cleanDate(event.end); + event.start = $.fullCalendar.parseDate(event.start); + event.end = $.fullCalendar.parseDate(event.end); var startDelta = event.start - event._start; var msLength = event.end - event.start; event._start = cloneDate(event.start); @@ -126,8 +154,8 @@ var e = events[i]; if (e.id === event.id && e !== event) { e.start = new Date(e.start.getTime() + startDelta); - e.end = new Date(e.start.getTime() + msLength); e._start = cloneDate(e.start); + e.end = new Date(e.start.getTime() + msLength); for (var k in event) { if (k && k != 'start' && k != 'end' && k.charAt(0) != '_') { e[k] = event[k]; @@ -135,14 +163,16 @@ } } } - clearEvents(); + clearEventElements(); renderEvents(); }, - + removeEvent: function(eventId) { if (typeof eventId == 'object') { eventId = eventId.id; } + + // remove from the 'events' array var newEvents = []; for (var i=0; i").appendTo(this); - if (bo) { + if (bo) { // "button options" var buttons = $("
").appendTo(header); var prevButton, nextButton; if (bo == true || bo.today != false) { todayButton = $("") - .click(today); + .click(gotoToday); if (typeof bo.today == 'string') todayButton.val(bo.today); buttons.append(todayButton); } @@ -237,14 +297,13 @@ monthElement = $("
") .appendTo($("
").appendTo(this)); - + // + // Build the TABLE cells for the current month. (calls event fetch+render code) + // - - - - var thead, tbody, glass, monthTitle; + var thead, tbody, glass; function render() { @@ -253,7 +312,7 @@ clearTime(date); var year = date.getFullYear(); var month = date.getMonth(); - monthTitle = formatTitle(date); + var monthTitle = $.fullCalendar.formatDate(date, titleFormat); if (titleElement) titleElement.text(monthTitle); clearTime(date); @@ -276,9 +335,14 @@ todayButton.css('visibility', 'visible'); } } + + var dayNames = $.fullCalendar.dayNames; + var dayAbbrevs = $.fullCalendar.dayAbbrevs; if (!tbody) { + // first time, build all cells from scratch + var table = $("").appendTo(monthElement); thead = ""; @@ -313,6 +377,8 @@ } tbody = $(tbody + "").appendTo(table); + // a protective coating over the TABLE + // intercepts mouse clicks and prevents text-selection glass = $("
") .appendTo(monthElement) .click(function(ev, ui) { @@ -324,9 +390,12 @@ }); }else{ + + // NOT first time, reuse as many cells as possible var diff = numWeeks - tbody.find('tr').length; if (diff < 0) { + // remove extra rows tbody.find('tr:gt(' + (numWeeks-1) + ')').remove(); } else if (diff > 0) { @@ -347,6 +416,7 @@ if (trs) tbody.append(trs); } + // re-label and re-class existing cells var d = cloneDate(start); tbody.find('tr').each(function() { for (var i=0; i<7; i++) { @@ -368,9 +438,11 @@ } - resizeTable(); + setCellSizes(); if (sniffBugs) { + // nasty bugs in opera 9.25 + // position() returning relative to direct parent var tr = tbody.find('tr'); var td = tr.find('td'); var trTop = tr.position().top; @@ -381,37 +453,7 @@ sniffBugs = false; } - - events = []; - var completed = eventSources.length; - var reportEvents = function(a) { - for (var i=0; i") + var cl = event.className; + if (typeof cl == 'string') { + cl = ' ' + cl; + } + else if (typeof cl == 'object') { + cl = ' ' + cl.join(' '); + } + var element = $("
") .append("" + (roundW ? ""); buildEventText(event, element.find('td.c')); - if (event.cssClass) element.addClass(event.cssClass); if (options.eventRender) { var res = options.eventRender(event, element); if (typeof res != 'undefined') { @@ -576,9 +654,33 @@ innerDiv.height(height); } } + + + // + // create the text-contents of an event segment + // + + function buildEventText(event, element) { + $("") + .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 = $(""); + if (r2l) element.append(timeElement.text(' ' + timeStr)); + else element.prepend(timeElement.text(timeStr + ' ')); + } + } + } - + // + // Attach event handlers to an event segment + // function initEventElement(event, element) { element.click(function(ev) { @@ -607,10 +709,35 @@ } eventElements.push([event, element]); } + + + // + // Remove all event segments from DOM + // + + function clearEventElements() { + for (var i=0; i") - .text(event.title) - .appendTo(element); - var st = typeof event.showTime == 'undefined' ? showTime : event.showTime; - 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"); - if (r2l) element.append(timeElement.text(' ' + s)); - else element.prepend(timeElement.text(s + ' ')); } + }; + if (options.loading) { + options.loading(true); + } + for (var i=0; i
" : '') + "" + @@ -549,7 +628,6 @@ "" + (roundE ? "" : '') + "