Skip to content

Commit 87976e3

Browse files
author
Richard Jones
committed
added date selection popup windows (thanks Marcus Priesch)
1 parent 5186681 commit 87976e3

File tree

6 files changed

+253
-1
lines changed

6 files changed

+253
-1
lines changed

CHANGES.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ are given with the most recent entry first.
44
????-??-?? 0.9.0
55
Feature:
66
- added "imapServer.py" script (sf patch 934567)
7+
- added date selection popup windows (thanks Marcus Priesch)
78

89

910
2005-??-?? 0.8.3

doc/customizing.txt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Customising Roundup
33
===================
44

5-
:Version: $Revision: 1.179 $
5+
:Version: $Revision: 1.180 $
66

77
.. This document borrows from the ZopeBook section on ZPT. The original is at:
88
http://www.zope.org/Documentation/Books/ZopeBook/current/ZPT.stx
@@ -1932,6 +1932,11 @@ pretty Date properties - render the date as "dd Mon YYYY" (eg. "19
19321932
format (eg. "yesterday"). The format arguments are those used
19331933
in the standard ``strftime`` call (see the `Python Library
19341934
Reference: time module`__)
1935+
popcal Generate a link to a popup calendar which may be used to
1936+
edit the date field, for example::
1937+
1938+
<span tal:replace="structure context/due/popupCalendar" />
1939+
19351940
menu only on Link and Multilink properties - render a form select
19361941
list for this property. Takes a number of optional arguments
19371942

@@ -2141,6 +2146,9 @@ Method Description
21412146
Batch return a batch object using the supplied list
21422147
url_quote quote some text as safe for a URL (ie. space, %, ...)
21432148
html_quote quote some text as safe in HTML (ie. <, >, ...)
2149+
html_calendar renders an HTML calendar used by the
2150+
``_generic.calendar.html`` template (itself invoked by
2151+
the popupCalendar DateHTMLProperty method
21442152
=============== ========================================================
21452153

21462154
You may add additional utility methods by writing them in your tracker

roundup/cgi/templating.py

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from __future__ import nested_scopes
2121

2222
import sys, cgi, urllib, os, re, os.path, time, errno, mimetypes, csv
23+
import calendar
2324

2425
from roundup import hyperdb, date, support
2526
from roundup import i18n
@@ -1505,6 +1506,21 @@ def local(self, offset):
15051506
return DateHTMLProperty(self._client, self._classname, self._nodeid,
15061507
self._prop, self._formname, self._value, offset=offset)
15071508

1509+
def popcal(self, width=300, height=200, label= "(cal)",
1510+
form="itemSynopsis"):
1511+
"""Generate a link to a calendar pop-up window.
1512+
1513+
item: HTMLProperty e.g.: context.deadline
1514+
"""
1515+
if self.isset():
1516+
date = "&date=%s"%self._value
1517+
else :
1518+
date = ""
1519+
return ('<a class="classhelp" href="javascript:help_window('
1520+
"'%s?@template=calendar&property=%s&form=%s%s', %d, %d)"
1521+
'">%s</a>'%(self._classname, self._name, form, date, width,
1522+
height, label))
1523+
15081524
class IntervalHTMLProperty(HTMLProperty):
15091525
def __init__(self, client, classname, nodeid, prop, name, value,
15101526
anonymous=0):
@@ -2329,6 +2345,86 @@ def __getattr__(self, name):
23292345
raise AttributeError, name
23302346
return self.client.instance.templating_utils[name]
23312347

2348+
def html_calendar(self, request):
2349+
"""Generate a HTML calendar.
2350+
2351+
`request` the roundup.request object
2352+
- @template : name of the template
2353+
- form : name of the form to store back the date
2354+
- property : name of the property of the form to store
2355+
back the date
2356+
- date : current date
2357+
- display : when browsing, specifies year and month
2358+
2359+
html will simply be a table.
2360+
"""
2361+
date_str = request.form.getfirst("date", ".")
2362+
display = request.form.getfirst("display", date_str)
2363+
template = request.form.getfirst("@template", "calendar")
2364+
form = request.form.getfirst("form")
2365+
property = request.form.getfirst("property")
2366+
curr_date = date.Date(date_str) # to highlight
2367+
display = date.Date(display) # to show
2368+
day = display.day
2369+
2370+
# for navigation
2371+
date_prev_month = display + date.Interval("-1m")
2372+
date_next_month = display + date.Interval("+1m")
2373+
date_prev_year = display + date.Interval("-1y")
2374+
date_next_year = display + date.Interval("+1y")
2375+
2376+
res = []
2377+
2378+
base_link = "%s?@template=%s&property=%s&form=%s&date=%s" % \
2379+
(request.classname, template, property, form, curr_date)
2380+
2381+
# navigation
2382+
# month
2383+
res.append('<table class="calendar"><tr><td>')
2384+
res.append(' <table width="100%" class="calendar_nav"><tr>')
2385+
link = "&display=%s"%date_prev_month
2386+
res.append(' <td><a href="%s&display=%s">&lt;</a></td>'%(base_link,
2387+
date_prev_month))
2388+
res.append(' <td>%s</td>'%calendar.month_name[display.month])
2389+
res.append(' <td><a href="%s&display=%s">&gt;</a></td>'%(base_link,
2390+
date_next_month))
2391+
# spacer
2392+
res.append(' <td width="100%"></td>')
2393+
# year
2394+
res.append(' <td><a href="%s&display=%s">&lt;</a></td>'%(base_link,
2395+
date_prev_year))
2396+
res.append(' <td>%s</td>'%display.year)
2397+
res.append(' <td><a href="%s&display=%s">&gt;</a></td>'%(base_link,
2398+
date_next_year))
2399+
res.append(' </tr></table>')
2400+
res.append(' </td></tr>')
2401+
2402+
# the calendar
2403+
res.append(' <tr><td><table class="calendar_display">')
2404+
res.append(' <tr class="weekdays">')
2405+
for day in calendar.weekheader(3).split():
2406+
res.append(' <td>%s</td>'%day)
2407+
res.append(' </tr>')
2408+
for week in calendar.monthcalendar(display.year, display.month):
2409+
res.append(' <tr>')
2410+
for day in week:
2411+
link = "javascript:form[field].value = '%d-%02d-%02d'; " \
2412+
"window.close ();"%(display.year, display.month, day)
2413+
if (day == curr_date.day and display.month == curr_date.month
2414+
and display.year == curr_date.year):
2415+
# highlight
2416+
style = "today"
2417+
else :
2418+
style = ""
2419+
if day:
2420+
res.append(' <td class="%s"><a href="%s">%s</a></td>'%(
2421+
style, link, day))
2422+
else :
2423+
res.append(' <td></td>')
2424+
res.append(' </tr>')
2425+
res.append('</table></td></tr></table>')
2426+
return "\n".join(res)
2427+
23322428
class MissingValue:
23332429
def __init__(self, description, **kwargs):
23342430
self.__description = description
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2+
<html>
3+
<head>
4+
<link rel="stylesheet" type="text/css" href="@@file/style.css" />
5+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8;" />
6+
<title tal:content="string:Roundup Calendar"></title>
7+
<script language="Javascript"
8+
type="text/javascript"
9+
tal:content="structure string:
10+
// this is the name of the field in the original form that we're working on
11+
form = window.opener.document.${request/form/form/value};
12+
field = '${request/form/property/value}';" >
13+
</script>
14+
</head>
15+
<body class="body"
16+
tal:content="structure python:utils.html_calendar(request)">
17+
</body>
18+
</html>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2+
<html>
3+
<head>
4+
<link rel="stylesheet" type="text/css" href="@@file/style.css" />
5+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8;" />
6+
<title tal:content="string:Roundup Calendar"></title>
7+
<script language="Javascript"
8+
type="text/javascript"
9+
tal:content="structure string:
10+
// this is the name of the field in the original form that we're working on
11+
form = window.opener.document.${request/form/form/value};
12+
field = '${request/form/property/value}';" >
13+
</script>
14+
</head>
15+
<body class="body"
16+
tal:content="structure python:utils.html_calendar (request)">
17+
</body>
18+
</html>
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
// initial values for either Nosy, Superseder, Topic and Waiting On,
2+
// depending on which has called
3+
original_field = form[field].value;
4+
5+
// Some browsers (ok, IE) don't define the "undefined" variable.
6+
undefined = document.geez_IE_is_really_friggin_annoying;
7+
8+
function trim(value) {
9+
var temp = value;
10+
var obj = /^(\s*)([\W\w]*)(\b\s*$)/;
11+
if (obj.test(temp)) { temp = temp.replace(obj, '$2'); }
12+
var obj = / /g;
13+
while (temp.match(obj)) { temp = temp.replace(obj, " "); }
14+
return temp;
15+
}
16+
17+
function determineList() {
18+
// generate a comma-separated list of the checked items
19+
var list = new String('');
20+
for (box=0; box < document.frm_help.check.length; box++) {
21+
if (document.frm_help.check[box].checked) {
22+
if (list.length == 0) {
23+
separator = '';
24+
}
25+
else {
26+
separator = ',';
27+
}
28+
// we used to use an Array and push / join, but IE5.0 sux
29+
list = list + separator + document.frm_help.check[box].value;
30+
}
31+
}
32+
return list;
33+
}
34+
35+
function updateList() {
36+
// write back to opener window
37+
if (document.frm_help.check==undefined) { return; }
38+
form[field].value = determineList();
39+
}
40+
41+
function updatePreview() {
42+
// update the preview box
43+
if (document.frm_help.check==undefined) { return; }
44+
writePreview(determineList());
45+
}
46+
47+
function clearList() {
48+
// uncheck all checkboxes
49+
if (document.frm_help.check==undefined) { return; }
50+
for (box=0; box < document.frm_help.check.length; box++) {
51+
document.frm_help.check[box].checked = false;
52+
}
53+
}
54+
55+
function reviseList(vals) {
56+
// update the checkboxes based on the preview field
57+
if (document.frm_help.check==undefined) { return; }
58+
var to_check;
59+
var list = vals.split(",");
60+
if (document.frm_help.check.length==undefined) {
61+
check = document.frm_help.check;
62+
to_check = false;
63+
for (val in list) {
64+
if (check.value==trim(list[val])) {
65+
to_check = true;
66+
break;
67+
}
68+
}
69+
check.checked = to_check;
70+
} else {
71+
for (box=0; box < document.frm_help.check.length; box++) {
72+
check = document.frm_help.check[box];
73+
to_check = false;
74+
for (val in list) {
75+
if (check.value==trim(list[val])) {
76+
to_check = true;
77+
break;
78+
}
79+
}
80+
check.checked = to_check;
81+
}
82+
}
83+
}
84+
85+
function resetList() {
86+
// reset preview and check boxes to initial values
87+
if (document.frm_help.check==undefined) { return; }
88+
writePreview(original_field);
89+
reviseList(original_field);
90+
}
91+
92+
function writePreview(val) {
93+
// writes a value to the text_preview
94+
document.frm_help.text_preview.value = val;
95+
}
96+
97+
function focusField(name) {
98+
for(i=0; i < document.forms.length; ++i) {
99+
var obj = document.forms[i].elements[name];
100+
if (obj && obj.focus) {obj.focus();}
101+
}
102+
}
103+
104+
function selectField(name) {
105+
for(i=0; i < document.forms.length; ++i) {
106+
var obj = document.forms[i].elements[name];
107+
if (obj && obj.focus){obj.focus();}
108+
if (obj && obj.select){obj.select();}
109+
}
110+
}
111+

0 commit comments

Comments
 (0)