Plone 3 Themes
PloneFormGen and jscalendar
PloneFormGen is a Plone Product for creating forms. It allows you to add a Date/Time field and then the rabbit hole opened...
The field let's you use some pull down menus or a JavaScript popup widget to select a date. The popup had no styling whatsoever.
It turns out the jscalendar is a third party product in Plone from dynarch.com (in particular, version 1.0). It does all the usual stuff. Except without a stylesheet.
Stylesheets
It took me a long time to fathom that, despite their presence in portal_styles; plone_3rdparty; jscalendar the stylesheets were simply not being called upon. There's two reasons for that.
portal_css
Plone is not generating any code to reference the stylesheets. To convince it otherwise you need to add a reference to a jscalendar stylesheet.
Go to Site Setup; ZMI; portal_css and whizz down to the bottom. Add a new entry with:
field | value |
---|---|
id/URL | calendar-theme.css |
CSS media | screen |
and click save.
If you then scroll down to the bottom again Plone will probably be whinging about it being missing. Which it is.
calendar-theme.css
Create a new stylesheet in .../skins/plonetheme_mytheme_styles called calendar-theme.css and put in it the contents of customizing portal_styles; plone_3rdparty; jscalendar; theme.css. Or one of the other stylesheets if you prefer.
The immediate problem with this is that it will be missing a dozen GIFs which it uses for background URLs when the mouse moves over various elements in the popup.
You can copy all of the referenced GIFs into .../skins/plonetheme_mytheme_custom_images but I didn't like them (too many horizontal lines!) and replaced all but one of them with a suitable background-color.
The remaining GIF is menuarrow.gif which I put in a jscalendar subdirectory and edited the background-url appropriately.
I couldn't put calendar-theme.css in a jscalendar subdirectory, it wouldn't be discovered.
Overrides
You can set some default values for the Date/Time field but they are fixed and not incredibly useful. You can set some "dynamic" overrides (the override itself isn't dynamic by the resultant value is).
The default value should be a TALES expression which can be python: followed by any legal Python expression. So long as you know what is in scope...
What I wanted to do was not merely set the default date to be today (which would be DateTime()) but rather set it to be the first Monday at least two weeks from now. This would be more than the minimum lead time for the service in question and you want it to be defaulting to a Monday because otherwise, if someone is browsing on a Saturday, the default value being a Saturday just looks daft.
Python has plenty of datetime operators available (strftime, weekday, strptime even) but every invocation fell over. Searching on plone tales datetime would occasionally drop me at the Zope API Reference Appendix B with the helpful comments that the cost of maintaining the documentation was too hard, please read the source code. RTFS, indeeed!
Eventually, I found the old Zope API Appendix B which reveals lots of anachronistic functions (dow for weekday: why?) and that DateTime() would accept a string as an argument that it would filter through strptime to generate a date. There's hope!
Default
So, we can now have the following expression to initialise the date on a Monday at least two weeks hence:
DateTime() + 21 - DateTime().dow() + 1
as (obviously) integer arithmetic means days. So we need to go three weeks days forward and then dow days backwards and correct for dow() (dow() starts with Sunday as 0) to get back to that Monday.
Validator
We can also define a validator in the same way. value will have the form YYYY-mm-dd HH:MM which is perfectly suited for DateTime() to parse and we use the suggested:
test(value=='eggs', False, 'input must be eggs')
format to get:
test(DateTime(value).dow() in [ 1, 2, 3, 4, 5], False, DateTime(value).strftime("%d %b %Y") + " is a weekend")
to ensure the requested date is not a weekend.
A Python Script Validator
TALES and test are very limiting and as documented here you can use a Python Script with much greater flexibility.
Add the Python Script
Go To Site Setup; ZMI; navigate your site through to the PloneFormGen folder and add a Script (Python) and give it an id of, say, dateValidator.
Edit the script with:
field | |
---|---|
Parameter List | value |
ie, value is going to be made available to the script as a bound variable.
The script itself might look like:
if DateTime(value).dow() in [ 0, 6]: return DateTime(value).strftime("%d %b %Y") + " is a weekend " if DateTime(value).dow() in [ 5]: return DateTime(value).strftime("%d %b %Y") + " is a Friday " else: return False
noting that you should return False when you're happy the date is OK and some pertinent string otherwise.
Validator
Change the validator in Overrides to:
python: folder.dateValidator(value)
Document Actions