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 cssStyle_background: {
142 Default: 'color:#ffffff; background-color:#
000000',
143 Value: 'color:#ffffff; background-color:#
000000',
145 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',},
146 cssStyle_backgroundFullscreen: {
148 Default: 'color:#ffffff; background-color:#
000000',
149 Value: 'color:#ffffff; background-color:#
000000',
150 Name: '.backgroundFullscreen',
151 Info: 'Same as background but for the fullscreen version of the widget',},
157 Info: 'Defines the appearance of all week day texts',},
163 Info: 'Defines the appearance of all date texts',},
166 Default: 'color:#ff0000',
167 Value: 'color:#ff0000',
169 Info: 'Defines the appearance of
"Today" text',},
172 Default: 'color:#
0000ff',
173 Value: 'color:#
0000ff',
175 Info: 'Defines the appearance of
"Tomorrow" text',},
181 Info: 'Defines the appearance of all time texts',},
184 Default: 'color:#ff00ff',
185 Value: 'color:#ff00ff',
187 Info: 'Defines the appearance of
"Now" text',},
188 cssStyle_description: {
192 Name: '.description',
193 Info: 'Defines the appearance of all event descriptions',},
196 Default: 'width:
15px; height:
15px',
197 Value: 'width:
15px; height:
15px',
199 Info: 'Defines size and appearance of icons',},
202 //-------------------------------------------------------
203 // Nothing of interest from here on...
204 //-------------------------------------------------------
205 var panelNum =
0; // use
1 for second panel
206 var version =
"1.23";
207 var calendarService = null;
208 var cacheEntriesHtml = [];
209 var months_translated = [];
210 var orientation = '';
211 var now = new Date();
212 var mode =
0; //
0 = homescreen,
1 = fullscreen,
2 = settings,
3 = about
214 // vars for daylight saving time
215 var daylightsavingWinter =
0;
216 var daylightsavingSummer =
0;
217 var summertime = false;
219 window.onload = init;
220 window.onresize = updateScreen;
221 window.onshow = updateScreen;
223 function isLeapYear( year ) {
224 if (( year %
4 ==
0 && year %
100 !=
0 ) || year %
400 ==
0 )
230 function calcLeapYear(year, days)
232 if (isLeapYear(year))
238 function subToSunday(myDate, year, days, prevMonthDays)
240 for (i = myDate.getDay(); i
> 0 ;i--)
242 days -= prevMonthDays;
243 days = isLeapYear(year) ? --days : days;
247 function calcDaylightSaving()
249 var thisYearS = new Date(now.getFullYear(),
3,
0,
0,
0,
0 );
250 var thisYearW = new Date(now.getFullYear(),
10,
0,
0,
0,
0 );
251 var nextYearS = new Date(now.getFullYear() +
1,
3,
0,
0,
0,
0 );
252 var nextYearW = new Date(now.getFullYear() +
1,
10,
0,
0,
0,
0 );
256 thisYearSDays = nextYearSDays =
90;
257 thisYearWDays = nextYearWDays =
304;
259 thisYearSDays = calcLeapYear(now.getFullYear(), thisYearSDays);
260 thisYearWDays = calcLeapYear(now.getFullYear(), thisYearWDays);
261 nextYearSDays = calcLeapYear(now.getFullYear() +
1, nextYearSDays);
262 nextYearWDays = calcLeapYear(now.getFullYear() +
1, nextYearWDays);
264 thisYearSDays = subToSunday(thisYearS, now.getFullYear(), thisYearSDays,
59);
265 thisYearWDays = subToSunday(thisYearW, now.getFullYear(), thisYearWDays,
273);
266 nextYearSDays = subToSunday(nextYearS, now.getFullYear() +
1, nextYearSDays,
59);
267 nextYearWDays = subToSunday(nextYearW, now.getFullYear() +
1, nextYearWDays,
273);
269 daylightsavingSummer = new Date (now.getFullYear(),
03-
1, thisYearSDays,
2,
0,
0);
270 daylightsavingWinter = new Date (now.getFullYear(),
10-
1, thisYearWDays,
2,
0,
0);
271 if (daylightsavingSummer < now) {
272 daylightsavingSummer = new Date (now.getFullYear()+
1,
03-
1, nextYearSDays,
2,
0,
0);
275 if (daylightsavingWinter < now) {
276 daylightsavingWinter = new Date (now.getFullYear()+
1,
10-
1, nextYearWDays,
2,
0,
0);
279 if (summer && !winter)
285 function error(message)
287 console.info('Error: ' + message);
288 document.getElementById(
"calendarList").innerHTML = 'Error: ' + message;
291 function isToday(date)
293 if (date.getDate() == now.getDate() && date.getMonth() == now.getMonth())
298 function isTomorrow(date)
300 if ((date.getDate() == now.getDate() +
1 && date.getMonth() == now.getMonth()) ||
301 (date.getDate() ==
0 && date.getMonth() == now.getMonth() +
1) ||
302 (date.getDate() ==
0 && date.getMonth() == now.getMonth() +
1 && date.getYear() == now.getYear() +
1))
307 function collectLocales()
309 var tmpyear = ((panelNum ==
0) ?
2000 :
2001);
312 if (months_translated.length
> 0)
314 for (month =
0; month <
12; month++) {
315 var startDate = new Date(tmpyear, month,
15);
317 var item = new Object();
318 item.Type =
"DayEvent";
319 item.StartTime = startDate;
320 item.Summary =
"__temp" + month;
322 var criteria = new Object();
323 criteria.Type =
"CalendarEntry";
324 criteria.Item = item;
327 var result = calendarService.IDataSource.Add(criteria);
328 if (result.ErrorCode)
329 error(result.ErrorMessage);
331 error(
"collectLocales: " + e + ', line ' + e.line);
335 var startTime = new Date(tmpyear,
0,
1);
336 var endTime = new Date(tmpyear,
11,
31);
337 var listFiltering = {
338 Type:'CalendarEntry',
340 StartRange: startTime,
342 SearchText: '__temp',
346 var result = calendarService.IDataSource.GetList(listFiltering);
347 if (result.ErrorCode) {
348 error(result.ErrorMessage);
351 var list = result.ReturnValue;
353 error(e + ', line ' + e.line);
356 var ids = new Array();
362 while (list && (entry = list.getNext()) != undefined) {
363 dateArr = entry.StartTime.replace(/,/g,'').replace(/\./g,':').replace(/ /g,' ').split(' ');
364 var day = dateArr[
1];
365 var month = dateArr[
2];
366 var year = dateArr[
3];
368 // make sure month is set properly
369 if (isNaN(parseInt(day))) {
373 } else if (isNaN(parseInt(year))) {
379 console.info(entry.StartTime + ' -
> ' + month + ' ' + counter);
380 ids[counter] = entry.id;
381 months_translated[month] = counter +
1;
385 error(e + ', line ' + e.line);
390 var criteria = new Object();
391 criteria.Type =
"CalendarEntry";
396 var result = calendarService.IDataSource.Delete(criteria);
397 if (result.ErrorCode)
398 error(result.ErrorMessage);
400 error('deleting temp calendar entries:' + e + ', line ' + e.line);
405 function requestNotification()
407 var criteria = new Object();
408 criteria.Type =
"CalendarEntry";
411 var result = calendarService.IDataSource.RequestNotification(criteria, callback);
412 if (result.ErrorCode)
413 error('loading Calendar items list');
415 error(
"requestNotification: " + e + ', line ' + e.line);
419 function callback(transId, eventCode, result)
424 function parseDate(dateString)
427 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:
428 Wednesday,
26 August,
2009 24:
00:
00
429 Wednesday,
26 August,
2009 12:
00:
00 am
430 Wednesday, August
26,
2009 12:
00:
00 am
431 Wednesday,
2009 August,
26 12:
00:
00 am
432 Wednesday,
2009 August,
28 8.00.00 pm
433 Wednesday,
2009 August,
28 08:
00:
00 PM
436 if (dateString ==
"" || dateString == null)
438 var dateArr = dateString.replace(/,/g,'').replace(/\./g,':').replace(/ /g,' ').split(' ');
439 if (dateArr.length !=
5 && dateArr.length !=
6)
443 var weekDay = dateArr[
0];
444 var day = dateArr[
1];
445 var month = dateArr[
2];
446 var year = dateArr[
3];
447 // make sure month is set properly
448 if (isNaN(parseInt(day))) {
452 } else if (isNaN(parseInt(year))) {
457 // make sure day and year are set properly
458 if (Number(day)
> Number(year)) {
463 month = months_translated[month];
466 var timeArr = dateArr[
4].split(':');
467 if (timeArr.length !=
3)
469 var hours = Number(timeArr[
0]);
470 var minutes = Number(timeArr[
1]);
471 var seconds = Number(timeArr[
2]);
472 if (dateArr.length ==
6 && dateArr[
5].toLowerCase() == 'pm' && hours <
12)
474 if (dateArr.length ==
6 && dateArr[
5].toLowerCase() == 'am' && hours ==
12)
477 console.info('year=' + year + ' month=' + month + ' day=' + day + ' hours=' + hours + ' minutes=' + minutes+ ' seconds=' + seconds);
479 // take care of daylight saving time
480 if (config['enableDaylightSaving'].Value) {
481 var date = new Date(year, month -
1, day, hours, minutes, seconds);
482 if (summertime && date
> daylightsavingWinter && date < daylightsavingSummer)
484 else if (!summertime && date
> daylightsavingSummer && date < daylightsavingWinter)
488 return new Date(year, month -
1, day, hours, minutes, seconds);
491 // 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"
492 function formatDate(date, format)
494 var day = date.getDate().toString();
495 var month = (date.getMonth() +
1).toString();
496 while (day.length <
2) { day = '
0' + day; }
497 while (month.length <
2) { month = '
0' + month; }
499 if (config['showTodayAsText'].Value && isToday(date))
500 return '
<span class=
"today">' + config['todayText'].Value + '
</span>';
501 if (config['showTodayAsText'].Value && isTomorrow(date))
502 return '
<span class=
"tomorrow">' + config['tomorrowText'].Value + '
</span>';
504 var dateArr = format.replace(/,/g,'').replace(/\./g,':').replace(/ /g,' ').split(' ');
505 if (dateArr.length !=
5 && dateArr.length !=
6) {
506 // we don't know how to format this
507 if (config['dateFormat'].Value == 'auto' || config['dateFormat'].Value == 'DDMM')
508 return day + config['dateSeparator'].Value + month;
510 return month + config['dateSeparator'].Value + day;
514 if (config['dateFormat'].Value == 'MMDD')
516 else if (config['dateFormat'].Value == 'DDMM')
519 // config['dateFormat'].Value == 'auto', try to detect system setting
521 var day_ = dateArr[
1];
522 var month_ = dateArr[
2];
523 var year_ = dateArr[
3];
524 // make sure month is set properly
525 if (isNaN(parseInt(day_))) {
530 } else if (isNaN(parseInt(year_))) {
536 // make sure day and year are set properly
537 if (Number(day_)
> Number(year_))
542 return day + config['dateSeparator'].Value + month;
544 return month + config['dateSeparator'].Value + day;
547 function formatTime(date)
549 // date is a Date() object
550 date.setSeconds(
0); // we don't care about seconds
551 var time = date.toLocaleTimeString().replace(/[\.:]
00/, ''); // remove seconds from string
552 if (time.replace(/\./, ':').split(':')[
0].length <
2)
554 if (config['showNowAsText'].Value && date.getTime() == now.getTime())
555 time = '
<span class=
"now">' + config['nowText'].Value + '
</span>';
559 function updateData()
561 calcDaylightSaving();
563 // meetings have time
564 // 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
566 var meetingListFiltering = {
567 Type:'CalendarEntry',
569 StartRange: (new Date(now.getFullYear(), now.getMonth(), now.getDate(),
0,
0,
0)),
570 EndRange: (new Date(now.getFullYear(), now.getMonth() + config['monthRange'].Value, now.getDate(),
0,
0,
0))
573 var meetingResult = calendarService.IDataSource.GetList(meetingListFiltering);
574 var meetingList = meetingResult.ReturnValue;
576 // todos don't, they start on
00:
00 hrs., but should be visible anyway
577 // this will generate a list of passed todos. We have to check if they have been marked as
"done" yet
578 if (config['includeTodos'].Value) {
579 var todayTodoListFiltering = {
580 Type:'CalendarEntry',
583 StartRange: (new Date(now.getFullYear() -
1, now.getMonth(), now.getDate(),
0,
0,
0)),
584 EndRange: (new Date(now.getFullYear(), now.getMonth(), now.getDate(),
0,
0,
1))
587 var todayTodoResult = calendarService.IDataSource.GetList(todayTodoListFiltering);
588 var todayTodoList = todayTodoResult.ReturnValue;
589 var entryLists = [todayTodoList, meetingList];
591 var entryLists = [meetingList];
594 error('loading Calendar items list:' + e + ', line ' + e.line);
603 var entriesHtml = '
<table>';
607 max = ((panelNum ==
0) ? config['eventsPerWidget'].Value :
2 * config['eventsPerWidget'].Value);
609 max =
30; // we can display a lot more events in fullscreen mode
611 // the first outer loop iteration is for passed ToDos, the second loop is for all upcomming events (may also include ToDos)
612 for (var i=
0; counter < max && i < entryLists.length; i++) {
613 while (counter < max && (entry = entryLists[i].getNext()) != undefined) {
616 // output event info for debugging
618 'event: Id=' + entry.id +
619 ',Type=' + entry.Type +
620 ',Summary=' + entry.Summary +
621 ',Location=' + entry.Location +
622 ',Status=' + entry.Status +
623 ',StartTime=' + entry.StartTime +
624 ',EndTime=' + entry.EndTime +
625 ',InstanceStartTime=' + entry.InstanceStartTime +
626 ',InstanceEndTime=' + entry.InstanceEndTime
629 // we don't want ToDos when includeTodos == false or when they are completed
630 if (entry.Type == 'ToDo' && (entry.Status ==
"TodoCompleted" || !config['includeTodos'].Value)) {
631 console.info('skipping ' + entry.id );
636 // make sure that we don't include an event twice (useful for ToDos that might come up twice)
637 if (eventIds[entry.id] ==
1) {
638 console.info('skipped (already included) ' + entry.id);
642 eventIds[entry.id] =
1;
644 // summary can be undefined!
645 var Summary = ((entry.Summary == null) ? '' : entry.Summary);
646 if (entry.Type == 'Meeting' && entry.Location != '' && config['showLocation'].Value)
647 Summary += ', ' + entry.Location;
649 // fix by yves: determine start and end dates/times
650 entryStartTime = ((entry.InstanceStartTime == null) ? entry.StartTime : entry.InstanceStartTime);
651 entryEndTime = ((entry.InstanceEndTime == null) ? entry.EndTime : entry.InstanceEndTime);
653 // there can be ToDos that have no date at all!
654 if (entry.Type == 'ToDo' && entry.EndTime == null)
655 entryDate =
""; // this will cause parseDate(entryDate) to return null;
657 entryDate = ((entry.Type == 'ToDo') ? entryEndTime : entryStartTime); // ToDo's use their EndTime, the rest use StartTime
659 // Convert date/time string to Date object
660 var date = parseDate(entryDate);
661 console.info('date: ' + date);
662 var endDate = ((entryEndTime == null) ? null : parseDate(entryEndTime));
663 console.info('endDate: ' + endDate);
665 // check if meeting event has already passed
666 if (entry.Type == 'Meeting') {
667 var compareTime = ((endDate == null) ? date.getTime() : endDate.getTime());
668 if (now.getTime()
> compareTime) {
669 console.info('skipping Meeting (already passed) ' + entry.id);
671 eventIds[entry.id] =
0;
676 // check if anniversary passed (not sure why they are in the list, the query was only for today - nokia?)
677 if (entry.Type == 'Anniversary') {
678 var tmp = new Date(now.getFullYear(), now.getMonth(), now.getDate(),
0,
0,
0);
679 if (date.getTime() < tmp.getTime()) {
680 console.info('skipping Anniversary (already passed) ' + entry.id);
682 eventIds[entry.id] =
0;
687 // fix DayEvents end time. End times are off by
1 Second. It's possible that the event has already passed
688 if (entry.Type == 'DayEvent' && endDate != null) {
689 endDate.setMinutes(endDate.getMinutes() -
1);
690 console.info('fixing DayEvent endDate: ' + endDate);
691 if (now.getTime()
> endDate.getTime()) {
692 console.info('event already passed ' + entry.id);
694 eventIds[entry.id] =
0;
699 // check if the event is currently taking place
700 if (entryStartTime != null && entryEndTime != null && date != null && endDate != null) {
701 // check if we are between start and endtime
702 if ((date.getTime() < now.getTime()) && (now.getTime() < endDate.getTime())) {
703 date = now; // change appointment date/time to now
704 console.info('event is currently taking place: ' + date);
708 // skip events for the first panel in case this is the second one and we're not in fullscreen mode
709 if (mode ==
0 && panelNum ==
1 && counter < config['eventsPerWidget'].Value +
1) {
710 console.info('skipping (already in first widget) ' + entry.id);
714 // generate html output
715 entriesHtml += '
<tr><td><img class=
"icon" src=
"' + entry.Type + '.png" /></td>';
717 // some languages have very strange locale date formats, can't parse all those. Also some todos don't have dates at all.
718 entriesHtml += '
<td colspan=
"4"><span class=
"date">' + entryDate + '
</span> ';
720 var weekDay = date.toLocaleDateString().substr(
0,config['weekDayLength'].Value);
721 var time = formatTime(date);
722 var dateStr = formatDate(date, entryDate);
723 if (entry.Type == 'ToDo' || entry.Type == 'Anniversary' || entry.Type == 'DayEvent' || entry.Type == 'Reminder') {
724 if ((isToday(date) || isTomorrow(date)) && config['showTodayAsText'].Value) // show weekday if the date string is not text. looks odd otherwise
725 entriesHtml += '
<td colspan=
"4" width=
"1px"><span class=
"date">' + dateStr + '
</span> ';
727 entriesHtml += '
<td class=
"weekDay" width=
"1px">' + weekDay + '
</td><td width=
"1px" class=
"date">' + dateStr + '
</td><td colspan=
"2">';
728 } else if (entry.Type == 'Meeting') {
729 if (config['showCombinedDateTime'].Value) {
731 entriesHtml += '
<td width=
"1px" colspan=
"4"><span class=
"today">' + time + '
</span> ';
732 else if (isTomorrow(date))
733 entriesHtml += '
<td width=
"1px" colspan=
"4"><span class=
"tomorrow">' + dateStr + '
</span> <span class=
"time">' + time + '
</span> ';
735 entriesHtml += '
<td width=
"1px" class=
"weekDay">' + weekDay + '
</td><td width=
"1px" class=
"date">' + dateStr + '
</td><td colspan=
"2">';
737 if ((isToday(date) || isTomorrow(date)) && config['showTodayAsText'].Value)
738 entriesHtml += '
<td colspan=
"4" width=
"1px"><span class=
"today">' + dateStr + '
</span> <span class=
"time">' + time + '
</span> ';
740 entriesHtml += '
<td width=
"1px" class=
"weekDay">' + weekDay + '
</td><td width=
"1px" class=
"date">' + dateStr + '
</td><td width=
"1px" class=
"time">' + time + '
</td><td>';
744 entriesHtml += '
<span class=
"description">' + Summary + '
</span></td></tr>';
747 entriesHtml += '
</table>';
748 if (config['showNothingText'].Value && entriesHtml == '
<table></table>')
749 entriesHtml = '
<div style=
"width:295px; height:75px; text-align:center; line-height:75px; overflow:visible;">' + config['nothingText'].Value + '
</div>';
750 if (cacheEntriesHtml != entriesHtml) {
752 document.getElementById('calendarList').innerHTML = entriesHtml;
754 document.getElementById('fullscreenCalendarList').innerHTML = entriesHtml;
755 cacheEntriesHtml = entriesHtml;
758 error('displaying list:' + e + ', line ' + e.line);
763 function updateScreen()
765 // check if opening fullscreen
766 if( window.innerHeight
> 91 && mode ==
0) {
768 cacheEntriesHtml = '';
769 document.getElementById('body').style.backgroundImage =
"";
772 else if (window.innerHeight <=
91 && mode !=
0) {
774 cacheEntriesHtml = '';
784 function launchCalendar()
787 widget.openApplication(config['calendarApp'].Value,
"");
790 error('starting Calendar App');
798 // call calendar service
799 calendarService = device.getServiceObject(
"Service.Calendar",
"IDataSource");
801 error('loading Calendar service');
809 requestNotification();
810 window.setInterval('updateData()',
1000 *
60 * config['updateDataInterval'].Value);
815 if (config['useBackgroundImage'].Value)
816 // check for screen rotation every
1 secs
817 window.setInterval('updateScreen()',
1000 *
1);
820 function createMenu()
822 window.menu.setLeftSoftkeyLabel(
"",null);
823 window.menu.setRightSoftkeyLabel(
"",null);
825 var menuSettings = new MenuItem(
"Settings", id++);
826 var menuCallApp = new MenuItem(
"Open Calendar App", id++);
827 var menuAbout = new MenuItem(
"About", id++);
828 menuSettings.onSelect = showSettings;
829 menuAbout.onSelect = showAbout;
830 menuCallApp.onSelect = launchCalendar;
832 window.menu.append(menuCallApp);
833 window.menu.append(menuSettings);
834 window.menu.append(menuAbout);
837 function showSettings()
840 document.getElementById(
"homescreenView").style.display =
"none";
841 document.getElementById(
"fullscreenView").style.display =
"none";
842 document.getElementById(
"aboutView").style.display =
"none";
843 document.getElementById(
"settingsView").style.display =
"block";
844 document.onclick = null;
846 window.menu.setLeftSoftkeyLabel(
"Save", function()
848 for (var key in config) {
849 if (config[key].Type == 'String')
850 config[key].Value = document.forms[
0].elements[
"settings." + key].value;
851 else if (config[key].Type == 'Int') {
852 config[key].Value = parseInt(document.forms[
0].elements[
"settings." + key].value);
853 if (config[key].Value <
0)
854 config[key].Value = config[key].Default;
856 else if (config[key].Type == 'Bool')
857 config[key].Value = document.forms[
0].elements[
"settings." + key].checked;
858 else if (config[key].Type == 'UID')
859 config[key].Value = parseInt(document.forms[
0].elements[
"settings." + key].value);
860 else if (config[key].Type == 'Enum') {
861 config[key].Value = document.forms[
0].elements[
"settings." + key].value;
862 if (config[key].ValidValues.indexOf(config[key].Value) == -
1)
863 config[key].Value = config[key].Default;
874 window.menu.setRightSoftkeyLabel(
"Cancel", function()
880 var settingsHtml = '
<form>';
881 for (var key in config) {
882 if (config[key].Type == 'String')
883 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 />';
884 else if (config[key].Type == 'Int')
885 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 />';
886 else if (config[key].Type == 'Bool')
887 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 />';
888 else if (config[key].Type == 'UID')
889 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 />';
890 else if (config[key].Type == 'Enum') {
891 settingsHtml += '
<table><tr><td>' + config[key].Name + '
<br /><select name=
"settings.' + key + '" size=
"1">';
892 for(var i =
0; i < config[key].ValidValues.length; i++)
893 settingsHtml += '
<option label=
"' + config[key].ValidValues[i] + '"' + (config[key].Value == config[key].ValidValues[i] ? '
selected=
"selected"' : '') + '
>' + config[key].ValidValues[i] + '
</option>';
894 settingsHtml += '
</select></div></td>' + printHintBox(config[key].Info) + '
<hr />';
897 settingsHtml += '
<input name=
"reset" type=
"button" value=
"Restore Defaults" onclick=
"javascript:restoreDefaultSettings();showSettings();" />';
898 settingsHtml += '
</form>';
899 document.getElementById(
"settingsList").innerHTML = settingsHtml;
902 function changeCssClass(classname, properties)
904 for(var i =
0; i < document.styleSheets[
0]['cssRules'].length; i++)
906 if (document.styleSheets[
0]['cssRules'][i].selectorText == classname) {
907 document.styleSheets[
0].deleteRule(i);
908 document.styleSheets[
0].insertRule(classname + ' { ' + properties + ' }', document.styleSheets[
0]['cssRules'].length);
914 function updateCssClasses()
916 for(var key in config) {
917 changeCssClass(config[key].Name, config[key].Value);
921 function restoreDefaultSettings()
923 for (var key in config)
924 config[key].Value = config[key].Default;
927 function loadSettings()
929 for (var key in config) {
930 if (widget.preferenceForKey(key)) {
931 if (config[key].Type == 'Int')
932 config[key].Value = Number(widget.preferenceForKey(key));
933 else if (config[key].Type == 'String')
934 config[key].Value = widget.preferenceForKey(key);
935 else if (config[key].Type == 'Bool')
936 config[key].Value = (widget.preferenceForKey(key) == 'true')
937 else if (config[key].Type == 'Enum')
938 config[key].Value = widget.preferenceForKey(key);
939 else if (config[key].Type == 'UID')
940 config[key].Value = Number(widget.preferenceForKey(key));
943 config[key].Value = config[key].Default;
948 function saveSettings()
950 for (var key in config) {
951 if (config[key].Type == 'Int')
952 widget.setPreferenceForKey(config[key].Value.toString(), key);
953 else if (config[key].Type == 'String')
954 widget.setPreferenceForKey(config[key].Value, key);
955 else if (config[key].Type == 'Bool')
956 widget.setPreferenceForKey(config[key].Value ? 'true' : 'false', key);
957 else if (config[key].Type == 'Enum')
958 widget.setPreferenceForKey(config[key].Value, key);
959 else if (config[key].Type == 'UID')
960 widget.setPreferenceForKey(config[key].Value.toString(), key);
964 function toggleVisibility(elementId)
966 if (document.getElementById(elementId).style.display ==
"none")
967 document.getElementById(elementId).style.display =
"block";
969 document.getElementById(elementId).style.display =
"none";
973 function printHintBox(text)
976 return '
<td width=
"1%" align=
"right" onclick=
"javascript:toggleVisibility(\'info' + uniqueId + '\')">Help
</td></tr></table>'+
977 '
<div class=
"settingsInfo" id=
"info' + uniqueId + '">' + text + '
</div>';
983 document.getElementById(
"homescreenView").style.display =
"none";
984 document.getElementById(
"fullscreenView").style.display =
"none";
985 document.getElementById(
"aboutView").style.display =
"block";
986 document.getElementById(
"settingsView").style.display =
"none";
987 document.onclick = null;
989 window.menu.setLeftSoftkeyLabel(
" ", function(){});
990 window.menu.setRightSoftkeyLabel(
"Back", function()
996 //document.getElementById(
"aboutView").innerHTML = 'aboutView';
997 document.getElementById(
"name").innerHTML =
"Coming Next " + version;
1000 function updateFullscreen()
1004 function showFullscreen()
1006 document.getElementById(
"homescreenView").style.display =
"none";
1007 document.getElementById(
"fullscreenView").style.display =
"block";
1008 document.getElementById(
"aboutView").style.display =
"none";
1009 document.getElementById(
"settingsView").style.display =
"none";
1010 document.getElementById('body').className =
"backgroundFullscreen";
1011 document.onclick = launchCalendar;
1016 function updateHomescreen()
1018 if (config['useBackgroundImage'].Value) {
1019 // check for screen rotation
1020 if (orientation != 'portrait' && screen.width ==
360 && screen.height ==
640) {
1021 window.widget.prepareForTransition(
"fade");
1022 orientation = 'portrait';
1023 document.getElementById('body').style.backgroundImage = 'url(background_' + orientation + '.png)';
1024 document.getElementById('body').style.backgroundColor = 'none';
1025 window.widget.performTransition();
1026 } else if (orientation != 'landscape' && screen.width ==
640 && screen.height ==
360) {
1027 window.widget.prepareForTransition(
"fade");
1028 orientation = 'landscape';
1029 document.getElementById('body').style.backgroundImage = 'url(background_' + orientation + '.png)';
1030 document.getElementById('body').style.backgroundColor = 'none';
1031 window.widget.performTransition();
1033 else if (document.getElementById('body').style.backgroundImage ==
"")
1035 document.getElementById('body').style.backgroundImage = 'url(background_' + orientation + '.png)';
1040 function showHomescreen()
1042 document.getElementById(
"homescreenView").style.display =
"block";
1043 document.getElementById(
"fullscreenView").style.display =
"none";
1044 document.getElementById(
"aboutView").style.display =
"none";
1045 document.getElementById(
"settingsView").style.display =
"none";
1046 document.getElementById('body').className =
"background";
1047 document.onclick = null;
1053 <style type=
"text/css">
1054 table { margin:
0px; padding:
0px; border-spacing:
0px; }
1055 td { padding:
0px
5px
0px
0px; white-space:nowrap; overflow:hidden; }
1056 hr { color:#ffffff; background-color:#ffffff; height:
1px; text-align:left; border-style:none; }
1057 .settingsInfo { display:none; font-style:italic; }
1058 .title { font-weight:bold; font-size:
14pt; }
1059 .textInput { width:
90%; }
1060 #homescreenView { width:
315px; height:
91px; overflow:hidden; }
1061 #calendarList { position:absolute; left:
10px; top:
4px; width:
295px; height:
75px; overflow:hidden; }
1062 #name { text-align:center; }
1063 #appicon { display: block; margin-left: auto; margin-right: auto; margin-top:
50px; }
1064 #smallappicon { width:
22px; height:
22px; margin-right:
10px; float:left; }
1069 <body id=
"body" class=
"background">
1070 <div id=
"homescreenView">
1071 <div id=
"calendarList"></div>
1073 <div id=
"fullscreenView" style=
"display:none;">
1074 <img src=
"Icon.png" id=
"smallappicon">
1075 <h1 class=
"title">Coming Next
</h1>
1077 <div id=
"fullscreenCalendarList">loading...
</div>
1079 <div id=
"settingsView" style=
"display:none">
1080 <img src=
"Icon.png" id=
"smallappicon">
1081 <h1 class=
"title">Settings
</h1>
1083 <div id=
"settingsList"></div>
1085 <div id=
"aboutView" style=
"display:none">
1086 <img src=
"Icon.png" id=
"appicon">
1087 <h1 id=
"name">Coming Next
</h1>
1089 <p>Created by Dr. Cochambre and Michael Prager.
</p>
1090 <p>This software is open source and licensed under the GPLv3.
</p>
1091 <p>Visit https://sourceforge.net/projects/comingnext/ for free updates.
</p>