Back to index

moin  1.9.0~rc2
Functions | Variables
MoinMoin.macro.MonthCalendar Namespace Reference

Functions

def cliprgb
def yearmonthplusoffset
def parseargs
def execute

Variables

list Dependencies = ['namespace', 'time', ]

Detailed Description

MoinMoin - MonthCalendar Macro

You can use this macro to put a month's calendar page on a Wiki page.

The days are links to Wiki pages following this naming convention:
BasePageName/year-month-day

@copyright: 2002-2009 MoinMoin:ThomasWaldmann
@license: GNU GPL, see COPYING for details.

Revisions:
* first revision without a number (=1.0):
    * was only online for a few hours and then replaced by 1.1
* 1.1:
    * changed name to MonthCalendar to avoid conflict with "calendar" under case-insensitive OSes like Win32
    * days as subpages
    * basepage argument
    * change order of year/month argument
    * browsing links to prev/next month/year
        * current limitation: you can only browse one calendar on the same
          page/url, if you try to browse another calendar on the same page,
          the first one jumps back to its original display
* show basepage in calendar header if basepage<>currentpage
* 1.2:
    * minor fixes in argument parsing
    * cosmetic fix for netscape, other cosmetic changes, changed css
    * i18n support (weekday short names)
* 1.3:
    * fixes to run with MoinMoin 0.11, thanks to JuergenHermann
    * fix: withspace before "," allowed in argument list
    * BasePage in calendar header (if present) is a link now
    * more i18n
    * HTML cleanup, generating code avoids bracketing errors
    * colour cosmetics
* 1.4:
    * new parameter for enabling fixed height of 6 "calendar weeks",
      if you want to show a whole year's calendar, this just looks
      better than having some months with 4, some with 5 and some with 6.
    * group calendaring functions:
      * you can give mutliple BasePages UserName1*UserName2*UserName3
      * first BasePage is considered "your" Basepage,
        used days are bright red
      * 2nd and all other BasePages are considered "others" BasePages
        and lead to an increasing green component the more "used" days
        the others have. So white gets greener and red gets more yellowish.
      * in the head part of the calendar, you can click on each name
        to get to the Page of the same name
      * colouring of my and others BasePage is done in a way to show
        the colouring used in the calendar:
      * others use green colouring (increasingly green if multiply used)
      * I use red colouring, which gets more and more yellowish as
        the day is used by more and more others, too
* 1.5:
    * fixed username colouring when using a BasePage
    * fixed navigation header of MonthCalendar not to get broken into
      multiple lines
    * fixed SubPage handling (please do not use relative SubPages like
      /SubPage yet. Use MyName/SubPage.)
* 1.6:
    * syntactic cleanup
    * removed i18n compatibility for moin<1.1 or cvs<2003-06-10
    * integrated Scott Chapman's changes:
        * Made it configurable for Sunday or Monday as the first day of the week.
          Search for "change here".
        * Made it so that today is not only set to a seperate css style, but also boldfaced.
          Some browsers don't show the other css style (Netscape).
        * Made it so weekend dates have different color.
* 1.7:
    * added request parameter where needed
* 1.8:
    * some fixes for moin 1.2 (use this version ONLY if you run moin 1.2, too):
        * .value backtrace fixed when selecting next/prev month/year
        * request param added to macro function
* 1.9:
    * adapted to moin 1.3
* 2.0:
    * integrated into moin 1.3
    * added some nice JS (thanks to Klaus Knopper) to show nice mouseovers
      showing a preview of the day page linked (use first level headlines
      to make entries)
    * merged "common navigation" change of OliverGraf
    * merged AnnualMonthlyCalendar change of JonathanDietrich
* 2.1:
    * fixed CSS for IE users
    * fix javascript for IE4
    * do a correct calculation of "today" using user's timezone
* 2.2:
    * added template argument for specifying an edit template for new pages
* 2.3:
    * adapted to moin 1.7 new macro parameter parsing

Usage:
    <<MonthCalendar(BasePage,year,month,monthoffset,monthoffset2,height6,anniversary,template)>>

    each parameter can be empty and then defaults to currentpage or currentdate or monthoffset=0

Samples (paste that to one of your pages for a first try):

Calendar of current month for current page:
<<MonthCalendar>>

Calendar of last month:
<<MonthCalendar(,,,-1)>>

Calendar of next month:
<<MonthCalendar(,,,+1)>>

Calendar of Page SampleUser, this years december:
<<MonthCalendar(SampleUser,,12)>>

Calendar of current Page, this years december:
<<MonthCalendar(,,12)>>

Calendar of December, 2001:
<<MonthCalendar(,2001,12)>>

Calendar of the month two months after December, 2001
(maybe doesn't make much sense, but is possible)
<<MonthCalendar(,2001,12,+2)>>

Calendar of year 2002 (every month padded to height of 6):
||||||Year 2002||
||<<MonthCalendar(,2002,1,,,1)>>||<<MonthCalendar(,2002,2,,,1)>>||<<MonthCalendar(,2002,3,,,1)>>||
||<<MonthCalendar(,2002,4,,,1)>>||<<MonthCalendar(,2002,5,,,1)>>||<<MonthCalendar(,2002,6,,,1)>>||
||<<MonthCalendar(,2002,7,,,1)>>||<<MonthCalendar(,2002,8,,,1)>>||<<MonthCalendar(,2002,9,,,1)>>||
||<<MonthCalendar(,2002,10,,,1)>>||<<MonthCalendar(,2002,11,,,1)>>||<<MonthCalendar(,2002,12,,,1)>>||

Current calendar of me, also showing entries of A and B:
<<MonthCalendar(MyPage*TestUserA*TestUserB)>>

SubPage calendars:
<<MonthCalendar(MyName/CalPrivate)>>
<<MonthCalendar(MyName/CalBusiness)>>
<<MonthCalendar(MyName/CalBusiness*MyName/CalPrivate)>>


Anniversary Calendars: (no year data)
<<MonthCalendar(Yearly,,,+1,,6,1)>>

This creates calendars of the format Yearly/MM-DD
By leaving out the year, you can set birthdays, and anniversaries in this
calendar and not have to re-enter each year.

This creates a calendar which uses MonthCalendarTemplate for directly editing
nonexisting day pages:
<<MonthCalendar(,,,,,,,MonthCalendarTemplate)>>

Function Documentation

def MoinMoin.macro.MonthCalendar.cliprgb (   r,
  g,
  b 
)
clip r,g,b values into range 0..254 

Definition at line 164 of file MonthCalendar.py.

00164 
00165 def cliprgb(r, g, b):
00166     """ clip r,g,b values into range 0..254 """
00167     def clip(x):
00168         """ clip x value into range 0..254 """
00169         if x < 0:
00170             x = 0
00171         elif x > 254:
00172             x = 254
00173         return x
00174     return clip(r), clip(g), clip(b)

Here is the caller graph for this function:

def MoinMoin.macro.MonthCalendar.execute (   macro,
  text 
)

Definition at line 206 of file MonthCalendar.py.

00206 
00207 def execute(macro, text):
00208     request = macro.request
00209     formatter = macro.formatter
00210     _ = request.getText
00211 
00212     # return immediately if getting links for the current page
00213     if request.mode_getpagelinks:
00214         return ''
00215 
00216     currentyear, currentmonth, currentday, h, m, s, wd, yd, ds = request.user.getTime(time.time())
00217     thispage = formatter.page.page_name
00218     # does the url have calendar params (= somebody has clicked on prev/next links in calendar) ?
00219     if 'calparms' in macro.request.args:
00220         has_calparms = 1 # yes!
00221         text2 = macro.request.args['calparms']
00222         cparmpagename, cparmyear, cparmmonth, cparmoffset, cparmoffset2, cparmheight6, cparmanniversary, cparmtemplate = \
00223             parseargs(request, text2, thispage, currentyear, currentmonth, 0, 0, False, False, u'')
00224         # Note: cparmheight6 and cparmanniversary are not used, they are just there
00225         # to have a consistent parameter string in calparms and macro args
00226     else:
00227         has_calparms = 0
00228 
00229     if text is None: # macro call without parameters
00230         text = u''
00231 
00232     # parse and check arguments
00233     parmpagename, parmyear, parmmonth, parmoffset, parmoffset2, parmheight6, anniversary, parmtemplate = \
00234         parseargs(request, text, thispage, currentyear, currentmonth, 0, 0, False, False, u'')
00235 
00236     # does url have calendar params and is THIS the right calendar to modify (we can have multiple
00237     # calendars on the same page)?
00238     #if has_calparms and (cparmpagename,cparmyear,cparmmonth,cparmoffset) == (parmpagename,parmyear,parmmonth,parmoffset):
00239 
00240     # move all calendars when using the navigation:
00241     if has_calparms and cparmpagename == parmpagename:
00242         year, month = yearmonthplusoffset(parmyear, parmmonth, parmoffset + cparmoffset2)
00243         parmoffset2 = cparmoffset2
00244         parmtemplate = cparmtemplate
00245     else:
00246         year, month = yearmonthplusoffset(parmyear, parmmonth, parmoffset)
00247 
00248     if request.isSpiderAgent and abs(currentyear - year) > 1:
00249         return '' # this is a bot and it didn't follow the rules (see below)
00250     if currentyear == year:
00251         attrs = {}
00252     else:
00253         attrs = {'rel': 'nofollow' } # otherwise even well-behaved bots will index forever
00254 
00255     # get the calendar
00256     monthcal = calendar.monthcalendar(year, month)
00257 
00258     # european / US differences
00259     months = ('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December')
00260     # Set things up for Monday or Sunday as the first day of the week
00261     if calendar.firstweekday() == calendar.MONDAY:
00262         wkend = (5, 6)
00263         wkdays = ('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun')
00264     if calendar.firstweekday() == calendar.SUNDAY:
00265         wkend = (0, 6)
00266         wkdays = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat')
00267 
00268     colorstep = 85
00269     p = Page(request, thispage)
00270     qpagenames = '*'.join([wikiutil.quoteWikinameURL(pn) for pn in parmpagename])
00271     qtemplate = wikiutil.quoteWikinameURL(parmtemplate)
00272     querystr = "calparms=%%s,%d,%d,%d,%%d,,,%%s" % (parmyear, parmmonth, parmoffset)
00273     prevlink = p.url(request, querystr % (qpagenames, parmoffset2 - 1, qtemplate))
00274     nextlink = p.url(request, querystr % (qpagenames, parmoffset2 + 1, qtemplate))
00275     prevylink = p.url(request, querystr % (qpagenames, parmoffset2 - 12, qtemplate))
00276     nextylink = p.url(request, querystr % (qpagenames, parmoffset2 + 12, qtemplate))
00277 
00278     prevmonth = formatter.url(1, prevlink, 'cal-link', **attrs) + '&lt;' + formatter.url(0)
00279     nextmonth = formatter.url(1, nextlink, 'cal-link', **attrs) + '&gt;' + formatter.url(0)
00280     prevyear = formatter.url(1, prevylink, 'cal-link', **attrs) + '&lt;&lt;' + formatter.url(0)
00281     nextyear = formatter.url(1, nextylink, 'cal-link', **attrs) + '&gt;&gt;' + formatter.url(0)
00282 
00283     if parmpagename != [thispage]:
00284         pagelinks = ''
00285         r, g, b = (255, 0, 0)
00286         l = len(parmpagename[0])
00287         steps = len(parmpagename)
00288         maxsteps = (255 / colorstep)
00289         if steps > maxsteps:
00290             steps = maxsteps
00291         chstep = int(l / steps)
00292         st = 0
00293         while st < l:
00294             ch = parmpagename[0][st:st+chstep]
00295             r, g, b = cliprgb(r, g, b)
00296             link = Page(request, parmpagename[0]).link_to(request, ch,
00297                         rel='nofollow',
00298                         style='background-color:#%02x%02x%02x;color:#000000;text-decoration:none' % (r, g, b))
00299             pagelinks = pagelinks + link
00300             r, g, b = (r, g+colorstep, b)
00301             st = st + chstep
00302         r, g, b = (255-colorstep, 255, 255-colorstep)
00303         for page in parmpagename[1:]:
00304             link = Page(request, page).link_to(request, page,
00305                         rel='nofollow',
00306                         style='background-color:#%02x%02x%02x;color:#000000;text-decoration:none' % (r, g, b))
00307             pagelinks = pagelinks + '*' + link
00308         showpagename = '   %s<BR>\n' % pagelinks
00309     else:
00310         showpagename = ''
00311     if calendar.firstweekday() == calendar.SUNDAY:
00312         resth1 = '  <th colspan="7" class="cal-header">\n' \
00313                  '%s' \
00314                  '   %s&nbsp;%s&nbsp;<b>&nbsp;%s&nbsp;%s</b>&nbsp;%s\n&nbsp;%s\n' \
00315                  '  </th>\n' % (showpagename, prevyear, prevmonth, months[month-1], str(year), nextmonth, nextyear)
00316     if calendar.firstweekday() == calendar.MONDAY:
00317         resth1 = '  <th colspan="7" class="cal-header">\n' \
00318                  '%s' \
00319                  '   %s&nbsp;%s&nbsp;<b>&nbsp;%s&nbsp;/&nbsp;%s</b>&nbsp;%s\n&nbsp;%s\n' \
00320                  '  </th>\n' % (showpagename, prevyear, prevmonth, str(year), month, nextmonth, nextyear)
00321     restr1 = ' <tr>\n%s </tr>\n' % resth1
00322 
00323     r7 = range(7)
00324     restd2 = []
00325     for wkday in r7:
00326         wday = _(wkdays[wkday])
00327         if wkday in wkend:
00328             cssday = "cal-weekend"
00329         else:
00330             cssday = "cal-workday"
00331         restd2.append('  <td class="%s">%s</td>\n' % (cssday, wday))
00332     restr2 = ' <tr>\n%s </tr>\n' % "".join(restd2)
00333 
00334     if parmheight6:
00335         while len(monthcal) < 6:
00336             monthcal = monthcal + [[0, 0, 0, 0, 0, 0, 0]]
00337 
00338     maketip_js = []
00339     restrn = []
00340     for week in monthcal:
00341         restdn = []
00342         for wkday in r7:
00343             day = week[wkday]
00344             if not day:
00345                 restdn.append('  <td class="cal-invalidday">&nbsp;</td>\n')
00346             else:
00347                 page = parmpagename[0]
00348                 if anniversary:
00349                     link = "%s/%02d-%02d" % (page, month, day)
00350                 else:
00351                     link = "%s/%4d-%02d-%02d" % (page, year, month, day)
00352                 daypage = Page(request, link)
00353                 if daypage.exists() and request.user.may.read(link):
00354                     csslink = "cal-usedday"
00355                     query = {}
00356                     r, g, b, u = (255, 0, 0, 1)
00357                     daycontent = daypage.get_raw_body()
00358                     header1_re = re.compile(r'^\s*=\s(.*)\s=$', re.MULTILINE) # re.UNICODE
00359                     titletext = []
00360                     for match in header1_re.finditer(daycontent):
00361                         if match:
00362                             title = match.group(1)
00363                             title = wikiutil.escape(title).replace("'", "\\'")
00364                             titletext.append(title)
00365                     link = wikiutil.escape(link).replace("'", "\\'")
00366                     tipname = link
00367                     tiptitle = link
00368                     tiptext = '<br>'.join(titletext)
00369                     maketip_js.append("maketip('%s','%s','%s');" % (tipname, tiptitle, tiptext))
00370                     attrs = {'onMouseOver': "tip('%s')" % tipname,
00371                              'onMouseOut': "untip()"}
00372                 else:
00373                     csslink = "cal-emptyday"
00374                     if parmtemplate:
00375                         query = {'action': 'edit', 'template': parmtemplate}
00376                     else:
00377                         query = {}
00378                     r, g, b, u = (255, 255, 255, 0)
00379                     if wkday in wkend:
00380                         csslink = "cal-weekend"
00381                     attrs = {'rel': 'nofollow'}
00382                 for otherpage in parmpagename[1:]:
00383                     otherlink = "%s/%4d-%02d-%02d" % (otherpage, year, month, day)
00384                     otherdaypage = Page(request, otherlink)
00385                     if otherdaypage.exists():
00386                         csslink = "cal-usedday"
00387                         if u == 0:
00388                             r, g, b = (r-colorstep, g, b-colorstep)
00389                         else:
00390                             r, g, b = (r, g+colorstep, b)
00391                 r, g, b = cliprgb(r, g, b)
00392                 style = 'background-color:#%02x%02x%02x' % (r, g, b)
00393                 fmtlink = formatter.url(1, daypage.url(request, query), csslink, **attrs) + str(day) + formatter.url(0)
00394                 if day == currentday and month == currentmonth and year == currentyear:
00395                     cssday = "cal-today"
00396                     fmtlink = "<b>%s</b>" % fmtlink # for browser with CSS probs
00397                 else:
00398                     cssday = "cal-nottoday"
00399                 restdn.append('  <td style="%s" class="%s">%s</td>\n' % (style, cssday, fmtlink))
00400         restrn.append(' <tr>\n%s </tr>\n' % "".join(restdn))
00401 
00402     restable = '<table border="2" cellspacing="2" cellpadding="2">\n<col width="14%%" span="7">%s%s%s</table>\n'
00403     restable = restable % (restr1, restr2, "".join(restrn))
00404 
00405     if maketip_js:
00406         tip_js = '''<script language="JavaScript" type="text/javascript">
00407 <!--
00408 %s
00409 // -->
00410 </script>
00411 ''' % '\n'.join(maketip_js)
00412     else:
00413         tip_js = ''
00414 
00415     result = """\
00416 <script type="text/javascript" src="%s/common/js/infobox.js"></script>
00417 <div id="%s" style="position:absolute; visibility:hidden; z-index:20; top:-999em; left:0px;"></div>
00418 %s%s
00419 """ % (request.cfg.url_prefix_static, formatter.make_id_unique('infodiv'), tip_js, restable)
00420     return formatter.rawHTML(result)
00421 
00422 # EOF
00423 

Here is the call graph for this function:

def MoinMoin.macro.MonthCalendar.parseargs (   request,
  args,
  defpagename,
  defyear,
  defmonth,
  defoffset,
  defoffset2,
  defheight6,
  defanniversary,
  deftemplate 
)
parse macro arguments 

Definition at line 187 of file MonthCalendar.py.

00187 
00188 def parseargs(request, args, defpagename, defyear, defmonth, defoffset, defoffset2, defheight6, defanniversary, deftemplate):
00189     """ parse macro arguments """
00190     args = wikiutil.parse_quoted_separated(args, name_value=False)
00191     args += [None] * 8 # fill up with None to trigger defaults
00192     parmpagename, parmyear, parmmonth, parmoffset, parmoffset2, parmheight6, parmanniversary, parmtemplate = args[:8]
00193     parmpagename = wikiutil.get_unicode(request, parmpagename, 'pagename', defpagename)
00194     parmyear = wikiutil.get_int(request, parmyear, 'year', defyear)
00195     parmmonth = wikiutil.get_int(request, parmmonth, 'month', defmonth)
00196     parmoffset = wikiutil.get_int(request, parmoffset, 'offset', defoffset)
00197     parmoffset2 = wikiutil.get_int(request, parmoffset2, 'offset2', defoffset2)
00198     parmheight6 = wikiutil.get_bool(request, parmheight6, 'height6', defheight6)
00199     parmanniversary = wikiutil.get_bool(request, parmanniversary, 'anniversary', defanniversary)
00200     parmtemplate = wikiutil.get_unicode(request, parmtemplate, 'template', deftemplate)
00201 
00202     # multiple pagenames separated by "*" - split into list of pagenames
00203     parmpagename = re.split(r'\*', parmpagename)
00204 
00205     return parmpagename, parmyear, parmmonth, parmoffset, parmoffset2, parmheight6, parmanniversary, parmtemplate

Here is the caller graph for this function:

def MoinMoin.macro.MonthCalendar.yearmonthplusoffset (   year,
  month,
  offset 
)
calculate new year/month from year/month and offset 

Definition at line 175 of file MonthCalendar.py.

00175 
00176 def yearmonthplusoffset(year, month, offset):
00177     """ calculate new year/month from year/month and offset """
00178     month += offset
00179     # handle offset and under/overflows - quick and dirty, yes!
00180     while month < 1:
00181         month += 12
00182         year -= 1
00183     while month > 12:
00184         month -= 12
00185         year += 1
00186     return year, month

Here is the caller graph for this function:


Variable Documentation

list MoinMoin.macro.MonthCalendar.Dependencies = ['namespace', 'time', ]

Definition at line 150 of file MonthCalendar.py.