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 collectLocales()
68 var tmpyear = ((panelNum ==
0) ?
2000 :
2001);
71 if (months_translated.length
> 0)
73 for (month =
0; month <
12; month++) {
74 var startDate = new Date(tmpyear, month,
15);
76 var item = new Object();
77 item.Type =
"DayEvent";
78 item.StartTime = startDate;
79 item.Summary =
"__temp" + month;
81 var criteria = new Object();
82 criteria.Type =
"CalendarEntry";
86 var result = calendarService.IDataSource.Add(criteria);
88 error(result.ErrorMessage);
90 error(
"collectLocales: " + e + ', line ' + e.line);
94 var startTime = new Date(tmpyear,
0,
1);
95 var endTime = new Date(tmpyear,
11,
31);
99 StartRange: startTime,
101 SearchText: '__temp',
105 var result = calendarService.IDataSource.GetList(listFiltering);
106 if (result.ErrorCode) {
107 error(result.ErrorMessage);
110 var list = result.ReturnValue;
112 error(e + ', line ' + e.line);
115 var ids = new Array();
121 while (list && (entry = list.getNext()) != undefined) {
122 dateArr = entry.StartTime.replace(/,/g,'').replace(/\./g,':').replace(/ /g,' ').split(' ');
123 var day = dateArr[
1];
124 var month = dateArr[
2];
125 var year = dateArr[
3];
127 // make sure month is set properly
128 if (isNaN(parseInt(day))) {
132 } else if (isNaN(parseInt(year))) {
138 console.info(entry.StartTime + ' -
> ' + month + ' ' + counter);
139 ids[counter] = entry.id;
140 months_translated[month] = counter +
1;
144 error(e + ', line ' + e.line);
149 var criteria = new Object();
150 criteria.Type =
"CalendarEntry";
155 var result = calendarService.IDataSource.Delete(criteria);
156 if (result.ErrorCode)
157 error(result.ErrorMessage);
159 error('deleting temp calendar entries:' + e + ', line ' + e.line);
164 function requestNotification()
166 var criteria = new Object();
167 criteria.Type =
"CalendarEntry";
170 var result = calendarService.IDataSource.RequestNotification(criteria, callback);
171 if (result.ErrorCode)
172 error('loading Calendar items list');
174 error(
"requestNotification: " + e + ', line ' + e.line);
178 function callback(transId, eventCode, result)
183 function parseDate(dateString)
186 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:
187 Wednesday,
26 August,
2009 24:
00:
00
188 Wednesday,
26 August,
2009 12:
00:
00 am
189 Wednesday, August
26,
2009 12:
00:
00 am
190 Wednesday,
2009 August,
26 12:
00:
00 am
191 Wednesday,
2009 August,
28 8.00.00 pm
192 Wednesday,
2009 August,
28 08:
00:
00 PM
195 if (dateString ==
"" || dateString == null)
197 var dateArr = dateString.replace(/,/g,'').replace(/\./g,':').replace(/ /g,' ').split(' ');
198 if (dateArr.length !=
5 && dateArr.length !=
6)
202 var weekDay = dateArr[
0];
203 var day = dateArr[
1];
204 var month = dateArr[
2];
205 var year = dateArr[
3];
206 // make sure month is set properly
207 if (isNaN(parseInt(day))) {
211 } else if (isNaN(parseInt(year))) {
216 // make sure day and year are set properly
217 if (Number(day)
> Number(year)) {
222 month = months_translated[month];
225 var timeArr = dateArr[
4].split(':');
226 if (timeArr.length !=
3)
228 var hours = Number(timeArr[
0]);
229 var minutes = Number(timeArr[
1]);
230 var seconds = Number(timeArr[
2]);
231 if (dateArr.length ==
6 && dateArr[
5].toLowerCase() == 'pm' && hours <
12)
233 if (dateArr.length ==
6 && dateArr[
5].toLowerCase() == 'am' && hours ==
12)
236 console.info('year=' + year + ' month=' + month + ' day=' + day + ' hours=' + hours + ' minutes=' + minutes+ ' seconds=' + seconds);
238 return new Date(year, month -
1, day, hours, minutes, seconds);
241 // 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"
242 function formatDate(date, format)
244 var day = date.getDate().toString();
245 var month = (date.getMonth() +
1).toString();
246 while (day.length <
2) { day = '
0' + day; }
247 while (month.length <
2) { month = '
0' + month; }
249 if (showTodayAsText && now.getDate() == date.getDate() && now.getMonth() == date.getMonth())
250 return '
<span class=
"today">' + todayText + '
</span>';
252 var dateArr = format.replace(/,/g,'').replace(/\./g,':').replace(/ /g,' ').split(' ');
253 if (dateArr.length !=
5 && dateArr.length !=
6) {
254 // we don't know how to format this
255 if (dateFormat == 'auto' || dateFormat == 'DDMM')
256 return day + dateSeparator + month;
258 return month + dateSeparator + day;
262 if (dateFormat == 'MMDD')
264 else if (dateFormat == 'DDMM')
267 // dateFormat == 'auto', try to detect system setting
269 var day_ = dateArr[
1];
270 var month_ = dateArr[
2];
271 var year_ = dateArr[
3];
272 // make sure month is set properly
273 if (isNaN(parseInt(day_))) {
278 } else if (isNaN(parseInt(year_))) {
284 // make sure day and year are set properly
285 if (Number(day_)
> Number(year_))
290 return day + dateSeparator + month;
292 return month + dateSeparator + day;
295 function formatTime(date)
297 // date is a Date() object
298 date.setSeconds(
0); // we don't care about seconds
299 var time = date.toLocaleTimeString().replace(/[\.:]
00/, ''); // remove seconds from string
300 if (time.replace(/\./, ':').split(':')[
0].length <
2)
302 if (showNowAsText && date.getTime() == now.getTime())
303 time = '
<span class=
"now">' + nowText + '
</span>';
307 function updateData()
310 // meetings have time
311 // 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
313 var meetingListFiltering = {
314 Type:'CalendarEntry',
316 StartRange: (new Date(now.getFullYear(), now.getMonth(), now.getDate(),
0,
0,
0)),
317 EndRange: (new Date(now.getFullYear(), now.getMonth() + monthRange, now.getDate(),
0,
0,
0))
320 var meetingResult = calendarService.IDataSource.GetList(meetingListFiltering);
321 var meetingList = meetingResult.ReturnValue;
323 // todos don't, they start on
00:
00 hrs., but should be visible anyway
324 // this will generate a list of passed todos. We have to check if they have been marked as
"done" yet
326 var todayTodoListFiltering = {
327 Type:'CalendarEntry',
330 StartRange: (new Date(now.getFullYear() -
1, now.getMonth(), now.getDate(),
0,
0,
0)),
331 EndRange: (new Date(now.getFullYear(), now.getMonth(), now.getDate(),
0,
0,
1))
334 var todayTodoResult = calendarService.IDataSource.GetList(todayTodoListFiltering);
335 var todayTodoList = todayTodoResult.ReturnValue;
336 var entryLists = [todayTodoList, meetingList];
338 var entryLists = [meetingList];
341 error('loading Calendar items list:' + e + ', line ' + e.line);
350 var entriesHtml = '
<table>';
352 var max = ((panelNum ==
0) ? eventsPerWidget :
2 * eventsPerWidget);
354 // the first outer loop iteration is for passed ToDos, the second loop is for all upcomming events (may also include ToDos)
355 for (var i=
0; counter < max && i < entryLists.length; i++) {
356 while (counter < max && (entry = entryLists[i].getNext()) != undefined) {
359 // output event info for debugging
361 'event: Id=' + entry.id +
362 ',Type=' + entry.Type +
363 ',Summary=' + entry.Summary +
364 ',Location=' + entry.Location +
365 ',Status=' + entry.Status +
366 ',StartTime=' + entry.StartTime +
367 ',EndTime=' + entry.EndTime +
368 ',InstanceStartTime=' + entry.InstanceStartTime +
369 ',InstanceEndTime=' + entry.InstanceEndTime
372 // we don't want ToDos when includeTodos == false or when they are completed
373 if (entry.Type == 'ToDo' && (entry.Status ==
"TodoCompleted" || !includeTodos)) {
374 console.info('skipping ' + entry.id );
379 // make sure that we don't include an event twice (useful for ToDos that might come up twice)
380 if (eventIds[entry.id] ==
1) {
381 console.info('skipped (already included) ' + entry.id);
385 eventIds[entry.id] =
1;
387 // summary can be undefined!
388 var Summary = ((entry.Summary == null) ? '' : entry.Summary);
389 if (entry.Type == 'Meeting' && entry.Location != '' && showLocation)
390 Summary += ', ' + entry.Location;
392 // fix by yves: determine start and end dates/times
393 entryStartTime = ((entry.InstanceStartTime == null) ? entry.StartTime : entry.InstanceStartTime);
394 entryEndTime = ((entry.InstanceEndTime == null) ? entry.EndTime : entry.InstanceEndTime);
396 // there can be ToDos that have no date at all!
397 if (entry.Type == 'ToDo' && entry.EndTime == null)
398 entryDate =
""; // this will cause parseDate(entryDate) to return null;
400 entryDate = ((entry.Type == 'ToDo') ? entryEndTime : entryStartTime); // ToDo's use their EndTime, the rest use StartTime
402 // Convert date/time string to Date object
403 var date = parseDate(entryDate);
404 console.info('date: ' + date);
405 var endDate = ((entryEndTime == null) ? null : parseDate(entryEndTime));
406 console.info('endDate: ' + endDate);
408 // check if meeting event has already passed
409 if (entry.Type == 'Meeting') {
410 var compareTime = ((endDate == null) ? date.getTime() : endDate.getTime());
411 if (now.getTime()
> compareTime) {
412 console.info('skipping Meeting (already passed) ' + entry.id);
414 eventIds[entry.id] =
0;
419 // check if anniversary passed (not sure why they are in the list, the query was only for today - nokia?)
420 if (entry.Type == 'Anniversary') {
421 var tmp = new Date(now.getFullYear(), now.getMonth(), now.getDate(),
0,
0,
0);
422 if (date.getTime() < tmp.getTime()) {
423 console.info('skipping Anniversary (already passed) ' + entry.id);
425 eventIds[entry.id] =
0;
430 // fix DayEvents end time. End times are off by
1 Second. It's possible that the event has already passed
431 if (entry.Type == 'DayEvent' && endDate != null) {
432 endDate.setMinutes(endDate.getMinutes() -
1);
433 console.info('fixing DayEvent endDate: ' + endDate);
434 if (now.getTime()
> endDate.getTime()) {
435 console.info('event already passed ' + entry.id);
437 eventIds[entry.id] =
0;
442 // check if the event is currently taking place
443 if (entryStartTime != null && entryEndTime != null && date != null && endDate != null) {
444 // check if we are between start and endtime
445 if ((date.getTime() < now.getTime()) && (now.getTime() < endDate.getTime())) {
446 date = now; // change appointment date/time to now
447 console.info('event is currently taking place: ' + date);
451 // skip events for the first panel in case this is the second one
452 if (panelNum ==
1 && counter < eventsPerWidget +
1) {
453 console.info('skipping (already in first widget) ' + entry.id);
457 // generate html output
458 entriesHtml += '
<tr><td><img class=
"icon" src=
"' + entry.Type + '.png" /></td>';
460 // some languages have very strange locale date formats, can't parse all those. Also some todos don't have dates at all.
461 entriesHtml += '
<td colspan=
"4"><span class=
"date">' + entryDate + '
</span> ';
463 var weekDay = date.toLocaleDateString().substr(
0,weekDayLength);
464 var time = formatTime(date);
465 var dateStr = formatDate(date, entryDate);
466 if (entry.Type == 'ToDo' || entry.Type == 'Anniversary' || entry.Type == 'DayEvent' || entry.Type == 'Reminder') {
467 // decide if we want to leave off the weekday
468 if (dateStr.search(/Today/) != -
1)
469 entriesHtml += '
<td colspan=
"4"><span class=
"date">' + dateStr + '
</span> ';
471 entriesHtml += '
<td><span class=
"weekDay">' + weekDay + '
</span></td><td><span class=
"date">' + dateStr + '
</span></td><td colspan=
"2">';
472 } else if (entry.Type == 'Meeting') {
473 if (showCombinedDateTime) {
474 if (now.getDate() == date.getDate() && now.getMonth() == date.getMonth())
475 entriesHtml += '
<td colspan=
"4"><span class=
"today">' + time + '
</span> ';
477 // decide if we want to leave off the weekday
478 if (dateStr.search(/Today/) != -
1)
479 entriesHtml += '
<td colspan=
"4"><span class=
"date">' + dateStr + '
</span> ';
481 entriesHtml += '
<td><span class=
"weekDay">' + weekDay + '
</span></td><td><span class=
"date">' + dateStr + '
</span></td><td colspan=
"2">';
484 // decide if we want to leave off the weekday
485 if (dateStr.search(/Today/) != -
1)
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>