[Checkins]
SVN: zc.datetimewidget/branches/gintas-dateranges/src/zc/datetimewidget/
Made the calendar widget more easily configurable. This will help
Gintautas Miliauskas
gintas at pov.lt
Mon Aug 28 12:45:27 EDT 2006
Log message for revision 69811:
Made the calendar widget more easily configurable. This will help
to create useful subclasses.
Changed:
U zc.datetimewidget/branches/gintas-dateranges/src/zc/datetimewidget/datetimewidget.py
A zc.datetimewidget/branches/gintas-dateranges/src/zc/datetimewidget/datetimewidget.txt
U zc.datetimewidget/branches/gintas-dateranges/src/zc/datetimewidget/tests.py
-=-
Modified: zc.datetimewidget/branches/gintas-dateranges/src/zc/datetimewidget/datetimewidget.py
===================================================================
--- zc.datetimewidget/branches/gintas-dateranges/src/zc/datetimewidget/datetimewidget.py 2006-08-28 16:44:26 UTC (rev 69810)
+++ zc.datetimewidget/branches/gintas-dateranges/src/zc/datetimewidget/datetimewidget.py 2006-08-28 16:45:26 UTC (rev 69811)
@@ -18,6 +18,9 @@
import datetime
import pytz
+from zope.schema import TextLine, Bool, Int, Date, Choice
+from zope.schema import getFieldsInOrder
+from zope.interface import Interface, implements
from zope.interface.common.idatetime import ITZInfo
from zope.datetime import parseDatetimetz, DateTimeError
from zope.app.form.browser import textwidgets
@@ -57,23 +60,157 @@
dt = dt.astimezone(tzinfo)
return dt
+
+class ICalendarWidgetConfiguration(Interface):
+ """Configuration schema for the calendar widget.
+
+ See http://www.dynarch.com/demos/jscalendar/doc/html/
+ reference.html#node_sec_2.1
+ """
+
+ inputField = TextLine(
+ title=u"Id of input field",
+ default=None,
+ required=False)
+ displayArea = TextLine(
+ title=u"Id of element which displays the date",
+ default=None,
+ required=False)
+ button = TextLine(
+ title=u"Id of trigger",
+ default=None,
+ required=False)
+ eventName = TextLine(
+ title=u"Event name of trigger",
+ default=u'click',
+ required=False)
+ ifFormat = TextLine(
+ title=u"Input field date format",
+ default=u'%Y/%m/%d')
+ daFormat = TextLine(
+ title=u"displayArea date format",
+ default=u'%Y/%m/%d')
+ singleClick = Bool(
+ title=u"Calendar is in single-click mode",
+ default=True)
+ # disableFunc - deprecated
+ dateStatusFunc = TextLine(
+ title=u"Date status function",
+ description=u"""
+ A function that receives a JS Date object and returns a boolean or a
+ string. This function allows one to set a certain CSS class to some
+ date, therefore making it look different. If it returns true then the
+ date will be disabled. If it returns false nothing special happens with
+ the given date. If it returns a string then that will be taken as a CSS
+ class and appended to the date element. If this string is ``disabled''
+ then the date is also disabled (therefore is like returning true).
+ """,
+ default=None,
+ required=False)
+ firstDay = Int(
+ title=u"First day of week (0 is Sunday, 1 is Monday, 6 is Saturday)",
+ default=0)
+ weekNumbers = Bool(
+ title=u"Display week numbers",
+ default=True)
+ align = TextLine(
+ title=u"Alingment of calendar",
+ default=u'Bl')
+ range = TextLine(
+ title=u"Range of allowed years",
+ default=u"[1900, 2999]")
+ flat = TextLine(
+ title=u"Id of parent object for flat calendars",
+ default=None,
+ required=False)
+ flatCallback = TextLine(
+ title=u"Function to call when the calendar is changed",
+ default=None)
+ onSelect = TextLine(
+ title=u"Custom click-on-date handler",
+ default=None,
+ required=False)
+ onClose = TextLine(
+ title=u"Custom handler of 'calendar closed' event",
+ default=None,
+ required=False)
+ onUpdate = TextLine(
+ title=u"Custom handler of 'calendar updated' event",
+ default=None,
+ required=False)
+ date = Date(
+ title=u"Initial date",
+ default=None,
+ required=False)
+ showsTime = Bool(
+ title=u"Show time",
+ default=False)
+ timeFormat = Choice(
+ title=u"Time format (12 hours / 24 hours)",
+ values=['12', '24'],
+ default='24')
+ electric = Bool(
+ title=u"Update date field only when calendar is closed",
+ default=True)
+ position = TextLine(
+ title=u"Default [x, y] position of calendar",
+ default=None,
+ required=False)
+ cache = Bool(
+ title=u"Cache calendar object",
+ default=False)
+ showOthers = Bool(
+ title=u"Show days belonging to other months",
+ default=False)
+
+
template = """
%(widget_html)s
-<input type="button" value="..." id="%(name)s_trigger">
+<input type="button" value="..." id="%(trigger_name)s">
<script type="text/javascript">
%(langDef)s
- Calendar.setup(
- {
- inputField: "%(name)s", // ID of the input field
- ifFormat: "%(datetime_format)s", // the date format
- button: "%(name)s_trigger", // ID of the button
- showsTime: %(showsTime)s
- }
- );
+ %(calendarSetup)s
</script>
"""
+class CalendarWidgetConfiguration(object):
+ implements(ICalendarWidgetConfiguration)
+
+ def __init__(self, **kw):
+ for name, field in getFieldsInOrder(ICalendarWidgetConfiguration):
+ if name in kw:
+ value = kw.pop(name)
+ else:
+ value = field.default
+ setattr(self, name, value)
+ if kw:
+ raise ValueError('unknown arguments: %s' % ', '.join(kw.keys()))
+
+ def dumpJS(self):
+ """Dump configuration as a JavaScript Calendar.setup call."""
+ rows = []
+ for name, field in getFieldsInOrder(ICalendarWidgetConfiguration):
+ value = getattr(self, name)
+ if value != field.default:
+ if value is None:
+ value_repr = 'null'
+ elif isinstance(value, basestring):
+ value_repr = repr(str(value))
+ elif isinstance(value, bool):
+ value_repr = value and 'true' or 'false'
+ elif isinstance(value, datetime.date):
+ value_repr = 'date(%d, %d, %d)' % (value.year,
+ value.month-1, value.day)
+ else:
+ raise ValueError(value)
+ row = ' %s: %s,' % (name, value_repr)
+ rows.append(row)
+ if rows:
+ rows[-1] = rows[-1][:-1] # remove last comma
+ return "Calendar.setup({\n" + '\n'.join(rows) + '\n});\n'
+
+
class DatetimeBase(object):
def __call__(self):
@@ -89,12 +226,18 @@
else:
langDef = ''
widget_html = super(DatetimeBase, self).__call__()
- return template % {"widget_html": widget_html,
- "name": self.name,
- "showsTime": self._showsTime,
- "datetime_format": self._format,
- "langDef":langDef}
+ trigger_name = '%s_trigger' % self.name
+ conf = CalendarWidgetConfiguration(showsTime=self._showsTime,
+ ifFormat=self._format,
+ button=trigger_name,
+ inputField=self.name)
+ return template % dict(widget_html=widget_html,
+ trigger_name=trigger_name,
+ langDef=langDef,
+ calendarSetup=conf.dumpJS())
+
+
def _toFieldValue(self, input):
if input == self._missing:
return self.context.missing_value
Added: zc.datetimewidget/branches/gintas-dateranges/src/zc/datetimewidget/datetimewidget.txt
===================================================================
--- zc.datetimewidget/branches/gintas-dateranges/src/zc/datetimewidget/datetimewidget.txt 2006-08-28 16:44:26 UTC (rev 69810)
+++ zc.datetimewidget/branches/gintas-dateranges/src/zc/datetimewidget/datetimewidget.txt 2006-08-28 16:45:26 UTC (rev 69811)
@@ -0,0 +1,62 @@
+===============
+Calendar Widget
+===============
+
+
+Configuration
+-------------
+
+ >>> from zope.interface.verify import verifyObject
+ >>> from zc.datetimewidget.datetimewidget import (
+ ... CalendarWidgetConfiguration, ICalendarWidgetConfiguration)
+
+Let's create a standard configuration object:
+
+ >>> conf = CalendarWidgetConfiguration()
+ >>> verifyObject(ICalendarWidgetConfiguration, conf)
+ True
+
+Fields have their default values:
+
+ >>> conf.daFormat
+ u'%Y/%m/%d'
+ >>> conf.singleClick
+ True
+ >>> print conf.flat
+ None
+
+We can customize some attributes during instantiation:
+
+ >>> import datetime
+ >>> conf = CalendarWidgetConfiguration(date=datetime.date(2006, 8, 25))
+ >>> conf.date
+ datetime.date(2006, 8, 25)
+
+Dumping JavaScript
+------------------
+
+Configuration can be dumped as JavaScript. First an empty configuration:
+
+ >>> print CalendarWidgetConfiguration().dumpJS()
+ Calendar.setup({
+ <BLANKLINE>
+ });
+
+Now let's add a few customizations:
+
+ >>> conf = CalendarWidgetConfiguration(daFormat=u'%m-%d', inputField='inp',
+ ... eventName=None, date=conf.date)
+ >>> print conf.dumpJS()
+ Calendar.setup({
+ inputField: 'inp',
+ eventName: null,
+ daFormat: '%m-%d',
+ date: date(2006, 7, 25)
+ });
+
+Invalid arguments are not accepted:
+
+ >>> conf = CalendarWidgetConfiguration(foo='bar')
+ Traceback (most recent call last):
+ ...
+ ValueError: unknown arguments: foo
Property changes on: zc.datetimewidget/branches/gintas-dateranges/src/zc/datetimewidget/datetimewidget.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: zc.datetimewidget/branches/gintas-dateranges/src/zc/datetimewidget/tests.py
===================================================================
--- zc.datetimewidget/branches/gintas-dateranges/src/zc/datetimewidget/tests.py 2006-08-28 16:44:26 UTC (rev 69810)
+++ zc.datetimewidget/branches/gintas-dateranges/src/zc/datetimewidget/tests.py 2006-08-28 16:45:26 UTC (rev 69811)
@@ -13,7 +13,7 @@
##############################################################################
"""Datetime Widget unittests
-$Id:$
+$Id$
"""
__docformat__ = "reStructuredText"
@@ -37,6 +37,9 @@
DocFileSuite('timezones.txt',
optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
),
+ DocFileSuite('datetimewidget.txt',
+ optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
+ ),
))
if __name__ == '__main__':
More information about the Checkins
mailing list