web/formwidgets.py
author Erica Marco <erica.marco@logilab.fr>
Thu, 26 Mar 2015 11:13:12 +0100
changeset 11048 96d57cb8b644
parent 10907 9ae707db5265
child 11049 1f41697f2e26
permissions -rw-r--r--
[views] improve JQueryDatePicker so that a date field can be defined as the min/max of an other one closes #5169039
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
9222
ec65ca70aac9 [date picker widgets] use bare jquery expression rather than jqNode
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9134
diff changeset
     1
# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
5421
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5384
diff changeset
     2
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5384
diff changeset
     3
#
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5384
diff changeset
     4
# This file is part of CubicWeb.
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5384
diff changeset
     5
#
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5384
diff changeset
     6
# CubicWeb is free software: you can redistribute it and/or modify it under the
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5384
diff changeset
     7
# terms of the GNU Lesser General Public License as published by the Free
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5384
diff changeset
     8
# Software Foundation, either version 2.1 of the License, or (at your option)
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5384
diff changeset
     9
# any later version.
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5384
diff changeset
    10
#
5424
8ecbcbff9777 replace logilab-common by CubicWeb in disclaimer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5421
diff changeset
    11
# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
5421
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5384
diff changeset
    12
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5384
diff changeset
    13
# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5384
diff changeset
    14
# details.
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5384
diff changeset
    15
#
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5384
diff changeset
    16
# You should have received a copy of the GNU Lesser General Public License along
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5384
diff changeset
    17
# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    18
"""
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    19
Widgets
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    20
~~~~~~~
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    21
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    22
.. Note::
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    23
   A widget is responsible for the display of a field. It may use more than one
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    24
   HTML input tags. When the form is posted, a widget is also reponsible to give
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    25
   back to the field something it can understand.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    26
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    27
   Of course you can not use any widget with any field...
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    28
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    29
.. autoclass:: cubicweb.web.formwidgets.FieldWidget
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    30
6880
4be32427b2b9 [book] fixes some references and other doc construction pbs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6682
diff changeset
    31
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    32
HTML <input> based widgets
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    33
''''''''''''''''''''''''''
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    34
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    35
.. autoclass:: cubicweb.web.formwidgets.HiddenInput
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    36
.. autoclass:: cubicweb.web.formwidgets.TextInput
9716
c44224387028 [widget] Addition of EmailInput
Alain Begey <alain@unlish.com>
parents: 9377
diff changeset
    37
.. autoclass:: cubicweb.web.formwidgets.EmailInput
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    38
.. autoclass:: cubicweb.web.formwidgets.PasswordSingleInput
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    39
.. autoclass:: cubicweb.web.formwidgets.FileInput
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    40
.. autoclass:: cubicweb.web.formwidgets.ButtonInput
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    41
6880
4be32427b2b9 [book] fixes some references and other doc construction pbs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6682
diff changeset
    42
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    43
Other standard HTML widgets
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    44
'''''''''''''''''''''''''''
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    45
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    46
.. autoclass:: cubicweb.web.formwidgets.TextArea
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    47
.. autoclass:: cubicweb.web.formwidgets.Select
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    48
.. autoclass:: cubicweb.web.formwidgets.CheckBox
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    49
.. autoclass:: cubicweb.web.formwidgets.Radio
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    50
6880
4be32427b2b9 [book] fixes some references and other doc construction pbs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6682
diff changeset
    51
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    52
Date and time widgets
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    53
'''''''''''''''''''''
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    54
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    55
.. autoclass:: cubicweb.web.formwidgets.DateTimePicker
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    56
.. autoclass:: cubicweb.web.formwidgets.JQueryDateTimePicker
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    57
.. autoclass:: cubicweb.web.formwidgets.JQueryDatePicker
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    58
.. autoclass:: cubicweb.web.formwidgets.JQueryTimePicker
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    59
6880
4be32427b2b9 [book] fixes some references and other doc construction pbs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6682
diff changeset
    60
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    61
Ajax / javascript widgets
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    62
'''''''''''''''''''''''''
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    63
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    64
.. autoclass:: cubicweb.web.formwidgets.FCKEditor
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    65
.. autoclass:: cubicweb.web.formwidgets.AjaxWidget
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    66
.. autoclass:: cubicweb.web.formwidgets.AutoCompletionWidget
6890
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
    67
.. autoclass:: cubicweb.web.formwidgets.InOutWidget
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    68
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    69
.. kill or document StaticFileAutoCompletionWidget
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    70
.. kill or document LazyRestrictedAutoCompletionWidget
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    71
.. kill or document RestrictedAutoCompletionWidget
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    72
6880
4be32427b2b9 [book] fixes some references and other doc construction pbs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6682
diff changeset
    73
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    74
Other widgets
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    75
'''''''''''''
6880
4be32427b2b9 [book] fixes some references and other doc construction pbs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6682
diff changeset
    76
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    77
.. autoclass:: cubicweb.web.formwidgets.PasswordInput
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    78
.. autoclass:: cubicweb.web.formwidgets.IntervalWidget
8029
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
    79
.. autoclass:: cubicweb.web.formwidgets.BitSelect
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    80
.. autoclass:: cubicweb.web.formwidgets.HorizontalLayoutWidget
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    81
.. autoclass:: cubicweb.web.formwidgets.EditableURLWidget
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    82
6880
4be32427b2b9 [book] fixes some references and other doc construction pbs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6682
diff changeset
    83
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    84
Form controls
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    85
'''''''''''''
6880
4be32427b2b9 [book] fixes some references and other doc construction pbs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6682
diff changeset
    86
4be32427b2b9 [book] fixes some references and other doc construction pbs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6682
diff changeset
    87
Those classes are not proper widget (they are not associated to field) but are
4be32427b2b9 [book] fixes some references and other doc construction pbs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6682
diff changeset
    88
used as form controls. Their API is similar to widgets except that `field`
4be32427b2b9 [book] fixes some references and other doc construction pbs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6682
diff changeset
    89
argument given to :meth:`render` will be `None`.
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    90
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    91
.. autoclass:: cubicweb.web.formwidgets.Button
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    92
.. autoclass:: cubicweb.web.formwidgets.SubmitButton
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    93
.. autoclass:: cubicweb.web.formwidgets.ResetButton
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    94
.. autoclass:: cubicweb.web.formwidgets.ImgButton
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    95
"""
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    96
__docformat__ = "restructuredtext en"
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    97
8719
539ed3fb27cb [towards py3k] import reduce() from functools (part of #2711624)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 8695
diff changeset
    98
from functools import reduce
1096
e1fe98850bf7 cleanup
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
    99
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
   100
from warnings import warn
1096
e1fe98850bf7 cleanup
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   101
10717
46f934bebd85 [py3k] unicode → six.text_type
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10612
diff changeset
   102
from six import text_type, string_types
10612
84468b90e9c1 [py3k] basestring → six.string_types
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10522
diff changeset
   103
4160
3fbdeef9a610 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4159
diff changeset
   104
from logilab.mtconverter import xml_escape
3fbdeef9a610 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4159
diff changeset
   105
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
   106
from logilab.common.date import todatetime
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   107
4481
56440a1f816a hidden usage of datetime function which has been moved to lgc
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4392
diff changeset
   108
from cubicweb import tags, uilib
6449
613d83588998 [formwidgets] rewrite autocomplete cw widgets to get rid of div-style declaration API
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6448
diff changeset
   109
from cubicweb.utils import json_dumps
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
   110
from cubicweb.web import stdmsgs, INTERNAL_FIELD_VALUE, ProcessFormError
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   111
4583
356f08325072 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4550
diff changeset
   112
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   113
class FieldWidget(object):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   114
    """The abstract base class for widgets.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   115
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   116
    **Attributes**
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   117
7879
9aae456abab5 [pylint] fix pylint detected errors and tweak it so that pylint -E will be much less verbose next time (+ update some copyrights on the way)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7453
diff changeset
   118
    Here are standard attributes of a widget, that may be set on concrete class
9aae456abab5 [pylint] fix pylint detected errors and tweak it so that pylint -E will be much less verbose next time (+ update some copyrights on the way)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7453
diff changeset
   119
    to override default behaviours:
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   120
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   121
    :attr:`needs_js`
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   122
       list of javascript files needed by the widget.
6880
4be32427b2b9 [book] fixes some references and other doc construction pbs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6682
diff changeset
   123
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   124
    :attr:`needs_css`
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   125
       list of css files needed by the widget.
6880
4be32427b2b9 [book] fixes some references and other doc construction pbs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6682
diff changeset
   126
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   127
    :attr:`setdomid`
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   128
       flag telling if HTML DOM identifier should be set on input.
6880
4be32427b2b9 [book] fixes some references and other doc construction pbs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6682
diff changeset
   129
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   130
    :attr:`settabindex`
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   131
       flag telling if HTML tabindex attribute of inputs should be set.
6880
4be32427b2b9 [book] fixes some references and other doc construction pbs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6682
diff changeset
   132
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   133
    :attr:`suffix`
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   134
       string to use a suffix when generating input, to ease usage as a
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   135
       sub-widgets (eg widget used by another widget)
6880
4be32427b2b9 [book] fixes some references and other doc construction pbs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6682
diff changeset
   136
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   137
    :attr:`vocabulary_widget`
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   138
       flag telling if this widget expect a vocabulary
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   139
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   140
    Also, widget instances takes as first argument a `attrs` dictionary which
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   141
    will be stored in the attribute of the same name. It contains HTML
7879
9aae456abab5 [pylint] fix pylint detected errors and tweak it so that pylint -E will be much less verbose next time (+ update some copyrights on the way)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7453
diff changeset
   142
    attributes that should be set in the widget's input tag (though concrete
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   143
    classes may ignore it).
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   144
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   145
    .. currentmodule:: cubicweb.web.formwidgets
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   146
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   147
    **Form generation methods**
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   148
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   149
    .. automethod:: render
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   150
    .. automethod:: _render
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   151
    .. automethod:: values
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   152
    .. automethod:: attributes
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   153
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   154
    **Post handling methods**
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   155
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   156
    .. automethod:: process_field_data
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   157
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   158
    """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   159
    needs_js = ()
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   160
    needs_css = ()
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   161
    setdomid = True
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   162
    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
   163
    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
   164
    # 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
   165
    vocabulary_widget = False
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   166
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
   167
    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
   168
        if attrs is None:
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   169
            attrs = {}
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   170
        self.attrs = attrs
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   171
        if setdomid is not None:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   172
            # override class's default value
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   173
            self.setdomid = setdomid
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   174
        if settabindex is not None:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   175
            # override class's default value
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   176
            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
   177
        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
   178
            self.suffix = suffix
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   179
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   180
    def add_media(self, form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   181
        """adds media (CSS & JS) required by this widget"""
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   182
        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
   183
            form._cw.add_js(self.needs_js)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   184
        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
   185
            form._cw.add_css(self.needs_css)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   186
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   187
    def render(self, form, field, renderer=None):
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   188
        """Called to render the widget for the given `field` in the given
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   189
        `form`.  Return a unicode string containing the HTML snippet.
4372
0c44af150a49 introduce a default render implementation on the base widget, which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4371
diff changeset
   190
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   191
        You will usually prefer to override the :meth:`_render` method so you
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   192
        don't have to handle addition of needed javascript / css files.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   193
        """
4372
0c44af150a49 introduce a default render implementation on the base widget, which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4371
diff changeset
   194
        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
   195
        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
   196
0c44af150a49 introduce a default render implementation on the base widget, which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4371
diff changeset
   197
    def _render(self, form, field, renderer):
7879
9aae456abab5 [pylint] fix pylint detected errors and tweak it so that pylint -E will be much less verbose next time (+ update some copyrights on the way)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7453
diff changeset
   198
        """This is the method you have to implement in concrete widget classes.
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   199
        """
4372
0c44af150a49 introduce a default render implementation on the base widget, which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4371
diff changeset
   200
        raise NotImplementedError()
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   201
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
   202
    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
   203
        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
   204
5367
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5111
diff changeset
   205
    def attributes(self, form, field):
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5111
diff changeset
   206
        """Return HTML attributes for the widget, automatically setting DOM
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5111
diff changeset
   207
        identifier and tabindex when desired (see :attr:`setdomid` and
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5111
diff changeset
   208
        :attr:`settabindex` attributes)
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
   209
        """
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
   210
        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
   211
        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
   212
            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
   213
        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
   214
            attrs['tabindex'] = form._cw.next_tabindex()
9718
927d035b6921 [formfields] Handle 'placeholder' attribute for text and textarea
Christophe de Vienne <christophe@unlish.com>
parents: 9716
diff changeset
   215
        if 'placeholder' in attrs:
927d035b6921 [formfields] Handle 'placeholder' attribute for text and textarea
Christophe de Vienne <christophe@unlish.com>
parents: 9716
diff changeset
   216
            attrs['placeholder'] = form._cw._(attrs['placeholder'])
5367
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5111
diff changeset
   217
        return attrs
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
   218
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
   219
    def values(self, form, field):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   220
        """Return the current *string* values (i.e. for display in an HTML
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   221
        string) for the given field. This method returns a list of values since
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   222
        it's suitable for all kind of widgets, some of them taking multiple
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   223
        values, but you'll get a single value in the list in most cases.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   224
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   225
        Those values are searched in:
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   226
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   227
        1. previously submitted form values if any (on validation error)
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   228
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   229
        2. req.form (specified using request parameters)
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   230
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   231
        3. extra form values given to form.render call (specified the code
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   232
           generating the form)
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   233
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   234
        4. field's typed value (returned by its
6880
4be32427b2b9 [book] fixes some references and other doc construction pbs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6682
diff changeset
   235
           :meth:`~cubicweb.web.formfields.Field.typed_value` method)
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   236
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   237
        Values found in 1. and 2. are expected te be already some 'display
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   238
        value' (eg a string) while those found in 3. and 4. are expected to be
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   239
        correctly typed value.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   240
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   241
        3 and 4 are handle by the :meth:`typed_value` method to ease reuse in
7879
9aae456abab5 [pylint] fix pylint detected errors and tweak it so that pylint -E will be much less verbose next time (+ update some copyrights on the way)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7453
diff changeset
   242
        concrete classes.
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   243
        """
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
   244
        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
   245
        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
   246
            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
   247
            # 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
   248
            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
   249
                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
   250
            # 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
   251
            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
   252
                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
   253
            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
   254
                # 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
   255
                # 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
   256
                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
   257
        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
   258
            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
   259
            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
   260
                values = self.format_value(form, field, values)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   261
        if not isinstance(values, (tuple, list)):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   262
            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
   263
        return values
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   264
4660
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   265
    def typed_value(self, form, field):
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   266
        """return field's *typed* value specified in:
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   267
        3. extra form values given to render()
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   268
        4. field's typed value
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   269
        """
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   270
        qname = field.input_name(form)
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   271
        for key in ((field, form), qname):
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   272
            try:
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   273
                return form.formvalues[key]
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   274
            except KeyError:
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   275
                continue
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   276
        if field.name != qname and field.name in form.formvalues:
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   277
            return form.formvalues[field.name]
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   278
        return field.typed_value(form)
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   279
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
   280
    def process_field_data(self, form, field):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   281
        """Return process posted value(s) for widget and return something
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   282
        understandable by the associated `field`. That value may be correctly
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   283
        typed or a string that the field may parse.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   284
        """
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   285
        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
   286
        val = posted.get(field.input_name(form, self.suffix))
10612
84468b90e9c1 [py3k] basestring → six.string_types
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10522
diff changeset
   287
        if isinstance(val, string_types):
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
   288
            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
   289
        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
   290
5367
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5111
diff changeset
   291
    # XXX deprecates
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5111
diff changeset
   292
    def values_and_attributes(self, form, field):
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5111
diff changeset
   293
        return self.values(form, field), self.attributes(form, field)
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5111
diff changeset
   294
1096
e1fe98850bf7 cleanup
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   295
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   296
class Input(FieldWidget):
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   297
    """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
   298
    type = None
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   299
4372
0c44af150a49 introduce a default render implementation on the base widget, which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4371
diff changeset
   300
    def _render(self, form, field, renderer):
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   301
        """render the widget for the given `field` of `form`.
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   302
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   303
        Generate one <input> tag for each field's value
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   304
        """
4163
b2747ed057e6 substitute _render_attrs by values_and_attributes method, keeping bw compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   305
        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
   306
        # 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
   307
        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
   308
            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
   309
        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
   310
                             type=self.type, value=value, **attrs)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   311
                  for value in values]
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   312
        return u'\n'.join(inputs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   313
1096
e1fe98850bf7 cleanup
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   314
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   315
# basic html widgets ###########################################################
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   316
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   317
class TextInput(Input):
9701
46c8d8701240 an unicode string -> a unicode string
Rémi Cardona <remi.cardona@logilab.fr>
parents: 9700
diff changeset
   318
    """Simple <input type='text'>, will return a unicode string."""
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   319
    type = 'text'
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   320
1096
e1fe98850bf7 cleanup
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   321
9716
c44224387028 [widget] Addition of EmailInput
Alain Begey <alain@unlish.com>
parents: 9377
diff changeset
   322
class EmailInput(Input):
c44224387028 [widget] Addition of EmailInput
Alain Begey <alain@unlish.com>
parents: 9377
diff changeset
   323
    """Simple <input type='email'>, will return a unicode string."""
c44224387028 [widget] Addition of EmailInput
Alain Begey <alain@unlish.com>
parents: 9377
diff changeset
   324
    type = 'email'
c44224387028 [widget] Addition of EmailInput
Alain Begey <alain@unlish.com>
parents: 9377
diff changeset
   325
c44224387028 [widget] Addition of EmailInput
Alain Begey <alain@unlish.com>
parents: 9377
diff changeset
   326
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   327
class PasswordSingleInput(Input):
9703
79ad734ca4d3 an utf-8 -> a utf-8
Rémi Cardona <remi.cardona@logilab.fr>
parents: 9701
diff changeset
   328
    """Simple <input type='password'>, will return a utf-8 encoded string.
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   329
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   330
    You may prefer using the :class:`~cubicweb.web.formwidgets.PasswordInput`
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   331
    widget which handles password confirmation.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   332
    """
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   333
    type = 'password'
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   334
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   335
    def process_field_data(self, form, field):
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   336
        value = super(PasswordSingleInput, self).process_field_data(form, field)
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   337
        if value is not None:
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   338
            return value.encode('utf-8')
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   339
        return value
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   340
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   341
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   342
class PasswordInput(Input):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   343
    """<input type='password'> and a confirmation input. Form processing will
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   344
    fail if password and confirmation differs, else it will return the password
9703
79ad734ca4d3 an utf-8 -> a utf-8
Rémi Cardona <remi.cardona@logilab.fr>
parents: 9701
diff changeset
   345
    as a utf-8 encoded string.
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   346
    """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   347
    type = 'password'
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   348
4372
0c44af150a49 introduce a default render implementation on the base widget, which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4371
diff changeset
   349
    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
   350
        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
   351
        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
   352
        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
   353
        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
   354
        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
   355
                             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
   356
                  '<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
   357
                  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
   358
                             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
   359
                  '&#160;', tags.span(form._cw._('confirm password'),
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   360
                                      **{'class': 'emphasis'})]
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   361
        return u'\n'.join(inputs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   362
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
   363
    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
   364
        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
   365
        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
   366
        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
   367
            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
   368
                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
   369
            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
   370
        raise ProcessFormError(form._cw._("password and confirmation don't match"))
1096
e1fe98850bf7 cleanup
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   371
e1fe98850bf7 cleanup
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   372
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   373
class FileInput(Input):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   374
    """Simple <input type='file'>, will return a tuple (name, stream) where
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   375
    name is the posted file name and stream a file like object containing the
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   376
    posted file data.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   377
    """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   378
    type = 'file'
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   379
5367
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5111
diff changeset
   380
    def values(self, form, field):
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   381
        # ignore value which makes no sense here (XXX even on form validation error?)
5367
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5111
diff changeset
   382
        return ('',)
1096
e1fe98850bf7 cleanup
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   383
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   384
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   385
class HiddenInput(Input):
9701
46c8d8701240 an unicode string -> a unicode string
Rémi Cardona <remi.cardona@logilab.fr>
parents: 9700
diff changeset
   386
    """Simple <input type='hidden'> for hidden value, will return a unicode
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   387
    string.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   388
    """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   389
    type = 'hidden'
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   390
    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
   391
    settabindex = False
1096
e1fe98850bf7 cleanup
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   392
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   393
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   394
class ButtonInput(Input):
9701
46c8d8701240 an unicode string -> a unicode string
Rémi Cardona <remi.cardona@logilab.fr>
parents: 9700
diff changeset
   395
    """Simple <input type='button'>, will return a unicode string.
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   396
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   397
    If you want a global form button, look at the :class:`Button`,
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   398
    :class:`SubmitButton`, :class:`ResetButton` and :class:`ImgButton` below.
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   399
    """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   400
    type = 'button'
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   401
1096
e1fe98850bf7 cleanup
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   402
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   403
class TextArea(FieldWidget):
9701
46c8d8701240 an unicode string -> a unicode string
Rémi Cardona <remi.cardona@logilab.fr>
parents: 9700
diff changeset
   404
    """Simple <textarea>, will return a unicode string."""
10404
797db633d60c [formwidgets] move TextArea constants to the class level
Aurelien Campeas <aurelien.campeas@pythonian.fr>
parents: 9821
diff changeset
   405
    _minrows = 2
797db633d60c [formwidgets] move TextArea constants to the class level
Aurelien Campeas <aurelien.campeas@pythonian.fr>
parents: 9821
diff changeset
   406
    _maxrows = 15
797db633d60c [formwidgets] move TextArea constants to the class level
Aurelien Campeas <aurelien.campeas@pythonian.fr>
parents: 9821
diff changeset
   407
    _columns = 80
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
   408
4372
0c44af150a49 introduce a default render implementation on the base widget, which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4371
diff changeset
   409
    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
   410
        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
   411
        attrs.setdefault('onkeyup', 'autogrow(this)')
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   412
        if not values:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   413
            value = u''
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   414
        elif len(values) == 1:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   415
            value = values[0]
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   416
        else:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   417
            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
   418
        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
   419
        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
   420
        for line in lines:
10783
02cc22d7d339 [web] integer division
Julien Cristau <julien.cristau@logilab.fr>
parents: 10771
diff changeset
   421
            linecount += len(line) // self._columns
10404
797db633d60c [formwidgets] move TextArea constants to the class level
Aurelien Campeas <aurelien.campeas@pythonian.fr>
parents: 9821
diff changeset
   422
        attrs.setdefault('cols', self._columns)
797db633d60c [formwidgets] move TextArea constants to the class level
Aurelien Campeas <aurelien.campeas@pythonian.fr>
parents: 9821
diff changeset
   423
        attrs.setdefault('rows', min(self._maxrows, linecount + self._minrows))
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
   424
        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
   425
                             **attrs)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   426
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   427
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   428
class FCKEditor(TextArea):
9701
46c8d8701240 an unicode string -> a unicode string
Rémi Cardona <remi.cardona@logilab.fr>
parents: 9700
diff changeset
   429
    """FCKEditor enabled <textarea>, will return a unicode string containing
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   430
    HTML formated text.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   431
    """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   432
    def __init__(self, *args, **kwargs):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   433
        super(FCKEditor, self).__init__(*args, **kwargs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   434
        self.attrs['cubicweb:type'] = 'wysiwyg'
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   435
4372
0c44af150a49 introduce a default render implementation on the base widget, which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4371
diff changeset
   436
    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
   437
        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
   438
        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
   439
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   440
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   441
class Select(FieldWidget):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   442
    """Simple <select>, for field having a specific vocabulary. Will return
9701
46c8d8701240 an unicode string -> a unicode string
Rémi Cardona <remi.cardona@logilab.fr>
parents: 9700
diff changeset
   443
    a unicode string, or a list of unicode strings.
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   444
    """
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
   445
    vocabulary_widget = True
8193
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   446
    default_size = 10
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
   447
4975
35b0dd80dc06 [widget] allow kwargs passed to Select widget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4901
diff changeset
   448
    def __init__(self, attrs=None, multiple=False, **kwargs):
35b0dd80dc06 [widget] allow kwargs passed to Select widget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4901
diff changeset
   449
        super(Select, self).__init__(attrs, **kwargs)
1541
ddddbb748355 [widgets] an option for Select to show sorted content
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 1538
diff changeset
   450
        self._multiple = multiple
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   451
5367
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5111
diff changeset
   452
    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
   453
        curvalues, attrs = self.values_and_attributes(form, field)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   454
        options = []
1771
bb9538d91465 fix <optgroup> tag cannot be empty according to DTD
Florent <florent@secondweb.fr>
parents: 1768
diff changeset
   455
        optgroup_opened = False
7453
84046395d2cd Fix name error introduced in c21d845836e4
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7450
diff changeset
   456
        vocab = field.vocabulary(form)
84046395d2cd Fix name error introduced in c21d845836e4
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7450
diff changeset
   457
        for option in vocab:
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
   458
            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
   459
                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
   460
            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
   461
                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
   462
                oattrs = {}
1336
2e552353c42a insert an optgroup as separator on None values
sylvain.thenault@logilab.fr
parents: 1330
diff changeset
   463
            if value is None:
2e552353c42a insert an optgroup as separator on None values
sylvain.thenault@logilab.fr
parents: 1330
diff changeset
   464
                # handle separator
1771
bb9538d91465 fix <optgroup> tag cannot be empty according to DTD
Florent <florent@secondweb.fr>
parents: 1768
diff changeset
   465
                if optgroup_opened:
bb9538d91465 fix <optgroup> tag cannot be empty according to DTD
Florent <florent@secondweb.fr>
parents: 1768
diff changeset
   466
                    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
   467
                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
   468
                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
   469
                optgroup_opened = True
8029
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   470
            elif self.value_selected(value, 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
   471
                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
   472
                                           selected='selected', **oattrs))
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   473
            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
   474
                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
   475
        if optgroup_opened:
bb9538d91465 fix <optgroup> tag cannot be empty according to DTD
Florent <florent@secondweb.fr>
parents: 1768
diff changeset
   476
            options.append(u'</optgroup>')
7450
c21d845836e4 [formwidgets] make the select size a class attribute (more easily tuned)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7411
diff changeset
   477
        if not 'size' in attrs:
c21d845836e4 [formwidgets] make the select size a class attribute (more easily tuned)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7411
diff changeset
   478
            if self._multiple:
10717
46f934bebd85 [py3k] unicode → six.text_type
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10612
diff changeset
   479
                size = text_type(min(self.default_size, len(vocab) or 1))
7450
c21d845836e4 [formwidgets] make the select size a class attribute (more easily tuned)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7411
diff changeset
   480
            else:
c21d845836e4 [formwidgets] make the select size a class attribute (more easily tuned)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7411
diff changeset
   481
                size = u'1'
c21d845836e4 [formwidgets] make the select size a class attribute (more easily tuned)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7411
diff changeset
   482
            attrs['size'] = size
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
   483
        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
   484
                           multiple=self._multiple, options=options, **attrs)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   485
8029
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   486
    def value_selected(self, value, curvalues):
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   487
        return value in curvalues
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   488
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   489
8193
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   490
class InOutWidget(Select):
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   491
    needs_js = ('cubicweb.widgets.js', )
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   492
    default_size = 10
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   493
    template = """
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   494
<table id="%(widgetid)s">
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   495
  <tr>
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   496
    <td>%(inoutinput)s</td>
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   497
    <td><div style="margin-bottom:3px">%(addinput)s</div>
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   498
        <div>%(removeinput)s</div>
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   499
    </td>
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   500
    <td>%(resinput)s</td>
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   501
  </tr>
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   502
</table>
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   503
"""
8936
010adc548b97 [form] remove hard coded id
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8732
diff changeset
   504
    add_button = ('<input type="button" class="wdgButton cwinoutadd" '
8193
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   505
                  'value="&gt;&gt;" size="10" />')
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   506
    remove_button = ('<input type="button" class="wdgButton cwinoutremove" '
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   507
                     'value="&lt;&lt;" size="10" />')
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   508
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   509
    def __init__(self, *args, **kwargs):
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   510
        super(InOutWidget, self).__init__(*args, **kwargs)
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   511
        self._multiple = True
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   512
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   513
    def render_select(self, form, field, name, selected=False):
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   514
        values, attrs = self.values_and_attributes(form, field)
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   515
        options = []
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   516
        inputs = []
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   517
        for option in field.vocabulary(form):
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   518
            try:
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   519
                label, value, _oattrs = option
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   520
            except ValueError:
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   521
                label, value = option
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   522
            if selected:
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   523
                # add values
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   524
                if value in values:
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   525
                    options.append(tags.option(label, value=value))
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   526
                    # add hidden inputs
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   527
                    inputs.append(tags.input(value=value,
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   528
                                             name=field.dom_id(form),
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   529
                                             type="hidden"))
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   530
            else:
9377
4e0d8f06efbc [js/widgets] fix the InOut widget with modern jQuery versions
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9255
diff changeset
   531
                if value not in values:
4e0d8f06efbc [js/widgets] fix the InOut widget with modern jQuery versions
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9255
diff changeset
   532
                    options.append(tags.option(label, value=value))
8193
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   533
        if 'size' not in attrs:
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   534
            attrs['size'] = self.default_size
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   535
        if 'id' in attrs :
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   536
            attrs.pop('id')
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   537
        return tags.select(name=name, multiple=self._multiple, id=name,
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   538
                           options=options, **attrs) + '\n'.join(inputs)
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   539
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   540
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   541
    def _render(self, form, field, renderer):
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   542
        domid = field.dom_id(form)
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   543
        jsnodes = {'widgetid': domid,
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   544
                   'from': 'from_' + domid,
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   545
                   'to': 'to_' + domid}
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   546
        form._cw.add_onload(u'$(cw.jqNode("%s")).cwinoutwidget("%s", "%s");'
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   547
                            % (jsnodes['widgetid'], jsnodes['from'], jsnodes['to']))
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   548
        field.required = True
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   549
        return (self.template %
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   550
                {'widgetid': jsnodes['widgetid'],
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   551
                 # helpinfo select tag
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   552
                 'inoutinput' : self.render_select(form, field, jsnodes['from']),
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   553
                 # select tag with resultats
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   554
                 'resinput' : self.render_select(form, field, jsnodes['to'], selected=True),
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   555
                 'addinput' : self.add_button % jsnodes,
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   556
                 'removeinput': self.remove_button % jsnodes
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   557
                 })
0c64d6b75303 [web/formwidgets] make default_size a tunable, fix code layout (closes #2165936)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
   558
9222
ec65ca70aac9 [date picker widgets] use bare jquery expression rather than jqNode
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9134
diff changeset
   559
8029
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   560
class BitSelect(Select):
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   561
    """Select widget for IntField using a vocabulary with bit masks as values.
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   562
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   563
    See also :class:`~cubicweb.web.facet.BitFieldFacet`.
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   564
    """
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   565
    def __init__(self, attrs=None, multiple=True, **kwargs):
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   566
        super(BitSelect, self).__init__(attrs, multiple=multiple, **kwargs)
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   567
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   568
    def value_selected(self, value, curvalues):
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   569
        mask = reduce(lambda x, y: int(x) | int(y), curvalues, 0)
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   570
        return int(value) & mask
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   571
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   572
    def process_field_data(self, form, field):
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   573
        """Return process posted value(s) for widget and return something
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   574
        understandable by the associated `field`. That value may be correctly
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   575
        typed or a string that the field may parse.
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   576
        """
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   577
        val = super(BitSelect, self).process_field_data(form, field)
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   578
        if isinstance(val, list):
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   579
            val = reduce(lambda x, y: int(x) | int(y), val, 0)
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   580
        elif val:
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   581
            val = int(val)
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   582
        else:
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   583
            val = 0
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   584
        return val
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   585
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   586
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   587
class CheckBox(Input):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   588
    """Simple <input type='checkbox'>, for field having a specific
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   589
    vocabulary. One input will be generated for each possible value.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   590
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   591
    You can specify separator using the `separator` constructor argument, by
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   592
    default <br/> is used.
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   593
    """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   594
    type = 'checkbox'
7231
18bcb98d129a [widgets] handle no value label for tristate radios, put default separator on class for easier redefinition - closes #1624839
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7115
diff changeset
   595
    default_separator = u'<br/>\n'
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
   596
    vocabulary_widget = True
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   597
7231
18bcb98d129a [widgets] handle no value label for tristate radios, put default separator on class for easier redefinition - closes #1624839
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7115
diff changeset
   598
    def __init__(self, attrs=None, separator=None, **kwargs):
5367
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5111
diff changeset
   599
        super(CheckBox, self).__init__(attrs, **kwargs)
7231
18bcb98d129a [widgets] handle no value label for tristate radios, put default separator on class for easier redefinition - closes #1624839
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7115
diff changeset
   600
        self.separator = separator or self.default_separator
5367
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5111
diff changeset
   601
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5111
diff changeset
   602
    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
   603
        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
   604
        domid = attrs.pop('id', None)
9255
46f41c3e1443 remove 3.8 bw compat
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9247
diff changeset
   605
        sep = self.separator
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   606
        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
   607
        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
   608
            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
   609
                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
   610
            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
   611
                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
   612
                oattrs = {}
1367
01bb5b727fe3 set dom id on the first input of radio choices
sylvain.thenault@logilab.fr
parents: 1359
diff changeset
   613
            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
   614
            iattrs.update(oattrs)
1367
01bb5b727fe3 set dom id on the first input of radio choices
sylvain.thenault@logilab.fr
parents: 1359
diff changeset
   615
            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
   616
                iattrs.setdefault('id', domid)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   617
            if value in curvalues:
1367
01bb5b727fe3 set dom id on the first input of radio choices
sylvain.thenault@logilab.fr
parents: 1359
diff changeset
   618
                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
   619
            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
   620
                             type=self.type, value=value, **iattrs)
10902
41bd01ebebb4 [web] Add a <label> around choices on CheckBox and Radio form widgets
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10901
diff changeset
   621
            options.append(u'<label>%s&#160;%s</label>' % (tag, xml_escape(label)))
2519
ac1a869e1e93 nicer checkbox widget implementation, avoid extra <br/> at the end
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2518
diff changeset
   622
        return sep.join(options)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   623
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   624
1832
3384264d25cc fix CheckBox multiple dom id and refactor with Radio
Florent <florent@secondweb.fr>
parents: 1771
diff changeset
   625
class Radio(CheckBox):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   626
    """Simle <input type='radio'>, for field having a specific vocabulary. One
1832
3384264d25cc fix CheckBox multiple dom id and refactor with Radio
Florent <florent@secondweb.fr>
parents: 1771
diff changeset
   627
    input will be generated for each possible value.
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   628
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   629
    You can specify separator using the `separator` constructor argument, by
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   630
    default <br/> is used.
1832
3384264d25cc fix CheckBox multiple dom id and refactor with Radio
Florent <florent@secondweb.fr>
parents: 1771
diff changeset
   631
    """
3384264d25cc fix CheckBox multiple dom id and refactor with Radio
Florent <florent@secondweb.fr>
parents: 1771
diff changeset
   632
    type = 'radio'
5384
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
   633
2523
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   634
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   635
# javascript widgets ###########################################################
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   636
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   637
class DateTimePicker(TextInput):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   638
    """<input type='text'> + javascript date/time picker for date or datetime
9701
46c8d8701240 an unicode string -> a unicode string
Rémi Cardona <remi.cardona@logilab.fr>
parents: 9700
diff changeset
   639
    fields. Will return the date or datetime as a unicode string.
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   640
    """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   641
    monthnames = ('january', 'february', 'march', 'april',
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   642
                  'may', 'june', 'july', 'august',
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   643
                  'september', 'october', 'november', 'december')
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   644
    daynames = ('monday', 'tuesday', 'wednesday', 'thursday',
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   645
                'friday', 'saturday', 'sunday')
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   646
1311
4cc6e2723dc7 move ajax.js to base form class
sylvain.thenault@logilab.fr
parents: 1304
diff changeset
   647
    needs_js = ('cubicweb.calendar.js',)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   648
    needs_css = ('cubicweb.calendar_popup.css',)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   649
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   650
    @classmethod
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   651
    def add_localized_infos(cls, req):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   652
        """inserts JS variables defining localized months and days"""
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   653
        _ = req._
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   654
        monthnames = [_(mname) for mname in cls.monthnames]
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   655
        daynames = [_(dname) for dname in cls.daynames]
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   656
        req.html_headers.define_var('MONTHNAMES', monthnames)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   657
        req.html_headers.define_var('DAYNAMES', daynames)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   658
5367
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5111
diff changeset
   659
    def _render(self, form, field, renderer):
5383
fbe7416104c6 [widgets] fix super calls, bug introduced in 5367:4176a50c81c9
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5377
diff changeset
   660
        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
   661
        self.add_localized_infos(form._cw)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   662
        cal_button = self._render_calendar_popup(form, field)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   663
        return txtwidget + cal_button
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   664
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   665
    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
   666
        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
   667
        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
   668
            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
   669
        inputid = field.dom_id(form)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   670
        helperid = '%shelper' % inputid
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   671
        year, month = value.year, value.month
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   672
        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
   673
<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
   674
                % (helperid, inputid, year, month,
5467
57372dbfd114 [https] fix resource urls in https version of a site: should use the https version as well to avoid warnings from the nrowser
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5453
diff changeset
   675
                   form._cw.uiprops['CALENDAR_ICON'],
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   676
                   form._cw._('calendar'), helperid) )
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   677
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   678
4373
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   679
class JQueryDatePicker(FieldWidget):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   680
    """Use jquery.ui.datepicker to define a date picker. Will return the date as
9701
46c8d8701240 an unicode string -> a unicode string
Rémi Cardona <remi.cardona@logilab.fr>
parents: 9700
diff changeset
   681
    a unicode string.
11048
96d57cb8b644 [views] improve JQueryDatePicker so that a date field can be defined as the min/max of an other one
Erica Marco <erica.marco@logilab.fr>
parents: 10907
diff changeset
   682
96d57cb8b644 [views] improve JQueryDatePicker so that a date field can be defined as the min/max of an other one
Erica Marco <erica.marco@logilab.fr>
parents: 10907
diff changeset
   683
    You can couple DatePickers by using the min_of and/or max_of parameters.
96d57cb8b644 [views] improve JQueryDatePicker so that a date field can be defined as the min/max of an other one
Erica Marco <erica.marco@logilab.fr>
parents: 10907
diff changeset
   684
    The DatePicker identified by the value of min_of(/max_of) will force the user to
96d57cb8b644 [views] improve JQueryDatePicker so that a date field can be defined as the min/max of an other one
Erica Marco <erica.marco@logilab.fr>
parents: 10907
diff changeset
   685
    choose a date anterior(/posterior) to this DatePicker.
96d57cb8b644 [views] improve JQueryDatePicker so that a date field can be defined as the min/max of an other one
Erica Marco <erica.marco@logilab.fr>
parents: 10907
diff changeset
   686
96d57cb8b644 [views] improve JQueryDatePicker so that a date field can be defined as the min/max of an other one
Erica Marco <erica.marco@logilab.fr>
parents: 10907
diff changeset
   687
    example:
96d57cb8b644 [views] improve JQueryDatePicker so that a date field can be defined as the min/max of an other one
Erica Marco <erica.marco@logilab.fr>
parents: 10907
diff changeset
   688
    start and end are two JQueryDatePicker and start must always be before end
96d57cb8b644 [views] improve JQueryDatePicker so that a date field can be defined as the min/max of an other one
Erica Marco <erica.marco@logilab.fr>
parents: 10907
diff changeset
   689
        affk.set_field_kwargs(etype, 'start_date', widget=JQueryDatePicker(min_of='end_date'))
96d57cb8b644 [views] improve JQueryDatePicker so that a date field can be defined as the min/max of an other one
Erica Marco <erica.marco@logilab.fr>
parents: 10907
diff changeset
   690
        affk.set_field_kwargs(etype, 'end_date', widget=JQueryDatePicker(max_of='start_date'))
96d57cb8b644 [views] improve JQueryDatePicker so that a date field can be defined as the min/max of an other one
Erica Marco <erica.marco@logilab.fr>
parents: 10907
diff changeset
   691
    That way, on change of end(/start) value a new max(/min) will be set for start(/end)
96d57cb8b644 [views] improve JQueryDatePicker so that a date field can be defined as the min/max of an other one
Erica Marco <erica.marco@logilab.fr>
parents: 10907
diff changeset
   692
    The invalid dates will be gray colored in the datepicker
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   693
    """
4373
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   694
    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
   695
    needs_css = ('jquery.ui.css',)
8471
05992aa3fc0d [form widgets] fix JQueryDatePicker and JQueryTimePicker so they consider widget custom attributes. Closes #2423720
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8193
diff changeset
   696
    default_size = 10
4373
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   697
11048
96d57cb8b644 [views] improve JQueryDatePicker so that a date field can be defined as the min/max of an other one
Erica Marco <erica.marco@logilab.fr>
parents: 10907
diff changeset
   698
    def __init__(self, datestr=None, min_of=None, max_of=None, **kwargs):
4373
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   699
        super(JQueryDatePicker, self).__init__(**kwargs)
11048
96d57cb8b644 [views] improve JQueryDatePicker so that a date field can be defined as the min/max of an other one
Erica Marco <erica.marco@logilab.fr>
parents: 10907
diff changeset
   700
        self.min_of = min_of
96d57cb8b644 [views] improve JQueryDatePicker so that a date field can be defined as the min/max of an other one
Erica Marco <erica.marco@logilab.fr>
parents: 10907
diff changeset
   701
        self.max_of = max_of
8471
05992aa3fc0d [form widgets] fix JQueryDatePicker and JQueryTimePicker so they consider widget custom attributes. Closes #2423720
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8193
diff changeset
   702
        self.value = datestr
4373
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   703
11048
96d57cb8b644 [views] improve JQueryDatePicker so that a date field can be defined as the min/max of an other one
Erica Marco <erica.marco@logilab.fr>
parents: 10907
diff changeset
   704
    def attributes(self, form, field):
96d57cb8b644 [views] improve JQueryDatePicker so that a date field can be defined as the min/max of an other one
Erica Marco <erica.marco@logilab.fr>
parents: 10907
diff changeset
   705
        form._cw.add_js('cubicweb.widgets.js')
96d57cb8b644 [views] improve JQueryDatePicker so that a date field can be defined as the min/max of an other one
Erica Marco <erica.marco@logilab.fr>
parents: 10907
diff changeset
   706
        attrs = super(JQueryDatePicker, self).attributes(form, field)
96d57cb8b644 [views] improve JQueryDatePicker so that a date field can be defined as the min/max of an other one
Erica Marco <erica.marco@logilab.fr>
parents: 10907
diff changeset
   707
        if self.max_of:
96d57cb8b644 [views] improve JQueryDatePicker so that a date field can be defined as the min/max of an other one
Erica Marco <erica.marco@logilab.fr>
parents: 10907
diff changeset
   708
            attrs['data-max-of'] = '%s-subject:%s' % (self.max_of, form.edited_entity.eid)
96d57cb8b644 [views] improve JQueryDatePicker so that a date field can be defined as the min/max of an other one
Erica Marco <erica.marco@logilab.fr>
parents: 10907
diff changeset
   709
        if self.min_of:
96d57cb8b644 [views] improve JQueryDatePicker so that a date field can be defined as the min/max of an other one
Erica Marco <erica.marco@logilab.fr>
parents: 10907
diff changeset
   710
            attrs['data-min-of'] = '%s-subject:%s' % (self.min_of, form.edited_entity.eid)
96d57cb8b644 [views] improve JQueryDatePicker so that a date field can be defined as the min/max of an other one
Erica Marco <erica.marco@logilab.fr>
parents: 10907
diff changeset
   711
        return attrs
96d57cb8b644 [views] improve JQueryDatePicker so that a date field can be defined as the min/max of an other one
Erica Marco <erica.marco@logilab.fr>
parents: 10907
diff changeset
   712
4373
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   713
    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
   714
        req = form._cw
6737
de49060d4be3 add localization files for jquery datepicker
Stephanie Marcu <stephanie.marcu@logilab.fr>
parents: 6682
diff changeset
   715
        if req.lang != 'en':
de49060d4be3 add localization files for jquery datepicker
Stephanie Marcu <stephanie.marcu@logilab.fr>
parents: 6682
diff changeset
   716
            req.add_js('jquery.ui.datepicker-%s.js' % req.lang)
4373
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   717
        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
   718
        # 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
   719
        fmt = req.property_value('ui.date-format')
11048
96d57cb8b644 [views] improve JQueryDatePicker so that a date field can be defined as the min/max of an other one
Erica Marco <erica.marco@logilab.fr>
parents: 10907
diff changeset
   720
        picker_fmt = fmt.replace('%Y', 'yy').replace('%m', 'mm').replace('%d', 'dd')
96d57cb8b644 [views] improve JQueryDatePicker so that a date field can be defined as the min/max of an other one
Erica Marco <erica.marco@logilab.fr>
parents: 10907
diff changeset
   721
        max_date = min_date = None
96d57cb8b644 [views] improve JQueryDatePicker so that a date field can be defined as the min/max of an other one
Erica Marco <erica.marco@logilab.fr>
parents: 10907
diff changeset
   722
        if self.min_of:
96d57cb8b644 [views] improve JQueryDatePicker so that a date field can be defined as the min/max of an other one
Erica Marco <erica.marco@logilab.fr>
parents: 10907
diff changeset
   723
            current = getattr(form.edited_entity, self.min_of)
96d57cb8b644 [views] improve JQueryDatePicker so that a date field can be defined as the min/max of an other one
Erica Marco <erica.marco@logilab.fr>
parents: 10907
diff changeset
   724
            if current is not None:
96d57cb8b644 [views] improve JQueryDatePicker so that a date field can be defined as the min/max of an other one
Erica Marco <erica.marco@logilab.fr>
parents: 10907
diff changeset
   725
                max_date = current.strftime(fmt)
96d57cb8b644 [views] improve JQueryDatePicker so that a date field can be defined as the min/max of an other one
Erica Marco <erica.marco@logilab.fr>
parents: 10907
diff changeset
   726
        if self.max_of:
96d57cb8b644 [views] improve JQueryDatePicker so that a date field can be defined as the min/max of an other one
Erica Marco <erica.marco@logilab.fr>
parents: 10907
diff changeset
   727
            current = getattr(form.edited_entity, self.max_of)
96d57cb8b644 [views] improve JQueryDatePicker so that a date field can be defined as the min/max of an other one
Erica Marco <erica.marco@logilab.fr>
parents: 10907
diff changeset
   728
            if current is not None:
96d57cb8b644 [views] improve JQueryDatePicker so that a date field can be defined as the min/max of an other one
Erica Marco <erica.marco@logilab.fr>
parents: 10907
diff changeset
   729
                min_date = current.strftime(fmt)
96d57cb8b644 [views] improve JQueryDatePicker so that a date field can be defined as the min/max of an other one
Erica Marco <erica.marco@logilab.fr>
parents: 10907
diff changeset
   730
        req.add_onload(u'renderJQueryDatePicker("%s", "%s", "%s", %s, %s);'
96d57cb8b644 [views] improve JQueryDatePicker so that a date field can be defined as the min/max of an other one
Erica Marco <erica.marco@logilab.fr>
parents: 10907
diff changeset
   731
                       % (domid, req.uiprops['CALENDAR_ICON'], picker_fmt, json_dumps(min_date),
96d57cb8b644 [views] improve JQueryDatePicker so that a date field can be defined as the min/max of an other one
Erica Marco <erica.marco@logilab.fr>
parents: 10907
diff changeset
   732
                          json_dumps(max_date)))
9223
233e770293a9 [date picker widgets] properly distinguish DOM id and input name. Closes #3096575
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9222
diff changeset
   733
        return self._render_input(form, field)
8471
05992aa3fc0d [form widgets] fix JQueryDatePicker and JQueryTimePicker so they consider widget custom attributes. Closes #2423720
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8193
diff changeset
   734
9223
233e770293a9 [date picker widgets] properly distinguish DOM id and input name. Closes #3096575
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9222
diff changeset
   735
    def _render_input(self, form, field):
8471
05992aa3fc0d [form widgets] fix JQueryDatePicker and JQueryTimePicker so they consider widget custom attributes. Closes #2423720
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8193
diff changeset
   736
        if self.value is None:
4373
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   737
            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
   738
        else:
8471
05992aa3fc0d [form widgets] fix JQueryDatePicker and JQueryTimePicker so they consider widget custom attributes. Closes #2423720
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8193
diff changeset
   739
            value = self.value
05992aa3fc0d [form widgets] fix JQueryDatePicker and JQueryTimePicker so they consider widget custom attributes. Closes #2423720
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8193
diff changeset
   740
        attrs = self.attributes(form, field)
10717
46f934bebd85 [py3k] unicode → six.text_type
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10612
diff changeset
   741
        attrs.setdefault('size', text_type(self.default_size))
9223
233e770293a9 [date picker widgets] properly distinguish DOM id and input name. Closes #3096575
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9222
diff changeset
   742
        return tags.input(name=field.input_name(form, self.suffix),
233e770293a9 [date picker widgets] properly distinguish DOM id and input name. Closes #3096575
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9222
diff changeset
   743
                          value=value, type='text', **attrs)
4373
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   744
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   745
8471
05992aa3fc0d [form widgets] fix JQueryDatePicker and JQueryTimePicker so they consider widget custom attributes. Closes #2423720
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8193
diff changeset
   746
class JQueryTimePicker(JQueryDatePicker):
10222
75d6096216d7 [docstrings] fix project-wide English language mistake
Dimitri Papadopoulos <dimitri.papadopoulos@cea.fr>
parents: 9821
diff changeset
   747
    """Use jquery.timePicker to define a time picker. Will return the time as a
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   748
    unicode string.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   749
    """
4373
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   750
    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
   751
    needs_css = ('jquery.timepicker.css',)
8471
05992aa3fc0d [form widgets] fix JQueryDatePicker and JQueryTimePicker so they consider widget custom attributes. Closes #2423720
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8193
diff changeset
   752
    default_size = 5
4373
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   753
4846
a2fb82770fa6 [widget] allow to specify hour/minute separator on the JQueryTimePicker (vgodard patch)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4660
diff changeset
   754
    def __init__(self, timestr=None, timesteps=30, separator=u':', **kwargs):
8471
05992aa3fc0d [form widgets] fix JQueryDatePicker and JQueryTimePicker so they consider widget custom attributes. Closes #2423720
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8193
diff changeset
   755
        super(JQueryTimePicker, self).__init__(timestr, **kwargs)
4373
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   756
        self.timesteps = timesteps
4846
a2fb82770fa6 [widget] allow to specify hour/minute separator on the JQueryTimePicker (vgodard patch)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4660
diff changeset
   757
        self.separator = separator
4373
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   758
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   759
    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
   760
        domid = field.dom_id(form, self.suffix)
9247
9785c54e707e [date picker] revert #ec65ca70aac9 which breaks the date picker (closes #3182844)
David Douard <david.douard@logilab.fr>
parents: 9223
diff changeset
   761
        form._cw.add_onload(u'cw.jqNode("%s").timePicker({step: %s, separator: "%s"})' % (
8471
05992aa3fc0d [form widgets] fix JQueryDatePicker and JQueryTimePicker so they consider widget custom attributes. Closes #2423720
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8193
diff changeset
   762
                domid, self.timesteps, self.separator))
9223
233e770293a9 [date picker widgets] properly distinguish DOM id and input name. Closes #3096575
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9222
diff changeset
   763
        return self._render_input(form, field)
4373
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   764
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   765
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   766
class JQueryDateTimePicker(FieldWidget):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   767
    """Compound widget using :class:`JQueryDatePicker` and
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   768
    :class:`JQueryTimePicker` widgets to define a date and time picker. Will
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   769
    return the date and time as python datetime instance.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   770
    """
4373
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   771
    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
   772
        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
   773
        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
   774
        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
   775
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   776
    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
   777
        """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
   778
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   779
        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
   780
        """
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   781
        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
   782
        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
   783
        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
   784
        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
   785
            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
   786
            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
   787
        else:
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   788
            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
   789
            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
   790
                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
   791
            else:
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   792
                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
   793
            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
   794
                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
   795
                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
   796
            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
   797
                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
   798
        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
   799
        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
   800
                                      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
   801
        return u'<div id="%s">%s%s</div>' % (field.dom_id(form),
5383
fbe7416104c6 [widgets] fix super calls, bug introduced in 5367:4176a50c81c9
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5377
diff changeset
   802
                                            datepicker.render(form, field, renderer),
fbe7416104c6 [widgets] fix super calls, bug introduced in 5367:4176a50c81c9
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5377
diff changeset
   803
                                            timepicker.render(form, field, renderer))
4373
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   804
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   805
    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
   806
        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
   807
        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
   808
        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
   809
        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
   810
            return None
6260
e06750b556ad raise ProcessFormError when a problem occurs during date / time parsing
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 5909
diff changeset
   811
        try:
e06750b556ad raise ProcessFormError when a problem occurs during date / time parsing
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 5909
diff changeset
   812
            date = todatetime(req.parse_datetime(datestr, 'Date'))
8695
358d8bed9626 [toward-py3k] rewrite to "except AnException as exc:" (part of #2711624)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 8471
diff changeset
   813
        except ValueError as exc:
10717
46f934bebd85 [py3k] unicode → six.text_type
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10612
diff changeset
   814
            raise ProcessFormError(text_type(exc))
4373
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   815
        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
   816
            return date
6260
e06750b556ad raise ProcessFormError when a problem occurs during date / time parsing
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 5909
diff changeset
   817
        try:
e06750b556ad raise ProcessFormError when a problem occurs during date / time parsing
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 5909
diff changeset
   818
            time = req.parse_datetime(timestr, 'Time')
8695
358d8bed9626 [toward-py3k] rewrite to "except AnException as exc:" (part of #2711624)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 8471
diff changeset
   819
        except ValueError as exc:
10717
46f934bebd85 [py3k] unicode → six.text_type
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10612
diff changeset
   820
            raise ProcessFormError(text_type(exc))
4373
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   821
        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
   822
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   823
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   824
# ajax widgets ################################################################
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   825
1337
828bbf500bcc backport AddComboBoxWidget, ajax widgets refactoring
sylvain.thenault@logilab.fr
parents: 1336
diff changeset
   826
def init_ajax_attributes(attrs, wdgtype, loadtype=u'auto'):
828bbf500bcc backport AddComboBoxWidget, ajax widgets refactoring
sylvain.thenault@logilab.fr
parents: 1336
diff changeset
   827
    try:
4597
e872097f2287 use class, not klass, in widget.attrs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4593
diff changeset
   828
        attrs['class'] += u' widget'
1337
828bbf500bcc backport AddComboBoxWidget, ajax widgets refactoring
sylvain.thenault@logilab.fr
parents: 1336
diff changeset
   829
    except KeyError:
4597
e872097f2287 use class, not klass, in widget.attrs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4593
diff changeset
   830
        attrs['class'] = u'widget'
1344
930020cb134b shouldn't use unicode keys in attrs
sylvain.thenault@logilab.fr
parents: 1337
diff changeset
   831
    attrs.setdefault('cubicweb:wdgtype', wdgtype)
930020cb134b shouldn't use unicode keys in attrs
sylvain.thenault@logilab.fr
parents: 1337
diff changeset
   832
    attrs.setdefault('cubicweb:loadtype', loadtype)
1337
828bbf500bcc backport AddComboBoxWidget, ajax widgets refactoring
sylvain.thenault@logilab.fr
parents: 1336
diff changeset
   833
828bbf500bcc backport AddComboBoxWidget, ajax widgets refactoring
sylvain.thenault@logilab.fr
parents: 1336
diff changeset
   834
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   835
class AjaxWidget(FieldWidget):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   836
    """Simple <div> based ajax widget, requiring a `wdgtype` argument telling
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   837
    which javascript widget should be used.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   838
    """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   839
    def __init__(self, wdgtype, inputid=None, **kwargs):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   840
        super(AjaxWidget, self).__init__(**kwargs)
1337
828bbf500bcc backport AddComboBoxWidget, ajax widgets refactoring
sylvain.thenault@logilab.fr
parents: 1336
diff changeset
   841
        init_ajax_attributes(self.attrs, wdgtype)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   842
        if inputid is not None:
1344
930020cb134b shouldn't use unicode keys in attrs
sylvain.thenault@logilab.fr
parents: 1337
diff changeset
   843
            self.attrs['cubicweb:inputid'] = inputid
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   844
4372
0c44af150a49 introduce a default render implementation on the base widget, which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4371
diff changeset
   845
    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
   846
        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
   847
        return tags.div(**attrs)
1304
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   848
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   849
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   850
class AutoCompletionWidget(TextInput):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   851
    """<input type='text'> based ajax widget, taking a `autocomplete_initfunc`
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   852
    argument which should specify the name of a method of the json
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   853
    controller. This method is expected to return allowed values for the input,
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   854
    that the widget will use to propose matching values as you type.
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   855
    """
6448
8590d82e9b1b [javascript] update to jQuery 1.4.2 and jQuery-ui 1.8.5
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6260
diff changeset
   856
    needs_js = ('cubicweb.widgets.js', 'jquery.ui.js')
8590d82e9b1b [javascript] update to jQuery 1.4.2 and jQuery-ui 1.8.5
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6260
diff changeset
   857
    needs_css = ('jquery.ui.css',)
6449
613d83588998 [formwidgets] rewrite autocomplete cw widgets to get rid of div-style declaration API
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6448
diff changeset
   858
    default_settings = {}
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   859
1966
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   860
    def __init__(self, *args, **kwargs):
6449
613d83588998 [formwidgets] rewrite autocomplete cw widgets to get rid of div-style declaration API
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6448
diff changeset
   861
        self.autocomplete_settings = kwargs.pop('autocomplete_settings',
613d83588998 [formwidgets] rewrite autocomplete cw widgets to get rid of div-style declaration API
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6448
diff changeset
   862
                                                self.default_settings)
7990
a673d1d9a738 [diet] drop pre 3.6 API compatibility (but attempt to keep data cmopatibility). Closes #2017916
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7879
diff changeset
   863
        self.autocomplete_initfunc = kwargs.pop('autocomplete_initfunc')
1966
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   864
        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
   865
5367
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5111
diff changeset
   866
    def values(self, form, field):
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5111
diff changeset
   867
        values = super(AutoCompletionWidget, self).values(form, field)
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5111
diff changeset
   868
        if not values:
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5111
diff changeset
   869
            values = ('',)
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5111
diff changeset
   870
        return values
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5111
diff changeset
   871
6449
613d83588998 [formwidgets] rewrite autocomplete cw widgets to get rid of div-style declaration API
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6448
diff changeset
   872
    def _render(self, form, field, renderer):
613d83588998 [formwidgets] rewrite autocomplete cw widgets to get rid of div-style declaration API
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6448
diff changeset
   873
        entity = form.edited_entity
613d83588998 [formwidgets] rewrite autocomplete cw widgets to get rid of div-style declaration API
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6448
diff changeset
   874
        domid = field.dom_id(form).replace(':', r'\\:')
613d83588998 [formwidgets] rewrite autocomplete cw widgets to get rid of div-style declaration API
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6448
diff changeset
   875
        if callable(self.autocomplete_initfunc):
613d83588998 [formwidgets] rewrite autocomplete cw widgets to get rid of div-style declaration API
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6448
diff changeset
   876
            data = self.autocomplete_initfunc(form, field)
613d83588998 [formwidgets] rewrite autocomplete cw widgets to get rid of div-style declaration API
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6448
diff changeset
   877
        else:
613d83588998 [formwidgets] rewrite autocomplete cw widgets to get rid of div-style declaration API
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6448
diff changeset
   878
            data = xml_escape(self._get_url(entity, field))
613d83588998 [formwidgets] rewrite autocomplete cw widgets to get rid of div-style declaration API
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6448
diff changeset
   879
        form._cw.add_onload(u'$("#%s").cwautocomplete(%s, %s);'
613d83588998 [formwidgets] rewrite autocomplete cw widgets to get rid of div-style declaration API
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6448
diff changeset
   880
                            % (domid, json_dumps(data),
613d83588998 [formwidgets] rewrite autocomplete cw widgets to get rid of div-style declaration API
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6448
diff changeset
   881
                               json_dumps(self.autocomplete_settings)))
613d83588998 [formwidgets] rewrite autocomplete cw widgets to get rid of div-style declaration API
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6448
diff changeset
   882
        return super(AutoCompletionWidget, self)._render(form, field, renderer)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   883
1875
7bcb02377516 no rschema attribute on widgets
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1874
diff changeset
   884
    def _get_url(self, entity, field):
7990
a673d1d9a738 [diet] drop pre 3.6 API compatibility (but attempt to keep data cmopatibility). Closes #2017916
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7879
diff changeset
   885
        fname = self.autocomplete_initfunc
8728
75be9de9d68e [web] Use the new '/ajax' URL path to access the AjaxController (closes #2758254)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 8471
diff changeset
   886
        return entity._cw.build_url('ajax', fname=fname, mode='remote',
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   887
                                    pageid=entity._cw.pageid)
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   888
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   889
6449
613d83588998 [formwidgets] rewrite autocomplete cw widgets to get rid of div-style declaration API
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6448
diff changeset
   890
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   891
class StaticFileAutoCompletionWidget(AutoCompletionWidget):
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   892
    """XXX describe me"""
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   893
    wdgtype = 'StaticFileSuggestField'
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   894
1875
7bcb02377516 no rschema attribute on widgets
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1874
diff changeset
   895
    def _get_url(self, entity, field):
7990
a673d1d9a738 [diet] drop pre 3.6 API compatibility (but attempt to keep data cmopatibility). Closes #2017916
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7879
diff changeset
   896
        return entity._cw.data_url(self.autocomplete_initfunc)
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   897
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   898
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   899
class RestrictedAutoCompletionWidget(AutoCompletionWidget):
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   900
    """XXX describe me"""
6449
613d83588998 [formwidgets] rewrite autocomplete cw widgets to get rid of div-style declaration API
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6448
diff changeset
   901
    default_settings = {'mustMatch': True}
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   902
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   903
4901
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   904
class LazyRestrictedAutoCompletionWidget(RestrictedAutoCompletionWidget):
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   905
    """remote autocomplete """
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   906
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   907
    def values_and_attributes(self, form, field):
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   908
        """override values_and_attributes to handle initial displayed values"""
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   909
        values, attrs = super(LazyRestrictedAutoCompletionWidget, self).values_and_attributes(form, field)
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   910
        assert len(values) == 1, "multiple selection is not supported yet by LazyWidget"
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   911
        if not values[0]:
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   912
            values = form.cw_extra_kwargs.get(field.name,'')
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   913
            if not isinstance(values, (tuple, list)):
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   914
                values = (values,)
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   915
        try:
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   916
            values = list(values)
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   917
            values[0] = int(values[0])
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   918
            attrs['cubicweb:initialvalue'] = values[0]
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   919
            values = (self.display_value_for(form, values[0]),)
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   920
        except (TypeError, ValueError):
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   921
            pass
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   922
        return values, attrs
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   923
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   924
    def display_value_for(self, form, value):
5367
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5111
diff changeset
   925
        entity = form._cw.entity_from_eid(value)
4901
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   926
        return entity.view('combobox')
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   927
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   928
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
   929
# more widgets #################################################################
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   930
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   931
class IntervalWidget(FieldWidget):
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   932
    """Custom widget to display an interval composed by 2 fields. This widget is
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   933
    expected to be used with a :class:`CompoundField` containing the two actual
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   934
    fields.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   935
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   936
    Exemple usage::
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   937
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   938
      class MyForm(FieldsForm):
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   939
         price = CompoundField(fields=(IntField(name='minprice'),
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   940
                                       IntField(name='maxprice')),
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   941
                               label=_('price'),
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   942
                               widget=IntervalWidget())
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   943
    """
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   944
    def _render(self, form, field, renderer):
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   945
        actual_fields = field.fields
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   946
        assert len(actual_fields) == 2
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   947
        return u'<div>%s %s %s %s</div>' % (
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   948
            form._cw._('from_interval_start'),
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   949
            actual_fields[0].render(form, renderer),
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   950
            form._cw._('to_interval_end'),
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   951
            actual_fields[1].render(form, renderer),
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   952
            )
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   953
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   954
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   955
class HorizontalLayoutWidget(FieldWidget):
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   956
    """Custom widget to display a set of fields grouped together horizontally in
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   957
    a form. See `IntervalWidget` for example usage.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   958
    """
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   959
    def _render(self, form, field, renderer):
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   960
        if self.attrs.get('display_label', True):
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   961
            subst = self.attrs.get('label_input_substitution', '%(label)s %(input)s')
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   962
            fields = [subst % {'label': renderer.render_label(form, f),
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   963
                              'input': f.render(form, renderer)}
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   964
                      for f in field.subfields(form)]
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   965
        else:
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   966
            fields = [f.render(form, renderer) for f in field.subfields(form)]
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   967
        return u'<div>%s</div>' % ' '.join(fields)
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   968
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   969
4375
6d34e3cf60a3 cleanup base class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4373
diff changeset
   970
class EditableURLWidget(FieldWidget):
9700
da7d341cca76 an URL -> a URL
Rémi Cardona <remi.cardona@logilab.fr>
parents: 9377
diff changeset
   971
    """Custom widget to edit separatly a URL path / query string (used by
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   972
    default for the `path` attribute of `Bookmark` entities).
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   973
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   974
    It deals with url quoting nicely so that the user edit the unquoted value.
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
   975
    """
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
   976
4372
0c44af150a49 introduce a default render implementation on the base widget, which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4371
diff changeset
   977
    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
   978
        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
   979
        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
   980
        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
   981
        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
   982
        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
   983
            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
   984
            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
   985
        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
   986
            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
   987
                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
   988
            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
   989
                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
   990
            if value:
d74098d1b69f fix bug when value is None
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4508
diff changeset
   991
                try:
d74098d1b69f fix bug when value is None
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4508
diff changeset
   992
                    path, qs = value.split('?', 1)
d74098d1b69f fix bug when value is None
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4508
diff changeset
   993
                except ValueError:
d74098d1b69f fix bug when value is None
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4508
diff changeset
   994
                    path = value
d74098d1b69f fix bug when value is None
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4508
diff changeset
   995
                    qs = ''
d74098d1b69f fix bug when value is None
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4508
diff changeset
   996
            else:
d74098d1b69f fix bug when value is None
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4508
diff changeset
   997
                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
   998
            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
   999
        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
  1000
        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
  1001
            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
  1002
        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
  1003
            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
  1004
        # 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
  1005
        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
  1006
                  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
  1007
                  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
  1008
                  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
  1009
                  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
  1010
                  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
  1011
                  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
  1012
        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
  1013
            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
  1014
        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
  1015
            attrs['tabindex'] = req.next_tabindex()
5111
9f3ea34f98d1 [widget] more wide textarea on bookmark edition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4975
diff changeset
  1016
        attrs.setdefault('cols', 60)
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
  1017
        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
  1018
        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
  1019
                   u'</td></tr></table>']
4376
839b28a3652e surrounding div necessary for proper error localization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4375
diff changeset
  1020
        # surrounding div necessary for proper error localization
4508
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
  1021
        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
  1022
            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
  1023
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
  1024
    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
  1025
        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
  1026
        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
  1027
        path = req.form.get(field.input_name(form, 'path'))
10612
84468b90e9c1 [py3k] basestring → six.string_types
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10522
diff changeset
  1028
        if isinstance(path, string_types):
6682
bdf9424b499c test and fix #1232202: [bookmarks] broken link for startupviews
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6449
diff changeset
  1029
            path = path.strip()
bdf9424b499c test and fix #1232202: [bookmarks] broken link for startupviews
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6449
diff changeset
  1030
        if path is None:
bdf9424b499c test and fix #1232202: [bookmarks] broken link for startupviews
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6449
diff changeset
  1031
            path = u''
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
  1032
        fqs = req.form.get(field.input_name(form, 'fqs'))
10612
84468b90e9c1 [py3k] basestring → six.string_types
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10522
diff changeset
  1033
        if isinstance(fqs, string_types):
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
  1034
            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
  1035
            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
  1036
                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
  1037
                    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
  1038
                    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
  1039
                        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
  1040
                            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
  1041
                        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
  1042
                            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
  1043
                        # value will be url quoted by build_url_params
10771
a688ef1a12eb [web/formwidgets] fix for py3k
Julien Cristau <julien.cristau@logilab.fr>
parents: 10717
diff changeset
  1044
                        values.setdefault(key, []).append(val)
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
  1045
        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
  1046
            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
  1047
        return u'%s?%s' % (path, req.build_url_params(**values))
5384
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1048
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1049
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1050
# form controls ######################################################################
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1051
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1052
class Button(Input):
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1053
    """Simple <input type='button'>, base class for global form buttons.
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1054
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1055
    Note that `label` is a msgid which will be translated at form generation
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1056
    time, you should not give an already translated string.
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1057
    """
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1058
    type = 'button'
9134
a5f53b023132 [css, html] add a css_class attribute on Button, allowing to change easily default CSS class for buttons
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 8936
diff changeset
  1059
    css_class = 'validateButton'
a5f53b023132 [css, html] add a css_class attribute on Button, allowing to change easily default CSS class for buttons
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 8936
diff changeset
  1060
5384
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1061
    def __init__(self, label=stdmsgs.BUTTON_OK, attrs=None,
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1062
                 setdomid=None, settabindex=None,
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1063
                 name='', value='', onclick=None, cwaction=None):
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1064
        super(Button, self).__init__(attrs, setdomid, settabindex)
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1065
        if isinstance(label, tuple):
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1066
            self.label = label[0]
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1067
            self.icon = label[1]
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1068
        else:
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1069
            self.label = label
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1070
            self.icon = None
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1071
        self.name = name
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1072
        self.value = ''
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1073
        self.onclick = onclick
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1074
        self.cwaction = cwaction
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1075
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1076
    def render(self, form, field=None, renderer=None):
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1077
        label = form._cw._(self.label)
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1078
        attrs = self.attrs.copy()
10479
b0417cacecd9 [web] write css_class to attrs on rendering and not on button creation
Laura Médioni <laura.medioni@logilab.fr>
parents: 10404
diff changeset
  1079
        attrs.setdefault('class', self.css_class)
5384
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1080
        if self.cwaction:
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1081
            assert self.onclick is None
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1082
            attrs['onclick'] = "postForm('__action_%s', \'%s\', \'%s\')" % (
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1083
                self.cwaction, self.label, form.domid)
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1084
        elif self.onclick:
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1085
            attrs['onclick'] = self.onclick
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1086
        if self.name:
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1087
            attrs['name'] = self.name
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1088
            if self.setdomid:
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1089
                attrs['id'] = self.name
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1090
        if self.settabindex and not 'tabindex' in attrs:
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1091
            attrs['tabindex'] = form._cw.next_tabindex()
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1092
        if self.icon:
5467
57372dbfd114 [https] fix resource urls in https version of a site: should use the https version as well to avoid warnings from the nrowser
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5453
diff changeset
  1093
            img = tags.img(src=form._cw.uiprops[self.icon], alt=self.icon)
5384
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1094
        else:
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1095
            img = u''
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1096
        return tags.button(img + xml_escape(label), escapecontent=False,
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1097
                           value=label, type=self.type, **attrs)
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1098
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1099
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1100
class SubmitButton(Button):
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1101
    """Simple <input type='submit'>, main button to submit a form"""
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1102
    type = 'submit'
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1103
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1104
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1105
class ResetButton(Button):
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1106
    """Simple <input type='reset'>, main button to reset a form. You usually
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1107
    don't want to use this.
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1108
    """
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1109
    type = 'reset'
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1110
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1111
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1112
class ImgButton(object):
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1113
    """Simple <img> wrapped into a <a> tag with href triggering something (usually a
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1114
    javascript call).
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1115
    """
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1116
    def __init__(self, domid, href, label, imgressource):
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1117
        self.domid = domid
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1118
        self.href = href
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1119
        self.imgressource = imgressource
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1120
        self.label = label
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1121
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1122
    def render(self, form, field=None, renderer=None):
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1123
        label = form._cw._(self.label)
5467
57372dbfd114 [https] fix resource urls in https version of a site: should use the https version as well to avoid warnings from the nrowser
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5453
diff changeset
  1124
        imgsrc = form._cw.uiprops[self.imgressource]
5384
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1125
        return '<a id="%(domid)s" href="%(href)s">'\
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1126
               '<img src="%(imgsrc)s" alt="%(label)s"/>%(label)s</a>' % {
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1127
            'label': label, 'imgsrc': imgsrc,
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1128
            'domid': self.domid, 'href': self.href}