web/views/formrenderers.py
author Sylvain Thénault <sylvain.thenault@logilab.fr>
Mon, 21 Dec 2009 19:18:49 +0100
changeset 4156 1bbb0ee42c8e
parent 4083 3b285889b8e9
child 4164 119a374c5eb4
permissions -rw-r--r--
drop form_field_name/form_field_id methods from form object, in favor of field.input_name(form) / field.dom_id(form)
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
     1
"""form renderers, responsible to layout a form to html
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
     2
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
     3
:organization: Logilab
1977
606923dff11b big bunch of copyright / docstring update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1967
diff changeset
     4
:copyright: 2009 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.
1147
402e8a8b1d6a more form works
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: 1967
diff changeset
     6
:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
     7
"""
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
     8
__docformat__ = "restructuredtext en"
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
     9
3478
f043f71017a3 handle display_fields in the form, not in the renderer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3477
diff changeset
    10
from warnings import warn
f043f71017a3 handle display_fields in the form, not in the renderer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3477
diff changeset
    11
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
    12
from logilab.common import dictattr
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2247
diff changeset
    13
from logilab.mtconverter import xml_escape
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
    14
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
    15
from simplejson import dumps
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
    16
4023
eae23c40627a drop common subpackage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3629
diff changeset
    17
from cubicweb import tags
2656
a93ae0f6c0ad R [base classes] only AppObject remaning, no more AppRsetObject
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2586
diff changeset
    18
from cubicweb.appobject import AppObject
4075
e710f4052bd6 use implements instead of entity_implements
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4073
diff changeset
    19
from cubicweb.selectors import implements, yes
2819
b864288fd316 remove more 3.2 deprecated code, reintroduce checkbox used by formrenderers
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2656
diff changeset
    20
from cubicweb.web import eid_param, formwidgets as fwdgs
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
    21
3478
f043f71017a3 handle display_fields in the form, not in the renderer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3477
diff changeset
    22
2819
b864288fd316 remove more 3.2 deprecated code, reintroduce checkbox used by formrenderers
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2656
diff changeset
    23
def checkbox(name, value, attrs='', checked=None):
b864288fd316 remove more 3.2 deprecated code, reintroduce checkbox used by formrenderers
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2656
diff changeset
    24
    if checked is None:
b864288fd316 remove more 3.2 deprecated code, reintroduce checkbox used by formrenderers
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2656
diff changeset
    25
        checked = value
b864288fd316 remove more 3.2 deprecated code, reintroduce checkbox used by formrenderers
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2656
diff changeset
    26
    checked = checked and 'checked="checked"' or ''
b864288fd316 remove more 3.2 deprecated code, reintroduce checkbox used by formrenderers
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2656
diff changeset
    27
    return u'<input type="checkbox" name="%s" value="%s" %s %s />' % (
b864288fd316 remove more 3.2 deprecated code, reintroduce checkbox used by formrenderers
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2656
diff changeset
    28
        name, value, checked, attrs)
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
    29
1319
sylvain.thenault@logilab.fr
parents: 1305
diff changeset
    30
2656
a93ae0f6c0ad R [base classes] only AppObject remaning, no more AppRsetObject
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2586
diff changeset
    31
class FormRenderer(AppObject):
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
    32
    """basic renderer displaying fields in a two columns table label | value
1401
56764b1b4887 new renderer displaying field in an horizontable table
sylvain.thenault@logilab.fr
parents: 1362
diff changeset
    33
56764b1b4887 new renderer displaying field in an horizontable table
sylvain.thenault@logilab.fr
parents: 1362
diff changeset
    34
    +--------------+--------------+
56764b1b4887 new renderer displaying field in an horizontable table
sylvain.thenault@logilab.fr
parents: 1362
diff changeset
    35
    | field1 label | field1 input |
56764b1b4887 new renderer displaying field in an horizontable table
sylvain.thenault@logilab.fr
parents: 1362
diff changeset
    36
    +--------------+--------------+
56764b1b4887 new renderer displaying field in an horizontable table
sylvain.thenault@logilab.fr
parents: 1362
diff changeset
    37
    | field1 label | field2 input |
56764b1b4887 new renderer displaying field in an horizontable table
sylvain.thenault@logilab.fr
parents: 1362
diff changeset
    38
    +--------------+--------------+
56764b1b4887 new renderer displaying field in an horizontable table
sylvain.thenault@logilab.fr
parents: 1362
diff changeset
    39
    +---------+
56764b1b4887 new renderer displaying field in an horizontable table
sylvain.thenault@logilab.fr
parents: 1362
diff changeset
    40
    | buttons |
56764b1b4887 new renderer displaying field in an horizontable table
sylvain.thenault@logilab.fr
parents: 1362
diff changeset
    41
    +---------+
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
    42
    """
1995
ec95eaa2b711 turn renderers into appobjects
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
    43
    __registry__ = 'formrenderers'
3377
dd9d292b6a6d use __regid__ instead of id on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3369
diff changeset
    44
    __regid__ = 'default'
1995
ec95eaa2b711 turn renderers into appobjects
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
    45
3478
f043f71017a3 handle display_fields in the form, not in the renderer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3477
diff changeset
    46
    _options = ('display_label', 'display_help',
1995
ec95eaa2b711 turn renderers into appobjects
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
    47
                'display_progress_div', 'table_class', 'button_bar_class',
ec95eaa2b711 turn renderers into appobjects
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
    48
                # add entity since it may be given to select the renderer
ec95eaa2b711 turn renderers into appobjects
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
    49
                'entity')
1362
decb7507fa91 nicer renderer options handling: can be passed to __init__ or to render
sylvain.thenault@logilab.fr
parents: 1340
diff changeset
    50
    display_label = True
decb7507fa91 nicer renderer options handling: can be passed to __init__ or to render
sylvain.thenault@logilab.fr
parents: 1340
diff changeset
    51
    display_help = True
decb7507fa91 nicer renderer options handling: can be passed to __init__ or to render
sylvain.thenault@logilab.fr
parents: 1340
diff changeset
    52
    display_progress_div = True
1710
8c717cc0b353 refactor error handling: get validation error information from a form attribute instead of req.data to avoid pb when multiple forms are displayed
sylvain.thenault@logilab.fr
parents: 1691
diff changeset
    53
    table_class = u'attributeForm'
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
    54
    button_bar_class = u'formButtonBar'
1436
97774eb6443b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1434
diff changeset
    55
1995
ec95eaa2b711 turn renderers into appobjects
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
    56
    def __init__(self, req=None, rset=None, row=None, col=None, **kwargs):
2890
fdcb8a2bb6eb fix __init__ parameters
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2819
diff changeset
    57
        super(FormRenderer, self).__init__(req, rset=rset, row=row, col=col)
1362
decb7507fa91 nicer renderer options handling: can be passed to __init__ or to render
sylvain.thenault@logilab.fr
parents: 1340
diff changeset
    58
        if self._set_options(kwargs):
decb7507fa91 nicer renderer options handling: can be passed to __init__ or to render
sylvain.thenault@logilab.fr
parents: 1340
diff changeset
    59
            raise ValueError('unconsumed arguments %s' % kwargs)
decb7507fa91 nicer renderer options handling: can be passed to __init__ or to render
sylvain.thenault@logilab.fr
parents: 1340
diff changeset
    60
decb7507fa91 nicer renderer options handling: can be passed to __init__ or to render
sylvain.thenault@logilab.fr
parents: 1340
diff changeset
    61
    def _set_options(self, kwargs):
1434
42e57dbbc585 new display_relations_form option on EntityFormRender
sylvain.thenault@logilab.fr
parents: 1412
diff changeset
    62
        for key in self._options:
1362
decb7507fa91 nicer renderer options handling: can be passed to __init__ or to render
sylvain.thenault@logilab.fr
parents: 1340
diff changeset
    63
            try:
decb7507fa91 nicer renderer options handling: can be passed to __init__ or to render
sylvain.thenault@logilab.fr
parents: 1340
diff changeset
    64
                setattr(self, key, kwargs.pop(key))
decb7507fa91 nicer renderer options handling: can be passed to __init__ or to render
sylvain.thenault@logilab.fr
parents: 1340
diff changeset
    65
            except KeyError:
decb7507fa91 nicer renderer options handling: can be passed to __init__ or to render
sylvain.thenault@logilab.fr
parents: 1340
diff changeset
    66
                continue
decb7507fa91 nicer renderer options handling: can be passed to __init__ or to render
sylvain.thenault@logilab.fr
parents: 1340
diff changeset
    67
        return kwargs
1436
97774eb6443b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1434
diff changeset
    68
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
    69
    # renderer interface ######################################################
1436
97774eb6443b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1434
diff changeset
    70
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
    71
    def render(self, form, values):
1362
decb7507fa91 nicer renderer options handling: can be passed to __init__ or to render
sylvain.thenault@logilab.fr
parents: 1340
diff changeset
    72
        self._set_options(values)
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
    73
        form.add_media()
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
    74
        data = []
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
    75
        w = data.append
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
    76
        w(self.open_form(form, values))
1362
decb7507fa91 nicer renderer options handling: can be passed to __init__ or to render
sylvain.thenault@logilab.fr
parents: 1340
diff changeset
    77
        if self.display_progress_div:
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3398
diff changeset
    78
            w(u'<div id="progress">%s</div>' % self._cw._('validating...'))
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
    79
        w(u'<fieldset>')
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
    80
        w(tags.input(type=u'hidden', name=u'__form_id',
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3398
diff changeset
    81
                     value=values.get('formvid', form.__regid__)))
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
    82
        if form.redirect_path:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
    83
            w(tags.input(type='hidden', name='__redirectpath', value=form.redirect_path))
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
    84
        self.render_fields(w, form, values)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
    85
        self.render_buttons(w, form)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
    86
        w(u'</fieldset>')
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
    87
        w(u'</form>')
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
    88
        errormsg = self.error_message(form)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
    89
        if errormsg:
1436
97774eb6443b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1434
diff changeset
    90
            data.insert(0, errormsg)
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
    91
        return '\n'.join(data)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
    92
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
    93
    def render_label(self, form, field):
2521
782360fa6cc0 take care to None labels
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2520
diff changeset
    94
        if field.label is None:
782360fa6cc0 take care to None labels
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2520
diff changeset
    95
            return u''
3275
5247789df541 [gettext] provide GNU contexts to avoid translations ambiguities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3264
diff changeset
    96
        if isinstance(field.label, tuple): # i.e. needs contextual translation
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3398
diff changeset
    97
            label = self._cw.pgettext(*field.label)
3275
5247789df541 [gettext] provide GNU contexts to avoid translations ambiguities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3264
diff changeset
    98
        else:
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3398
diff changeset
    99
            label = self._cw._(field.label)
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: 4083
diff changeset
   100
        attrs = {'for': field.dom_id(form)}
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   101
        if field.required:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   102
            attrs['class'] = 'required'
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   103
        return tags.label(label, **attrs)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   104
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   105
    def render_help(self, form, field):
1946
d60ddfc4bb09 don't use tab
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1863
diff changeset
   106
        help = []
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   107
        descr = field.help
2093
e3aaf61f8c66 field's help may now be a callable taking the form as argument
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2006
diff changeset
   108
        if callable(descr):
e3aaf61f8c66 field's help may now be a callable taking the form as argument
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2006
diff changeset
   109
            descr = descr(form)
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   110
        if descr:
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3398
diff changeset
   111
            help.append('<div class="helper">%s</div>' % self._cw._(descr))
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3398
diff changeset
   112
        example = field.example_format(self._cw)
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   113
        if example:
1863
9a02979a2c00 do not use <br> in widgets
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 1757
diff changeset
   114
            help.append('<div class="helper">(%s: %s)</div>'
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3398
diff changeset
   115
                        % (self._cw._('sample format'), example))
2996
866a2c135c33 B #345282 xhtml requires to use &#160; instead of &nbsp;
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2656
diff changeset
   116
        return u'&#160;'.join(help)
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   117
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   118
    # specific methods (mostly to ease overriding) #############################
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   119
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   120
    def error_message(self, form):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   121
        """return formatted error message
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   122
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   123
        This method should be called once inlined field errors has been consumed
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   124
        """
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3398
diff changeset
   125
        req = self._cw
1710
8c717cc0b353 refactor error handling: get validation error information from a form attribute instead of req.data to avoid pb when multiple forms are displayed
sylvain.thenault@logilab.fr
parents: 1691
diff changeset
   126
        errex = form.form_valerror
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   127
        # get extra errors
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   128
        if errex is not None:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   129
            errormsg = req._('please correct the following errors:')
1710
8c717cc0b353 refactor error handling: get validation error information from a form attribute instead of req.data to avoid pb when multiple forms are displayed
sylvain.thenault@logilab.fr
parents: 1691
diff changeset
   130
            displayed = form.form_displayed_errors
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   131
            errors = sorted((field, err) for field, err in errex.errors.items()
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   132
                            if not field in displayed)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   133
            if errors:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   134
                if len(errors) > 1:
1436
97774eb6443b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1434
diff changeset
   135
                    templstr = '<li>%s</li>\n'
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   136
                else:
2996
866a2c135c33 B #345282 xhtml requires to use &#160; instead of &nbsp;
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2656
diff changeset
   137
                    templstr = '&#160;%s\n'
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   138
                for field, err in errors:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   139
                    if field is None:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   140
                        errormsg += templstr % err
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   141
                    else:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   142
                        errormsg += templstr % '%s: %s' % (req._(field), err)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   143
                if len(errors) > 1:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   144
                    errormsg = '<ul>%s</ul>' % errormsg
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   145
            return u'<div class="errorMessage">%s</div>' % errormsg
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   146
        return u''
1436
97774eb6443b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1434
diff changeset
   147
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   148
    def open_form(self, form, values):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   149
        if form.form_needs_multipart:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   150
            enctype = 'multipart/form-data'
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   151
        else:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   152
            enctype = 'application/x-www-form-urlencoded'
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   153
        if form.action is None:
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3398
diff changeset
   154
            action = self._cw.build_url('edit')
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   155
        else:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   156
            action = form.action
1274
b730932a79b7 we don't want dom id systematically
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   157
        tag = ('<form action="%s" method="post" enctype="%s"' % (
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2247
diff changeset
   158
            xml_escape(action or '#'), enctype))
1274
b730932a79b7 we don't want dom id systematically
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   159
        if form.domid:
b730932a79b7 we don't want dom id systematically
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   160
            tag += ' id="%s"' % form.domid
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   161
        if form.onsubmit:
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2247
diff changeset
   162
            tag += ' onsubmit="%s"' % xml_escape(form.onsubmit % dictattr(form))
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   163
        if form.cssstyle:
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2247
diff changeset
   164
            tag += ' style="%s"' % xml_escape(form.cssstyle)
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   165
        if form.cssclass:
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2247
diff changeset
   166
            tag += ' class="%s"' % xml_escape(form.cssclass)
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   167
        if form.cwtarget:
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2247
diff changeset
   168
            tag += ' cubicweb:target="%s"' % xml_escape(form.cwtarget)
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   169
        return tag + '>'
1436
97774eb6443b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1434
diff changeset
   170
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   171
    def render_fields(self, w, form, values):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   172
        fields = self._render_hidden_fields(w, form)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   173
        if fields:
1403
425892e14e67 _render_fields don't need values argument
sylvain.thenault@logilab.fr
parents: 1401
diff changeset
   174
            self._render_fields(fields, w, form)
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   175
        self.render_child_forms(w, form, values)
1436
97774eb6443b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1434
diff changeset
   176
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   177
    def render_child_forms(self, w, form, values):
1436
97774eb6443b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1434
diff changeset
   178
        # render
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   179
        for childform in getattr(form, 'forms', []):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   180
            self.render_fields(w, childform, values)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   181
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   182
    def _render_hidden_fields(self, w, form):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   183
        fields = form.fields[:]
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   184
        for field in form.fields:
3478
f043f71017a3 handle display_fields in the form, not in the renderer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3477
diff changeset
   185
            if not field.is_visible():
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   186
                w(field.render(form, self))
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   187
                fields.remove(field)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   188
        return fields
1436
97774eb6443b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1434
diff changeset
   189
1403
425892e14e67 _render_fields don't need values argument
sylvain.thenault@logilab.fr
parents: 1401
diff changeset
   190
    def _render_fields(self, fields, w, form):
2520
8c5cf48ae9ea new fieldset attribute on field, use to group fields by the default form renderer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2381
diff changeset
   191
        byfieldset = {}
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   192
        for field in fields:
2520
8c5cf48ae9ea new fieldset attribute on field, use to group fields by the default form renderer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2381
diff changeset
   193
            byfieldset.setdefault(field.fieldset, []).append(field)
2574
37154aa90947 [form renderer] consider form.fieldsets_in_order if specified. Warn about unexistant or unused fieldsets.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2561
diff changeset
   194
        if form.fieldsets_in_order:
37154aa90947 [form renderer] consider form.fieldsets_in_order if specified. Warn about unexistant or unused fieldsets.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2561
diff changeset
   195
            fieldsets = form.fieldsets_in_order
37154aa90947 [form renderer] consider form.fieldsets_in_order if specified. Warn about unexistant or unused fieldsets.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2561
diff changeset
   196
        else:
37154aa90947 [form renderer] consider form.fieldsets_in_order if specified. Warn about unexistant or unused fieldsets.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2561
diff changeset
   197
            fieldsets = byfieldset.keys()
37154aa90947 [form renderer] consider form.fieldsets_in_order if specified. Warn about unexistant or unused fieldsets.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2561
diff changeset
   198
        for fieldset in fieldsets:
37154aa90947 [form renderer] consider form.fieldsets_in_order if specified. Warn about unexistant or unused fieldsets.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2561
diff changeset
   199
            try:
37154aa90947 [form renderer] consider form.fieldsets_in_order if specified. Warn about unexistant or unused fieldsets.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2561
diff changeset
   200
                fields = byfieldset.pop(fieldset)
37154aa90947 [form renderer] consider form.fieldsets_in_order if specified. Warn about unexistant or unused fieldsets.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2561
diff changeset
   201
            except KeyError:
37154aa90947 [form renderer] consider form.fieldsets_in_order if specified. Warn about unexistant or unused fieldsets.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2561
diff changeset
   202
                self.warning('no such fieldset: %s (%s)', fieldset, form)
37154aa90947 [form renderer] consider form.fieldsets_in_order if specified. Warn about unexistant or unused fieldsets.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2561
diff changeset
   203
                continue
2520
8c5cf48ae9ea new fieldset attribute on field, use to group fields by the default form renderer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2381
diff changeset
   204
            w(u'<fieldset class="%s">' % (fieldset or u'default'))
8c5cf48ae9ea new fieldset attribute on field, use to group fields by the default form renderer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2381
diff changeset
   205
            if fieldset:
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3398
diff changeset
   206
                w(u'<legend>%s</legend>' % self._cw._(fieldset))
2520
8c5cf48ae9ea new fieldset attribute on field, use to group fields by the default form renderer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2381
diff changeset
   207
            w(u'<table class="%s">' % self.table_class)
8c5cf48ae9ea new fieldset attribute on field, use to group fields by the default form renderer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2381
diff changeset
   208
            for field in fields:
2561
c6f0634e2d77 [F xhml] use a class to avoid duplicated ids when editing several entities at once
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2550
diff changeset
   209
                w(u'<tr class="%s_%s_row">' % (field.name, field.role))
2520
8c5cf48ae9ea new fieldset attribute on field, use to group fields by the default form renderer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2381
diff changeset
   210
                if self.display_label:
8c5cf48ae9ea new fieldset attribute on field, use to group fields by the default form renderer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2381
diff changeset
   211
                    w(u'<th class="labelCol">%s</th>' % self.render_label(form, field))
8c5cf48ae9ea new fieldset attribute on field, use to group fields by the default form renderer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2381
diff changeset
   212
                error = form.form_field_error(field)
8c5cf48ae9ea new fieldset attribute on field, use to group fields by the default form renderer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2381
diff changeset
   213
                if error:
8c5cf48ae9ea new fieldset attribute on field, use to group fields by the default form renderer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2381
diff changeset
   214
                    w(u'<td class="error">')
8c5cf48ae9ea new fieldset attribute on field, use to group fields by the default form renderer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2381
diff changeset
   215
                    w(error)
8c5cf48ae9ea new fieldset attribute on field, use to group fields by the default form renderer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2381
diff changeset
   216
                else:
8c5cf48ae9ea new fieldset attribute on field, use to group fields by the default form renderer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2381
diff changeset
   217
                    w(u'<td>')
8c5cf48ae9ea new fieldset attribute on field, use to group fields by the default form renderer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2381
diff changeset
   218
                w(field.render(form, self))
8c5cf48ae9ea new fieldset attribute on field, use to group fields by the default form renderer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2381
diff changeset
   219
                if self.display_help:
8c5cf48ae9ea new fieldset attribute on field, use to group fields by the default form renderer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2381
diff changeset
   220
                    w(self.render_help(form, field))
8c5cf48ae9ea new fieldset attribute on field, use to group fields by the default form renderer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2381
diff changeset
   221
                w(u'</td></tr>')
8c5cf48ae9ea new fieldset attribute on field, use to group fields by the default form renderer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2381
diff changeset
   222
            w(u'</table></fieldset>')
2574
37154aa90947 [form renderer] consider form.fieldsets_in_order if specified. Warn about unexistant or unused fieldsets.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2561
diff changeset
   223
        if byfieldset:
37154aa90947 [form renderer] consider form.fieldsets_in_order if specified. Warn about unexistant or unused fieldsets.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2561
diff changeset
   224
            self.warning('unused fieldsets: %s', ', '.join(byfieldset))
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   225
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   226
    def render_buttons(self, w, form):
2148
2b2b9626a98f do not write -invalid- empty table row when form has no buttons
Florent <florent@secondweb.fr>
parents: 2093
diff changeset
   227
        if not form.form_buttons:
2b2b9626a98f do not write -invalid- empty table row when form has no buttons
Florent <florent@secondweb.fr>
parents: 2093
diff changeset
   228
            return
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   229
        w(u'<table class="%s">\n<tr>\n' % self.button_bar_class)
1304
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1293
diff changeset
   230
        for button in form.form_buttons:
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1293
diff changeset
   231
            w(u'<td>%s</td>\n' % button.render(form))
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   232
        w(u'</tr></table>')
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   233
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   234
2005
e8032965f37a turn every form class into appobject. They should not be instantiated manually anymore.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1995
diff changeset
   235
class BaseFormRenderer(FormRenderer):
2198
ac45d4dbaf76 close #344264, pb with composite fields / renderer.display_fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2148
diff changeset
   236
    """use form_renderer_id = 'base' if you want base FormRenderer layout even
ac45d4dbaf76 close #344264, pb with composite fields / renderer.display_fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2148
diff changeset
   237
    when selected for an entity
2005
e8032965f37a turn every form class into appobject. They should not be instantiated manually anymore.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1995
diff changeset
   238
    """
3377
dd9d292b6a6d use __regid__ instead of id on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3369
diff changeset
   239
    __regid__ = 'base'
2198
ac45d4dbaf76 close #344264, pb with composite fields / renderer.display_fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2148
diff changeset
   240
ac45d4dbaf76 close #344264, pb with composite fields / renderer.display_fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2148
diff changeset
   241
ac45d4dbaf76 close #344264, pb with composite fields / renderer.display_fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2148
diff changeset
   242
1401
56764b1b4887 new renderer displaying field in an horizontable table
sylvain.thenault@logilab.fr
parents: 1362
diff changeset
   243
class HTableFormRenderer(FormRenderer):
56764b1b4887 new renderer displaying field in an horizontable table
sylvain.thenault@logilab.fr
parents: 1362
diff changeset
   244
    """display fields horizontally in a table
56764b1b4887 new renderer displaying field in an horizontable table
sylvain.thenault@logilab.fr
parents: 1362
diff changeset
   245
56764b1b4887 new renderer displaying field in an horizontable table
sylvain.thenault@logilab.fr
parents: 1362
diff changeset
   246
    +--------------+--------------+---------+
56764b1b4887 new renderer displaying field in an horizontable table
sylvain.thenault@logilab.fr
parents: 1362
diff changeset
   247
    | field1 label | field2 label |         |
56764b1b4887 new renderer displaying field in an horizontable table
sylvain.thenault@logilab.fr
parents: 1362
diff changeset
   248
    +--------------+--------------+---------+
56764b1b4887 new renderer displaying field in an horizontable table
sylvain.thenault@logilab.fr
parents: 1362
diff changeset
   249
    | field1 input | field2 input | buttons
1436
97774eb6443b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1434
diff changeset
   250
    +--------------+--------------+---------+
1401
56764b1b4887 new renderer displaying field in an horizontable table
sylvain.thenault@logilab.fr
parents: 1362
diff changeset
   251
    """
3377
dd9d292b6a6d use __regid__ instead of id on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3369
diff changeset
   252
    __regid__ = 'htable'
1995
ec95eaa2b711 turn renderers into appobjects
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   253
1401
56764b1b4887 new renderer displaying field in an horizontable table
sylvain.thenault@logilab.fr
parents: 1362
diff changeset
   254
    display_help = False
1403
425892e14e67 _render_fields don't need values argument
sylvain.thenault@logilab.fr
parents: 1401
diff changeset
   255
    def _render_fields(self, fields, w, form):
3572
606ce53dc557 [forms] some style for htable renderer layout
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3519
diff changeset
   256
        w(u'<table border="0" class="htableForm">')
1401
56764b1b4887 new renderer displaying field in an horizontable table
sylvain.thenault@logilab.fr
parents: 1362
diff changeset
   257
        w(u'<tr>')
1436
97774eb6443b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1434
diff changeset
   258
        for field in fields:
1401
56764b1b4887 new renderer displaying field in an horizontable table
sylvain.thenault@logilab.fr
parents: 1362
diff changeset
   259
            if self.display_label:
56764b1b4887 new renderer displaying field in an horizontable table
sylvain.thenault@logilab.fr
parents: 1362
diff changeset
   260
                w(u'<th class="labelCol">%s</th>' % self.render_label(form, field))
56764b1b4887 new renderer displaying field in an horizontable table
sylvain.thenault@logilab.fr
parents: 1362
diff changeset
   261
            if self.display_help:
56764b1b4887 new renderer displaying field in an horizontable table
sylvain.thenault@logilab.fr
parents: 1362
diff changeset
   262
                w(self.render_help(form, field))
56764b1b4887 new renderer displaying field in an horizontable table
sylvain.thenault@logilab.fr
parents: 1362
diff changeset
   263
        # empty slot for buttons
2996
866a2c135c33 B #345282 xhtml requires to use &#160; instead of &nbsp;
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2656
diff changeset
   264
        w(u'<th class="labelCol">&#160;</th>')
1401
56764b1b4887 new renderer displaying field in an horizontable table
sylvain.thenault@logilab.fr
parents: 1362
diff changeset
   265
        w(u'</tr>')
56764b1b4887 new renderer displaying field in an horizontable table
sylvain.thenault@logilab.fr
parents: 1362
diff changeset
   266
        w(u'<tr>')
1436
97774eb6443b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1434
diff changeset
   267
        for field in fields:
1401
56764b1b4887 new renderer displaying field in an horizontable table
sylvain.thenault@logilab.fr
parents: 1362
diff changeset
   268
            error = form.form_field_error(field)
56764b1b4887 new renderer displaying field in an horizontable table
sylvain.thenault@logilab.fr
parents: 1362
diff changeset
   269
            if error:
1757
fbb9928bf4f1 remove fixed width
sylvain.thenault@logilab.fr
parents: 1710
diff changeset
   270
                w(u'<td class="error">')
1401
56764b1b4887 new renderer displaying field in an horizontable table
sylvain.thenault@logilab.fr
parents: 1362
diff changeset
   271
                w(error)
56764b1b4887 new renderer displaying field in an horizontable table
sylvain.thenault@logilab.fr
parents: 1362
diff changeset
   272
            else:
1757
fbb9928bf4f1 remove fixed width
sylvain.thenault@logilab.fr
parents: 1710
diff changeset
   273
                w(u'<td>')
1401
56764b1b4887 new renderer displaying field in an horizontable table
sylvain.thenault@logilab.fr
parents: 1362
diff changeset
   274
            w(field.render(form, self))
56764b1b4887 new renderer displaying field in an horizontable table
sylvain.thenault@logilab.fr
parents: 1362
diff changeset
   275
            w(u'</td>')
56764b1b4887 new renderer displaying field in an horizontable table
sylvain.thenault@logilab.fr
parents: 1362
diff changeset
   276
        w(u'<td>')
56764b1b4887 new renderer displaying field in an horizontable table
sylvain.thenault@logilab.fr
parents: 1362
diff changeset
   277
        for button in form.form_buttons:
56764b1b4887 new renderer displaying field in an horizontable table
sylvain.thenault@logilab.fr
parents: 1362
diff changeset
   278
            w(button.render(form))
56764b1b4887 new renderer displaying field in an horizontable table
sylvain.thenault@logilab.fr
parents: 1362
diff changeset
   279
        w(u'</td>')
56764b1b4887 new renderer displaying field in an horizontable table
sylvain.thenault@logilab.fr
parents: 1362
diff changeset
   280
        w(u'</tr>')
56764b1b4887 new renderer displaying field in an horizontable table
sylvain.thenault@logilab.fr
parents: 1362
diff changeset
   281
        w(u'</table>')
56764b1b4887 new renderer displaying field in an horizontable table
sylvain.thenault@logilab.fr
parents: 1362
diff changeset
   282
56764b1b4887 new renderer displaying field in an horizontable table
sylvain.thenault@logilab.fr
parents: 1362
diff changeset
   283
    def render_buttons(self, w, form):
56764b1b4887 new renderer displaying field in an horizontable table
sylvain.thenault@logilab.fr
parents: 1362
diff changeset
   284
        pass
1436
97774eb6443b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1434
diff changeset
   285
97774eb6443b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1434
diff changeset
   286
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   287
class EntityCompositeFormRenderer(FormRenderer):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   288
    """specific renderer for multiple entities edition form (muledit)"""
3377
dd9d292b6a6d use __regid__ instead of id on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3369
diff changeset
   289
    __regid__ = 'composite'
1436
97774eb6443b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1434
diff changeset
   290
2575
e033939d5664 [form renderer] fix composite form renderer in case the main form has some visible fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2574
diff changeset
   291
    _main_display_fields = None
e033939d5664 [form renderer] fix composite form renderer in case the main form has some visible fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2574
diff changeset
   292
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   293
    def render_fields(self, w, form, values):
3513
c002f6488631 [form] replace is_subform by parent_form, carrying more information at the same cost
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3510
diff changeset
   294
        if form.parent_form is None:
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   295
            w(u'<table class="listing">')
2586
879912fe94e1 [xhtml form renderer] fix html structure, move header where we are sure to display it when necesary (_render_fields not displayed if main form has no visible fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2577
diff changeset
   296
            subfields = [field for field in form.forms[0].fields
4076
2e8637a97b89 no more handled by the renderer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4075
diff changeset
   297
                         if field.is_visible()]
2586
879912fe94e1 [xhtml form renderer] fix html structure, move header where we are sure to display it when necesary (_render_fields not displayed if main form has no visible fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2577
diff changeset
   298
            if subfields:
879912fe94e1 [xhtml form renderer] fix html structure, move header where we are sure to display it when necesary (_render_fields not displayed if main form has no visible fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2577
diff changeset
   299
                # main form, display table headers
879912fe94e1 [xhtml form renderer] fix html structure, move header where we are sure to display it when necesary (_render_fields not displayed if main form has no visible fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2577
diff changeset
   300
                w(u'<tr class="header">')
879912fe94e1 [xhtml form renderer] fix html structure, move header where we are sure to display it when necesary (_render_fields not displayed if main form has no visible fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2577
diff changeset
   301
                w(u'<th align="left">%s</th>' %
879912fe94e1 [xhtml form renderer] fix html structure, move header where we are sure to display it when necesary (_render_fields not displayed if main form has no visible fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2577
diff changeset
   302
                  tags.input(type='checkbox',
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3398
diff changeset
   303
                             title=self._cw._('toggle check boxes'),
2586
879912fe94e1 [xhtml form renderer] fix html structure, move header where we are sure to display it when necesary (_render_fields not displayed if main form has no visible fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2577
diff changeset
   304
                             onclick="setCheckboxesState('eid', this.checked)"))
879912fe94e1 [xhtml form renderer] fix html structure, move header where we are sure to display it when necesary (_render_fields not displayed if main form has no visible fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2577
diff changeset
   305
                for field in subfields:
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3398
diff changeset
   306
                    w(u'<th>%s</th>' % self._cw._(field.label))
2586
879912fe94e1 [xhtml form renderer] fix html structure, move header where we are sure to display it when necesary (_render_fields not displayed if main form has no visible fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2577
diff changeset
   307
                w(u'</tr>')
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   308
        super(EntityCompositeFormRenderer, self).render_fields(w, form, values)
3513
c002f6488631 [form] replace is_subform by parent_form, carrying more information at the same cost
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3510
diff changeset
   309
        if form.parent_form is None:
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   310
            w(u'</table>')
2575
e033939d5664 [form renderer] fix composite form renderer in case the main form has some visible fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2574
diff changeset
   311
            if self._main_display_fields:
e033939d5664 [form renderer] fix composite form renderer in case the main form has some visible fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2574
diff changeset
   312
                super(EntityCompositeFormRenderer, self)._render_fields(
e033939d5664 [form renderer] fix composite form renderer in case the main form has some visible fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2574
diff changeset
   313
                    self._main_display_fields, w, form)
1436
97774eb6443b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1434
diff changeset
   314
1403
425892e14e67 _render_fields don't need values argument
sylvain.thenault@logilab.fr
parents: 1401
diff changeset
   315
    def _render_fields(self, fields, w, form):
3513
c002f6488631 [form] replace is_subform by parent_form, carrying more information at the same cost
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3510
diff changeset
   316
        if form.parent_form is not None:
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   317
            entity = form.edited_entity
1710
8c717cc0b353 refactor error handling: get validation error information from a form attribute instead of req.data to avoid pb when multiple forms are displayed
sylvain.thenault@logilab.fr
parents: 1691
diff changeset
   318
            values = form.form_previous_values
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   319
            qeid = eid_param('eid', entity.eid)
2577
7c9888114085 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2575
diff changeset
   320
            cbsetstate = "setCheckboxesState2('eid', %s, 'checked')" % \
7c9888114085 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2575
diff changeset
   321
                         xml_escape(dumps(entity.eid))
3467
a6405235aac6 [tests] make unittest_views_editforms pass again
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3451
diff changeset
   322
            w(u'<tr class="%s">' % (entity.cw_row % 2 and u'even' or u'odd'))
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   323
            # XXX turn this into a widget used on the eid field
2577
7c9888114085 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2575
diff changeset
   324
            w(u'<td>%s</td>' % checkbox('eid', entity.eid,
7c9888114085 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2575
diff changeset
   325
                                        checked=qeid in values))
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   326
            for field in fields:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   327
                error = form.form_field_error(field)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   328
                if error:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   329
                    w(u'<td class="error">')
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   330
                    w(error)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   331
                else:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   332
                    w(u'<td>')
2577
7c9888114085 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2575
diff changeset
   333
                if isinstance(field.widget, (fwdgs.Select, fwdgs.CheckBox,
7c9888114085 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2575
diff changeset
   334
                                             fwdgs.Radio)):
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   335
                    field.widget.attrs['onchange'] = cbsetstate
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   336
                elif isinstance(field.widget, fwdgs.Input):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   337
                    field.widget.attrs['onkeypress'] = cbsetstate
2577
7c9888114085 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2575
diff changeset
   338
                # XXX else
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   339
                w(u'<div>%s</div>' % field.render(form, self))
2586
879912fe94e1 [xhtml form renderer] fix html structure, move header where we are sure to display it when necesary (_render_fields not displayed if main form has no visible fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2577
diff changeset
   340
                w(u'</td>\n')
879912fe94e1 [xhtml form renderer] fix html structure, move header where we are sure to display it when necesary (_render_fields not displayed if main form has no visible fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2577
diff changeset
   341
            w(u'</tr>')
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   342
        else:
2575
e033939d5664 [form renderer] fix composite form renderer in case the main form has some visible fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2574
diff changeset
   343
            self._main_display_fields = fields
1436
97774eb6443b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1434
diff changeset
   344
97774eb6443b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1434
diff changeset
   345
3478
f043f71017a3 handle display_fields in the form, not in the renderer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3477
diff changeset
   346
class EntityFormRenderer(BaseFormRenderer):
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   347
    """specific renderer for entity edition form (edition)"""
3377
dd9d292b6a6d use __regid__ instead of id on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3369
diff changeset
   348
    __regid__ = 'default'
2198
ac45d4dbaf76 close #344264, pb with composite fields / renderer.display_fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2148
diff changeset
   349
    # needs some additional points in some case (XXX explain cases)
4075
e710f4052bd6 use implements instead of entity_implements
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4073
diff changeset
   350
    __select__ = implements('Any') & yes()
1995
ec95eaa2b711 turn renderers into appobjects
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   351
3507
ff945c7013d9 [form] make EntityFormRenderer a little bit easier to override
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 3360
diff changeset
   352
    _options = FormRenderer._options + ('display_relations_form', 'main_form_title')
1434
42e57dbbc585 new display_relations_form option on EntityFormRender
sylvain.thenault@logilab.fr
parents: 1412
diff changeset
   353
    display_relations_form = True
3592
4c08780e54ed [i18n] msgid tweaks
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3572
diff changeset
   354
    main_form_title = _('main informations')
1436
97774eb6443b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1434
diff changeset
   355
1181
620ec8e6ae19 cleanup, various fix to get something working
sylvain.thenault@logilab.fr
parents: 1147
diff changeset
   356
    def render(self, form, values):
620ec8e6ae19 cleanup, various fix to get something working
sylvain.thenault@logilab.fr
parents: 1147
diff changeset
   357
        rendered = super(EntityFormRenderer, self).render(form, values)
620ec8e6ae19 cleanup, various fix to get something working
sylvain.thenault@logilab.fr
parents: 1147
diff changeset
   358
        return rendered + u'</div>' # close extra div introducted by open_form
1436
97774eb6443b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1434
diff changeset
   359
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   360
    def open_form(self, form, values):
3507
ff945c7013d9 [form] make EntityFormRenderer a little bit easier to override
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 3360
diff changeset
   361
        attrs_fs_label = ''
ff945c7013d9 [form] make EntityFormRenderer a little bit easier to override
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 3360
diff changeset
   362
        if self.main_form_title:
ff945c7013d9 [form] make EntityFormRenderer a little bit easier to override
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 3360
diff changeset
   363
            attrs_fs_label += ('<div class="iformTitle"><span>%s</span></div>'
4073
03681ba6da0b cw 3.6 api update
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4023
diff changeset
   364
                               % self._cw._(self.main_form_title))
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   365
        attrs_fs_label += '<div class="formBody">'
1181
620ec8e6ae19 cleanup, various fix to get something working
sylvain.thenault@logilab.fr
parents: 1147
diff changeset
   366
        return attrs_fs_label + super(EntityFormRenderer, self).open_form(form, values)
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   367
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   368
    def render_fields(self, w, form, values):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   369
        super(EntityFormRenderer, self).render_fields(w, form, values)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   370
        self.inline_entities_form(w, form)
1436
97774eb6443b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1434
diff changeset
   371
        if form.edited_entity.has_eid() and self.display_relations_form:
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   372
            self.relations_form(w, form)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   373
1403
425892e14e67 _render_fields don't need values argument
sylvain.thenault@logilab.fr
parents: 1401
diff changeset
   374
    def _render_fields(self, fields, w, form):
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   375
        if not form.edited_entity.has_eid() or form.edited_entity.has_perm('update'):
1403
425892e14e67 _render_fields don't need values argument
sylvain.thenault@logilab.fr
parents: 1401
diff changeset
   376
            super(EntityFormRenderer, self)._render_fields(fields, w, form)
1436
97774eb6443b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1434
diff changeset
   377
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   378
    def render_buttons(self, w, form):
1304
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1293
diff changeset
   379
        if len(form.form_buttons) == 3:
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   380
            w("""<table width="100%%">
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   381
  <tbody>
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   382
   <tr><td align="center">
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   383
     %s
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   384
   </td><td style="align: right; width: 50%%;">
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   385
     %s
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   386
     %s
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   387
   </td></tr>
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   388
  </tbody>
1304
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1293
diff changeset
   389
 </table>""" % tuple(button.render(form) for button in form.form_buttons))
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   390
        else:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   391
            super(EntityFormRenderer, self).render_buttons(w, form)
1436
97774eb6443b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1434
diff changeset
   392
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   393
    def relations_form(self, w, form):
3477
8a9e26b93bb7 [uicfg, autoform] should have been in previous ci
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3467
diff changeset
   394
        try:
8a9e26b93bb7 [uicfg, autoform] should have been in previous ci
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3467
diff changeset
   395
            srels_by_cat = form.srelations_by_category('generic', 'add', strict=True)
8a9e26b93bb7 [uicfg, autoform] should have been in previous ci
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3467
diff changeset
   396
            warn('[3.6] %s: srelations_by_category is deprecated, override '
8a9e26b93bb7 [uicfg, autoform] should have been in previous ci
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3467
diff changeset
   397
                 'editable_relations instead' % classid(form), DeprecationWarning)
8a9e26b93bb7 [uicfg, autoform] should have been in previous ci
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3467
diff changeset
   398
        except AttributeError:
8a9e26b93bb7 [uicfg, autoform] should have been in previous ci
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3467
diff changeset
   399
            srels_by_cat = form.editable_relations()
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   400
        if not srels_by_cat:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   401
            return u''
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3398
diff changeset
   402
        req = self._cw
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   403
        _ = req._
3263
5129918c671b i18n update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3244
diff changeset
   404
        __ = _
5129918c671b i18n update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3244
diff changeset
   405
        label = u'%s :' % __('This %s' % form.edited_entity.e_schema).capitalize()
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   406
        eid = form.edited_entity.eid
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   407
        w(u'<fieldset class="subentity">')
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   408
        w(u'<legend class="iformTitle">%s</legend>' % label)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   409
        w(u'<table id="relatedEntities">')
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   410
        for rschema, target, related in form.relations_table():
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   411
            # already linked entities
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   412
            if related:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   413
                w(u'<tr><th class="labelCol">%s</th>' % rschema.display_name(req, target))
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   414
                w(u'<td>')
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   415
                w(u'<ul>')
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   416
                for viewparams in related:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   417
                    w(u'<li class="invisible">%s<div id="span%s" class="%s">%s</div></li>'
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   418
                      % (viewparams[1], viewparams[0], viewparams[2], viewparams[3]))
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   419
                if not form.force_display and form.maxrelitems < len(related):
1436
97774eb6443b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1434
diff changeset
   420
                    link = (u'<span class="invisible">'
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   421
                            '[<a href="javascript: window.location.href+=\'&amp;__force_display=1\'">%s</a>]'
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3398
diff changeset
   422
                            '</span>' % self._cw._('view all'))
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   423
                    w(u'<li class="invisible">%s</li>' % link)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   424
                w(u'</ul>')
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   425
                w(u'</td>')
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   426
                w(u'</tr>')
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   427
        pendings = list(form.restore_pending_inserts())
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   428
        if not pendings:
2996
866a2c135c33 B #345282 xhtml requires to use &#160; instead of &nbsp;
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2656
diff changeset
   429
            w(u'<tr><th>&#160;</th><td>&#160;</td></tr>')
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   430
        else:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   431
            for row in pendings:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   432
                # soon to be linked to entities
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   433
                w(u'<tr id="tr%s">' % row[1])
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   434
                w(u'<th>%s</th>' % row[3])
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   435
                w(u'<td>')
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   436
                w(u'<a class="handle" title="%s" href="%s">[x]</a>' %
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   437
                  (_('cancel this insert'), row[2]))
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   438
                w(u'<a id="a%s" class="editionPending" href="%s">%s</a>'
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2247
diff changeset
   439
                  % (row[1], row[4], xml_escape(row[5])))
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   440
                w(u'</td>')
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   441
                w(u'</tr>')
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   442
        w(u'<tr id="relationSelectorRow_%s" class="separator">' % eid)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   443
        w(u'<th class="labelCol">')
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   444
        w(u'<span>%s</span>' % _('add relation'))
1305
395ef7f2b95b cleanup, remove some unnecessary (sometime buggy) stuff
sylvain.thenault@logilab.fr
parents: 1304
diff changeset
   445
        w(u'<select id="relationSelector_%s" tabindex="%s" '
395ef7f2b95b cleanup, remove some unnecessary (sometime buggy) stuff
sylvain.thenault@logilab.fr
parents: 1304
diff changeset
   446
          'onchange="javascript:showMatchingSelect(this.options[this.selectedIndex].value,%s);">'
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2247
diff changeset
   447
          % (eid, req.next_tabindex(), xml_escape(dumps(eid))))
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   448
        w(u'<option value="">%s</option>' % _('select a relation'))
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   449
        for i18nrtype, rschema, target in srels_by_cat:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   450
            # more entities to link to
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   451
            w(u'<option value="%s_%s">%s</option>' % (rschema, target, i18nrtype))
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   452
        w(u'</select>')
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   453
        w(u'</th>')
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   454
        w(u'<td id="unrelatedDivs_%s"></td>' % eid)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   455
        w(u'</tr>')
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   456
        w(u'</table>')
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   457
        w(u'</fieldset>')
1436
97774eb6443b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1434
diff changeset
   458
3360
b02df886eb3e cleanup, reorganize
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3358
diff changeset
   459
    # NOTE: should_* and display_* method extracted and moved to the form to
b02df886eb3e cleanup, reorganize
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3358
diff changeset
   460
    # ease overriding
b02df886eb3e cleanup, reorganize
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3358
diff changeset
   461
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   462
    def inline_entities_form(self, w, form):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   463
        """create a form to edit entity's inlined relations"""
3518
11ce4682187d [form] important refactoring of inlined forms to get proper separation of form object creation / rendering
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3513
diff changeset
   464
        if not hasattr(form, 'inlined_form_views'):
1967
28eed65ce1e6 don't crash if inlined_relation is not defined on the form
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1964
diff changeset
   465
            return
3518
11ce4682187d [form] important refactoring of inlined forms to get proper separation of form object creation / rendering
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3513
diff changeset
   466
        keysinorder = []
11ce4682187d [form] important refactoring of inlined forms to get proper separation of form object creation / rendering
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3513
diff changeset
   467
        formviews = form.inlined_form_views()
11ce4682187d [form] important refactoring of inlined forms to get proper separation of form object creation / rendering
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3513
diff changeset
   468
        for formview in formviews:
11ce4682187d [form] important refactoring of inlined forms to get proper separation of form object creation / rendering
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3513
diff changeset
   469
            if not (formview.rtype, formview.role) in keysinorder:
11ce4682187d [form] important refactoring of inlined forms to get proper separation of form object creation / rendering
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3513
diff changeset
   470
                keysinorder.append( (formview.rtype, formview.role) )
11ce4682187d [form] important refactoring of inlined forms to get proper separation of form object creation / rendering
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3513
diff changeset
   471
        for key in keysinorder:
11ce4682187d [form] important refactoring of inlined forms to get proper separation of form object creation / rendering
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3513
diff changeset
   472
            self.inline_relation_form(w, form, [fv for fv in formviews
11ce4682187d [form] important refactoring of inlined forms to get proper separation of form object creation / rendering
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3513
diff changeset
   473
                                                if (fv.rtype, fv.role) == key])
2103
41840b1a2a1a make inline relation forms individually renderable
Florent <florent@secondweb.fr>
parents: 2006
diff changeset
   474
3518
11ce4682187d [form] important refactoring of inlined forms to get proper separation of form object creation / rendering
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3513
diff changeset
   475
    def inline_relation_form(self, w, form, formviews):
11ce4682187d [form] important refactoring of inlined forms to get proper separation of form object creation / rendering
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3513
diff changeset
   476
        i18nctx = 'inlined:%s.%s.%s' % (form.edited_entity.e_schema,
11ce4682187d [form] important refactoring of inlined forms to get proper separation of form object creation / rendering
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3513
diff changeset
   477
                                        formviews[0].rtype, formviews[0].role)
11ce4682187d [form] important refactoring of inlined forms to get proper separation of form object creation / rendering
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3513
diff changeset
   478
        w(u'<div id="inline%sslot">' % formviews[0].rtype)
11ce4682187d [form] important refactoring of inlined forms to get proper separation of form object creation / rendering
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3513
diff changeset
   479
        for formview in formviews:
4083
3b285889b8e9 3.6 api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4076
diff changeset
   480
            w(formview.render(i18nctx=i18nctx, row=formview.cw_row, col=formview.cw_col))
2103
41840b1a2a1a make inline relation forms individually renderable
Florent <florent@secondweb.fr>
parents: 2006
diff changeset
   481
        w(u'</div>')
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   482
1436
97774eb6443b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1434
diff changeset
   483
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   484
class EntityInlinedFormRenderer(EntityFormRenderer):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   485
    """specific renderer for entity inlined edition form
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   486
    (inline-[creation|edition])
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   487
    """
3377
dd9d292b6a6d use __regid__ instead of id on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3369
diff changeset
   488
    __regid__ = 'inline'
1995
ec95eaa2b711 turn renderers into appobjects
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   489
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   490
    def render(self, form, values):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   491
        form.add_media()
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   492
        data = []
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   493
        w = data.append
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   494
        try:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   495
            w(u'<div id="div-%(divid)s" onclick="%(divonclick)s">' % values)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   496
        except KeyError:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   497
            w(u'<div id="div-%(divid)s">' % values)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   498
        else:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   499
            w(u'<div id="notice-%s" class="notice">%s</div>' % (
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3398
diff changeset
   500
                values['divid'], self._cw._('click on the box to cancel the deletion')))
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   501
        w(u'<div class="iformBody">')
3327
44efba78afac fix/enhance i18n context usage for inlined forms
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3275
diff changeset
   502
        eschema = form.edited_entity.e_schema
44efba78afac fix/enhance i18n context usage for inlined forms
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3275
diff changeset
   503
        ctx = values.pop('i18nctx')
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3398
diff changeset
   504
        values['removemsg'] = self._cw.pgettext(ctx, 'remove this %s' % eschema)
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   505
        w(u'<div class="iformTitle"><span>%(title)s</span> '
2247
9dbbe6a4c9b0 use a counter of displayed inlined forms
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2198
diff changeset
   506
          '#<span class="icounter">%(counter)s</span> '
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   507
          '[<a href="javascript: %(removejs)s;noop();">%(removemsg)s</a>]</div>'
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   508
          % values)
1964
b60719223965 need to cleanup values if we don't want them to be interpreted by fields (title is a common field name for instance)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1946
diff changeset
   509
        # cleanup values
b60719223965 need to cleanup values if we don't want them to be interpreted by fields (title is a common field name for instance)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1946
diff changeset
   510
        for key in ('title', 'removejs', 'removemsg'):
b60719223965 need to cleanup values if we don't want them to be interpreted by fields (title is a common field name for instance)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1946
diff changeset
   511
            values.pop(key)
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   512
        self.render_fields(w, form, values)
1293
aae1516b6426 missing closing div
sylvain.thenault@logilab.fr
parents: 1292
diff changeset
   513
        w(u'</div></div>')
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   514
        return '\n'.join(data)
1436
97774eb6443b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1434
diff changeset
   515
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   516
    def render_fields(self, w, form, values):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   517
        w(u'<fieldset id="fs-%(divid)s">' % values)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   518
        fields = self._render_hidden_fields(w, form)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   519
        w(u'</fieldset>')
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   520
        w(u'<fieldset class="subentity">')
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   521
        if fields:
1403
425892e14e67 _render_fields don't need values argument
sylvain.thenault@logilab.fr
parents: 1401
diff changeset
   522
            self._render_fields(fields, w, form)
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   523
        self.render_child_forms(w, form, values)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   524
        self.inline_entities_form(w, form)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents:
diff changeset
   525
        w(u'</fieldset>')
1436
97774eb6443b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1434
diff changeset
   526