Source code for gavo.formal.widgets.multiselect

from zope.interface import implementer
from twisted.web.template import tags as T
from .. import iformal
from ..util import render_cssid

_UNSET = object()

[docs]class MultichoiceBase(object): """ A base class for widgets that provide the UI to select one or more items from a list. Based on ChoiceBase options: A sequence of objects adaptable to IKey and ILabel. IKey is used as the <option>'s value attribute; ILabel is used as the <option>'s child. IKey and ILabel adapters for tuple are provided. noneOption: An object adaptable to IKey and ILabel that is used to identify when nothing has been selected. Defaults to ('', '') default can be whitespace-separated items. """ options = None noneOption = None def __init__(self, original, options=None, noneOption=_UNSET): self.original = original if options is not None: self.options = options if noneOption is not _UNSET: self.noneOption = noneOption
[docs] def processInput(self, request, key, args, default=''): values = args.get(key, default.split()) rv = [] for value in values: value = iformal.IStringConvertible(self.original).toType(value) if self.noneOption is not None and value == self.noneOption[0]: value = None rv.append(self.original.validate(value)) return rv
[docs]@implementer( iformal.IWidget ) class MultiselectChoice(MultichoiceBase): """ A drop-down list of options. """ noneOption = ('', '') def _renderTag(self, request, key, value, converter, disabled): def renderOptions(request, data): if self.noneOption is not None: yield T.option(value=iformal.IKey(self.noneOption).key())[iformal.ILabel(self.noneOption).label()] if data is None: return for item in data: optValue = iformal.IKey(item).key() optLabel = iformal.ILabel(item).label() optValue = converter.fromType(optValue) option = T.option(value=str(optValue))[str(optLabel)] if value and optValue in value: option = option(selected='selected') yield option tag=T.select(name=key, id=render_cssid(key), data=self.options, multiple="multiple")[renderOptions] if disabled: tag(class_='disabled', disabled='disabled') return tag
[docs] def render(self, request, key, args, errors): converter = iformal.IStringConvertible(self.original) if errors: value = args.get(key, ['']) else: value = converter.fromType(args.get(key)) return self._renderTag(request, key, value, converter, False)
[docs] def renderImmutable(self, request, key, args, errors): converter = iformal.IStringConvertible(self.original) value = converter.fromType(args.get(key)) return self._renderTag(request, key, value, converter, True)
__all__ = ["MultichoiceBase", "MultiselectChoice"]