[Checkins] SVN: zc.datetimewidget/branches/gintas-dateranges/src/zc/datetimewidget/ Sort-of-working implementation of a multiselect date widget. Disabling

Gintautas Miliauskas gintas at pov.lt
Tue Aug 29 11:12:46 EDT 2006


Log message for revision 69845:
  Sort-of-working implementation of a multiselect date widget.  Disabling
  weekdays also works.
  

Changed:
  U   zc.datetimewidget/branches/gintas-dateranges/src/zc/datetimewidget/configure.zcml
  U   zc.datetimewidget/branches/gintas-dateranges/src/zc/datetimewidget/datetimewidget.py
  U   zc.datetimewidget/branches/gintas-dateranges/src/zc/datetimewidget/datetimewidget.txt
  U   zc.datetimewidget/branches/gintas-dateranges/src/zc/datetimewidget/resources/datetimewidget.js

-=-
Modified: zc.datetimewidget/branches/gintas-dateranges/src/zc/datetimewidget/configure.zcml
===================================================================
--- zc.datetimewidget/branches/gintas-dateranges/src/zc/datetimewidget/configure.zcml	2006-08-29 14:50:12 UTC (rev 69844)
+++ zc.datetimewidget/branches/gintas-dateranges/src/zc/datetimewidget/configure.zcml	2006-08-29 15:12:45 UTC (rev 69845)
@@ -13,4 +13,15 @@
                  calendar-setup.js"/>
   </resourceLibrary>
 
+  <!-- Widgets -->
+
+  <view
+      type="zope.publisher.interfaces.browser.IBrowserRequest"
+      for="zope.schema.interfaces.ISet
+           zope.schema.interfaces.IDate"
+      provides="zope.app.form.interfaces.IInputWidget"
+      factory=".datetimewidget.DateSetWidget"
+      permission="zope.Public"
+      />
+
 </configure>

Modified: zc.datetimewidget/branches/gintas-dateranges/src/zc/datetimewidget/datetimewidget.py
===================================================================
--- zc.datetimewidget/branches/gintas-dateranges/src/zc/datetimewidget/datetimewidget.py	2006-08-29 14:50:12 UTC (rev 69844)
+++ zc.datetimewidget/branches/gintas-dateranges/src/zc/datetimewidget/datetimewidget.py	2006-08-29 15:12:45 UTC (rev 69845)
@@ -164,20 +164,12 @@
         default=False)
 
 
-template = """
-%(widget_html)s
-<input type="button" value="..." id="%(trigger_name)s">
-<script type="text/javascript">
-  %(langDef)s
-  %(calendarSetup)s
-</script>
-"""
-
-
 class CalendarWidgetConfiguration(object):
     implements(ICalendarWidgetConfiguration)
 
     def __init__(self, **kw):
+        self.multiple = False
+        self.enabled_weekdays = None
         for name, field in getFieldsInOrder(ICalendarWidgetConfiguration):
             if name in kw:
                 value = kw.pop(name)
@@ -187,6 +179,13 @@
         if kw:
             raise ValueError('unknown arguments: %s' % ', '.join(kw.keys()))
 
+    def setMultiple(self, dates):
+        self.multiple = True
+        self._multiple_dates = dates
+
+    def setEnabledWeekdays(self, enabled_weekdays):
+        self.enabled_weekdays = enabled_weekdays
+
     def dumpJS(self):
         """Dump configuration as a JavaScript Calendar.setup call."""
         rows = []
@@ -206,13 +205,33 @@
                     raise ValueError(value)
                 row = '  %s: %s,' % (name, value_repr)
                 rows.append(row)
+        if self.multiple:
+            rows.append('  multiple: [],') # TODO: add current values
+            rows.append('  onClose: getMultipleDateClosedHandler("%s"),'
+                        % self.inputField)
+        if self.enabled_weekdays is not None:
+            rows.append('  dateStatusFunc: enabledWeekdays([%s]),'
+                        % ', '.join(str(weekday)
+                                    for weekday in self.enabled_weekdays))
         if rows:
             rows[-1] = rows[-1][:-1] # remove last comma
         return "Calendar.setup({\n" + '\n'.join(rows) + '\n});\n'
 
 
+template = """
+%(widget_html)s
+<input type="button" value="..." id="%(trigger_name)s">
+<script type="text/javascript">
+  %(langDef)s
+  %(calendarSetup)s
+</script>
+"""
+
+
 class DatetimeBase(object):
 
+    enabled_weekdays = None
+
     def __call__(self):
         zc.resourcelibrary.need('zc.datetimewidget')
         lang = self.request.locale.id.language
@@ -226,17 +245,29 @@
         else:
             langDef = ''
         widget_html = super(DatetimeBase, self).__call__()
+        conf = self._configuration()
         trigger_name = '%s_trigger' % self.name
+        return template % dict(widget_html=widget_html,
+                               trigger_name=trigger_name,
+                               langDef=langDef,
+                               calendarSetup=conf.dumpJS())
+
+    def _configuration(self):
+        trigger_name = '%s_trigger' % self.name
         conf = CalendarWidgetConfiguration(showsTime=self._showsTime,
                                            ifFormat=self._format,
                                            button=trigger_name,
                                            inputField=self.name)
+        if self.enabled_weekdays is not None:
+            conf.setEnabledWeekdays(self.enabled_weekdays)
+        return conf
 
-        return template % dict(widget_html=widget_html,
-                               trigger_name=trigger_name,
-                               langDef=langDef,
-                               calendarSetup=conf.dumpJS())
+    def setEnabledWeekdays(self, enabled_days):
+        """Enable only particular weekdays.
 
+        `enabled_days` is a set of integers (0 = Sunday, 1 = Monday).
+        """
+        self.enabled_days = enabled_days
 
     def _toFieldValue(self, input):
         if input == self._missing:
@@ -258,7 +289,7 @@
     """Datetime entry widget."""
 
     _format = '%Y-%m-%d %H:%M:%S'
-    _showsTime = "true"
+    _showsTime = True
 
     def _toFieldValue(self, input):
         res = super(DatetimeWidget, self)._toFieldValue(input)
@@ -266,15 +297,52 @@
             res = normalizeDateTime(res, self.request)
         return res
 
+
 class DateWidget(DatetimeBase, textwidgets.DateWidget):
     """Date entry widget."""
 
     displayWidth = 10
 
     _format = '%Y-%m-%d'
-    _showsTime = "false"
+    _showsTime = False
 
 
+class DateSetWidget(DatetimeBase, textwidgets.DateWidget):
+    """Widget for entry of sets of dates."""
+
+    displayWidth = 10
+
+    _format = '%Y-%m-%d'
+    _showsTime = False
+
+    def __init__(self, field, item, request):
+        super(DateSetWidget, self).__init__(field, request)
+
+    def _configuration(self):
+        conf = DatetimeBase._configuration(self)
+        conf.setMultiple([]) # TODO insert real dates
+        return conf
+
+    def _toFieldValue(self, input):
+        if input == self._missing:
+            return self.context.missing_value
+        else:
+            dates = input.split()
+            values = set()
+            for date in dates:
+                value = super(DateSetWidget, self)._toFieldValue(date)
+                values.add(value)
+        return values
+
+    def _toFormValue(self, value):
+        if value == self.context.missing_value:
+            return self._missing
+
+        date_strs = [super(DateSetWidget, self)._toFormValue(date)
+                     for date in sorted(value)]
+        return ' '.join(date_strs)
+
+
 class DatetimeDisplayBase(object):
 
     def __call__(self):
@@ -293,9 +361,7 @@
 
 class DatetimeDisplayWidget(
     DatetimeDisplayBase, textwidgets.DatetimeDisplayWidget):
-
     pass
 
 class DateDisplayWidget(DatetimeDisplayBase, textwidgets.DateDisplayWidget):
-
     pass

Modified: zc.datetimewidget/branches/gintas-dateranges/src/zc/datetimewidget/datetimewidget.txt
===================================================================
--- zc.datetimewidget/branches/gintas-dateranges/src/zc/datetimewidget/datetimewidget.txt	2006-08-29 14:50:12 UTC (rev 69844)
+++ zc.datetimewidget/branches/gintas-dateranges/src/zc/datetimewidget/datetimewidget.txt	2006-08-29 15:12:45 UTC (rev 69845)
@@ -32,6 +32,7 @@
     >>> conf.date
     datetime.date(2006, 8, 25)
 
+
 Dumping JavaScript
 ------------------
 
@@ -60,3 +61,34 @@
     Traceback (most recent call last):
         ...
     ValueError: unknown arguments: foo
+
+
+Date set widget
+---------------
+
+    >>> from zc.datetimewidget.datetimewidget import DateSetWidget
+    >>> from zope.schema import Set
+    >>> from zope.publisher.browser import TestRequest
+
+    >>> request = TestRequest()
+    >>> field = Set()
+    >>> field.context = set()
+    >>> widget = DateSetWidget(field, object(), request)
+
+    >>> print widget()
+    <BLANKLINE>
+    <input class="textType" id="field." name="field." size="10" type="text" value=""  />
+    <input type="button" value="..." id="field._trigger">
+    <script type="text/javascript">
+    <BLANKLINE>
+      Calendar.setup({
+      inputField: 'field.',
+      button: 'field._trigger',
+      ifFormat: '%Y-%m-%d',
+      multiple: [],
+      onClose: getMultipleDateClosedHandler("field.")
+    });
+    <BLANKLINE>
+    </script>
+    <BLANKLINE>
+

Modified: zc.datetimewidget/branches/gintas-dateranges/src/zc/datetimewidget/resources/datetimewidget.js
===================================================================
--- zc.datetimewidget/branches/gintas-dateranges/src/zc/datetimewidget/resources/datetimewidget.js	2006-08-29 14:50:12 UTC (rev 69844)
+++ zc.datetimewidget/branches/gintas-dateranges/src/zc/datetimewidget/resources/datetimewidget.js	2006-08-29 15:12:45 UTC (rev 69845)
@@ -1,10 +1,9 @@
 var dtwLanguageLoaded = false;
 
 function dateTimeWidgetLoadLanguageFile(url){
-
     // this method loads a languagefile for the datetimewidget
     // TODO: move this functinality into zc.resourcelibrary
-    
+
     if (dtwLanguageLoaded==true){
         return;
     }
@@ -16,3 +15,45 @@
 }
 
 
+function dateSelected(cal, date) {
+  cal.sel.value = date; // just update the date in the input field.
+  if (cal.dateClicked && !cal.multiple)
+    // if we add this call we close the calendar on single-click.
+    // just to exemplify both cases, we are using this only for the 1st
+    // and the 3rd field, while 2nd and 4th will still require double-click.
+    cal.callCloseHandler();
+}
+
+
+function getMultipleDateClosedHandler(input_id) {
+  return function(cal) {
+    var el = document.getElementById(input_id);
+    var MA = cal.multiple;
+
+    // reset initial content.
+    el.value = "";
+    MA.length = 0;
+
+    // walk the calendar's multiple dates selection hash
+    for (var i in cal.multiple) {
+      var d = cal.multiple[i];
+      if (d) {
+        el.value += d.print("%Y-%m-%d ");
+        MA[MA.length] = d;
+      }
+    }
+    cal.hide();
+    return true;
+  }
+}
+
+function enabledWeekdays(enabled_weekdays) {
+  return function(date) {
+    weekday = date.getDay();
+    for (var enabled_wd in enabled_weekdays) {
+      if (weekday == enabled_weekdays[enabled_wd])
+        return true;
+    }
+    return false;
+  }
+}



More information about the Checkins mailing list