Attachment 'HackedMonthCalendar.py'
Download 1 """
2 ##
3 ## Great!!
4 ## 100% invalid html 4.01 strict - and all for free!! So what do you want more??
5 ##
6
7 MoinMoin - HackedMonthCalendar Macro
8
9 You can use this macro to put a month's calendar page on a Wiki page.
10
11 The days are links to Wiki pages following this naming convention:
12 BasePageName/year-month-day
13
14 @copyright: 2002-2005 by Thomas Waldmann <ThomasWaldmann@gmx.de>
15 @copyright: 2007-forever by Oliver Siemoneit
16 @license: GNU GPL - see COPYING for details.
17
18 Revisions:
19 * first revision without a number (=1.0):
20 * was only online for a few hours and then replaced by 1.1
21 * 1.1:
22 * changed name to MonthCalendar to avoid conflict with "calendar" under case-insensitive OSes like Win32
23 * days as subpages
24 * basepage argument
25 * change order of year/month argument
26 * browsing links to prev/next month/year
27 * current limitation: you can only browse one calendar on the same
28 page/url, if you try to browse another calendar on the same page,
29 the first one jumps back to its original display
30 * show basepage in calendar header if basepage<>currentpage
31 * 1.2:
32 * minor fixes in argument parsing
33 * cosmetic fix for netscape, other cosmetic changes, changed css
34 * i18n support (weekday short names)
35 * 1.3:
36 * fixes to run with MoinMoin 0.11, thanks to JuergenHermann
37 * fix: withspace before "," allowed in argument list
38 * BasePage in calendar header (if present) is a link now
39 * more i18n
40 * HTML cleanup, generating code avoids bracketing errors
41 * colour cosmetics
42 * 1.4:
43 * new parameter for enabling fixed height of 6 "calendar weeks",
44 if you want to show a whole year's calendar, this just looks
45 better than having some months with 4, some with 5 and some with 6.
46 * group calendaring functions:
47 * you can give mutliple BasePages UserName1*UserName2*UserName3
48 * first BasePage is considered "your" Basepage,
49 used days are bright red
50 * 2nd and all other BasePages are considered "others" BasePages
51 and lead to an increasing green component the more "used" days
52 the others have. So white gets greener and red gets more yellowish.
53 * in the head part of the calendar, you can click on each name
54 to get to the Page of the same name
55 * colouring of my and others BasePage is done in a way to show
56 the colouring used in the calendar:
57 * others use green colouring (increasingly green if multiply used)
58 * I use red colouring, which gets more and more yellowish as
59 the day is used by more and more others, too
60 * 1.5:
61 * fixed username colouring when using a BasePage
62 * fixed navigation header of MonthCalendar not to get broken into
63 multiple lines
64 * fixed SubPage handling (please do not use relative SubPages like
65 /SubPage yet. Use MyName/SubPage.)
66 * 1.6:
67 * syntactic cleanup
68 * removed i18n compatibility for moin<1.1 or cvs<2003-06-10
69 * integrated Scott Chapman's changes:
70 * Made it configurable for Sunday or Monday as the first day of the week.
71 Search for "change here".
72 * Made it so that today is not only set to a seperate css style, but also boldfaced.
73 Some browsers don't show the other css style (Netscape).
74 * Made it so weekend dates have different color.
75 * 1.7:
76 * added request parameter where needed
77 * 1.8:
78 * some fixes for moin 1.2 (use this version ONLY if you run moin 1.2, too):
79 * .value backtrace fixed when selecting next/prev month/year
80 * request param added to macro function
81 * 1.9:
82 * adapted to moin 1.3
83 * 2.0:
84 * integrated into moin 1.3
85 * added some nice JS (thanks to Klaus Knopper) to show nice mouseovers
86 showing a preview of the day page linked (use first level headlines
87 to make entries)
88 * merged "common navigation" change of OliverGraf
89 * merged AnnualMonthlyCalendar change of JonathanDietrich
90 * 2.1:
91 * fixed CSS for IE users
92 * fix javascript for IE4
93 * do a correct calculation of "today" using user's timezone
94 * 2.2:
95 * added template argument for specifying an edit template for new pages
96 * 2.3:
97 * MonthCalender macro messed by Oliver Siemoneit in only two hours by adding some
98 preview frame which is not allowed in html 4.01 strict...
99
100 Usage:
101 [[MonthCalendar(BasePage,year,month,monthoffset,monthoffset2,height6)]]
102
103 each parameter can be empty and then defaults to currentpage or currentdate or monthoffset=0
104
105 Samples (paste that to one of your pages for a first try):
106
107 Calendar of current month for current page:
108 [[MonthCalendar]]
109
110 Calendar of last month:
111 [[MonthCalendar(,,,-1)]]
112
113 Calendar of next month:
114 [[MonthCalendar(,,,+1)]]
115
116 Calendar of Page SampleUser, this years december:
117 [[MonthCalendar(SampleUser,,12)]]
118
119 Calendar of current Page, this years december:
120 [[MonthCalendar(,,12)]]
121
122 Calendar of December, 2001:
123 [[MonthCalendar(,2001,12)]]
124
125 Calendar of the month two months after December, 2001
126 (maybe doesn't make much sense, but is possible)
127 [[MonthCalendar(,2001,12,+2)]]
128
129 Calendar of year 2002 (every month padded to height of 6):
130 ||||||Year 2002||
131 ||[[MonthCalendar(,2002,1,,,1)]]||[[MonthCalendar(,2002,2,,,1)]]||[[MonthCalendar(,2002,3,,,1)]]||
132 ||[[MonthCalendar(,2002,4,,,1)]]||[[MonthCalendar(,2002,5,,,1)]]||[[MonthCalendar(,2002,6,,,1)]]||
133 ||[[MonthCalendar(,2002,7,,,1)]]||[[MonthCalendar(,2002,8,,,1)]]||[[MonthCalendar(,2002,9,,,1)]]||
134 ||[[MonthCalendar(,2002,10,,,1)]]||[[MonthCalendar(,2002,11,,,1)]]||[[MonthCalendar(,2002,12,,,1)]]||
135
136 Current calendar of me, also showing entries of A and B:
137 [[MonthCalendar(MyPage*TestUserA*TestUserB)]]
138
139 SubPage calendars:
140 [[MonthCalendar(MyName/CalPrivate)]]
141 [[MonthCalendar(MyName/CalBusiness)]]
142 [[MonthCalendar(MyName/CalBusiness*MyName/CalPrivate)]]
143
144
145 Anniversary Calendars: (no year data)
146 [[MonthCalendar(Yearly,,,+1,,6,1)]]
147
148 This creates calendars of the format Yearly/MM-DD
149 By leaving out the year, you can set birthdays, and anniversaries in this
150 calendar and not have to re-enter each year.
151
152 This creates a calendar which uses MonthCalendarTemplate for directly editing
153 nonexisting day pages:
154 [[MonthCalendar(,,,,,,MonthCalendarTemplate)]]
155 """
156
157 Dependencies = ['namespace', 'time', ]
158
159 from MoinMoin import wikiutil
160 from MoinMoin.Page import Page
161 import re, calendar, time
162
163 # The following line sets the calendar to have either Sunday or Monday as
164 # the first day of the week. Only SUNDAY or MONDAY (case sensitive) are
165 # valid here. All other values will not make good calendars.
166 # If set to Sunday, the calendar is displayed at "March 2003" vs. "2003 / 3" also.
167 # XXX change here ----------------vvvvvv
168 calendar.setfirstweekday(calendar.MONDAY)
169
170 def cliprgb(r, g, b): # don't use 255!
171 if r < 0: r = 0
172 if r > 254: r = 254
173 if b < 0: b = 0
174 if b > 254: b = 254
175 if g < 0: g = 0
176 if g > 254: g = 254
177 return r, g, b
178
179 def yearmonthplusoffset(year, month, offset):
180 month = month+offset
181 # handle offset and under/overflows - quick and dirty, yes!
182 while month < 1:
183 month = month + 12
184 year = year - 1
185 while month > 12:
186 month = month - 12
187 year = year + 1
188 return year, month
189
190 def parseargs(args, defpagename, defyear, defmonth, defoffset, defoffset2, defheight6, defanniversary, deftemplate):
191 strpagename = args.group('basepage')
192 if strpagename:
193 parmpagename = wikiutil.unquoteWikiname(strpagename)
194 else:
195 parmpagename = defpagename
196 # multiple pagenames separated by "*" - split into list of pagenames
197 parmpagename = re.split(r'\*', parmpagename)
198
199 stryear = args.group('year')
200 if stryear:
201 parmyear = int(stryear)
202 else:
203 parmyear = defyear
204
205 strmonth = args.group('month')
206 if strmonth:
207 parmmonth = int(strmonth)
208 else:
209 parmmonth = defmonth
210
211 stroffset = args.group('offset')
212 if stroffset:
213 parmoffset = int(stroffset)
214 else:
215 parmoffset = defoffset
216
217 stroffset2 = args.group('offset2')
218 if stroffset2:
219 parmoffset2 = int(stroffset2)
220 else:
221 parmoffset2 = defoffset2
222
223 strheight6 = args.group('height6')
224 if strheight6:
225 parmheight6 = int(strheight6)
226 else:
227 parmheight6 = defheight6
228
229 stranniversary = args.group('anniversary')
230 if stranniversary:
231 parmanniversary = int(stranniversary)
232 else:
233 parmanniversary = defanniversary
234
235 strtemplate = args.group('template')
236 if strtemplate:
237 parmtemplate = wikiutil.unquoteWikiname(strtemplate)
238 else:
239 parmtemplate = deftemplate
240 return parmpagename, parmyear, parmmonth, parmoffset, parmoffset2, parmheight6, parmanniversary, parmtemplate
241
242 # FIXME: vvvvvv is there a better way for matching a pagename ?
243 _arg_basepage = r'\s*(?P<basepage>[^, ]+)?\s*'
244 _arg_year = r',\s*(?P<year>\d+)?\s*'
245 _arg_month = r',\s*(?P<month>\d+)?\s*'
246 _arg_offset = r',\s*(?P<offset>[+-]?\d+)?\s*'
247 _arg_offset2 = r',\s*(?P<offset2>[+-]?\d+)?\s*'
248 _arg_height6 = r',\s*(?P<height6>[+-]?\d+)?\s*'
249 _arg_anniversary = r',\s*(?P<anniversary>[+-]?\d+)?\s*'
250 _arg_template = r',\s*(?P<template>[^, ]+)?\s*' # XXX see basepage comment
251 _args_re_pattern = r'^(%s)?(%s)?(%s)?(%s)?(%s)?(%s)?(%s)?(%s)?$' % \
252 (_arg_basepage, _arg_year, _arg_month,
253 _arg_offset, _arg_offset2, _arg_height6, _arg_anniversary, _arg_template)
254
255
256 def execute(macro, text):
257 request = macro.request
258 formatter = macro.formatter
259 _ = request.getText
260
261 # return immediately if getting links for the current page
262 if request.mode_getpagelinks:
263 return ''
264
265 args_re = re.compile(_args_re_pattern)
266
267 currentyear, currentmonth, currentday, h, m, s, wd, yd, ds = request.user.getTime(time.time())
268 thispage = formatter.page.page_name
269 # does the url have calendar params (= somebody has clicked on prev/next links in calendar) ?
270 if macro.form.has_key('calparms'):
271 text2 = macro.form['calparms'][0]
272 args2 = args_re.match(text2)
273 if not args2:
274 return ('<p><strong class="error">%s</strong></p>' % _('Invalid MonthCalendar calparms "%s"!')) % (text2,)
275 else:
276 has_calparms = 1 # yes!
277 cparmpagename, cparmyear, cparmmonth, cparmoffset, cparmoffset2, cparmheight6, cparmanniversary, cparmtemplate = \
278 parseargs(args2, thispage, currentyear, currentmonth, 0, 0, 0, 0, '')
279 else:
280 has_calparms = 0
281
282 if text is None: # macro call without parameters
283 parmpagename, parmyear, parmmonth, parmoffset, parmoffset2, parmheight6, anniversary, parmtemplate = \
284 [thispage], currentyear, currentmonth, 0, 0, 0, 0, ''
285 else:
286 # parse and check arguments
287 args = args_re.match(text)
288 if not args:
289 return ('<p><strong class="error">%s</strong></p>' % _('Invalid MonthCalendar arguments "%s"!')) % (text,)
290 else:
291 parmpagename, parmyear, parmmonth, parmoffset, parmoffset2, parmheight6, anniversary, parmtemplate = \
292 parseargs(args, thispage, currentyear, currentmonth, 0, 0, 0, 0, '')
293
294 # does url have calendar params and is THIS the right calendar to modify (we can have multiple
295 # calendars on the same page)?
296 #if has_calparms and (cparmpagename,cparmyear,cparmmonth,cparmoffset) == (parmpagename,parmyear,parmmonth,parmoffset):
297
298 # move all calendars when using the navigation:
299 if has_calparms and cparmpagename == parmpagename:
300 year, month = yearmonthplusoffset(parmyear, parmmonth, parmoffset + cparmoffset2)
301 parmoffset2 = cparmoffset2
302 parmtemplate = cparmtemplate
303 else:
304 year, month = yearmonthplusoffset(parmyear, parmmonth, parmoffset)
305
306 # get the calendar
307 monthcal = calendar.monthcalendar(year, month)
308
309 # european / US differences
310 months = ('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December')
311 # Set things up for Monday or Sunday as the first day of the week
312 if calendar.firstweekday() == calendar.MONDAY:
313 wkend = (5, 6)
314 wkdays = ('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun')
315 if calendar.firstweekday() == calendar.SUNDAY:
316 wkend = (0, 6)
317 wkdays = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat')
318
319 colorstep = 85
320 p = Page(request, thispage)
321 qpagenames = '*'.join(map(wikiutil.quoteWikinameURL, parmpagename))
322 qtemplate = wikiutil.quoteWikinameURL(parmtemplate)
323 querystr = "calparms=%%s,%d,%d,%d,%%d,%%s" % (parmyear, parmmonth, parmoffset)
324 prevlink = p.url(request, querystr % (qpagenames, parmoffset2 - 1, qtemplate), escape=0)
325 nextlink = p.url(request, querystr % (qpagenames, parmoffset2 + 1, qtemplate), escape=0)
326 prevylink = p.url(request, querystr % (qpagenames, parmoffset2 - 12, qtemplate), escape=0)
327 nextylink = p.url(request, querystr % (qpagenames, parmoffset2 + 12, qtemplate), escape=0)
328 prevmonth = formatter.url(1, prevlink, 'cal-link') + '<' + formatter.url(0)
329 nextmonth = formatter.url(1, nextlink, 'cal-link') + '>' + formatter.url(0)
330 prevyear = formatter.url(1, prevylink, 'cal-link') + '<<' + formatter.url(0)
331 nextyear = formatter.url(1, nextylink, 'cal-link') + '>>' + formatter.url(0)
332
333 if parmpagename != [thispage]:
334 pagelinks = ''
335 r, g, b = (255, 0, 0)
336 l = len(parmpagename[0])
337 steps = len(parmpagename)
338 maxsteps = (255 / colorstep)
339 if steps > maxsteps:
340 steps = maxsteps
341 chstep = int(l / steps)
342 st = 0
343 while st < l:
344 ch = parmpagename[0][st:st+chstep]
345 r, g, b = cliprgb(r, g, b)
346 link = Page(request, parmpagename[0]).link_to(request, ch,
347 style='background-color:#%02x%02x%02x;color:#000000;text-decoration:none' % (r, g, b))
348 pagelinks = pagelinks + link
349 r, g, b = (r, g+colorstep, b)
350 st = st + chstep
351 r, g, b = (255-colorstep, 255, 255-colorstep)
352 for page in parmpagename[1:]:
353 link = Page(request, page).link_to(request, page,
354 style='background-color:#%02x%02x%02x;color:#000000;text-decoration:none' % (r, g, b))
355 pagelinks = pagelinks + '*' + link
356 showpagename = ' %s<BR>\n' % pagelinks
357 else:
358 showpagename = ''
359 if calendar.firstweekday() == calendar.SUNDAY:
360 resth1 = ' <th colspan="7" class="cal-header">\n' \
361 '%s' \
362 ' %s %s <b> %s %s</b> %s\n %s\n' \
363 ' </th>\n' % (showpagename, prevyear, prevmonth, months[month-1], str(year), nextmonth, nextyear)
364 if calendar.firstweekday() == calendar.MONDAY:
365 resth1 = ' <th colspan="7" class="cal-header">\n' \
366 '%s' \
367 ' %s %s <b> %s / %s</b> %s\n %s\n' \
368 ' </th>\n' % (showpagename, prevyear, prevmonth, str(year), month, nextmonth, nextyear)
369 restr1 = ' <tr>\n%s </tr>\n' % resth1
370
371 r7 = range(7)
372 restd2 = []
373 for wkday in r7:
374 wday = _(wkdays[wkday])
375 if wkday in wkend:
376 cssday = "cal-weekend"
377 else:
378 cssday = "cal-workday"
379 restd2.append(' <td class="%s" width="14%%">%s</td>\n' % (cssday, wday))
380 restr2 = ' <tr>\n%s </tr>\n' % "".join(restd2)
381
382 if parmheight6:
383 while len(monthcal) < 6:
384 monthcal = monthcal + [[0, 0, 0, 0, 0, 0, 0]]
385
386 maketip_js = []
387 restrn = []
388 for week in monthcal:
389 restdn = []
390 for wkday in r7:
391 day = week[wkday]
392 if not day:
393 restdn.append(' <td class="cal-invalidday"> </td>\n')
394 else:
395 page = parmpagename[0]
396 if anniversary:
397 link = "%s/%02d-%02d" % (page, month, day)
398 else:
399 link = "%s/%4d-%02d-%02d" % (page, year, month, day)
400 daypage = Page(request, link)
401 if daypage.exists():
402 csslink = "cal-usedday"
403 query = {}
404 r, g, b, u = (255, 0, 0, 1)
405 daycontent = daypage.get_raw_body()
406 header1_re = re.compile(r'^\s*=\s(.*)\s=$', re.MULTILINE) # re.UNICODE
407 titletext = []
408 for match in header1_re.finditer(daycontent):
409 if match:
410 title = match.group(1)
411 title = wikiutil.escape(title).replace("'", "\\'")
412 titletext.append(title)
413 tipname = link
414 tiptitle = link
415 tiptext = '<br>'.join(titletext)
416 maketip_js.append("maketip('%s','%s','%s');" % (tipname, tiptitle, tiptext))
417 onmouse = {'onClick': "updatePreview('%s', ''); return false;" % link,
418 'onMouseOver': "tip('%s')" % tipname,
419 'onMouseOut': "untip()"}
420 else:
421 csslink = "cal-emptyday"
422 if parmtemplate:
423 query = parmtemplate
424 else:
425 query = 'none'
426 r, g, b, u = (255, 255, 255, 0)
427 if wkday in wkend:
428 csslink = "cal-weekend"
429 onmouse = {'onClick': "updatePreview('%s', '%s'); return false;" % (link, query)}
430 for otherpage in parmpagename[1:]:
431 otherlink = "%s/%4d-%02d-%02d" % (otherpage, year, month, day)
432 otherdaypage = Page(request, otherlink)
433 if otherdaypage.exists():
434 csslink = "cal-usedday"
435 if u == 0:
436 r, g, b = (r-colorstep, g, b-colorstep)
437 else:
438 r, g, b = (r, g+colorstep, b)
439 r, g, b = cliprgb(r, g, b)
440 style = 'background-color:#%02x%02x%02x' % (r, g, b)
441 fmtlink = formatter.url(1, "#", csslink, **onmouse) + str(day) + formatter.url(0)
442 if day == currentday and month == currentmonth and year == currentyear:
443 cssday = "cal-today"
444 fmtlink = "<b>%s</b>" % fmtlink # for browser with CSS probs
445 else:
446 cssday = "cal-nottoday"
447 restdn.append(' <td style="%s" class="%s">%s</td>\n' % (style, cssday, fmtlink))
448 restrn.append(' <tr>\n%s </tr>\n' % "".join(restdn))
449
450 restable = '<table border="2" cellspacing="2" cellpadding="2">\n%s%s%s</table>\n'
451 restable = restable % (restr1, restr2, "".join(restrn))
452
453 result = """\
454 <script language="JavaScript" type="text/javascript" src="%s/common/js/infobox.js"></script>
455 <script language="JavaScript" type="text/javascript">
456 <!--
457 function updatePreview(link, template) {
458 var preview = document.getElementById('calendar_preview');
459 if(template == ''){
460 preview.setAttribute("src", link);
461 }
462 else if(template == 'none') {
463 preview.setAttribute("src", link + + "?action=edit");
464 }
465 else {
466 preview.setAttribute("src", link + "?action=edit&template=" + template);
467 }
468 }
469 // -->
470 </script>
471 <div id="infodiv" style="position:absolute; visibility:hidden; z-index:20; top:-999em; left:0px;"></div>
472 <script language="JavaScript" type="text/javascript">
473 <!--
474 %s
475 // -->
476 </script>
477 %s
478 <br>
479 <iframe src="" width="800px" height="400px" id="calendar_preview">
480 <p>%s</p>
481 </iframe>
482 """ % (request.cfg.url_prefix_static, "\n".join(maketip_js), restable, _('Your browser does not support inlined frames.'))
483 return formatter.rawHTML(result)
484
485 # EOF
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.