web/formwidgets.py
author Sylvain Thénault <sylvain.thenault@logilab.fr>
Thu, 18 Feb 2010 11:08:00 +0100
branchstable
changeset 4628 2f23148d0870
parent 4627 54de0ddd0bf3
child 4658 25de2eb0432b
permissions -rw-r--r--
[form fields] nicer behaviour of the password field: don't put internal field value on edition (triggering validation error if one validation without removing the value, due to confirmation mismatch), and don't show the field as required in such case
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
     1
"""widget classes for form construction
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
     2
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
     3
:organization: Logilab
4382
6fb02edd05da 3.6 api update, cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4376
diff changeset
     4
:copyright: 2009-2010 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
     5
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
1977
606923dff11b big bunch of copyright / docstring update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1970
diff changeset
     6
:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
     7
"""
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
     8
__docformat__ = "restructuredtext en"
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
     9
1096
e1fe98850bf7 cleanup
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
    10
from datetime import date
1966
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
    11
from warnings import warn
1096
e1fe98850bf7 cleanup
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
    12
4160
3fbdeef9a610 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4159
diff changeset
    13
from logilab.mtconverter import xml_escape
3fbdeef9a610 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4159
diff changeset
    14
from logilab.common.deprecation import deprecated
4481
56440a1f816a hidden usage of datetime function which has been moved to lgc
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4392
diff changeset
    15
from logilab.common.date import todatetime
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    16
4481
56440a1f816a hidden usage of datetime function which has been moved to lgc
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4392
diff changeset
    17
from cubicweb import tags, uilib
3387
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2549
diff changeset
    18
from cubicweb.web import stdmsgs, INTERNAL_FIELD_VALUE, ProcessFormError
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
    19
4583
356f08325072 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4550
diff changeset
    20
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    21
class FieldWidget(object):
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
    22
    """abstract widget class"""
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
    23
    # javascript / css files required by the widget
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    24
    needs_js = ()
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    25
    needs_css = ()
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
    26
    # automatically set id and tabindex attributes ?
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    27
    setdomid = True
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    28
    settabindex = True
4371
0d337feb5374 [forms] new optional suffix attribute on widget objects, used to generage input name / dom id.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4305
diff changeset
    29
    # to ease usage as a sub-widgets (eg widget used by another widget)
0d337feb5374 [forms] new optional suffix attribute on widget objects, used to generage input name / dom id.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4305
diff changeset
    30
    suffix = None
2091
a7ea618e5478 don't set select widget when a vocabulary widget is already specified on the field class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1989
diff changeset
    31
    # does this widget expect a vocabulary
a7ea618e5478 don't set select widget when a vocabulary widget is already specified on the field class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1989
diff changeset
    32
    vocabulary_widget = False
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
    33
4371
0d337feb5374 [forms] new optional suffix attribute on widget objects, used to generage input name / dom id.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4305
diff changeset
    34
    def __init__(self, attrs=None, setdomid=None, settabindex=None, suffix=None):
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
    35
        if attrs is None:
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
    36
            attrs = {}
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
    37
        self.attrs = attrs
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    38
        if setdomid is not None:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    39
            # override class's default value
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    40
            self.setdomid = setdomid
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    41
        if settabindex is not None:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    42
            # override class's default value
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    43
            self.settabindex = settabindex
4371
0d337feb5374 [forms] new optional suffix attribute on widget objects, used to generage input name / dom id.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4305
diff changeset
    44
        if suffix is not None:
0d337feb5374 [forms] new optional suffix attribute on widget objects, used to generage input name / dom id.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4305
diff changeset
    45
            self.suffix = suffix
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    46
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    47
    def add_media(self, form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    48
        """adds media (CSS & JS) required by this widget"""
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    49
        if self.needs_js:
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
    50
            form._cw.add_js(self.needs_js)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    51
        if self.needs_css:
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
    52
            form._cw.add_css(self.needs_css)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
    53
4372
0c44af150a49 introduce a default render implementation on the base widget, which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4371
diff changeset
    54
0c44af150a49 introduce a default render implementation on the base widget, which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4371
diff changeset
    55
    def render(self, form, field, renderer=None):
0c44af150a49 introduce a default render implementation on the base widget, which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4371
diff changeset
    56
        self.add_media(form)
0c44af150a49 introduce a default render implementation on the base widget, which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4371
diff changeset
    57
        return self._render(form, field, renderer)
0c44af150a49 introduce a default render implementation on the base widget, which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4371
diff changeset
    58
0c44af150a49 introduce a default render implementation on the base widget, which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4371
diff changeset
    59
    def _render(self, form, field, renderer):
0c44af150a49 introduce a default render implementation on the base widget, which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4371
diff changeset
    60
        raise NotImplementedError()
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    61
4304
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    62
    def typed_value(self, form, field):
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    63
        """return field's *typed* value specified in:
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    64
        3. extra form values given to render()
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    65
        4. field's typed value
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    66
        """
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    67
        qname = field.input_name(form)
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    68
        for key in (field, qname):
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    69
            try:
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    70
                return form.formvalues[key]
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    71
            except KeyError:
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    72
                continue
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    73
        if field.name != qname and field.name in form.formvalues:
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    74
            return form.formvalues[field.name]
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    75
        return field.typed_value(form)
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    76
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    77
    def format_value(self, form, field, value):
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    78
        return field.format_value(form._cw, value)
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    79
4163
b2747ed057e6 substitute _render_attrs by values_and_attributes method, keeping bw compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
    80
    def values_and_attributes(self, form, field):
4304
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    81
        """found field's *string* value in:
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    82
        1. previously submitted form values if any (eg on validation error)
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    83
        2. req.form
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    84
        3. extra form values given to render()
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    85
        4. field's typed value
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    86
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    87
        values found in 1. and 2. are expected te be already some 'display'
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    88
        value while those found in 3. and 4. are expected to be correctly typed.
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    89
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    90
        3 and 4 are handle by the .typed_value(form, field) method
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    91
        """
4371
0d337feb5374 [forms] new optional suffix attribute on widget objects, used to generage input name / dom id.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4305
diff changeset
    92
        attrs = dict(self.attrs)
0d337feb5374 [forms] new optional suffix attribute on widget objects, used to generage input name / dom id.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4305
diff changeset
    93
        if self.setdomid:
0d337feb5374 [forms] new optional suffix attribute on widget objects, used to generage input name / dom id.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4305
diff changeset
    94
            attrs['id'] = field.dom_id(form, self.suffix)
0d337feb5374 [forms] new optional suffix attribute on widget objects, used to generage input name / dom id.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4305
diff changeset
    95
        if self.settabindex and not 'tabindex' in attrs:
0d337feb5374 [forms] new optional suffix attribute on widget objects, used to generage input name / dom id.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4305
diff changeset
    96
            attrs['tabindex'] = form._cw.next_tabindex()
0d337feb5374 [forms] new optional suffix attribute on widget objects, used to generage input name / dom id.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4305
diff changeset
    97
        return self.values(form, field), attrs
0d337feb5374 [forms] new optional suffix attribute on widget objects, used to generage input name / dom id.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4305
diff changeset
    98
0d337feb5374 [forms] new optional suffix attribute on widget objects, used to generage input name / dom id.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4305
diff changeset
    99
    def values(self, form, field):
0d337feb5374 [forms] new optional suffix attribute on widget objects, used to generage input name / dom id.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4305
diff changeset
   100
        qname = field.input_name(form, self.suffix)
4304
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   101
        if qname in form.form_previous_values:
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   102
            values = form.form_previous_values[qname]
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   103
        elif qname in form._cw.form:
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   104
            values = form._cw.form[qname]
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   105
        elif field.name != qname and field.name in form._cw.form:
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   106
            # compat: accept attr=value in req.form to specify value of attr-subject
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   107
            values = form._cw.form[field.name]
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   108
        else:
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   109
            values = self.typed_value(form, field)
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   110
            if values != INTERNAL_FIELD_VALUE:
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   111
                values = self.format_value(form, field, values)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   112
        if not isinstance(values, (tuple, list)):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   113
            values = (values,)
4371
0d337feb5374 [forms] new optional suffix attribute on widget objects, used to generage input name / dom id.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4305
diff changeset
   114
        return values
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   115
3387
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2549
diff changeset
   116
    def process_field_data(self, form, field):
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   117
        posted = form._cw.form
4371
0d337feb5374 [forms] new optional suffix attribute on widget objects, used to generage input name / dom id.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4305
diff changeset
   118
        val = posted.get(field.input_name(form, self.suffix))
4169
341d19ef7b7c strip string by default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4163
diff changeset
   119
        if isinstance(val, basestring):
4392
91a56a30141e by default this is not the widget responsability to turn empty string into None,
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4382
diff changeset
   120
            val = val.strip()
4163
b2747ed057e6 substitute _render_attrs by values_and_attributes method, keeping bw compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   121
        return val
b2747ed057e6 substitute _render_attrs by values_and_attributes method, keeping bw compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   122
b2747ed057e6 substitute _render_attrs by values_and_attributes method, keeping bw compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   123
    @deprecated('[3.6] use values_and_attributes')
b2747ed057e6 substitute _render_attrs by values_and_attributes method, keeping bw compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   124
    def _render_attrs(self, form, field):
b2747ed057e6 substitute _render_attrs by values_and_attributes method, keeping bw compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   125
        """return html tag name, attributes and a list of values for the field
b2747ed057e6 substitute _render_attrs by values_and_attributes method, keeping bw compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   126
        """
b2747ed057e6 substitute _render_attrs by values_and_attributes method, keeping bw compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   127
        values, attrs = self.values_and_attributes(form, field)
4371
0d337feb5374 [forms] new optional suffix attribute on widget objects, used to generage input name / dom id.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4305
diff changeset
   128
        return field.input_name(form, self.suffix), values, attrs
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   129
1096
e1fe98850bf7 cleanup
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   130
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   131
class Input(FieldWidget):
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   132
    """abstract widget class for <input> tag based widgets"""
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   133
    type = None
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   134
4372
0c44af150a49 introduce a default render implementation on the base widget, which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4371
diff changeset
   135
    def _render(self, form, field, renderer):
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   136
        """render the widget for the given `field` of `form`.
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   137
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   138
        Generate one <input> tag for each field's value
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   139
        """
4163
b2747ed057e6 substitute _render_attrs by values_and_attributes method, keeping bw compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   140
        values, attrs = self.values_and_attributes(form, field)
1768
b59b7c422a8a ensure input widgets are displayed anyway if they get an empty list as values
sylvain.thenault@logilab.fr
parents: 1749
diff changeset
   141
        # ensure something is rendered
b59b7c422a8a ensure input widgets are displayed anyway if they get an empty list as values
sylvain.thenault@logilab.fr
parents: 1749
diff changeset
   142
        if not values:
b59b7c422a8a ensure input widgets are displayed anyway if they get an empty list as values
sylvain.thenault@logilab.fr
parents: 1749
diff changeset
   143
            values = (INTERNAL_FIELD_VALUE,)
4371
0d337feb5374 [forms] new optional suffix attribute on widget objects, used to generage input name / dom id.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4305
diff changeset
   144
        inputs = [tags.input(name=field.input_name(form, self.suffix),
0d337feb5374 [forms] new optional suffix attribute on widget objects, used to generage input name / dom id.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4305
diff changeset
   145
                             type=self.type, value=value, **attrs)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   146
                  for value in values]
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   147
        return u'\n'.join(inputs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   148
1096
e1fe98850bf7 cleanup
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   149
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   150
# basic html widgets ###########################################################
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   151
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   152
class TextInput(Input):
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   153
    """<input type='text'>"""
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   154
    type = 'text'
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   155
1096
e1fe98850bf7 cleanup
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   156
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   157
class PasswordInput(Input):
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   158
    """<input type='password'> and its confirmation field (using
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   159
    <field's name>-confirm as name)
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   160
    """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   161
    type = 'password'
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   162
4372
0c44af150a49 introduce a default render implementation on the base widget, which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4371
diff changeset
   163
    def _render(self, form, field, renderer):
0c44af150a49 introduce a default render implementation on the base widget, which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4371
diff changeset
   164
        assert self.suffix is None, 'suffix not supported'
4163
b2747ed057e6 substitute _render_attrs by values_and_attributes method, keeping bw compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   165
        values, attrs = self.values_and_attributes(form, field)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   166
        assert len(values) == 1
4627
54de0ddd0bf3 minor cleanup: don't use builtin 'id' as variable name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4597
diff changeset
   167
        domid = attrs.pop('id')
4156
1bbb0ee42c8e drop form_field_name/form_field_id methods from form object, in favor of field.input_name(form) / field.dom_id(form)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4023
diff changeset
   168
        inputs = [tags.input(name=field.input_name(form),
4627
54de0ddd0bf3 minor cleanup: don't use builtin 'id' as variable name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4597
diff changeset
   169
                             value=values[0], type=self.type, id=domid, **attrs),
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   170
                  '<br/>',
4156
1bbb0ee42c8e drop form_field_name/form_field_id methods from form object, in favor of field.input_name(form) / field.dom_id(form)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4023
diff changeset
   171
                  tags.input(name=field.input_name(form, '-confirm'),
1bbb0ee42c8e drop form_field_name/form_field_id methods from form object, in favor of field.input_name(form) / field.dom_id(form)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4023
diff changeset
   172
                             value=values[0], type=self.type, **attrs),
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   173
                  '&#160;', tags.span(form._cw._('confirm password'),
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   174
                                      **{'class': 'emphasis'})]
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   175
        return u'\n'.join(inputs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   176
3387
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2549
diff changeset
   177
    def process_field_data(self, form, field):
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2549
diff changeset
   178
        passwd1 = super(PasswordInput, self).process_field_data(form, field)
4156
1bbb0ee42c8e drop form_field_name/form_field_id methods from form object, in favor of field.input_name(form) / field.dom_id(form)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4023
diff changeset
   179
        passwd2 = form._cw.form.get(field.input_name(form, '-confirm'))
3387
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2549
diff changeset
   180
        if passwd1 == passwd2:
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2549
diff changeset
   181
            if passwd1 is None:
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2549
diff changeset
   182
                return None
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2549
diff changeset
   183
            return passwd1.encode('utf-8')
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   184
        raise ProcessFormError(form._cw._("password and confirmation don't match"))
1096
e1fe98850bf7 cleanup
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   185
e1fe98850bf7 cleanup
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   186
1934
be86bb31c4c2 add single input password widget
Florent <florent@secondweb.fr>
parents: 1875
diff changeset
   187
class PasswordSingleInput(Input):
be86bb31c4c2 add single input password widget
Florent <florent@secondweb.fr>
parents: 1875
diff changeset
   188
    """<input type='password'> without a confirmation field"""
be86bb31c4c2 add single input password widget
Florent <florent@secondweb.fr>
parents: 1875
diff changeset
   189
    type = 'password'
be86bb31c4c2 add single input password widget
Florent <florent@secondweb.fr>
parents: 1875
diff changeset
   190
3387
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2549
diff changeset
   191
    def process_field_data(self, form, field):
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2549
diff changeset
   192
        value = super(PasswordSingleInput, self).process_field_data(form, field)
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2549
diff changeset
   193
        if value is not None:
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2549
diff changeset
   194
            return value.encode('utf-8')
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2549
diff changeset
   195
        return value
1934
be86bb31c4c2 add single input password widget
Florent <florent@secondweb.fr>
parents: 1875
diff changeset
   196
be86bb31c4c2 add single input password widget
Florent <florent@secondweb.fr>
parents: 1875
diff changeset
   197
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   198
class FileInput(Input):
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   199
    """<input type='file'>"""
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   200
    type = 'file'
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   201
4163
b2747ed057e6 substitute _render_attrs by values_and_attributes method, keeping bw compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   202
    def values_and_attributes(self, form, field):
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   203
        # ignore value which makes no sense here (XXX even on form validation error?)
4163
b2747ed057e6 substitute _render_attrs by values_and_attributes method, keeping bw compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   204
        values, attrs = super(FileInput, self).values_and_attributes(form, field)
b2747ed057e6 substitute _render_attrs by values_and_attributes method, keeping bw compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   205
        return ('',), attrs
1096
e1fe98850bf7 cleanup
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   206
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   207
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   208
class HiddenInput(Input):
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   209
    """<input type='hidden'>"""
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   210
    type = 'hidden'
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   211
    setdomid = False # by default, don't set id attribute on hidden input
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   212
    settabindex = False
1096
e1fe98850bf7 cleanup
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   213
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   214
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   215
class ButtonInput(Input):
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   216
    """<input type='button'>
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   217
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   218
    if you want a global form button, look at the Button, SubmitButton,
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   219
    ResetButton and ImgButton classes below.
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   220
    """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   221
    type = 'button'
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   222
1096
e1fe98850bf7 cleanup
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   223
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   224
class TextArea(FieldWidget):
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   225
    """<textarea>"""
2366
e4229723b824 [formwidgets] let the textarea height be dependant on the actual content (up to a limit)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2360
diff changeset
   226
4372
0c44af150a49 introduce a default render implementation on the base widget, which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4371
diff changeset
   227
    def _render(self, form, field, renderer):
4163
b2747ed057e6 substitute _render_attrs by values_and_attributes method, keeping bw compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   228
        values, attrs = self.values_and_attributes(form, field)
2131
00e6d1cb18ea [views] call autogrow only once per key event
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2091
diff changeset
   229
        attrs.setdefault('onkeyup', 'autogrow(this)')
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   230
        if not values:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   231
            value = u''
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   232
        elif len(values) == 1:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   233
            value = values[0]
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   234
        else:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   235
            raise ValueError('a textarea is not supposed to be multivalued')
2366
e4229723b824 [formwidgets] let the textarea height be dependant on the actual content (up to a limit)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2360
diff changeset
   236
        lines = value.splitlines()
e4229723b824 [formwidgets] let the textarea height be dependant on the actual content (up to a limit)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2360
diff changeset
   237
        linecount = len(lines)
e4229723b824 [formwidgets] let the textarea height be dependant on the actual content (up to a limit)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2360
diff changeset
   238
        for line in lines:
e4229723b824 [formwidgets] let the textarea height be dependant on the actual content (up to a limit)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2360
diff changeset
   239
            linecount += len(line) / 80
e4229723b824 [formwidgets] let the textarea height be dependant on the actual content (up to a limit)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2360
diff changeset
   240
        attrs.setdefault('cols', 80)
e4229723b824 [formwidgets] let the textarea height be dependant on the actual content (up to a limit)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2360
diff changeset
   241
        attrs.setdefault('rows', min(15, linecount + 2))
4371
0d337feb5374 [forms] new optional suffix attribute on widget objects, used to generage input name / dom id.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4305
diff changeset
   242
        return tags.textarea(value, name=field.input_name(form, self.suffix),
0d337feb5374 [forms] new optional suffix attribute on widget objects, used to generage input name / dom id.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4305
diff changeset
   243
                             **attrs)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   244
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   245
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   246
class FCKEditor(TextArea):
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   247
    """FCKEditor enabled <textarea>"""
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   248
    def __init__(self, *args, **kwargs):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   249
        super(FCKEditor, self).__init__(*args, **kwargs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   250
        self.attrs['cubicweb:type'] = 'wysiwyg'
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   251
4372
0c44af150a49 introduce a default render implementation on the base widget, which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4371
diff changeset
   252
    def _render(self, form, field, renderer):
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   253
        form._cw.fckeditor_config()
4372
0c44af150a49 introduce a default render implementation on the base widget, which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4371
diff changeset
   254
        return super(FCKEditor, self)._render(form, field, renderer)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   255
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   256
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   257
class Select(FieldWidget):
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   258
    """<select>, for field having a specific vocabulary"""
2091
a7ea618e5478 don't set select widget when a vocabulary widget is already specified on the field class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1989
diff changeset
   259
    vocabulary_widget = True
a7ea618e5478 don't set select widget when a vocabulary widget is already specified on the field class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1989
diff changeset
   260
1562
e6d2c07c0c58 [forms/widgets] fix relation field not sorting its vocabulary, revert hack on Select widget
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 1541
diff changeset
   261
    def __init__(self, attrs=None, multiple=False):
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   262
        super(Select, self).__init__(attrs)
1541
ddddbb748355 [widgets] an option for Select to show sorted content
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 1538
diff changeset
   263
        self._multiple = multiple
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   264
2522
562f5dcf2345 widget.render now takes the renderer as third argument (keeping minimal bw compat)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2519
diff changeset
   265
    def render(self, form, field, renderer):
4163
b2747ed057e6 substitute _render_attrs by values_and_attributes method, keeping bw compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   266
        curvalues, attrs = self.values_and_attributes(form, field)
1989
8c8dead642f7 set default select size to 1 into the widget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   267
        if not 'size' in attrs:
8c8dead642f7 set default select size to 1 into the widget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   268
            attrs['size'] = self._multiple and '5' or '1'
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   269
        options = []
1771
bb9538d91465 fix <optgroup> tag cannot be empty according to DTD
Florent <florent@secondweb.fr>
parents: 1768
diff changeset
   270
        optgroup_opened = False
2518
38c28ee40138 allow vocabulary functions to return either label/value or label/value/dict (to use as attributes of the tag for this input)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2366
diff changeset
   271
        for option in field.vocabulary(form):
38c28ee40138 allow vocabulary functions to return either label/value or label/value/dict (to use as attributes of the tag for this input)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2366
diff changeset
   272
            try:
38c28ee40138 allow vocabulary functions to return either label/value or label/value/dict (to use as attributes of the tag for this input)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2366
diff changeset
   273
                label, value, oattrs = option
38c28ee40138 allow vocabulary functions to return either label/value or label/value/dict (to use as attributes of the tag for this input)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2366
diff changeset
   274
            except ValueError:
38c28ee40138 allow vocabulary functions to return either label/value or label/value/dict (to use as attributes of the tag for this input)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2366
diff changeset
   275
                label, value = option
38c28ee40138 allow vocabulary functions to return either label/value or label/value/dict (to use as attributes of the tag for this input)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2366
diff changeset
   276
                oattrs = {}
1336
2e552353c42a insert an optgroup as separator on None values
sylvain.thenault@logilab.fr
parents: 1330
diff changeset
   277
            if value is None:
2e552353c42a insert an optgroup as separator on None values
sylvain.thenault@logilab.fr
parents: 1330
diff changeset
   278
                # handle separator
1771
bb9538d91465 fix <optgroup> tag cannot be empty according to DTD
Florent <florent@secondweb.fr>
parents: 1768
diff changeset
   279
                if optgroup_opened:
bb9538d91465 fix <optgroup> tag cannot be empty according to DTD
Florent <florent@secondweb.fr>
parents: 1768
diff changeset
   280
                    options.append(u'</optgroup>')
2518
38c28ee40138 allow vocabulary functions to return either label/value or label/value/dict (to use as attributes of the tag for this input)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2366
diff changeset
   281
                oattrs.setdefault('label', label or '')
38c28ee40138 allow vocabulary functions to return either label/value or label/value/dict (to use as attributes of the tag for this input)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2366
diff changeset
   282
                options.append(u'<optgroup %s>' % uilib.sgml_attributes(oattrs))
1771
bb9538d91465 fix <optgroup> tag cannot be empty according to DTD
Florent <florent@secondweb.fr>
parents: 1768
diff changeset
   283
                optgroup_opened = True
1336
2e552353c42a insert an optgroup as separator on None values
sylvain.thenault@logilab.fr
parents: 1330
diff changeset
   284
            elif value in curvalues:
2518
38c28ee40138 allow vocabulary functions to return either label/value or label/value/dict (to use as attributes of the tag for this input)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2366
diff changeset
   285
                options.append(tags.option(label, value=value,
38c28ee40138 allow vocabulary functions to return either label/value or label/value/dict (to use as attributes of the tag for this input)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2366
diff changeset
   286
                                           selected='selected', **oattrs))
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   287
            else:
2518
38c28ee40138 allow vocabulary functions to return either label/value or label/value/dict (to use as attributes of the tag for this input)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2366
diff changeset
   288
                options.append(tags.option(label, value=value, **oattrs))
1771
bb9538d91465 fix <optgroup> tag cannot be empty according to DTD
Florent <florent@secondweb.fr>
parents: 1768
diff changeset
   289
        if optgroup_opened:
bb9538d91465 fix <optgroup> tag cannot be empty according to DTD
Florent <florent@secondweb.fr>
parents: 1768
diff changeset
   290
            options.append(u'</optgroup>')
4371
0d337feb5374 [forms] new optional suffix attribute on widget objects, used to generage input name / dom id.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4305
diff changeset
   291
        return tags.select(name=field.input_name(form, self.suffix),
0d337feb5374 [forms] new optional suffix attribute on widget objects, used to generage input name / dom id.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4305
diff changeset
   292
                           multiple=self._multiple, options=options, **attrs)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   293
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   294
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   295
class CheckBox(Input):
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   296
    """<input type='checkbox'>, for field having a specific vocabulary. One
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   297
    input will be generated for each possible value.
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   298
    """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   299
    type = 'checkbox'
2091
a7ea618e5478 don't set select widget when a vocabulary widget is already specified on the field class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1989
diff changeset
   300
    vocabulary_widget = True
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   301
2522
562f5dcf2345 widget.render now takes the renderer as third argument (keeping minimal bw compat)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2519
diff changeset
   302
    def render(self, form, field, renderer):
4163
b2747ed057e6 substitute _render_attrs by values_and_attributes method, keeping bw compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   303
        curvalues, attrs = self.values_and_attributes(form, field)
1367
01bb5b727fe3 set dom id on the first input of radio choices
sylvain.thenault@logilab.fr
parents: 1359
diff changeset
   304
        domid = attrs.pop('id', None)
2519
ac1a869e1e93 nicer checkbox widget implementation, avoid extra <br/> at the end
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2518
diff changeset
   305
        sep = attrs.pop('separator', u'<br/>\n')
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   306
        options = []
2518
38c28ee40138 allow vocabulary functions to return either label/value or label/value/dict (to use as attributes of the tag for this input)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2366
diff changeset
   307
        for i, option in enumerate(field.vocabulary(form)):
38c28ee40138 allow vocabulary functions to return either label/value or label/value/dict (to use as attributes of the tag for this input)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2366
diff changeset
   308
            try:
38c28ee40138 allow vocabulary functions to return either label/value or label/value/dict (to use as attributes of the tag for this input)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2366
diff changeset
   309
                label, value, oattrs = option
38c28ee40138 allow vocabulary functions to return either label/value or label/value/dict (to use as attributes of the tag for this input)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2366
diff changeset
   310
            except ValueError:
38c28ee40138 allow vocabulary functions to return either label/value or label/value/dict (to use as attributes of the tag for this input)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2366
diff changeset
   311
                label, value = option
38c28ee40138 allow vocabulary functions to return either label/value or label/value/dict (to use as attributes of the tag for this input)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2366
diff changeset
   312
                oattrs = {}
1367
01bb5b727fe3 set dom id on the first input of radio choices
sylvain.thenault@logilab.fr
parents: 1359
diff changeset
   313
            iattrs = attrs.copy()
2518
38c28ee40138 allow vocabulary functions to return either label/value or label/value/dict (to use as attributes of the tag for this input)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2366
diff changeset
   314
            iattrs.update(oattrs)
1367
01bb5b727fe3 set dom id on the first input of radio choices
sylvain.thenault@logilab.fr
parents: 1359
diff changeset
   315
            if i == 0 and domid is not None:
2518
38c28ee40138 allow vocabulary functions to return either label/value or label/value/dict (to use as attributes of the tag for this input)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2366
diff changeset
   316
                iattrs.setdefault('id', domid)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   317
            if value in curvalues:
1367
01bb5b727fe3 set dom id on the first input of radio choices
sylvain.thenault@logilab.fr
parents: 1359
diff changeset
   318
                iattrs['checked'] = u'checked'
4371
0d337feb5374 [forms] new optional suffix attribute on widget objects, used to generage input name / dom id.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4305
diff changeset
   319
            tag = tags.input(name=field.input_name(form, self.suffix),
0d337feb5374 [forms] new optional suffix attribute on widget objects, used to generage input name / dom id.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4305
diff changeset
   320
                             type=self.type, value=value, **iattrs)
4593
d0b5ef72a492 add space between a checkbox and its label
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4583
diff changeset
   321
            options.append(u'%s&#160;%s' % (tag, label))
2519
ac1a869e1e93 nicer checkbox widget implementation, avoid extra <br/> at the end
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2518
diff changeset
   322
        return sep.join(options)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   323
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   324
1832
3384264d25cc fix CheckBox multiple dom id and refactor with Radio
Florent <florent@secondweb.fr>
parents: 1771
diff changeset
   325
class Radio(CheckBox):
3384264d25cc fix CheckBox multiple dom id and refactor with Radio
Florent <florent@secondweb.fr>
parents: 1771
diff changeset
   326
    """<input type='radio'>, for field having a specific vocabulary. One
3384264d25cc fix CheckBox multiple dom id and refactor with Radio
Florent <florent@secondweb.fr>
parents: 1771
diff changeset
   327
    input will be generated for each possible value.
3384264d25cc fix CheckBox multiple dom id and refactor with Radio
Florent <florent@secondweb.fr>
parents: 1771
diff changeset
   328
    """
3384264d25cc fix CheckBox multiple dom id and refactor with Radio
Florent <florent@secondweb.fr>
parents: 1771
diff changeset
   329
    type = 'radio'
3384264d25cc fix CheckBox multiple dom id and refactor with Radio
Florent <florent@secondweb.fr>
parents: 1771
diff changeset
   330
2225
16826403affa cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2131
diff changeset
   331
2523
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   332
# compound widgets #############################################################
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   333
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   334
class IntervalWidget(FieldWidget):
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   335
    """custom widget to display an interval composed by 2 fields. This widget
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   336
    is expected to be used with a CompoundField containing the two actual
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   337
    fields.
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   338
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   339
    Exemple usage::
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   340
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   341
from uicfg import autoform_field, autoform_section
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   342
autoform_field.tag_attribute(('Concert', 'minprice'),
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   343
                              CompoundField(fields=(IntField(name='minprice'),
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   344
                                                    IntField(name='maxprice')),
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   345
                                            label=_('price'),
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   346
                                            widget=IntervalWidget()
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   347
                                            ))
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   348
# we've to hide the other field manually for now
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   349
autoform_section.tag_attribute(('Concert', 'maxprice'), 'generated')
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   350
    """
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   351
    def render(self, form, field, renderer):
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   352
        actual_fields = field.fields
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   353
        assert len(actual_fields) == 2
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   354
        return u'<div>%s %s %s %s</div>' % (
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   355
            form._cw._('from_interval_start'),
2523
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   356
            actual_fields[0].render(form, renderer),
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   357
            form._cw._('to_interval_end'),
2523
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   358
            actual_fields[1].render(form, renderer),
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   359
            )
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   360
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   361
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   362
class HorizontalLayoutWidget(FieldWidget):
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   363
    """custom widget to display a set of fields grouped together horizontally
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   364
    in a form. See `IntervalWidget` for example usage.
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   365
    """
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   366
    def render(self, form, field, renderer):
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   367
        if self.attrs.get('display_label', True):
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   368
            subst = self.attrs.get('label_input_substitution', '%(label)s %(input)s')
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   369
            fields = [subst % {'label': renderer.render_label(form, f),
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   370
                              'input': f.render(form, renderer)}
2549
3d8c62e5e2d4 [R forms] use a subfields(form) method to get a chance to adapt to context
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2523
diff changeset
   371
                      for f in field.subfields(form)]
2523
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   372
        else:
2549
3d8c62e5e2d4 [R forms] use a subfields(form) method to get a chance to adapt to context
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2523
diff changeset
   373
            fields = [f.render(form, renderer) for f in field.subfields(form)]
2523
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   374
        return u'<div>%s</div>' % ' '.join(fields)
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   375
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   376
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   377
# javascript widgets ###########################################################
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   378
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   379
class DateTimePicker(TextInput):
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   380
    """<input type='text' + javascript date/time picker for date or datetime
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   381
    fields
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   382
    """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   383
    monthnames = ('january', 'february', 'march', 'april',
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   384
                  'may', 'june', 'july', 'august',
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   385
                  'september', 'october', 'november', 'december')
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   386
    daynames = ('monday', 'tuesday', 'wednesday', 'thursday',
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   387
                'friday', 'saturday', 'sunday')
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   388
1311
4cc6e2723dc7 move ajax.js to base form class
sylvain.thenault@logilab.fr
parents: 1304
diff changeset
   389
    needs_js = ('cubicweb.calendar.js',)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   390
    needs_css = ('cubicweb.calendar_popup.css',)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   391
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   392
    @classmethod
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   393
    def add_localized_infos(cls, req):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   394
        """inserts JS variables defining localized months and days"""
4023
eae23c40627a drop common subpackage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3998
diff changeset
   395
        # import here to avoid dependancy from cubicweb to simplejson
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   396
        _ = req._
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   397
        monthnames = [_(mname) for mname in cls.monthnames]
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   398
        daynames = [_(dname) for dname in cls.daynames]
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   399
        req.html_headers.define_var('MONTHNAMES', monthnames)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   400
        req.html_headers.define_var('DAYNAMES', daynames)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   401
2522
562f5dcf2345 widget.render now takes the renderer as third argument (keeping minimal bw compat)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2519
diff changeset
   402
    def render(self, form, field, renderer):
562f5dcf2345 widget.render now takes the renderer as third argument (keeping minimal bw compat)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2519
diff changeset
   403
        txtwidget = super(DateTimePicker, self).render(form, field, renderer)
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   404
        self.add_localized_infos(form._cw)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   405
        cal_button = self._render_calendar_popup(form, field)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   406
        return txtwidget + cal_button
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   407
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   408
    def _render_calendar_popup(self, form, field):
4159
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4156
diff changeset
   409
        value = field.typed_value(form)
1392
d6279efff7b3 refactor the way field value/display value are handled to avoid getting a 'display' value when expected a 'typed' value
sylvain.thenault@logilab.fr
parents: 1389
diff changeset
   410
        if not value:
d6279efff7b3 refactor the way field value/display value are handled to avoid getting a 'display' value when expected a 'typed' value
sylvain.thenault@logilab.fr
parents: 1389
diff changeset
   411
            value = date.today()
4156
1bbb0ee42c8e drop form_field_name/form_field_id methods from form object, in favor of field.input_name(form) / field.dom_id(form)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4023
diff changeset
   412
        inputid = field.dom_id(form)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   413
        helperid = '%shelper' % inputid
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   414
        year, month = value.year, value.month
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   415
        return (u"""<a onclick="toggleCalendar('%s', '%s', %s, %s);" class="calhelper">
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   416
<img src="%s" title="%s" alt="" /></a><div class="calpopup hidden" id="%s"></div>"""
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   417
                % (helperid, inputid, year, month,
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   418
                   form._cw.external_resource('CALENDAR_ICON'),
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   419
                   form._cw._('calendar'), helperid) )
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   420
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   421
4373
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   422
class JQueryDatePicker(FieldWidget):
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   423
    """use jquery.ui.datepicker to define a date time picker"""
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   424
    needs_js = ('jquery.ui.js', )
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   425
    needs_css = ('jquery.ui.css',)
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   426
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   427
    def __init__(self, datestr=None, **kwargs):
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   428
        super(JQueryDatePicker, self).__init__(**kwargs)
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   429
        self.datestr = datestr
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   430
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   431
    def _render(self, form, field, renderer):
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   432
        req = form._cw
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   433
        domid = field.dom_id(form, self.suffix)
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   434
        # XXX find a way to understand every format
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   435
        fmt = req.property_value('ui.date-format')
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   436
        fmt = fmt.replace('%Y', 'yy').replace('%m', 'mm').replace('%d', 'dd')
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   437
        req.add_onload(u'jqNode("%s").datepicker('
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   438
                       '{buttonImage: "%s", dateFormat: "%s", firstDay: 1,'
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   439
                       ' showOn: "button", buttonImageOnly: true})' % (
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   440
                           domid, req.external_resource('CALENDAR_ICON'), fmt))
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   441
        if self.datestr is None:
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   442
            value = self.values(form, field)[0]
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   443
        else:
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   444
            value = self.datestr
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   445
        return tags.input(id=domid, name=domid, value=value,
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   446
                          type='text', size='10')
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   447
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   448
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   449
class JQueryTimePicker(FieldWidget):
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   450
    """use jquery.timePicker.js to define a js time picker"""
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   451
    needs_js = ('jquery.timePicker.js',)
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   452
    needs_css = ('jquery.timepicker.css',)
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   453
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   454
    def __init__(self, timestr=None, timesteps=30, **kwargs):
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   455
        super(JQueryTimePicker, self).__init__(**kwargs)
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   456
        self.timestr = timestr
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   457
        self.timesteps = timesteps
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   458
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   459
    def _render(self, form, field, renderer):
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   460
        req = form._cw
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   461
        domid = field.dom_id(form, self.suffix)
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   462
        req.add_onload(u'jqNode("%s").timePicker({selectedTime: "%s", step: %s})' % (
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   463
            domid, self.timestr, self.timesteps))
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   464
        if self.timestr is None:
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   465
            value = self.values(form, field)[0]
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   466
        else:
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   467
            value = self.timestr
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   468
        return tags.input(id=domid, name=domid, value=value,
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   469
                          type='text', size='5')
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   470
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   471
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   472
class JQueryDateTimePicker(FieldWidget):
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   473
    def __init__(self, initialtime=None, timesteps=15, **kwargs):
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   474
        super(JQueryDateTimePicker, self).__init__(**kwargs)
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   475
        self.initialtime = initialtime
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   476
        self.timesteps = timesteps
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   477
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   478
    def _render(self, form, field, renderer):
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   479
        """render the widget for the given `field` of `form`.
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   480
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   481
        Generate one <input> tag for each field's value
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   482
        """
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   483
        req = form._cw
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   484
        dateqname = field.input_name(form, 'date')
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   485
        timeqname = field.input_name(form, 'time')
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   486
        if dateqname in form.form_previous_values:
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   487
            datestr = form.form_previous_values[dateqname]
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   488
            timestr = form.form_previous_values[timeqname]
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   489
        else:
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   490
            datestr = timestr = u''
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   491
            if field.name in req.form:
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   492
                value = req.parse_datetime(req.form[field.name])
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   493
            else:
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   494
                value = self.typed_value(form, field)
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   495
            if value:
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   496
                datestr = req.format_date(value)
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   497
                timestr = req.format_time(value)
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   498
            elif self.initialtime:
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   499
                timestr = req.format_time(self.initialtime)
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   500
        datepicker = JQueryDatePicker(datestr=datestr, suffix='date')
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   501
        timepicker = JQueryTimePicker(timestr=timestr, timesteps=self.timesteps,
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   502
                                      suffix='time')
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   503
        return u'<div id="%s">%s%s</div>' % (field.dom_id(form),
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   504
                                            datepicker.render(form, field),
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   505
                                            timepicker.render(form, field))
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   506
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   507
    def process_field_data(self, form, field):
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   508
        req = form._cw
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   509
        datestr = req.form.get(field.input_name(form, 'date')).strip() or None
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   510
        timestr = req.form.get(field.input_name(form, 'time')).strip() or None
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   511
        if datestr is None:
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   512
            return None
4481
56440a1f816a hidden usage of datetime function which has been moved to lgc
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4392
diff changeset
   513
        date = todatetime(req.parse_datetime(datestr, 'Date'))
4373
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   514
        if timestr is None:
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   515
            return date
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   516
        time = req.parse_datetime(timestr, 'Time')
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   517
        return date.replace(hour=time.hour, minute=time.minute, second=time.second)
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   518
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   519
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   520
# ajax widgets ################################################################
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   521
1337
828bbf500bcc backport AddComboBoxWidget, ajax widgets refactoring
sylvain.thenault@logilab.fr
parents: 1336
diff changeset
   522
def init_ajax_attributes(attrs, wdgtype, loadtype=u'auto'):
828bbf500bcc backport AddComboBoxWidget, ajax widgets refactoring
sylvain.thenault@logilab.fr
parents: 1336
diff changeset
   523
    try:
4597
e872097f2287 use class, not klass, in widget.attrs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4593
diff changeset
   524
        attrs['class'] += u' widget'
1337
828bbf500bcc backport AddComboBoxWidget, ajax widgets refactoring
sylvain.thenault@logilab.fr
parents: 1336
diff changeset
   525
    except KeyError:
4597
e872097f2287 use class, not klass, in widget.attrs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4593
diff changeset
   526
        attrs['class'] = u'widget'
1344
930020cb134b shouldn't use unicode keys in attrs
sylvain.thenault@logilab.fr
parents: 1337
diff changeset
   527
    attrs.setdefault('cubicweb:wdgtype', wdgtype)
930020cb134b shouldn't use unicode keys in attrs
sylvain.thenault@logilab.fr
parents: 1337
diff changeset
   528
    attrs.setdefault('cubicweb:loadtype', loadtype)
1337
828bbf500bcc backport AddComboBoxWidget, ajax widgets refactoring
sylvain.thenault@logilab.fr
parents: 1336
diff changeset
   529
828bbf500bcc backport AddComboBoxWidget, ajax widgets refactoring
sylvain.thenault@logilab.fr
parents: 1336
diff changeset
   530
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   531
class AjaxWidget(FieldWidget):
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   532
    """simple <div> based ajax widget"""
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   533
    def __init__(self, wdgtype, inputid=None, **kwargs):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   534
        super(AjaxWidget, self).__init__(**kwargs)
1337
828bbf500bcc backport AddComboBoxWidget, ajax widgets refactoring
sylvain.thenault@logilab.fr
parents: 1336
diff changeset
   535
        init_ajax_attributes(self.attrs, wdgtype)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   536
        if inputid is not None:
1344
930020cb134b shouldn't use unicode keys in attrs
sylvain.thenault@logilab.fr
parents: 1337
diff changeset
   537
            self.attrs['cubicweb:inputid'] = inputid
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   538
4372
0c44af150a49 introduce a default render implementation on the base widget, which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4371
diff changeset
   539
    def _render(self, form, field, renderer):
4163
b2747ed057e6 substitute _render_attrs by values_and_attributes method, keeping bw compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   540
        attrs = self.values_and_attributes(form, field)[-1]
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   541
        return tags.div(**attrs)
1304
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   542
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   543
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   544
class AutoCompletionWidget(TextInput):
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   545
    """ajax widget for StringField, proposing matching existing values as you
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   546
    type.
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   547
    """
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   548
    needs_js = ('cubicweb.widgets.js', 'jquery.autocomplete.js')
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   549
    needs_css = ('jquery.autocomplete.css',)
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   550
    wdgtype = 'SuggestField'
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   551
    loadtype = 'auto'
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   552
1966
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   553
    def __init__(self, *args, **kwargs):
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   554
        try:
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   555
            self.autocomplete_initfunc = kwargs.pop('autocomplete_initfunc')
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   556
        except KeyError:
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   557
            warn('use autocomplete_initfunc argument of %s constructor '
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   558
                 'instead of relying on autocomplete_initfuncs dictionary on '
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   559
                 'the entity class' % self.__class__.__name__,
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   560
                 DeprecationWarning)
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   561
            self.autocomplete_initfunc = None
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   562
        super(AutoCompletionWidget, self).__init__(*args, **kwargs)
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   563
4163
b2747ed057e6 substitute _render_attrs by values_and_attributes method, keeping bw compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   564
    def values_and_attributes(self, form, field):
b2747ed057e6 substitute _render_attrs by values_and_attributes method, keeping bw compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   565
        values, attrs = super(AutoCompletionWidget, self).values_and_attributes(form, field)
1337
828bbf500bcc backport AddComboBoxWidget, ajax widgets refactoring
sylvain.thenault@logilab.fr
parents: 1336
diff changeset
   566
        init_ajax_attributes(attrs, self.wdgtype, self.loadtype)
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   567
        # XXX entity form specific
1875
7bcb02377516 no rschema attribute on widgets
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1874
diff changeset
   568
        attrs['cubicweb:dataurl'] = self._get_url(form.edited_entity, field)
3993
8cf7c767b134 quick & dirty fix for auto completion widget
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3803
diff changeset
   569
        if not values:
8cf7c767b134 quick & dirty fix for auto completion widget
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3803
diff changeset
   570
            values = ('',)
4163
b2747ed057e6 substitute _render_attrs by values_and_attributes method, keeping bw compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   571
        return values, attrs
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   572
1875
7bcb02377516 no rschema attribute on widgets
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1874
diff changeset
   573
    def _get_url(self, entity, field):
1966
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   574
        if self.autocomplete_initfunc is None:
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   575
            # XXX for bw compat
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   576
            fname = entity.autocomplete_initfuncs[field.name]
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   577
        else:
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   578
            fname = self.autocomplete_initfunc
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   579
        return entity._cw.build_url('json', fname=fname, mode='remote',
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   580
                                    pageid=entity._cw.pageid)
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   581
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   582
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   583
class StaticFileAutoCompletionWidget(AutoCompletionWidget):
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   584
    """XXX describe me"""
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   585
    wdgtype = 'StaticFileSuggestField'
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   586
1875
7bcb02377516 no rschema attribute on widgets
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1874
diff changeset
   587
    def _get_url(self, entity, field):
1966
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   588
        if self.autocomplete_initfunc is None:
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   589
            # XXX for bw compat
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   590
            fname = entity.autocomplete_initfuncs[field.name]
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   591
        else:
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   592
            fname = self.autocomplete_initfunc
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   593
        return entity._cw.datadir_url + fname
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   594
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   595
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   596
class RestrictedAutoCompletionWidget(AutoCompletionWidget):
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   597
    """XXX describe me"""
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   598
    wdgtype = 'RestrictedSuggestField'
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   599
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   600
1337
828bbf500bcc backport AddComboBoxWidget, ajax widgets refactoring
sylvain.thenault@logilab.fr
parents: 1336
diff changeset
   601
class AddComboBoxWidget(Select):
4163
b2747ed057e6 substitute _render_attrs by values_and_attributes method, keeping bw compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   602
    def values_and_attributes(self, form, field):
b2747ed057e6 substitute _render_attrs by values_and_attributes method, keeping bw compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   603
        values, attrs = super(AddComboBoxWidget, self).values_and_attributes(form, field)
1337
828bbf500bcc backport AddComboBoxWidget, ajax widgets refactoring
sylvain.thenault@logilab.fr
parents: 1336
diff changeset
   604
        init_ajax_attributes(self.attrs, 'AddComboBox')
828bbf500bcc backport AddComboBoxWidget, ajax widgets refactoring
sylvain.thenault@logilab.fr
parents: 1336
diff changeset
   605
        # XXX entity form specific
828bbf500bcc backport AddComboBoxWidget, ajax widgets refactoring
sylvain.thenault@logilab.fr
parents: 1336
diff changeset
   606
        entity = form.edited_entity
828bbf500bcc backport AddComboBoxWidget, ajax widgets refactoring
sylvain.thenault@logilab.fr
parents: 1336
diff changeset
   607
        attrs['cubicweb:etype_to'] = entity.e_schema
3689
deb13e88e037 follow yams 0.25 api changes to improve performance
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3106
diff changeset
   608
        etype_from = entity.e_schema.subjrels[field.name].objects(entity.e_schema)[0]
1337
828bbf500bcc backport AddComboBoxWidget, ajax widgets refactoring
sylvain.thenault@logilab.fr
parents: 1336
diff changeset
   609
        attrs['cubicweb:etype_from'] = etype_from
4163
b2747ed057e6 substitute _render_attrs by values_and_attributes method, keeping bw compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   610
        return values, attrs
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   611
2522
562f5dcf2345 widget.render now takes the renderer as third argument (keeping minimal bw compat)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2519
diff changeset
   612
    def render(self, form, field, renderer):
562f5dcf2345 widget.render now takes the renderer as third argument (keeping minimal bw compat)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2519
diff changeset
   613
        return super(AddComboBoxWidget, self).render(form, field, renderer) + u'''
1337
828bbf500bcc backport AddComboBoxWidget, ajax widgets refactoring
sylvain.thenault@logilab.fr
parents: 1336
diff changeset
   614
<div id="newvalue">
828bbf500bcc backport AddComboBoxWidget, ajax widgets refactoring
sylvain.thenault@logilab.fr
parents: 1336
diff changeset
   615
  <input type="text" id="newopt" />
2996
866a2c135c33 B #345282 xhtml requires to use &#160; instead of &nbsp;
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2549
diff changeset
   616
  <a href="javascript:noop()" id="add_newopt">&#160;</a></div>
1337
828bbf500bcc backport AddComboBoxWidget, ajax widgets refactoring
sylvain.thenault@logilab.fr
parents: 1336
diff changeset
   617
'''
1359
bef6891393d7 backport some tests
sylvain.thenault@logilab.fr
parents: 1344
diff changeset
   618
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   619
# buttons ######################################################################
1304
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   620
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   621
class Button(Input):
1389
ae58c2e7e1f7 clear label handling
sylvain.thenault@logilab.fr
parents: 1367
diff changeset
   622
    """<input type='button'>, base class for global form buttons
ae58c2e7e1f7 clear label handling
sylvain.thenault@logilab.fr
parents: 1367
diff changeset
   623
ae58c2e7e1f7 clear label handling
sylvain.thenault@logilab.fr
parents: 1367
diff changeset
   624
    note label is a msgid which will be translated at form generation time, you
ae58c2e7e1f7 clear label handling
sylvain.thenault@logilab.fr
parents: 1367
diff changeset
   625
    should not give an already translated string.
ae58c2e7e1f7 clear label handling
sylvain.thenault@logilab.fr
parents: 1367
diff changeset
   626
    """
1304
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   627
    type = 'button'
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   628
    def __init__(self, label=stdmsgs.BUTTON_OK, attrs=None,
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   629
                 setdomid=None, settabindex=None,
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   630
                 name='', value='', onclick=None, cwaction=None):
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   631
        super(Button, self).__init__(attrs, setdomid, settabindex)
3803
414bb8439002 [web ui] decorate form buttons with icons (at last)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 3689
diff changeset
   632
        if isinstance(label, tuple):
414bb8439002 [web ui] decorate form buttons with icons (at last)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 3689
diff changeset
   633
            self.label = label[0]
414bb8439002 [web ui] decorate form buttons with icons (at last)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 3689
diff changeset
   634
            self.icon = label[1]
414bb8439002 [web ui] decorate form buttons with icons (at last)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 3689
diff changeset
   635
        else:
414bb8439002 [web ui] decorate form buttons with icons (at last)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 3689
diff changeset
   636
            self.label = label
414bb8439002 [web ui] decorate form buttons with icons (at last)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 3689
diff changeset
   637
            self.icon = None
1304
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   638
        self.name = name
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   639
        self.value = ''
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   640
        self.onclick = onclick
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   641
        self.cwaction = cwaction
4597
e872097f2287 use class, not klass, in widget.attrs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4593
diff changeset
   642
        self.attrs.setdefault('class', 'validateButton')
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   643
2522
562f5dcf2345 widget.render now takes the renderer as third argument (keeping minimal bw compat)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2519
diff changeset
   644
    def render(self, form, field=None, renderer=None):
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   645
        label = form._cw._(self.label)
1304
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   646
        attrs = self.attrs.copy()
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   647
        if self.cwaction:
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   648
            assert self.onclick is None
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   649
            attrs['onclick'] = "postForm('__action_%s', \'%s\', \'%s\')" % (
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   650
                self.cwaction, self.label, form.domid)
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   651
        elif self.onclick:
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   652
            attrs['onclick'] = self.onclick
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   653
        if self.name:
4250
39adce674a09 fix NameError
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 4212
diff changeset
   654
            attrs['name'] = self.name
1304
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   655
            if self.setdomid:
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   656
                attrs['id'] = self.name
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   657
        if self.settabindex and not 'tabindex' in attrs:
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   658
            attrs['tabindex'] = form._cw.next_tabindex()
3803
414bb8439002 [web ui] decorate form buttons with icons (at last)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 3689
diff changeset
   659
        if self.icon:
3890
d7a270f50f54 backport stable branch (one more time painfully)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3720 3803
diff changeset
   660
            img = tags.img(src=form._cw.external_resource(self.icon), alt=self.icon)
3803
414bb8439002 [web ui] decorate form buttons with icons (at last)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 3689
diff changeset
   661
        else:
414bb8439002 [web ui] decorate form buttons with icons (at last)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 3689
diff changeset
   662
            img = u''
414bb8439002 [web ui] decorate form buttons with icons (at last)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 3689
diff changeset
   663
        return tags.button(img + xml_escape(label), escapecontent=False,
414bb8439002 [web ui] decorate form buttons with icons (at last)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 3689
diff changeset
   664
                           value=label, type=self.type, **attrs)
1304
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   665
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   666
1304
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   667
class SubmitButton(Button):
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   668
    """<input type='submit'>, main button to submit a form"""
1304
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   669
    type = 'submit'
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   670
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   671
1304
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   672
class ResetButton(Button):
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   673
    """<input type='reset'>, main button to reset a form.
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   674
    You usually don't want this.
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   675
    """
1304
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   676
    type = 'reset'
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   677
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   678
1304
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   679
class ImgButton(object):
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   680
    """<img> wrapped into a <a> tag with href triggering something (usually a
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   681
    javascript call)
1389
ae58c2e7e1f7 clear label handling
sylvain.thenault@logilab.fr
parents: 1367
diff changeset
   682
ae58c2e7e1f7 clear label handling
sylvain.thenault@logilab.fr
parents: 1367
diff changeset
   683
    note label is a msgid which will be translated at form generation time, you
ae58c2e7e1f7 clear label handling
sylvain.thenault@logilab.fr
parents: 1367
diff changeset
   684
    should not give an already translated string.
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   685
    """
1304
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   686
    def __init__(self, domid, href, label, imgressource):
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   687
        self.domid = domid
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   688
        self.href = href
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   689
        self.imgressource = imgressource
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   690
        self.label = label
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   691
2522
562f5dcf2345 widget.render now takes the renderer as third argument (keeping minimal bw compat)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2519
diff changeset
   692
    def render(self, form, field=None, renderer=None):
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   693
        label = form._cw._(self.label)
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   694
        imgsrc = form._cw.external_resource(self.imgressource)
1389
ae58c2e7e1f7 clear label handling
sylvain.thenault@logilab.fr
parents: 1367
diff changeset
   695
        return '<a id="%(domid)s" href="%(href)s">'\
ae58c2e7e1f7 clear label handling
sylvain.thenault@logilab.fr
parents: 1367
diff changeset
   696
               '<img src="%(imgsrc)s" alt="%(label)s"/>%(label)s</a>' % {
ae58c2e7e1f7 clear label handling
sylvain.thenault@logilab.fr
parents: 1367
diff changeset
   697
            'label': label, 'imgsrc': imgsrc,
ae58c2e7e1f7 clear label handling
sylvain.thenault@logilab.fr
parents: 1367
diff changeset
   698
            'domid': self.domid, 'href': self.href}
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   699
1304
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   700
4304
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   701
# more widgets #################################################################
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   702
4375
6d34e3cf60a3 cleanup base class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4373
diff changeset
   703
class EditableURLWidget(FieldWidget):
4305
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   704
    """custom widget to edit separatly an url path / query string (used by
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   705
    default for Bookmark.path for instance), dealing with url quoting nicely
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   706
    (eg user edit the unquoted value).
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   707
    """
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   708
4372
0c44af150a49 introduce a default render implementation on the base widget, which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4371
diff changeset
   709
    def _render(self, form, field, renderer):
4305
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   710
        """render the widget for the given `field` of `form`.
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   711
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   712
        Generate one <input> tag for each field's value
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   713
        """
4372
0c44af150a49 introduce a default render implementation on the base widget, which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4371
diff changeset
   714
        assert self.suffix is None, 'not supported'
4305
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   715
        req = form._cw
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   716
        pathqname = field.input_name(form, 'path')
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   717
        fqsqname = field.input_name(form, 'fqs') # formatted query string
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   718
        if pathqname in form.form_previous_values:
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   719
            path = form.form_previous_values[pathqname]
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   720
            fqs = form.form_previous_values[fqsqname]
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   721
        else:
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   722
            if field.name in req.form:
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   723
                value = req.form[field.name]
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   724
            else:
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   725
                value = self.typed_value(form, field)
4550
d74098d1b69f fix bug when value is None
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4508
diff changeset
   726
            if value:
d74098d1b69f fix bug when value is None
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4508
diff changeset
   727
                try:
d74098d1b69f fix bug when value is None
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4508
diff changeset
   728
                    path, qs = value.split('?', 1)
d74098d1b69f fix bug when value is None
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4508
diff changeset
   729
                except ValueError:
d74098d1b69f fix bug when value is None
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4508
diff changeset
   730
                    path = value
d74098d1b69f fix bug when value is None
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4508
diff changeset
   731
                    qs = ''
d74098d1b69f fix bug when value is None
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4508
diff changeset
   732
            else:
d74098d1b69f fix bug when value is None
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4508
diff changeset
   733
                path = qs = ''
4305
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   734
            fqs = u'\n'.join(u'%s=%s' % (k, v) for k, v in req.url_parse_qsl(qs))
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   735
        attrs = dict(self.attrs)
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   736
        if self.setdomid:
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   737
            attrs['id'] = field.dom_id(form)
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   738
        if self.settabindex and not 'tabindex' in attrs:
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   739
            attrs['tabindex'] = req.next_tabindex()
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   740
        # ensure something is rendered
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   741
        inputs = [u'<table><tr><th>',
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   742
                  req._('i18n_bookmark_url_path'),
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   743
                  u'</th><td>',
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   744
                  tags.input(name=pathqname, type='string', value=path, **attrs),
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   745
                  u'</td></tr><tr><th>',
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   746
                  req._('i18n_bookmark_url_fqs'),
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   747
                  u'</th><td>']
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   748
        if self.setdomid:
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   749
            attrs['id'] = field.dom_id(form, 'fqs')
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   750
        if self.settabindex:
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   751
            attrs['tabindex'] = req.next_tabindex()
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   752
        attrs.setdefault('onkeyup', 'autogrow(this)')
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   753
        inputs += [tags.textarea(fqs, name=fqsqname, **attrs),
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   754
                   u'</td></tr></table>']
4376
839b28a3652e surrounding div necessary for proper error localization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4375
diff changeset
   755
        # surrounding div necessary for proper error localization
4508
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   756
        return u'<div id="%s">%s</div>' % (
4376
839b28a3652e surrounding div necessary for proper error localization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4375
diff changeset
   757
            field.dom_id(form), u'\n'.join(inputs))
4305
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   758
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   759
    def process_field_data(self, form, field):
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   760
        req = form._cw
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   761
        values = {}
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   762
        path = req.form.get(field.input_name(form, 'path'))
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   763
        if isinstance(path, basestring):
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   764
            path = path.strip() or None
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   765
        fqs = req.form.get(field.input_name(form, 'fqs'))
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   766
        if isinstance(fqs, basestring):
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   767
            fqs = fqs.strip() or None
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   768
            if fqs:
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   769
                for i, line in enumerate(fqs.split('\n')):
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   770
                    line = line.strip()
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   771
                    if line:
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   772
                        try:
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   773
                            key, val = line.split('=', 1)
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   774
                        except ValueError:
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   775
                            raise ProcessFormError(req._("wrong query parameter line %s") % (i+1))
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   776
                        # value will be url quoted by build_url_params
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   777
                        values.setdefault(key.encode(req.encoding), []).append(val)
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   778
        if not values:
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   779
            return path
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   780
        return u'%s?%s' % (path, req.build_url_params(**values))