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">
5 <title>Coming Next
</title>
6 <style type=
"text/css">
7 /* -----------------------------------------------------------------------
8 here you can customize background color, font color, font size etc...
9 --------------------------------------------------------------------------- */
10 .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 */
11 .weekDay { } /* Defines the appearance of all week day texts */
12 .date { } /* Defines the appearance of all date texts */
13 .today { color:#ff0000; } /* Defines the appearance of
"Today" text */
14 .time { } /* Defines the appearance of all time texts */
15 .now { color:#ff0000; } /* Defines the appearance of
"Now" text */
16 .description { } /* Defines the appearance of all event descriptions */
17 .icon { width:
15px; height:
15px; } /* Defines size and appearance of icons */
20 //---------------------------------------------------------------
21 // The following section contains settings you may want to tweak
22 //---------------------------------------------------------------
23 var monthRange =
2; // number of months to include in the event list
24 var includeTodos = true; // disable to remove ToDos from event list
25 var useBackgroundImage = true; // use background_portrait.png and background_landscape.png to fake transparency. Set to
"false" to use a solid background color
26 var showTodayAsText = true; // if enabled, the current date will be shown as
"Today" instead of
"31.12"
27 var todayText = 'Today'; // text to display for
"Today"
28 var showNowAsText = true; // if enabled, the appointment time will be shown as
"Now" instead of
"12:00"
29 var nowText = 'Now'; // text to display for
"Now"
30 var dateSeparator = '.'; // separator for dates. e.g.
"31.12" or
"31/12"
31 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
32 var weekDayLength =
2; // defines how many characters of the weekday will be shown. E.g.
2 will cut
"Friday" to
"Fr"
33 var updateDataInterval =
5; // how many minutes to wait before updating the displayed data. The higher the number, the less battery is used
34 var calendarApp =
0x10005901; // UID of the calendar app to run when clicking the widget.
0x10005901 = buildin calendar,
0x20004ec1 = Epocware Handy Calendar
35 var eventsPerWidget =
4; // number of events to show per widget. Default is
4
36 var showNothingText = true; // if set to
"true", show a text if no events are in the list
37 var nothingText = 'No further events within '+monthRange+' months'; // text to show when no events are in the list
39 //-------------------------------------------------------
40 // Nothing of interest from here on...
41 //-------------------------------------------------------
42 var panelNum =
0; // use
1 for second panel
43 var calendarService = null;
44 var cacheEntriesHtml = [];
45 var months_translated = [];
50 window.onresize = updateScreen;
51 window.onshow = updateScreen;
53 function error(message){
54 console.info('Error: ' + message);
55 document.getElementById(
"calendarList").innerHTML = 'Error: ' + message;
58 function collectLocales(){
59 if (months_translated.length
> 0){
62 var tmpyear = ((panelNum ==
0) ?
2000 :
2001);
64 for(month =
0; month <
12; month++){
65 var startDate = new Date(tmpyear, month,
15);
66 var item = new Object();
67 item.Type =
"DayEvent";
68 item.StartTime = startDate;
69 item.Summary =
"__temp" + month;
71 var criteria = new Object();
72 criteria.Type =
"CalendarEntry";
76 var result = calendarService.IDataSource.Add(criteria);
77 if (result.ErrorCode){
78 error(result.ErrorMessage);
82 error(
"collectLocales: " + e + ', line ' + e.line);
86 var startTime = new Date(tmpyear,
0,
1);
87 var endTime = new Date(tmpyear,
11,
31);
91 StartRange: startTime,
97 var result = calendarService.IDataSource.GetList(listFiltering);
98 if (result.ErrorCode){
99 error(result.ErrorMessage);
102 var list = result.ReturnValue;
104 error(e + ', line ' + e.line);
107 var ids = new Array();
112 while( list && (entry = list.getNext()) != undefined ){
113 dateArr = entry.StartTime.replace(/,/g,'').replace(/\./g,':').replace(/ /g,' ').split(' ');
114 var day = dateArr[
1];
115 var month = dateArr[
2];
116 var year = dateArr[
3];
117 // make sure month is set properly
118 if (isNaN(parseInt(day))){
123 else if (isNaN(parseInt(year))){
128 console.info(entry.StartTime + ' -
> ' + month + ' ' + counter);
129 ids[counter] = entry.id;
130 months_translated[month] = counter +
1;
134 error(e + ', line ' + e.line);
139 var criteria = new Object();
140 criteria.Type =
"CalendarEntry";
144 var result = calendarService.IDataSource.Delete(criteria);
145 if (result.ErrorCode)
146 error(result.ErrorMessage);
148 error('deleting temp calendar entries:' + e + ', line ' + e.line);
153 function requestNotification(){
154 var criteria = new Object();
155 criteria.Type =
"CalendarEntry";
157 var result = calendarService.IDataSource.RequestNotification(criteria, callback);
158 if (result.ErrorCode)
159 error('loading Calendar items list');
162 error(
"requestNotification: " + e + ', line ' + e.line);
166 function callback(transId, eventCode, result){
170 function parseDate(dateString)
173 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:
174 Wednesday,
26 August,
2009 24:
00:
00
175 Wednesday,
26 August,
2009 12:
00:
00 am
176 Wednesday, August
26,
2009 12:
00:
00 am
177 Wednesday,
2009 August,
26 12:
00:
00 am
178 Wednesday,
2009 August,
28 8.00.00 pm
180 if (dateString ==
"" || dateString == null)
183 var dateArr = dateString.replace(/,/g,'').replace(/\./g,':').replace(/ /g,' ').split(' ');
185 if (dateArr.length !=
5 && dateArr.length !=
6)
189 var weekDay = dateArr[
0];
190 var day = dateArr[
1];
191 var month = dateArr[
2];
192 var year = dateArr[
3];
193 // make sure month is set properly
194 if (isNaN(parseInt(day))){
199 else if (isNaN(parseInt(year))){
204 // make sure day and year are set properly
205 if (Number(day)
> Number(year))
211 month = months_translated[month];
214 var timeArr = dateArr[
4].split(':');
215 if (timeArr.length !=
3)
217 var hours = Number(timeArr[
0]);
218 var minutes = Number(timeArr[
1]);
219 var seconds = Number(timeArr[
2]);
220 if (dateArr.length ==
6 && dateArr[
5].toLowerCase() == 'pm')
223 console.info('year=' + year + ' month=' + month + ' day=' + day + ' hours=' + hours + ' minutes=' + minutes+ ' seconds=' + seconds);
225 return new Date(year, month -
1, day, hours, minutes, seconds);
228 // 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"
229 function formatDate(date, format)
231 var day = date.getDate().toString();
232 var month = (date.getMonth() +
1).toString();
233 while (day.length <
2) { day = '
0' + day; }
234 while (month.length <
2) { month = '
0' + month; }
236 if (showTodayAsText && now.getDate() == date.getDate() && now.getMonth() == date.getMonth())
237 return '
<span class=
"today">' + todayText + '
</span>';
239 var dateArr = format.replace(/,/g,'').replace(/\./g,':').replace(/ /g,' ').split(' ');
241 if (dateArr.length !=
5 && dateArr.length !=
6){
242 // we don't know how to format this
243 if (dateFormat == 'auto' || dateFormat == 'DDMM')
244 return day + dateSeparator + month;
246 return month + dateSeparator + day;
250 if (dateFormat == 'MMDD')
252 else if (dateFormat == 'DDMM')
254 else { // dateFormat == 'auto', try to detect system setting
256 var day_ = dateArr[
1];
257 var month_ = dateArr[
2];
258 var year_ = dateArr[
3];
259 // make sure month is set properly
260 if (isNaN(parseInt(day_))){
266 else if (isNaN(parseInt(year_))){
272 // make sure day and year are set properly
273 if (Number(day_)
> Number(year_))
278 return day + dateSeparator + month;
280 return month + dateSeparator + day;
283 function formatTime(date)
285 // date is a Date() object
286 date.setSeconds(
0); // we don't care about seconds
287 var time = date.toLocaleTimeString().replace(/[\.:]
00/, ''); // remove seconds from string
288 if (time.replace(/\./, ':').split(':')[
0].length <
2)
290 if (showNowAsText && date.getTime() == now.getTime())
291 time = '
<span class=
"now">' + nowText + '
</span>';
295 function updateData(){
297 // meetings have time
298 // 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
300 var meetingListFiltering = {
301 Type:'CalendarEntry',
303 StartRange: (new Date(now.getFullYear(), now.getMonth(), now.getDate(),
0,
0,
0)),
304 EndRange: (new Date(now.getFullYear(), now.getMonth() + monthRange, now.getDate(),
0,
0,
0))
307 var meetingResult = calendarService.IDataSource.GetList(meetingListFiltering);
308 var meetingList = meetingResult.ReturnValue;
309 // todos don't, they start on
00:
00 hrs., but should be visible anyway
310 // this will generate a list of passed todos. We have to check if they have been marked as
"done" yet
312 var todayTodoListFiltering = {
313 Type:'CalendarEntry',
316 StartRange: (new Date(now.getFullYear() -
1, now.getMonth(), now.getDate(),
0,
0,
0)),
317 EndRange: (new Date(now.getFullYear(), now.getMonth(), now.getDate(),
0,
0,
1))
320 var todayTodoResult = calendarService.IDataSource.GetList(todayTodoListFiltering);
321 var todayTodoList = todayTodoResult.ReturnValue;
322 var entryLists = [todayTodoList, meetingList];
324 var entryLists = [meetingList];
327 error('loading Calendar items list:' + e + ', line ' + e.line);
336 var entriesHtml = '
<table>';
338 var max = ((panelNum ==
0) ? eventsPerWidget :
2 * eventsPerWidget);
339 // the first outer loop iteration is for passed ToDos, the second loop is for all upcomming events (may also include ToDos)
340 for(var i=
0; counter < max && i < entryLists.length; i++){
341 while( counter < max && (entry = entryLists[i].getNext()) != undefined ){
344 // output event info for debugging
346 'event: Id=' + entry.id +
347 ',Type=' + entry.Type +
348 ',Summary=' + entry.Summary +
349 ',Location=' + entry.Location +
350 ',Status=' + entry.Status +
351 ',StartTime=' + entry.StartTime +
352 ',EndTime=' + entry.EndTime +
353 ',InstanceStartTime=' + entry.InstanceStartTime +
354 ',InstanceEndTime=' + entry.InstanceEndTime
357 // we don't want ToDos when includeTodos == false or when they are completed
358 if (entry.Type == 'ToDo' && (entry.Status ==
"TodoCompleted" || !includeTodos)){
359 console.info('skipping ' + entry.id );
364 // make sure that we don't include an event twice (useful for ToDos that might come up twice)
365 if (eventIds[entry.id] ==
1){
366 console.info('skipped (already included) ' + entry.id);
370 eventIds[entry.id] =
1;
373 if (panelNum ==
1 && counter < eventsPerWidget +
1)
376 // summary can be undefined!
377 var Summary = ((entry.Summary == null) ? '' : entry.Summary);
378 if (entry.Type == 'Meeting' && entry.Location != ''){
379 Summary += ', ' + entry.Location;
382 // fix by yves: determine start and end dates/times
383 entryStartTime = ((entry.InstanceStartTime == null) ? entry.StartTime : entry.InstanceStartTime);
384 entryEndTime = ((entry.InstanceEndTime == null) ? entry.EndTime : entry.InstanceEndTime);
386 // there can be ToDos that have no date at all!
387 if (entry.Type == 'ToDo' && entry.EndTime == null)
388 entryDate =
""; // this will cause parseDate(entryDate) to return null;
390 entryDate = ((entry.Type == 'ToDo') ? entryEndTime : entryStartTime); // ToDo's use their EndTime, the rest use StartTime
392 // Convert date/time string to Date object
393 var date = parseDate(entryDate);
396 // check if event has already passed
397 if (entry.Type == 'Meeting' || entry.Type == 'Reminder'){
398 if (entryEndTime == null){
399 if (now.getTime()
> date.getTime()){
403 }else if (entryEndTime != null){
404 var endDate = parseDate(entryEndTime);
405 if (now.getTime()
> endDate.getTime()){
412 // check if the event is currently taking place
413 if (entryStartTime != null && entryEndTime != null && date != null)
415 // check if we are between start and endtime
416 var endDate = parseDate(entryEndTime);
417 if (endDate != null && (date.getTime() < now.getTime()) && (now.getTime() < endDate.getTime()))
418 date = now; // change appointment date/time to now
421 // generate html output
422 entriesHtml += '
<tr><td><img class=
"icon" src=
"' + entry.Type + '.png" /></td>';
423 if(date == null){ // some languages have very strange locale date formats, can't parse all those. Also some todos don't have dates at all.
424 entriesHtml += '
<td colspan=
"4"><span class=
"date">' + entryDate + '
</span> ';
426 var weekDay = date.toLocaleDateString().substr(
0,weekDayLength);
427 var time = formatTime(date);
428 date = formatDate(date, entryDate);
429 if( entry.Type == 'ToDo' || entry.Type == 'Anniversary' || entry.Type == 'DayEvent' ){
430 entriesHtml += '
<td><span class=
"weekDay">' + weekDay +'
</span></td><td><span class=
"date">'+ date +'
</span></td><td colspan=
"2">';
431 }else if( entry.Type == 'Meeting' || entry.Type == 'Reminder' ){
432 entriesHtml += '
<td><span class=
"weekDay">' + weekDay +'
</span></td><td><span class=
"date">'+ date +'
</span></td><td width=
"1px"><span class=
"time">'+ time +'
</span></td><td>';
435 entriesHtml += '
<span class=
"description">' + Summary +'
</span></td></tr>';
438 entriesHtml += '
</table>';
439 if (showNothingText && entriesHtml == '
<table></table>')
440 entriesHtml = '
<div style=
"width:295px; height:75px; text-align:center; line-height:75px; overflow:visible;">' + nothingText + '
</div>';
441 if( cacheEntriesHtml != entriesHtml ){
442 document.getElementById('calendarList').innerHTML = entriesHtml;
443 cacheEntriesHtml = entriesHtml;
446 error('displaying list:' + e + ', line ' + e.line);
451 function updateScreen(){
452 // Check if opening fullscreen
453 if( window.innerHeight
> 91){
457 if (useBackgroundImage){
458 // check for screen rotation
459 if (orientation != 'portrait' && screen.width ==
360 && screen.height ==
640){
460 window.widget.prepareForTransition(
"fade");
461 orientation = 'portrait';
462 document.getElementById('body').style.backgroundImage = 'url(background_' + orientation + '.png)';
463 document.getElementById('body').style.backgroundColor = 'none';
464 window.widget.performTransition();
465 }else if (orientation != 'landscape' && screen.width ==
640 && screen.height ==
360){
466 window.widget.prepareForTransition(
"fade");
467 orientation = 'landscape';
468 document.getElementById('body').style.backgroundImage = 'url(background_' + orientation + '.png)';
469 document.getElementById('body').style.backgroundColor = 'none';
470 window.widget.performTransition();
475 function launchCalendar(){
477 widget.openApplication(calendarApp,
"");
480 error('starting Calendar App');
487 calendarService = device.getServiceObject(
"Service.Calendar",
"IDataSource"); // call calendar service
489 error('loading Calendar service');
494 requestNotification();
495 window.setInterval('updateData()',
1000 *
60 * updateDataInterval); // start update interval every
5 minutes
498 if (useBackgroundImage)
499 window.setInterval('updateScreen()',
1000 *
3); // check for screen rotation every
3 secs
502 <style type=
"text/css">
503 table{ margin:
0px; padding:
0px; border-spacing:
0px; }
504 td{ padding:
0px
5px
0px
0px; white-space:nowrap; overflow:hidden; }
505 #homescreenView{ width:
315px; height:
91px; overflow:hidden; }
506 #calendarList{ position:absolute; left:
10px; top:
4px; width:
295px; height:
75px; overflow:hidden; }
509 <body id=
"body" class=
"background">
510 <div id=
"homescreenView">
511 <div id=
"calendarList"></div>