X-Git-Url: https://code.delx.au/comingnext/blobdiff_plain/31bc03fb8ace68ddb9fce39f60b48219ba970c9e..2de56af5f6389b2bf02d40ff58cfd2f2be40188e:/comingNext/index.html diff --git a/comingNext/index.html b/comingNext/index.html index 5730519..d66fd29 100644 --- a/comingNext/index.html +++ b/comingNext/index.html @@ -17,6 +17,7 @@ .now { } .description { } .icon { } +.overdue {} @@ -27,6 +28,7 @@ var config = { monthRange: { Type: 'Int', Default: 2, Value: 2,}, includeTodos: { Type: 'Bool', Default: true, Value: true,}, useBackgroundImage: { Type: 'Bool', Default: true, Value: true,}, + backgroundImageLocation: { Type: 'Enum', Default: 'internal', Value: 'internal', ValidValues: ['internal', 'external']}, showCombinedDateTime: { Type: 'Bool', Default: false, Value: false,}, showLocation: { Type: 'Bool', Default: true, Value: true,}, showTodayAsText: { Type: 'Bool', Default: true, Value: true,}, @@ -34,6 +36,8 @@ var config = { tomorrowText: { Type: 'String', Default: getLocalizedText('settings.default.tomorrowText'), Value: getLocalizedText('settings.default.tomorrowText'),}, showNowAsText: { Type: 'Bool', Default: true, Value: true,}, nowText: { Type: 'String', Default: getLocalizedText('settings.default.nowText'), Value: getLocalizedText('settings.default.nowText'),}, + markOverdueTodos: { Type: 'Bool', Default: true, Value: true,}, + overdueText: {Type: 'String', Default: getLocalizedText('settings.default.overdueText'), Value: getLocalizedText('settings.default.overdueText'),}, dateSeparator: { Type: 'String', Default: getLocalizedText('settings.default.dateSeparator'), Value: getLocalizedText('settings.default.dateSeparator'),}, dateFormat: { Type: 'Enum', Default: 'auto', Value: 'auto', ValidValues: ['auto', 'DDMM', 'MMDD'],}, weekDayLength: { Type: 'Int', Default: 2, Value: 2,}, @@ -43,6 +47,7 @@ var config = { showNothingText: { Type: 'Bool', Default: true, Value: true,}, nothingText: { Type: 'String', Default: getLocalizedText('settings.default.nothingText'), Value: getLocalizedText('settings.default.nothingText'),}, enableDaylightSaving: { Type: 'Bool', Default: true, Value: true,}, + daylightSavingOffset: { Type: 'Int', Default: 1, Value: 1,}, hideWidgetOnCalendarOpen: { Type: 'Bool', Default: false, Value: false,}, cssStyle_background: { Type: 'String', Default: 'color:#ffffff; background-color:#000000', Value: 'color:#ffffff; background-color:#000000',}, cssStyle_backgroundFullscreen: { Type: 'String', Default: 'color:#ffffff; background-color:#000000', Value: 'color:#ffffff; background-color:#000000',}, @@ -54,25 +59,46 @@ var config = { cssStyle_now: { Type: 'String', Default: 'color:#ff00ff', Value: 'color:#ff00ff',}, cssStyle_description: { Type: 'String', Default: '', Value: '',}, cssStyle_icon: { Type: 'String', Default: 'width:15px; height:15px', Value: 'width:15px; height:15px',}, + cssStyle_overdue: { Type: 'String', Default: 'color:#ffff00', Value: 'color:#ffff00',}, } + //------------------------------------------------------- // Nothing of interest from here on... //------------------------------------------------------- var panelNum = 0; // use 1 for second panel -var version = "1.25"; +var version = "1.29"; +var versionURL = "http://comingnext.sourceforge.net/version.xml"; var calendarService = null; var cacheEntriesHtml = []; var months_translated = []; var orientation = ''; var now = new Date(); -var mode = 0; // 0 = homescreen, 1 = fullscreen, 2 = settings, 3 = about +var mode = 0; // 0 = homescreen, 1 = fullscreen, 2 = settings, 3 = about, 4 = check for update +var reqV = null; +var settingsCalEntryId = null; +var settingsCache = null; +var notificationRequest1; +var notificationRequest2; +var calendarList = []; // vars for daylight saving time -var daylightsavingWinter = 0; -var daylightsavingSummer = 0; -var summertime = false; +var summertime = false; // true, if current date is in summer, false if in winter +var daylightSavingDates = new Object(); // caches calculated DST winter and summer time shift dates + +// this is a list of data fields a calendar event can have +var entryFields = [ + "id", + "Type", + "Summary", + "Location", + "Status", + "StartTime", + "EndTime", + "InstanceStartTime", + "InstanceEndTime" +]; window.onload = init; window.onresize = updateScreen; @@ -101,43 +127,48 @@ function subToSunday(myDate, year, days, prevMonthDays) days = isLeapYear(year) ? --days : days; return days; } - -function calcDaylightSaving() + +function isSummertime(curDate) { - var thisYearS = new Date(now.getFullYear(), 3, 0, 0, 0, 0 ); - var thisYearW = new Date(now.getFullYear(), 10, 0, 0, 0, 0 ); - var nextYearS = new Date(now.getFullYear() + 1, 3, 0, 0, 0, 0 ); - var nextYearW = new Date(now.getFullYear() + 1, 10, 0, 0, 0, 0 ); var summer = false; var winter = false; - - thisYearSDays = nextYearSDays = 90; - thisYearWDays = nextYearWDays = 304; - - thisYearSDays = calcLeapYear(now.getFullYear(), thisYearSDays); - thisYearWDays = calcLeapYear(now.getFullYear(), thisYearWDays); - nextYearSDays = calcLeapYear(now.getFullYear() + 1, nextYearSDays); - nextYearWDays = calcLeapYear(now.getFullYear() + 1, nextYearWDays); - - thisYearSDays = subToSunday(thisYearS, now.getFullYear(), thisYearSDays, 59); - thisYearWDays = subToSunday(thisYearW, now.getFullYear(), thisYearWDays, 273); - nextYearSDays = subToSunday(nextYearS, now.getFullYear() + 1, nextYearSDays, 59); - nextYearWDays = subToSunday(nextYearW, now.getFullYear() + 1, nextYearWDays, 273); - - daylightsavingSummer = new Date (now.getFullYear(), 03-1, thisYearSDays, 2, 0, 0); - daylightsavingWinter = new Date (now.getFullYear(), 10-1, thisYearWDays, 2, 0, 0); - if (daylightsavingSummer < now) { - daylightsavingSummer = new Date (now.getFullYear()+1, 03-1, nextYearSDays, 2, 0, 0); - var summer = true; - } - if (daylightsavingWinter < now) { - daylightsavingWinter = new Date (now.getFullYear()+1, 10-1, nextYearWDays, 2, 0, 0); - var winter = true; + + // if we already calculated DST summer and winter time dates for this year, use cached values + var dst = daylightSavingDates[curDate.getFullYear()]; + if (!dst) { + var thisYearS = new Date(curDate.getFullYear(), 3, 0, 0, 0, 0 ); + var thisYearW = new Date(curDate.getFullYear(), 10, 0, 0, 0, 0 ); + var nextYearS = new Date(curDate.getFullYear() + 1, 3, 0, 0, 0, 0 ); + var nextYearW = new Date(curDate.getFullYear() + 1, 10, 0, 0, 0, 0 ); + + thisYearSDays = nextYearSDays = 90; + thisYearWDays = nextYearWDays = 304; + + thisYearSDays = calcLeapYear(curDate.getFullYear(), thisYearSDays); + thisYearWDays = calcLeapYear(curDate.getFullYear(), thisYearWDays); + nextYearSDays = calcLeapYear(curDate.getFullYear() + 1, nextYearSDays); + nextYearWDays = calcLeapYear(curDate.getFullYear() + 1, nextYearWDays); + + thisYearSDays = subToSunday(thisYearS, curDate.getFullYear(), thisYearSDays, 59); + thisYearWDays = subToSunday(thisYearW, curDate.getFullYear(), thisYearWDays, 273); + nextYearSDays = subToSunday(nextYearS, curDate.getFullYear() + 1, nextYearSDays, 59); + nextYearWDays = subToSunday(nextYearW, curDate.getFullYear() + 1, nextYearWDays, 273); + + dst = { + Summer: new Date (curDate.getFullYear(), 03-1, thisYearSDays, 2, 0, 0), + Winter: new Date (curDate.getFullYear(), 10-1, thisYearWDays, 2, 0, 0), + } + daylightSavingDates[curDate.getFullYear()] = dst; } + + if (dst.Summer < curDate) + summer = true; + if (dst.Winter < curDate) + winter = true; if (summer && !winter) - summertime = true; + return true; else - summertime = false; + return false; } function error(message) @@ -146,25 +177,28 @@ function error(message) document.getElementById("calendarList").innerHTML = 'Error: ' + message; } -function isToday(date) +function areDatesEqual(date1, date2) { - if (date.getDate() == now.getDate() && date.getMonth() == now.getMonth()) - return true; - return false; + return (date1.getFullYear() == date2.getFullYear() && + date1.getMonth() == date2.getMonth() && + date1.getDate() == date2.getDate()); } function isTomorrow(date) { - if ((date.getDate() == now.getDate() + 1 && date.getMonth() == now.getMonth()) || - (date.getDate() == 0 && date.getMonth() == now.getMonth() + 1) || - (date.getDate() == 0 && date.getMonth() == now.getMonth() + 1 && date.getYear() == now.getYear() + 1)) - return true; - return false; + // tommorow = now + 1 day + // ToDo: some days can be shorter as 24 hours(daylight saving change day) + return areDatesEqual(date, new Date (now.getTime() + 24*60*60*1000)); +} + +function isToday(date) +{ + return areDatesEqual(date, now); } function collectLocales() { - var tmpyear = ((panelNum == 0) ? 2000 : 2001); + var tmpyear = 2000 + panelNum; var month = 0; if (months_translated.length > 0) @@ -266,9 +300,23 @@ function requestNotification() criteria.Type = "CalendarEntry"; try { - var result = calendarService.IDataSource.RequestNotification(criteria, callback); - if (result.ErrorCode) - error('loading Calendar items list'); + notificationRequest1 = calendarService.IDataSource.RequestNotification(criteria, callback); + if (notificationRequest1.ErrorCode) + error('requestNotification failed with error code ' + notificationRequest1.ErrorCode); + } catch (e) { + error("requestNotification: " + e + ', line ' + e.line); + } + + var criteria2 = new Object(); + criteria2.Type = "CalendarEntry"; + criteria2.Filter = new Object(); + criteria2.Filter.LocalIdList = new Array(); + criteria2.Filter.LocalIdList[0] = settingsCalEntryId; + + try { + notificationRequest2 = calendarService.IDataSource.RequestNotification(criteria2, settingsCallback); + if (notificationRequest2.ErrorCode) + error('requestNotification failed with error code ' + notificationRequest2.ErrorCode); } catch (e) { error("requestNotification: " + e + ', line ' + e.line); } @@ -276,9 +324,16 @@ function requestNotification() function callback(transId, eventCode, result) { + console.info("callback(): panelNum: %d transId: %d eventCode: %d result.ErrorCode: %d", panelNum, transId, eventCode, result.ErrorCode); updateData(); } +function settingsCallback(transId, eventCode, result) +{ + console.info("settingsCallback(): panelNum: %d transId: %d eventCode: %d result.ErrorCode: %d", panelNum, transId, eventCode, result.ErrorCode); + loadSettings(); +} + function parseDate(dateString) { /* @@ -332,18 +387,26 @@ function parseDate(dateString) if (dateArr.length == 6 && dateArr[5].toLowerCase() == 'am' && hours == 12) hours = 0; - console.info('year=' + year + ' month=' + month + ' day=' + day + ' hours=' + hours + ' minutes=' + minutes+ ' seconds=' + seconds); - + var result = new Date(year, month - 1, day, hours, minutes, seconds); + // take care of daylight saving time if (config['enableDaylightSaving'].Value) { - var date = new Date(year, month - 1, day, hours, minutes, seconds); - if (summertime && date > daylightsavingWinter && date < daylightsavingSummer) - hours -= 1; - else if (!summertime && date > daylightsavingSummer && date < daylightsavingWinter) - hours += 1; + + // determine if date is in summer or winter time + var dateSummerTime = isSummertime(result); + + // work around bug in Nokias calendar api resulting in dates within a different DST to be off by 1 hour + if (summertime && !dateSummerTime) { + result = new Date(result.getTime() - 1000 * 60 * 60 * config['daylightSavingOffset'].Value); // -1 hour + console.info('parseDate(): fixing time -1h: ' + result); + } + else if (!summertime && dateSummerTime) { + result = new Date(result.getTime() + 1000 * 60 * 60 * config['daylightSavingOffset'].Value); // +1 hour + console.info('parseDate(): fixing time +1h: ' + result); + } } - return new Date(year, month - 1, day, hours, minutes, seconds); + return result; } // 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" @@ -417,36 +480,50 @@ function formatTime(date) function updateData() { console.info('updateData()'); - calcDaylightSaving(); try { // meetings have time // 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 now = new Date(); - var meetingListFiltering = { - Type:'CalendarEntry', - Filter:{ - StartRange: (new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0)), - EndRange: (new Date(now.getFullYear(), now.getMonth() + config['monthRange'].Value, now.getDate(), 0, 0, 0)) + summertime = isSummertime(now); // cache summer time info for today + var meetingList = []; + for(var i=0; i < calendarList.length; i++) { + var meetingListFiltering = { + Type:'CalendarEntry', + Filter:{ + CalendarName: calendarList[i], + StartRange: (new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0)), + EndRange: (new Date(now.getFullYear(), now.getMonth() + config['monthRange'].Value, now.getDate(), 0, 0, 0)) + } } + var meetingResult = calendarService.IDataSource.GetList(meetingListFiltering); + if (meetingResult.ErrorCode != 0) + throw("Error fetching calendar data: " + meetingResult.ErrorCode + ': ' + meetingResult.ErrorMessage); + var list = meetingResult.ReturnValue; + meetingList = meetingList.concat(listToArray(list)); } - var meetingResult = calendarService.IDataSource.GetList(meetingListFiltering); - if (meetingResult.ErrorCode != 0) - throw("Error fetching calendar data: " + meetingResult.ErrorCode + ': ' + meetingResult.ErrorMessage); - var meetingList = meetingResult.ReturnValue; + console.info("updateData(): meetingList.sort()"); + meetingList.sort(sortCalendarEntries); // todos don't, they start on 00:00 hrs., but should be visible anyway // this will generate a list of passed todos. We have to check if they have been marked as "done" yet if (config['includeTodos'].Value) { - var todayTodoListFiltering = { - Type:'CalendarEntry', - Filter:{ - Type: 'ToDo', - StartRange: (new Date(now.getFullYear() - 1, now.getMonth(), now.getDate(), 0, 0, 0)), - EndRange: (new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 1)) + var todayTodoList = []; + for(var i=0; i < calendarList.length; i++) { + var todayTodoListFiltering = { + Type:'CalendarEntry', + Filter:{ + CalendarName: calendarList[i], + Type: 'ToDo', + StartRange: (new Date(now.getFullYear() - 1, now.getMonth(), now.getDate(), 0, 0, 0)), + EndRange: (new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 1)) + } } + var todayTodoResult = calendarService.IDataSource.GetList(todayTodoListFiltering); + var list = todayTodoResult.ReturnValue; + todayTodoList = todayTodoList.concat(listToArray(list)); } - var todayTodoResult = calendarService.IDataSource.GetList(todayTodoListFiltering); - var todayTodoList = todayTodoResult.ReturnValue; + console.info("updateData(): todayTodoList.sort()"); + todayTodoList.sort(sortCalendarEntries); var entryLists = [todayTodoList, meetingList]; } else { var entryLists = [meetingList]; @@ -461,31 +538,56 @@ function updateData() var counter = 0; var entryDate = ''; var dateArr = []; - var entriesHtml = '
'; @@ -581,7 +693,10 @@ function updateData() var weekDay = date.toLocaleDateString().substr(0,config['weekDayLength'].Value); var time = formatTime(date); var dateStr = formatDate(date, entryDate); - if (entry.Type == 'ToDo' || entry.Type == 'Anniversary' || entry.Type == 'DayEvent' || entry.Type == 'Reminder') { + if (entry.Type == 'ToDo' && overdue && config['markOverdueTodos'].Value) { + dateStr = '' + config['overdueText'].Value + ''; + entriesHtml += ' | ' + dateStr + ' '; + } else if (entry.Type == 'ToDo' || entry.Type == 'Anniversary' || entry.Type == 'DayEvent' || entry.Type == 'Reminder') { if ((isToday(date) || isTomorrow(date)) && config['showTodayAsText'].Value) // show weekday if the date string is not text. looks odd otherwise entriesHtml += ' | ' + dateStr + ' '; else @@ -662,25 +777,35 @@ function init() try { // call calendar service - calendarService = device.getServiceObject("Service.Calendar", "IDataSource"); + if (device != "undefined") + calendarService = device.getServiceObject("Service.Calendar", "IDataSource"); + else + throw('device object does not exist'); } catch(e) { - error('loading Calendar service'); + error('loading Calendar service: ' + e + ', line ' + e.line); return; } + calendarList = listCalendars(); loadSettings(); - updateCssClasses(); collectLocales(); //updateData(); requestNotification(); window.setInterval('updateData()', 1000 * 60 * config['updateDataInterval'].Value); + document.getElementById("settingsTitle").innerHTML = getLocalizedText('menu.settings'); - mode = 0; - showHomescreen(); + if (window.innerHeight > 91) { + mode = 0; // we're starting fullscreen, we set mode to homescreen in order to let updateScreen() do all the work for us + } + else { + mode = 1; + } + console.info("init(): updateScreen()"); updateScreen(); if (config['useBackgroundImage'].Value) // check for screen rotation every 1 secs window.setInterval('updateScreen()', 1000 * 1); + console.info("init(): finished..."); } function createMenu() @@ -690,22 +815,23 @@ function createMenu() var id = 0; var menuSettings = new MenuItem(getLocalizedText('menu.settings'), id++); var menuCallApp = new MenuItem(getLocalizedText('menu.openCalendarApp'), id++); + var menuUpdate = new MenuItem(getLocalizedText('menu.update'), id++); var menuAbout = new MenuItem(getLocalizedText('menu.about'), id++); menuSettings.onSelect = showSettings; menuAbout.onSelect = showAbout; menuCallApp.onSelect = launchCalendar; + menuUpdate.onSelect = showUpdate; window.menu.clear(); window.menu.append(menuCallApp); window.menu.append(menuSettings); + window.menu.append(menuUpdate); window.menu.append(menuAbout); } function showSettings() { mode = 2; - document.getElementById("homescreenView").style.display = "none"; - document.getElementById("fullscreenView").style.display = "none"; - document.getElementById("aboutView").style.display = "none"; + hideViews(); document.getElementById("settingsView").style.display = "block"; document.onclick = null; @@ -745,8 +871,12 @@ function showSettings() var settingsHtml = ' |