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 { }
22 <script type=
"text/javascript" src=
"localizedTextStrings.js" charset=
"utf-8" />
25 // valid types for the config object are 'Int', 'Bool', 'String', 'Enum', 'UID'
27 monthRange: { Type: 'Int', Default:
2, Value:
2,},
28 includeTodos: { Type: 'Bool', Default: true, Value: true,},
29 useBackgroundImage: { Type: 'Bool', Default: true, Value: true,},
30 showCombinedDateTime: { Type: 'Bool', Default: false, Value: false,},
31 showLocation: { Type: 'Bool', Default: true, Value: true,},
32 showTodayAsText: { Type: 'Bool', Default: true, Value: true,},
33 todayText: { Type: 'String', Default: getLocalizedText('settings.default.todayText'), Value: getLocalizedText('settings.default.todayText'),},
34 tomorrowText: { Type: 'String', Default: getLocalizedText('settings.default.tomorrowText'), Value: getLocalizedText('settings.default.tomorrowText'),},
35 showNowAsText: { Type: 'Bool', Default: true, Value: true,},
36 nowText: { Type: 'String', Default: getLocalizedText('settings.default.nowText'), Value: getLocalizedText('settings.default.nowText'),},
37 dateSeparator: { Type: 'String', Default: getLocalizedText('settings.default.dateSeparator'), Value: getLocalizedText('settings.default.dateSeparator'),},
38 dateFormat: { Type: 'Enum', Default: 'auto', Value: 'auto', ValidValues: ['auto', 'DDMM', 'MMDD'],},
39 weekDayLength: { Type: 'Int', Default:
2, Value:
2,},
40 updateDataInterval: { Type: 'Int', Default:
5, Value:
5,},
41 calendarApp: { Type: 'UID', Default:
0x10005901, Value:
0x10005901,},
42 eventsPerWidget: { Type: 'Int', Default:
4, Value:
4,},
43 showNothingText: { Type: 'Bool', Default: true, Value: true,},
44 nothingText: { Type: 'String', Default: getLocalizedText('settings.default.nothingText'), Value: getLocalizedText('settings.default.nothingText'),},
45 enableDaylightSaving: { Type: 'Bool', Default: true, Value: true,},
46 hideWidgetOnCalendarOpen: { Type: 'Bool', Default: false, Value: false,},
47 cssStyle_background: { Type: 'String', Default: 'color:#ffffff; background-color:#
000000', Value: 'color:#ffffff; background-color:#
000000',},
48 cssStyle_backgroundFullscreen: { Type: 'String', Default: 'color:#ffffff; background-color:#
000000', Value: 'color:#ffffff; background-color:#
000000',},
49 cssStyle_weekDay: { Type: 'String', Default: '', Value: '',},
50 cssStyle_date: { Type: 'String', Default: '', Value: '',},
51 cssStyle_today: { Type: 'String', Default: 'color:#ff0000', Value: 'color:#ff0000',},
52 cssStyle_tomorrow: { Type: 'String', Default: 'color:#
0000ff', Value: 'color:#
0000ff',},
53 cssStyle_time: { Type: 'String', Default: '', Value: '',},
54 cssStyle_now: { Type: 'String', Default: 'color:#ff00ff', Value: 'color:#ff00ff',},
55 cssStyle_description: { Type: 'String', Default: '', Value: '',},
56 cssStyle_icon: { Type: 'String', Default: 'width:
15px; height:
15px', Value: 'width:
15px; height:
15px',},
61 //-------------------------------------------------------
62 // Nothing of interest from here on...
63 //-------------------------------------------------------
64 var panelNum =
0; // use
1 for second panel
66 var versionURL =
"http://comingnext.sourceforge.net/version.xml";
67 var calendarService = null;
68 var cacheEntriesHtml = [];
69 var months_translated = [];
72 var mode =
0; //
0 = homescreen,
1 = fullscreen,
2 = settings,
3 = about,
4 = check for update
75 // vars for daylight saving time
76 var daylightsavingWinter =
0;
77 var daylightsavingSummer =
0;
78 var summertime = false;
81 window.onresize = updateScreen;
82 window.onshow = updateScreen;
84 function isLeapYear( year ) {
85 if (( year %
4 ==
0 && year %
100 !=
0 ) || year %
400 ==
0 )
91 function calcLeapYear(year, days)
99 function subToSunday(myDate, year, days, prevMonthDays)
101 for (i = myDate.getDay(); i
> 0 ;i--)
103 days -= prevMonthDays;
104 days = isLeapYear(year) ? --days : days;
108 function calcDaylightSaving()
110 var thisYearS = new Date(now.getFullYear(),
3,
0,
0,
0,
0 );
111 var thisYearW = new Date(now.getFullYear(),
10,
0,
0,
0,
0 );
112 var nextYearS = new Date(now.getFullYear() +
1,
3,
0,
0,
0,
0 );
113 var nextYearW = new Date(now.getFullYear() +
1,
10,
0,
0,
0,
0 );
117 thisYearSDays = nextYearSDays =
90;
118 thisYearWDays = nextYearWDays =
304;
120 thisYearSDays = calcLeapYear(now.getFullYear(), thisYearSDays);
121 thisYearWDays = calcLeapYear(now.getFullYear(), thisYearWDays);
122 nextYearSDays = calcLeapYear(now.getFullYear() +
1, nextYearSDays);
123 nextYearWDays = calcLeapYear(now.getFullYear() +
1, nextYearWDays);
125 thisYearSDays = subToSunday(thisYearS, now.getFullYear(), thisYearSDays,
59);
126 thisYearWDays = subToSunday(thisYearW, now.getFullYear(), thisYearWDays,
273);
127 nextYearSDays = subToSunday(nextYearS, now.getFullYear() +
1, nextYearSDays,
59);
128 nextYearWDays = subToSunday(nextYearW, now.getFullYear() +
1, nextYearWDays,
273);
130 daylightsavingSummer = new Date (now.getFullYear(),
03-
1, thisYearSDays,
2,
0,
0);
131 daylightsavingWinter = new Date (now.getFullYear(),
10-
1, thisYearWDays,
2,
0,
0);
132 if (daylightsavingSummer < now) {
133 daylightsavingSummer = new Date (now.getFullYear()+
1,
03-
1, nextYearSDays,
2,
0,
0);
136 if (daylightsavingWinter < now) {
137 daylightsavingWinter = new Date (now.getFullYear()+
1,
10-
1, nextYearWDays,
2,
0,
0);
140 if (summer && !winter)
146 function error(message)
148 console.info('Error: ' + message);
149 document.getElementById(
"calendarList").innerHTML = 'Error: ' + message;
152 function isToday(date)
154 if (date.getDate() == now.getDate() && date.getMonth() == now.getMonth())
159 function isTomorrow(date)
161 if ((date.getDate() == now.getDate() +
1 && date.getMonth() == now.getMonth()) ||
162 (date.getDate() ==
0 && date.getMonth() == now.getMonth() +
1) ||
163 (date.getDate() ==
0 && date.getMonth() == now.getMonth() +
1 && date.getYear() == now.getYear() +
1))
168 function collectLocales()
170 var tmpyear = ((panelNum ==
0) ?
2000 :
2001);
173 if (months_translated.length
> 0)
175 for (month =
0; month <
12; month++) {
176 var startDate = new Date(tmpyear, month,
15);
178 var item = new Object();
179 item.Type =
"DayEvent";
180 item.StartTime = startDate;
181 item.Summary =
"__temp" + month;
183 var criteria = new Object();
184 criteria.Type =
"CalendarEntry";
185 criteria.Item = item;
188 var result = calendarService.IDataSource.Add(criteria);
189 if (result.ErrorCode)
190 error(result.ErrorMessage);
192 error(
"collectLocales: " + e + ', line ' + e.line);
196 var startTime = new Date(tmpyear,
0,
1);
197 var endTime = new Date(tmpyear,
11,
31);
198 var listFiltering = {
199 Type:'CalendarEntry',
201 StartRange: startTime,
203 SearchText: '__temp',
207 var result = calendarService.IDataSource.GetList(listFiltering);
208 if (result.ErrorCode) {
209 error(result.ErrorMessage);
212 var list = result.ReturnValue;
214 error(e + ', line ' + e.line);
217 var ids = new Array();
223 while (list && (entry = list.getNext()) != undefined) {
224 dateArr = entry.StartTime.replace(/,/g,'').replace(/\./g,':').replace(/ /g,' ').split(' ');
225 var day = dateArr[
1];
226 var month = dateArr[
2];
227 var year = dateArr[
3];
229 // make sure month is set properly
230 if (isNaN(parseInt(day))) {
234 } else if (isNaN(parseInt(year))) {
240 console.info(entry.StartTime + ' -
> ' + month + ' ' + counter);
241 ids[counter] = entry.id;
242 months_translated[month] = counter +
1;
246 error(e + ', line ' + e.line);
251 var criteria = new Object();
252 criteria.Type =
"CalendarEntry";
257 var result = calendarService.IDataSource.Delete(criteria);
258 if (result.ErrorCode)
259 error(result.ErrorMessage);
261 error('deleting temp calendar entries:' + e + ', line ' + e.line);
266 function requestNotification()
268 var criteria = new Object();
269 criteria.Type =
"CalendarEntry";
272 var result = calendarService.IDataSource.RequestNotification(criteria, callback);
273 if (result.ErrorCode)
274 error('loading Calendar items list');
276 error(
"requestNotification: " + e + ', line ' + e.line);
280 function callback(transId, eventCode, result)
285 function parseDate(dateString)
288 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:
289 Wednesday,
26 August,
2009 24:
00:
00
290 Wednesday,
26 August,
2009 12:
00:
00 am
291 Wednesday, August
26,
2009 12:
00:
00 am
292 Wednesday,
2009 August,
26 12:
00:
00 am
293 Wednesday,
2009 August,
28 8.00.00 pm
294 Wednesday,
2009 August,
28 08:
00:
00 PM
297 if (dateString ==
"" || dateString == null)
299 var dateArr = dateString.replace(/,/g,'').replace(/\./g,':').replace(/ /g,' ').split(' ');
300 if (dateArr.length !=
5 && dateArr.length !=
6)
304 var weekDay = dateArr[
0];
305 var day = dateArr[
1];
306 var month = dateArr[
2];
307 var year = dateArr[
3];
308 // make sure month is set properly
309 if (isNaN(parseInt(day))) {
313 } else if (isNaN(parseInt(year))) {
318 // make sure day and year are set properly
319 if (Number(day)
> Number(year)) {
324 month = months_translated[month];
327 var timeArr = dateArr[
4].split(':');
328 if (timeArr.length !=
3)
330 var hours = Number(timeArr[
0]);
331 var minutes = Number(timeArr[
1]);
332 var seconds = Number(timeArr[
2]);
333 if (dateArr.length ==
6 && dateArr[
5].toLowerCase() == 'pm' && hours <
12)
335 if (dateArr.length ==
6 && dateArr[
5].toLowerCase() == 'am' && hours ==
12)
338 console.info('year=' + year + ' month=' + month + ' day=' + day + ' hours=' + hours + ' minutes=' + minutes+ ' seconds=' + seconds);
340 // take care of daylight saving time
341 if (config['enableDaylightSaving'].Value) {
342 var date = new Date(year, month -
1, day, hours, minutes, seconds);
343 if (summertime && date
> daylightsavingWinter && date < daylightsavingSummer)
345 else if (!summertime && date
> daylightsavingSummer && date < daylightsavingWinter)
349 return new Date(year, month -
1, day, hours, minutes, seconds);
352 // 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"
353 function formatDate(date, format)
355 var day = date.getDate().toString();
356 var month = (date.getMonth() +
1).toString();
357 while (day.length <
2) { day = '
0' + day; }
358 while (month.length <
2) { month = '
0' + month; }
360 if (config['showTodayAsText'].Value && isToday(date))
361 return '
<span class=
"today">' + config['todayText'].Value + '
</span>';
362 if (config['showTodayAsText'].Value && isTomorrow(date))
363 return '
<span class=
"tomorrow">' + config['tomorrowText'].Value + '
</span>';
365 var dateArr = format.replace(/,/g,'').replace(/\./g,':').replace(/ /g,' ').split(' ');
366 if (dateArr.length !=
5 && dateArr.length !=
6) {
367 // we don't know how to format this
368 if (config['dateFormat'].Value == 'auto' || config['dateFormat'].Value == 'DDMM')
369 return day + config['dateSeparator'].Value + month;
371 return month + config['dateSeparator'].Value + day;
375 if (config['dateFormat'].Value == 'MMDD')
377 else if (config['dateFormat'].Value == 'DDMM')
380 // config['dateFormat'].Value == 'auto', try to detect system setting
382 var day_ = dateArr[
1];
383 var month_ = dateArr[
2];
384 var year_ = dateArr[
3];
385 // make sure month is set properly
386 if (isNaN(parseInt(day_))) {
391 } else if (isNaN(parseInt(year_))) {
397 // make sure day and year are set properly
398 if (Number(day_)
> Number(year_))
403 return day + config['dateSeparator'].Value + month;
405 return month + config['dateSeparator'].Value + day;
408 function formatTime(date)
410 // date is a Date() object
411 date.setSeconds(
0); // we don't care about seconds
412 var time = date.toLocaleTimeString().replace(/[\.:]
00/, ''); // remove seconds from string
413 if (time.replace(/\./, ':').split(':')[
0].length <
2)
415 if (config['showNowAsText'].Value && date.getTime() == now.getTime())
416 time = '
<span class=
"now">' + config['nowText'].Value + '
</span>';
420 function updateData()
422 console.info('updateData()');
423 calcDaylightSaving();
425 // meetings have time
426 // 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
428 var meetingListFiltering = {
429 Type:'CalendarEntry',
431 StartRange: (new Date(now.getFullYear(), now.getMonth(), now.getDate(),
0,
0,
0)),
432 EndRange: (new Date(now.getFullYear(), now.getMonth() + config['monthRange'].Value, now.getDate(),
0,
0,
0))
435 var meetingResult = calendarService.IDataSource.GetList(meetingListFiltering);
436 if (meetingResult.ErrorCode !=
0)
437 throw(
"Error fetching calendar data: " + meetingResult.ErrorCode + ': ' + meetingResult.ErrorMessage);
438 var meetingList = meetingResult.ReturnValue;
440 // todos don't, they start on
00:
00 hrs., but should be visible anyway
441 // this will generate a list of passed todos. We have to check if they have been marked as
"done" yet
442 if (config['includeTodos'].Value) {
443 var todayTodoListFiltering = {
444 Type:'CalendarEntry',
447 StartRange: (new Date(now.getFullYear() -
1, now.getMonth(), now.getDate(),
0,
0,
0)),
448 EndRange: (new Date(now.getFullYear(), now.getMonth(), now.getDate(),
0,
0,
1))
451 var todayTodoResult = calendarService.IDataSource.GetList(todayTodoListFiltering);
452 var todayTodoList = todayTodoResult.ReturnValue;
453 var entryLists = [todayTodoList, meetingList];
455 var entryLists = [meetingList];
458 error('loading Calendar items list:' + e + ', line ' + e.line);
467 var entriesHtml = '
<table>';
471 max = ((panelNum ==
0) ? config['eventsPerWidget'].Value :
2 * config['eventsPerWidget'].Value);
473 max =
30; // we can display a lot more events in fullscreen mode
475 // the first outer loop iteration is for passed ToDos, the second loop is for all upcomming events (may also include ToDos)
476 for (var i=
0; counter < max && i < entryLists.length; i++) {
477 while (counter < max && (entry = entryLists[i].getNext()) != undefined) {
480 // output event info for debugging
482 'event: Id=' + entry.id +
483 ',Type=' + entry.Type +
484 ',Summary=' + entry.Summary +
485 ',Location=' + entry.Location +
486 ',Status=' + entry.Status +
487 ',StartTime=' + entry.StartTime +
488 ',EndTime=' + entry.EndTime +
489 ',InstanceStartTime=' + entry.InstanceStartTime +
490 ',InstanceEndTime=' + entry.InstanceEndTime
493 // we don't want ToDos when includeTodos == false or when they are completed
494 if (entry.Type == 'ToDo' && (entry.Status ==
"TodoCompleted" || !config['includeTodos'].Value)) {
495 console.info('skipping ' + entry.id );
500 // make sure that we don't include an event twice (useful for ToDos that might come up twice)
501 if (eventIds[entry.id] ==
1 && entry.Type == 'ToDo') {
502 console.info('skipped (already included) ' + entry.id);
506 eventIds[entry.id] =
1;
508 // summary can be undefined!
509 var Summary = ((entry.Summary == null) ? '' : entry.Summary);
510 if (entry.Type == 'Meeting' && entry.Location != '' && config['showLocation'].Value)
511 Summary += ', ' + entry.Location;
513 // fix by yves: determine start and end dates/times
514 entryStartTime = ((entry.InstanceStartTime == null) ? entry.StartTime : entry.InstanceStartTime);
515 entryEndTime = ((entry.InstanceEndTime == null) ? entry.EndTime : entry.InstanceEndTime);
517 // there can be ToDos that have no date at all!
518 if (entry.Type == 'ToDo' && entry.EndTime == null)
519 entryDate =
""; // this will cause parseDate(entryDate) to return null;
521 entryDate = ((entry.Type == 'ToDo') ? entryEndTime : entryStartTime); // ToDo's use their EndTime, the rest use StartTime
523 // Convert date/time string to Date object
524 var date = parseDate(entryDate);
525 console.info('date: ' + date);
526 var endDate = ((entryEndTime == null) ? null : parseDate(entryEndTime));
527 console.info('endDate: ' + endDate);
529 // check if meeting event has already passed
530 if (entry.Type == 'Meeting') {
531 var compareTime = ((endDate == null) ? date.getTime() : endDate.getTime());
532 if (now.getTime()
> compareTime) {
533 console.info('skipping Meeting (already passed) ' + entry.id);
535 eventIds[entry.id] =
0;
540 // check if anniversary passed (not sure why they are in the list, the query was only for today - nokia?)
541 if (entry.Type == 'Anniversary') {
542 var tmp = new Date(now.getFullYear(), now.getMonth(), now.getDate(),
0,
0,
0);
543 if (date.getTime() < tmp.getTime()) {
544 console.info('skipping Anniversary (already passed) ' + entry.id);
546 eventIds[entry.id] =
0;
551 // fix DayEvents end time. End times are off by
1 Second. It's possible that the event has already passed
552 if (entry.Type == 'DayEvent' && endDate != null) {
553 endDate.setMinutes(endDate.getMinutes() -
1);
554 console.info('fixing DayEvent endDate: ' + endDate);
555 if (now.getTime()
> endDate.getTime()) {
556 console.info('event already passed ' + entry.id);
558 eventIds[entry.id] =
0;
563 // check if the event is currently taking place
564 if (entryStartTime != null && entryEndTime != null && date != null && endDate != null) {
565 // check if we are between start and endtime
566 if ((date.getTime() < now.getTime()) && (now.getTime() < endDate.getTime())) {
567 date = now; // change appointment date/time to now
568 console.info('event is currently taking place: ' + date);
572 // skip events for the first panel in case this is the second one and we're not in fullscreen mode
573 if (mode ==
0 && panelNum ==
1 && counter < config['eventsPerWidget'].Value +
1) {
574 console.info('skipping (already in first widget) ' + entry.id);
578 // generate html output
579 entriesHtml += '
<tr><td><img class=
"icon" src=
"' + entry.Type + '.png" /></td>';
581 // some languages have very strange locale date formats, can't parse all those. Also some todos don't have dates at all.
582 entriesHtml += '
<td colspan=
"4"><span class=
"date">' + entryDate + '
</span> ';
584 var weekDay = date.toLocaleDateString().substr(
0,config['weekDayLength'].Value);
585 var time = formatTime(date);
586 var dateStr = formatDate(date, entryDate);
587 if (entry.Type == 'ToDo' || entry.Type == 'Anniversary' || entry.Type == 'DayEvent' || entry.Type == 'Reminder') {
588 if ((isToday(date) || isTomorrow(date)) && config['showTodayAsText'].Value) // show weekday if the date string is not text. looks odd otherwise
589 entriesHtml += '
<td colspan=
"4" width=
"1px"><span class=
"date">' + dateStr + '
</span> ';
591 entriesHtml += '
<td class=
"weekDay" width=
"1px">' + weekDay + '
</td><td width=
"1px" class=
"date">' + dateStr + '
</td><td colspan=
"2">';
592 } else if (entry.Type == 'Meeting') {
593 if (config['showCombinedDateTime'].Value) {
595 entriesHtml += '
<td width=
"1px" colspan=
"4"><span class=
"today">' + time + '
</span> ';
596 else if (isTomorrow(date))
597 entriesHtml += '
<td width=
"1px" colspan=
"4"><span class=
"tomorrow">' + dateStr + '
</span> <span class=
"time">' + time + '
</span> ';
599 entriesHtml += '
<td width=
"1px" class=
"weekDay">' + weekDay + '
</td><td width=
"1px" class=
"date">' + dateStr + '
</td><td colspan=
"2">';
601 if ((isToday(date) || isTomorrow(date)) && config['showTodayAsText'].Value)
602 entriesHtml += '
<td colspan=
"4" width=
"1px"><span class=
"today">' + dateStr + '
</span> <span class=
"time">' + time + '
</span> ';
604 entriesHtml += '
<td width=
"1px" class=
"weekDay">' + weekDay + '
</td><td width=
"1px" class=
"date">' + dateStr + '
</td><td width=
"1px" class=
"time">' + time + '
</td><td>';
608 entriesHtml += '
<span class=
"description">' + Summary + '
</span></td></tr>';
611 entriesHtml += '
</table>';
612 if (config['showNothingText'].Value && entriesHtml == '
<table></table>') {
613 var text = config['nothingText'].Value.replace(/%d/, config['monthRange'].Value);
614 entriesHtml = '
<div style=
"width:295px; height:75px; text-align:center; line-height:75px; overflow:visible;">' + text + '
</div>';
616 if (cacheEntriesHtml != entriesHtml) {
618 document.getElementById('calendarList').innerHTML = entriesHtml;
620 document.getElementById('fullscreenCalendarList').innerHTML = entriesHtml;
621 cacheEntriesHtml = entriesHtml;
624 error('displaying list:' + e + ', line ' + e.line);
629 function updateScreen()
631 // check if opening fullscreen
632 if( window.innerHeight
> 91 && mode ==
0) {
634 cacheEntriesHtml = '';
635 document.getElementById('body').style.backgroundImage =
"";
638 else if (window.innerHeight <=
91 && mode !=
0) {
640 cacheEntriesHtml = '';
650 function launchCalendar()
653 widget.openApplication(config['calendarApp'].Value,
"");
654 if (config['hideWidgetOnCalendarOpen'].Value)
657 error('starting Calendar App');
664 console.info('New widget instance starting up...');
667 // call calendar service
668 if (device !=
"undefined")
669 calendarService = device.getServiceObject(
"Service.Calendar",
"IDataSource");
671 throw('device object does not exist');
673 error('loading Calendar service: ' + e + ', line ' + e.line);
681 requestNotification();
682 window.setInterval('updateData()',
1000 *
60 * config['updateDataInterval'].Value);
687 if (config['useBackgroundImage'].Value)
688 // check for screen rotation every
1 secs
689 window.setInterval('updateScreen()',
1000 *
1);
692 function createMenu()
694 window.menu.setLeftSoftkeyLabel(
"",null);
695 window.menu.setRightSoftkeyLabel(
"",null);
697 var menuSettings = new MenuItem(getLocalizedText('menu.settings'), id++);
698 var menuCallApp = new MenuItem(getLocalizedText('menu.openCalendarApp'), id++);
699 var menuUpdate = new MenuItem(getLocalizedText('menu.update'), id++);
700 var menuAbout = new MenuItem(getLocalizedText('menu.about'), id++);
701 menuSettings.onSelect = showSettings;
702 menuAbout.onSelect = showAbout;
703 menuCallApp.onSelect = launchCalendar;
704 menuUpdate.onSelect = showUpdate;
706 window.menu.append(menuCallApp);
707 window.menu.append(menuSettings);
708 window.menu.append(menuUpdate);
709 window.menu.append(menuAbout);
712 function showSettings()
716 document.getElementById(
"settingsView").style.display =
"block";
717 document.onclick = null;
719 window.menu.setLeftSoftkeyLabel(getLocalizedText('settings.save'), function()
721 for (var key in config) {
722 if (config[key].Type == 'String')
723 config[key].Value = document.forms[
0].elements[
"settings." + key].value;
724 else if (config[key].Type == 'Int') {
725 config[key].Value = parseInt(document.forms[
0].elements[
"settings." + key].value);
726 if (config[key].Value <
0)
727 config[key].Value = config[key].Default;
729 else if (config[key].Type == 'Bool')
730 config[key].Value = document.forms[
0].elements[
"settings." + key].checked;
731 else if (config[key].Type == 'UID')
732 config[key].Value = parseInt(document.forms[
0].elements[
"settings." + key].value);
733 else if (config[key].Type == 'Enum') {
734 config[key].Value = document.forms[
0].elements[
"settings." + key].value;
735 if (config[key].ValidValues.indexOf(config[key].Value) == -
1)
736 config[key].Value = config[key].Default;
747 window.menu.setRightSoftkeyLabel(getLocalizedText('settings.cancel'), function()
753 var settingsHtml = '
<form>';
754 for (var key in config) {
755 if (config[key].Type == 'String')
756 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 />';
757 else if (config[key].Type == 'Int')
758 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 />';
759 else if (config[key].Type == 'Bool')
760 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 />';
761 else if (config[key].Type == 'UID')
762 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 />';
763 else if (config[key].Type == 'Enum') {
764 settingsHtml += '
<table><tr><td>' + getLocalizedText('settings.name.' + key) + '
<br /><select name=
"settings.' + key + '" size=
"1">';
765 for(var i =
0; i < config[key].ValidValues.length; i++)
766 settingsHtml += '
<option label=
"' + config[key].ValidValues[i] + '"' + (config[key].Value == config[key].ValidValues[i] ? '
selected=
"selected"' : '') + '
>' + config[key].ValidValues[i] + '
</option>';
767 settingsHtml += '
</select></div></td>' + printHintBox(getLocalizedText('settings.info.' + key)) + '
<hr />';
770 settingsHtml += '
<input name=
"reset" type=
"button" value=
"' + getLocalizedText('settings.restoreDefaults') + '" onclick=
"javascript:restoreDefaultSettings();showSettings();" />';
771 settingsHtml += '
</form>';
772 document.getElementById(
"settingsList").innerHTML = settingsHtml;
775 function changeCssClass(classname, properties)
777 for(var i =
0; i < document.styleSheets[
0]['cssRules'].length; i++)
779 if (document.styleSheets[
0]['cssRules'][i].selectorText == classname) {
780 document.styleSheets[
0].deleteRule(i);
781 document.styleSheets[
0].insertRule(classname + ' { ' + properties + ' }', document.styleSheets[
0]['cssRules'].length);
787 function updateCssClasses()
789 for(var key in config) {
790 changeCssClass(getLocalizedText('settings.name.' + key), config[key].Value);
794 function restoreDefaultSettings()
796 for (var key in config)
797 config[key].Value = config[key].Default;
800 function loadSettings()
802 for (var key in config) {
803 if (widget.preferenceForKey(key)) {
804 if (config[key].Type == 'Int')
805 config[key].Value = Number(widget.preferenceForKey(key));
806 else if (config[key].Type == 'String')
807 config[key].Value = widget.preferenceForKey(key);
808 else if (config[key].Type == 'Bool')
809 config[key].Value = (widget.preferenceForKey(key) == 'true')
810 else if (config[key].Type == 'Enum')
811 config[key].Value = widget.preferenceForKey(key);
812 else if (config[key].Type == 'UID')
813 config[key].Value = Number(widget.preferenceForKey(key));
816 config[key].Value = config[key].Default;
817 console.info('Settings: ' + key + '=\'' + config[key].Value + '\'');
821 function saveSettings()
823 for (var key in config) {
824 if (config[key].Type == 'Int')
825 widget.setPreferenceForKey(config[key].Value.toString(), key);
826 else if (config[key].Type == 'String')
827 widget.setPreferenceForKey(config[key].Value, key);
828 else if (config[key].Type == 'Bool')
829 widget.setPreferenceForKey(config[key].Value ? 'true' : 'false', key);
830 else if (config[key].Type == 'Enum')
831 widget.setPreferenceForKey(config[key].Value, key);
832 else if (config[key].Type == 'UID')
833 widget.setPreferenceForKey(config[key].Value.toString(), key);
837 function toggleVisibility(elementId)
839 if (document.getElementById(elementId).style.display ==
"none")
840 document.getElementById(elementId).style.display =
"block";
842 document.getElementById(elementId).style.display =
"none";
846 function printHintBox(text)
849 return '
<td width=
"1%" align=
"right" onclick=
"javascript:toggleVisibility(\'info' + uniqueId + '\')">' + getLocalizedText('settings.help') + '
</td></tr></table>'+
850 '
<div class=
"settingsInfo" id=
"info' + uniqueId + '">' + text + '
</div>';
857 document.getElementById(
"aboutView").style.display =
"block";
858 document.onclick = null;
860 window.menu.setLeftSoftkeyLabel(
" ", function(){});
861 window.menu.setRightSoftkeyLabel(getLocalizedText('softkey.back'), function()
867 //document.getElementById(
"aboutView").innerHTML = 'aboutView';
868 document.getElementById(
"name").innerHTML =
"Coming Next " + version;
871 function updateFullscreen()
875 function showFullscreen()
878 document.getElementById(
"fullscreenView").style.display =
"block";
879 document.getElementById('body').className =
"backgroundFullscreen";
880 document.onclick = launchCalendar;
885 function updateHomescreen()
887 if (config['useBackgroundImage'].Value) {
888 // check for screen rotation
889 if (orientation != 'portrait' && screen.width ==
360 && screen.height ==
640) {
890 window.widget.prepareForTransition(
"fade");
891 orientation = 'portrait';
892 document.getElementById('body').style.backgroundImage = 'url(background_' + orientation + '.png)';
893 document.getElementById('body').style.backgroundColor = 'none';
894 window.widget.performTransition();
895 } else if (orientation != 'landscape' && screen.width ==
640 && screen.height ==
360) {
896 window.widget.prepareForTransition(
"fade");
897 orientation = 'landscape';
898 document.getElementById('body').style.backgroundImage = 'url(background_' + orientation + '.png)';
899 document.getElementById('body').style.backgroundColor = 'none';
900 window.widget.performTransition();
902 else if (document.getElementById('body').style.backgroundImage ==
"")
904 document.getElementById('body').style.backgroundImage = 'url(background_' + orientation + '.png)';
909 function showHomescreen()
912 document.getElementById(
"homescreenView").style.display =
"block";
913 document.getElementById('body').className =
"background";
914 document.onclick = null;
918 function getLocalizedText(p_Txt)
920 if (localizedText[p_Txt])
921 return localizedText[p_Txt];
923 return 'ERROR: missing translation for ' + p_Txt;
926 function showUpdate()
930 document.getElementById(
"updateView").style.display =
"block";
931 document.onclick = null;
933 window.menu.setLeftSoftkeyLabel(getLocalizedText('update.checknow'), function(){
936 window.menu.setRightSoftkeyLabel(getLocalizedText('softkey.back'), function()
942 document.getElementById(
"currentVersion").innerHTML = getLocalizedText(
"update.current") + version;
946 function checkForUpdate()
948 // asynch XHR to server url
949 reqV = new XMLHttpRequest();
950 reqV.onreadystatechange = checkForUpdateCallback;
951 document.getElementById(
"updateDiv").innerHTML = getLocalizedText(
"update.checking");
952 reqV.open(
"GET", versionURL, true);
953 reqV.setRequestHeader(
"If-Modified-Since",
"Sat, 1 Jan 2000 00:00:00 GMT" ); // disable caching
957 function checkForUpdateCallback()
959 if (reqV.readyState ==
4) {
960 if (reqV.status ==
200) {
961 // little overhead here, one could use also string for version info
962 var resultXml = reqV.responseText;
964 var div = document.getElementById(
"tmp");
965 div.innerHTML = resultXml;
966 var newVersion = div.getElementsByTagName('version')[
0].innerHTML;
967 var newVersionURL = div.getElementsByTagName('url')[
0].innerHTML;
969 if (version != newVersion) {
970 document.getElementById(
"updateDiv").innerHTML = getLocalizedText(
"update.download").replace(/%
1/, newVersion).replace(/%
2/, newVersionURL);
973 document.getElementById(
"updateDiv").innerHTML = getLocalizedText(
"update.nonewversion");
978 document.getElementById(
"updateDiv").innerHTML = getLocalizedText(
"update.error") + reqV.status +
" " + reqV.responseText;
985 document.getElementById(
"homescreenView").style.display =
"none";
986 document.getElementById(
"fullscreenView").style.display =
"none";
987 document.getElementById(
"aboutView").style.display =
"none";
988 document.getElementById(
"settingsView").style.display =
"none";
989 document.getElementById(
"updateView").style.display =
"none";
993 <style type=
"text/css">
994 table { margin:
0px; padding:
0px; border-spacing:
0px; }
995 td { padding:
0px
5px
0px
0px; white-space:nowrap; overflow:hidden; }
996 hr { color:#ffffff; background-color:#ffffff; height:
1px; text-align:left; border-style:none; }
997 .settingsInfo { display:none; font-style:italic; }
998 .title { font-weight:bold; font-size:
14pt; }
999 .textInput { width:
90%; }
1000 .credits { margin-left:
40px; text-indent: -
20px; margin-bottom:
0px; }
1001 #homescreenView { width:
315px; height:
91px; overflow:hidden; }
1002 #calendarList { position:absolute; left:
10px; top:
4px; width:
295px; height:
75px; overflow:hidden; }
1003 #name { text-align:center; }
1004 #appicon { display: block; margin-left: auto; margin-right: auto; margin-top:
10px; }
1005 #smallappicon { width:
22px; height:
22px; margin-right:
10px; float:left; }
1010 <body id=
"body" class=
"background">
1011 <div id=
"homescreenView">
1012 <div id=
"calendarList"></div>
1014 <div id=
"fullscreenView" style=
"display:none;">
1015 <img src=
"Icon.png" id=
"smallappicon">
1016 <h1 class=
"title">Coming Next
</h1>
1018 <div id=
"fullscreenCalendarList">loading...
</div>
1020 <div id=
"settingsView" style=
"display:none">
1021 <img src=
"Icon.png" id=
"smallappicon">
1022 <h1 class=
"title">Settings
</h1>
1024 <div id=
"settingsList"></div>
1026 <div id=
"aboutView" style=
"display:none">
1027 <img src=
"Icon.png" id=
"appicon">
1028 <h1 id=
"name">Coming Next
</h1>
1030 <p>Created by Dr. Cochambre and Michael Prager.
</p>
1031 <p>Contributions:
</p>
1032 <p class=
"credits">Paul Moore (bug fixes, new features and code cleanup)
</p>
1033 <p class=
"credits">Manfred Hanselmann (DST support)
</p>
1034 <p class=
"credits">Christophe Milsent (translation support & french translation
</p>
1035 <p>This software is open source and licensed under the GPLv3.
</p>
1036 <p>Visit sourceforge.net/projects/comingnext for free updates.
</p>
1039 <div id=
"updateView" style=
"display:none">
1040 <img src=
"Icon.png" id=
"smallappicon">
1041 <h1 class=
"title">Check for update
</h1>
1043 <div id=
"currentVersion">Coming Next ??
</div>
1044 <div id=
"updateDiv"></div>
1045 <div id=
"tmp" style=
"display:none;"></div>