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 backgroundImageLocation: { Type: 'Enum', Default: 'internal', Value: 'internal', ValidValues: ['internal', 'external']},
31 showCombinedDateTime: { Type: 'Bool', Default: false, Value: false,},
32 showLocation: { Type: 'Bool', Default: true, Value: true,},
33 showTodayAsText: { Type: 'Bool', Default: true, Value: true,},
34 todayText: { Type: 'String', Default: getLocalizedText('settings.default.todayText'), Value: getLocalizedText('settings.default.todayText'),},
35 tomorrowText: { Type: 'String', Default: getLocalizedText('settings.default.tomorrowText'), Value: getLocalizedText('settings.default.tomorrowText'),},
36 showNowAsText: { Type: 'Bool', Default: true, Value: true,},
37 nowText: { Type: 'String', Default: getLocalizedText('settings.default.nowText'), Value: getLocalizedText('settings.default.nowText'),},
38 dateSeparator: { Type: 'String', Default: getLocalizedText('settings.default.dateSeparator'), Value: getLocalizedText('settings.default.dateSeparator'),},
39 dateFormat: { Type: 'Enum', Default: 'auto', Value: 'auto', ValidValues: ['auto', 'DDMM', 'MMDD'],},
40 weekDayLength: { Type: 'Int', Default:
2, Value:
2,},
41 updateDataInterval: { Type: 'Int', Default:
5, Value:
5,},
42 calendarApp: { Type: 'UID', Default:
0x10005901, Value:
0x10005901,},
43 eventsPerWidget: { Type: 'Int', Default:
4, Value:
4,},
44 showNothingText: { Type: 'Bool', Default: true, Value: true,},
45 nothingText: { Type: 'String', Default: getLocalizedText('settings.default.nothingText'), Value: getLocalizedText('settings.default.nothingText'),},
46 enableDaylightSaving: { Type: 'Bool', Default: true, Value: true,},
47 hideWidgetOnCalendarOpen: { Type: 'Bool', Default: false, Value: false,},
48 cssStyle_background: { Type: 'String', Default: 'color:#ffffff; background-color:#
000000', Value: 'color:#ffffff; background-color:#
000000',},
49 cssStyle_backgroundFullscreen: { Type: 'String', Default: 'color:#ffffff; background-color:#
000000', Value: 'color:#ffffff; background-color:#
000000',},
50 cssStyle_weekDay: { Type: 'String', Default: '', Value: '',},
51 cssStyle_date: { Type: 'String', Default: '', Value: '',},
52 cssStyle_today: { Type: 'String', Default: 'color:#ff0000', Value: 'color:#ff0000',},
53 cssStyle_tomorrow: { Type: 'String', Default: 'color:#
0000ff', Value: 'color:#
0000ff',},
54 cssStyle_time: { Type: 'String', Default: '', Value: '',},
55 cssStyle_now: { Type: 'String', Default: 'color:#ff00ff', Value: 'color:#ff00ff',},
56 cssStyle_description: { Type: 'String', Default: '', Value: '',},
57 cssStyle_icon: { Type: 'String', Default: 'width:
15px; height:
15px', Value: 'width:
15px; height:
15px',},
62 //-------------------------------------------------------
63 // Nothing of interest from here on...
64 //-------------------------------------------------------
65 var panelNum =
0; // use
1 for second panel
67 var versionURL =
"http://comingnext.sourceforge.net/version.xml";
68 var calendarService = null;
69 var cacheEntriesHtml = [];
70 var months_translated = [];
73 var mode =
0; //
0 = homescreen,
1 = fullscreen,
2 = settings,
3 = about,
4 = check for update
76 // vars for daylight saving time
77 var daylightsavingWinter =
0;
78 var daylightsavingSummer =
0;
79 var summertime = false;
82 window.onresize = updateScreen;
83 window.onshow = updateScreen;
85 function isLeapYear( year ) {
86 if (( year %
4 ==
0 && year %
100 !=
0 ) || year %
400 ==
0 )
92 function calcLeapYear(year, days)
100 function subToSunday(myDate, year, days, prevMonthDays)
102 for (i = myDate.getDay(); i
> 0 ;i--)
104 days -= prevMonthDays;
105 days = isLeapYear(year) ? --days : days;
109 function calcDaylightSaving()
111 var thisYearS = new Date(now.getFullYear(),
3,
0,
0,
0,
0 );
112 var thisYearW = new Date(now.getFullYear(),
10,
0,
0,
0,
0 );
113 var nextYearS = new Date(now.getFullYear() +
1,
3,
0,
0,
0,
0 );
114 var nextYearW = new Date(now.getFullYear() +
1,
10,
0,
0,
0,
0 );
118 thisYearSDays = nextYearSDays =
90;
119 thisYearWDays = nextYearWDays =
304;
121 thisYearSDays = calcLeapYear(now.getFullYear(), thisYearSDays);
122 thisYearWDays = calcLeapYear(now.getFullYear(), thisYearWDays);
123 nextYearSDays = calcLeapYear(now.getFullYear() +
1, nextYearSDays);
124 nextYearWDays = calcLeapYear(now.getFullYear() +
1, nextYearWDays);
126 thisYearSDays = subToSunday(thisYearS, now.getFullYear(), thisYearSDays,
59);
127 thisYearWDays = subToSunday(thisYearW, now.getFullYear(), thisYearWDays,
273);
128 nextYearSDays = subToSunday(nextYearS, now.getFullYear() +
1, nextYearSDays,
59);
129 nextYearWDays = subToSunday(nextYearW, now.getFullYear() +
1, nextYearWDays,
273);
131 daylightsavingSummer = new Date (now.getFullYear(),
03-
1, thisYearSDays,
2,
0,
0);
132 daylightsavingWinter = new Date (now.getFullYear(),
10-
1, thisYearWDays,
2,
0,
0);
133 if (daylightsavingSummer < now) {
134 daylightsavingSummer = new Date (now.getFullYear()+
1,
03-
1, nextYearSDays,
2,
0,
0);
137 if (daylightsavingWinter < now) {
138 daylightsavingWinter = new Date (now.getFullYear()+
1,
10-
1, nextYearWDays,
2,
0,
0);
141 if (summer && !winter)
147 function error(message)
149 console.info('Error: ' + message);
150 document.getElementById(
"calendarList").innerHTML = 'Error: ' + message;
153 function isToday(date)
155 if (date.getDate() == now.getDate() && date.getMonth() == now.getMonth())
160 function isTomorrow(date)
162 if ((date.getDate() == now.getDate() +
1 && date.getMonth() == now.getMonth()) ||
163 (date.getDate() ==
0 && date.getMonth() == now.getMonth() +
1) ||
164 (date.getDate() ==
0 && date.getMonth() == now.getMonth() +
1 && date.getYear() == now.getYear() +
1))
169 function collectLocales()
171 var tmpyear = ((panelNum ==
0) ?
2000 :
2001);
174 if (months_translated.length
> 0)
176 for (month =
0; month <
12; month++) {
177 var startDate = new Date(tmpyear, month,
15);
179 var item = new Object();
180 item.Type =
"DayEvent";
181 item.StartTime = startDate;
182 item.Summary =
"__temp" + month;
184 var criteria = new Object();
185 criteria.Type =
"CalendarEntry";
186 criteria.Item = item;
189 var result = calendarService.IDataSource.Add(criteria);
190 if (result.ErrorCode)
191 error(result.ErrorMessage);
193 error(
"collectLocales: " + e + ', line ' + e.line);
197 var startTime = new Date(tmpyear,
0,
1);
198 var endTime = new Date(tmpyear,
11,
31);
199 var listFiltering = {
200 Type:'CalendarEntry',
202 StartRange: startTime,
204 SearchText: '__temp',
208 var result = calendarService.IDataSource.GetList(listFiltering);
209 if (result.ErrorCode) {
210 error(result.ErrorMessage);
213 var list = result.ReturnValue;
215 error(e + ', line ' + e.line);
218 var ids = new Array();
224 while (list && (entry = list.getNext()) != undefined) {
225 dateArr = entry.StartTime.replace(/,/g,'').replace(/\./g,':').replace(/ /g,' ').split(' ');
226 var day = dateArr[
1];
227 var month = dateArr[
2];
228 var year = dateArr[
3];
230 // make sure month is set properly
231 if (isNaN(parseInt(day))) {
235 } else if (isNaN(parseInt(year))) {
241 console.info(entry.StartTime + ' -
> ' + month + ' ' + counter);
242 ids[counter] = entry.id;
243 months_translated[month] = counter +
1;
247 error(e + ', line ' + e.line);
252 var criteria = new Object();
253 criteria.Type =
"CalendarEntry";
258 var result = calendarService.IDataSource.Delete(criteria);
259 if (result.ErrorCode)
260 error(result.ErrorMessage);
262 error('deleting temp calendar entries:' + e + ', line ' + e.line);
267 function requestNotification()
269 var criteria = new Object();
270 criteria.Type =
"CalendarEntry";
273 var result = calendarService.IDataSource.RequestNotification(criteria, callback);
274 if (result.ErrorCode)
275 error('loading Calendar items list');
277 error(
"requestNotification: " + e + ', line ' + e.line);
281 function callback(transId, eventCode, result)
286 function parseDate(dateString)
289 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:
290 Wednesday,
26 August,
2009 24:
00:
00
291 Wednesday,
26 August,
2009 12:
00:
00 am
292 Wednesday, August
26,
2009 12:
00:
00 am
293 Wednesday,
2009 August,
26 12:
00:
00 am
294 Wednesday,
2009 August,
28 8.00.00 pm
295 Wednesday,
2009 August,
28 08:
00:
00 PM
298 if (dateString ==
"" || dateString == null)
300 var dateArr = dateString.replace(/,/g,'').replace(/\./g,':').replace(/ /g,' ').split(' ');
301 if (dateArr.length !=
5 && dateArr.length !=
6)
305 var weekDay = dateArr[
0];
306 var day = dateArr[
1];
307 var month = dateArr[
2];
308 var year = dateArr[
3];
309 // make sure month is set properly
310 if (isNaN(parseInt(day))) {
314 } else if (isNaN(parseInt(year))) {
319 // make sure day and year are set properly
320 if (Number(day)
> Number(year)) {
325 month = months_translated[month];
328 var timeArr = dateArr[
4].split(':');
329 if (timeArr.length !=
3)
331 var hours = Number(timeArr[
0]);
332 var minutes = Number(timeArr[
1]);
333 var seconds = Number(timeArr[
2]);
334 if (dateArr.length ==
6 && dateArr[
5].toLowerCase() == 'pm' && hours <
12)
336 if (dateArr.length ==
6 && dateArr[
5].toLowerCase() == 'am' && hours ==
12)
339 console.info('year=' + year + ' month=' + month + ' day=' + day + ' hours=' + hours + ' minutes=' + minutes+ ' seconds=' + seconds);
341 // take care of daylight saving time
342 if (config['enableDaylightSaving'].Value) {
343 var date = new Date(year, month -
1, day, hours, minutes, seconds);
344 if (summertime && date
> daylightsavingWinter && date < daylightsavingSummer)
346 else if (!summertime && date
> daylightsavingSummer && date < daylightsavingWinter)
350 return new Date(year, month -
1, day, hours, minutes, seconds);
353 // 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"
354 function formatDate(date, format)
356 var day = date.getDate().toString();
357 var month = (date.getMonth() +
1).toString();
358 while (day.length <
2) { day = '
0' + day; }
359 while (month.length <
2) { month = '
0' + month; }
361 if (config['showTodayAsText'].Value && isToday(date))
362 return '
<span class=
"today">' + config['todayText'].Value + '
</span>';
363 if (config['showTodayAsText'].Value && isTomorrow(date))
364 return '
<span class=
"tomorrow">' + config['tomorrowText'].Value + '
</span>';
366 var dateArr = format.replace(/,/g,'').replace(/\./g,':').replace(/ /g,' ').split(' ');
367 if (dateArr.length !=
5 && dateArr.length !=
6) {
368 // we don't know how to format this
369 if (config['dateFormat'].Value == 'auto' || config['dateFormat'].Value == 'DDMM')
370 return day + config['dateSeparator'].Value + month;
372 return month + config['dateSeparator'].Value + day;
376 if (config['dateFormat'].Value == 'MMDD')
378 else if (config['dateFormat'].Value == 'DDMM')
381 // config['dateFormat'].Value == 'auto', try to detect system setting
383 var day_ = dateArr[
1];
384 var month_ = dateArr[
2];
385 var year_ = dateArr[
3];
386 // make sure month is set properly
387 if (isNaN(parseInt(day_))) {
392 } else if (isNaN(parseInt(year_))) {
398 // make sure day and year are set properly
399 if (Number(day_)
> Number(year_))
404 return day + config['dateSeparator'].Value + month;
406 return month + config['dateSeparator'].Value + day;
409 function formatTime(date)
411 // date is a Date() object
412 date.setSeconds(
0); // we don't care about seconds
413 var time = date.toLocaleTimeString().replace(/[\.:]
00/, ''); // remove seconds from string
414 if (time.replace(/\./, ':').split(':')[
0].length <
2)
416 if (config['showNowAsText'].Value && date.getTime() == now.getTime())
417 time = '
<span class=
"now">' + config['nowText'].Value + '
</span>';
421 function updateData()
423 console.info('updateData()');
424 calcDaylightSaving();
426 // meetings have time
427 // 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
429 var meetingListFiltering = {
430 Type:'CalendarEntry',
432 StartRange: (new Date(now.getFullYear(), now.getMonth(), now.getDate(),
0,
0,
0)),
433 EndRange: (new Date(now.getFullYear(), now.getMonth() + config['monthRange'].Value, now.getDate(),
0,
0,
0))
436 var meetingResult = calendarService.IDataSource.GetList(meetingListFiltering);
437 if (meetingResult.ErrorCode !=
0)
438 throw(
"Error fetching calendar data: " + meetingResult.ErrorCode + ': ' + meetingResult.ErrorMessage);
439 var meetingList = meetingResult.ReturnValue;
441 // todos don't, they start on
00:
00 hrs., but should be visible anyway
442 // this will generate a list of passed todos. We have to check if they have been marked as
"done" yet
443 if (config['includeTodos'].Value) {
444 var todayTodoListFiltering = {
445 Type:'CalendarEntry',
448 StartRange: (new Date(now.getFullYear() -
1, now.getMonth(), now.getDate(),
0,
0,
0)),
449 EndRange: (new Date(now.getFullYear(), now.getMonth(), now.getDate(),
0,
0,
1))
452 var todayTodoResult = calendarService.IDataSource.GetList(todayTodoListFiltering);
453 var todayTodoList = todayTodoResult.ReturnValue;
454 var entryLists = [todayTodoList, meetingList];
456 var entryLists = [meetingList];
459 error('loading Calendar items list:' + e + ', line ' + e.line);
468 var entriesHtml = '
<table>';
472 max = ((panelNum ==
0) ? config['eventsPerWidget'].Value :
2 * config['eventsPerWidget'].Value);
474 max =
30; // we can display a lot more events in fullscreen mode
476 // the first outer loop iteration is for passed ToDos, the second loop is for all upcomming events (may also include ToDos)
477 for (var i=
0; counter < max && i < entryLists.length; i++) {
478 while (counter < max && (entry = entryLists[i].getNext()) != undefined) {
481 // output event info for debugging
483 'event: Id=' + entry.id +
484 ',Type=' + entry.Type +
485 ',Summary=' + entry.Summary +
486 ',Location=' + entry.Location +
487 ',Status=' + entry.Status +
488 ',StartTime=' + entry.StartTime +
489 ',EndTime=' + entry.EndTime +
490 ',InstanceStartTime=' + entry.InstanceStartTime +
491 ',InstanceEndTime=' + entry.InstanceEndTime
494 // we don't want ToDos when includeTodos == false or when they are completed
495 if (entry.Type == 'ToDo' && (entry.Status ==
"TodoCompleted" || !config['includeTodos'].Value)) {
496 console.info('skipping ' + entry.id );
501 // make sure that we don't include an event twice (useful for ToDos that might come up twice)
502 if (eventIds[entry.id] ==
1 && entry.Type == 'ToDo') {
503 console.info('skipped (already included) ' + entry.id);
507 eventIds[entry.id] =
1;
509 // summary can be undefined!
510 var Summary = ((entry.Summary == null) ? '' : entry.Summary);
511 if (entry.Type == 'Meeting' && entry.Location != '' && config['showLocation'].Value)
512 Summary += ', ' + entry.Location;
514 // fix by yves: determine start and end dates/times
515 entryStartTime = ((entry.InstanceStartTime == null) ? entry.StartTime : entry.InstanceStartTime);
516 entryEndTime = ((entry.InstanceEndTime == null) ? entry.EndTime : entry.InstanceEndTime);
518 // there can be ToDos that have no date at all!
519 if (entry.Type == 'ToDo' && entry.EndTime == null)
520 entryDate =
""; // this will cause parseDate(entryDate) to return null;
522 entryDate = ((entry.Type == 'ToDo') ? entryEndTime : entryStartTime); // ToDo's use their EndTime, the rest use StartTime
524 // Convert date/time string to Date object
525 var date = parseDate(entryDate);
526 console.info('date: ' + date);
527 var endDate = ((entryEndTime == null) ? null : parseDate(entryEndTime));
528 console.info('endDate: ' + endDate);
530 // check if meeting event has already passed
531 if (entry.Type == 'Meeting') {
532 var compareTime = ((endDate == null) ? date.getTime() : endDate.getTime());
533 if (now.getTime()
> compareTime) {
534 console.info('skipping Meeting (already passed) ' + entry.id);
536 eventIds[entry.id] =
0;
541 // check if anniversary passed (not sure why they are in the list, the query was only for today - nokia?)
542 if (entry.Type == 'Anniversary') {
543 var tmp = new Date(now.getFullYear(), now.getMonth(), now.getDate(),
0,
0,
0);
544 if (date.getTime() < tmp.getTime()) {
545 console.info('skipping Anniversary (already passed) ' + entry.id);
547 eventIds[entry.id] =
0;
552 // fix DayEvents end time. End times are off by
1 Second. It's possible that the event has already passed
553 if (entry.Type == 'DayEvent' && endDate != null) {
554 endDate.setMinutes(endDate.getMinutes() -
1);
555 console.info('fixing DayEvent endDate: ' + endDate);
556 if (now.getTime()
> endDate.getTime()) {
557 console.info('event already passed ' + entry.id);
559 eventIds[entry.id] =
0;
564 // check if the event is currently taking place
565 if (entryStartTime != null && entryEndTime != null && date != null && endDate != null) {
566 // check if we are between start and endtime
567 if ((date.getTime() < now.getTime()) && (now.getTime() < endDate.getTime())) {
568 date = now; // change appointment date/time to now
569 console.info('event is currently taking place: ' + date);
573 // skip events for the first panel in case this is the second one and we're not in fullscreen mode
574 if (mode ==
0 && panelNum ==
1 && counter < config['eventsPerWidget'].Value +
1) {
575 console.info('skipping (already in first widget) ' + entry.id);
579 // generate html output
580 entriesHtml += '
<tr><td><img class=
"icon" src=
"' + entry.Type + '.png" /></td>';
582 // some languages have very strange locale date formats, can't parse all those. Also some todos don't have dates at all.
583 entriesHtml += '
<td colspan=
"4"><span class=
"date">' + entryDate + '
</span> ';
585 var weekDay = date.toLocaleDateString().substr(
0,config['weekDayLength'].Value);
586 var time = formatTime(date);
587 var dateStr = formatDate(date, entryDate);
588 if (entry.Type == 'ToDo' || entry.Type == 'Anniversary' || entry.Type == 'DayEvent' || entry.Type == 'Reminder') {
589 if ((isToday(date) || isTomorrow(date)) && config['showTodayAsText'].Value) // show weekday if the date string is not text. looks odd otherwise
590 entriesHtml += '
<td colspan=
"4" width=
"1px"><span class=
"date">' + dateStr + '
</span> ';
592 entriesHtml += '
<td class=
"weekDay" width=
"1px">' + weekDay + '
</td><td width=
"1px" class=
"date">' + dateStr + '
</td><td colspan=
"2">';
593 } else if (entry.Type == 'Meeting') {
594 if (config['showCombinedDateTime'].Value) {
596 entriesHtml += '
<td width=
"1px" colspan=
"4"><span class=
"today">' + time + '
</span> ';
597 else if (isTomorrow(date))
598 entriesHtml += '
<td width=
"1px" colspan=
"4"><span class=
"tomorrow">' + dateStr + '
</span> <span class=
"time">' + time + '
</span> ';
600 entriesHtml += '
<td width=
"1px" class=
"weekDay">' + weekDay + '
</td><td width=
"1px" class=
"date">' + dateStr + '
</td><td colspan=
"2">';
602 if ((isToday(date) || isTomorrow(date)) && config['showTodayAsText'].Value)
603 entriesHtml += '
<td colspan=
"4" width=
"1px"><span class=
"today">' + dateStr + '
</span> <span class=
"time">' + time + '
</span> ';
605 entriesHtml += '
<td width=
"1px" class=
"weekDay">' + weekDay + '
</td><td width=
"1px" class=
"date">' + dateStr + '
</td><td width=
"1px" class=
"time">' + time + '
</td><td>';
609 entriesHtml += '
<span class=
"description">' + Summary + '
</span></td></tr>';
612 entriesHtml += '
</table>';
613 if (config['showNothingText'].Value && entriesHtml == '
<table></table>') {
614 var text = config['nothingText'].Value.replace(/%d/, config['monthRange'].Value);
615 entriesHtml = '
<div style=
"width:295px; height:75px; text-align:center; line-height:75px; overflow:visible;">' + text + '
</div>';
617 if (cacheEntriesHtml != entriesHtml) {
619 document.getElementById('calendarList').innerHTML = entriesHtml;
621 document.getElementById('fullscreenCalendarList').innerHTML = entriesHtml;
622 cacheEntriesHtml = entriesHtml;
625 error('displaying list:' + e + ', line ' + e.line);
630 function updateScreen()
632 // check if opening fullscreen
633 if( window.innerHeight
> 91 && mode ==
0) {
635 cacheEntriesHtml = '';
636 document.getElementById('body').style.backgroundImage =
"";
639 else if (window.innerHeight <=
91 && mode !=
0) {
641 cacheEntriesHtml = '';
651 function launchCalendar()
654 widget.openApplication(config['calendarApp'].Value,
"");
655 if (config['hideWidgetOnCalendarOpen'].Value)
658 error('starting Calendar App');
665 console.info('New widget instance starting up...');
668 // call calendar service
669 if (device !=
"undefined")
670 calendarService = device.getServiceObject(
"Service.Calendar",
"IDataSource");
672 throw('device object does not exist');
674 error('loading Calendar service: ' + e + ', line ' + e.line);
682 requestNotification();
683 window.setInterval('updateData()',
1000 *
60 * config['updateDataInterval'].Value);
688 if (config['useBackgroundImage'].Value)
689 // check for screen rotation every
1 secs
690 window.setInterval('updateScreen()',
1000 *
1);
693 function createMenu()
695 window.menu.setLeftSoftkeyLabel(
"",null);
696 window.menu.setRightSoftkeyLabel(
"",null);
698 var menuSettings = new MenuItem(getLocalizedText('menu.settings'), id++);
699 var menuCallApp = new MenuItem(getLocalizedText('menu.openCalendarApp'), id++);
700 var menuUpdate = new MenuItem(getLocalizedText('menu.update'), id++);
701 var menuAbout = new MenuItem(getLocalizedText('menu.about'), id++);
702 menuSettings.onSelect = showSettings;
703 menuAbout.onSelect = showAbout;
704 menuCallApp.onSelect = launchCalendar;
705 menuUpdate.onSelect = showUpdate;
707 window.menu.append(menuCallApp);
708 window.menu.append(menuSettings);
709 window.menu.append(menuUpdate);
710 window.menu.append(menuAbout);
713 function showSettings()
717 document.getElementById(
"settingsView").style.display =
"block";
718 document.onclick = null;
720 window.menu.setLeftSoftkeyLabel(getLocalizedText('settings.save'), function()
722 for (var key in config) {
723 if (config[key].Type == 'String')
724 config[key].Value = document.forms[
0].elements[
"settings." + key].value;
725 else if (config[key].Type == 'Int') {
726 config[key].Value = parseInt(document.forms[
0].elements[
"settings." + key].value);
727 if (config[key].Value <
0)
728 config[key].Value = config[key].Default;
730 else if (config[key].Type == 'Bool')
731 config[key].Value = document.forms[
0].elements[
"settings." + key].checked;
732 else if (config[key].Type == 'UID')
733 config[key].Value = parseInt(document.forms[
0].elements[
"settings." + key].value);
734 else if (config[key].Type == 'Enum') {
735 config[key].Value = document.forms[
0].elements[
"settings." + key].value;
736 if (config[key].ValidValues.indexOf(config[key].Value) == -
1)
737 config[key].Value = config[key].Default;
748 window.menu.setRightSoftkeyLabel(getLocalizedText('settings.cancel'), function()
754 var settingsHtml = '
<form>';
755 for (var key in config) {
756 if (config[key].Type == 'String')
757 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 />';
758 else if (config[key].Type == 'Int')
759 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 />';
760 else if (config[key].Type == 'Bool')
761 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 />';
762 else if (config[key].Type == 'UID')
763 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 />';
764 else if (config[key].Type == 'Enum') {
765 settingsHtml += '
<table><tr><td>' + getLocalizedText('settings.name.' + key) + '
<br /><select name=
"settings.' + key + '" size=
"1">';
766 for(var i =
0; i < config[key].ValidValues.length; i++)
767 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>';
768 settingsHtml += '
</select></div></td>' + printHintBox(getLocalizedText('settings.info.' + key)) + '
<hr />';
771 settingsHtml += '
<input name=
"reset" type=
"button" value=
"' + getLocalizedText('settings.restoreDefaults') + '" onclick=
"javascript:restoreDefaultSettings();showSettings();" />';
772 settingsHtml += '
</form>';
773 document.getElementById(
"settingsList").innerHTML = settingsHtml;
776 function changeCssClass(classname, properties)
778 for(var i =
0; i < document.styleSheets[
0]['cssRules'].length; i++)
780 if (document.styleSheets[
0]['cssRules'][i].selectorText == classname) {
781 document.styleSheets[
0].deleteRule(i);
782 document.styleSheets[
0].insertRule(classname + ' { ' + properties + ' }', document.styleSheets[
0]['cssRules'].length);
788 function updateCssClasses()
790 for(var key in config) {
791 changeCssClass(getLocalizedText('settings.name.' + key), config[key].Value);
795 function restoreDefaultSettings()
797 for (var key in config)
798 config[key].Value = config[key].Default;
801 function loadSettings()
803 for (var key in config) {
804 if (widget.preferenceForKey(key)) {
805 if (config[key].Type == 'Int')
806 config[key].Value = Number(widget.preferenceForKey(key));
807 else if (config[key].Type == 'String')
808 config[key].Value = widget.preferenceForKey(key);
809 else if (config[key].Type == 'Bool')
810 config[key].Value = (widget.preferenceForKey(key) == 'true')
811 else if (config[key].Type == 'Enum')
812 config[key].Value = widget.preferenceForKey(key);
813 else if (config[key].Type == 'UID')
814 config[key].Value = Number(widget.preferenceForKey(key));
817 config[key].Value = config[key].Default;
818 console.info('Settings: ' + key + '=\'' + config[key].Value + '\'');
822 function saveSettings()
824 for (var key in config) {
825 if (config[key].Type == 'Int')
826 widget.setPreferenceForKey(config[key].Value.toString(), key);
827 else if (config[key].Type == 'String')
828 widget.setPreferenceForKey(config[key].Value, key);
829 else if (config[key].Type == 'Bool')
830 widget.setPreferenceForKey(config[key].Value ? 'true' : 'false', key);
831 else if (config[key].Type == 'Enum')
832 widget.setPreferenceForKey(config[key].Value, key);
833 else if (config[key].Type == 'UID')
834 widget.setPreferenceForKey(config[key].Value.toString(), key);
838 function toggleVisibility(elementId)
840 if (document.getElementById(elementId).style.display ==
"none")
841 document.getElementById(elementId).style.display =
"block";
843 document.getElementById(elementId).style.display =
"none";
847 function printHintBox(text)
850 return '
<td width=
"1%" align=
"right" onclick=
"javascript:toggleVisibility(\'info' + uniqueId + '\')">' + getLocalizedText('settings.help') + '
</td></tr></table>'+
851 '
<div class=
"settingsInfo" id=
"info' + uniqueId + '">' + text + '
</div>';
858 document.getElementById(
"aboutView").style.display =
"block";
859 document.onclick = null;
861 window.menu.setLeftSoftkeyLabel(
" ", function(){});
862 window.menu.setRightSoftkeyLabel(getLocalizedText('softkey.back'), function()
868 //document.getElementById(
"aboutView").innerHTML = 'aboutView';
869 document.getElementById(
"name").innerHTML =
"Coming Next " + version;
872 function updateFullscreen()
876 function showFullscreen()
879 document.getElementById(
"fullscreenView").style.display =
"block";
880 document.getElementById('body').className =
"backgroundFullscreen";
881 document.onclick = launchCalendar;
886 function getBackgroundImage()
889 if (config['backgroundImageLocation'].Value == config['backgroundImageLocation'].ValidValues[
0]) // internal
890 bgImage = 'background_' + orientation + '.png';
892 bgImage = 'C:/Data/background_' + panelNum + '_' + orientation + '.png';
896 function updateHomescreen()
898 if (config['useBackgroundImage'].Value) {
899 // check for screen rotation
900 if (orientation != 'portrait' && screen.width ==
360 && screen.height ==
640) {
901 window.widget.prepareForTransition(
"fade");
902 orientation = 'portrait';
903 document.getElementById('body').style.backgroundImage = 'url(' + getBackgroundImage() + ')';
904 document.getElementById('body').style.backgroundColor = 'none';
905 window.widget.performTransition();
906 } else if (orientation != 'landscape' && screen.width ==
640 && screen.height ==
360) {
907 window.widget.prepareForTransition(
"fade");
908 orientation = 'landscape';
909 document.getElementById('body').style.backgroundImage = 'url(' + getBackgroundImage() + ')';
910 document.getElementById('body').style.backgroundColor = 'none';
911 window.widget.performTransition();
913 else if (document.getElementById('body').style.backgroundImage ==
"")
915 document.getElementById('body').style.backgroundImage = 'url(' + getBackgroundImage() + ')';
920 function showHomescreen()
923 document.getElementById(
"homescreenView").style.display =
"block";
924 document.getElementById('body').className =
"background";
925 document.onclick = null;
929 function getLocalizedText(p_Txt)
931 if (localizedText[p_Txt])
932 return localizedText[p_Txt];
934 return 'ERROR: missing translation for ' + p_Txt;
937 function showUpdate()
941 document.getElementById(
"updateView").style.display =
"block";
942 document.onclick = null;
944 window.menu.setLeftSoftkeyLabel(getLocalizedText('update.checknow'), function(){
947 window.menu.setRightSoftkeyLabel(getLocalizedText('softkey.back'), function()
953 document.getElementById(
"currentVersion").innerHTML = getLocalizedText(
"update.current") + version;
957 function checkForUpdate()
959 // asynch XHR to server url
960 reqV = new XMLHttpRequest();
961 reqV.onreadystatechange = checkForUpdateCallback;
962 document.getElementById(
"updateDiv").innerHTML = getLocalizedText(
"update.checking");
963 reqV.open(
"GET", versionURL, true);
964 reqV.setRequestHeader(
"If-Modified-Since",
"Sat, 1 Jan 2000 00:00:00 GMT" ); // disable caching
968 function checkForUpdateCallback()
970 if (reqV.readyState ==
4) {
971 if (reqV.status ==
200) {
972 var resultXml = reqV.responseText;
974 var div = document.getElementById(
"tmp");
975 div.innerHTML = resultXml;
976 var newVersion = div.getElementsByTagName('version')[
0].innerHTML;
977 var newVersionURL = div.getElementsByTagName('url')[
0].innerHTML;
979 if (version != newVersion) {
980 document.getElementById(
"updateDiv").innerHTML = getLocalizedText(
"update.download").replace(/%
1/, newVersion).replace(/%
2/, newVersionURL);
983 document.getElementById(
"updateDiv").innerHTML = getLocalizedText(
"update.nonewversion");
988 document.getElementById(
"updateDiv").innerHTML = getLocalizedText(
"update.error") + reqV.status +
" " + reqV.responseText;
995 document.getElementById(
"homescreenView").style.display =
"none";
996 document.getElementById(
"fullscreenView").style.display =
"none";
997 document.getElementById(
"aboutView").style.display =
"none";
998 document.getElementById(
"settingsView").style.display =
"none";
999 document.getElementById(
"updateView").style.display =
"none";
1003 <style type=
"text/css">
1004 table { margin:
0px; padding:
0px; border-spacing:
0px; }
1005 td { padding:
0px
5px
0px
0px; white-space:nowrap; overflow:hidden; }
1006 hr { color:#ffffff; background-color:#ffffff; height:
1px; text-align:left; border-style:none; }
1007 .settingsInfo { display:none; font-style:italic; }
1008 .title { font-weight:bold; font-size:
14pt; }
1009 .textInput { width:
90%; }
1010 .credits { margin-left:
40px; text-indent: -
20px; margin-bottom:
0px; }
1011 #homescreenView { width:
315px; height:
91px; overflow:hidden; }
1012 #calendarList { position:absolute; left:
10px; top:
4px; width:
295px; height:
75px; overflow:hidden; }
1013 #name { text-align:center; }
1014 #appicon { display: block; margin-left: auto; margin-right: auto; margin-top:
10px; }
1015 #smallappicon { width:
22px; height:
22px; margin-right:
10px; float:left; }
1020 <body id=
"body" class=
"background">
1021 <div id=
"homescreenView">
1022 <div id=
"calendarList"></div>
1024 <div id=
"fullscreenView" style=
"display:none;">
1025 <img src=
"Icon.png" id=
"smallappicon">
1026 <h1 class=
"title">Coming Next
</h1>
1028 <div id=
"fullscreenCalendarList">loading...
</div>
1030 <div id=
"settingsView" style=
"display:none">
1031 <img src=
"Icon.png" id=
"smallappicon">
1032 <h1 class=
"title">Settings
</h1>
1034 <div id=
"settingsList"></div>
1036 <div id=
"aboutView" style=
"display:none">
1037 <img src=
"Icon.png" id=
"appicon">
1038 <h1 id=
"name">Coming Next
</h1>
1040 <p>Created by Dr. Cochambre and Michael Prager.
</p>
1041 <p>Contributions:
</p>
1042 <p class=
"credits">Paul Moore (bug fixes, new features and code cleanup)
</p>
1043 <p class=
"credits">Manfred Hanselmann (DST support)
</p>
1044 <p class=
"credits">Christophe Milsent (translation support & french translation
</p>
1045 <p>This software is open source and licensed under the GPLv3.
</p>
1046 <p>Visit sourceforge.net/projects/comingnext for free updates.
</p>
1049 <div id=
"updateView" style=
"display:none">
1050 <img src=
"Icon.png" id=
"smallappicon">
1051 <h1 class=
"title">Check for update
</h1>
1053 <div id=
"currentVersion">Coming Next ??
</div>
1054 <div id=
"updateDiv"></div>
1055 <div id=
"tmp" style=
"display:none;"></div>