<% Site.calendar %>
macro renders a calendar version 2

Sourcecode in Site/macros.js:
1:   function calendar_macro(param) {
2:      // do nothing if there is not a single story :-))
3:      // or if archive of this site is disabled
4:      if (!this.allstories.size() || !this.preferences.getProperty("archive"))
5:         return;
6:      // define variables needed in this function
7:      var calParam = new Object();
8:      var dayParam = new Object();
9:      var weekParam = new Object();
10:     res.push();
11:  
12:     // create new calendar-object
13:     var cal = java.util.Calendar.getInstance(this.getTimeZone(), this.getLocale());
14:     var symbols = this.getDateSymbols();
15:  
16:     // render header-row of calendar
17:     var firstDayOfWeek = cal.getFirstDayOfWeek();
18:     var weekdays = symbols.getShortWeekdays();
19:     res.push();
20:     for (var i=0;i<7;i++) {
21:        dayParam.day = weekdays[(i+firstDayOfWeek-1)%7+1];
22:        this.renderSkin("calendardayheader", dayParam);
23:     }
24:     weekParam.week = res.pop();
25:     this.renderSkin("calendarweek", weekParam);
26:  
27:     cal.set(java.util.Calendar.DATE, 1);
28:     // check whether there's a day or a story in path
29:     // if so, use it to determine the month to render
30:     if (path.Story)
31:        var today = path.Story.day.toString();
32:     else if (path.Day && path.Day._prototype == "Day")
33:        var today = path.Day.groupname.toString();
34:     if (today) {
35:        // instead of using String.toDate
36:        // we do it manually here to avoid that a day like 20021001
37:        // would be changed to 20020930 in some cases
38:        cal.set(java.util.Calendar.YEAR, parseInt(today.substring(0, 4), 10));
39:        cal.set(java.util.Calendar.MONTH, parseInt(today.substring(4, 6), 10)-1);
40:     }
41:     // nr. of empty days in rendered calendar before the first day of month appears
42:     var pre = (7-firstDayOfWeek+cal.get(java.util.Calendar.DAY_OF_WEEK)) % 7;
43:     var days = cal.getActualMaximum(java.util.Calendar.DATE);
44:     var weeks = Math.ceil((pre + days) / 7);
45:     var daycnt = 1;
46:  
47:     var monthNames = symbols.getMonths();
48:     calParam.month = monthNames[cal.get(java.util.Calendar.MONTH)];
49:     calParam.year =  cal.get(java.util.Calendar.YEAR);
50:  
51:     // pre-render the year and month so we only have to append the days as we loop
52:     var currMonth = formatTimestamp(new Date(cal.getTime().getTime()), "yyyyMM");
53:     // remember the index of the first and last days within this month.
54:     // this is needed to optimize previous and next month links.
55:     var lastDayIndex = 9999999;
56:     var firstDayIndex = -1;
57:  
58:     for (var i=0;i<weeks;i++) {
59:        res.push();
60:        for (var j=0;j<7;j++) {
61:           dayParam.skin = "calendarday";
62:           if ((i == 0 && j < pre) || daycnt > days)
63:              dayParam.day = "&nbsp;";
64:           else {
65:              var currGroupname = currMonth+daycnt.format("00");
66:              var linkText = daycnt < 10 ? "&nbsp;" + daycnt + "&nbsp;" : daycnt.toString();
67:              var currGroup = this.get(currGroupname);
68:              if (currGroup) {
69:                 var idx = this.contains(currGroup);
70:                 if (idx > -1) {
71:                    if  (idx > firstDayIndex)
72:                       firstDayIndex = idx;
73:                    if (idx < lastDayIndex)
74:                       lastDayIndex = idx;
75:                 }
76:                 dayParam.day = Html.linkAsString({href: currGroup.href()}, linkText);
77:              } else {
78:                 dayParam.day = linkText;
79:              }
80:              if (currGroupname == today)
81:                 dayParam.skin = "calendarselday";
82:              daycnt++;
83:           }
84:           this.renderSkin(dayParam.skin, dayParam);
85:        }
86:        weekParam.week = res.pop();
87:        this.renderSkin("calendarweek", weekParam);
88:     }
89:     // set day to last day of month and try to render next month
90:     // check what the last day of the month is
91:     calParam.back = this.renderLinkToPrevMonth(firstDayIndex, currMonth + "01", monthNames);
92:     calParam.forward = this.renderLinkToNextMonth(lastDayIndex, currMonth + "31", monthNames);
93:     calParam.calendar = res.pop();
94:     this.renderSkin("calendar", calParam);
95:     return;
96:  }