.calendar6 { background-color:#9fdf57 }\r
</style>\r
\r
-<script type="text/javascript" src="localizedTextStrings.js" charset="utf-8" />\r
-\r
-<script>\r
+<script type="text/javascript" src="localizedTextStrings.js" charset="utf-8"></script>\r
+<script type="text/javascript" src="../debug.js" charset="utf-8"></script>\r
+<script type="text/javascript">\r
// valid types for the config object are 'Int', 'Bool', 'String', 'Enum', 'UID', 'Array'\r
var config = {\r
+ fontsize: { Type: 'Enum', Default: 'auto', Value: 'auto', ValidValues: ['auto', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28'],},\r
+ eventsPerWidget: { Type: 'Int', Default: 4, Value: 4,},\r
monthRange: { Type: 'Int', Default: 2, Value: 2,},\r
includeTodos: { Type: 'Bool', Default: true, Value: true,},\r
useBackgroundImage: { Type: 'Bool', Default: true, Value: true,},\r
backgroundImageLocation: { Type: 'Enum', Default: 'internal', Value: 'internal', ValidValues: ['internal', 'external']},\r
showCombinedDateTime: { Type: 'Bool', Default: false, Value: false,},\r
showLocation: { Type: 'Bool', Default: true, Value: true,},\r
+ showIcons: { Type: 'Bool', Default: true, Value: true,},\r
showTodayAsText: { Type: 'Bool', Default: true, Value: true,},\r
todayText: { Type: 'String', Default: getLocalizedText('settings.default.todayText'), Value: getLocalizedText('settings.default.todayText'),},\r
tomorrowText: { Type: 'String', Default: getLocalizedText('settings.default.tomorrowText'), Value: getLocalizedText('settings.default.tomorrowText'),},\r
weekDayLength: { Type: 'Int', Default: 2, Value: 2,},\r
updateDataInterval: { Type: 'Int', Default: 5, Value: 5,},\r
calendarApp: { Type: 'UID', Default: 0x10005901, Value: 0x10005901,},\r
- eventsPerWidget: { Type: 'Int', Default: 4, Value: 4,},\r
showNothingText: { Type: 'Bool', Default: true, Value: true,},\r
nothingText: { Type: 'String', Default: getLocalizedText('settings.default.nothingText'), Value: getLocalizedText('settings.default.nothingText'),},\r
enableDaylightSaving: { Type: 'Bool', Default: true, Value: true,},\r
showCalendarIndicator: { Type: 'Bool', Default: true, Value: true,},\r
excludedCalendars: { Type: 'Array', Default: [], Value: [],},\r
enableLogging: { Type: 'Bool', Default: false, Value: false,},\r
+ anonymizeLogging: { Type: 'Bool', Default: false, Value: false,},\r
cssStyle_background: { Type: 'String', Default: 'color:#ffffff; background-color:#000000', Value: 'color:#ffffff; background-color:#000000',},\r
cssStyle_backgroundFullscreen: { Type: 'String', Default: 'color:#ffffff; background-color:#000000', Value: 'color:#ffffff; background-color:#000000',},\r
cssStyle_weekDay: { Type: 'String', Default: '', Value: '',},\r
cssStyle_time: { Type: 'String', Default: '', Value: '',},\r
cssStyle_now: { Type: 'String', Default: 'color:#ff00ff', Value: 'color:#ff00ff',},\r
cssStyle_description: { Type: 'String', Default: '', Value: '',},\r
- cssStyle_icon: { Type: 'String', Default: 'width:15px; height:15px', Value: 'width:15px; height:15px',},\r
+ cssStyle_icon: { Type: 'String', Default: '', Value: '',},\r
cssStyle_overdue: { Type: 'String', Default: 'color:#ffff00', Value: 'color:#ffff00',},\r
cssStyle_calendar1: { Type: 'String', Default: 'background-color:#0757cf', Value: 'background-color:#0757cf',},\r
cssStyle_calendar2: { Type: 'String', Default: 'background-color:#579f37', Value: 'background-color:#579f37',},\r
// Nothing of interest from here on...\r
//-------------------------------------------------------\r
var panelNum = 0; // use 1 for second panel\r
-var version = "1.33";\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
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
+var defaultFontSize = null; // default browser font size will be set by init\r
\r
// vars for daylight saving time\r
var summertime = false; // true, if current date is in summer, false if in winter\r
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
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
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
}\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
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
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
\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
var counter = 0;\r
var entryDate = '';\r
var dateArr = [];\r
- var fontsize = 'normal';\r
+ var fontsize = getDefaultFontSize()[1] + 'px';\r
+ var lineheight = fontsize;\r
if (mode == 0) {\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
+ if (config['fontsize'].Value == config['fontsize'].ValidValues[0]) {\r
+ fontsize = parseInt(72 / config['eventsPerWidget'].Value) + 'px';\r
+ lineheight = parseInt(72 / config['eventsPerWidget'].Value) + 'px';\r
}\r
}\r
- else\r
- changeCssClass('.icon', config['cssStyle_icon'].Value);\r
- var entriesHtml = '<table style="font-size:' + fontsize + ';">';\r
+ if (config['fontsize'].Value != config['fontsize'].ValidValues[0]) {\r
+ fontsize = config['fontsize'].Value + 'px';\r
+ lineheight = fontsize;\r
+ }\r
+ changeCssClass('.icon', config['cssStyle_icon'].Value + '; width:' + fontsize + '; height:' + 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
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
// generate html output\r
entriesHtml += '<tr>';\r
if (config['showCalendarIndicator'].Value && calendarList.length - config['excludedCalendars'].Value.length > 1) {\r
- entriesHtml += '<td><span class="calendar' + calendarColors[entry.CalendarName] + '"> </span></td>';\r
+ entriesHtml += '<td><div class="calendar' + calendarColors[entry.CalendarName] + '" style="height:' + (lineheight.split("px")[0] - 1) + 'px; width:4px;"></div></td>';\r
}\r
- entriesHtml += '<td><img class="icon" src="' + entry.Type + '.png" /></td>';\r
+ if (config['showIcons'].Value)\r
+ entriesHtml += '<td><img class="icon" align="top" src="' + entry.Type + '.png" /></td>';\r
+ else\r
+ entriesHtml += '<td style="padding:0px;"></td>';\r
if(date == null) {\r
// 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
}\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
// 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
window.widget.onshow = handleOnShow;\r
\r
log("init(): finished...");\r
+ if (!errorOccured)\r
+ statupSuccessful = true;\r
}\r
\r
function checkOrientation()\r
settingsHtml += '<table><tr><td>' + getLocalizedText('settings.name.' + key) + '<br /><input class="textInput" name="settings.' + key + '" type="text" value="0x' + config[key].Value.toString(16) + '" /></td>' + printHintBox(getLocalizedText('settings.info.' + key)) + '<hr />';\r
else if (config[key].Type == 'Enum') {\r
settingsHtml += '<table><tr><td>' + getLocalizedText('settings.name.' + key) + '<br /><select name="settings.' + key + '" size="1">';\r
- for(var i = 0; i < config[key].ValidValues.length; i++)\r
- settingsHtml += '<option value="' + config[key].ValidValues[i] + '"' + (config[key].Value == config[key].ValidValues[i] ? ' selected="selected"' : '') + '>' + getLocalizedText('settings.validValues.' + key + '.' + config[key].ValidValues[i]) + '</option>';\r
+ for(var i = 0; i < config[key].ValidValues.length; i++) {\r
+ var text = getLocalizedText('settings.validValues.' + key + '.' + config[key].ValidValues[i]);\r
+ if (text.indexOf('ERROR') == 0)\r
+ text = config[key].ValidValues[i];\r
+ settingsHtml += '<option value="' + config[key].ValidValues[i] + '"' + (config[key].Value == config[key].ValidValues[i] ? ' selected="selected"' : '') + '>' + text + '</option>';\r
+ }\r
settingsHtml += '</select></div></td>' + printHintBox(getLocalizedText('settings.info.' + key)) + '<hr />';\r
}\r
else if (config[key].Type == 'Array') {\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
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
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
log('Warning: unknown or invalid setting: ' + stringlist[i]);\r
continue;\r
}\r
- log('stringlist: ' + key + '=\'' + value + '\'');\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
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
{\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
reqV.onreadystatechange = checkForUpdateCallback;\r
document.getElementById("updateDiv").innerHTML = getLocalizedText("update.checking");\r
reqV.open("GET", versionURL, true);\r
- reqV.setRequestHeader( "If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT" ); // disable caching\r
reqV.send(null);\r
}\r
\r
if (!itemCopy['CalendarName']) {\r
itemCopy['CalendarName'] = calendarName;\r
}\r
+ if (config['anonymizeLogging'].Value && config['enableLogging'].Value) {\r
+ if (itemCopy['Summary'])\r
+ itemCopy['Summary'] = getHashForString(itemCopy['Summary']);\r
+ if (itemCopy['Location'])\r
+ itemCopy['Location'] = getHashForString(itemCopy['Location']);\r
+ }\r
array.push(itemCopy);\r
txt += array[array.length - 1].Summary + ", ";\r
}\r
}\r
}\r
\r
+function getDefaultFontSize()\r
+{\r
+ if (defaultFontSize == null) {\r
+ var pa = document.body;\r
+ var who = document.createElement('div');\r
+ who.className = 'defaultEm';\r
+ who.appendChild(document.createTextNode('M'));\r
+ pa.appendChild(who);\r
+ var fs = [who.offsetWidth, who.offsetHeight];\r
+ pa.removeChild(who);\r
+ defaultFontSize = fs;\r
+ }\r
+ return defaultFontSize;\r
+}\r
+\r
+function getHashForString(string)\r
+{\r
+ // cheap hashing, loosly based on Java's String.hashCode()\r
+ for (var hash = 0, i = 0; i < string.length; i++)\r
+ hash = (hash << 5) - hash + string.charCodeAt(i);\r
+ hash = hash & hash; // Convert to 32bit integer\r
+ if (hash < 0)\r
+ hash = -hash;\r
+ return hash.toString(16).toUpperCase();\r
+}\r
+\r
</script>\r
\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:visible; 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
+.defaultEm { font-size:1em; position:absolute; line-height:1; padding:0; visibility:hidden; } \r
</style>\r
\r
</head>\r
<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