]> code.delx.au - comingnext/blobdiff - comingNext/index.html
fixed help button on settings page require double tap (bug no. 3302891)
[comingnext] / comingNext / index.html
index 10e23093fe9bf031da13f6d5115dbd7c34d07a1a..f30cb7d77a95fb9ebbc17fd69b41b0d55a7ed599 100644 (file)
@@ -83,11 +83,12 @@ var config = {
 // Nothing of interest from here on...\r
 //-------------------------------------------------------\r
 var panelNum = 0; // use 1 for second panel\r
-var version = "1.32";\r
+var version = "1.37";\r
 var versionURL = "http://comingnext.sourceforge.net/version.xml";\r
 var calendarService = null;\r
 var cacheEntriesHtml = [];\r
 var months_translated = [];\r
+var weekdays_translated = [];\r
 var orientation = '';\r
 var now = new Date();\r
 var mode = 0; // 0 = homescreen, 1 = fullscreen, 2 = settings, 3 = about, 4 = check for update\r
@@ -104,6 +105,9 @@ var lastReloadTime = null; // last time we fetched calendar data
 var reloadInterval = 6 * 60 * 60 * 1000; // = 6 hours; time interval for reloading calendar data\r
 var errorOccured = false;\r
 var entryLists = null; // stores all fetched calendar entries until data is refreshed\r
+var statupSuccessful = false; // indicates if everything started up wihtout errors. If we detect an error after that, it might just be a temporary problem e.g. by a backup process.\r
+var use12hoursTimeFormat = false; // defines how time should be formated: 19:00 or 07:00 pm\r
+var timeFormatSeparator = ":"; // format time 19:00 or 19.00 depending on system setting\r
 \r
 // vars for daylight saving time\r
 var summertime = false; // true, if current date is in summer, false if in winter\r
@@ -240,7 +244,27 @@ function collectLocales()
                try {\r
                        var result = calendarService.IDataSource.Add(criteria);\r
                        if (result.ErrorCode)\r
-                               error(result.ErrorMessage);\r
+                               throw(result.ErrorMessage);\r
+               } catch (e) {\r
+                       error("collectLocales: " + e + ', line ' + e.line);\r
+               }\r
+       }\r
+       for (weekday = 0; weekday < 7; weekday++) {\r
+               var startDate = new Date(2000, 0, 2 + weekday); // date that we know for sure is a sunday\r
+\r
+               var item = new Object();\r
+               item.Type = "DayEvent";\r
+               item.StartTime = startDate;\r
+               item.Summary = "__weekday_temp" + weekday;\r
+\r
+               var criteria = new Object();\r
+               criteria.Type = "CalendarEntry";\r
+               criteria.Item = item;\r
+\r
+               try {\r
+                       var result = calendarService.IDataSource.Add(criteria);\r
+                       if (result.ErrorCode)\r
+                               throw(result.ErrorMessage);\r
                } catch (e) {\r
                        error("collectLocales: " + e + ', line ' + e.line);\r
                }\r
@@ -258,13 +282,11 @@ function collectLocales()
                        }\r
                }\r
                var result = calendarService.IDataSource.GetList(listFiltering);\r
-               if (result.ErrorCode) {\r
-                       error(result.ErrorMessage);\r
-                       return;\r
-               }\r
+               if (result.ErrorCode)\r
+                       throw(result.ErrorMessage);\r
                var list = result.ReturnValue;\r
        } catch(e) {\r
-               error(e + ', line ' + e.line);\r
+               error("collectLocales: " + e + ', line ' + e.line);\r
                return;\r
        }\r
        var ids = new Array();\r
@@ -274,7 +296,7 @@ function collectLocales()
                var dateArr = [];\r
 \r
                while (list && (entry = list.getNext()) != undefined) {\r
-                       dateArr = entry.StartTime.replace(/,/g,'').replace(/\./g,':').replace(/  /g,' ').split(' ');\r
+                       dateArr = (entry.StartTime + '').replace(/,/g,'').replace(/\./g,':').replace(/  /g,' ').split(' ');\r
                        var day = dateArr[1];\r
                        var month = dateArr[2];\r
                        var year = dateArr[3];\r
@@ -296,7 +318,44 @@ function collectLocales()
                        counter++;\r
                }\r
        } catch(e) {\r
-               error(e + ', line ' + e.line);\r
+               error("collectLocales: " + e + ', line ' + e.line);\r
+               return;\r
+       }\r
+       try {\r
+               var startTime = new Date(2000,0,2);\r
+               var endTime = new Date(2000,0,9);\r
+               var listFiltering = {\r
+                       Type:'CalendarEntry', \r
+                       Filter:{\r
+                               StartRange: startTime,\r
+                               EndRange: endTime,\r
+                               SearchText: '__weekday_temp',\r
+                               Type: 'DayEvent'\r
+                       }\r
+               }\r
+               var result = calendarService.IDataSource.GetList(listFiltering);\r
+               if (result.ErrorCode)\r
+                       throw(result.ErrorMessage);\r
+               var weekdaylist = result.ReturnValue;\r
+       } catch(e) {\r
+               error("collectLocales: " + e + ', line ' + e.line);\r
+               return;\r
+       }\r
+       try {\r
+               var entry;\r
+               var counter2 = 0;\r
+               var curWeekday = "";\r
+\r
+               while (weekdaylist && (entry = weekdaylist.getNext()) != undefined) {\r
+                       detectTimeFormat(entry.StartTime + '');\r
+                       curWeekday = (entry.StartTime + '').split(',')[0];\r
+                       log(entry.StartTime + ' -> ' + curWeekday + ' ' + counter2);\r
+                       ids[counter + counter2] = entry.id;\r
+                       weekdays_translated[counter2] = curWeekday;\r
+                       counter2++;\r
+               }\r
+       } catch(e) {\r
+               error("collectLocales: " + e + ', line ' + e.line);\r
                return;\r
        }\r
        log(ids);\r
@@ -309,13 +368,26 @@ function collectLocales()
 \r
                var result = calendarService.IDataSource.Delete(criteria);\r
                if (result.ErrorCode)\r
-                       error(result.ErrorMessage);\r
+                       throw(result.ErrorMessage);\r
        } catch(e) {\r
                error('deleting temp calendar entries:' + e + ', line ' + e.line);\r
                return;\r
        }\r
 }\r
 \r
+function stringEndsWith(str, suffix)\r
+{\r
+       return str.indexOf(suffix, str.length - suffix.length) !== -1;\r
+}\r
+\r
+// detects the system's current time format by parsing a native calendar timestamp (this is the only reliable formating across all devices and firmwares)\r
+function detectTimeFormat(localeTimeString)\r
+{\r
+       localeTimeString = localeTimeString.toLowerCase();\r
+       use12hoursTimeFormat = stringEndsWith(localeTimeString, "am") || stringEndsWith(localeTimeString, "pm");\r
+       timeFormatSeparator = localeTimeString.indexOf(":") != -1 ? ":" : ".";\r
+}\r
+\r
 function requestNotification()\r
 {\r
        var criteria = new Object();\r
@@ -385,49 +457,58 @@ function parseDate(dateString)
        Wednesday,  2009 August, 28 8.00.00 pm\r
        Wednesday,  2009 August, 28 08:00:00 PM\r
        */\r
+       var result = null;\r
 \r
-       if (dateString == "" || dateString == null)\r
-               return null;\r
-       var dateArr = dateString.replace(/,/g,'').replace(/\./g,':').replace(/  /g,' ').split(' ');\r
-       if (dateArr.length != 5 && dateArr.length != 6)\r
-               return null;\r
-\r
-       // parse date\r
-       var weekDay = dateArr[0];\r
-       var day = dateArr[1];\r
-       var month = dateArr[2];\r
-       var year = dateArr[3];\r
-       // make sure month is set properly\r
-       if (isNaN(parseInt(day))) {\r
-               var tmp = day;\r
-               day = month;\r
-               month = tmp;\r
-       } else if (isNaN(parseInt(year))) {\r
-               var tmp = year;\r
-               year = month;\r
-               month = tmp;\r
+       if (dateString == "" || dateString == null || dateString == undefined)\r
+               return result;\r
+       if (dateString instanceof Date) {\r
+               // we already have a date object, no need to parse string here\r
+               result = dateString;\r
        }\r
-       // make sure day and year are set properly\r
-       if (Number(day) > Number(year)) {\r
-               var tmp = year;\r
-               year = day;\r
-               day = tmp;\r
+       else {\r
+               var dateArr = (dateString + '').replace(/,/g, '').replace(/\./g, ':').replace(/  /g, ' ').split(' ');\r
+               if (dateArr.length != 5 && dateArr.length != 6) \r
+                       return null;\r
+               \r
+               // parse date\r
+               var weekDay = dateArr[0];\r
+               var day = dateArr[1];\r
+               var month = dateArr[2];\r
+               var year = dateArr[3];\r
+               // make sure month is set properly\r
+               if (isNaN(parseInt(day))) {\r
+                       var tmp = day;\r
+                       day = month;\r
+                       month = tmp;\r
+               }\r
+               else \r
+                       if (isNaN(parseInt(year))) {\r
+                               var tmp = year;\r
+                               year = month;\r
+                               month = tmp;\r
+                       }\r
+               // make sure day and year are set properly\r
+               if (Number(day) > Number(year)) {\r
+                       var tmp = year;\r
+                       year = day;\r
+                       day = tmp;\r
+               }\r
+               month = months_translated[month];\r
+               \r
+               // parse time\r
+               var timeArr = dateArr[4].split(':');\r
+               if (timeArr.length != 3) \r
+                       return null;\r
+               var hours = Number(timeArr[0]);\r
+               var minutes = Number(timeArr[1]);\r
+               var seconds = Number(timeArr[2]);\r
+               if (dateArr.length == 6 && dateArr[5].toLowerCase() == 'pm' && hours < 12) \r
+                       hours += 12;\r
+               if (dateArr.length == 6 && dateArr[5].toLowerCase() == 'am' && hours == 12) \r
+                       hours = 0;\r
+               \r
+               result = new Date(year, month - 1, day, hours, minutes, seconds);\r
        }\r
-       month = months_translated[month];\r
-\r
-       // parse time\r
-       var timeArr = dateArr[4].split(':');\r
-       if (timeArr.length != 3)\r
-               return null;\r
-       var hours = Number(timeArr[0]);\r
-       var minutes = Number(timeArr[1]);\r
-       var seconds = Number(timeArr[2]);\r
-       if (dateArr.length == 6 && dateArr[5].toLowerCase() == 'pm' && hours < 12)\r
-               hours += 12;\r
-       if (dateArr.length == 6 && dateArr[5].toLowerCase() == 'am' && hours == 12)\r
-               hours = 0;\r
-\r
-       var result = new Date(year, month - 1, day, hours, minutes, seconds);\r
        \r
        // take care of daylight saving time\r
        if (config['enableDaylightSaving'].Value) {\r
@@ -449,6 +530,14 @@ function parseDate(dateString)
        return result;\r
 }\r
 \r
+function getWeekdayLocalized(date) {\r
+       var localizedString = date.toLocaleDateString();\r
+       if (localizedString.indexOf(",") == -1) {\r
+               return weekdays_translated[date.getDay()];\r
+       } else\r
+               return localizedString.split(',')[0];\r
+}\r
+\r
 // 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"\r
 function formatDate(date, format)\r
 {\r
@@ -462,6 +551,13 @@ function formatDate(date, format)
        if (config['showTodayAsText'].Value && isTomorrow(date))\r
                return '<span class="tomorrow">' + config['tomorrowText'].Value + '</span>';\r
 \r
+       if (format instanceof Date) {\r
+               // we don't know how to format this\r
+               if (config['dateFormat'].Value == 'auto' || config['dateFormat'].Value == 'DDMM')\r
+                       return day + config['dateSeparator'].Value + month;\r
+               else\r
+                       return month + config['dateSeparator'].Value + day;\r
+       }\r
        var dateArr = format.replace(/,/g,'').replace(/\./g,':').replace(/  /g,' ').split(' ');\r
        if (dateArr.length != 5 && dateArr.length != 6) {\r
                // we don't know how to format this\r
@@ -508,12 +604,35 @@ function formatDate(date, format)
 function formatTime(date)\r
 {\r
        // date is a Date() object\r
-       date.setSeconds(0); // we don't care about seconds\r
-       var time = date.toLocaleTimeString().replace(/[\.:]00/, ''); // remove seconds from string\r
-       if (time.replace(/\./, ':').split(':')[0].length < 2)\r
-               time = '0' + time;\r
+       var hour = date.getHours();\r
+       var minute = date.getMinutes();\r
+       \r
+       // don't use Date().toLocaleTimeString() as it is utterly broken on newer firmwares\r
+       if (use12hoursTimeFormat) {\r
+               var ap = "AM";\r
+               if (hour > 11)\r
+                       ap = "PM";\r
+               if (hour > 12)\r
+                       hour = hour - 12;\r
+               if (hour == 0)\r
+                       hour = 12;\r
+               if (hour < 10)\r
+                       hour = "0" + hour;\r
+               if (minute < 10)\r
+                       minute = "0" + minute;\r
+               time = hour + timeFormatSeparator + minute + " " + ap;\r
+       }\r
+       else {\r
+               if (hour < 10)\r
+                       hour = "0" + hour;\r
+               if (minute < 10)\r
+                       minute = "0" + minute;\r
+               time = hour + timeFormatSeparator + minute;\r
+       }\r
+       \r
        if (config['showNowAsText'].Value && date.getTime() == now.getTime())\r
                time = '<span class="now">' + config['nowText'].Value + '</span>';\r
+       log("formatTime(): " + time + ", use12hoursTimeFormat=" + use12hoursTimeFormat + ", timeFormatSeparator=" + timeFormatSeparator + ", date.toLocateTimeString(): " + date.toLocaleTimeString());\r
        return time;\r
 }\r
 \r
@@ -526,6 +645,16 @@ function updateData()
 \r
        // check if we got additional or less calendars since our last update\r
        var newCalendarList = listCalendars();\r
+       if (newCalendarList == null) {\r
+               // Something went wrong fetching the calendars list.\r
+               // This usually happens when a backup is being made.\r
+               // Retry the next time updateData() is called by \r
+               // resetting errorOccured\r
+               log('updateData(): listCalendars() failed, trying again later...');\r
+               cacheEntriesHtml = ''; // make sure we replace the currently shown error message on the next update\r
+               errorOccured = false;\r
+               return;\r
+       }\r
        if (newCalendarList.length != calendarList.length) {\r
                calendarList = newCalendarList;\r
                updateCalendarColors();\r
@@ -605,23 +734,26 @@ function updateData()
                var entryDate = '';\r
                var dateArr = [];\r
                var fontsize = 'normal';\r
+               var lineheight = 'normal';\r
                if (mode == 0) {\r
+                       fontsize = parseInt(72 / config['eventsPerWidget'].Value) + 'px';\r
+                       lineheight = parseInt(82 / config['eventsPerWidget'].Value) + 'px';\r
+                       \r
                        if (config['eventsPerWidget'].Value == 3) {\r
-                               fontsize = '17pt';\r
                                changeCssClass('.icon', 'width:20px; height:20px');\r
                        }\r
                        else if (config['eventsPerWidget'].Value == 5) {\r
-                               fontsize = '10pt';\r
                                changeCssClass('.icon', 'width:10px; height:10px');\r
                        }\r
                        else if (config['eventsPerWidget'].Value == 6) {\r
-                               fontsize = '8pt';\r
                                changeCssClass('.icon', 'width:8px; height:8px');\r
                        }\r
                }\r
                else\r
                        changeCssClass('.icon', config['cssStyle_icon'].Value);\r
-               var entriesHtml = '<table style="font-size:' + fontsize + ';">';\r
+               var entriesHtml = '<table style="font-size:' + fontsize + '; line-height:' + lineheight + ';">';\r
+               if (mode == 0)\r
+                       entriesHtml = '<table width="307" height="82"><tr><td>' + entriesHtml; // this is needed to center the actual content vertically\r
                var eventIds = [];\r
                var max;\r
                if (mode == 0)\r
@@ -674,7 +806,7 @@ function updateData()
 \r
                                // summary can be undefined!\r
                                var Summary = ((entry.Summary == null) ? '' : entry.Summary);\r
-                               if (entry.Type == 'Meeting' && entry.Location != '' && config['showLocation'].Value)\r
+                               if (entry.Location != '' && entry.Location != undefined && config['showLocation'].Value)\r
                                        Summary += ', ' + entry.Location;\r
                                \r
                                // fix by yves: determine start and end dates/times\r
@@ -692,6 +824,14 @@ function updateData()
                                log('date: ' + date);\r
                                var endDate = ((entryEndTime == null) ? null : parseDate(entryEndTime));\r
                                log('endDate: ' + endDate);\r
+                               \r
+                               // check if Meeting is actually a DayEvent. Bug introduced by "Anna" updates to various Symbian^3 devices.\r
+                               // Note that this workaround is not 100% save! It might missinterpret some meetings as dayevents of starting and ending on 00:00\r
+                               if (entry.Type == 'Meeting' && date.getHours() == 0 && date.getMinutes() == 0 && \r
+                                       endDate != null && endDate.getHours() == 0 && endDate.getMinutes() == 0) {\r
+                                       log('fixing event type: changed from "Meeting" to "DayEvent".');\r
+                                       entry.Type = 'DayEvent';\r
+                               }\r
 \r
                                // check if meeting event has already passed\r
                                if (entry.Type == 'Meeting') {\r
@@ -762,7 +902,9 @@ function updateData()
                                        // some languages have very strange locale date formats, can't parse all those. Also some todos don't have dates at all.\r
                                        entriesHtml += '<td colspan="4"><span class="date">' + entryDate + '</span> ';\r
                                } else {\r
-                                       var weekDay = date.toLocaleDateString().substr(0,config['weekDayLength'].Value);\r
+                                       var weekDay = getWeekdayLocalized(date).substr(0,config['weekDayLength'].Value);\r
+                                       log('date.toLocaleDateString(): ' + date.toLocaleDateString());\r
+                                       log('weekDay: ' + weekDay);\r
                                        var time = formatTime(date);\r
                                        var dateStr = formatDate(date, entryDate);\r
                                        if (entry.Type == 'ToDo' && overdue && config['markOverdueTodos'].Value) {\r
@@ -793,10 +935,13 @@ function updateData()
                        }\r
                }\r
                entriesHtml += '</table>';\r
+               if (mode == 0)\r
+                       entriesHtml = entriesHtml + '</td></tr></table>';\r
                if (config['showNothingText'].Value && entriesHtml == '<table></table>') {\r
                        var text = config['nothingText'].Value.replace(/%d/, config['monthRange'].Value);\r
                        entriesHtml = '<div style="width:295px; height:75px; text-align:center; line-height:75px; overflow:visible;">' + text + '</div>';\r
                }\r
+               log("output: " + entriesHtml);\r
                if (cacheEntriesHtml != entriesHtml) {\r
                        if (mode == 0)\r
                                document.getElementById('calendarList').innerHTML = entriesHtml;\r
@@ -815,16 +960,21 @@ function updateData()
 // called by handleOnShow() and onResize events\r
 function updateScreen()\r
 {\r
-       log('updateScreen()');\r
+       log('updateScreen(): mode=' + mode + ', window.innerHeight=' + window.innerHeight);\r
 \r
        // check if opening fullscreen\r
-       if( window.innerHeight > 91 && mode == 0) {\r
+\r
+       // Note: according to Nokia's documentation, an innerHeight of >91 is an indicator for fullscreen view. \r
+       // However a bug in E6's firmware causes different window widths and heights (disabled compatibility scaling). \r
+       // So far, values of 104 and 115 for window.innerHeight were reported, we use a safty margin here and check \r
+       // for 150 instead.\r
+       if( window.innerHeight > 150 && mode == 0) {\r
                mode = 1;\r
                cacheEntriesHtml = '';\r
                document.getElementById('body').style.backgroundImage = "";\r
                showFullscreen();\r
        }\r
-       else if (window.innerHeight <= 91 && mode != 0) {\r
+       else if (window.innerHeight <= 150 && mode != 0) {\r
                mode = 0;\r
                cacheEntriesHtml = '';\r
                showHomescreen();\r
@@ -900,6 +1050,8 @@ function init()
        window.widget.onshow = handleOnShow;\r
 \r
        log("init(): finished...");\r
+       if (!errorOccured)\r
+               statupSuccessful = true;\r
 }\r
 \r
 function checkOrientation()\r
@@ -1066,15 +1218,20 @@ function getSettingsCalEntryId()
                var listFiltering = {\r
                        Type:'CalendarEntry', \r
                        Filter:{\r
-                               StartRange: new Date(2000, 0, 1),\r
-                               EndRange: new Date(2000, 0, 1),\r
+                               StartRange: new Date(1999, 11, 30), // note: due to Nokia's buggy calendar API, the settings event can be on 01.01.2000 AND on 31.12.1999, depending on when the calendar entry was created (in summer or winter). It is not even possible to narrow the search down to these two days (probably because of DST offsets). So we're looking for an event between 30.12.1999 and 02.01.2000!\r
+                               EndRange: new Date(2000, 0, 2),\r
                                SearchText: 'ComingNext Settings|',\r
                                Type: 'DayEvent'\r
                        }\r
                }\r
-               var result = calendarService.IDataSource.GetList(listFiltering);\r
-               if (result.ErrorCode) {\r
-                       error(result.ErrorMessage);\r
+               var result = null;\r
+               try {\r
+                       result = calendarService.IDataSource.GetList(listFiltering);\r
+                       if (result.ErrorCode)\r
+                               throw(result.ErrorMessage);\r
+               }\r
+               catch (e) {\r
+                       error("getSettingsCalEntryId: GetList() failed: " + e + ', line ' + e.line);\r
                        return;\r
                }\r
                var list = result.ReturnValue;\r
@@ -1096,7 +1253,7 @@ function getSettingsCalEntryId()
                        try {\r
                                var result = calendarService.IDataSource.Add(criteria);\r
                                if (result.ErrorCode)\r
-                                       error(result.ErrorMessage);\r
+                                       throw(result.ErrorMessage);\r
                        } catch (e) {\r
                                error("getSettingsCalEntryId: " + e + ', line ' + e.line);\r
                        }\r
@@ -1121,9 +1278,14 @@ function loadSettings()
                        LocalId: settingsCalEntryId\r
                }\r
        }\r
-       var result = calendarService.IDataSource.GetList(listFiltering);\r
-       if (result.ErrorCode) {\r
-               error(result.ErrorMessage);\r
+       var result = null;\r
+       try     {\r
+               result = calendarService.IDataSource.GetList(listFiltering);\r
+               if (result.ErrorCode)\r
+                       throw(result.ErrorMessage);\r
+       }\r
+       catch (e) {\r
+               error("loadSettings: GetList() failed: " + e + ', line ' + e.line);\r
                return;\r
        }\r
        var entry = result.ReturnValue.getNext();\r
@@ -1139,7 +1301,11 @@ function loadSettings()
                                var pair = stringlist[i].split('=');\r
                                var key = pair[0];\r
                                var value = pair[1];\r
-                               log('stringlist: ' + key + '=\'' + value + '\'');\r
+                               if (key == null || value == null || config[key] == null) {\r
+                                       log('Warning: unknown or invalid setting: ' + stringlist[i]);\r
+                                       continue;\r
+                               }\r
+                               log('stringlist[' + i + ']: ' + key + '=\'' + value + '\'');\r
                                if (config[key].Type == 'Int') {\r
                                        config[key].Value = Number(value);\r
                                        if (isNaN(config[key].Value))\r
@@ -1208,7 +1374,7 @@ function saveSettings()
        try {\r
                var result = calendarService.IDataSource.Add(criteria);\r
                if (result.ErrorCode)\r
-                       error(result.ErrorMessage);\r
+                       throw(result.ErrorMessage);\r
        } catch (e) {\r
                error("saveSettings: " + e + ', line ' + e.line);\r
        }\r
@@ -1231,7 +1397,7 @@ function printHintBox(text)
 {\r
        uniqueId++;\r
        return '<td width="1%" align="right" onclick="javascript:toggleVisibility(\'info' + uniqueId + '\')">' + getLocalizedText('settings.help') + '</td></tr></table>'+\r
-              '<div class="settingsInfo" id="info' + uniqueId + '">' + text + '</div>';\r
+              '<div class="settingsInfo" id="info' + uniqueId + '" style="display:none">' + text + '</div>';\r
 }\r
 \r
 function showAbout()\r
@@ -1287,14 +1453,22 @@ function getBackgroundImage()
 function updateHomescreen()\r
 {\r
        if (config['useBackgroundImage'].Value) {\r
+               // check if we have a completely unknown screen resolution\r
+               var screenHeight = screen.height;\r
+               var screenWidth = screen.width;\r
+               if (screenHeight != 640 && screenHeight != 480 && screenHeight != 360)\r
+                       screenHeight = 360; // we can only assume we're in portrait mode, so we set the screen dims as needed for the following code\r
+               if (screenWidth != 640 && screenWidth != 480 && screenWidth != 360)\r
+                       screenWidth = 640; // we can only assume we're in portrait mode, so we set the screen dims as needed for the following code\r
+               \r
                // check for screen rotation\r
-               if (orientation != 'portrait' && screen.width == 360 && screen.height == 640) {\r
+               if (orientation != 'portrait' && ((screenWidth == 360 && screenHeight == 640) || (screenWidth == 640 && screenHeight == 480))) {\r
                        window.widget.prepareForTransition("fade");\r
                        orientation = 'portrait';\r
                        document.getElementById('body').style.backgroundImage = 'url(' + getBackgroundImage() + ')';\r
                        document.getElementById('body').style.backgroundColor = 'none';\r
                        window.widget.performTransition();\r
-               } else if (orientation != 'landscape' && screen.width == 640 && screen.height == 360) {\r
+               } else if (orientation != 'landscape' && ((screenWidth == 640 && screenHeight == 360) || (screenWidth == 480 && screenHeight == 640))) {\r
                        window.widget.prepareForTransition("fade");\r
                        orientation = 'landscape';\r
                        document.getElementById('body').style.backgroundImage = 'url(' + getBackgroundImage() + ')';\r
@@ -1552,7 +1726,8 @@ function updateCalendarColors()
        }\r
 }\r
 \r
-function log(message) {\r
+function log(message)\r
+{\r
        if (config['enableLogging'].Value) {\r
                console.info(message);\r
        }\r
@@ -1562,15 +1737,15 @@ function log(message) {
 \r
 <style type="text/css">\r
 a { color:#aaccff }\r
-table { margin:0px; padding:0px; border-spacing:0px; }\r
-td { padding:0px 5px 0px 0px; white-space:nowrap; overflow:hidden; }\r
+table { margin:0px; padding:0px; border-spacing:0px; border-collapse: collapse; }\r
+td { padding:0px 5px 0px 0px; white-space:nowrap; overflow:hidden; margin:0px; }\r
 hr { color:#ffffff; background-color:#ffffff; height:1px; text-align:left; border-style:none; }\r
 .settingsInfo { display:none; font-style:italic; }\r
 .title { font-weight:bold; font-size:14pt; }\r
 .textInput { width:90%; }\r
 .credits { margin-left:40px; text-indent: -20px; margin-bottom:0px; }\r
-#homescreenView { width: 315px; height:91px; overflow:hidden; }\r
-#calendarList { position:absolute; left:5px; top:4px; width:295px; height:75px; overflow:hidden; }\r
+#homescreenView { width: 312px; height:82px; overflow:hidden; }\r
+#calendarList { position:absolute; left:5px; top:0px; width:307px; height:82px; overflow:hidden; }\r
 #name { text-align:center; }\r
 #appicon { display: block; margin-left: auto; margin-right: auto; margin-top: 10px; }\r
 #smallappicon { width:22px; height:22px; margin-right:10px; float:left; }\r
@@ -1602,11 +1777,15 @@ hr { color:#ffffff; background-color:#ffffff; height:1px; text-align:left; borde
        <p>Contributions:</p>\r
                <p class="credits">Paul Moore (bug fixes, new features and code cleanup)</p>\r
                <p class="credits">Manfred Hanselmann (DST support)</p>\r
-               <p class="credits">Christophe Milsent (translation support & french translation)</p>\r
-               <p class="credits">Flavio Nathan (portuguese-brazilian translation)</p>\r
-               <p class="credits">Tokeda (russian translation)</p>\r
-               <p class="credits">Marcella Ferrari (italian translation)</p>\r
-               <p class="credits">Venos (italian translation)</p>\r
+               <p class="credits">Christophe Milsent (translation support & French translation)</p>\r
+               <p class="credits">Flavio Nathan (Portuguese-Brazilian translation)</p>\r
+               <p class="credits">Tokeda (Russian translation)</p>\r
+               <p class="credits">Marcella Ferrari (Italian translation)</p>\r
+               <p class="credits">Venos (Italian translation)</p>\r
+               <p class="credits">Francisco Rodero (Catalan translation)</p>\r
+               <p class="credits">zbigzbig20 (Polish translation)</p>\r
+               <p class="credits">Streamkeskus (Finnish translation)</p>\r
+               <p class="credits">renek (Czech translation)</p>\r
        <p>This software is open source and licensed under the GPLv3.</p>\r
        <p>Visit <a onclick="widget.openURL('http://comingnext.sf.net/'); return false;" href="http://comingnext.sf.net/">comingnext.sf.net</a> for free updates.</p>\r
        <hr />\r