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 areDatesEqual(date1, date2)
155 return (date1.getFullYear() == date2.getFullYear() &&
156 date1.getMonth() == date2.getMonth() &&
157 date1.getDate() == date2.getDate());
160 function isTomorrow(date)
162 // tommorow = now +
1 day
163 // ToDo: some days can be shorter as
24 hours(daylight saving change day)
164 return areDatesEqual(date, new Date (now.getTime() +
24*
60*
60*
1000));
167 function isToday(date)
169 return areDatesEqual(date, now);
172 function collectLocales()
174 var tmpyear = ((panelNum ==
0) ?
2000 :
2001);
177 if (months_translated.length
> 0)
179 for (month =
0; month <
12; month++) {
180 var startDate = new Date(tmpyear, month,
15);
182 var item = new Object();
183 item.Type =
"DayEvent";
184 item.StartTime = startDate;
185 item.Summary =
"__temp" + month;
187 var criteria = new Object();
188 criteria.Type =
"CalendarEntry";
189 criteria.Item = item;
192 var result = calendarService.IDataSource.Add(criteria);
193 if (result.ErrorCode)
194 error(result.ErrorMessage);
196 error(
"collectLocales: " + e + ', line ' + e.line);
200 var startTime = new Date(tmpyear,
0,
1);
201 var endTime = new Date(tmpyear,
11,
31);
202 var listFiltering = {
203 Type:'CalendarEntry',
205 StartRange: startTime,
207 SearchText: '__temp',
211 var result = calendarService.IDataSource.GetList(listFiltering);
212 if (result.ErrorCode) {
213 error(result.ErrorMessage);
216 var list = result.ReturnValue;
218 error(e + ', line ' + e.line);
221 var ids = new Array();
227 while (list && (entry = list.getNext()) != undefined) {
228 dateArr = entry.StartTime.replace(/,/g,'').replace(/\./g,':').replace(/ /g,' ').split(' ');
229 var day = dateArr[
1];
230 var month = dateArr[
2];
231 var year = dateArr[
3];
233 // make sure month is set properly
234 if (isNaN(parseInt(day))) {
238 } else if (isNaN(parseInt(year))) {
244 console.info(entry.StartTime + ' -
> ' + month + ' ' + counter);
245 ids[counter] = entry.id;
246 months_translated[month] = counter +
1;
250 error(e + ', line ' + e.line);
255 var criteria = new Object();
256 criteria.Type =
"CalendarEntry";
261 var result = calendarService.IDataSource.Delete(criteria);
262 if (result.ErrorCode)
263 error(result.ErrorMessage);
265 error('deleting temp calendar entries:' + e + ', line ' + e.line);
270 function requestNotification()
272 var criteria = new Object();
273 criteria.Type =
"CalendarEntry";
276 var result = calendarService.IDataSource.RequestNotification(criteria, callback);
277 if (result.ErrorCode)
278 error('loading Calendar items list');
280 error(
"requestNotification: " + e + ', line ' + e.line);
284 function callback(transId, eventCode, result)
289 function parseDate(dateString)
292 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:
293 Wednesday,
26 August,
2009 24:
00:
00
294 Wednesday,
26 August,
2009 12:
00:
00 am
295 Wednesday, August
26,
2009 12:
00:
00 am
296 Wednesday,
2009 August,
26 12:
00:
00 am
297 Wednesday,
2009 August,
28 8.00.00 pm
298 Wednesday,
2009 August,
28 08:
00:
00 PM
301 if (dateString ==
"" || dateString == null)
303 var dateArr = dateString.replace(/,/g,'').replace(/\./g,':').replace(/ /g,' ').split(' ');
304 if (dateArr.length !=
5 && dateArr.length !=
6)
308 var weekDay = dateArr[
0];
309 var day = dateArr[
1];
310 var month = dateArr[
2];
311 var year = dateArr[
3];
312 // make sure month is set properly
313 if (isNaN(parseInt(day))) {
317 } else if (isNaN(parseInt(year))) {
322 // make sure day and year are set properly
323 if (Number(day)
> Number(year)) {
328 month = months_translated[month];
331 var timeArr = dateArr[
4].split(':');
332 if (timeArr.length !=
3)
334 var hours = Number(timeArr[
0]);
335 var minutes = Number(timeArr[
1]);
336 var seconds = Number(timeArr[
2]);
337 if (dateArr.length ==
6 && dateArr[
5].toLowerCase() == 'pm' && hours <
12)
339 if (dateArr.length ==
6 && dateArr[
5].toLowerCase() == 'am' && hours ==
12)
342 console.info('year=' + year + ' month=' + month + ' day=' + day + ' hours=' + hours + ' minutes=' + minutes+ ' seconds=' + seconds);
344 // take care of daylight saving time
345 if (config['enableDaylightSaving'].Value) {
346 var date = new Date(year, month -
1, day, hours, minutes, seconds);
347 if (summertime && date
> daylightsavingWinter && date < daylightsavingSummer)
349 else if (!summertime && date
> daylightsavingSummer && date < daylightsavingWinter)
353 return new Date(year, month -
1, day, hours, minutes, seconds);
356 // 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"
357 function formatDate(date, format)
359 var day = date.getDate().toString();
360 var month = (date.getMonth() +
1).toString();
361 while (day.length <
2) { day = '
0' + day; }
362 while (month.length <
2) { month = '
0' + month; }
364 if (config['showTodayAsText'].Value && isToday(date))
365 return '
<span class=
"today">' + config['todayText'].Value + '
</span>';
366 if (config['showTodayAsText'].Value && isTomorrow(date))
367 return '
<span class=
"tomorrow">' + config['tomorrowText'].Value + '
</span>';
369 var dateArr = format.replace(/,/g,'').replace(/\./g,':').replace(/ /g,' ').split(' ');
370 if (dateArr.length !=
5 && dateArr.length !=
6) {
371 // we don't know how to format this
372 if (config['dateFormat'].Value == 'auto' || config['dateFormat'].Value == 'DDMM')
373 return day + config['dateSeparator'].Value + month;
375 return month + config['dateSeparator'].Value + day;
379 if (config['dateFormat'].Value == 'MMDD')
381 else if (config['dateFormat'].Value == 'DDMM')
384 // config['dateFormat'].Value == 'auto', try to detect system setting
386 var day_ = dateArr[
1];
387 var month_ = dateArr[
2];
388 var year_ = dateArr[
3];
389 // make sure month is set properly
390 if (isNaN(parseInt(day_))) {
395 } else if (isNaN(parseInt(year_))) {
401 // make sure day and year are set properly
402 if (Number(day_)
> Number(year_))
407 return day + config['dateSeparator'].Value + month;
409 return month + config['dateSeparator'].Value + day;
412 function formatTime(date)
414 // date is a Date() object
415 date.setSeconds(
0); // we don't care about seconds
416 var time = date.toLocaleTimeString().replace(/[\.:]
00/, ''); // remove seconds from string
417 if (time.replace(/\./, ':').split(':')[
0].length <
2)
419 if (config['showNowAsText'].Value && date.getTime() == now.getTime())
420 time = '
<span class=
"now">' + config['nowText'].Value + '
</span>';
424 function updateData()
426 console.info('updateData()');
427 calcDaylightSaving();
429 // meetings have time
430 // 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
432 var meetingListFiltering = {
433 Type:'CalendarEntry',
435 StartRange: (new Date(now.getFullYear(), now.getMonth(), now.getDate(),
0,
0,
0)),
436 EndRange: (new Date(now.getFullYear(), now.getMonth() + config['monthRange'].Value, now.getDate(),
0,
0,
0))
439 var meetingResult = calendarService.IDataSource.GetList(meetingListFiltering);
440 if (meetingResult.ErrorCode !=
0)
441 throw(
"Error fetching calendar data: " + meetingResult.ErrorCode + ': ' + meetingResult.ErrorMessage);
442 var meetingList = meetingResult.ReturnValue;
444 // todos don't, they start on
00:
00 hrs., but should be visible anyway
445 // this will generate a list of passed todos. We have to check if they have been marked as
"done" yet
446 if (config['includeTodos'].Value) {
447 var todayTodoListFiltering = {
448 Type:'CalendarEntry',
451 StartRange: (new Date(now.getFullYear() -
1, now.getMonth(), now.getDate(),
0,
0,
0)),
452 EndRange: (new Date(now.getFullYear(), now.getMonth(), now.getDate(),
0,
0,
1))
455 var todayTodoResult = calendarService.IDataSource.GetList(todayTodoListFiltering);
456 var todayTodoList = todayTodoResult.ReturnValue;
457 var entryLists = [todayTodoList, meetingList];
459 var entryLists = [meetingList];
462 error('loading Calendar items list:' + e + ', line ' + e.line);
471 var entriesHtml = '
<table>';
475 max = ((panelNum ==
0) ? config['eventsPerWidget'].Value :
2 * config['eventsPerWidget'].Value);
477 max =
30; // we can display a lot more events in fullscreen mode
479 // the first outer loop iteration is for passed ToDos, the second loop is for all upcomming events (may also include ToDos)
480 for (var i=
0; counter < max && i < entryLists.length; i++) {
481 while (counter < max && (entry = entryLists[i].getNext()) != undefined) {
484 // output event info for debugging
486 'event: Id=' + entry.id +
487 ',Type=' + entry.Type +
488 ',Summary=' + entry.Summary +
489 ',Location=' + entry.Location +
490 ',Status=' + entry.Status +
491 ',StartTime=' + entry.StartTime +
492 ',EndTime=' + entry.EndTime +
493 ',InstanceStartTime=' + entry.InstanceStartTime +
494 ',InstanceEndTime=' + entry.InstanceEndTime
497 // we don't want ToDos when includeTodos == false or when they are completed
498 if (entry.Type == 'ToDo' && (entry.Status ==
"TodoCompleted" || !config['includeTodos'].Value)) {
499 console.info('skipping ' + entry.id );
504 // make sure that we don't include an event twice (useful for ToDos that might come up twice)
505 if (eventIds[entry.id] ==
1 && entry.Type == 'ToDo') {
506 console.info('skipped (already included) ' + entry.id);
510 eventIds[entry.id] =
1;
512 // summary can be undefined!
513 var Summary = ((entry.Summary == null) ? '' : entry.Summary);
514 if (entry.Type == 'Meeting' && entry.Location != '' && config['showLocation'].Value)
515 Summary += ', ' + entry.Location;
517 // fix by yves: determine start and end dates/times
518 entryStartTime = ((entry.InstanceStartTime == null) ? entry.StartTime : entry.InstanceStartTime);
519 entryEndTime = ((entry.InstanceEndTime == null) ? entry.EndTime : entry.InstanceEndTime);
521 // there can be ToDos that have no date at all!
522 if (entry.Type == 'ToDo' && entry.EndTime == null)
523 entryDate =
""; // this will cause parseDate(entryDate) to return null;
525 entryDate = ((entry.Type == 'ToDo') ? entryEndTime : entryStartTime); // ToDo's use their EndTime, the rest use StartTime
527 // Convert date/time string to Date object
528 var date = parseDate(entryDate);
529 console.info('date: ' + date);
530 var endDate = ((entryEndTime == null) ? null : parseDate(entryEndTime));
531 console.info('endDate: ' + endDate);
533 // check if meeting event has already passed
534 if (entry.Type == 'Meeting') {
535 var compareTime = ((endDate == null) ? date.getTime() : endDate.getTime());
536 if (now.getTime()
> compareTime) {
537 console.info('skipping Meeting (already passed) ' + entry.id);
539 eventIds[entry.id] =
0;
544 // check if anniversary passed (not sure why they are in the list, the query was only for today - nokia?)
545 if (entry.Type == 'Anniversary') {
546 var tmp = new Date(now.getFullYear(), now.getMonth(), now.getDate(),
0,
0,
0);
547 if (date.getTime() < tmp.getTime()) {
548 console.info('skipping Anniversary (already passed) ' + entry.id);
550 eventIds[entry.id] =
0;
555 // fix DayEvents end time. End times are off by
1 Second. It's possible that the event has already passed
556 if (entry.Type == 'DayEvent' && endDate != null) {
557 endDate.setMinutes(endDate.getMinutes() -
1);
558 console.info('fixing DayEvent endDate: ' + endDate);
559 if (now.getTime()
> endDate.getTime()) {
560 console.info('event already passed ' + entry.id);
562 eventIds[entry.id] =
0;
567 // check if the event is currently taking place
568 if (entryStartTime != null && entryEndTime != null && date != null && endDate != null) {
569 // check if we are between start and endtime
570 if ((date.getTime() < now.getTime()) && (now.getTime() < endDate.getTime())) {
571 date = now; // change appointment date/time to now
572 console.info('event is currently taking place: ' + date);
576 // skip events for the first panel in case this is the second one and we're not in fullscreen mode
577 if (mode ==
0 && panelNum ==
1 && counter < config['eventsPerWidget'].Value +
1) {
578 console.info('skipping (already in first widget) ' + entry.id);
582 // generate html output
583 entriesHtml += '
<tr><td><img class=
"icon" src=
"' + entry.Type + '.png" /></td>';
585 // some languages have very strange locale date formats, can't parse all those. Also some todos don't have dates at all.
586 entriesHtml += '
<td colspan=
"4"><span class=
"date">' + entryDate + '
</span> ';
588 var weekDay = date.toLocaleDateString().substr(
0,config['weekDayLength'].Value);
589 var time = formatTime(date);
590 var dateStr = formatDate(date, entryDate);
591 if (entry.Type == 'ToDo' || entry.Type == 'Anniversary' || entry.Type == 'DayEvent' || entry.Type == 'Reminder') {
592 if ((isToday(date) || isTomorrow(date)) && config['showTodayAsText'].Value) // show weekday if the date string is not text. looks odd otherwise
593 entriesHtml += '
<td colspan=
"4" width=
"1px"><span class=
"date">' + dateStr + '
</span> ';
595 entriesHtml += '
<td class=
"weekDay" width=
"1px">' + weekDay + '
</td><td width=
"1px" class=
"date">' + dateStr + '
</td><td colspan=
"2">';
596 } else if (entry.Type == 'Meeting') {
597 if (config['showCombinedDateTime'].Value) {
599 entriesHtml += '
<td width=
"1px" colspan=
"4"><span class=
"today">' + time + '
</span> ';
600 else if (isTomorrow(date))
601 entriesHtml += '
<td width=
"1px" colspan=
"4"><span class=
"tomorrow">' + dateStr + '
</span> <span class=
"time">' + time + '
</span> ';
603 entriesHtml += '
<td width=
"1px" class=
"weekDay">' + weekDay + '
</td><td width=
"1px" class=
"date">' + dateStr + '
</td><td colspan=
"2">';
605 if ((isToday(date) || isTomorrow(date)) && config['showTodayAsText'].Value)
606 entriesHtml += '
<td colspan=
"4" width=
"1px"><span class=
"today">' + dateStr + '
</span> <span class=
"time">' + time + '
</span> ';
608 entriesHtml += '
<td width=
"1px" class=
"weekDay">' + weekDay + '
</td><td width=
"1px" class=
"date">' + dateStr + '
</td><td width=
"1px" class=
"time">' + time + '
</td><td>';
612 entriesHtml += '
<span class=
"description">' + Summary + '
</span></td></tr>';
615 entriesHtml += '
</table>';
616 if (config['showNothingText'].Value && entriesHtml == '
<table></table>') {
617 var text = config['nothingText'].Value.replace(/%d/, config['monthRange'].Value);
618 entriesHtml = '
<div style=
"width:295px; height:75px; text-align:center; line-height:75px; overflow:visible;">' + text + '
</div>';
620 if (cacheEntriesHtml != entriesHtml) {
622 document.getElementById('calendarList').innerHTML = entriesHtml;
624 document.getElementById('fullscreenCalendarList').innerHTML = entriesHtml;
625 cacheEntriesHtml = entriesHtml;
628 error('displaying list:' + e + ', line ' + e.line);
633 function updateScreen()
635 // check if opening fullscreen
636 if( window.innerHeight
> 91 && mode ==
0) {
638 cacheEntriesHtml = '';
639 document.getElementById('body').style.backgroundImage =
"";
642 else if (window.innerHeight <=
91 && mode !=
0) {
644 cacheEntriesHtml = '';
654 function launchCalendar()
657 widget.openApplication(config['calendarApp'].Value,
"");
658 if (config['hideWidgetOnCalendarOpen'].Value)
661 error('starting Calendar App');
668 console.info('New widget instance starting up...');
671 // call calendar service
672 if (device !=
"undefined")
673 calendarService = device.getServiceObject(
"Service.Calendar",
"IDataSource");
675 throw('device object does not exist');
677 error('loading Calendar service: ' + e + ', line ' + e.line);
685 requestNotification();
686 window.setInterval('updateData()',
1000 *
60 * config['updateDataInterval'].Value);
691 if (config['useBackgroundImage'].Value)
692 // check for screen rotation every
1 secs
693 window.setInterval('updateScreen()',
1000 *
1);
696 function createMenu()
698 window.menu.setLeftSoftkeyLabel(
"",null);
699 window.menu.setRightSoftkeyLabel(
"",null);
701 var menuSettings = new MenuItem(getLocalizedText('menu.settings'), id++);
702 var menuCallApp = new MenuItem(getLocalizedText('menu.openCalendarApp'), id++);
703 var menuUpdate = new MenuItem(getLocalizedText('menu.update'), id++);
704 var menuAbout = new MenuItem(getLocalizedText('menu.about'), id++);
705 menuSettings.onSelect = showSettings;
706 menuAbout.onSelect = showAbout;
707 menuCallApp.onSelect = launchCalendar;
708 menuUpdate.onSelect = showUpdate;
710 window.menu.append(menuCallApp);
711 window.menu.append(menuSettings);
712 window.menu.append(menuUpdate);
713 window.menu.append(menuAbout);
716 function showSettings()
720 document.getElementById(
"settingsView").style.display =
"block";
721 document.onclick = null;
723 window.menu.setLeftSoftkeyLabel(getLocalizedText('settings.save'), function()
725 for (var key in config) {
726 if (config[key].Type == 'String')
727 config[key].Value = document.forms[
0].elements[
"settings." + key].value;
728 else if (config[key].Type == 'Int') {
729 config[key].Value = parseInt(document.forms[
0].elements[
"settings." + key].value);
730 if (config[key].Value <
0)
731 config[key].Value = config[key].Default;
733 else if (config[key].Type == 'Bool')
734 config[key].Value = document.forms[
0].elements[
"settings." + key].checked;
735 else if (config[key].Type == 'UID')
736 config[key].Value = parseInt(document.forms[
0].elements[
"settings." + key].value);
737 else if (config[key].Type == 'Enum') {
738 config[key].Value = document.forms[
0].elements[
"settings." + key].value;
739 if (config[key].ValidValues.indexOf(config[key].Value) == -
1)
740 config[key].Value = config[key].Default;
751 window.menu.setRightSoftkeyLabel(getLocalizedText('settings.cancel'), function()
757 var settingsHtml = '
<form>';
758 for (var key in config) {
759 if (config[key].Type == 'String')
760 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 />';
761 else if (config[key].Type == 'Int')
762 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 />';
763 else if (config[key].Type == 'Bool')
764 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 />';
765 else if (config[key].Type == 'UID')
766 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 />';
767 else if (config[key].Type == 'Enum') {
768 settingsHtml += '
<table><tr><td>' + getLocalizedText('settings.name.' + key) + '
<br /><select name=
"settings.' + key + '" size=
"1">';
769 for(var i =
0; i < config[key].ValidValues.length; i++)
770 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>';
771 settingsHtml += '
</select></div></td>' + printHintBox(getLocalizedText('settings.info.' + key)) + '
<hr />';
774 settingsHtml += '
<input name=
"reset" type=
"button" value=
"' + getLocalizedText('settings.restoreDefaults') + '" onclick=
"javascript:restoreDefaultSettings();showSettings();" />';
775 settingsHtml += '
</form>';
776 document.getElementById(
"settingsList").innerHTML = settingsHtml;
779 function changeCssClass(classname, properties)
781 for(var i =
0; i < document.styleSheets[
0]['cssRules'].length; i++)
783 if (document.styleSheets[
0]['cssRules'][i].selectorText == classname) {
784 document.styleSheets[
0].deleteRule(i);
785 document.styleSheets[
0].insertRule(classname + ' { ' + properties + ' }', document.styleSheets[
0]['cssRules'].length);
791 function updateCssClasses()
793 for(var key in config) {
794 changeCssClass(getLocalizedText('settings.name.' + key), config[key].Value);
798 function restoreDefaultSettings()
800 for (var key in config)
801 config[key].Value = config[key].Default;
804 function loadSettings()
806 for (var key in config) {
807 if (widget.preferenceForKey(key)) {
808 if (config[key].Type == 'Int')
809 config[key].Value = Number(widget.preferenceForKey(key));
810 else if (config[key].Type == 'String')
811 config[key].Value = widget.preferenceForKey(key);
812 else if (config[key].Type == 'Bool')
813 config[key].Value = (widget.preferenceForKey(key) == 'true')
814 else if (config[key].Type == 'Enum')
815 config[key].Value = widget.preferenceForKey(key);
816 else if (config[key].Type == 'UID')
817 config[key].Value = Number(widget.preferenceForKey(key));
820 config[key].Value = config[key].Default;
821 console.info('Settings: ' + key + '=\'' + config[key].Value + '\'');
825 function saveSettings()
827 for (var key in config) {
828 if (config[key].Type == 'Int')
829 widget.setPreferenceForKey(config[key].Value.toString(), key);
830 else if (config[key].Type == 'String')
831 widget.setPreferenceForKey(config[key].Value, key);
832 else if (config[key].Type == 'Bool')
833 widget.setPreferenceForKey(config[key].Value ? 'true' : 'false', key);
834 else if (config[key].Type == 'Enum')
835 widget.setPreferenceForKey(config[key].Value, key);
836 else if (config[key].Type == 'UID')
837 widget.setPreferenceForKey(config[key].Value.toString(), key);
841 function toggleVisibility(elementId)
843 if (document.getElementById(elementId).style.display ==
"none")
844 document.getElementById(elementId).style.display =
"block";
846 document.getElementById(elementId).style.display =
"none";
850 function printHintBox(text)
853 return '
<td width=
"1%" align=
"right" onclick=
"javascript:toggleVisibility(\'info' + uniqueId + '\')">' + getLocalizedText('settings.help') + '
</td></tr></table>'+
854 '
<div class=
"settingsInfo" id=
"info' + uniqueId + '">' + text + '
</div>';
861 document.getElementById(
"aboutView").style.display =
"block";
862 document.onclick = null;
864 window.menu.setLeftSoftkeyLabel(
" ", function(){});
865 window.menu.setRightSoftkeyLabel(getLocalizedText('softkey.back'), function()
871 //document.getElementById(
"aboutView").innerHTML = 'aboutView';
872 document.getElementById(
"name").innerHTML =
"Coming Next " + version;
875 function updateFullscreen()
879 function showFullscreen()
882 document.getElementById(
"fullscreenView").style.display =
"block";
883 document.getElementById('body').className =
"backgroundFullscreen";
884 document.onclick = launchCalendar;
889 function getBackgroundImage()
892 if (config['backgroundImageLocation'].Value == config['backgroundImageLocation'].ValidValues[
0]) // internal
893 bgImage = 'background_' + orientation + '.png';
895 bgImage = 'C:/Data/background_' + panelNum + '_' + orientation + '.png';
899 function updateHomescreen()
901 if (config['useBackgroundImage'].Value) {
902 // check for screen rotation
903 if (orientation != 'portrait' && screen.width ==
360 && screen.height ==
640) {
904 window.widget.prepareForTransition(
"fade");
905 orientation = 'portrait';
906 document.getElementById('body').style.backgroundImage = 'url(' + getBackgroundImage() + ')';
907 document.getElementById('body').style.backgroundColor = 'none';
908 window.widget.performTransition();
909 } else if (orientation != 'landscape' && screen.width ==
640 && screen.height ==
360) {
910 window.widget.prepareForTransition(
"fade");
911 orientation = 'landscape';
912 document.getElementById('body').style.backgroundImage = 'url(' + getBackgroundImage() + ')';
913 document.getElementById('body').style.backgroundColor = 'none';
914 window.widget.performTransition();
916 else if (document.getElementById('body').style.backgroundImage ==
"")
918 document.getElementById('body').style.backgroundImage = 'url(' + getBackgroundImage() + ')';
923 function showHomescreen()
926 document.getElementById(
"homescreenView").style.display =
"block";
927 document.getElementById('body').className =
"background";
928 document.onclick = null;
932 function getLocalizedText(p_Txt)
934 if (localizedText[p_Txt])
935 return localizedText[p_Txt];
937 return 'ERROR: missing translation for ' + p_Txt;
940 function showUpdate()
944 document.getElementById(
"updateView").style.display =
"block";
945 document.onclick = null;
947 window.menu.setLeftSoftkeyLabel(getLocalizedText('update.checknow'), function(){
950 window.menu.setRightSoftkeyLabel(getLocalizedText('softkey.back'), function()
956 document.getElementById(
"currentVersion").innerHTML = getLocalizedText(
"update.current") + version;
960 function checkForUpdate()
962 // asynch XHR to server url
963 reqV = new XMLHttpRequest();
964 reqV.onreadystatechange = checkForUpdateCallback;
965 document.getElementById(
"updateDiv").innerHTML = getLocalizedText(
"update.checking");
966 reqV.open(
"GET", versionURL, true);
967 reqV.setRequestHeader(
"If-Modified-Since",
"Sat, 1 Jan 2000 00:00:00 GMT" ); // disable caching
971 function checkForUpdateCallback()
973 if (reqV.readyState ==
4) {
974 if (reqV.status ==
200) {
975 var resultXml = reqV.responseText;
977 var div = document.getElementById(
"tmp");
978 div.innerHTML = resultXml;
979 var newVersion = div.getElementsByTagName('version')[
0].innerHTML;
980 var newVersionURL = div.getElementsByTagName('url')[
0].innerHTML;
982 if (version != newVersion) {
983 document.getElementById(
"updateDiv").innerHTML = getLocalizedText(
"update.download").replace(/%
1/, newVersion).replace(/%
2/, newVersionURL);
986 document.getElementById(
"updateDiv").innerHTML = getLocalizedText(
"update.nonewversion");
991 document.getElementById(
"updateDiv").innerHTML = getLocalizedText(
"update.error") + reqV.status +
" " + reqV.responseText;
998 document.getElementById(
"homescreenView").style.display =
"none";
999 document.getElementById(
"fullscreenView").style.display =
"none";
1000 document.getElementById(
"aboutView").style.display =
"none";
1001 document.getElementById(
"settingsView").style.display =
"none";
1002 document.getElementById(
"updateView").style.display =
"none";
1006 <style type=
"text/css">
1007 table { margin:
0px; padding:
0px; border-spacing:
0px; }
1008 td { padding:
0px
5px
0px
0px; white-space:nowrap; overflow:hidden; }
1009 hr { color:#ffffff; background-color:#ffffff; height:
1px; text-align:left; border-style:none; }
1010 .settingsInfo { display:none; font-style:italic; }
1011 .title { font-weight:bold; font-size:
14pt; }
1012 .textInput { width:
90%; }
1013 .credits { margin-left:
40px; text-indent: -
20px; margin-bottom:
0px; }
1014 #homescreenView { width:
315px; height:
91px; overflow:hidden; }
1015 #calendarList { position:absolute; left:
10px; top:
4px; width:
295px; height:
75px; overflow:hidden; }
1016 #name { text-align:center; }
1017 #appicon { display: block; margin-left: auto; margin-right: auto; margin-top:
10px; }
1018 #smallappicon { width:
22px; height:
22px; margin-right:
10px; float:left; }
1023 <body id=
"body" class=
"background">
1024 <div id=
"homescreenView">
1025 <div id=
"calendarList"></div>
1027 <div id=
"fullscreenView" style=
"display:none;">
1028 <img src=
"Icon.png" id=
"smallappicon">
1029 <h1 class=
"title">Coming Next
</h1>
1031 <div id=
"fullscreenCalendarList">loading...
</div>
1033 <div id=
"settingsView" style=
"display:none">
1034 <img src=
"Icon.png" id=
"smallappicon">
1035 <h1 class=
"title">Settings
</h1>
1037 <div id=
"settingsList"></div>
1039 <div id=
"aboutView" style=
"display:none">
1040 <img src=
"Icon.png" id=
"appicon">
1041 <h1 id=
"name">Coming Next
</h1>
1043 <p>Created by Dr. Cochambre and Michael Prager.
</p>
1044 <p>Contributions:
</p>
1045 <p class=
"credits">Paul Moore (bug fixes, new features and code cleanup)
</p>
1046 <p class=
"credits">Manfred Hanselmann (DST support)
</p>
1047 <p class=
"credits">Christophe Milsent (translation support & french translation
</p>
1048 <p class=
"credits">Flavio Nathan (portuguese-brazilian translation
</p>
1049 <p>This software is open source and licensed under the GPLv3.
</p>
1050 <p>Visit sourceforge.net/projects/comingnext for free updates.
</p>
1053 <div id=
"updateView" style=
"display:none">
1054 <img src=
"Icon.png" id=
"smallappicon">
1055 <h1 class=
"title">Check for update
</h1>
1057 <div id=
"currentVersion">Coming Next ??
</div>
1058 <div id=
"updateDiv"></div>
1059 <div id=
"tmp" style=
"display:none;"></div>