1 <?xml version=
"1.0" encoding=
"UTF-8"?>
2 <!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3 <html xmlns=
"http://www.w3.org/1999/xhtml">
6 <title>Coming Next
</title>
8 <style type=
"text/css">
9 /* -----------------------------------------------------------------------
10 here you can customize background color, font color, font size etc...
11 --------------------------------------------------------------------------- */
12 .background { color:#ffffff; background-color:#
000000; font:normal
12pt; } /* Defines the background of the widget. If you want to use a background image, set useBackgroundImage = true below */
13 /* for the default themes, black, gray, and light blue, codes are #
292029, #e7dfe7, #
009aef */
14 .weekDay { } /* Defines the appearance of all week day texts */
15 .date { } /* Defines the appearance of all date texts */
16 .today { color:#ff0000; } /* Defines the appearance of
"Today" text */
17 .time { } /* Defines the appearance of all time texts */
18 .now { color:#ff00ff; } /* Defines the appearance of
"Now" text */
19 .description { } /* Defines the appearance of all event descriptions */
20 .icon { width:
15px; height:
15px; } /* Defines size and appearance of icons */
25 //---------------------------------------------------------------
26 // The following section contains settings you may want to tweak
27 //---------------------------------------------------------------
28 var monthRange =
2; // number of months to include in the event list
29 var includeTodos = true; // disable to remove ToDos from event list
30 var useBackgroundImage = true; // use background_portrait.png and background_landscape.png to fake transparency. Set to
"false" to use a solid background color
31 var showCombinedDateTime = false;// only show the time for events happening today, otherwise just show the date
32 var showLocation = true; // show the location for meeting events
33 var showTodayAsText = true; // if enabled, the current date will be shown as
"Today" instead of
"31.12"
34 var todayText = 'Today'; // text to display for
"Today"
35 var showNowAsText = true; // if enabled, the appointment time will be shown as
"Now" instead of
"12:00"
36 var nowText = 'Now'; // text to display for
"Now"
37 var dateSeparator = '.'; // separator for dates. e.g.
"31.12" or
"31/12"
38 var dateFormat = 'auto' // how dates will be displayed. 'auto' will autodetect your phone's date format setting. 'MMDD' will write month first, 'DDMM' will write day first
39 var weekDayLength =
2; // defines how many characters of the weekday will be shown. E.g.
2 will cut
"Friday" to
"Fr"
40 var updateDataInterval =
5; // how many minutes to wait before updating the displayed data. The higher the number, the less battery is used
41 var calendarApp =
0x10005901; // UID of the calendar app to run when clicking the widget.
0x10005901 = buildin calendar,
0x20004ec1 = Epocware Handy Calendar
42 var eventsPerWidget =
4; // number of events to show per widget. Default is
4
43 var showNothingText = true; // if set to
"true", show a text if no events are in the list
44 var nothingText = 'No further events within ' + monthRange + ' months'; // text to show when no events are in the list
46 //-------------------------------------------------------
47 // Nothing of interest from here on...
48 //-------------------------------------------------------
49 var panelNum =
0; // use
1 for second panel
50 var calendarService = null;
51 var cacheEntriesHtml = [];
52 var months_translated = [];
57 window.onresize = updateScreen;
58 window.onshow = updateScreen;
60 function error(message)
62 console.info('Error: ' + message);
63 document.getElementById(
"calendarList").innerHTML = 'Error: ' + message;
66 function isToday(date)
68 if (date.getDate() == now.getDate() && date.getMonth() == now.getMonth())
73 function collectLocales()
75 var tmpyear = ((panelNum ==
0) ?
2000 :
2001);
78 if (months_translated.length
> 0)
80 for (month =
0; month <
12; month++) {
81 var startDate = new Date(tmpyear, month,
15);
83 var item = new Object();
84 item.Type =
"DayEvent";
85 item.StartTime = startDate;
86 item.Summary =
"__temp" + month;
88 var criteria = new Object();
89 criteria.Type =
"CalendarEntry";
93 var result = calendarService.IDataSource.Add(criteria);
95 error(result.ErrorMessage);
97 error(
"collectLocales: " + e + ', line ' + e.line);
101 var startTime = new Date(tmpyear,
0,
1);
102 var endTime = new Date(tmpyear,
11,
31);
103 var listFiltering = {
104 Type:'CalendarEntry',
106 StartRange: startTime,
108 SearchText: '__temp',
112 var result = calendarService.IDataSource.GetList(listFiltering);
113 if (result.ErrorCode) {
114 error(result.ErrorMessage);
117 var list = result.ReturnValue;
119 error(e + ', line ' + e.line);
122 var ids = new Array();
128 while (list && (entry = list.getNext()) != undefined) {
129 dateArr = entry.StartTime.replace(/,/g,'').replace(/\./g,':').replace(/ /g,' ').split(' ');
130 var day = dateArr[
1];
131 var month = dateArr[
2];
132 var year = dateArr[
3];
134 // make sure month is set properly
135 if (isNaN(parseInt(day))) {
139 } else if (isNaN(parseInt(year))) {
145 console.info(entry.StartTime + ' -
> ' + month + ' ' + counter);
146 ids[counter] = entry.id;
147 months_translated[month] = counter +
1;
151 error(e + ', line ' + e.line);
156 var criteria = new Object();
157 criteria.Type =
"CalendarEntry";
162 var result = calendarService.IDataSource.Delete(criteria);
163 if (result.ErrorCode)
164 error(result.ErrorMessage);
166 error('deleting temp calendar entries:' + e + ', line ' + e.line);
171 function requestNotification()
173 var criteria = new Object();
174 criteria.Type =
"CalendarEntry";
177 var result = calendarService.IDataSource.RequestNotification(criteria, callback);
178 if (result.ErrorCode)
179 error('loading Calendar items list');
181 error(
"requestNotification: " + e + ', line ' + e.line);
185 function callback(transId, eventCode, result)
190 function parseDate(dateString)
193 Dates my look very differently. Also keep in mind that the names are localized!!! These are the possibilities depending on the users date format setting:
194 Wednesday,
26 August,
2009 24:
00:
00
195 Wednesday,
26 August,
2009 12:
00:
00 am
196 Wednesday, August
26,
2009 12:
00:
00 am
197 Wednesday,
2009 August,
26 12:
00:
00 am
198 Wednesday,
2009 August,
28 8.00.00 pm
199 Wednesday,
2009 August,
28 08:
00:
00 PM
202 if (dateString ==
"" || dateString == null)
204 var dateArr = dateString.replace(/,/g,'').replace(/\./g,':').replace(/ /g,' ').split(' ');
205 if (dateArr.length !=
5 && dateArr.length !=
6)
209 var weekDay = dateArr[
0];
210 var day = dateArr[
1];
211 var month = dateArr[
2];
212 var year = dateArr[
3];
213 // make sure month is set properly
214 if (isNaN(parseInt(day))) {
218 } else if (isNaN(parseInt(year))) {
223 // make sure day and year are set properly
224 if (Number(day)
> Number(year)) {
229 month = months_translated[month];
232 var timeArr = dateArr[
4].split(':');
233 if (timeArr.length !=
3)
235 var hours = Number(timeArr[
0]);
236 var minutes = Number(timeArr[
1]);
237 var seconds = Number(timeArr[
2]);
238 if (dateArr.length ==
6 && dateArr[
5].toLowerCase() == 'pm' && hours <
12)
240 if (dateArr.length ==
6 && dateArr[
5].toLowerCase() == 'am' && hours ==
12)
243 console.info('year=' + year + ' month=' + month + ' day=' + day + ' hours=' + hours + ' minutes=' + minutes+ ' seconds=' + seconds);
245 return new Date(year, month -
1, day, hours, minutes, seconds);
248 // returns a short date as string (
"31.12" or
"12.31") based on the format string which should look like
"Wednesday, 26 August, 2009 12:00:00 am"
249 function formatDate(date, format)
251 var day = date.getDate().toString();
252 var month = (date.getMonth() +
1).toString();
253 while (day.length <
2) { day = '
0' + day; }
254 while (month.length <
2) { month = '
0' + month; }
256 if (showTodayAsText && isToday(date))
257 return '
<span class=
"today">' + todayText + '
</span>';
259 var dateArr = format.replace(/,/g,'').replace(/\./g,':').replace(/ /g,' ').split(' ');
260 if (dateArr.length !=
5 && dateArr.length !=
6) {
261 // we don't know how to format this
262 if (dateFormat == 'auto' || dateFormat == 'DDMM')
263 return day + dateSeparator + month;
265 return month + dateSeparator + day;
269 if (dateFormat == 'MMDD')
271 else if (dateFormat == 'DDMM')
274 // dateFormat == 'auto', try to detect system setting
276 var day_ = dateArr[
1];
277 var month_ = dateArr[
2];
278 var year_ = dateArr[
3];
279 // make sure month is set properly
280 if (isNaN(parseInt(day_))) {
285 } else if (isNaN(parseInt(year_))) {
291 // make sure day and year are set properly
292 if (Number(day_)
> Number(year_))
297 return day + dateSeparator + month;
299 return month + dateSeparator + day;
302 function formatTime(date)
304 // date is a Date() object
305 date.setSeconds(
0); // we don't care about seconds
306 var time = date.toLocaleTimeString().replace(/[\.:]
00/, ''); // remove seconds from string
307 if (time.replace(/\./, ':').split(':')[
0].length <
2)
309 if (showNowAsText && date.getTime() == now.getTime())
310 time = '
<span class=
"now">' + nowText + '
</span>';
314 function updateData()
317 // meetings have time
318 // note: anniveraries have a start time of
12:
00am. So since we want to include them, we have to query the whole day and check if events have passed later
320 var meetingListFiltering = {
321 Type:'CalendarEntry',
323 StartRange: (new Date(now.getFullYear(), now.getMonth(), now.getDate(),
0,
0,
0)),
324 EndRange: (new Date(now.getFullYear(), now.getMonth() + monthRange, now.getDate(),
0,
0,
0))
327 var meetingResult = calendarService.IDataSource.GetList(meetingListFiltering);
328 var meetingList = meetingResult.ReturnValue;
330 // todos don't, they start on
00:
00 hrs., but should be visible anyway
331 // this will generate a list of passed todos. We have to check if they have been marked as
"done" yet
333 var todayTodoListFiltering = {
334 Type:'CalendarEntry',
337 StartRange: (new Date(now.getFullYear() -
1, now.getMonth(), now.getDate(),
0,
0,
0)),
338 EndRange: (new Date(now.getFullYear(), now.getMonth(), now.getDate(),
0,
0,
1))
341 var todayTodoResult = calendarService.IDataSource.GetList(todayTodoListFiltering);
342 var todayTodoList = todayTodoResult.ReturnValue;
343 var entryLists = [todayTodoList, meetingList];
345 var entryLists = [meetingList];
348 error('loading Calendar items list:' + e + ', line ' + e.line);
357 var entriesHtml = '
<table>';
359 var max = ((panelNum ==
0) ? eventsPerWidget :
2 * eventsPerWidget);
361 // the first outer loop iteration is for passed ToDos, the second loop is for all upcomming events (may also include ToDos)
362 for (var i=
0; counter < max && i < entryLists.length; i++) {
363 while (counter < max && (entry = entryLists[i].getNext()) != undefined) {
366 // output event info for debugging
368 'event: Id=' + entry.id +
369 ',Type=' + entry.Type +
370 ',Summary=' + entry.Summary +
371 ',Location=' + entry.Location +
372 ',Status=' + entry.Status +
373 ',StartTime=' + entry.StartTime +
374 ',EndTime=' + entry.EndTime +
375 ',InstanceStartTime=' + entry.InstanceStartTime +
376 ',InstanceEndTime=' + entry.InstanceEndTime
379 // we don't want ToDos when includeTodos == false or when they are completed
380 if (entry.Type == 'ToDo' && (entry.Status ==
"TodoCompleted" || !includeTodos)) {
381 console.info('skipping ' + entry.id );
386 // make sure that we don't include an event twice (useful for ToDos that might come up twice)
387 if (eventIds[entry.id] ==
1) {
388 console.info('skipped (already included) ' + entry.id);
392 eventIds[entry.id] =
1;
394 // summary can be undefined!
395 var Summary = ((entry.Summary == null) ? '' : entry.Summary);
396 if (entry.Type == 'Meeting' && entry.Location != '' && showLocation)
397 Summary += ', ' + entry.Location;
399 // fix by yves: determine start and end dates/times
400 entryStartTime = ((entry.InstanceStartTime == null) ? entry.StartTime : entry.InstanceStartTime);
401 entryEndTime = ((entry.InstanceEndTime == null) ? entry.EndTime : entry.InstanceEndTime);
403 // there can be ToDos that have no date at all!
404 if (entry.Type == 'ToDo' && entry.EndTime == null)
405 entryDate =
""; // this will cause parseDate(entryDate) to return null;
407 entryDate = ((entry.Type == 'ToDo') ? entryEndTime : entryStartTime); // ToDo's use their EndTime, the rest use StartTime
409 // Convert date/time string to Date object
410 var date = parseDate(entryDate);
411 console.info('date: ' + date);
412 var endDate = ((entryEndTime == null) ? null : parseDate(entryEndTime));
413 console.info('endDate: ' + endDate);
415 // check if meeting event has already passed
416 if (entry.Type == 'Meeting') {
417 var compareTime = ((endDate == null) ? date.getTime() : endDate.getTime());
418 if (now.getTime()
> compareTime) {
419 console.info('skipping Meeting (already passed) ' + entry.id);
421 eventIds[entry.id] =
0;
426 // check if anniversary passed (not sure why they are in the list, the query was only for today - nokia?)
427 if (entry.Type == 'Anniversary') {
428 var tmp = new Date(now.getFullYear(), now.getMonth(), now.getDate(),
0,
0,
0);
429 if (date.getTime() < tmp.getTime()) {
430 console.info('skipping Anniversary (already passed) ' + entry.id);
432 eventIds[entry.id] =
0;
437 // fix DayEvents end time. End times are off by
1 Second. It's possible that the event has already passed
438 if (entry.Type == 'DayEvent' && endDate != null) {
439 endDate.setMinutes(endDate.getMinutes() -
1);
440 console.info('fixing DayEvent endDate: ' + endDate);
441 if (now.getTime()
> endDate.getTime()) {
442 console.info('event already passed ' + entry.id);
444 eventIds[entry.id] =
0;
449 // check if the event is currently taking place
450 if (entryStartTime != null && entryEndTime != null && date != null && endDate != null) {
451 // check if we are between start and endtime
452 if ((date.getTime() < now.getTime()) && (now.getTime() < endDate.getTime())) {
453 date = now; // change appointment date/time to now
454 console.info('event is currently taking place: ' + date);
458 // skip events for the first panel in case this is the second one
459 if (panelNum ==
1 && counter < eventsPerWidget +
1) {
460 console.info('skipping (already in first widget) ' + entry.id);
464 // generate html output
465 entriesHtml += '
<tr><td><img class=
"icon" src=
"' + entry.Type + '.png" /></td>';
467 // some languages have very strange locale date formats, can't parse all those. Also some todos don't have dates at all.
468 entriesHtml += '
<td colspan=
"4"><span class=
"date">' + entryDate + '
</span> ';
470 var weekDay = date.toLocaleDateString().substr(
0,weekDayLength);
471 var time = formatTime(date);
472 var dateStr = formatDate(date, entryDate);
473 if (entry.Type == 'ToDo' || entry.Type == 'Anniversary' || entry.Type == 'DayEvent' || entry.Type == 'Reminder') {
475 entriesHtml += '
<td colspan=
"4"><span class=
"date">' + dateStr + '
</span> ';
477 entriesHtml += '
<td><span class=
"weekDay">' + weekDay + '
</span></td><td><span class=
"date">' + dateStr + '
</span></td><td colspan=
"2">';
478 } else if (entry.Type == 'Meeting') {
479 if (showCombinedDateTime) {
481 entriesHtml += '
<td colspan=
"4"><span class=
"today">' + time + '
</span> ';
483 entriesHtml += '
<td><span class=
"weekDay">' + weekDay + '
</span></td><td><span class=
"date">' + dateStr + '
</span></td><td colspan=
"2">';
486 entriesHtml += '
<td colspan=
"4"><span class=
"date">' + dateStr + '
</span> <span class=
"time">' + time + '
</span> ';
488 entriesHtml += '
<td><span class=
"weekDay">' + weekDay + '
</span></td><td><span class=
"date">' + dateStr + '
</span></td><td width=
"1px"><span class=
"time">' + time + '
</span></td><td>';
492 entriesHtml += '
<span class=
"description">' + Summary + '
</span></td></tr>';
495 entriesHtml += '
</table>';
496 if (showNothingText && entriesHtml == '
<table></table>')
497 entriesHtml = '
<div style=
"width:295px; height:75px; text-align:center; line-height:75px; overflow:visible;">' + nothingText + '
</div>';
498 if (cacheEntriesHtml != entriesHtml) {
499 document.getElementById('calendarList').innerHTML = entriesHtml;
500 cacheEntriesHtml = entriesHtml;
503 error('displaying list:' + e + ', line ' + e.line);
508 function updateScreen()
510 // check if opening fullscreen
511 if( window.innerHeight
> 91)
514 if (useBackgroundImage) {
515 // check for screen rotation
516 if (orientation != 'portrait' && screen.width ==
360 && screen.height ==
640) {
517 window.widget.prepareForTransition(
"fade");
518 orientation = 'portrait';
519 document.getElementById('body').style.backgroundImage = 'url(background_' + orientation + '.png)';
520 document.getElementById('body').style.backgroundColor = 'none';
521 window.widget.performTransition();
522 } else if (orientation != 'landscape' && screen.width ==
640 && screen.height ==
360) {
523 window.widget.prepareForTransition(
"fade");
524 orientation = 'landscape';
525 document.getElementById('body').style.backgroundImage = 'url(background_' + orientation + '.png)';
526 document.getElementById('body').style.backgroundColor = 'none';
527 window.widget.performTransition();
532 function launchCalendar()
535 widget.openApplication(calendarApp,
"");
538 error('starting Calendar App');
546 // call calendar service
547 calendarService = device.getServiceObject(
"Service.Calendar",
"IDataSource");
549 error('loading Calendar service');
555 requestNotification();
556 window.setInterval('updateData()',
1000 *
60 * updateDataInterval);
559 if (useBackgroundImage)
560 // check for screen rotation every
3 secs
561 window.setInterval('updateScreen()',
1000 *
3);
566 <style type=
"text/css">
567 table { margin:
0px; padding:
0px; border-spacing:
0px; }
568 td { padding:
0px
5px
0px
0px; white-space:nowrap; overflow:hidden; }
569 #homescreenView { width:
315px; height:
91px; overflow:hidden; }
570 #calendarList { position:absolute; left:
10px; top:
4px; width:
295px; height:
75px; overflow:hidden; }
575 <body id=
"body" class=
"background">
576 <div id=
"homescreenView">
577 <div id=
"calendarList"></div>