The Device APIs Working Group is currently not pursuing the approach outlined in this draft, so it should be considered historical. Please treat this document with caution and do not reference it or use it as the basis for implementation. The domain covered by this document is still within the scope of the Working Group as defined in its Charter. The Working Group may pursue an alternative API design that is based on the current Web browser security model.
The Calendar API defines the high-level interfaces required to obtain read access to a user's calendaring service.
This API includes the following key interfaces:
The approach proposed for this API is very similar to the one taken in the Contacts API. The known issues in the document are highlighted below, and concern in particular the management of timezones and recurrence.
The Calendar API defines a high-level interface to access Calendar information such as events, reminders, alarms and other calendar information.
The API itself is designed to be agnostic of any underlying calendaring service sources.
A set of Security and Privacy Considerations are presented for the discretion of both implementors of the Calendar API and recipients of calendaring information (i.e. web pages). This specification provides a set of non-normative User Interaction Guidelines demonstrating an example user experience that is compliant with the Security and Privacy Considerations provided herein.
This specification also provides informative examples illustrating how to add and update calendar events, utilising existing web platform APIs.
The requirements for this set of interfaces are listed in the Device API Requirements document [[DAP-REQS]].
The API provided in this specification is limited to providing a programmatic way to retrieve Calendar information.
The scope of this specification does not include the ability to attach Contacts to Calendar Events or vice versa. This denotes cross-API dependency and the intention of this specification is to provide a standalone API for the provision and management of Calendar Event information.
This specification requires that formatting for all dates and times be applied according to the definition of valid date and time string in [[!HTML5]].
The following code illustrates how to obtain calendaring information from a user's calendar:
function success (events) { // do something with resulting list of objects for (var i in events) alert(events[i].id); } function error (err) { // do something with resulting errors alert(err.code); } // Perform an calendar search. Initially filter the list to Calendar records starting // before April 9, 2011 @ 5pm (UTC). navigator.calendar.findEvents( success, error, { filter: { startBefore: '2011-04-10T05:00:00+12:00' } });
This specification defines conformance criteria that apply to a single product: the user agent that implements the interfaces that it contains.
Implementations that use ECMAScript to implement the APIs defined in this specification must implement them in a manner consistent with the ECMAScript Bindings defined in the Web IDL specification [[!WEBIDL]], as this specification uses that specification’s terminology.
The terms document base URL, browsing context, event handler attributes, event handler event type, task, task source and task queues are defined by the HTML5 specification [[!HTML5]].
The task source used by this specification is the device task source.
To dispatch a success
event means that an event with the name success
, which does
not bubble and is not cancelable, and which uses the Event
interface, is to be dispatched at the CalendarEventSuccessCB
object.
To dispatch an error
event means that an event with the name error
, which does
not bubble and is not cancelable, and which uses the Event
interface, is to be dispatched at the CalendarErrorCB
object.
The overall architecture for addressing privacy in DAP is still under construction. As it is finalized, there may be changes made to this API to reflect requirements or support for privacy-related functionality.
The API defined in this specification can be used to create, retrieve, update and remove calendar event information from a user's calendar. All API methods disclose information related to a user's calendars such as events, schedules and reminders and other personally identifying information. The distribution of this information could potentially compromise the user's privacy. A conforming implementation of this specification MUST provide a mechanism that protects the user's privacy and this mechanism should ensure that no calendar information is creatable, retrivable, updateable or removable without the user's express permission.
A user agent must not create, retrieve, update or delete calendar information to Web sites without the express permission of the user. A user agent must acquire permission through a user interface, unless they have prearranged trust relationships with users, as described below. The user interface must include the URI of the document origin, as defined in [[HTML5]]. Those permissions that are acquired through the user interface and that are preserved beyond the current browsing session (i.e. beyond the time when the browsing context, as defined in [[HTML5]], is navigated to another URL) MUST be revocable and a user agent must respect revoked permissions.
Obtaining the user's express permission to access one API method does not imply the user has granted permission for the same Web site to access other methods provided by this API, or to access the same method with a different set of arguments, as part of the same permission context. If a user has expressed permission for an implementation to, e.g. find a set of existing calendar events, the implementation must seek the user's express permission if and when any additional create, find, update or remove function is called on this API.
A user agent may have prearranged trust relationships that do not require such user interfaces. For example, while a Web browser will present a user interface when a Web site performs a calendar request, a Widget Runtime MAY have a prearranged, delegated security relationship with the user and, as such, a suitable alternative security and privacy mechanism with which to authorize the creation, retrieval, update and/or removal of calendar event information.
Recipients should take care to only request calendar information when necessary, and only use the calendar information for the task for which it was provided to them. Recipients are invited to dispose of calendar information once that task is completed, unless expressly permitted to retain it by the user, and to take measures to protect this information against unauthorized access. If calendar information is stored, users should be allowed to update and delete this information.
The recipient of calendar information should not retransmit the calendar information without the user’s express permission. Care should be taken when retransmitting and use of encryption is encouraged.
Recipients should clearly and conspicuously disclose the fact that they are collecting calendar data, the purpose for the collection, how long the data is retained, how the data is secured, how the data is shared if it is shared, how users can access, update and delete the data, and any other choices that users have with respect to the data. This disclosure should include an explanation of any exceptions to the guidelines listed above.
Further to the requirements listed in the previous section, implementors of the Calendar API are also advised to consider the following aspects that can negatively affect the privacy of their users: in certain cases, users can inadvertently grant permission to the User Agent to disclose their calendar items to Web sites. In other cases, the content hosted at a certain URL changes in such a way that the previously granted calendar permissions no longer apply as far as the user is concerned. Or the users might simply change their minds.
Predicting or preventing these situations is inherently difficult. Mitigation and in-depth defensive measures are an implementation responsibility and not prescribed by this specification. However, in designing these measures, implementers are advised to enable user awareness of calendar sharing, and to provide easy access to interfaces that enable revocation of permissions.
The ServiceCalendar
interface is
exposed on the Navigator interface [[NAVIGATOR]].
The Calendar interface provides a method to retrieve calendaring information from a user's calendar.
Find calendar event items in the calendar based on an CalendarEventFilter
object.
This method takes between one and three arguments. When called, it immediately returns, and then asynchronously start a find calendar event items process defined as follows:
findEvents()
operation is still pending a response), and the
current method was invoked with a non-null
errorCB
argument,
dispatch an error
event with a
PENDING_OPERATION_ERROR
code
value.
success
event. If the attempt
fails, and the method was invoked with a non-null
errorCB
argument,
this method must dispatch an error
event with the code
attribute set according to the type of failure that has occurred.
The CalendarEvent
interface captures a calendar event object.
TZDate
object that would address this.A globally unique identifier for the given CalendarEvent
object. Each CalendarEvent
referenced from Calendar
MUST include a non-empty id
value.
An implementation MUST maintain this globally unique resource identifier when a calendar event is added to, or present within, a Calendar.
An implementation MAY use an IANA registered identifier format. The value can also be a non-standard format.
A description of the event.
{description: "Meeting with Joe's team"}
A plain text description of the location of the event.
{location: 'Conf call #+4402000000001'}
A summary of the event.
{summary: "Agenda:\n\n\t* Introductions\n\t* AoB"}
The start date and time of the event as a valid date or time string.
{start: '2011-03-24T09:00-08:00'} // Event starts on March 24, 2011 @ 5pm (UTC)
The end date and time of the event as a valid date or time string.
{end: '2011-03-24T10:00:00-08:00'} // Event ends on March 24, 2011 @ 6pm (UTC)
An indication of the user's status of the event.
This parameter may be set to one of the following constants:
'pending', 'tentative', 'confirmed', 'cancelled'.
{status: 'pending'} // Event is awaiting user action
An indication of the display status to set for the event.
This parameter may be set to one of the following constants:
'transparent', 'opaque'.
{freebusy: 'transparent'} // Mark event as transparent in Calendar
The recurrence or repetition rule for this event
{recurrence: {frequency: 'daily'}} // Event occurs every day and never expires
{recurrence: {frequency: 'weekly', // Event occurs weekly... daysInWeek: [2, 4], // ...every Tuesday and Thursday expires: '2011-06-11T12:00:00-04:00'}} // Event expires on or before June 11, 2011 @ 4pm (UTC)
{recurrence: {frequency: 'weekly', // Event occurs weekly...on every Wednesday // (if we say the 'start' attribute is March 24, 2011 @ 2pm (Wednesday) as // shown above and no daysInWeek attribute is provided) expires: '2011-06-11T11:00:00-05:00'}} // Event expires on or before June 11, 2011 @ 4pm (UTC)
{recurrence: {frequency: 'monthly', // Event occurs monthly... daysInMonth: [-5], // ...5 days before the end of each month expires: '2011-06-11T20:00:00+04:00'}} // Event expires on or before June 11, 2011 @ 4pm (UTC)
{recurrence: {frequency: 'monthly', // Event occurs monthly...on the 24th day of every month // (if we say the 'start' attribute is March 24, 2011 @ 2pm as // shown above and no daysInMonth attribute is provided) expires: '2011-06-11T20:00:00+04:00'}} // Event expires on or before June 11, 2011 @ 4pm (UTC)
{recurrence: {frequency: 'yearly', // Event occurs yearly...on the 24th day of every March // (if we say the 'start' attribute is March 24, 2011 @ 2pm as // shown above and no daysInMonth attribute is provided) expires: '2011-06-11T16:00:00+00:00'}} // Event expires on or before June 11, 2011 @ 4pm (UTC)
{recurrence: {frequency: 'yearly', // Event occurs yearly... daysInMonth: [24], // ...every 24th day... monthsInYear: [3, 6], // ...in every March and June expires: '2011-06-11T16:00:00Z'}} // Event expires on or before June 11, 2011 @ 4pm (UTC)
{recurrence: {frequency: 'yearly', // Event occurs yearly... daysInYear: [168], // ...every 168th day of each year expires: '2011-06-11T21:45:00+05:45'}} // Event expires on or before June 11, 2011 @ 4pm (UTC)
A reminder for the event.
This attribute can be specified as a positive valid date or time string.
, denoting a one-time reminder or as a negative value in milliseconds denoting a relative relationship to the start time of the calendar event.A relative reminder is recommended for setting a reminder for recurrent events.
{reminder: '2011-03-24T13:00:00+00:00'} // Remind ONCE on March 24, 2011 @ 1pm (UTC)
{reminder: '-3600000'} // Remind 1 hour before every occurrence of this event
The CalendarRepeatRule
interface captures the recurrence of a calendar event item.
The frequency of the CalendarRepeatRule.
This parameter must be set to one of the following constants:
'daily', 'weekly', 'monthly', 'yearly'.
Additional values must be ignored for this attribute.
{frequency: 'monthly'} // Event repeats on a monthly basis
A positive integer defining how often the recurrence rule MUST repeat.
For interval N, recurrence rule repeats every Nth frequency. Default interval value is 1, that is every day for a daily, every week for a weekly, every month for a monthly and every year for a yearly.
If this parameter is set to null
the event item does not have any fixed interval and the event interal should be derived from the other CalendarRepeatRule
attributes.
{interval: 1}
The date and time to which the CalendarRepeatRule applies as a valid date or time string.
If this parameter is set to null
the event item does not have any fixed expiry date and the event is scheduled to continue indefintely.
{expires: '2011-08-01T01:00:00+01:00'} // Event repeats until August 1, 2011 @ 12am (UTC)
One or more dates and times to which the CalendarRepeatRule does not apply as valid date or time string strings.
If this parameter is set to null
the event item does not have any exception dates and/or times.
{exceptionDates: ['2011-12-22', '2011-12-29']} // Event does not occur on December 22, 2011 and December 29, 2011
The day or days of the week for which the CalendarRepeatRule applies. If this attribute is set to null
then the day of the CalendarEvent.start value is used to derive the recurrent dates.
NOTE: This property only applies to weekly occurrences. If CalendarRepeatRule.frequency is not set to 'weekly' this property must be ignored.
The possible values are:
{daysInWeek: [0, 6]} // A weekly event repeats every Sunday and Saturday
The day or days of the month for which the CalendarRepeatRule applies. If this attribute is set to null
then the day of the month of the CalendarEvent.start value is used to derive the recurrent dates.
NOTE: This property only applies to monthly occurrences. If CalendarRepeatRule.frequency is not set to 'monthly' this property must be ignored.
The possible values are:
{daysInMonth: [4, -10]} // A monthly event repeats on the 4th and 10th to last day of each month.
The day or days of the month for which the CalendarRepeatRule applies. If this attribute is set to null
then the day of the year of the CalendarEvent.start value is used to derive the recurrent dates.
NOTE: This property only applies to yearly occurrences. If CalendarRepeatRule.frequency is not set to 'yearly' this property must be ignored.
The possible values are:
{daysInYear: [262, -102]} // A yearly event repeats on day 262 and 102 days before the last day of each year.
The week or weeks of the month for which the CalendarRepeatRule applies. If this attribute is set to null
then the week of the month of the CalendarEvent.start value is used to derive the recurrent dates.
NOTE: This property only applies to monthly occurrences. If CalendarRepeatRule.frequency is not set to 'monthly' this property must be ignored.
The possible values are:
{weeksInMonth: [1, -1]} // A monthly event repeats on the first and last week of each month.
The month or months of the year for which the CalendarRepeatRule applies. If this attribute is set to null
then the month of the year of the CalendarEvent.start value is used to derive the recurrent dates.
NOTE: This property only applies to yearly occurrences. If CalendarRepeatRule.frequency is not set to 'yearly' this property must be ignored.
The possible values are:
{monthsInYear: [4, 10]} // A yearly event repeats in April and October each year.
The CalendarFindOptions interface describes the options that can be applied to calendar searching.
By default this option is set to true
.
The CalendarEventFilter
interface captures the searchable parameters for finding calendar event items.
CalendarEvent
objects resulting from a successful search operation.
The following is the event handler attribute (and its corresponding event handler event type) that MUST be
supported as a DOM attribute by the CalendarEventSuccessCB
object.
event handler attribute | event handler event type |
---|---|
onsuccess
|
success
|
The following is the event handler attribute (and its corresponding event handler event type) that MUST be
supported as a DOM attribute by the CalendarErrorCB
object.
event handler attribute | event handler event type |
---|---|
onerror
|
error
|
The CalendarError
interface encapsulates all errors in the manipulation of CalendarEvent
objects in the Calendar API.
The Calendar
interface findEvents() method
provides a method to search for calendar items according to the input of a
CalendarEventFilter
object.
All fields within a CalendarEventFilter
object provided to this method represent a logical UNION of value matching.
Fields provided with a null
value are considered to match anything.
For example, the following CalendarEventFilter
object is supplied for Calendar Event searching:
navigator.calendar.findEvents( function(eventItems) { }, function(error) { }, { filter: { startBefore: '2011-08-26', // All events before August 26, 2011 status: 'confirmed' } } );The above example logically implies: "find calendar event items that contain a start date before August 26, 2011 AND a status of 'confirmed'".
We need to be a lot clearer about partial matching included below. It might just be simpler to use pass RegExp objects around. Then again it might not...
All calendar item searching SHOULD apply a loose-matching policy. If a CalendarEventFilter
attribute being searched in Calendar
partially matches the input filter value, a CalendarEvent
object representing the calendar item
SHOULD be returned as part of the resulting CalendarEventSuccessCB
.
The rules for processing filter combinations is defined below and is always provided with an input parameter and, an optional options parameter. Its behaviour depends on the type of input:
null
, go to step 2.null
. apply the provided options to calendaritemsset.Return a null
value.
The properties and parameters defined on the CalendarEvent
interface MAY be extended by implementors of this specification.
Non-standard, private properties and parameters SHOULD have a prefixed name starting with X
(U+0058 LATIN CAPTIAL
LETTER X) or use a vendor-specific prefix. Extended properties and parameters can be defined bilaterally between user agents without outside registration or standardization.
It is RECOMMENDED that authors define both a formal iCalendar grammar [[RFC5545]] and a WebIDL grammar [[WEBIDL]] for their proposed extension to ensure interoperability between iCalendar databases and other non-standard Calendar databases and formats. It is also RECOMMENDED that authors provide documentation of their extension properties and parameters within the public domain.
A new parameter is required by Company X to provide a distinct indication that a Calendar Event is all-day.
The [[WEBIDL]] syntax for this parameter is defined as follows:
true
if the given event is an all-day event.
The corresponding iCalendar [[RFC5545]] notation for this parameter is defined as follows:
The following ABNF grammar extends the grammar found in [[RFC5545]] (Section 4). X-ALLDAY Purpose: To specify whether the event is an all day occurance. Value type: A single boolean value. Cardinality: (0,1) Special notes: ... ABNF: X-ALLDAY-value = boolean
This parameter will be used within the Calendar API as follows:
var calendarEvent = ...; // ...obtain individual calendar event object alert(calendarEvent.Xallday);
This parameter will be used within the iCalendar format [[RFC5545]]] as follows:
X-ALLDAY;true
The API contained in this document can be invoked either programmatically (for example, inline within a general script) or resulting from the interaction of a user.
The interaction of a user is when a user invokes the API from an
HTMLElement
[[HTML5]] within the current
browsing context via a valid auto-invocation event.
A valid auto-invocation event includes any of the following event types, as defined in [[!DOM-LEVEL-3-EVENTS]]:
click
dblclick
mouseup
The findEvents()
method on Calendar
should, if the method was invoked
by an interaction of a user (as opposed to having been created and executed in general script), display the
Calendar Picker directly.
The ability to add and update calendar event information is not a function of the API provided in this specification. Instead, the intention is to reuse existing web platform APIs and paradigms in order to acheive add and update functionality.
In this section we show how the existing web platform would be used to provide add and update writeback functionality to allow users to add new calendar events or update existing calendar events from a web page to their calendar.
A valid Calendar resource is a web resource with a .ical
, .ics
, .ifb
or .icalendar
filename extension or a web resource with a MIME-type matching a valid media type.
To handle the saving of a new Calendar Event, a user agent SHOULD register as the default handler for any valid Calendar resource.
A valid media type will be the following web resource MIME type:
text/calendar
On invocation of a valid Calendar resource, the user agent SHOULD, on successful download of the valid Calendar resource, store the given resource in the user's calendar according to the rule for storing a Calendar resource. As part of this standard download process, the user agent MAY present a dialog to the user allowing them to select a different application with which to handle the given resource, thereby overriding the use of the unified calendar for the storage of the data contained therein and bypassing the rule for storing a Calendar resource.
The rule for storing a Calendar resource is defined as follows:
Let Event be the parsed key/value pairs contained in the valid Calendar resource.
UID
key then process the valid Calendar resource as follows.
UID
provided.
null
) then update the contents of
MatchedEvent with the contents of Event and exit this rule.
As part of the rule for storing a Calendar resource, the user agent MAY provide additional dialogs to the user after successful completion of the download and before the Calendar Event information is saved to the unified calendar, such as to show a preview of the Calendar information contained therein as it will be stored in the user's calendar. The user MAY be able to override the information provided before accepting the additions and permanently storing the given data in their unified calendar.
A web page can dynamically generate an iCalendar object on the client side for download to the user's unified calendar via the [[FILE-WRITER]] and [[FILE-API]] interfaces. The following example shows the process in which a web site may create an iCalendar object dynamically and then present this to the user. The user may then save this information by clicking on the presented information, download the dynamically generated iCalendar object and invoke a suitable application with which to handle the dynamic resource.
<a id="ical">Save our Event in your Calendar</a> <script type="text/javascript"> // obtain an ArrayBuffer consisting of valid iCalendar syntax (out of scope) var iCalObj = getICalendar( /* ... */ ); // create a new iCalendar Blob [[FILE-WRITER]] var calendarEventBlobBuilder = new BlobBuilder(); calendarEventBlobBuilder.append( iCalObj ); var calendarEventBlob = calendarEventBlobBuilder.getBlob( "text/calendar" ); // obtain an iCalendar Blob URL [[FILE-API]] var calendarEventBlobURL = window.URL.createObjectUrl( calendarEventBlob ); // assign iCalendar Blob URL to an anchor element for presentation and download by the user document.getElementById('ical').href = calendarEventBlobURL; </script>
To update an existing Calendar Event, the user must have already shared the event information to edit with the current web page via the
findEvents() operation of the Calendar
interface.
This section assumes that the user is already sharing some calendar event information with the current web page via this process.
If this existing Calendar Event information is to be updated in the user's unified calendar then the developer will assign the
id
attribute, as returned in the CalendarEvent
object, as the UID
property of any resulting
iCalendar object to be processed by the user agent according to the rule for storing a Calendar resource.
The example below shows how to update an existing Calendar Event in the user's unified calendar by maintaining a valid UID property while changing other parameters of the Calendar Event. The user is then required to click on the resulting anchor element to download the modified Calendar resource.
<a id="vcard">Update our Event in your Calendar</a> <script type="text/javascript"> // Obtain a single existing Calendar Event object resulting from navigator.calendar.findEvents() var existingCalendarEventObj = ...; // Modify some parameters as required. e.g. add a new phone number existingCalendarEventObj.location = 'Conf call number change: #XXX'; // With the existing Calendar Event object, create an ArrayBuffer consisting of valid iCalendar // syntax (out of scope) making sure to set the resulting iCalendar UID property to // the id parameter returned in the existing Calendar Event object var iCalObj = getICalendar( existingCalendarEventObj ); // create a new iCalendar Blob [[FILE-WRITER]] var calendarEventBlobBuilder = new BlobBuilder(); calendarEventBlobBuilder.append( iCalObj ); var calendarEventBlob = calendarEventBlobBuilder.getBlob( "text/calendar" ); // obtain an iCalendar Blob URL [[FILE-API]] var calendarEventBlobURL = window.URL.createObjectUrl( calendarEventBlob ); // assign iCalendar Blob URL to an anchor element for presentation and download by the user document.getElementById('ical').href = calendarEventBlobURL; </script>
@ to be included
This interface:
This is a list of features that have been discussed with respect to this version of the API but for which it has been decided that if they are included it will be in a future revision.
The current specification suggests support for only Calendar Events. However Andrew McMillan makes the following point [1]:
"Given that the differences between [iCalendar ]VEVENT & VTODO are trivial in comparison to the complexity of their common elements, and that VJOURNAL is entirely a subset of those, it seems to me there is very little to gain by removing VTODO and VJOURNAL from this specification. Removal might restrict clients from implementing some potentially useful functionality. The other supporting components of the specification like VALARM and VTIMEZONE seem to me so essential in any reasonable implementation of VEVENT that they don't even merit discussion."
The editors would like to thank the input from the PhoneGap, Nokia, and OMTP BONDI groups and the feedback received from W3C DAP members to date ...