[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