This is a pre-production deployment of Warehouse. Changes made here affect the production instance of PyPI (pypi.python.org).
Help us improve Python packaging - Donate today!
Project Description

Description

This package contains 4 widgets for z3cform using the chosen and ajaxchosen libraries.

  • A single valued widget for chosen
  • A multi valued widget for chosen
  • A single valued widget for ajaxchosen
  • A multi valued widget for ajaxchosen

Repository : github

Chosen widget

collective.chosen.widget provides an autocomplete widget based on the jQuery Autocomplete widget.

>>> from collective.z3cform.chosen import AjaxChosenFieldWidget
>>> from collective.z3cform.chosen import AjaxChosenMultiFieldWidget
>>> from collective.z3cform.chosen import ChosenFieldWidget
>>> from collective.z3cform.chosen import ChosenMultiFieldWidget

First, we need a vocabulary to search. This is shamelessly stolen from z3c.formwidget.query, which we extend.

>>> from zope.interface import implements
>>> from z3c.formwidget.query.interfaces import IQuerySource
>>> from zope.schema.vocabulary import SimpleVocabulary, SimpleTerm
>>> class ItalianCities(object):
...     implements(IQuerySource)
...
...     vocabulary = SimpleVocabulary((
...         SimpleTerm(u'bologna',  'bologna', u'Bologna'),
...         SimpleTerm(u'palermo',  'palermo', u'Palermo'),
...         SimpleTerm(u'sorrento', 'sorrento', u'Sorrento'),
...         SimpleTerm(u'torino', 'torino', u'Torino')))
...
...     def __init__(self, context):
...         self.context = context
...
...     __contains__ = vocabulary.__contains__
...     __iter__ = vocabulary.__iter__
...     getTerm = vocabulary.getTerm
...     getTermByToken = vocabulary.getTermByToken
...
...     def search(self, query_string):
...         return [v
...                 for v in self
...          if query_string.lower() in v.value.lower()]
>>> from zope.schema.interfaces import IContextSourceBinder
>>> class ItalianCitiesSourceBinder(object):
...     implements(IContextSourceBinder)
...
...     def __call__(self, context):
...         return ItalianCities(context)

Then, we will set up a simple test form and context.

>>> from zope.interface import alsoProvides
>>> from OFS.SimpleItem import SimpleItem
>>> from Testing.makerequest import makerequest
>>> from zope.annotation.interfaces import IAttributeAnnotatable
>>> from z3c.form.interfaces import IFormLayer
>>> def make_request(path, form={}):
...     app = SimpleItem('')
...     request = makerequest(app).REQUEST
...     request.form.update(form)
...     alsoProvides(request, IFormLayer)
...     alsoProvides(request, IAttributeAnnotatable)
...     request._script = path.split('/')
...     request._steps = []
...     request._resetURLS()
...     return request
>>> from zope.interface import Interface
>>> from zope import schema
>>> from z3c.form import form, field, button
>>> from plone.z3cform.layout import wrap_form
>>> class ICities(Interface):
...     afavourite_city = schema.Choice(title=u"Favourite city",
...                                    source=ItalianCitiesSourceBinder(), required=False)
...     avisited_cities = schema.List(title=u"Visited cities",
...                                  value_type=schema.Choice(title=u"Selection",
...                                                           source=ItalianCitiesSourceBinder()))
...     favourite_city = schema.Choice(title=u"Favourite city",
...                                    source=ItalianCitiesSourceBinder())
...     visited_cities = schema.List(title=u"Visited cities",
...                                  value_type=schema.Choice(title=u"Selection",
...                                                           source=ItalianCitiesSourceBinder()))
>>> from z3c.form.interfaces import IFieldsForm
>>> from zope.interface import implements
>>> class CitiesForm(form.Form):
...     implements(ICities)
...     fields = field.Fields(ICities)
...     fields['afavourite_city'].widgetFactory = AjaxChosenFieldWidget
...     fields['avisited_cities'].widgetFactory = AjaxChosenMultiFieldWidget
...     fields['favourite_city'].widgetFactory = ChosenFieldWidget
...     fields['visited_cities'].widgetFactory = ChosenMultiFieldWidget
...
...     @button.buttonAndHandler(u'Apply')
...     def handleApply(self, action):
...         data, errors = self.extractData()
...         print "Submitted data:", data
>>> form_view = wrap_form(CitiesForm)
>>> from zope.component import provideAdapter
>>> from zope.publisher.interfaces.browser import IBrowserRequest
>>> from zope.interface import Interface
>>> provideAdapter(adapts=(ICities, IBrowserRequest),
...                provides=Interface,
...                factory=form_view,
...                name=u"cities-form")
>>> from OFS.SimpleItem import SimpleItem
>>> class Bar(SimpleItem):
...     implements(ICities)
...
...     def __init__(self, id):
...         self.id = id
...         self.favourite_city = None
...         self.visited_cities = []
...         self.afavourite_city = None
...         self.avisited_cities = []
...     def absolute_url(self):
...         return 'http://foo/bar'

Let us now look up the form and attempt to render the widget.

>>> from zope.component import getMultiAdapter
>>> context = Bar('bar')

Simulates traversal:

>>> request = make_request('bar/@@cities-form')
>>> from Testing.makerequest import makerequest
>>> context = makerequest(context)
>>> form_view = getMultiAdapter((context, request), name=u"cities-form")
>>> form_view.__name__ = 'cities-form'

Simulates partial rendering:

>>> form = form_view.form_instance
>>> form.__name__ = 'cities-form'
>>> form.update()
>>> print form.widgets['favourite_city'].render().replace("...", "") # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE +REPORT_UDIFF
<BLANKLINE>
<script type="text/javascript">    (function($) {
        $().ready(function() {
            $('#form-widgets-favourite_city-select').data('klass','chosen-selection-widget required choice-field').data('title','None');
            $('#form-widgets-favourite_city-select').chosen({
                allow_single_deselect: false,
                no_results_text: 'No results found',
                width: '280px'
            });
<BLANKLINE>
        });
    })(jQuery);
    </script>
<div id="form-widgets-favourite_city-chosen" class="chosen-selection-widget required choice-field">
  <select data-placeholder="Select a value" id="form-widgets-favourite_city-select" name="form.widgets.favourite_city:list" onselect="" style="" >
<BLANKLINE>
      <option id="form-widgets-favourite_city-novalue" value="(nothing)" selected="selected">Select a value</option>
<BLANKLINE>
<BLANKLINE>
<BLANKLINE>
      <option id="form-widgets-favourite_city-0" value="bologna">Bologna</option>
<BLANKLINE>
<BLANKLINE>
      <option id="form-widgets-favourite_city-1" value="palermo">Palermo</option>
<BLANKLINE>
<BLANKLINE>
      <option id="form-widgets-favourite_city-2" value="sorrento">Sorrento</option>
<BLANKLINE>
<BLANKLINE>
      <option id="form-widgets-favourite_city-3" value="torino">Torino</option>
<BLANKLINE>
  </select>
  <input name="form.widgets.favourite_city-empty-marker" type="hidden" value="1" />
</div>
<BLANKLINE>

We can see that the rendered JavaScript is expecting to call a view for ajax widgets like this:

>>> widget = form.widgets['afavourite_city']
>>> context.REQUEST._script = 'bar/@@cities-form/++widget++form.widgets.avisited_cities/@@chosen-autocomplete-search'.split('/')
>>> context.REQUEST._resetURLS()
>>> context.REQUEST.form['term'] = 'or'
>>> search_view = getMultiAdapter((widget, context.REQUEST), name=u'chosen-autocomplete-search')

The results are a json tuple list of tokens:

>>> print search_view()
[["sorrento","Sorrento"],["torino","Torino"]]

At first we didnt set anything in the request, we are missing fields

>>> form.update()
>>> data, errors = form.extractData()
>>> len(errors)
3
>>> form.request.form.update({
...  "form.buttons.apply" : "Apply",
...  "form.widgets.visited_cities" : ["palermo", "bologna"],
...  "form.widgets.avisited_cities" : ["palermo", "bologna"],
...  "form.widgets.afavourite_city" :"bologna",
...  "form.widgets.favourite_city" : "palermo",
... })
>>> form.update() # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
Submitted data:...
>>> data, errors = form.extractData()
>>> items = data.items()
>>> items.sort(key=lambda x:x[0])
>>> pprint(items)
[('afavourite_city', u'bologna'),
 ('avisited_cities', [u'palermo', u'bologna']),
 ('favourite_city', u'palermo'),
 ('visited_cities', [u'palermo', u'bologna'])]

Our values are marked as selected

>>> results = form.render().replace('...', '')
>>> False not in [
... (it in results)
... for it in ['id="form-widgets-visited_cities-0" value="bologna" selected="selected">Bologna',
...            'id="form-widgets-visited_cities-1" value="palermo" selected="selected">Palermo']]
True

Our widget also handle display mode

>>> form.widgets['favourite_city'].mode = 'display'
>>> print form.widgets['favourite_city'].render().strip()
 <span id="form-widgets-favourite_city" class="chosen-selection-widget required choice-field" style=""><span class="selected-option">Palermo</span></span>
>>> form.widgets['visited_cities'].mode = 'display'
>>> print form.widgets['visited_cities'].render().strip()
<span id="form-widgets-visited_cities" class="chosen-multiselection-widget required list-field" style=""><span class="selected-option">Palermo</span>, <span class="selected-option">Bologna</span></span>

Our widget also handle hidden mode

>>> form.widgets['favourite_city'].mode = 'hidden'
>>> print form.widgets['favourite_city'].render().strip()
<input id="form-widgets-favourite_city-1" name="form.widgets.favourite_city:list" value="palermo" class="hidden-widget" type="hidden" />
<BLANKLINE>
<BLANKLINE>
<BLANKLINE>
<BLANKLINE>
<BLANKLINE>
<BLANKLINE>
<BLANKLINE>
<input name="form.widgets.favourite_city-empty-marker" type="hidden" value="1" />
>>> form.widgets['visited_cities'].mode = 'hidden'
>>> print form.widgets['visited_cities'].render().strip()
<input id="form-widgets-visited_cities-0" name="form.widgets.visited_cities:list" value="bologna" class="hidden-widget" type="hidden" />
<BLANKLINE>
<BLANKLINE>
  <input id="form-widgets-visited_cities-1" name="form.widgets.visited_cities:list" value="palermo" class="hidden-widget" type="hidden" />
<BLANKLINE>
<BLANKLINE>
<BLANKLINE>
<BLANKLINE>
<BLANKLINE>
<BLANKLINE>
<BLANKLINE>
<input name="form.widgets.visited_cities-empty-marker" type="hidden" value="1" />

collective.z3cform.chosen Installation

To install collective.z3cform.chosen, follow this documentation.

Changelog

1.2.1 (2014-09-25)

  • Widget works when the field is initially hidden (for instance in an overlay). [thomasdesvenain]
  • Pyflakes, pep8, unused code removed, etc. [thomasdesvenain]

1.2 (2014-06-03)

  • Set width, and apply as chosen parameter rather than styling widgets with a specific width; doing so ensures chosen will set a valid width when it’s initialized off-screen or when the element applied to it is invisible. [damilgra]
  • Updated french translations. [cedricmessiant]

1.1 (2013-06-04)

  • buildout, tests & travis [kiorky]
  • Change prompt message and update French translations. Fix bug for no value in List fields. [cedricmessiant]

1.0 (2012-06-06)

  • Initial release [kiorky]
Release History

Release History

1.2.1

This version

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

1.2

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

1.1

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

1.0

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

Download Files

Download Files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

File Name & Checksum SHA256 Checksum Help Version File Type Upload Date
collective.z3cform.chosen-1.2.1.zip (60.5 kB) Copy SHA256 Checksum SHA256 Source Sep 25, 2014

Supported By

WebFaction WebFaction Technical Writing Elastic Elastic Search Pingdom Pingdom Monitoring Dyn Dyn DNS Sentry Sentry Error Logging CloudAMQP CloudAMQP RabbitMQ Heroku Heroku PaaS Kabu Creative Kabu Creative UX & Design Fastly Fastly CDN DigiCert DigiCert EV Certificate Rackspace Rackspace Cloud Servers DreamHost DreamHost Log Hosting