web/formwidgets.py
author Sylvain Thénault <sylvain.thenault@logilab.fr>
Tue, 23 Feb 2010 12:51:20 +0100
branchstable
changeset 4661 87672c718c3c
parent 4660 21ed77792c33
child 4846 a2fb82770fa6
permissions -rw-r--r--
[form] cache field value in form.formvalues using (field, form) key since in some case the same field instance may be shared accross multiple forms, which may share the formvalues dict in case of sub-forms
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 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
    63
        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
    64
4163
b2747ed057e6 substitute _render_attrs by values_and_attributes method, keeping bw compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
    65
    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
    66
        """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
    67
        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
    68
        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
    69
        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
    70
        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
    71
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
        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
    73
        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
    74
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
        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
    76
        """
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
    77
        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
    78
        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
    79
            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
    80
        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
    81
            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
    82
        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
    83
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
    84
    def values(self, form, field):
4658
25de2eb0432b [form] add a new ignore_req_params attribute on field controlling value's retreival
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4627
diff changeset
    85
        values = None
25de2eb0432b [form] add a new ignore_req_params attribute on field controlling value's retreival
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4627
diff changeset
    86
        if not field.ignore_req_params:
25de2eb0432b [form] add a new ignore_req_params attribute on field controlling value's retreival
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4627
diff changeset
    87
            qname = field.input_name(form, self.suffix)
25de2eb0432b [form] add a new ignore_req_params attribute on field controlling value's retreival
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4627
diff changeset
    88
            # value from a previous post that has raised a validation error
25de2eb0432b [form] add a new ignore_req_params attribute on field controlling value's retreival
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4627
diff changeset
    89
            if qname in form.form_previous_values:
25de2eb0432b [form] add a new ignore_req_params attribute on field controlling value's retreival
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4627
diff changeset
    90
                values = form.form_previous_values[qname]
25de2eb0432b [form] add a new ignore_req_params attribute on field controlling value's retreival
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4627
diff changeset
    91
            # value specified using form parameters
25de2eb0432b [form] add a new ignore_req_params attribute on field controlling value's retreival
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4627
diff changeset
    92
            elif qname in form._cw.form:
25de2eb0432b [form] add a new ignore_req_params attribute on field controlling value's retreival
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4627
diff changeset
    93
                values = form._cw.form[qname]
25de2eb0432b [form] add a new ignore_req_params attribute on field controlling value's retreival
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4627
diff changeset
    94
            elif field.name != qname and field.name in form._cw.form:
25de2eb0432b [form] add a new ignore_req_params attribute on field controlling value's retreival
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4627
diff changeset
    95
                # XXX compat: accept attr=value in req.form to specify value of
25de2eb0432b [form] add a new ignore_req_params attribute on field controlling value's retreival
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4627
diff changeset
    96
                # attr-subject
25de2eb0432b [form] add a new ignore_req_params attribute on field controlling value's retreival
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4627
diff changeset
    97
                values = form._cw.form[field.name]
25de2eb0432b [form] add a new ignore_req_params attribute on field controlling value's retreival
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4627
diff changeset
    98
        if values is None:
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
    99
            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
   100
            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
   101
                values = self.format_value(form, field, values)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   102
        if not isinstance(values, (tuple, list)):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   103
            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
   104
        return values
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   105
4660
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   106
    def typed_value(self, form, field):
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   107
        """return field's *typed* value specified in:
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   108
        3. extra form values given to render()
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   109
        4. field's typed value
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   110
        """
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   111
        qname = field.input_name(form)
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   112
        for key in ((field, form), qname):
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   113
            try:
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   114
                return form.formvalues[key]
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   115
            except KeyError:
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   116
                continue
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   117
        if field.name != qname and field.name in form.formvalues:
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   118
            return form.formvalues[field.name]
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   119
        return field.typed_value(form)
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   120
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
   121
    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
   122
        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
   123
        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
   124
        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
   125
            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
   126
        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
   127
b2747ed057e6 substitute _render_attrs by values_and_attributes method, keeping bw compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   128
    @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
   129
    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
   130
        """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
   131
        """
b2747ed057e6 substitute _render_attrs by values_and_attributes method, keeping bw compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   132
        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
   133
        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
   134
1096
e1fe98850bf7 cleanup
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   135
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   136
class Input(FieldWidget):
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   137
    """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
   138
    type = None
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   139
4372
0c44af150a49 introduce a default render implementation on the base widget, which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4371
diff changeset
   140
    def _render(self, form, field, renderer):
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   141
        """render the widget for the given `field` of `form`.
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   142
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   143
        Generate one <input> tag for each field's value
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   144
        """
4163
b2747ed057e6 substitute _render_attrs by values_and_attributes method, keeping bw compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   145
        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
   146
        # 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
   147
        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
   148
            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
   149
        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
   150
                             type=self.type, value=value, **attrs)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   151
                  for value in values]
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   152
        return u'\n'.join(inputs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   153
1096
e1fe98850bf7 cleanup
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   154
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   155
# basic html widgets ###########################################################
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   156
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   157
class TextInput(Input):
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   158
    """<input type='text'>"""
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   159
    type = 'text'
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   160
1096
e1fe98850bf7 cleanup
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   161
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   162
class PasswordInput(Input):
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   163
    """<input type='password'> and its confirmation field (using
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   164
    <field's name>-confirm as name)
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   165
    """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   166
    type = 'password'
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   167
4372
0c44af150a49 introduce a default render implementation on the base widget, which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4371
diff changeset
   168
    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
   169
        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
   170
        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
   171
        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
   172
        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
   173
        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
   174
                             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
   175
                  '<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
   176
                  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
   177
                             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
   178
                  '&#160;', tags.span(form._cw._('confirm password'),
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   179
                                      **{'class': 'emphasis'})]
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   180
        return u'\n'.join(inputs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   181
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
   182
    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
   183
        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
   184
        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
   185
        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
   186
            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
   187
                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
   188
            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
   189
        raise ProcessFormError(form._cw._("password and confirmation don't match"))
1096
e1fe98850bf7 cleanup
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   190
e1fe98850bf7 cleanup
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   191
1934
be86bb31c4c2 add single input password widget
Florent <florent@secondweb.fr>
parents: 1875
diff changeset
   192
class PasswordSingleInput(Input):
be86bb31c4c2 add single input password widget
Florent <florent@secondweb.fr>
parents: 1875
diff changeset
   193
    """<input type='password'> without a confirmation field"""
be86bb31c4c2 add single input password widget
Florent <florent@secondweb.fr>
parents: 1875
diff changeset
   194
    type = 'password'
be86bb31c4c2 add single input password widget
Florent <florent@secondweb.fr>
parents: 1875
diff changeset
   195
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
   196
    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
   197
        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
   198
        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
   199
            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
   200
        return value
1934
be86bb31c4c2 add single input password widget
Florent <florent@secondweb.fr>
parents: 1875
diff changeset
   201
be86bb31c4c2 add single input password widget
Florent <florent@secondweb.fr>
parents: 1875
diff changeset
   202
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   203
class FileInput(Input):
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   204
    """<input type='file'>"""
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   205
    type = 'file'
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   206
4163
b2747ed057e6 substitute _render_attrs by values_and_attributes method, keeping bw compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   207
    def values_and_attributes(self, form, field):
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   208
        # 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
   209
        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
   210
        return ('',), attrs
1096
e1fe98850bf7 cleanup
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   211
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   212
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   213
class HiddenInput(Input):
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   214
    """<input type='hidden'>"""
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   215
    type = 'hidden'
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   216
    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
   217
    settabindex = False
1096
e1fe98850bf7 cleanup
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   218
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   219
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   220
class ButtonInput(Input):
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   221
    """<input type='button'>
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   222
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   223
    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
   224
    ResetButton and ImgButton classes below.
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   225
    """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   226
    type = 'button'
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   227
1096
e1fe98850bf7 cleanup
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   228
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   229
class TextArea(FieldWidget):
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   230
    """<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
   231
4372
0c44af150a49 introduce a default render implementation on the base widget, which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4371
diff changeset
   232
    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
   233
        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
   234
        attrs.setdefault('onkeyup', 'autogrow(this)')
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   235
        if not values:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   236
            value = u''
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   237
        elif len(values) == 1:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   238
            value = values[0]
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   239
        else:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   240
            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
   241
        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
   242
        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
   243
        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
   244
            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
   245
        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
   246
        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
   247
        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
   248
                             **attrs)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   249
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   250
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   251
class FCKEditor(TextArea):
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   252
    """FCKEditor enabled <textarea>"""
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   253
    def __init__(self, *args, **kwargs):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   254
        super(FCKEditor, self).__init__(*args, **kwargs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   255
        self.attrs['cubicweb:type'] = 'wysiwyg'
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   256
4372
0c44af150a49 introduce a default render implementation on the base widget, which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4371
diff changeset
   257
    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
   258
        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
   259
        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
   260
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   261
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   262
class Select(FieldWidget):
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   263
    """<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
   264
    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
   265
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
   266
    def __init__(self, attrs=None, multiple=False):
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   267
        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
   268
        self._multiple = multiple
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   269
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
   270
    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
   271
        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
   272
        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
   273
            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
   274
        options = []
1771
bb9538d91465 fix <optgroup> tag cannot be empty according to DTD
Florent <florent@secondweb.fr>
parents: 1768
diff changeset
   275
        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
   276
        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
   277
            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
   278
                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
   279
            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
   280
                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
   281
                oattrs = {}
1336
2e552353c42a insert an optgroup as separator on None values
sylvain.thenault@logilab.fr
parents: 1330
diff changeset
   282
            if value is None:
2e552353c42a insert an optgroup as separator on None values
sylvain.thenault@logilab.fr
parents: 1330
diff changeset
   283
                # handle separator
1771
bb9538d91465 fix <optgroup> tag cannot be empty according to DTD
Florent <florent@secondweb.fr>
parents: 1768
diff changeset
   284
                if optgroup_opened:
bb9538d91465 fix <optgroup> tag cannot be empty according to DTD
Florent <florent@secondweb.fr>
parents: 1768
diff changeset
   285
                    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
   286
                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
   287
                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
   288
                optgroup_opened = True
1336
2e552353c42a insert an optgroup as separator on None values
sylvain.thenault@logilab.fr
parents: 1330
diff changeset
   289
            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
   290
                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
   291
                                           selected='selected', **oattrs))
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   292
            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
   293
                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
   294
        if optgroup_opened:
bb9538d91465 fix <optgroup> tag cannot be empty according to DTD
Florent <florent@secondweb.fr>
parents: 1768
diff changeset
   295
            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
   296
        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
   297
                           multiple=self._multiple, options=options, **attrs)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   298
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   299
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   300
class CheckBox(Input):
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   301
    """<input type='checkbox'>, for field having a specific vocabulary. One
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   302
    input will be generated for each possible value.
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   303
    """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   304
    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
   305
    vocabulary_widget = True
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   306
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
   307
    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
   308
        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
   309
        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
   310
        sep = attrs.pop('separator', u'<br/>\n')
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   311
        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
   312
        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
   313
            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
   314
                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
   315
            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
   316
                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
   317
                oattrs = {}
1367
01bb5b727fe3 set dom id on the first input of radio choices
sylvain.thenault@logilab.fr
parents: 1359
diff changeset
   318
            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
   319
            iattrs.update(oattrs)
1367
01bb5b727fe3 set dom id on the first input of radio choices
sylvain.thenault@logilab.fr
parents: 1359
diff changeset
   320
            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
   321
                iattrs.setdefault('id', domid)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   322
            if value in curvalues:
1367
01bb5b727fe3 set dom id on the first input of radio choices
sylvain.thenault@logilab.fr
parents: 1359
diff changeset
   323
                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
   324
            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
   325
                             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
   326
            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
   327
        return sep.join(options)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   328
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   329
1832
3384264d25cc fix CheckBox multiple dom id and refactor with Radio
Florent <florent@secondweb.fr>
parents: 1771
diff changeset
   330
class Radio(CheckBox):
3384264d25cc fix CheckBox multiple dom id and refactor with Radio
Florent <florent@secondweb.fr>
parents: 1771
diff changeset
   331
    """<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
   332
    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
   333
    """
3384264d25cc fix CheckBox multiple dom id and refactor with Radio
Florent <florent@secondweb.fr>
parents: 1771
diff changeset
   334
    type = 'radio'
3384264d25cc fix CheckBox multiple dom id and refactor with Radio
Florent <florent@secondweb.fr>
parents: 1771
diff changeset
   335
2225
16826403affa cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2131
diff changeset
   336
2523
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   337
# compound widgets #############################################################
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
class IntervalWidget(FieldWidget):
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   340
    """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
   341
    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
   342
    fields.
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   343
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   344
    Exemple usage::
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   345
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   346
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
   347
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
   348
                              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
   349
                                                    IntField(name='maxprice')),
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   350
                                            label=_('price'),
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   351
                                            widget=IntervalWidget()
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   352
                                            ))
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   353
# 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
   354
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
   355
    """
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   356
    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
   357
        actual_fields = field.fields
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   358
        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
   359
        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
   360
            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
   361
            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
   362
            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
   363
            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
   364
            )
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
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   367
class HorizontalLayoutWidget(FieldWidget):
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   368
    """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
   369
    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
   370
    """
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   371
    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
   372
        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
   373
            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
   374
            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
   375
                              '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
   376
                      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
   377
        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
   378
            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
   379
        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
   380
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   381
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   382
# javascript widgets ###########################################################
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   383
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   384
class DateTimePicker(TextInput):
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   385
    """<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
   386
    fields
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   387
    """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   388
    monthnames = ('january', 'february', 'march', 'april',
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   389
                  'may', 'june', 'july', 'august',
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   390
                  'september', 'october', 'november', 'december')
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   391
    daynames = ('monday', 'tuesday', 'wednesday', 'thursday',
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   392
                'friday', 'saturday', 'sunday')
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   393
1311
4cc6e2723dc7 move ajax.js to base form class
sylvain.thenault@logilab.fr
parents: 1304
diff changeset
   394
    needs_js = ('cubicweb.calendar.js',)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   395
    needs_css = ('cubicweb.calendar_popup.css',)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   396
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   397
    @classmethod
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   398
    def add_localized_infos(cls, req):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   399
        """inserts JS variables defining localized months and days"""
4023
eae23c40627a drop common subpackage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3998
diff changeset
   400
        # 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
   401
        _ = req._
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   402
        monthnames = [_(mname) for mname in cls.monthnames]
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   403
        daynames = [_(dname) for dname in cls.daynames]
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   404
        req.html_headers.define_var('MONTHNAMES', monthnames)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   405
        req.html_headers.define_var('DAYNAMES', daynames)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   406
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
   407
    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
   408
        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
   409
        self.add_localized_infos(form._cw)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   410
        cal_button = self._render_calendar_popup(form, field)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   411
        return txtwidget + cal_button
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   412
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   413
    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
   414
        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
   415
        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
   416
            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
   417
        inputid = field.dom_id(form)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   418
        helperid = '%shelper' % inputid
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   419
        year, month = value.year, value.month
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   420
        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
   421
<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
   422
                % (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
   423
                   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
   424
                   form._cw._('calendar'), helperid) )
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   425
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   426
4373
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   427
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
   428
    """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
   429
    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
   430
    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
   431
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   432
    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
   433
        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
   434
        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
   435
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   436
    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
   437
        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
   438
        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
   439
        # 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
   440
        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
   441
        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
   442
        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
   443
                       '{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
   444
                       ' 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
   445
                           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
   446
        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
   447
            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
   448
        else:
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   449
            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
   450
        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
   451
                          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
   452
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
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
   455
    """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
   456
    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
   457
    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
   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 __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
   460
        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
   461
        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
   462
        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
   463
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   464
    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
   465
        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
   466
        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
   467
        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
   468
            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
   469
        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
   470
            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
   471
        else:
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   472
            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
   473
        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
   474
                          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
   475
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   476
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   477
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
   478
    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
   479
        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
   480
        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
   481
        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
   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
    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
   484
        """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
   485
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   486
        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
   487
        """
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   488
        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
   489
        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
   490
        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
   491
        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
   492
            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
   493
            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
   494
        else:
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   495
            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
   496
            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
   497
                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
   498
            else:
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   499
                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
   500
            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
   501
                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
   502
                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
   503
            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
   504
                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
   505
        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
   506
        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
   507
                                      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
   508
        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
   509
                                            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
   510
                                            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
   511
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   512
    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
   513
        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
   514
        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
   515
        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
   516
        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
   517
            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
   518
        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
   519
        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
   520
            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
   521
        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
   522
        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
   523
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   524
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   525
# ajax widgets ################################################################
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   526
1337
828bbf500bcc backport AddComboBoxWidget, ajax widgets refactoring
sylvain.thenault@logilab.fr
parents: 1336
diff changeset
   527
def init_ajax_attributes(attrs, wdgtype, loadtype=u'auto'):
828bbf500bcc backport AddComboBoxWidget, ajax widgets refactoring
sylvain.thenault@logilab.fr
parents: 1336
diff changeset
   528
    try:
4597
e872097f2287 use class, not klass, in widget.attrs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4593
diff changeset
   529
        attrs['class'] += u' widget'
1337
828bbf500bcc backport AddComboBoxWidget, ajax widgets refactoring
sylvain.thenault@logilab.fr
parents: 1336
diff changeset
   530
    except KeyError:
4597
e872097f2287 use class, not klass, in widget.attrs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4593
diff changeset
   531
        attrs['class'] = u'widget'
1344
930020cb134b shouldn't use unicode keys in attrs
sylvain.thenault@logilab.fr
parents: 1337
diff changeset
   532
    attrs.setdefault('cubicweb:wdgtype', wdgtype)
930020cb134b shouldn't use unicode keys in attrs
sylvain.thenault@logilab.fr
parents: 1337
diff changeset
   533
    attrs.setdefault('cubicweb:loadtype', loadtype)
1337
828bbf500bcc backport AddComboBoxWidget, ajax widgets refactoring
sylvain.thenault@logilab.fr
parents: 1336
diff changeset
   534
828bbf500bcc backport AddComboBoxWidget, ajax widgets refactoring
sylvain.thenault@logilab.fr
parents: 1336
diff changeset
   535
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   536
class AjaxWidget(FieldWidget):
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   537
    """simple <div> based ajax widget"""
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   538
    def __init__(self, wdgtype, inputid=None, **kwargs):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   539
        super(AjaxWidget, self).__init__(**kwargs)
1337
828bbf500bcc backport AddComboBoxWidget, ajax widgets refactoring
sylvain.thenault@logilab.fr
parents: 1336
diff changeset
   540
        init_ajax_attributes(self.attrs, wdgtype)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   541
        if inputid is not None:
1344
930020cb134b shouldn't use unicode keys in attrs
sylvain.thenault@logilab.fr
parents: 1337
diff changeset
   542
            self.attrs['cubicweb:inputid'] = inputid
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   543
4372
0c44af150a49 introduce a default render implementation on the base widget, which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4371
diff changeset
   544
    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
   545
        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
   546
        return tags.div(**attrs)
1304
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   547
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   548
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   549
class AutoCompletionWidget(TextInput):
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   550
    """ajax widget for StringField, proposing matching existing values as you
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   551
    type.
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   552
    """
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   553
    needs_js = ('cubicweb.widgets.js', 'jquery.autocomplete.js')
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   554
    needs_css = ('jquery.autocomplete.css',)
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   555
    wdgtype = 'SuggestField'
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   556
    loadtype = 'auto'
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   557
1966
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   558
    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
   559
        try:
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   560
            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
   561
        except KeyError:
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   562
            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
   563
                 '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
   564
                 '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
   565
                 DeprecationWarning)
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   566
            self.autocomplete_initfunc = None
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   567
        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
   568
4163
b2747ed057e6 substitute _render_attrs by values_and_attributes method, keeping bw compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   569
    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
   570
        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
   571
        init_ajax_attributes(attrs, self.wdgtype, self.loadtype)
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   572
        # XXX entity form specific
1875
7bcb02377516 no rschema attribute on widgets
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1874
diff changeset
   573
        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
   574
        if not values:
8cf7c767b134 quick & dirty fix for auto completion widget
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3803
diff changeset
   575
            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
   576
        return values, attrs
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   577
1875
7bcb02377516 no rschema attribute on widgets
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1874
diff changeset
   578
    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
   579
        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
   580
            # XXX for bw compat
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   581
            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
   582
        else:
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   583
            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
   584
        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
   585
                                    pageid=entity._cw.pageid)
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   586
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   587
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   588
class StaticFileAutoCompletionWidget(AutoCompletionWidget):
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   589
    """XXX describe me"""
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   590
    wdgtype = 'StaticFileSuggestField'
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   591
1875
7bcb02377516 no rschema attribute on widgets
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1874
diff changeset
   592
    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
   593
        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
   594
            # XXX for bw compat
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   595
            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
   596
        else:
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   597
            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
   598
        return entity._cw.datadir_url + fname
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
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   601
class RestrictedAutoCompletionWidget(AutoCompletionWidget):
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   602
    """XXX describe me"""
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   603
    wdgtype = 'RestrictedSuggestField'
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   604
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   605
1337
828bbf500bcc backport AddComboBoxWidget, ajax widgets refactoring
sylvain.thenault@logilab.fr
parents: 1336
diff changeset
   606
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
   607
    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
   608
        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
   609
        init_ajax_attributes(self.attrs, 'AddComboBox')
828bbf500bcc backport AddComboBoxWidget, ajax widgets refactoring
sylvain.thenault@logilab.fr
parents: 1336
diff changeset
   610
        # XXX entity form specific
828bbf500bcc backport AddComboBoxWidget, ajax widgets refactoring
sylvain.thenault@logilab.fr
parents: 1336
diff changeset
   611
        entity = form.edited_entity
828bbf500bcc backport AddComboBoxWidget, ajax widgets refactoring
sylvain.thenault@logilab.fr
parents: 1336
diff changeset
   612
        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
   613
        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
   614
        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
   615
        return values, attrs
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   616
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
   617
    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
   618
        return super(AddComboBoxWidget, self).render(form, field, renderer) + u'''
1337
828bbf500bcc backport AddComboBoxWidget, ajax widgets refactoring
sylvain.thenault@logilab.fr
parents: 1336
diff changeset
   619
<div id="newvalue">
828bbf500bcc backport AddComboBoxWidget, ajax widgets refactoring
sylvain.thenault@logilab.fr
parents: 1336
diff changeset
   620
  <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
   621
  <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
   622
'''
1359
bef6891393d7 backport some tests
sylvain.thenault@logilab.fr
parents: 1344
diff changeset
   623
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   624
# buttons ######################################################################
1304
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   625
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   626
class Button(Input):
1389
ae58c2e7e1f7 clear label handling
sylvain.thenault@logilab.fr
parents: 1367
diff changeset
   627
    """<input type='button'>, base class for global form buttons
ae58c2e7e1f7 clear label handling
sylvain.thenault@logilab.fr
parents: 1367
diff changeset
   628
ae58c2e7e1f7 clear label handling
sylvain.thenault@logilab.fr
parents: 1367
diff changeset
   629
    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
   630
    should not give an already translated string.
ae58c2e7e1f7 clear label handling
sylvain.thenault@logilab.fr
parents: 1367
diff changeset
   631
    """
1304
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   632
    type = 'button'
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   633
    def __init__(self, label=stdmsgs.BUTTON_OK, attrs=None,
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   634
                 setdomid=None, settabindex=None,
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   635
                 name='', value='', onclick=None, cwaction=None):
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   636
        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
   637
        if isinstance(label, tuple):
414bb8439002 [web ui] decorate form buttons with icons (at last)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 3689
diff changeset
   638
            self.label = label[0]
414bb8439002 [web ui] decorate form buttons with icons (at last)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 3689
diff changeset
   639
            self.icon = label[1]
414bb8439002 [web ui] decorate form buttons with icons (at last)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 3689
diff changeset
   640
        else:
414bb8439002 [web ui] decorate form buttons with icons (at last)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 3689
diff changeset
   641
            self.label = label
414bb8439002 [web ui] decorate form buttons with icons (at last)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 3689
diff changeset
   642
            self.icon = None
1304
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   643
        self.name = name
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   644
        self.value = ''
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   645
        self.onclick = onclick
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   646
        self.cwaction = cwaction
4597
e872097f2287 use class, not klass, in widget.attrs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4593
diff changeset
   647
        self.attrs.setdefault('class', 'validateButton')
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   648
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
   649
    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
   650
        label = form._cw._(self.label)
1304
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   651
        attrs = self.attrs.copy()
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   652
        if self.cwaction:
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   653
            assert self.onclick is None
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   654
            attrs['onclick'] = "postForm('__action_%s', \'%s\', \'%s\')" % (
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   655
                self.cwaction, self.label, form.domid)
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   656
        elif self.onclick:
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   657
            attrs['onclick'] = self.onclick
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   658
        if self.name:
4250
39adce674a09 fix NameError
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 4212
diff changeset
   659
            attrs['name'] = self.name
1304
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   660
            if self.setdomid:
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   661
                attrs['id'] = self.name
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   662
        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
   663
            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
   664
        if self.icon:
3890
d7a270f50f54 backport stable branch (one more time painfully)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3720 3803
diff changeset
   665
            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
   666
        else:
414bb8439002 [web ui] decorate form buttons with icons (at last)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 3689
diff changeset
   667
            img = u''
414bb8439002 [web ui] decorate form buttons with icons (at last)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 3689
diff changeset
   668
        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
   669
                           value=label, type=self.type, **attrs)
1304
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
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 SubmitButton(Button):
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   673
    """<input type='submit'>, main button to submit a form"""
1304
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   674
    type = 'submit'
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   675
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   676
1304
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   677
class ResetButton(Button):
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   678
    """<input type='reset'>, main button to reset a form.
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   679
    You usually don't want this.
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   680
    """
1304
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   681
    type = 'reset'
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   682
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   683
1304
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   684
class ImgButton(object):
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   685
    """<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
   686
    javascript call)
1389
ae58c2e7e1f7 clear label handling
sylvain.thenault@logilab.fr
parents: 1367
diff changeset
   687
ae58c2e7e1f7 clear label handling
sylvain.thenault@logilab.fr
parents: 1367
diff changeset
   688
    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
   689
    should not give an already translated string.
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   690
    """
1304
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   691
    def __init__(self, domid, href, label, imgressource):
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   692
        self.domid = domid
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   693
        self.href = href
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   694
        self.imgressource = imgressource
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   695
        self.label = label
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   696
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
   697
    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
   698
        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
   699
        imgsrc = form._cw.external_resource(self.imgressource)
1389
ae58c2e7e1f7 clear label handling
sylvain.thenault@logilab.fr
parents: 1367
diff changeset
   700
        return '<a id="%(domid)s" href="%(href)s">'\
ae58c2e7e1f7 clear label handling
sylvain.thenault@logilab.fr
parents: 1367
diff changeset
   701
               '<img src="%(imgsrc)s" alt="%(label)s"/>%(label)s</a>' % {
ae58c2e7e1f7 clear label handling
sylvain.thenault@logilab.fr
parents: 1367
diff changeset
   702
            'label': label, 'imgsrc': imgsrc,
ae58c2e7e1f7 clear label handling
sylvain.thenault@logilab.fr
parents: 1367
diff changeset
   703
            'domid': self.domid, 'href': self.href}
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   704
1304
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   705
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
   706
# more widgets #################################################################
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   707
4375
6d34e3cf60a3 cleanup base class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4373
diff changeset
   708
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
   709
    """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
   710
    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
   711
    (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
   712
    """
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
    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
   715
        """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
   716
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
        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
   718
        """
4372
0c44af150a49 introduce a default render implementation on the base widget, which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4371
diff changeset
   719
        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
   720
        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
   721
        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
   722
        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
   723
        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
   724
            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
   725
            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
   726
        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
   727
            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
   728
                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
   729
            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
   730
                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
   731
            if value:
d74098d1b69f fix bug when value is None
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4508
diff changeset
   732
                try:
d74098d1b69f fix bug when value is None
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4508
diff changeset
   733
                    path, qs = value.split('?', 1)
d74098d1b69f fix bug when value is None
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4508
diff changeset
   734
                except ValueError:
d74098d1b69f fix bug when value is None
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4508
diff changeset
   735
                    path = value
d74098d1b69f fix bug when value is None
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4508
diff changeset
   736
                    qs = ''
d74098d1b69f fix bug when value is None
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4508
diff changeset
   737
            else:
d74098d1b69f fix bug when value is None
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4508
diff changeset
   738
                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
   739
            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
   740
        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
   741
        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
   742
            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
   743
        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
   744
            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
   745
        # 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
   746
        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
   747
                  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
   748
                  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
   749
                  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
   750
                  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
   751
                  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
   752
                  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
   753
        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
   754
            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
   755
        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
   756
            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
   757
        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
   758
        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
   759
                   u'</td></tr></table>']
4376
839b28a3652e surrounding div necessary for proper error localization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4375
diff changeset
   760
        # surrounding div necessary for proper error localization
4508
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   761
        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
   762
            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
   763
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
    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
   765
        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
   766
        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
   767
        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
   768
        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
   769
            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
   770
        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
   771
        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
   772
            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
   773
            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
   774
                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
   775
                    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
   776
                    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
   777
                        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
   778
                            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
   779
                        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
   780
                            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
   781
                        # 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
   782
                        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
   783
        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
   784
            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
   785
        return u'%s?%s' % (path, req.build_url_params(**values))