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 /* The following classes can be modified by widget settings */
11 .backgroundFullscreen { }
23 <script type=
"text/javascript" src=
"localizedTextStrings.js" charset=
"utf-8" />
26 // valid types for the config object are 'Int', 'Bool', 'String', 'Enum', 'UID'
28 monthRange: { Type: 'Int', Default:
2, Value:
2,},
29 includeTodos: { Type: 'Bool', Default: true, Value: true,},
30 useBackgroundImage: { Type: 'Bool', Default: true, Value: true,},
31 backgroundImageLocation: { Type: 'Enum', Default: 'internal', Value: 'internal', ValidValues: ['internal', 'external']},
32 showCombinedDateTime: { Type: 'Bool', Default: false, Value: false,},
33 showLocation: { Type: 'Bool', Default: true, Value: true,},
34 showTodayAsText: { Type: 'Bool', Default: true, Value: true,},
35 todayText: { Type: 'String', Default: getLocalizedText('settings.default.todayText'), Value: getLocalizedText('settings.default.todayText'),},
36 tomorrowText: { Type: 'String', Default: getLocalizedText('settings.default.tomorrowText'), Value: getLocalizedText('settings.default.tomorrowText'),},
37 showNowAsText: { Type: 'Bool', Default: true, Value: true,},
38 nowText: { Type: 'String', Default: getLocalizedText('settings.default.nowText'), Value: getLocalizedText('settings.default.nowText'),},
39 markOverdueTodos: { Type: 'Bool', Default: true, Value: true,},
40 overdueText: {Type: 'String', Default: getLocalizedText('settings.default.overdueText'), Value: getLocalizedText('settings.default.overdueText'),},
41 dateSeparator: { Type: 'String', Default: getLocalizedText('settings.default.dateSeparator'), Value: getLocalizedText('settings.default.dateSeparator'),},
42 dateFormat: { Type: 'Enum', Default: 'auto', Value: 'auto', ValidValues: ['auto', 'DDMM', 'MMDD'],},
43 weekDayLength: { Type: 'Int', Default:
2, Value:
2,},
44 updateDataInterval: { Type: 'Int', Default:
5, Value:
5,},
45 calendarApp: { Type: 'UID', Default:
0x10005901, Value:
0x10005901,},
46 eventsPerWidget: { Type: 'Int', Default:
4, Value:
4,},
47 showNothingText: { Type: 'Bool', Default: true, Value: true,},
48 nothingText: { Type: 'String', Default: getLocalizedText('settings.default.nothingText'), Value: getLocalizedText('settings.default.nothingText'),},
49 enableDaylightSaving: { Type: 'Bool', Default: true, Value: true,},
50 hideWidgetOnCalendarOpen: { Type: 'Bool', Default: false, Value: false,},
51 cssStyle_background: { Type: 'String', Default: 'color:#ffffff; background-color:#
000000', Value: 'color:#ffffff; background-color:#
000000',},
52 cssStyle_backgroundFullscreen: { Type: 'String', Default: 'color:#ffffff; background-color:#
000000', Value: 'color:#ffffff; background-color:#
000000',},
53 cssStyle_weekDay: { Type: 'String', Default: '', Value: '',},
54 cssStyle_date: { Type: 'String', Default: '', Value: '',},
55 cssStyle_today: { Type: 'String', Default: 'color:#ff0000', Value: 'color:#ff0000',},
56 cssStyle_tomorrow: { Type: 'String', Default: 'color:#
0000ff', Value: 'color:#
0000ff',},
57 cssStyle_time: { Type: 'String', Default: '', Value: '',},
58 cssStyle_now: { Type: 'String', Default: 'color:#ff00ff', Value: 'color:#ff00ff',},
59 cssStyle_description: { Type: 'String', Default: '', Value: '',},
60 cssStyle_icon: { Type: 'String', Default: 'width:
15px; height:
15px', Value: 'width:
15px; height:
15px',},
61 cssStyle_overdue: { Type: 'String', Default: 'color:#ffff00', Value: 'color:#ffff00',},
66 //-------------------------------------------------------
67 // Nothing of interest from here on...
68 //-------------------------------------------------------
69 var panelNum =
0; // use
1 for second panel
71 var versionURL =
"http://comingnext.sourceforge.net/version.xml";
72 var calendarService = null;
73 var cacheEntriesHtml = [];
74 var months_translated = [];
77 var mode =
0; //
0 = homescreen,
1 = fullscreen,
2 = settings,
3 = about,
4 = check for update
80 // vars for daylight saving time
81 var daylightsavingWinter =
0;
82 var daylightsavingSummer =
0;
83 var summertime = false;
86 window.onresize = updateScreen;
87 window.onshow = updateScreen;
89 function isLeapYear( year ) {
90 if (( year %
4 ==
0 && year %
100 !=
0 ) || year %
400 ==
0 )
96 function calcLeapYear(year, days)
104 function subToSunday(myDate, year, days, prevMonthDays)
106 for (i = myDate.getDay(); i
> 0 ;i--)
108 days -= prevMonthDays;
109 days = isLeapYear(year) ? --days : days;
113 function calcDaylightSaving()
115 var thisYearS = new Date(now.getFullYear(),
3,
0,
0,
0,
0 );
116 var thisYearW = new Date(now.getFullYear(),
10,
0,
0,
0,
0 );
117 var nextYearS = new Date(now.getFullYear() +
1,
3,
0,
0,
0,
0 );
118 var nextYearW = new Date(now.getFullYear() +
1,
10,
0,
0,
0,
0 );
122 thisYearSDays = nextYearSDays =
90;
123 thisYearWDays = nextYearWDays =
304;
125 thisYearSDays = calcLeapYear(now.getFullYear(), thisYearSDays);
126 thisYearWDays = calcLeapYear(now.getFullYear(), thisYearWDays);
127 nextYearSDays = calcLeapYear(now.getFullYear() +
1, nextYearSDays);
128 nextYearWDays = calcLeapYear(now.getFullYear() +
1, nextYearWDays);
130 thisYearSDays = subToSunday(thisYearS, now.getFullYear(), thisYearSDays,
59);
131 thisYearWDays = subToSunday(thisYearW, now.getFullYear(), thisYearWDays,
273);
132 nextYearSDays = subToSunday(nextYearS, now.getFullYear() +
1, nextYearSDays,
59);
133 nextYearWDays = subToSunday(nextYearW, now.getFullYear() +
1, nextYearWDays,
273);
135 daylightsavingSummer = new Date (now.getFullYear(),
03-
1, thisYearSDays,
2,
0,
0);
136 daylightsavingWinter = new Date (now.getFullYear(),
10-
1, thisYearWDays,
2,
0,
0);
137 if (daylightsavingSummer < now) {
138 daylightsavingSummer = new Date (now.getFullYear()+
1,
03-
1, nextYearSDays,
2,
0,
0);
141 if (daylightsavingWinter < now) {
142 daylightsavingWinter = new Date (now.getFullYear()+
1,
10-
1, nextYearWDays,
2,
0,
0);
145 if (summer && !winter)
151 function error(message)
153 console.info('Error: ' + message);
154 document.getElementById(
"calendarList").innerHTML = 'Error: ' + message;
157 function areDatesEqual(date1, date2)
159 return (date1.getFullYear() == date2.getFullYear() &&
160 date1.getMonth() == date2.getMonth() &&
161 date1.getDate() == date2.getDate());
164 function isTomorrow(date)
166 // tommorow = now +
1 day
167 // ToDo: some days can be shorter as
24 hours(daylight saving change day)
168 return areDatesEqual(date, new Date (now.getTime() +
24*
60*
60*
1000));
171 function isToday(date)
173 return areDatesEqual(date, now);
176 function collectLocales()
178 var tmpyear =
2000 + panelNum;
181 if (months_translated.length
> 0)
183 for (month =
0; month <
12; month++) {
184 var startDate = new Date(tmpyear, month,
15);
186 var item = new Object();
187 item.Type =
"DayEvent";
188 item.StartTime = startDate;
189 item.Summary =
"__temp" + month;
191 var criteria = new Object();
192 criteria.Type =
"CalendarEntry";
193 criteria.Item = item;
196 var result = calendarService.IDataSource.Add(criteria);
197 if (result.ErrorCode)
198 error(result.ErrorMessage);
200 error(
"collectLocales: " + e + ', line ' + e.line);
204 var startTime = new Date(tmpyear,
0,
1);
205 var endTime = new Date(tmpyear,
11,
31);
206 var listFiltering = {
207 Type:'CalendarEntry',
209 StartRange: startTime,
211 SearchText: '__temp',
215 var result = calendarService.IDataSource.GetList(listFiltering);
216 if (result.ErrorCode) {
217 error(result.ErrorMessage);
220 var list = result.ReturnValue;
222 error(e + ', line ' + e.line);
225 var ids = new Array();
231 while (list && (entry = list.getNext()) != undefined) {
232 dateArr = entry.StartTime.replace(/,/g,'').replace(/\./g,':').replace(/ /g,' ').split(' ');
233 var day = dateArr[
1];
234 var month = dateArr[
2];
235 var year = dateArr[
3];
237 // make sure month is set properly
238 if (isNaN(parseInt(day))) {
242 } else if (isNaN(parseInt(year))) {
248 console.info(entry.StartTime + ' -
> ' + month + ' ' + counter);
249 ids[counter] = entry.id;
250 months_translated[month] = counter +
1;
254 error(e + ', line ' + e.line);
259 var criteria = new Object();
260 criteria.Type =
"CalendarEntry";
265 var result = calendarService.IDataSource.Delete(criteria);
266 if (result.ErrorCode)
267 error(result.ErrorMessage);
269 error('deleting temp calendar entries:' + e + ', line ' + e.line);
274 function requestNotification()
276 var criteria = new Object();
277 criteria.Type =
"CalendarEntry";
280 var result = calendarService.IDataSource.RequestNotification(criteria, callback);
281 if (result.ErrorCode)
282 error('loading Calendar items list');
284 error(
"requestNotification: " + e + ', line ' + e.line);
288 function callback(transId, eventCode, result)
293 function parseDate(dateString)
296 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:
297 Wednesday,
26 August,
2009 24:
00:
00
298 Wednesday,
26 August,
2009 12:
00:
00 am
299 Wednesday, August
26,
2009 12:
00:
00 am
300 Wednesday,
2009 August,
26 12:
00:
00 am
301 Wednesday,
2009 August,
28 8.00.00 pm
302 Wednesday,
2009 August,
28 08:
00:
00 PM
305 if (dateString ==
"" || dateString == null)
307 var dateArr = dateString.replace(/,/g,'').replace(/\./g,':').replace(/ /g,' ').split(' ');
308 if (dateArr.length !=
5 && dateArr.length !=
6)
312 var weekDay = dateArr[
0];
313 var day = dateArr[
1];
314 var month = dateArr[
2];
315 var year = dateArr[
3];
316 // make sure month is set properly
317 if (isNaN(parseInt(day))) {
321 } else if (isNaN(parseInt(year))) {
326 // make sure day and year are set properly
327 if (Number(day)
> Number(year)) {
332 month = months_translated[month];
335 var timeArr = dateArr[
4].split(':');
336 if (timeArr.length !=
3)
338 var hours = Number(timeArr[
0]);
339 var minutes = Number(timeArr[
1]);
340 var seconds = Number(timeArr[
2]);
341 if (dateArr.length ==
6 && dateArr[
5].toLowerCase() == 'pm' && hours <
12)
343 if (dateArr.length ==
6 && dateArr[
5].toLowerCase() == 'am' && hours ==
12)
346 console.info('year=' + year + ' month=' + month + ' day=' + day + ' hours=' + hours + ' minutes=' + minutes+ ' seconds=' + seconds);
348 // take care of daylight saving time
349 if (config['enableDaylightSaving'].Value) {
350 var date = new Date(year, month -
1, day, hours, minutes, seconds);
351 if (summertime && date
> daylightsavingWinter && date < daylightsavingSummer)
353 else if (!summertime && date
> daylightsavingSummer && date < daylightsavingWinter)
357 return new Date(year, month -
1, day, hours, minutes, seconds);
360 // 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"
361 function formatDate(date, format)
363 var day = date.getDate().toString();
364 var month = (date.getMonth() +
1).toString();
365 while (day.length <
2) { day = '
0' + day; }
366 while (month.length <
2) { month = '
0' + month; }
368 if (config['showTodayAsText'].Value && isToday(date))
369 return '
<span class=
"today">' + config['todayText'].Value + '
</span>';
370 if (config['showTodayAsText'].Value && isTomorrow(date))
371 return '
<span class=
"tomorrow">' + config['tomorrowText'].Value + '
</span>';
373 var dateArr = format.replace(/,/g,'').replace(/\./g,':').replace(/ /g,' ').split(' ');
374 if (dateArr.length !=
5 && dateArr.length !=
6) {
375 // we don't know how to format this
376 if (config['dateFormat'].Value == 'auto' || config['dateFormat'].Value == 'DDMM')
377 return day + config['dateSeparator'].Value + month;
379 return month + config['dateSeparator'].Value + day;
383 if (config['dateFormat'].Value == 'MMDD')
385 else if (config['dateFormat'].Value == 'DDMM')
388 // config['dateFormat'].Value == 'auto', try to detect system setting
390 var day_ = dateArr[
1];
391 var month_ = dateArr[
2];
392 var year_ = dateArr[
3];
393 // make sure month is set properly
394 if (isNaN(parseInt(day_))) {
399 } else if (isNaN(parseInt(year_))) {
405 // make sure day and year are set properly
406 if (Number(day_)
> Number(year_))
411 return day + config['dateSeparator'].Value + month;
413 return month + config['dateSeparator'].Value + day;
416 function formatTime(date)
418 // date is a Date() object
419 date.setSeconds(
0); // we don't care about seconds
420 var time = date.toLocaleTimeString().replace(/[\.:]
00/, ''); // remove seconds from string
421 if (time.replace(/\./, ':').split(':')[
0].length <
2)
423 if (config['showNowAsText'].Value && date.getTime() == now.getTime())
424 time = '
<span class=
"now">' + config['nowText'].Value + '
</span>';
428 function updateData()
430 console.info('updateData()');
431 calcDaylightSaving();
433 // meetings have time
434 // 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
436 var meetingListFiltering = {
437 Type:'CalendarEntry',
439 StartRange: (new Date(now.getFullYear(), now.getMonth(), now.getDate(),
0,
0,
0)),
440 EndRange: (new Date(now.getFullYear(), now.getMonth() + config['monthRange'].Value, now.getDate(),
0,
0,
0))
443 var meetingResult = calendarService.IDataSource.GetList(meetingListFiltering);
444 if (meetingResult.ErrorCode !=
0)
445 throw(
"Error fetching calendar data: " + meetingResult.ErrorCode + ': ' + meetingResult.ErrorMessage);
446 var meetingList = meetingResult.ReturnValue;
448 // todos don't, they start on
00:
00 hrs., but should be visible anyway
449 // this will generate a list of passed todos. We have to check if they have been marked as
"done" yet
450 if (config['includeTodos'].Value) {
451 var todayTodoListFiltering = {
452 Type:'CalendarEntry',
455 StartRange: (new Date(now.getFullYear() -
1, now.getMonth(), now.getDate(),
0,
0,
0)),
456 EndRange: (new Date(now.getFullYear(), now.getMonth(), now.getDate(),
0,
0,
1))
459 var todayTodoResult = calendarService.IDataSource.GetList(todayTodoListFiltering);
460 var todayTodoList = todayTodoResult.ReturnValue;
461 var entryLists = [todayTodoList, meetingList];
463 var entryLists = [meetingList];
466 error('loading Calendar items list:' + e + ', line ' + e.line);
475 var fontsize = 'normal';
477 if (config['eventsPerWidget'].Value ==
3) {
479 changeCssClass('.icon', 'width:
20px; height:
20px');
481 else if (config['eventsPerWidget'].Value ==
5) {
483 changeCssClass('.icon', 'width:
10px; height:
10px');
485 else if (config['eventsPerWidget'].Value ==
6) {
487 changeCssClass('.icon', 'width:
8px; height:
8px');
491 changeCssClass('.icon', config['cssStyle_icon'].Value);
492 var entriesHtml = '
<table style=
"font-size:' + fontsize + ';">';
496 max = (panelNum +
1) * config['eventsPerWidget'].Value;
498 max =
30; // we can display a lot more events in fullscreen mode
500 // the first outer loop iteration is for passed ToDos, the second loop is for all upcomming events (may also include ToDos)
501 for (var i=
0; counter < max && i < entryLists.length; i++) {
502 while (counter < max && (entry = entryLists[i].getNext()) != undefined) {
505 // output event info for debugging
507 'event: Id=' + entry.id +
508 ',Type=' + entry.Type +
509 ',Summary=' + entry.Summary +
510 ',Location=' + entry.Location +
511 ',Status=' + entry.Status +
512 ',StartTime=' + entry.StartTime +
513 ',EndTime=' + entry.EndTime +
514 ',InstanceStartTime=' + entry.InstanceStartTime +
515 ',InstanceEndTime=' + entry.InstanceEndTime
518 // we don't want ToDos when includeTodos == false or when they are completed
519 if (entry.Type == 'ToDo' && (entry.Status ==
"TodoCompleted" || !config['includeTodos'].Value)) {
520 console.info('skipping ' + entry.id );
525 // make sure that we don't include an event twice (useful for ToDos that might come up twice)
526 if (eventIds[entry.id] ==
1 && entry.Type == 'ToDo') {
527 console.info('skipped (already included) ' + entry.id);
531 eventIds[entry.id] =
1;
533 // summary can be undefined!
534 var Summary = ((entry.Summary == null) ? '' : entry.Summary);
535 if (entry.Type == 'Meeting' && entry.Location != '' && config['showLocation'].Value)
536 Summary += ', ' + entry.Location;
538 // fix by yves: determine start and end dates/times
539 entryStartTime = ((entry.InstanceStartTime == null) ? entry.StartTime : entry.InstanceStartTime);
540 entryEndTime = ((entry.InstanceEndTime == null) ? entry.EndTime : entry.InstanceEndTime);
542 // there can be ToDos that have no date at all!
543 if (entry.Type == 'ToDo' && entry.EndTime == null)
544 entryDate =
""; // this will cause parseDate(entryDate) to return null;
546 entryDate = ((entry.Type == 'ToDo') ? entryEndTime : entryStartTime); // ToDo's use their EndTime, the rest use StartTime
548 // Convert date/time string to Date object
549 var date = parseDate(entryDate);
550 console.info('date: ' + date);
551 var endDate = ((entryEndTime == null) ? null : parseDate(entryEndTime));
552 console.info('endDate: ' + endDate);
554 // check if meeting event has already passed
555 if (entry.Type == 'Meeting') {
556 var compareTime = ((endDate == null) ? date.getTime() : endDate.getTime());
557 if (now.getTime()
> compareTime) {
558 console.info('skipping Meeting (already passed) ' + entry.id);
560 eventIds[entry.id] =
0;
565 // check if anniversary passed (not sure why they are in the list, the query was only for today - nokia?)
566 if (entry.Type == 'Anniversary') {
567 var tmp = new Date(now.getFullYear(), now.getMonth(), now.getDate(),
0,
0,
0);
568 if (date.getTime() < tmp.getTime()) {
569 console.info('skipping Anniversary (already passed) ' + entry.id);
571 eventIds[entry.id] =
0;
576 // fix DayEvents end time. End times are off by
1 Second. It's possible that the event has already passed
577 if (entry.Type == 'DayEvent' && endDate != null) {
578 endDate.setMinutes(endDate.getMinutes() -
1);
579 console.info('fixing DayEvent endDate: ' + endDate);
580 if (now.getTime()
> endDate.getTime()) {
581 console.info('event already passed ' + entry.id);
583 eventIds[entry.id] =
0;
588 // check if the event is currently taking place
589 if (entryStartTime != null && entryEndTime != null && date != null && endDate != null) {
590 // check if we are between start and endtime
591 if ((date.getTime() < now.getTime()) && (now.getTime() < endDate.getTime())) {
592 date = now; // change appointment date/time to now
593 console.info('event is currently taking place: ' + date);
597 // skip events for the first panel in case this is the second one and we're not in fullscreen mode
598 if (mode ==
0 && panelNum
> 0 && counter < panelNum * config['eventsPerWidget'].Value +
1) {
599 console.info('skipping (already in first widget) ' + entry.id);
603 // mark overdue todos
605 if (entry.Type == 'ToDo' && date != null) {
606 var tmp1 = new Date(date.getFullYear(), date.getMonth(), date.getDate(),
0,
0,
0);
607 var tmp2 = new Date(now.getFullYear(), now.getMonth(), now.getDate(),
0,
0,
0);
608 if (tmp1.getTime() < tmp2.getTime()) {
613 // generate html output
614 entriesHtml += '
<tr><td><img class=
"icon" src=
"' + entry.Type + '.png" /></td>';
616 // some languages have very strange locale date formats, can't parse all those. Also some todos don't have dates at all.
617 entriesHtml += '
<td colspan=
"4"><span class=
"date">' + entryDate + '
</span> ';
619 var weekDay = date.toLocaleDateString().substr(
0,config['weekDayLength'].Value);
620 var time = formatTime(date);
621 var dateStr = formatDate(date, entryDate);
622 if (entry.Type == 'ToDo' && overdue && config['markOverdueTodos'].Value) {
623 dateStr = '
<span class=
"overdue">' + config['overdueText'].Value + '
</span>';
624 entriesHtml += '
<td colspan=
"4" width=
"1px"><span class=
"date">' + dateStr + '
</span> ';
625 } else if (entry.Type == 'ToDo' || entry.Type == 'Anniversary' || entry.Type == 'DayEvent' || entry.Type == 'Reminder') {
626 if ((isToday(date) || isTomorrow(date)) && config['showTodayAsText'].Value) // show weekday if the date string is not text. looks odd otherwise
627 entriesHtml += '
<td colspan=
"4" width=
"1px"><span class=
"date">' + dateStr + '
</span> ';
629 entriesHtml += '
<td class=
"weekDay" width=
"1px">' + weekDay + '
</td><td width=
"1px" class=
"date">' + dateStr + '
</td><td colspan=
"2">';
630 } else if (entry.Type == 'Meeting') {
631 if (config['showCombinedDateTime'].Value) {
633 entriesHtml += '
<td width=
"1px" colspan=
"4"><span class=
"today">' + time + '
</span> ';
634 else if (isTomorrow(date))
635 entriesHtml += '
<td width=
"1px" colspan=
"4"><span class=
"tomorrow">' + dateStr + '
</span> <span class=
"time">' + time + '
</span> ';
637 entriesHtml += '
<td width=
"1px" class=
"weekDay">' + weekDay + '
</td><td width=
"1px" class=
"date">' + dateStr + '
</td><td colspan=
"2">';
639 if ((isToday(date) || isTomorrow(date)) && config['showTodayAsText'].Value)
640 entriesHtml += '
<td colspan=
"4" width=
"1px"><span class=
"today">' + dateStr + '
</span> <span class=
"time">' + time + '
</span> ';
642 entriesHtml += '
<td width=
"1px" class=
"weekDay">' + weekDay + '
</td><td width=
"1px" class=
"date">' + dateStr + '
</td><td width=
"1px" class=
"time">' + time + '
</td><td>';
646 entriesHtml += '
<span class=
"description">' + Summary + '
</span></td></tr>';
649 entriesHtml += '
</table>';
650 if (config['showNothingText'].Value && entriesHtml == '
<table></table>') {
651 var text = config['nothingText'].Value.replace(/%d/, config['monthRange'].Value);
652 entriesHtml = '
<div style=
"width:295px; height:75px; text-align:center; line-height:75px; overflow:visible;">' + text + '
</div>';
654 if (cacheEntriesHtml != entriesHtml) {
656 document.getElementById('calendarList').innerHTML = entriesHtml;
658 document.getElementById('fullscreenCalendarList').innerHTML = entriesHtml;
659 cacheEntriesHtml = entriesHtml;
662 error('displaying list:' + e + ', line ' + e.line);
667 function updateScreen()
669 // check if opening fullscreen
670 if( window.innerHeight
> 91 && mode ==
0) {
672 cacheEntriesHtml = '';
673 document.getElementById('body').style.backgroundImage =
"";
676 else if (window.innerHeight <=
91 && mode !=
0) {
678 cacheEntriesHtml = '';
688 function launchCalendar()
691 widget.openApplication(config['calendarApp'].Value,
"");
692 if (config['hideWidgetOnCalendarOpen'].Value)
695 error('starting Calendar App');
702 console.info('New widget instance starting up...');
705 // call calendar service
706 if (device !=
"undefined")
707 calendarService = device.getServiceObject(
"Service.Calendar",
"IDataSource");
709 throw('device object does not exist');
711 error('loading Calendar service: ' + e + ', line ' + e.line);
719 requestNotification();
720 window.setInterval('updateData()',
1000 *
60 * config['updateDataInterval'].Value);
725 if (config['useBackgroundImage'].Value)
726 // check for screen rotation every
1 secs
727 window.setInterval('updateScreen()',
1000 *
1);
730 function createMenu()
732 window.menu.setLeftSoftkeyLabel(
"",null);
733 window.menu.setRightSoftkeyLabel(
"",null);
735 var menuSettings = new MenuItem(getLocalizedText('menu.settings'), id++);
736 var menuCallApp = new MenuItem(getLocalizedText('menu.openCalendarApp'), id++);
737 var menuUpdate = new MenuItem(getLocalizedText('menu.update'), id++);
738 var menuAbout = new MenuItem(getLocalizedText('menu.about'), id++);
739 menuSettings.onSelect = showSettings;
740 menuAbout.onSelect = showAbout;
741 menuCallApp.onSelect = launchCalendar;
742 menuUpdate.onSelect = showUpdate;
744 window.menu.append(menuCallApp);
745 window.menu.append(menuSettings);
746 window.menu.append(menuUpdate);
747 window.menu.append(menuAbout);
750 function showSettings()
754 document.getElementById(
"settingsView").style.display =
"block";
755 document.onclick = null;
757 window.menu.setLeftSoftkeyLabel(getLocalizedText('settings.save'), function()
759 for (var key in config) {
760 if (config[key].Type == 'String')
761 config[key].Value = document.forms[
0].elements[
"settings." + key].value;
762 else if (config[key].Type == 'Int') {
763 config[key].Value = parseInt(document.forms[
0].elements[
"settings." + key].value);
764 if (config[key].Value <
0)
765 config[key].Value = config[key].Default;
767 else if (config[key].Type == 'Bool')
768 config[key].Value = document.forms[
0].elements[
"settings." + key].checked;
769 else if (config[key].Type == 'UID')
770 config[key].Value = parseInt(document.forms[
0].elements[
"settings." + key].value);
771 else if (config[key].Type == 'Enum') {
772 config[key].Value = document.forms[
0].elements[
"settings." + key].value;
773 if (config[key].ValidValues.indexOf(config[key].Value) == -
1)
774 config[key].Value = config[key].Default;
785 window.menu.setRightSoftkeyLabel(getLocalizedText('settings.cancel'), function()
791 var settingsHtml = '
<form>';
792 for (var key in config) {
793 if (config[key].Type == 'String')
794 settingsHtml += '
<table><tr><td>' + getLocalizedText('settings.name.' + key) + '
<br /><input class=
"textInput" name=
"settings.' + key + '" type=
"text" value=
"' + config[key].Value + '" /></td>' + printHintBox(getLocalizedText('settings.info.' + key)) + '
<hr />';
795 else if (config[key].Type == 'Int')
796 settingsHtml += '
<table><tr><td>' + getLocalizedText('settings.name.' + key) + '
<br /><input class=
"textInput" name=
"settings.' + key + '" type=
"text" value=
"' + config[key].Value + '" /></td>' + printHintBox(getLocalizedText('settings.info.' + key)) + '
<hr />';
797 else if (config[key].Type == 'Bool')
798 settingsHtml += '
<table><tr><td>' + getLocalizedText('settings.name.' + key) + '
<br /><input name=
"settings.' + key + '" type=
"checkbox" value=
"true" ' + (config[key].Value ? '
checked=
"checked"' : '') + '
/></td>' + printHintBox(getLocalizedText('settings.info.' + key)) + '
<hr />';
799 else if (config[key].Type == 'UID')
800 settingsHtml += '
<table><tr><td>' + getLocalizedText('settings.name.' + key) + '
<br /><input class=
"textInput" name=
"settings.' + key + '" type=
"text" value=
"0x' + config[key].Value.toString(16) + '" /></td>' + printHintBox(getLocalizedText('settings.info.' + key)) + '
<hr />';
801 else if (config[key].Type == 'Enum') {
802 settingsHtml += '
<table><tr><td>' + getLocalizedText('settings.name.' + key) + '
<br /><select name=
"settings.' + key + '" size=
"1">';
803 for(var i =
0; i < config[key].ValidValues.length; i++)
804 settingsHtml += '
<option value=
"' + config[key].ValidValues[i] + '"' + (config[key].Value == config[key].ValidValues[i] ? '
selected=
"selected"' : '') + '
>' + getLocalizedText('settings.validValues.' + key + '.' + config[key].ValidValues[i]) + '
</option>';
805 settingsHtml += '
</select></div></td>' + printHintBox(getLocalizedText('settings.info.' + key)) + '
<hr />';
808 settingsHtml += '
<input name=
"reset" type=
"button" value=
"' + getLocalizedText('settings.restoreDefaults') + '" onclick=
"javascript:restoreDefaultSettings();showSettings();" />';
809 settingsHtml += '
</form>';
810 document.getElementById(
"settingsList").innerHTML = settingsHtml;
813 function changeCssClass(classname, properties)
815 for(var i =
0; i < document.styleSheets[
0]['cssRules'].length; i++)
817 if (document.styleSheets[
0]['cssRules'][i].selectorText == classname) {
818 document.styleSheets[
0].deleteRule(i);
819 document.styleSheets[
0].insertRule(classname + ' { ' + properties + ' }', document.styleSheets[
0]['cssRules'].length);
825 function updateCssClasses()
827 for(var key in config) {
828 changeCssClass(getLocalizedText('settings.name.' + key), config[key].Value);
832 function restoreDefaultSettings()
834 for (var key in config)
835 config[key].Value = config[key].Default;
838 function loadSettings()
840 for (var key in config) {
841 if (widget.preferenceForKey(key)) {
842 if (config[key].Type == 'Int')
843 config[key].Value = Number(widget.preferenceForKey(key));
844 else if (config[key].Type == 'String')
845 config[key].Value = widget.preferenceForKey(key);
846 else if (config[key].Type == 'Bool')
847 config[key].Value = (widget.preferenceForKey(key) == 'true')
848 else if (config[key].Type == 'Enum')
849 config[key].Value = widget.preferenceForKey(key);
850 else if (config[key].Type == 'UID')
851 config[key].Value = Number(widget.preferenceForKey(key));
854 config[key].Value = config[key].Default;
855 console.info('Settings: ' + key + '=\'' + config[key].Value + '\'');
859 function saveSettings()
861 for (var key in config) {
862 if (config[key].Type == 'Int')
863 widget.setPreferenceForKey(config[key].Value.toString(), key);
864 else if (config[key].Type == 'String')
865 widget.setPreferenceForKey(config[key].Value, key);
866 else if (config[key].Type == 'Bool')
867 widget.setPreferenceForKey(config[key].Value ? 'true' : 'false', key);
868 else if (config[key].Type == 'Enum')
869 widget.setPreferenceForKey(config[key].Value, key);
870 else if (config[key].Type == 'UID')
871 widget.setPreferenceForKey(config[key].Value.toString(), key);
875 function toggleVisibility(elementId)
877 if (document.getElementById(elementId).style.display ==
"none")
878 document.getElementById(elementId).style.display =
"block";
880 document.getElementById(elementId).style.display =
"none";
884 function printHintBox(text)
887 return '
<td width=
"1%" align=
"right" onclick=
"javascript:toggleVisibility(\'info' + uniqueId + '\')">' + getLocalizedText('settings.help') + '
</td></tr></table>'+
888 '
<div class=
"settingsInfo" id=
"info' + uniqueId + '">' + text + '
</div>';
895 document.getElementById(
"aboutView").style.display =
"block";
896 document.onclick = null;
898 window.menu.setLeftSoftkeyLabel(
" ", function(){});
899 window.menu.setRightSoftkeyLabel(getLocalizedText('softkey.back'), function()
905 //document.getElementById(
"aboutView").innerHTML = 'aboutView';
906 document.getElementById(
"name").innerHTML =
"Coming Next " + version;
909 function updateFullscreen()
913 function showFullscreen()
916 document.getElementById(
"fullscreenView").style.display =
"block";
917 document.getElementById('body').className =
"backgroundFullscreen";
918 document.onclick = launchCalendar;
923 function getBackgroundImage()
926 if (config['backgroundImageLocation'].Value == config['backgroundImageLocation'].ValidValues[
0]) // internal
927 bgImage = 'background_' + orientation + '.png';
929 bgImage = 'C:/Data/background_' + panelNum + '_' + orientation + '.png';
933 function updateHomescreen()
935 if (config['useBackgroundImage'].Value) {
936 // check for screen rotation
937 if (orientation != 'portrait' && screen.width ==
360 && screen.height ==
640) {
938 window.widget.prepareForTransition(
"fade");
939 orientation = 'portrait';
940 document.getElementById('body').style.backgroundImage = 'url(' + getBackgroundImage() + ')';
941 document.getElementById('body').style.backgroundColor = 'none';
942 window.widget.performTransition();
943 } else if (orientation != 'landscape' && screen.width ==
640 && screen.height ==
360) {
944 window.widget.prepareForTransition(
"fade");
945 orientation = 'landscape';
946 document.getElementById('body').style.backgroundImage = 'url(' + getBackgroundImage() + ')';
947 document.getElementById('body').style.backgroundColor = 'none';
948 window.widget.performTransition();
950 else if (document.getElementById('body').style.backgroundImage ==
"")
952 document.getElementById('body').style.backgroundImage = 'url(' + getBackgroundImage() + ')';
957 function showHomescreen()
960 document.getElementById(
"homescreenView").style.display =
"block";
961 document.getElementById('body').className =
"background";
962 document.onclick = null;
966 function getLocalizedText(p_Txt)
968 if (localizedText[p_Txt])
969 return localizedText[p_Txt];
971 return 'ERROR: missing translation for ' + p_Txt;
974 function showUpdate()
978 document.getElementById(
"updateView").style.display =
"block";
979 document.onclick = null;
981 window.menu.setLeftSoftkeyLabel(getLocalizedText('update.checknow'), function(){
984 window.menu.setRightSoftkeyLabel(getLocalizedText('softkey.back'), function()
990 document.getElementById(
"currentVersion").innerHTML = getLocalizedText(
"update.current") + version;
994 function checkForUpdate()
996 // asynch XHR to server url
997 reqV = new XMLHttpRequest();
998 reqV.onreadystatechange = checkForUpdateCallback;
999 document.getElementById(
"updateDiv").innerHTML = getLocalizedText(
"update.checking");
1000 reqV.open(
"GET", versionURL, true);
1001 reqV.setRequestHeader(
"If-Modified-Since",
"Sat, 1 Jan 2000 00:00:00 GMT" ); // disable caching
1005 function checkForUpdateCallback()
1007 if (reqV.readyState ==
4) {
1008 if (reqV.status ==
200) {
1009 var resultXml = reqV.responseText;
1011 var div = document.getElementById(
"tmp");
1012 div.innerHTML = resultXml;
1013 var newVersion = div.getElementsByTagName('version')[
0].innerHTML;
1014 var newVersionURL = div.getElementsByTagName('url')[
0].innerHTML;
1016 if (version != newVersion) {
1017 document.getElementById(
"updateDiv").innerHTML = getLocalizedText(
"update.download").replace(/%
1/, newVersion).replace(/%
2/, newVersionURL);
1020 document.getElementById(
"updateDiv").innerHTML = getLocalizedText(
"update.nonewversion");
1025 document.getElementById(
"updateDiv").innerHTML = getLocalizedText(
"update.error") + reqV.status +
" " + reqV.responseText;
1030 function hideViews()
1032 document.getElementById(
"homescreenView").style.display =
"none";
1033 document.getElementById(
"fullscreenView").style.display =
"none";
1034 document.getElementById(
"aboutView").style.display =
"none";
1035 document.getElementById(
"settingsView").style.display =
"none";
1036 document.getElementById(
"updateView").style.display =
"none";
1040 <style type=
"text/css">
1041 table { margin:
0px; padding:
0px; border-spacing:
0px; }
1042 td { padding:
0px
5px
0px
0px; white-space:nowrap; overflow:hidden; }
1043 hr { color:#ffffff; background-color:#ffffff; height:
1px; text-align:left; border-style:none; }
1044 .settingsInfo { display:none; font-style:italic; }
1045 .title { font-weight:bold; font-size:
14pt; }
1046 .textInput { width:
90%; }
1047 .credits { margin-left:
40px; text-indent: -
20px; margin-bottom:
0px; }
1048 #homescreenView { width:
315px; height:
91px; overflow:hidden; }
1049 #calendarList { position:absolute; left:
10px; top:
4px; width:
295px; height:
75px; overflow:hidden; }
1050 #name { text-align:center; }
1051 #appicon { display: block; margin-left: auto; margin-right: auto; margin-top:
10px; }
1052 #smallappicon { width:
22px; height:
22px; margin-right:
10px; float:left; }
1057 <body id=
"body" class=
"background">
1058 <div id=
"homescreenView">
1059 <div id=
"calendarList"></div>
1061 <div id=
"fullscreenView" style=
"display:none;">
1062 <img src=
"Icon.png" id=
"smallappicon">
1063 <h1 class=
"title">Coming Next
</h1>
1065 <div id=
"fullscreenCalendarList">loading...
</div>
1067 <div id=
"settingsView" style=
"display:none">
1068 <img src=
"Icon.png" id=
"smallappicon">
1069 <h1 class=
"title">Settings
</h1>
1071 <div id=
"settingsList"></div>
1073 <div id=
"aboutView" style=
"display:none">
1074 <img src=
"Icon.png" id=
"appicon">
1075 <h1 id=
"name">Coming Next
</h1>
1077 <p>Created by Dr. Cochambre and Michael Prager.
</p>
1078 <p>Contributions:
</p>
1079 <p class=
"credits">Paul Moore (bug fixes, new features and code cleanup)
</p>
1080 <p class=
"credits">Manfred Hanselmann (DST support)
</p>
1081 <p class=
"credits">Christophe Milsent (translation support & french translation
</p>
1082 <p class=
"credits">Flavio Nathan (portuguese-brazilian translation
</p>
1083 <p>This software is open source and licensed under the GPLv3.
</p>
1084 <p>Visit sourceforge.net/projects/comingnext for free updates.
</p>
1087 <div id=
"updateView" style=
"display:none">
1088 <img src=
"Icon.png" id=
"smallappicon">
1089 <h1 class=
"title">Check for update
</h1>
1091 <div id=
"currentVersion">Coming Next ??
</div>
1092 <div id=
"updateDiv"></div>
1093 <div id=
"tmp" style=
"display:none;"></div>