]> code.delx.au - comingnext/blob - comingNext/index.html
added support for daylight saving time (DST)
[comingnext] / comingNext / index.html
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3 <html xmlns="http://www.w3.org/1999/xhtml">
4 <head>
5
6 <title>Coming Next</title>
7
8 <style type="text/css">
9 /* -----------------------------------------------------------------------
10 here you can customize background color, font color, font size etc...
11 --------------------------------------------------------------------------- */
12 .background { color:#ffffff; background-color:#000000; font:normal 12pt; } /* Defines the background of the widget. If you want to use a background image, set useBackgroundImage = true below */
13 /* for the default themes, black, gray, and light blue, codes are #292029, #e7dfe7, #009aef */
14 .weekDay { } /* Defines the appearance of all week day texts */
15 .date { } /* Defines the appearance of all date texts */
16 .today { color:#ff0000; } /* Defines the appearance of "Today" text */
17 .time { } /* Defines the appearance of all time texts */
18 .now { color:#ff00ff; } /* Defines the appearance of "Now" text */
19 .description { } /* Defines the appearance of all event descriptions */
20 .icon { width:15px; height:15px; } /* Defines size and appearance of icons */
21 </style>
22
23 <script>
24
25 //---------------------------------------------------------------
26 // The following section contains settings you may want to tweak
27 //---------------------------------------------------------------
28 var monthRange = 2; // number of months to include in the event list
29 var includeTodos = true; // disable to remove ToDos from event list
30 var useBackgroundImage = true; // use background_portrait.png and background_landscape.png to fake transparency. Set to "false" to use a solid background color
31 var showCombinedDateTime = false;// only show the time for events happening today, otherwise just show the date
32 var showLocation = true; // show the location for meeting events
33 var showTodayAsText = true; // if enabled, the current date will be shown as "Today" instead of "31.12"
34 var todayText = 'Today'; // text to display for "Today"
35 var showNowAsText = true; // if enabled, the appointment time will be shown as "Now" instead of "12:00"
36 var nowText = 'Now'; // text to display for "Now"
37 var dateSeparator = '.'; // separator for dates. e.g. "31.12" or "31/12"
38 var dateFormat = 'auto' // how dates will be displayed. 'auto' will autodetect your phone's date format setting. 'MMDD' will write month first, 'DDMM' will write day first
39 var weekDayLength = 2; // defines how many characters of the weekday will be shown. E.g. 2 will cut "Friday" to "Fr"
40 var updateDataInterval = 5; // how many minutes to wait before updating the displayed data. The higher the number, the less battery is used
41 var calendarApp = 0x10005901; // UID of the calendar app to run when clicking the widget. 0x10005901 = buildin calendar, 0x20004ec1 = Epocware Handy Calendar
42 var eventsPerWidget = 4; // number of events to show per widget. Default is 4
43 var showNothingText = true; // if set to "true", show a text if no events are in the list
44 var nothingText = 'No further events within ' + monthRange + ' months'; // text to show when no events are in the list
45 var enableDaylightSaving = true;// enable this if you are in a timezone that has daylight saving time (+1h)
46
47 //-------------------------------------------------------
48 // Nothing of interest from here on...
49 //-------------------------------------------------------
50 var panelNum = 0; // use 1 for second panel
51 var calendarService = null;
52 var cacheEntriesHtml = [];
53 var months_translated = [];
54 var orientation = '';
55 var now = new Date();
56
57 // vars for daylight saving time
58 var daylightsavingWinter = 0;
59 var daylightsavingSummer = 0;
60 var summertime = false;
61
62 window.onload = init;
63 window.onresize = updateScreen;
64 window.onshow = updateScreen;
65
66 function isLeapYear( year ) {
67 if (( year % 4 == 0 && year % 100 != 0 ) || year % 400 == 0 )
68 return true;
69 else
70 return false;
71 }
72
73 function calcLeapYear(year, days)
74 {
75 if (isLeapYear(year))
76 return ++days;
77 else
78 return days;
79 }
80
81 function subToSunday(myDate, year, days, prevMonthDays)
82 {
83 for (i = myDate.getDay(); i > 0 ;i--)
84 days--;
85 days -= prevMonthDays;
86 days = isLeapYear(year) ? --days : days;
87 return days;
88 }
89
90 function calcDaylightSaving()
91 {
92 var thisYearS = new Date(now.getFullYear(), 3, 0, 0, 0, 0 );
93 var thisYearW = new Date(now.getFullYear(), 10, 0, 0, 0, 0 );
94 var nextYearS = new Date(now.getFullYear() + 1, 3, 0, 0, 0, 0 );
95 var nextYearW = new Date(now.getFullYear() + 1, 10, 0, 0, 0, 0 );
96 var summer = false;
97 var winter = false;
98
99 thisYearSDays = nextYearSDays = 90;
100 thisYearWDays = nextYearWDays = 304;
101
102 thisYearSDays = calcLeapYear(now.getFullYear(), thisYearSDays);
103 thisYearWDays = calcLeapYear(now.getFullYear(), thisYearWDays);
104 nextYearSDays = calcLeapYear(now.getFullYear() + 1, nextYearSDays);
105 nextYearWDays = calcLeapYear(now.getFullYear() + 1, nextYearWDays);
106
107 thisYearSDays = subToSunday(thisYearS, now.getFullYear(), thisYearSDays, 59);
108 thisYearWDays = subToSunday(thisYearW, now.getFullYear(), thisYearWDays, 273);
109 nextYearSDays = subToSunday(nextYearS, now.getFullYear() + 1, nextYearSDays, 59);
110 nextYearWDays = subToSunday(nextYearW, now.getFullYear() + 1, nextYearWDays, 273);
111
112 daylightsavingSummer = new Date (now.getFullYear(), 03-1, thisYearSDays, 2, 0, 0);
113 daylightsavingWinter = new Date (now.getFullYear(), 10-1, thisYearWDays, 2, 0, 0);
114 if (daylightsavingSummer < now) {
115 daylightsavingSummer = new Date (now.getFullYear()+1, 03-1, nextYearSDays, 2, 0, 0);
116 var summer = true;
117 }
118 if (daylightsavingWinter < now) {
119 daylightsavingWinter = new Date (now.getFullYear()+1, 10-1, nextYearWDays, 2, 0, 0);
120 var winter = true;
121 }
122 if (summer && !winter)
123 summertime = true;
124 else
125 summertime = false;
126 }
127
128 function error(message)
129 {
130 console.info('Error: ' + message);
131 document.getElementById("calendarList").innerHTML = 'Error: ' + message;
132 }
133
134 function isToday(date)
135 {
136 if (date.getDate() == now.getDate() && date.getMonth() == now.getMonth())
137 return true;
138 return false;
139 }
140
141 function collectLocales()
142 {
143 var tmpyear = ((panelNum == 0) ? 2000 : 2001);
144 var month = 0;
145
146 if (months_translated.length > 0)
147 return;
148 for (month = 0; month < 12; month++) {
149 var startDate = new Date(tmpyear, month, 15);
150
151 var item = new Object();
152 item.Type = "DayEvent";
153 item.StartTime = startDate;
154 item.Summary = "__temp" + month;
155
156 var criteria = new Object();
157 criteria.Type = "CalendarEntry";
158 criteria.Item = item;
159
160 try {
161 var result = calendarService.IDataSource.Add(criteria);
162 if (result.ErrorCode)
163 error(result.ErrorMessage);
164 } catch (e) {
165 error("collectLocales: " + e + ', line ' + e.line);
166 }
167 }
168 try {
169 var startTime = new Date(tmpyear,0,1);
170 var endTime = new Date(tmpyear,11,31);
171 var listFiltering = {
172 Type:'CalendarEntry',
173 Filter:{
174 StartRange: startTime,
175 EndRange: endTime,
176 SearchText: '__temp',
177 Type: 'DayEvent'
178 }
179 }
180 var result = calendarService.IDataSource.GetList(listFiltering);
181 if (result.ErrorCode) {
182 error(result.ErrorMessage);
183 return;
184 }
185 var list = result.ReturnValue;
186 } catch(e) {
187 error(e + ', line ' + e.line);
188 return;
189 }
190 var ids = new Array();
191 try {
192 var entry;
193 var counter = 0;
194 var dateArr = [];
195
196 while (list && (entry = list.getNext()) != undefined) {
197 dateArr = entry.StartTime.replace(/,/g,'').replace(/\./g,':').replace(/ /g,' ').split(' ');
198 var day = dateArr[1];
199 var month = dateArr[2];
200 var year = dateArr[3];
201
202 // make sure month is set properly
203 if (isNaN(parseInt(day))) {
204 var tmp = day;
205 day = month;
206 month = tmp;
207 } else if (isNaN(parseInt(year))) {
208 var tmp = year;
209 year = month;
210 month = tmp;
211 }
212
213 console.info(entry.StartTime + ' -> ' + month + ' ' + counter);
214 ids[counter] = entry.id;
215 months_translated[month] = counter + 1;
216 counter++;
217 }
218 } catch(e) {
219 error(e + ', line ' + e.line);
220 return;
221 }
222 console.info(ids);
223 try {
224 var criteria = new Object();
225 criteria.Type = "CalendarEntry";
226 criteria.Data = {
227 IdList: ids
228 }
229
230 var result = calendarService.IDataSource.Delete(criteria);
231 if (result.ErrorCode)
232 error(result.ErrorMessage);
233 } catch(e) {
234 error('deleting temp calendar entries:' + e + ', line ' + e.line);
235 return;
236 }
237 }
238
239 function requestNotification()
240 {
241 var criteria = new Object();
242 criteria.Type = "CalendarEntry";
243
244 try {
245 var result = calendarService.IDataSource.RequestNotification(criteria, callback);
246 if (result.ErrorCode)
247 error('loading Calendar items list');
248 } catch (e) {
249 error("requestNotification: " + e + ', line ' + e.line);
250 }
251 }
252
253 function callback(transId, eventCode, result)
254 {
255 updateData();
256 }
257
258 function parseDate(dateString)
259 {
260 /*
261 Dates my look very differently. Also keep in mind that the names are localized!!! These are the possibilities depending on the users date format setting:
262 Wednesday, 26 August, 2009 24:00:00
263 Wednesday, 26 August, 2009 12:00:00 am
264 Wednesday, August 26, 2009 12:00:00 am
265 Wednesday, 2009 August, 26 12:00:00 am
266 Wednesday, 2009 August, 28 8.00.00 pm
267 Wednesday, 2009 August, 28 08:00:00 PM
268 */
269
270 if (dateString == "" || dateString == null)
271 return null;
272 var dateArr = dateString.replace(/,/g,'').replace(/\./g,':').replace(/ /g,' ').split(' ');
273 if (dateArr.length != 5 && dateArr.length != 6)
274 return null;
275
276 // parse date
277 var weekDay = dateArr[0];
278 var day = dateArr[1];
279 var month = dateArr[2];
280 var year = dateArr[3];
281 // make sure month is set properly
282 if (isNaN(parseInt(day))) {
283 var tmp = day;
284 day = month;
285 month = tmp;
286 } else if (isNaN(parseInt(year))) {
287 var tmp = year;
288 year = month;
289 month = tmp;
290 }
291 // make sure day and year are set properly
292 if (Number(day) > Number(year)) {
293 var tmp = year;
294 year = day;
295 day = tmp;
296 }
297 month = months_translated[month];
298
299 // parse time
300 var timeArr = dateArr[4].split(':');
301 if (timeArr.length != 3)
302 return null;
303 var hours = Number(timeArr[0]);
304 var minutes = Number(timeArr[1]);
305 var seconds = Number(timeArr[2]);
306 if (dateArr.length == 6 && dateArr[5].toLowerCase() == 'pm' && hours < 12)
307 hours += 12;
308 if (dateArr.length == 6 && dateArr[5].toLowerCase() == 'am' && hours == 12)
309 hours = 0;
310
311 console.info('year=' + year + ' month=' + month + ' day=' + day + ' hours=' + hours + ' minutes=' + minutes+ ' seconds=' + seconds);
312
313 // take care of daylight saving time
314 if (enableDaylightSaving) {
315 var date = new Date(year, month - 1, day, hours, minutes, seconds);
316 if (summertime && date > daylightsavingWinter && date < daylightsavingSummer)
317 hours -= 1;
318 else if (!summertime && date > daylightsavingSummer && date < daylightsavingWinter)
319 hours += 1;
320 }
321
322 return new Date(year, month - 1, day, hours, minutes, seconds);
323 }
324
325 // 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"
326 function formatDate(date, format)
327 {
328 var day = date.getDate().toString();
329 var month = (date.getMonth() + 1).toString();
330 while (day.length < 2) { day = '0' + day; }
331 while (month.length < 2) { month = '0' + month; }
332
333 if (showTodayAsText && isToday(date))
334 return '<span class="today">' + todayText + '</span>';
335
336 var dateArr = format.replace(/,/g,'').replace(/\./g,':').replace(/ /g,' ').split(' ');
337 if (dateArr.length != 5 && dateArr.length != 6) {
338 // we don't know how to format this
339 if (dateFormat == 'auto' || dateFormat == 'DDMM')
340 return day + dateSeparator + month;
341 else
342 return month + dateSeparator + day;
343 }
344
345 var dayFirst = true;
346 if (dateFormat == 'MMDD')
347 dayFirst = false;
348 else if (dateFormat == 'DDMM')
349 dayFirst = true;
350 else {
351 // dateFormat == 'auto', try to detect system setting
352 // parse date
353 var day_ = dateArr[1];
354 var month_ = dateArr[2];
355 var year_ = dateArr[3];
356 // make sure month is set properly
357 if (isNaN(parseInt(day_))) {
358 var tmp = day_;
359 day_ = month_;
360 month_ = tmp;
361 dayFirst = false;
362 } else if (isNaN(parseInt(year_))) {
363 var tmp = year_;
364 year_ = month_;
365 month_ = tmp;
366 dayFirst = true;
367 }
368 // make sure day and year are set properly
369 if (Number(day_) > Number(year_))
370 dayFirst = false;
371 }
372
373 if (dayFirst)
374 return day + dateSeparator + month;
375 else
376 return month + dateSeparator + day;
377 }
378
379 function formatTime(date)
380 {
381 // date is a Date() object
382 date.setSeconds(0); // we don't care about seconds
383 var time = date.toLocaleTimeString().replace(/[\.:]00/, ''); // remove seconds from string
384 if (time.replace(/\./, ':').split(':')[0].length < 2)
385 time = '0' + time;
386 if (showNowAsText && date.getTime() == now.getTime())
387 time = '<span class="now">' + nowText + '</span>';
388 return time;
389 }
390
391 function updateData()
392 {
393 calcDaylightSaving();
394 try {
395 // meetings have time
396 // 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
397 now = new Date();
398 var meetingListFiltering = {
399 Type:'CalendarEntry',
400 Filter:{
401 StartRange: (new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0)),
402 EndRange: (new Date(now.getFullYear(), now.getMonth() + monthRange, now.getDate(), 0, 0, 0))
403 }
404 }
405 var meetingResult = calendarService.IDataSource.GetList(meetingListFiltering);
406 var meetingList = meetingResult.ReturnValue;
407
408 // todos don't, they start on 00:00 hrs., but should be visible anyway
409 // this will generate a list of passed todos. We have to check if they have been marked as "done" yet
410 if (includeTodos) {
411 var todayTodoListFiltering = {
412 Type:'CalendarEntry',
413 Filter:{
414 Type: 'ToDo',
415 StartRange: (new Date(now.getFullYear() - 1, now.getMonth(), now.getDate(), 0, 0, 0)),
416 EndRange: (new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 1))
417 }
418 }
419 var todayTodoResult = calendarService.IDataSource.GetList(todayTodoListFiltering);
420 var todayTodoList = todayTodoResult.ReturnValue;
421 var entryLists = [todayTodoList, meetingList];
422 } else {
423 var entryLists = [meetingList];
424 }
425 } catch(e) {
426 error('loading Calendar items list:' + e + ', line ' + e.line);
427 return;
428 }
429
430 try {
431 var entry;
432 var counter = 0;
433 var entryDate = '';
434 var dateArr = [];
435 var entriesHtml = '<table>';
436 var eventIds = [];
437 var max = ((panelNum == 0) ? eventsPerWidget : 2 * eventsPerWidget);
438
439 // the first outer loop iteration is for passed ToDos, the second loop is for all upcomming events (may also include ToDos)
440 for (var i=0; counter < max && i < entryLists.length; i++) {
441 while (counter < max && (entry = entryLists[i].getNext()) != undefined) {
442 counter++;
443
444 // output event info for debugging
445 console.info(
446 'event: Id=' + entry.id +
447 ',Type=' + entry.Type +
448 ',Summary=' + entry.Summary +
449 ',Location=' + entry.Location +
450 ',Status=' + entry.Status +
451 ',StartTime=' + entry.StartTime +
452 ',EndTime=' + entry.EndTime +
453 ',InstanceStartTime=' + entry.InstanceStartTime +
454 ',InstanceEndTime=' + entry.InstanceEndTime
455 );
456
457 // we don't want ToDos when includeTodos == false or when they are completed
458 if (entry.Type == 'ToDo' && (entry.Status == "TodoCompleted" || !includeTodos)) {
459 console.info('skipping ' + entry.id );
460 counter--;
461 continue;
462 }
463
464 // make sure that we don't include an event twice (useful for ToDos that might come up twice)
465 if (eventIds[entry.id] == 1) {
466 console.info('skipped (already included) ' + entry.id);
467 counter--;
468 continue;
469 } else
470 eventIds[entry.id] = 1;
471
472 // summary can be undefined!
473 var Summary = ((entry.Summary == null) ? '' : entry.Summary);
474 if (entry.Type == 'Meeting' && entry.Location != '' && showLocation)
475 Summary += ', ' + entry.Location;
476
477 // fix by yves: determine start and end dates/times
478 entryStartTime = ((entry.InstanceStartTime == null) ? entry.StartTime : entry.InstanceStartTime);
479 entryEndTime = ((entry.InstanceEndTime == null) ? entry.EndTime : entry.InstanceEndTime);
480
481 // there can be ToDos that have no date at all!
482 if (entry.Type == 'ToDo' && entry.EndTime == null)
483 entryDate = ""; // this will cause parseDate(entryDate) to return null;
484 else
485 entryDate = ((entry.Type == 'ToDo') ? entryEndTime : entryStartTime); // ToDo's use their EndTime, the rest use StartTime
486
487 // Convert date/time string to Date object
488 var date = parseDate(entryDate);
489 console.info('date: ' + date);
490 var endDate = ((entryEndTime == null) ? null : parseDate(entryEndTime));
491 console.info('endDate: ' + endDate);
492
493 // check if meeting event has already passed
494 if (entry.Type == 'Meeting') {
495 var compareTime = ((endDate == null) ? date.getTime() : endDate.getTime());
496 if (now.getTime() > compareTime) {
497 console.info('skipping Meeting (already passed) ' + entry.id);
498 counter--;
499 eventIds[entry.id] = 0;
500 continue;
501 }
502 }
503
504 // check if anniversary passed (not sure why they are in the list, the query was only for today - nokia?)
505 if (entry.Type == 'Anniversary') {
506 var tmp = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0,0,0);
507 if (date.getTime() < tmp.getTime()) {
508 console.info('skipping Anniversary (already passed) ' + entry.id);
509 counter--;
510 eventIds[entry.id] = 0;
511 continue;
512 }
513 }
514
515 // fix DayEvents end time. End times are off by 1 Second. It's possible that the event has already passed
516 if (entry.Type == 'DayEvent' && endDate != null) {
517 endDate.setMinutes(endDate.getMinutes() - 1);
518 console.info('fixing DayEvent endDate: ' + endDate);
519 if (now.getTime() > endDate.getTime()) {
520 console.info('event already passed ' + entry.id);
521 counter--;
522 eventIds[entry.id] = 0;
523 continue;
524 }
525 }
526
527 // check if the event is currently taking place
528 if (entryStartTime != null && entryEndTime != null && date != null && endDate != null) {
529 // check if we are between start and endtime
530 if ((date.getTime() < now.getTime()) && (now.getTime() < endDate.getTime())) {
531 date = now; // change appointment date/time to now
532 console.info('event is currently taking place: ' + date);
533 }
534 }
535
536 // skip events for the first panel in case this is the second one
537 if (panelNum == 1 && counter < eventsPerWidget + 1) {
538 console.info('skipping (already in first widget) ' + entry.id);
539 continue;
540 }
541
542 // generate html output
543 entriesHtml += '<tr><td><img class="icon" src="' + entry.Type + '.png" /></td>';
544 if(date == null) {
545 // some languages have very strange locale date formats, can't parse all those. Also some todos don't have dates at all.
546 entriesHtml += '<td colspan="4"><span class="date">' + entryDate + '</span> ';
547 } else {
548 var weekDay = date.toLocaleDateString().substr(0,weekDayLength);
549 var time = formatTime(date);
550 var dateStr = formatDate(date, entryDate);
551 if (entry.Type == 'ToDo' || entry.Type == 'Anniversary' || entry.Type == 'DayEvent' || entry.Type == 'Reminder') {
552 if (isToday(date) && showTodayAsText) // show weekday if the date string is not text. looks odd otherwise
553 entriesHtml += '<td colspan="4"><span class="date">' + dateStr + '</span> ';
554 else
555 entriesHtml += '<td class="weekDay">' + weekDay + '</td><td class="date">' + dateStr + '</td><td colspan="2">';
556 } else if (entry.Type == 'Meeting') {
557 if (showCombinedDateTime) {
558 if (isToday(date))
559 entriesHtml += '<td colspan="4"><span class="today">' + time + '</span> ';
560 else
561 entriesHtml += '<td class="weekDay">' + weekDay + '</td><td class="date">' + dateStr + '</td><td colspan="2">';
562 } else {
563 if (isToday(date) && showTodayAsText)
564 entriesHtml += '<td colspan="4"><span class="today">' + dateStr + '</span> <span class="time">' + time + '</span> ';
565 else
566 entriesHtml += '<td class="weekDay">' + weekDay + '</td><td class="date">' + dateStr + '</td><td width="1px" class="time">' + time + '</td><td>';
567 }
568 }
569 }
570 entriesHtml += '<span class="description">' + Summary + '</span></td></tr>';
571 }
572 }
573 entriesHtml += '</table>';
574 if (showNothingText && entriesHtml == '<table></table>')
575 entriesHtml = '<div style="width:295px; height:75px; text-align:center; line-height:75px; overflow:visible;">' + nothingText + '</div>';
576 if (cacheEntriesHtml != entriesHtml) {
577 document.getElementById('calendarList').innerHTML = entriesHtml;
578 cacheEntriesHtml = entriesHtml;
579 }
580 } catch(e) {
581 error('displaying list:' + e + ', line ' + e.line);
582 return;
583 }
584 }
585
586 function updateScreen()
587 {
588 // check if opening fullscreen
589 if( window.innerHeight > 91)
590 launchCalendar();
591
592 if (useBackgroundImage) {
593 // check for screen rotation
594 if (orientation != 'portrait' && screen.width == 360 && screen.height == 640) {
595 window.widget.prepareForTransition("fade");
596 orientation = 'portrait';
597 document.getElementById('body').style.backgroundImage = 'url(background_' + orientation + '.png)';
598 document.getElementById('body').style.backgroundColor = 'none';
599 window.widget.performTransition();
600 } else if (orientation != 'landscape' && screen.width == 640 && screen.height == 360) {
601 window.widget.prepareForTransition("fade");
602 orientation = 'landscape';
603 document.getElementById('body').style.backgroundImage = 'url(background_' + orientation + '.png)';
604 document.getElementById('body').style.backgroundColor = 'none';
605 window.widget.performTransition();
606 }
607 }
608 }
609
610 function launchCalendar()
611 {
612 try {
613 widget.openApplication(calendarApp, "");
614 window.close();
615 } catch(e) {
616 error('starting Calendar App');
617 return;
618 }
619 }
620
621 function init()
622 {
623 try {
624 // call calendar service
625 calendarService = device.getServiceObject("Service.Calendar", "IDataSource");
626 } catch(e) {
627 error('loading Calendar service');
628 return;
629 }
630
631 collectLocales();
632 updateData();
633 requestNotification();
634 window.setInterval('updateData()', 1000 * 60 * updateDataInterval);
635
636 updateScreen();
637 if (useBackgroundImage)
638 // check for screen rotation every 3 secs
639 window.setInterval('updateScreen()', 1000 * 3);
640 }
641
642 </script>
643
644 <style type="text/css">
645 table { margin:0px; padding:0px; border-spacing:0px; }
646 td { padding:0px 5px 0px 0px; white-space:nowrap; overflow:hidden; }
647 #homescreenView { width: 315px; height:91px; overflow:hidden; }
648 #calendarList { position:absolute; left:10px; top:4px; width:295px; height:75px; overflow:hidden; }
649 </style>
650
651 </head>
652
653 <body id="body" class="background">
654 <div id="homescreenView">
655 <div id="calendarList"></div>
656 </div>
657 </body>
658
659 </html>