def render(self, ctx, key, args, errors): converter = iformal.IDateTupleConvertible(self.original) namer = self._namer(key) if errors: year = args.get(namer('year'), [''])[0] month = args.get(namer('month'), [''])[0] day = args.get(namer('day'), [''])[0] else: year, month, day = converter.fromType(args.get(key)) return self._renderTag(ctx, year, month, day, namer, False)
def render(self, ctx, key, args, errors): converter = iformal.IDateTupleConvertible(self.original) namer = self._namer(key) if errors: year = args.get(namer('year'), [''])[0] month = args.get(namer('month'), [''])[0] # return a blank for the day day = '' else: year, month, day = converter.fromType(args.get(key)) # if we have a year as default data, stringify it and only use last two digits if year is not None: year = str(year)[2:] return self._renderTag(ctx, year, month, namer, False)
class MMYYDatePartsInput(object): """ Two input fields for entering the month and year. """ implements(iformal.IWidget) cutoffYear = 70 def __init__(self, original, cutoffYear=None): self.original = original if cutoffYear is not None: self.cutoffYear = cutoffYear def _namer(self, prefix): def _(part): return '%s__%s' % (prefix, part) return _ def _renderTag(self, ctx, year, month, namer, readonly): yearTag = T.input(type="text", name=namer('year'), value=year, size=2) monthTag = T.input(type="text", name=namer('month'), value=month, size=2) if readonly: tags = (yearTag, monthTag) for tag in tags: tag(class_='readonly', readonly='readonly') return monthTag, ' / ', yearTag, ' (mm/yy)' def render(self, ctx, key, args, errors): converter = iformal.IDateTupleConvertible(self.original) namer = self._namer(key) if errors: year = args.get(namer('year'), [''])[0] month = args.get(namer('month'), [''])[0] # return a blank for the day day = '' else: year, month, day = converter.fromType(args.get(key)) # if we have a year as default data, stringify it and only use last two digits if year is not None: year = str(year)[2:] return self._renderTag(ctx, year, month, namer, False) def renderImmutable(self, ctx, key, args, errors): converter = iformal.IDateTupleConvertible(self.original) year, month, day = converter.fromType(args.get(key)) namer = self._namer(key) # if we have a year as default data, stringify it and only use last two digits if year is not None: year = str(year)[2:] return self._renderTag(ctx, year, month, namer, True) def processInput(self, ctx, key, args): namer = self._namer(key) value = [ args.get(namer(part), [''])[0].strip() for part in ('year', 'month') ] value = [p for p in value if p] if not value: value = None elif len(value) != 2: raise validation.FieldValidationError("Invalid date") if value is not None: try: value = [int(p) for p in value] except ValueError, e: raise validation.FieldValidationError("Invalid date") if value[1] < 0 or value[1] > 99: raise validation.FieldValidationError( "Invalid year. Please enter a two-digit year.") if value[0] > self.cutoffYear: value[0] = 1900 + value[0] else: value[0] = 2000 + value[0] value.append(1) value = iformal.IDateTupleConvertible(self.original).toType(value) return self.original.validate(value)
def renderImmutable(self, ctx, key, args, errors): converter = iformal.IDateTupleConvertible(self.original) namer = self._namer(key) year, month, day = converter.fromType(args.get(key)) return self._renderTag(ctx, year, month, day, namer, True)
class DatePartsInput(object): """ A date entry widget that uses three <input> elements for the day, month and year parts. The default entry format is the US (month, day, year) but can be switched to the more common (day, month, year) by setting the dayFirst attribute to True. By default the widget is designed to only accept unambiguous years, i.e. the user must enter 4 character dates. Many people find it convenient or even necessary to allow a 2 character year. This can be allowed by setting the twoCharCutoffYear attribute to an integer value between 0 and 99. Anything greater than or equal to the cutoff year will be considered part of the 20th century (1900 + year); anything less the cutoff year is a 21st century (2000 + year) date. A typical twoCharCutoffYear value is 70 (i.e. 1970). However, that value is somewhat arbitrary. It's the year that time began according to the PC, but it doesn't mean much to your non-techie user. dayFirst: Make the day the first input field, i.e. day, month, year twoCharCutoffYear: Allow 2 char years and set the year where the century flips between 20th and 21st century. """ implements(iformal.IWidget) dayFirst = False twoCharCutoffYear = None def __init__(self, original, dayFirst=None, twoCharCutoffYear=None): self.original = original if dayFirst is not None: self.dayFirst = dayFirst if twoCharCutoffYear is not None: self.twoCharCutoffYear = twoCharCutoffYear def _namer(self, prefix): def _(part): return '%s__%s' % (prefix, part) return _ def _renderTag(self, ctx, year, month, day, namer, readonly): yearTag = T.input(type="text", name=namer('year'), value=year, size=4) monthTag = T.input(type="text", name=namer('month'), value=month, size=2) dayTag = T.input(type="text", name=namer('day'), value=day, size=2) if readonly: tags = (yearTag, monthTag, dayTag) for tag in tags: tag(class_='readonly', readonly='readonly') if self.dayFirst: return dayTag, ' / ', monthTag, ' / ', yearTag, ' ', _( '(day/month/year)') else: return monthTag, ' / ', dayTag, ' / ', yearTag, ' ', _( '(month/day/year)') def render(self, ctx, key, args, errors): converter = iformal.IDateTupleConvertible(self.original) namer = self._namer(key) if errors: year = args.get(namer('year'), [''])[0] month = args.get(namer('month'), [''])[0] day = args.get(namer('day'), [''])[0] else: year, month, day = converter.fromType(args.get(key)) return self._renderTag(ctx, year, month, day, namer, False) def renderImmutable(self, ctx, key, args, errors): converter = iformal.IDateTupleConvertible(self.original) namer = self._namer(key) year, month, day = converter.fromType(args.get(key)) return self._renderTag(ctx, year, month, day, namer, True) def processInput(self, ctx, key, args): namer = self._namer(key) # Get the form field values as a (y,m,d) tuple ymd = [ args.get(namer(part), [''])[0].strip() for part in ('year', 'month', 'day') ] # Remove parts that were not entered. ymd = [p for p in ymd if p] # Nothing entered means None otherwise we need all three. if not ymd: ymd = None elif len(ymd) != 3: raise validation.FieldValidationError("Invalid date") # So, we have what looks like a good attempt to enter a date. if ymd is not None: # If a 2-char year is allowed then prepend the century. if self.twoCharCutoffYear is not None and len(ymd[0]) == 2: try: if int(ymd[0]) >= self.twoCharCutoffYear: century = '19' else: century = '20' ymd[0] = century + ymd[0] except ValueError: pass # By now, we should have a year of at least 4 characters. if len(ymd[0]) < 4: if self.twoCharCutoffYear is not None: msg = "Please enter a 2 or 4 digit year" else: msg = "Please enter a 4 digit year" raise validation.FieldValidationError(msg) # Map to integers try: ymd = [int(p) for p in ymd] except ValueError, e: raise validation.FieldValidationError("Invalid date") ymd = iformal.IDateTupleConvertible(self.original).toType(ymd) return self.original.validate(ymd)
class DatePartsSelect(object): """ A date entry widget that uses three <input> elements for the day, month and year parts. The default entry format is the US (month, day, year) but can be switched to the more common (day, month, year) by setting the dayFirst attribute to True. The start and end year can be passed through but default to 1970 and 2070. The months default to non-zero prefixed numerics but can be passed as a list of label, value pairs """ implements( iformal.IWidget ) dayFirst = False days = [ (d,d) for d in xrange(1,32) ] months = [ (m,m) for m in xrange(1,13) ] yearFrom = 1970 yearTo = 2070 noneOption = ('', '') def __init__(self, original, dayFirst=None, yearFrom=None, yearTo=None, months=None, noneOption=_UNSET): self.original = original if dayFirst is not None: self.dayFirst = dayFirst if yearFrom is not None: self.yearFrom = yearFrom if yearTo is not None: self.yearTo = yearTo if months is not None: self.months = months if noneOption is not _UNSET: self.noneOption = noneOption def _namer(self, prefix): def _(part): return '%s__%s' % (prefix,part) return _ def _renderTag(self, ctx, year, month, day, namer, readonly): years = [(v,v) for v in xrange(self.yearFrom,self.yearTo)] months = self.months days = self.days options = [] if self.noneOption is not None: options.append( T.option(value=self.noneOption[0])[self.noneOption[1]] ) for value in years: if str(value[0]) == str(year): options.append( T.option(value=value[0],selected='selected')[value[1]] ) else: options.append( T.option(value=value[0])[value[1]] ) yearTag = T.select(name=namer('year'))[ options ] options = [] if self.noneOption is not None: options.append( T.option(value=self.noneOption[0])[self.noneOption[1]] ) for value in months: if str(value[0]) == str(month): options.append( T.option(value=value[0],selected='selected')[value[1]] ) else: options.append( T.option(value=value[0])[value[1]] ) monthTag = T.select(name=namer('month'))[ options ] options = [] if self.noneOption is not None: options.append( T.option(value=self.noneOption[0])[self.noneOption[1]] ) for value in days: if str(value[0]) == str(day): options.append( T.option(value=value[0],selected='selected')[value[1]] ) else: options.append( T.option(value=value[0])[value[1]] ) dayTag = T.select(name=namer('day'))[ options ] if readonly: tags = (yearTag, monthTag, dayTag) for tag in tags: tag(class_='readonly', readonly='readonly') if self.dayFirst: return dayTag, ' / ', monthTag, ' / ', yearTag, ' ', _('(day/month/year)') else: return monthTag, ' / ', dayTag, ' / ', yearTag, ' ', _('(month/day/year)') def render(self, ctx, key, args, errors): converter = iformal.IDateTupleConvertible(self.original) namer = self._namer(key) if errors: year = args.get(namer('year'), [''])[0] month = args.get(namer('month'), [''])[0] day = args.get(namer('day'), [''])[0] else: year, month, day = converter.fromType(args.get(key)) return self._renderTag(ctx, year, month, day, namer, False) def renderImmutable(self, ctx, key, args, errors): converter = iformal.IDateTupleConvertible(self.original) namer = self._namer(key) year, month, day = converter.fromType(args.get(key)) return self._renderTag(ctx, year, month, day, namer, True) def processInput(self, ctx, key, args): namer = self._namer(key) # Get the form field values as a (y,m,d) tuple ymd = [args.get(namer(part), [''])[0].strip() for part in ('year', 'month', 'day')] # Remove parts that were not entered. ymd = [p for p in ymd if p] # Nothing entered means None otherwise we need all three. if not ymd: ymd = None elif len(ymd) != 3: raise validation.FieldValidationError("Invalid date") # So, we have what looks like a good attempt to enter a date. if ymd is not None: # Map to integers try: ymd = [int(p) for p in ymd] except ValueError, e: raise validation.FieldValidationError("Invalid date") ymd = iformal.IDateTupleConvertible(self.original).toType(ymd) return self.original.validate(ymd)