\r
<style type="text/css">\r
/* The following classes can be modified by widget settings */\r
-.background { }\r
-.backgroundFullscreen { }\r
+.background { color:#ffffff; background-color:#000000 }\r
+.backgroundFullscreen { color:#ffffff; background-color:#000000 }\r
.weekDay { }\r
.date { }\r
-.today { }\r
-.tomorrow { }\r
+.today { color:#ff0000 }\r
+.tomorrow { color:#0000ff }\r
.time { }\r
-.now { }\r
+.now { color:#ff00ff }\r
.description { }\r
-.icon { }\r
-.overdue {}\r
-.calendar1 {}\r
-.calendar2 {}\r
-.calendar3 {}\r
-.calendar4 {}\r
-.calendar5 {}\r
-.calendar6 {}\r
+.icon { width:15px; height:15px }\r
+.overdue { color:#ffff00 }\r
+.calendar1 { background-color:#0757cf }\r
+.calendar2 { background-color:#579f37 }\r
+.calendar3 { background-color:#ff9f07 }\r
+.calendar4 { background-color:#af8fef }\r
+.calendar5 { background-color:#57afbf }\r
+.calendar6 { background-color:#9fdf57 }\r
</style>\r
\r
<script type="text/javascript" src="localizedTextStrings.js" charset="utf-8" />\r
hideWidgetOnCalendarOpen: { Type: 'Bool', Default: false, Value: false,},\r
showCalendarIndicator: { Type: 'Bool', Default: true, Value: true,},\r
excludedCalendars: { Type: 'Array', Default: [], Value: [],},\r
+ enableLogging: { 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
// Nothing of interest from here on...\r
//-------------------------------------------------------\r
var panelNum = 0; // use 1 for second panel\r
-var version = "1.31";\r
+var version = "1.32";\r
var versionURL = "http://comingnext.sourceforge.net/version.xml";\r
var calendarService = null;\r
var cacheEntriesHtml = [];\r
var calendarColors = [];\r
var updateTimer = null;\r
var screenRotationTimer = null;\r
-var lastUpdateTime = now;\r
+var lastUpdateTime = now; // last time we updated the display\r
+var lastReloadTime = null; // last time we fetched calendar data\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
\r
// vars for daylight saving time\r
var summertime = false; // true, if current date is in summer, false if in winter\r
"InstanceEndTime"\r
];\r
\r
-window.onload = init;\r
-window.onresize = updateScreen;\r
-window.onshow = updateScreen;\r
-\r
function isLeapYear( year ) {\r
if (( year % 4 == 0 && year % 100 != 0 ) || year % 400 == 0 )\r
return true;\r
else\r
return false;\r
}\r
- \r
+\r
function calcLeapYear(year, days)\r
{\r
if (isLeapYear(year))\r
month = tmp;\r
}\r
\r
- console.info(entry.StartTime + ' -> ' + month + ' ' + counter);\r
+ log(entry.StartTime + ' -> ' + month + ' ' + counter);\r
ids[counter] = entry.id;\r
months_translated[month] = counter + 1;\r
counter++;\r
error(e + ', line ' + e.line);\r
return;\r
}\r
- console.info(ids);\r
+ log(ids);\r
try {\r
var criteria = new Object();\r
criteria.Type = "CalendarEntry";\r
\r
function callback(transId, eventCode, result)\r
{\r
- console.info("callback(): panelNum: %d transId: %d eventCode: %d result.ErrorCode: %d", panelNum, transId, eventCode, result.ErrorCode);\r
+ log("callback(): panelNum: " + panelNum + " transId: " + transId + " eventCode: " + eventCode + " result.ErrorCode: " + result.ErrorCode);\r
+ lastReloadTime = null; // force calendar data reload on next update\r
updateData();\r
}\r
\r
function settingsCallback(transId, eventCode, result)\r
{\r
- console.info("settingsCallback(): panelNum: %d transId: %d eventCode: %d result.ErrorCode: %d", panelNum, transId, eventCode, result.ErrorCode);\r
+ log("settingsCallback(): panelNum: " + panelNum + " transId: " + transId + " eventCode: " + eventCode + " result.ErrorCode: " + result.ErrorCode);\r
loadSettings();\r
}\r
\r
// work around bug in Nokias calendar api resulting in dates within a different DST to be off by 1 hour\r
if (summertime && !dateSummerTime) {\r
result = new Date(result.getTime() - 1000 * 60 * 60 * config['daylightSavingOffset'].Value); // -1 hour\r
- console.info('parseDate(): fixing time -1h: ' + result);\r
+ log('parseDate(): fixing time -1h: ' + result);\r
}\r
else if (!summertime && dateSummerTime) {\r
result = new Date(result.getTime() + 1000 * 60 * 60 * config['daylightSavingOffset'].Value); // +1 hour\r
- console.info('parseDate(): fixing time +1h: ' + result);\r
+ log('parseDate(): fixing time +1h: ' + result);\r
}\r
}\r
\r
\r
function updateData()\r
{\r
- console.info('updateData()');\r
+ log('updateData()');\r
if (errorOccured) {\r
return;\r
}\r
updateCalendarColors();\r
cancelNotification();\r
requestNotification();\r
+ lastReloadTime = null; // force calendar data reload on this update\r
}\r
- \r
- try {\r
- // meetings have time\r
- // 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\r
- now = new Date();\r
- summertime = isSummertime(now); // cache summer time info for today\r
- var meetingList = [];\r
- for(var i=0; i < calendarList.length; i++) {\r
- // ignore excluded calendars\r
- if (config['excludedCalendars'].Value.indexOf(calendarList[i]) != -1)\r
- continue;\r
- var meetingListFiltering = {\r
- Type:'CalendarEntry',\r
- Filter:{\r
- CalendarName: calendarList[i],\r
- StartRange: (new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0)),\r
- EndRange: (new Date(now.getFullYear(), now.getMonth() + config['monthRange'].Value, now.getDate(), 0, 0, 0))\r
- }\r
- }\r
- var meetingResult = calendarService.IDataSource.GetList(meetingListFiltering);\r
- if (meetingResult.ErrorCode != 0)\r
- throw("Error fetching calendar data: " + meetingResult.ErrorCode + ': ' + meetingResult.ErrorMessage);\r
- var list = meetingResult.ReturnValue;\r
- meetingList = meetingList.concat(listToArray(list, calendarList[i]));\r
- }\r
- console.info("updateData(): meetingList.sort()");\r
- meetingList.sort(sortCalendarEntries);\r
\r
- // todos don't, they start on 00:00 hrs., but should be visible anyway\r
- // this will generate a list of passed todos. We have to check if they have been marked as "done" yet\r
- if (config['includeTodos'].Value) {\r
- var todayTodoList = [];\r
+ now = new Date();\r
+ \r
+ // only reload calendar data every 6 hours, visual updates occure more often\r
+ if (!lastReloadTime || now.getTime() - lastReloadTime.getTime() > reloadInterval) {\r
+ log('updateData(): reloading calendar data');\r
+ try {\r
+ // meetings have time\r
+ // 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\r
+ summertime = isSummertime(now); // cache summer time info for today\r
+ var meetingList = [];\r
for(var i=0; i < calendarList.length; i++) {\r
// ignore excluded calendars\r
if (config['excludedCalendars'].Value.indexOf(calendarList[i]) != -1)\r
continue;\r
- var todayTodoListFiltering = {\r
+ var meetingListFiltering = {\r
Type:'CalendarEntry',\r
Filter:{\r
CalendarName: calendarList[i],\r
- Type: 'ToDo',\r
- StartRange: (new Date(now.getFullYear() - 1, now.getMonth(), now.getDate(), 0, 0, 0)),\r
- EndRange: (new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 1))\r
+ StartRange: (new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0)),\r
+ EndRange: (new Date(now.getFullYear(), now.getMonth() + config['monthRange'].Value, now.getDate(), 0, 0, 0))\r
+ }\r
+ }\r
+ var meetingResult = calendarService.IDataSource.GetList(meetingListFiltering);\r
+ if (meetingResult.ErrorCode != 0)\r
+ throw("Error fetching calendar data: " + meetingResult.ErrorCode + ': ' + meetingResult.ErrorMessage);\r
+ var list = meetingResult.ReturnValue;\r
+ meetingList = meetingList.concat(listToArray(list, calendarList[i]));\r
+ }\r
+ log("updateData(): meetingList.sort()");\r
+ meetingList.sort(sortCalendarEntries);\r
+\r
+ // todos don't, they start on 00:00 hrs., but should be visible anyway\r
+ // this will generate a list of passed todos. We have to check if they have been marked as "done" yet\r
+ if (config['includeTodos'].Value) {\r
+ var todayTodoList = [];\r
+ for(var i=0; i < calendarList.length; i++) {\r
+ // ignore excluded calendars\r
+ if (config['excludedCalendars'].Value.indexOf(calendarList[i]) != -1)\r
+ continue;\r
+ var todayTodoListFiltering = {\r
+ Type:'CalendarEntry',\r
+ Filter:{\r
+ CalendarName: calendarList[i],\r
+ Type: 'ToDo',\r
+ StartRange: (new Date(now.getFullYear() - 1, now.getMonth(), now.getDate(), 0, 0, 0)),\r
+ EndRange: (new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 1))\r
+ }\r
}\r
+ var todayTodoResult = calendarService.IDataSource.GetList(todayTodoListFiltering);\r
+ var list = todayTodoResult.ReturnValue;\r
+ todayTodoList = todayTodoList.concat(listToArray(list, calendarList[i]));\r
}\r
- var todayTodoResult = calendarService.IDataSource.GetList(todayTodoListFiltering);\r
- var list = todayTodoResult.ReturnValue;\r
- todayTodoList = todayTodoList.concat(listToArray(list, calendarList[i]));\r
+ log("updateData(): todayTodoList.sort()");\r
+ todayTodoList.sort(sortCalendarEntries);\r
+ entryLists = [todayTodoList, meetingList];\r
+ } else {\r
+ entryLists = [meetingList];\r
}\r
- console.info("updateData(): todayTodoList.sort()");\r
- todayTodoList.sort(sortCalendarEntries);\r
- var entryLists = [todayTodoList, meetingList];\r
- } else {\r
- var entryLists = [meetingList];\r
+ lastReloadTime = new Date();\r
+ } catch(e) {\r
+ error('loading Calendar items list:' + e + ', line ' + e.line);\r
+ return;\r
}\r
- } catch(e) {\r
- error('loading Calendar items list:' + e + ', line ' + e.line);\r
- return;\r
}\r
\r
try {\r
else\r
max = 30; // we can display a lot more events in fullscreen mode\r
\r
- var listinfo = "";\r
- for (var i=0; i < entryLists.length; i++) {\r
- listinfo = listinfo + " " + entryLists[i].length;\r
- var entrieslist = "";\r
- for (var j=0; j < entryLists[i].length; j++) {\r
- entrieslist += entryLists[i][j].Summary + ", ";\r
+ if (config['enableLogging'].Value) {\r
+ var listinfo = "";\r
+ for (var i=0; i < entryLists.length; i++) {\r
+ listinfo = listinfo + " " + entryLists[i].length;\r
+ var entrieslist = "";\r
+ for (var j=0; j < entryLists[i].length; j++) {\r
+ entrieslist += entryLists[i][j].Summary + ", ";\r
+ }\r
+ log("updateData(): entrieslist: " + entrieslist);\r
}\r
- console.info("updateData(): entrieslist: " + entrieslist);\r
+ log("updateData(): inner loop, " + entryLists.length + " lists, [" + listinfo + "] entries");\r
}\r
- console.info("updateData(): inner loop, " + entryLists.length + " lists, [" + listinfo + "] entries");\r
\r
// the first outer loop iteration is for passed ToDos, the second loop is for all upcomming events (may also include ToDos)\r
for (var i=0; counter < max && i < entryLists.length; i++) {\r
entryInfo += entryFields[k] + "=" + entry[entryFields[k]] + ",";\r
}\r
}\r
- console.info(entryInfo);\r
+ log(entryInfo);\r
\r
// we don't want ToDos when includeTodos == false or when they are completed\r
if (entry.Type == 'ToDo' && (entry.Status == "TodoCompleted" || !config['includeTodos'].Value)) {\r
- console.info('skipping ' + entry.id );\r
+ log('skipping ' + entry.id );\r
counter--;\r
continue;\r
}\r
\r
// make sure that we don't include an event twice (useful for ToDos that might come up twice)\r
if (eventIds[entry.id] == 1 && entry.Type == 'ToDo') {\r
- console.info('skipped (already included) ' + entry.id);\r
+ log('skipped (already included) ' + entry.id);\r
counter--;\r
continue;\r
} else\r
\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
\r
// Convert date/time string to Date object\r
var date = parseDate(entryDate);\r
- console.info('date: ' + date);\r
+ log('date: ' + date);\r
var endDate = ((entryEndTime == null) ? null : parseDate(entryEndTime));\r
- console.info('endDate: ' + endDate);\r
+ log('endDate: ' + endDate);\r
\r
// check if meeting event has already passed\r
if (entry.Type == 'Meeting') {\r
var compareTime = ((endDate == null) ? date.getTime() : endDate.getTime());\r
if (now.getTime() > compareTime) {\r
- console.info('skipping Meeting (already passed) ' + entry.id);\r
+ log('skipping Meeting (already passed) ' + entry.id);\r
counter--;\r
eventIds[entry.id] = 0;\r
continue;\r
if (entry.Type == 'Anniversary') {\r
var tmp = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0,0,0);\r
if (date.getTime() < tmp.getTime()) {\r
- console.info('skipping Anniversary (already passed) ' + entry.id);\r
+ log('skipping Anniversary (already passed) ' + entry.id);\r
counter--;\r
eventIds[entry.id] = 0;\r
continue;\r
// fix DayEvents end time. End times are off by 1 Second. It's possible that the event has already passed\r
if (entry.Type == 'DayEvent' && endDate != null) {\r
endDate.setMinutes(endDate.getMinutes() - 1);\r
- console.info('fixing DayEvent endDate: ' + endDate);\r
+ log('fixing DayEvent endDate: ' + endDate);\r
if (now.getTime() > endDate.getTime()) {\r
- console.info('event already passed ' + entry.id);\r
+ log('event already passed ' + entry.id);\r
counter--;\r
eventIds[entry.id] = 0;\r
continue;\r
// check if we are between start and endtime\r
if ((date.getTime() < now.getTime()) && (now.getTime() < endDate.getTime())) {\r
date = now; // change appointment date/time to now\r
- console.info('event is currently taking place: ' + date);\r
+ log('event is currently taking place: ' + date);\r
}\r
}\r
\r
// skip events for the first panel in case this is the second one and we're not in fullscreen mode\r
if (mode == 0 && panelNum > 0 && counter < panelNum * config['eventsPerWidget'].Value + 1) {\r
- console.info('skipping (already in first widget) ' + entry.id);\r
+ log('skipping (already in first widget) ' + entry.id);\r
continue;\r
}\r
\r
}\r
}\r
\r
+// called by handleOnShow() and onResize events\r
function updateScreen()\r
{\r
+ log('updateScreen()');\r
+\r
// check if opening fullscreen\r
if( window.innerHeight > 91 && mode == 0) {\r
mode = 1;\r
}\r
\r
if (mode == 0)\r
- updateHomescreen();\r
+ updateHomescreen(); // check for screen rotation\r
else if (mode == 1)\r
updateFullscreen();\r
- \r
+}\r
+\r
+function handleOnShow()\r
+{\r
+ updateScreen();\r
+\r
var time = new Date();\r
if (time.getTime() - lastUpdateTime.getTime() > config['updateDataInterval'].Value * 60 * 1000) {\r
- console.info('updateScreen(): force updateData() because last update was too long ago (' + (time.getTime() - lastUpdateTime.getTime()) / 1000 + 's)');\r
+ log('updateScreen(): force updateData() because last update was too long ago (' + (time.getTime() - lastUpdateTime.getTime()) / 1000 + 's)');\r
clearUpdateTimer();\r
updateData();\r
setUpdateTimer(); // reinitialize update timer\r
\r
function init()\r
{\r
- console.info('New widget instance starting up...');\r
+ log('New widget instance starting up...');\r
\r
try {\r
// call calendar service\r
else {\r
mode = 1;\r
}\r
- console.info("init(): updateScreen()");\r
+ log("init(): updateScreen()");\r
updateScreen();\r
if (config['useBackgroundImage'].Value)\r
// check for screen rotation every 1 secs\r
- screenRotationTimer = window.setInterval('updateScreen()', 1000 * 1);\r
- console.info("init(): finished...");\r
+ screenRotationTimer = window.setInterval('checkOrientation()', 1000 * 1);\r
+ \r
+ // call updateScreen() when widget changes from background to forground\r
+ window.widget.onshow = handleOnShow;\r
+\r
+ log("init(): finished...");\r
+}\r
+\r
+function checkOrientation()\r
+{\r
+ //updateScreen();\r
+ if (mode == 0)\r
+ updateHomescreen(); // check for screen rotation\r
}\r
\r
function setUpdateTimer()\r
\r
function updateTimerCallback()\r
{\r
- console.info("updateTimerCallback()");\r
+ log("updateTimerCallback()");\r
updateData();\r
}\r
\r
config[key].Value = document.forms[0].elements["settings." + key].value;\r
else if (config[key].Type == 'Int') {\r
config[key].Value = parseInt(document.forms[0].elements["settings." + key].value);\r
- if (config[key].Value < 0)\r
+ if (config[key].Value < 0 || isNaN(config[key].Value))\r
config[key].Value = config[key].Default;\r
}\r
else if (config[key].Type == 'Bool')\r
config[key].Value = document.forms[0].elements["settings." + key].checked;\r
- else if (config[key].Type == 'UID')\r
+ else if (config[key].Type == 'UID') {\r
config[key].Value = parseInt(document.forms[0].elements["settings." + key].value);\r
+ if (isNaN(config[key].Value))\r
+ config[key].Value = config[key].Default;\r
+ }\r
else if (config[key].Type == 'Enum') {\r
config[key].Value = document.forms[0].elements["settings." + key].value;\r
if (config[key].ValidValues.indexOf(config[key].Value) == -1)\r
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
var entry = list.getNext();\r
if (entry != undefined) {\r
settingsCalEntryId = entry.LocalId;\r
- console.info("settingsCalEntryId=" + settingsCalEntryId);\r
+ log("settingsCalEntryId=" + settingsCalEntryId);\r
}\r
else { // create settings item\r
var item = new Object();\r
}\r
var entry = result.ReturnValue.getNext();\r
if (entry != undefined) {\r
- console.info("Loading Settings...");\r
+ log("Loading Settings...");\r
// only reload settings if they chanced since the last reload\r
if (settingsCache != entry.Summary)\r
{\r
var pair = stringlist[i].split('=');\r
var key = pair[0];\r
var value = pair[1];\r
- console.info('stringlist: ' + key + '=\'' + value + '\'');\r
- if (config[key].Type == 'Int')\r
+ if (key == null || value == null || config[key] == null) {\r
+ log('Warning: unknown or invalid setting: ' + stringlist[i]);\r
+ continue;\r
+ }\r
+ log('stringlist: ' + key + '=\'' + value + '\'');\r
+ if (config[key].Type == 'Int') {\r
config[key].Value = Number(value);\r
+ if (isNaN(config[key].Value))\r
+ config[key].Value = config[key].Default;\r
+ }\r
else if (config[key].Type == 'String')\r
config[key].Value = value;\r
else if (config[key].Type == 'Bool')\r
config[key].Value = (value == 'true')\r
else if (config[key].Type == 'Enum')\r
config[key].Value = value;\r
- else if (config[key].Type == 'UID')\r
+ else if (config[key].Type == 'UID') {\r
config[key].Value = Number(value);\r
+ if (isNaN(config[key].Value))\r
+ config[key].Value = config[key].Default;\r
+ }\r
else if (config[key].Type == 'Array') {\r
config[key].Value = value.split("^");\r
if (config[key].Value.length == 1 && config[key].Value[0] == "") {\r
updateCssClasses();\r
}\r
else {\r
- console.info("Settings already cached and did not change");\r
+ log("Settings already cached and did not change");\r
}\r
}\r
else {\r
criteria.Type = "CalendarEntry";\r
criteria.Item = item;\r
\r
- console.info("Saving settings to calendar entry: " + item.Summary);\r
+ log("Saving settings to calendar entry: " + item.Summary);\r
try {\r
var result = calendarService.IDataSource.Add(criteria);\r
if (result.ErrorCode)\r
error("saveSettings: " + e + ', line ' + e.line);\r
}\r
\r
+ lastReloadTime = null; // force calendar data reload on next update\r
clearUpdateTimer();\r
setUpdateTimer();\r
}\r
\r
function showFullscreen()\r
{\r
- console.info("showFullscreen()");\r
+ log("showFullscreen()");\r
hideViews();\r
document.getElementById("fullscreenView").style.display = "block";\r
document.getElementById('body').className = "backgroundFullscreen";\r
\r
function showHomescreen()\r
{\r
- console.info("showHomescreen()");\r
+ log("showHomescreen()");\r
hideViews();\r
document.getElementById("homescreenView").style.display = "block";\r
document.getElementById('body').className = "background";\r
\r
function listCalendars()\r
{\r
+ if (errorOccured) {\r
+ return null;\r
+ }\r
+\r
try {\r
var criteria = {\r
Type:'Calendar', \r
while (( item = calendarListIterator.getNext()) != undefined ) {\r
calendars[count++] = item;\r
}\r
- console.info("Available Calendars: " + calendars.join(", "));\r
+ log("Available Calendars: " + calendars.join(", "));\r
return calendars;\r
} catch(e) {\r
error('listing calendars:' + e + ', line ' + e.line);\r
array.push(itemCopy);\r
txt += array[array.length - 1].Summary + ", ";\r
}\r
- console.info("listToArray(): " + txt);\r
+ log("listToArray(): " + txt);\r
return array;\r
}\r
\r
function sortCalendarEntries(a, b)\r
{\r
var atime, btime;\r
- console.info("sortCalendarEntries(" + a.Summary + "," + b.Summary + ")");\r
+ log("sortCalendarEntries(" + a.Summary + "," + b.Summary + ")");\r
\r
if (a.InstanceStartTime != null) {\r
atime = a.InstanceStartTime;\r
var maxColors = 6;\r
calendarColors = [];\r
if (calendarList.length > maxColors) {\r
- console.info("updateCalendarColors(): Warning: more calendars than available indicator colors");\r
+ log("updateCalendarColors(): Warning: more calendars than available indicator colors");\r
}\r
for(var i=0; i < calendarList.length; i++) {\r
calendarColors[calendarList[i]] = (i % maxColors) + 1;\r
}\r
}\r
\r
+function log(message) {\r
+ if (config['enableLogging'].Value) {\r
+ console.info(message);\r
+ }\r
+}\r
+\r
</script>\r
\r
<style type="text/css">\r
\r
</head>\r
\r
-<body id="body" class="background">\r
+<body onload="javascript:setTimeout('init()', 10)" onresize="javascript:updateScreen()" id="body" class="background">\r
<div id="homescreenView">\r
- <div id="calendarList"></div>\r
+ <div id="calendarList">loading...</div>\r
</div>\r
<div id="fullscreenView" style="display:none;">\r
<img src="Icon.png" id="smallappicon">\r