1 <?xml version=
"1.0" encoding=
"UTF-8"?>
2 <!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3 <html xmlns=
"http://www.w3.org/1999/xhtml">
6 <title>Coming Next
</title>
8 <style type=
"text/css">
9 /* The following classes can be modified by widget settings */
11 .backgroundFullscreen { }
23 // valid types for the config object are 'Int', 'Bool', 'String', 'Enum', 'UID'
30 Info: 'number of months to include in the event list',},
35 Name: 'Include ToDos',
36 Info: 'disable to remove ToDos from event list',},
41 Name: 'Use Background Image',
42 Info: 'use background_portrait.png and background_landscape.png to fake transparency. Disable to use a solid background color',},
43 showCombinedDateTime: {
47 Name: 'Show Combined Date/Time',
48 Info: 'only show the time for events happening today, otherwise just show the date',},
53 Name: 'Show Location',
54 Info: 'show the location for meeting events',},
59 Name: 'Show Today as Text',
60 Info: 'if enabled, the current date will be shown as
"Today" instead of
"31.12"',},
66 Info: 'text to display for
"Today"',},
71 Name: '
"Tomorrow" Text',
72 Info: 'text to display for
"Tomorrow"',},
77 Name: 'Show Now as Text',
78 Info: 'if enabled, the appointment time will be shown as
"Now" instead of
"12:00"',},
84 Info: 'text to display for
"Now"',},
89 Name: 'Date Separator',
90 Info: 'separator for dates. e.g.
"31.12" or
"31/12"',},
95 ValidValues: ['auto', 'DDMM', 'MMDD'],
97 Info: 'how dates will be displayed. \'auto\' will autodetect your phone\'s date format setting. \'MMDD\' will write month first, \'DDMM\' will write day first',},
102 Name: 'Weekday Length',
103 Info: 'defines how many characters of the weekday will be shown. E.g.
2 will cut
"Friday" to
"Fr"',},
104 updateDataInterval: {
108 Name: 'Update Data Interval',
109 Info: 'how many minutes to wait before updating the displayed data. The higher the number, the less battery is used',},
114 Name: 'Calendar Application To Run',
115 Info: 'UID of the calendar app to run when clicking the widget.
0x10005901 = buildin calendar,
0x20004ec1 = Epocware Handy Calendar',},
120 Name: 'Events Per Widget',
121 Info: 'number of events to show per widget. Default is
4',},
126 Name: 'Show
"Nothing" Text',
127 Info: 'if enabled, show a text if no events are in the list',},
130 Default: 'No further events within
2 months',
131 Value: 'No further events within
2 months',
132 Name: '
"No further events..." Text',
133 Info: 'text to show when no events are in the list',},
134 enableDaylightSaving: {
138 Name: 'Enable Daylight Saving (+
1h)',
139 Info: 'enable this if you are in a timezone that has daylight saving time (+
1h)',},
140 hideWidgetOnCalendarOpen: {
144 Name: 'Hide Widget When Opening Calendar',
145 Info: 'enable this if the fullscreen widget should be hidden when clicking on the widget to open the calendar app',},
146 cssStyle_background: {
148 Default: 'color:#ffffff; background-color:#
000000',
149 Value: 'color:#ffffff; background-color:#
000000',
151 Info: 'Defines the background of the widget. If you want to use a background image, set useBackgroundImage = true below. For the default themes, black, gray, and light blue, codes are #
292029, #e7dfe7, #
009aef',},
152 cssStyle_backgroundFullscreen: {
154 Default: 'color:#ffffff; background-color:#
000000',
155 Value: 'color:#ffffff; background-color:#
000000',
156 Name: '.backgroundFullscreen',
157 Info: 'Same as background but for the fullscreen version of the widget',},
163 Info: 'Defines the appearance of all week day texts',},
169 Info: 'Defines the appearance of all date texts',},
172 Default: 'color:#ff0000',
173 Value: 'color:#ff0000',
175 Info: 'Defines the appearance of
"Today" text',},
178 Default: 'color:#
0000ff',
179 Value: 'color:#
0000ff',
181 Info: 'Defines the appearance of
"Tomorrow" text',},
187 Info: 'Defines the appearance of all time texts',},
190 Default: 'color:#ff00ff',
191 Value: 'color:#ff00ff',
193 Info: 'Defines the appearance of
"Now" text',},
194 cssStyle_description: {
198 Name: '.description',
199 Info: 'Defines the appearance of all event descriptions',},
202 Default: 'width:
15px; height:
15px',
203 Value: 'width:
15px; height:
15px',
205 Info: 'Defines size and appearance of icons',},
208 //-------------------------------------------------------
209 // Nothing of interest from here on...
210 //-------------------------------------------------------
211 var panelNum =
0; // use
1 for second panel
212 var version =
"1.23";
213 var calendarService = null;
214 var cacheEntriesHtml = [];
215 var months_translated = [];
216 var orientation = '';
217 var now = new Date();
218 var mode =
0; //
0 = homescreen,
1 = fullscreen,
2 = settings,
3 = about
220 // vars for daylight saving time
221 var daylightsavingWinter =
0;
222 var daylightsavingSummer =
0;
223 var summertime = false;
225 window.onload = init;
226 window.onresize = updateScreen;
227 window.onshow = updateScreen;
229 function isLeapYear( year ) {
230 if (( year %
4 ==
0 && year %
100 !=
0 ) || year %
400 ==
0 )
236 function calcLeapYear(year, days)
238 if (isLeapYear(year))
244 function subToSunday(myDate, year, days, prevMonthDays)
246 for (i = myDate.getDay(); i
> 0 ;i--)
248 days -= prevMonthDays;
249 days = isLeapYear(year) ? --days : days;
253 function calcDaylightSaving()
255 var thisYearS = new Date(now.getFullYear(),
3,
0,
0,
0,
0 );
256 var thisYearW = new Date(now.getFullYear(),
10,
0,
0,
0,
0 );
257 var nextYearS = new Date(now.getFullYear() +
1,
3,
0,
0,
0,
0 );
258 var nextYearW = new Date(now.getFullYear() +
1,
10,
0,
0,
0,
0 );
262 thisYearSDays = nextYearSDays =
90;
263 thisYearWDays = nextYearWDays =
304;
265 thisYearSDays = calcLeapYear(now.getFullYear(), thisYearSDays);
266 thisYearWDays = calcLeapYear(now.getFullYear(), thisYearWDays);
267 nextYearSDays = calcLeapYear(now.getFullYear() +
1, nextYearSDays);
268 nextYearWDays = calcLeapYear(now.getFullYear() +
1, nextYearWDays);
270 thisYearSDays = subToSunday(thisYearS, now.getFullYear(), thisYearSDays,
59);
271 thisYearWDays = subToSunday(thisYearW, now.getFullYear(), thisYearWDays,
273);
272 nextYearSDays = subToSunday(nextYearS, now.getFullYear() +
1, nextYearSDays,
59);
273 nextYearWDays = subToSunday(nextYearW, now.getFullYear() +
1, nextYearWDays,
273);
275 daylightsavingSummer = new Date (now.getFullYear(),
03-
1, thisYearSDays,
2,
0,
0);
276 daylightsavingWinter = new Date (now.getFullYear(),
10-
1, thisYearWDays,
2,
0,
0);
277 if (daylightsavingSummer < now) {
278 daylightsavingSummer = new Date (now.getFullYear()+
1,
03-
1, nextYearSDays,
2,
0,
0);
281 if (daylightsavingWinter < now) {
282 daylightsavingWinter = new Date (now.getFullYear()+
1,
10-
1, nextYearWDays,
2,
0,
0);
285 if (summer && !winter)
291 function error(message)
293 console.info('Error: ' + message);
294 document.getElementById(
"calendarList").innerHTML = 'Error: ' + message;
297 function isToday(date)
299 if (date.getDate() == now.getDate() && date.getMonth() == now.getMonth())
304 function isTomorrow(date)
306 if ((date.getDate() == now.getDate() +
1 && date.getMonth() == now.getMonth()) ||
307 (date.getDate() ==
0 && date.getMonth() == now.getMonth() +
1) ||
308 (date.getDate() ==
0 && date.getMonth() == now.getMonth() +
1 && date.getYear() == now.getYear() +
1))
313 function collectLocales()
315 var tmpyear = ((panelNum ==
0) ?
2000 :
2001);
318 if (months_translated.length
> 0)
320 for (month =
0; month <
12; month++) {
321 var startDate = new Date(tmpyear, month,
15);
323 var item = new Object();
324 item.Type =
"DayEvent";
325 item.StartTime = startDate;
326 item.Summary =
"__temp" + month;
328 var criteria = new Object();
329 criteria.Type =
"CalendarEntry";
330 criteria.Item = item;
333 var result = calendarService.IDataSource.Add(criteria);
334 if (result.ErrorCode)
335 error(result.ErrorMessage);
337 error(
"collectLocales: " + e + ', line ' + e.line);
341 var startTime = new Date(tmpyear,
0,
1);
342 var endTime = new Date(tmpyear,
11,
31);
343 var listFiltering = {
344 Type:'CalendarEntry',
346 StartRange: startTime,
348 SearchText: '__temp',
352 var result = calendarService.IDataSource.GetList(listFiltering);
353 if (result.ErrorCode) {
354 error(result.ErrorMessage);
357 var list = result.ReturnValue;
359 error(e + ', line ' + e.line);
362 var ids = new Array();
368 while (list && (entry = list.getNext()) != undefined) {
369 dateArr = entry.StartTime.replace(/,/g,'').replace(/\./g,':').replace(/ /g,' ').split(' ');
370 var day = dateArr[
1];
371 var month = dateArr[
2];
372 var year = dateArr[
3];
374 // make sure month is set properly
375 if (isNaN(parseInt(day))) {
379 } else if (isNaN(parseInt(year))) {
385 console.info(entry.StartTime + ' -
> ' + month + ' ' + counter);
386 ids[counter] = entry.id;
387 months_translated[month] = counter +
1;
391 error(e + ', line ' + e.line);
396 var criteria = new Object();
397 criteria.Type =
"CalendarEntry";
402 var result = calendarService.IDataSource.Delete(criteria);
403 if (result.ErrorCode)
404 error(result.ErrorMessage);
406 error('deleting temp calendar entries:' + e + ', line ' + e.line);
411 function requestNotification()
413 var criteria = new Object();
414 criteria.Type =
"CalendarEntry";
417 var result = calendarService.IDataSource.RequestNotification(criteria, callback);
418 if (result.ErrorCode)
419 error('loading Calendar items list');
421 error(
"requestNotification: " + e + ', line ' + e.line);
425 function callback(transId, eventCode, result)
430 function parseDate(dateString)
433 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:
434 Wednesday,
26 August,
2009 24:
00:
00
435 Wednesday,
26 August,
2009 12:
00:
00 am
436 Wednesday, August
26,
2009 12:
00:
00 am
437 Wednesday,
2009 August,
26 12:
00:
00 am
438 Wednesday,
2009 August,
28 8.00.00 pm
439 Wednesday,
2009 August,
28 08:
00:
00 PM
442 if (dateString ==
"" || dateString == null)
444 var dateArr = dateString.replace(/,/g,'').replace(/\./g,':').replace(/ /g,' ').split(' ');
445 if (dateArr.length !=
5 && dateArr.length !=
6)
449 var weekDay = dateArr[
0];
450 var day = dateArr[
1];
451 var month = dateArr[
2];
452 var year = dateArr[
3];
453 // make sure month is set properly
454 if (isNaN(parseInt(day))) {
458 } else if (isNaN(parseInt(year))) {
463 // make sure day and year are set properly
464 if (Number(day)
> Number(year)) {
469 month = months_translated[month];
472 var timeArr = dateArr[
4].split(':');
473 if (timeArr.length !=
3)
475 var hours = Number(timeArr[
0]);
476 var minutes = Number(timeArr[
1]);
477 var seconds = Number(timeArr[
2]);
478 if (dateArr.length ==
6 && dateArr[
5].toLowerCase() == 'pm' && hours <
12)
480 if (dateArr.length ==
6 && dateArr[
5].toLowerCase() == 'am' && hours ==
12)
483 console.info('year=' + year + ' month=' + month + ' day=' + day + ' hours=' + hours + ' minutes=' + minutes+ ' seconds=' + seconds);
485 // take care of daylight saving time
486 if (config['enableDaylightSaving'].Value) {
487 var date = new Date(year, month -
1, day, hours, minutes, seconds);
488 if (summertime && date
> daylightsavingWinter && date < daylightsavingSummer)
490 else if (!summertime && date
> daylightsavingSummer && date < daylightsavingWinter)
494 return new Date(year, month -
1, day, hours, minutes, seconds);
497 // 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"
498 function formatDate(date, format)
500 var day = date.getDate().toString();
501 var month = (date.getMonth() +
1).toString();
502 while (day.length <
2) { day = '
0' + day; }
503 while (month.length <
2) { month = '
0' + month; }
505 if (config['showTodayAsText'].Value && isToday(date))
506 return '
<span class=
"today">' + config['todayText'].Value + '
</span>';
507 if (config['showTodayAsText'].Value && isTomorrow(date))
508 return '
<span class=
"tomorrow">' + config['tomorrowText'].Value + '
</span>';
510 var dateArr = format.replace(/,/g,'').replace(/\./g,':').replace(/ /g,' ').split(' ');
511 if (dateArr.length !=
5 && dateArr.length !=
6) {
512 // we don't know how to format this
513 if (config['dateFormat'].Value == 'auto' || config['dateFormat'].Value == 'DDMM')
514 return day + config['dateSeparator'].Value + month;
516 return month + config['dateSeparator'].Value + day;
520 if (config['dateFormat'].Value == 'MMDD')
522 else if (config['dateFormat'].Value == 'DDMM')
525 // config['dateFormat'].Value == 'auto', try to detect system setting
527 var day_ = dateArr[
1];
528 var month_ = dateArr[
2];
529 var year_ = dateArr[
3];
530 // make sure month is set properly
531 if (isNaN(parseInt(day_))) {
536 } else if (isNaN(parseInt(year_))) {
542 // make sure day and year are set properly
543 if (Number(day_)
> Number(year_))
548 return day + config['dateSeparator'].Value + month;
550 return month + config['dateSeparator'].Value + day;
553 function formatTime(date)
555 // date is a Date() object
556 date.setSeconds(
0); // we don't care about seconds
557 var time = date.toLocaleTimeString().replace(/[\.:]
00/, ''); // remove seconds from string
558 if (time.replace(/\./, ':').split(':')[
0].length <
2)
560 if (config['showNowAsText'].Value && date.getTime() == now.getTime())
561 time = '
<span class=
"now">' + config['nowText'].Value + '
</span>';
565 function updateData()
567 calcDaylightSaving();
569 // meetings have time
570 // 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
572 var meetingListFiltering = {
573 Type:'CalendarEntry',
575 StartRange: (new Date(now.getFullYear(), now.getMonth(), now.getDate(),
0,
0,
0)),
576 EndRange: (new Date(now.getFullYear(), now.getMonth() + config['monthRange'].Value, now.getDate(),
0,
0,
0))
579 var meetingResult = calendarService.IDataSource.GetList(meetingListFiltering);
580 var meetingList = meetingResult.ReturnValue;
582 // todos don't, they start on
00:
00 hrs., but should be visible anyway
583 // this will generate a list of passed todos. We have to check if they have been marked as
"done" yet
584 if (config['includeTodos'].Value) {
585 var todayTodoListFiltering = {
586 Type:'CalendarEntry',
589 StartRange: (new Date(now.getFullYear() -
1, now.getMonth(), now.getDate(),
0,
0,
0)),
590 EndRange: (new Date(now.getFullYear(), now.getMonth(), now.getDate(),
0,
0,
1))
593 var todayTodoResult = calendarService.IDataSource.GetList(todayTodoListFiltering);
594 var todayTodoList = todayTodoResult.ReturnValue;
595 var entryLists = [todayTodoList, meetingList];
597 var entryLists = [meetingList];
600 error('loading Calendar items list:' + e + ', line ' + e.line);
609 var entriesHtml = '
<table>';
613 max = ((panelNum ==
0) ? config['eventsPerWidget'].Value :
2 * config['eventsPerWidget'].Value);
615 max =
30; // we can display a lot more events in fullscreen mode
617 // the first outer loop iteration is for passed ToDos, the second loop is for all upcomming events (may also include ToDos)
618 for (var i=
0; counter < max && i < entryLists.length; i++) {
619 while (counter < max && (entry = entryLists[i].getNext()) != undefined) {
622 // output event info for debugging
624 'event: Id=' + entry.id +
625 ',Type=' + entry.Type +
626 ',Summary=' + entry.Summary +
627 ',Location=' + entry.Location +
628 ',Status=' + entry.Status +
629 ',StartTime=' + entry.StartTime +
630 ',EndTime=' + entry.EndTime +
631 ',InstanceStartTime=' + entry.InstanceStartTime +
632 ',InstanceEndTime=' + entry.InstanceEndTime
635 // we don't want ToDos when includeTodos == false or when they are completed
636 if (entry.Type == 'ToDo' && (entry.Status ==
"TodoCompleted" || !config['includeTodos'].Value)) {
637 console.info('skipping ' + entry.id );
642 // make sure that we don't include an event twice (useful for ToDos that might come up twice)
643 if (eventIds[entry.id] ==
1) {
644 console.info('skipped (already included) ' + entry.id);
648 eventIds[entry.id] =
1;
650 // summary can be undefined!
651 var Summary = ((entry.Summary == null) ? '' : entry.Summary);
652 if (entry.Type == 'Meeting' && entry.Location != '' && config['showLocation'].Value)
653 Summary += ', ' + entry.Location;
655 // fix by yves: determine start and end dates/times
656 entryStartTime = ((entry.InstanceStartTime == null) ? entry.StartTime : entry.InstanceStartTime);
657 entryEndTime = ((entry.InstanceEndTime == null) ? entry.EndTime : entry.InstanceEndTime);
659 // there can be ToDos that have no date at all!
660 if (entry.Type == 'ToDo' && entry.EndTime == null)
661 entryDate =
""; // this will cause parseDate(entryDate) to return null;
663 entryDate = ((entry.Type == 'ToDo') ? entryEndTime : entryStartTime); // ToDo's use their EndTime, the rest use StartTime
665 // Convert date/time string to Date object
666 var date = parseDate(entryDate);
667 console.info('date: ' + date);
668 var endDate = ((entryEndTime == null) ? null : parseDate(entryEndTime));
669 console.info('endDate: ' + endDate);
671 // check if meeting event has already passed
672 if (entry.Type == 'Meeting') {
673 var compareTime = ((endDate == null) ? date.getTime() : endDate.getTime());
674 if (now.getTime()
> compareTime) {
675 console.info('skipping Meeting (already passed) ' + entry.id);
677 eventIds[entry.id] =
0;
682 // check if anniversary passed (not sure why they are in the list, the query was only for today - nokia?)
683 if (entry.Type == 'Anniversary') {
684 var tmp = new Date(now.getFullYear(), now.getMonth(), now.getDate(),
0,
0,
0);
685 if (date.getTime() < tmp.getTime()) {
686 console.info('skipping Anniversary (already passed) ' + entry.id);
688 eventIds[entry.id] =
0;
693 // fix DayEvents end time. End times are off by
1 Second. It's possible that the event has already passed
694 if (entry.Type == 'DayEvent' && endDate != null) {
695 endDate.setMinutes(endDate.getMinutes() -
1);
696 console.info('fixing DayEvent endDate: ' + endDate);
697 if (now.getTime()
> endDate.getTime()) {
698 console.info('event already passed ' + entry.id);
700 eventIds[entry.id] =
0;
705 // check if the event is currently taking place
706 if (entryStartTime != null && entryEndTime != null && date != null && endDate != null) {
707 // check if we are between start and endtime
708 if ((date.getTime() < now.getTime()) && (now.getTime() < endDate.getTime())) {
709 date = now; // change appointment date/time to now
710 console.info('event is currently taking place: ' + date);
714 // skip events for the first panel in case this is the second one and we're not in fullscreen mode
715 if (mode ==
0 && panelNum ==
1 && counter < config['eventsPerWidget'].Value +
1) {
716 console.info('skipping (already in first widget) ' + entry.id);
720 // generate html output
721 entriesHtml += '
<tr><td><img class=
"icon" src=
"' + entry.Type + '.png" /></td>';
723 // some languages have very strange locale date formats, can't parse all those. Also some todos don't have dates at all.
724 entriesHtml += '
<td colspan=
"4"><span class=
"date">' + entryDate + '
</span> ';
726 var weekDay = date.toLocaleDateString().substr(
0,config['weekDayLength'].Value);
727 var time = formatTime(date);
728 var dateStr = formatDate(date, entryDate);
729 if (entry.Type == 'ToDo' || entry.Type == 'Anniversary' || entry.Type == 'DayEvent' || entry.Type == 'Reminder') {
730 if ((isToday(date) || isTomorrow(date)) && config['showTodayAsText'].Value) // show weekday if the date string is not text. looks odd otherwise
731 entriesHtml += '
<td colspan=
"4" width=
"1px"><span class=
"date">' + dateStr + '
</span> ';
733 entriesHtml += '
<td class=
"weekDay" width=
"1px">' + weekDay + '
</td><td width=
"1px" class=
"date">' + dateStr + '
</td><td colspan=
"2">';
734 } else if (entry.Type == 'Meeting') {
735 if (config['showCombinedDateTime'].Value) {
737 entriesHtml += '
<td width=
"1px" colspan=
"4"><span class=
"today">' + time + '
</span> ';
738 else if (isTomorrow(date))
739 entriesHtml += '
<td width=
"1px" colspan=
"4"><span class=
"tomorrow">' + dateStr + '
</span> <span class=
"time">' + time + '
</span> ';
741 entriesHtml += '
<td width=
"1px" class=
"weekDay">' + weekDay + '
</td><td width=
"1px" class=
"date">' + dateStr + '
</td><td colspan=
"2">';
743 if ((isToday(date) || isTomorrow(date)) && config['showTodayAsText'].Value)
744 entriesHtml += '
<td colspan=
"4" width=
"1px"><span class=
"today">' + dateStr + '
</span> <span class=
"time">' + time + '
</span> ';
746 entriesHtml += '
<td width=
"1px" class=
"weekDay">' + weekDay + '
</td><td width=
"1px" class=
"date">' + dateStr + '
</td><td width=
"1px" class=
"time">' + time + '
</td><td>';
750 entriesHtml += '
<span class=
"description">' + Summary + '
</span></td></tr>';
753 entriesHtml += '
</table>';
754 if (config['showNothingText'].Value && entriesHtml == '
<table></table>')
755 entriesHtml = '
<div style=
"width:295px; height:75px; text-align:center; line-height:75px; overflow:visible;">' + config['nothingText'].Value + '
</div>';
756 if (cacheEntriesHtml != entriesHtml) {
758 document.getElementById('calendarList').innerHTML = entriesHtml;
760 document.getElementById('fullscreenCalendarList').innerHTML = entriesHtml;
761 cacheEntriesHtml = entriesHtml;
764 error('displaying list:' + e + ', line ' + e.line);
769 function updateScreen()
771 // check if opening fullscreen
772 if( window.innerHeight
> 91 && mode ==
0) {
774 cacheEntriesHtml = '';
775 document.getElementById('body').style.backgroundImage =
"";
778 else if (window.innerHeight <=
91 && mode !=
0) {
780 cacheEntriesHtml = '';
790 function launchCalendar()
793 widget.openApplication(config['calendarApp'].Value,
"");
794 if (config['hideWidgetOnCalendarOpen'].Value)
797 error('starting Calendar App');
805 // call calendar service
806 calendarService = device.getServiceObject(
"Service.Calendar",
"IDataSource");
808 error('loading Calendar service');
816 requestNotification();
817 window.setInterval('updateData()',
1000 *
60 * config['updateDataInterval'].Value);
822 if (config['useBackgroundImage'].Value)
823 // check for screen rotation every
1 secs
824 window.setInterval('updateScreen()',
1000 *
1);
827 function createMenu()
829 window.menu.setLeftSoftkeyLabel(
"",null);
830 window.menu.setRightSoftkeyLabel(
"",null);
832 var menuSettings = new MenuItem(
"Settings", id++);
833 var menuCallApp = new MenuItem(
"Open Calendar App", id++);
834 var menuAbout = new MenuItem(
"About", id++);
835 menuSettings.onSelect = showSettings;
836 menuAbout.onSelect = showAbout;
837 menuCallApp.onSelect = launchCalendar;
839 window.menu.append(menuCallApp);
840 window.menu.append(menuSettings);
841 window.menu.append(menuAbout);
844 function showSettings()
847 document.getElementById(
"homescreenView").style.display =
"none";
848 document.getElementById(
"fullscreenView").style.display =
"none";
849 document.getElementById(
"aboutView").style.display =
"none";
850 document.getElementById(
"settingsView").style.display =
"block";
851 document.onclick = null;
853 window.menu.setLeftSoftkeyLabel(
"Save", function()
855 for (var key in config) {
856 if (config[key].Type == 'String')
857 config[key].Value = document.forms[
0].elements[
"settings." + key].value;
858 else if (config[key].Type == 'Int') {
859 config[key].Value = parseInt(document.forms[
0].elements[
"settings." + key].value);
860 if (config[key].Value <
0)
861 config[key].Value = config[key].Default;
863 else if (config[key].Type == 'Bool')
864 config[key].Value = document.forms[
0].elements[
"settings." + key].checked;
865 else if (config[key].Type == 'UID')
866 config[key].Value = parseInt(document.forms[
0].elements[
"settings." + key].value);
867 else if (config[key].Type == 'Enum') {
868 config[key].Value = document.forms[
0].elements[
"settings." + key].value;
869 if (config[key].ValidValues.indexOf(config[key].Value) == -
1)
870 config[key].Value = config[key].Default;
881 window.menu.setRightSoftkeyLabel(
"Cancel", function()
887 var settingsHtml = '
<form>';
888 for (var key in config) {
889 if (config[key].Type == 'String')
890 settingsHtml += '
<table><tr><td>' + config[key].Name + '
<br /><input class=
"textInput" name=
"settings.' + key + '" type=
"text" value=
"' + config[key].Value + '" /></td>' + printHintBox(config[key].Info) + '
<hr />';
891 else if (config[key].Type == 'Int')
892 settingsHtml += '
<table><tr><td>' + config[key].Name + '
<br /><input class=
"textInput" name=
"settings.' + key + '" type=
"text" value=
"' + config[key].Value + '" /></td>' + printHintBox(config[key].Info) + '
<hr />';
893 else if (config[key].Type == 'Bool')
894 settingsHtml += '
<table><tr><td>' + config[key].Name + '
<br /><input name=
"settings.' + key + '" type=
"checkbox" value=
"true" ' + (config[key].Value ? '
checked=
"checked"' : '') + '
/></td>' + printHintBox(config[key].Info) + '
<hr />';
895 else if (config[key].Type == 'UID')
896 settingsHtml += '
<table><tr><td>' + config[key].Name + '
<br /><input class=
"textInput" name=
"settings.' + key + '" type=
"text" value=
"0x' + config[key].Value.toString(16) + '" /></td>' + printHintBox(config[key].Info) + '
<hr />';
897 else if (config[key].Type == 'Enum') {
898 settingsHtml += '
<table><tr><td>' + config[key].Name + '
<br /><select name=
"settings.' + key + '" size=
"1">';
899 for(var i =
0; i < config[key].ValidValues.length; i++)
900 settingsHtml += '
<option label=
"' + config[key].ValidValues[i] + '"' + (config[key].Value == config[key].ValidValues[i] ? '
selected=
"selected"' : '') + '
>' + config[key].ValidValues[i] + '
</option>';
901 settingsHtml += '
</select></div></td>' + printHintBox(config[key].Info) + '
<hr />';
904 settingsHtml += '
<input name=
"reset" type=
"button" value=
"Restore Defaults" onclick=
"javascript:restoreDefaultSettings();showSettings();" />';
905 settingsHtml += '
</form>';
906 document.getElementById(
"settingsList").innerHTML = settingsHtml;
909 function changeCssClass(classname, properties)
911 for(var i =
0; i < document.styleSheets[
0]['cssRules'].length; i++)
913 if (document.styleSheets[
0]['cssRules'][i].selectorText == classname) {
914 document.styleSheets[
0].deleteRule(i);
915 document.styleSheets[
0].insertRule(classname + ' { ' + properties + ' }', document.styleSheets[
0]['cssRules'].length);
921 function updateCssClasses()
923 for(var key in config) {
924 changeCssClass(config[key].Name, config[key].Value);
928 function restoreDefaultSettings()
930 for (var key in config)
931 config[key].Value = config[key].Default;
934 function loadSettings()
936 for (var key in config) {
937 if (widget.preferenceForKey(key)) {
938 if (config[key].Type == 'Int')
939 config[key].Value = Number(widget.preferenceForKey(key));
940 else if (config[key].Type == 'String')
941 config[key].Value = widget.preferenceForKey(key);
942 else if (config[key].Type == 'Bool')
943 config[key].Value = (widget.preferenceForKey(key) == 'true')
944 else if (config[key].Type == 'Enum')
945 config[key].Value = widget.preferenceForKey(key);
946 else if (config[key].Type == 'UID')
947 config[key].Value = Number(widget.preferenceForKey(key));
950 config[key].Value = config[key].Default;
955 function saveSettings()
957 for (var key in config) {
958 if (config[key].Type == 'Int')
959 widget.setPreferenceForKey(config[key].Value.toString(), key);
960 else if (config[key].Type == 'String')
961 widget.setPreferenceForKey(config[key].Value, key);
962 else if (config[key].Type == 'Bool')
963 widget.setPreferenceForKey(config[key].Value ? 'true' : 'false', key);
964 else if (config[key].Type == 'Enum')
965 widget.setPreferenceForKey(config[key].Value, key);
966 else if (config[key].Type == 'UID')
967 widget.setPreferenceForKey(config[key].Value.toString(), key);
971 function toggleVisibility(elementId)
973 if (document.getElementById(elementId).style.display ==
"none")
974 document.getElementById(elementId).style.display =
"block";
976 document.getElementById(elementId).style.display =
"none";
980 function printHintBox(text)
983 return '
<td width=
"1%" align=
"right" onclick=
"javascript:toggleVisibility(\'info' + uniqueId + '\')">Help
</td></tr></table>'+
984 '
<div class=
"settingsInfo" id=
"info' + uniqueId + '">' + text + '
</div>';
990 document.getElementById(
"homescreenView").style.display =
"none";
991 document.getElementById(
"fullscreenView").style.display =
"none";
992 document.getElementById(
"aboutView").style.display =
"block";
993 document.getElementById(
"settingsView").style.display =
"none";
994 document.onclick = null;
996 window.menu.setLeftSoftkeyLabel(
" ", function(){});
997 window.menu.setRightSoftkeyLabel(
"Back", function()
1003 //document.getElementById(
"aboutView").innerHTML = 'aboutView';
1004 document.getElementById(
"name").innerHTML =
"Coming Next " + version;
1007 function updateFullscreen()
1011 function showFullscreen()
1013 document.getElementById(
"homescreenView").style.display =
"none";
1014 document.getElementById(
"fullscreenView").style.display =
"block";
1015 document.getElementById(
"aboutView").style.display =
"none";
1016 document.getElementById(
"settingsView").style.display =
"none";
1017 document.getElementById('body').className =
"backgroundFullscreen";
1018 document.onclick = launchCalendar;
1023 function updateHomescreen()
1025 if (config['useBackgroundImage'].Value) {
1026 // check for screen rotation
1027 if (orientation != 'portrait' && screen.width ==
360 && screen.height ==
640) {
1028 window.widget.prepareForTransition(
"fade");
1029 orientation = 'portrait';
1030 document.getElementById('body').style.backgroundImage = 'url(background_' + orientation + '.png)';
1031 document.getElementById('body').style.backgroundColor = 'none';
1032 window.widget.performTransition();
1033 } else if (orientation != 'landscape' && screen.width ==
640 && screen.height ==
360) {
1034 window.widget.prepareForTransition(
"fade");
1035 orientation = 'landscape';
1036 document.getElementById('body').style.backgroundImage = 'url(background_' + orientation + '.png)';
1037 document.getElementById('body').style.backgroundColor = 'none';
1038 window.widget.performTransition();
1040 else if (document.getElementById('body').style.backgroundImage ==
"")
1042 document.getElementById('body').style.backgroundImage = 'url(background_' + orientation + '.png)';
1047 function showHomescreen()
1049 document.getElementById(
"homescreenView").style.display =
"block";
1050 document.getElementById(
"fullscreenView").style.display =
"none";
1051 document.getElementById(
"aboutView").style.display =
"none";
1052 document.getElementById(
"settingsView").style.display =
"none";
1053 document.getElementById('body').className =
"background";
1054 document.onclick = null;
1059 <style type=
"text/css">
1060 table { margin:
0px; padding:
0px; border-spacing:
0px; }
1061 td { padding:
0px
5px
0px
0px; white-space:nowrap; overflow:hidden; }
1062 hr { color:#ffffff; background-color:#ffffff; height:
1px; text-align:left; border-style:none; }
1063 .settingsInfo { display:none; font-style:italic; }
1064 .title { font-weight:bold; font-size:
14pt; }
1065 .textInput { width:
90%; }
1066 #homescreenView { width:
315px; height:
91px; overflow:hidden; }
1067 #calendarList { position:absolute; left:
10px; top:
4px; width:
295px; height:
75px; overflow:hidden; }
1068 #name { text-align:center; }
1069 #appicon { display: block; margin-left: auto; margin-right: auto; margin-top:
50px; }
1070 #smallappicon { width:
22px; height:
22px; margin-right:
10px; float:left; }
1075 <body id=
"body" class=
"background">
1076 <div id=
"homescreenView">
1077 <div id=
"calendarList"></div>
1079 <div id=
"fullscreenView" style=
"display:none;">
1080 <img src=
"Icon.png" id=
"smallappicon">
1081 <h1 class=
"title">Coming Next
</h1>
1083 <div id=
"fullscreenCalendarList">loading...
</div>
1085 <div id=
"settingsView" style=
"display:none">
1086 <img src=
"Icon.png" id=
"smallappicon">
1087 <h1 class=
"title">Settings
</h1>
1089 <div id=
"settingsList"></div>
1091 <div id=
"aboutView" style=
"display:none">
1092 <img src=
"Icon.png" id=
"appicon">
1093 <h1 id=
"name">Coming Next
</h1>
1095 <p>Created by Dr. Cochambre and Michael Prager.
</p>
1096 <p>This software is open source and licensed under the GPLv3.
</p>
1097 <p>Visit https://sourceforge.net/projects/comingnext/ for free updates.
</p>