web/formwidgets.py
author Sylvain Thénault <sylvain.thenault@logilab.fr>
Fri, 07 Oct 2011 11:47:42 +0200
branchstable
changeset 7917 436400e7f807
parent 7879 9aae456abab5
child 7990 a673d1d9a738
permissions -rw-r--r--
sample script to turn a pyro source into a datafeed source
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
7411
238da9684f99 cleanup and update some copyright
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7231
diff changeset
     1
# copyright 2003-2011 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
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    37
.. autoclass:: cubicweb.web.formwidgets.PasswordSingleInput
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    38
.. autoclass:: cubicweb.web.formwidgets.FileInput
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    39
.. autoclass:: cubicweb.web.formwidgets.ButtonInput
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    40
6880
4be32427b2b9 [book] fixes some references and other doc construction pbs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6682
diff changeset
    41
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    42
Other standard HTML widgets
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    43
'''''''''''''''''''''''''''
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
.. autoclass:: cubicweb.web.formwidgets.TextArea
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    46
.. autoclass:: cubicweb.web.formwidgets.Select
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    47
.. autoclass:: cubicweb.web.formwidgets.CheckBox
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    48
.. autoclass:: cubicweb.web.formwidgets.Radio
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    49
6880
4be32427b2b9 [book] fixes some references and other doc construction pbs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6682
diff changeset
    50
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    51
Date and time widgets
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    52
'''''''''''''''''''''
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
.. autoclass:: cubicweb.web.formwidgets.DateTimePicker
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    55
.. autoclass:: cubicweb.web.formwidgets.JQueryDateTimePicker
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    56
.. autoclass:: cubicweb.web.formwidgets.JQueryDatePicker
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    57
.. autoclass:: cubicweb.web.formwidgets.JQueryTimePicker
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    58
6880
4be32427b2b9 [book] fixes some references and other doc construction pbs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6682
diff changeset
    59
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    60
Ajax / javascript widgets
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    61
'''''''''''''''''''''''''
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
.. autoclass:: cubicweb.web.formwidgets.FCKEditor
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    64
.. autoclass:: cubicweb.web.formwidgets.AjaxWidget
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    65
.. 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
    66
.. 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
    67
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    68
.. kill or document StaticFileAutoCompletionWidget
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    69
.. kill or document LazyRestrictedAutoCompletionWidget
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    70
.. kill or document RestrictedAutoCompletionWidget
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    71
6880
4be32427b2b9 [book] fixes some references and other doc construction pbs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6682
diff changeset
    72
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    73
Other widgets
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    74
'''''''''''''
6880
4be32427b2b9 [book] fixes some references and other doc construction pbs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6682
diff changeset
    75
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    76
.. autoclass:: cubicweb.web.formwidgets.PasswordInput
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    77
.. autoclass:: cubicweb.web.formwidgets.IntervalWidget
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    78
.. autoclass:: cubicweb.web.formwidgets.HorizontalLayoutWidget
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    79
.. autoclass:: cubicweb.web.formwidgets.EditableURLWidget
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    80
6880
4be32427b2b9 [book] fixes some references and other doc construction pbs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6682
diff changeset
    81
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    82
Form controls
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    83
'''''''''''''
6880
4be32427b2b9 [book] fixes some references and other doc construction pbs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6682
diff changeset
    84
4be32427b2b9 [book] fixes some references and other doc construction pbs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6682
diff changeset
    85
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
    86
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
    87
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
    88
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    89
.. autoclass:: cubicweb.web.formwidgets.Button
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    90
.. autoclass:: cubicweb.web.formwidgets.SubmitButton
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    91
.. autoclass:: cubicweb.web.formwidgets.ResetButton
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    92
.. autoclass:: cubicweb.web.formwidgets.ImgButton
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    93
"""
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    94
__docformat__ = "restructuredtext en"
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    95
1096
e1fe98850bf7 cleanup
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
    96
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
    97
from warnings import warn
1096
e1fe98850bf7 cleanup
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
    98
4160
3fbdeef9a610 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4159
diff changeset
    99
from logilab.mtconverter import xml_escape
3fbdeef9a610 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4159
diff changeset
   100
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
   101
from logilab.common.date import todatetime
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   102
4481
56440a1f816a hidden usage of datetime function which has been moved to lgc
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4392
diff changeset
   103
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
   104
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
   105
from cubicweb.web import stdmsgs, INTERNAL_FIELD_VALUE, ProcessFormError
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   106
4583
356f08325072 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4550
diff changeset
   107
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   108
class FieldWidget(object):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   109
    """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
   110
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   111
    **Attributes**
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   112
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
   113
    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
   114
    to override default behaviours:
5368
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
    :attr:`needs_js`
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   117
       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
   118
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   119
    :attr:`needs_css`
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   120
       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
   121
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   122
    :attr:`setdomid`
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   123
       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
   124
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   125
    :attr:`settabindex`
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   126
       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
   127
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   128
    :attr:`suffix`
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   129
       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
   130
       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
   131
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   132
    :attr:`vocabulary_widget`
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   133
       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
   134
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   135
    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
   136
    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
   137
    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
   138
    classes may ignore it).
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
    .. currentmodule:: cubicweb.web.formwidgets
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   141
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   142
    **Form generation methods**
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   143
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   144
    .. automethod:: render
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   145
    .. automethod:: _render
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   146
    .. automethod:: values
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   147
    .. automethod:: attributes
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
    **Post handling methods**
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   150
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   151
    .. automethod:: process_field_data
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   152
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   153
    """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   154
    needs_js = ()
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   155
    needs_css = ()
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   156
    setdomid = True
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   157
    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
   158
    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
   159
    # 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
   160
    vocabulary_widget = False
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   161
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
   162
    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
   163
        if attrs is None:
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   164
            attrs = {}
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   165
        self.attrs = attrs
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   166
        if setdomid is not None:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   167
            # override class's default value
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   168
            self.setdomid = setdomid
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   169
        if settabindex is not None:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   170
            # override class's default value
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   171
            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
   172
        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
   173
            self.suffix = suffix
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   174
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   175
    def add_media(self, form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   176
        """adds media (CSS & JS) required by this widget"""
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   177
        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
   178
            form._cw.add_js(self.needs_js)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   179
        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
   180
            form._cw.add_css(self.needs_css)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   181
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   182
    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
   183
        """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
   184
        `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
   185
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   186
        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
   187
        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
   188
        """
4372
0c44af150a49 introduce a default render implementation on the base widget, which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4371
diff changeset
   189
        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
   190
        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
   191
0c44af150a49 introduce a default render implementation on the base widget, which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4371
diff changeset
   192
    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
   193
        """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
   194
        """
4372
0c44af150a49 introduce a default render implementation on the base widget, which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4371
diff changeset
   195
        raise NotImplementedError()
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   196
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
   197
    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
   198
        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
   199
5367
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5111
diff changeset
   200
    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
   201
        """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
   202
        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
   203
        :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
   204
        """
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
   205
        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
   206
        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
   207
            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
   208
        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
   209
            attrs['tabindex'] = form._cw.next_tabindex()
5367
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5111
diff changeset
   210
        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
   211
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
    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
   213
        """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
   214
        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
   215
        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
   216
        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
   217
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   218
        Those values are searched in:
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   219
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   220
        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
   221
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   222
        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
   223
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   224
        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
   225
           generating the form)
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
        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
   228
           :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
   229
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   230
        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
   231
        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
   232
        correctly typed value.
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
        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
   235
        concrete classes.
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   236
        """
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
   237
        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
   238
        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
   239
            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
   240
            # 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
   241
            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
   242
                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
   243
            # 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
   244
            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
   245
                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
   246
            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
   247
                # 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
   248
                # 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
   249
                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
   250
        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
   251
            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
   252
            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
   253
                values = self.format_value(form, field, values)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   254
        if not isinstance(values, (tuple, list)):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   255
            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
   256
        return values
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   257
4660
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   258
    def typed_value(self, form, field):
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   259
        """return field's *typed* value specified in:
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   260
        3. extra form values given to render()
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   261
        4. field's typed value
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   262
        """
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   263
        qname = field.input_name(form)
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   264
        for key in ((field, form), qname):
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   265
            try:
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   266
                return form.formvalues[key]
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   267
            except KeyError:
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   268
                continue
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   269
        if field.name != qname and field.name in form.formvalues:
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   270
            return form.formvalues[field.name]
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   271
        return field.typed_value(form)
21ed77792c33 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   272
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
   273
    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
   274
        """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
   275
        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
   276
        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
   277
        """
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   278
        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
   279
        val = posted.get(field.input_name(form, self.suffix))
4169
341d19ef7b7c strip string by default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4163
diff changeset
   280
        if isinstance(val, basestring):
4392
91a56a30141e by default this is not the widget responsability to turn empty string into None,
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4382
diff changeset
   281
            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
   282
        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
   283
5367
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5111
diff changeset
   284
    # 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
   285
    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
   286
        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
   287
4163
b2747ed057e6 substitute _render_attrs by values_and_attributes method, keeping bw compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   288
    @deprecated('[3.6] use values_and_attributes')
b2747ed057e6 substitute _render_attrs by values_and_attributes method, keeping bw compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   289
    def _render_attrs(self, form, field):
b2747ed057e6 substitute _render_attrs by values_and_attributes method, keeping bw compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   290
        """return html tag name, attributes and a list of values for the field
b2747ed057e6 substitute _render_attrs by values_and_attributes method, keeping bw compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   291
        """
b2747ed057e6 substitute _render_attrs by values_and_attributes method, keeping bw compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   292
        values, attrs = self.values_and_attributes(form, field)
4371
0d337feb5374 [forms] new optional suffix attribute on widget objects, used to generage input name / dom id.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4305
diff changeset
   293
        return field.input_name(form, self.suffix), values, attrs
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   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):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   318
    """Simple <input type='text'>, will return an 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
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   322
class PasswordSingleInput(Input):
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   323
    """Simple <input type='password'>, will return an utf-8 encoded string.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   324
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   325
    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
   326
    widget which handles password confirmation.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   327
    """
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   328
    type = 'password'
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
    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
   331
        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
   332
        if value is not None:
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   333
            return value.encode('utf-8')
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   334
        return value
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   335
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   336
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   337
class PasswordInput(Input):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   338
    """<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
   339
    fail if password and confirmation differs, else it will return the password
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   340
    as an utf-8 encoded string.
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   341
    """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   342
    type = 'password'
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   343
4372
0c44af150a49 introduce a default render implementation on the base widget, which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4371
diff changeset
   344
    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
   345
        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
   346
        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
   347
        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
   348
        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
   349
        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
   350
                             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
   351
                  '<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
   352
                  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
   353
                             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
   354
                  '&#160;', tags.span(form._cw._('confirm password'),
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   355
                                      **{'class': 'emphasis'})]
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   356
        return u'\n'.join(inputs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   357
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
   358
    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
   359
        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
   360
        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
   361
        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
   362
            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
   363
                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
   364
            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
   365
        raise ProcessFormError(form._cw._("password and confirmation don't match"))
1096
e1fe98850bf7 cleanup
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   366
e1fe98850bf7 cleanup
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   367
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   368
class FileInput(Input):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   369
    """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
   370
    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
   371
    posted file data.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   372
    """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   373
    type = 'file'
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   374
5367
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5111
diff changeset
   375
    def values(self, form, field):
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   376
        # 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
   377
        return ('',)
1096
e1fe98850bf7 cleanup
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   378
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   379
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   380
class HiddenInput(Input):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   381
    """Simple <input type='hidden'> for hidden value, will return an unicode
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   382
    string.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   383
    """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   384
    type = 'hidden'
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   385
    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
   386
    settabindex = False
1096
e1fe98850bf7 cleanup
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   387
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   388
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   389
class ButtonInput(Input):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   390
    """Simple <input type='button'>, will return an unicode string.
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   391
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   392
    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
   393
    :class:`SubmitButton`, :class:`ResetButton` and :class:`ImgButton` below.
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   394
    """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   395
    type = 'button'
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   396
1096
e1fe98850bf7 cleanup
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   397
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   398
class TextArea(FieldWidget):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   399
    """Simple <textarea>, will return an unicode string."""
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
   400
4372
0c44af150a49 introduce a default render implementation on the base widget, which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4371
diff changeset
   401
    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
   402
        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
   403
        attrs.setdefault('onkeyup', 'autogrow(this)')
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   404
        if not values:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   405
            value = u''
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   406
        elif len(values) == 1:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   407
            value = values[0]
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   408
        else:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   409
            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
   410
        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
   411
        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
   412
        for line in lines:
e4229723b824 [formwidgets] let the textarea height be dependant on the actual content (up to a limit)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2360
diff changeset
   413
            linecount += len(line) / 80
e4229723b824 [formwidgets] let the textarea height be dependant on the actual content (up to a limit)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2360
diff changeset
   414
        attrs.setdefault('cols', 80)
e4229723b824 [formwidgets] let the textarea height be dependant on the actual content (up to a limit)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2360
diff changeset
   415
        attrs.setdefault('rows', min(15, linecount + 2))
4371
0d337feb5374 [forms] new optional suffix attribute on widget objects, used to generage input name / dom id.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4305
diff changeset
   416
        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
   417
                             **attrs)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   418
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   419
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   420
class FCKEditor(TextArea):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   421
    """FCKEditor enabled <textarea>, will return an unicode string containing
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   422
    HTML formated text.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   423
    """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   424
    def __init__(self, *args, **kwargs):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   425
        super(FCKEditor, self).__init__(*args, **kwargs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   426
        self.attrs['cubicweb:type'] = 'wysiwyg'
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   427
4372
0c44af150a49 introduce a default render implementation on the base widget, which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4371
diff changeset
   428
    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
   429
        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
   430
        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
   431
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   432
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   433
class Select(FieldWidget):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   434
    """Simple <select>, for field having a specific vocabulary. Will return
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   435
    an unicode string, or a list of unicode strings.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   436
    """
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
   437
    vocabulary_widget = True
7450
c21d845836e4 [formwidgets] make the select size a class attribute (more easily tuned)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7411
diff changeset
   438
    default_size = 5
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
   439
4975
35b0dd80dc06 [widget] allow kwargs passed to Select widget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4901
diff changeset
   440
    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
   441
        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
   442
        self._multiple = multiple
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   443
5367
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5111
diff changeset
   444
    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
   445
        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
   446
        options = []
1771
bb9538d91465 fix <optgroup> tag cannot be empty according to DTD
Florent <florent@secondweb.fr>
parents: 1768
diff changeset
   447
        optgroup_opened = False
7453
84046395d2cd Fix name error introduced in c21d845836e4
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7450
diff changeset
   448
        vocab = field.vocabulary(form)
84046395d2cd Fix name error introduced in c21d845836e4
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7450
diff changeset
   449
        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
   450
            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
   451
                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
   452
            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
   453
                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
   454
                oattrs = {}
1336
2e552353c42a insert an optgroup as separator on None values
sylvain.thenault@logilab.fr
parents: 1330
diff changeset
   455
            if value is None:
2e552353c42a insert an optgroup as separator on None values
sylvain.thenault@logilab.fr
parents: 1330
diff changeset
   456
                # handle separator
1771
bb9538d91465 fix <optgroup> tag cannot be empty according to DTD
Florent <florent@secondweb.fr>
parents: 1768
diff changeset
   457
                if optgroup_opened:
bb9538d91465 fix <optgroup> tag cannot be empty according to DTD
Florent <florent@secondweb.fr>
parents: 1768
diff changeset
   458
                    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
   459
                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
   460
                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
   461
                optgroup_opened = True
1336
2e552353c42a insert an optgroup as separator on None values
sylvain.thenault@logilab.fr
parents: 1330
diff changeset
   462
            elif value in curvalues:
2518
38c28ee40138 allow vocabulary functions to return either label/value or label/value/dict (to use as attributes of the tag for this input)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2366
diff changeset
   463
                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
   464
                                           selected='selected', **oattrs))
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   465
            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
   466
                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
   467
        if optgroup_opened:
bb9538d91465 fix <optgroup> tag cannot be empty according to DTD
Florent <florent@secondweb.fr>
parents: 1768
diff changeset
   468
            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
   469
        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
   470
            if self._multiple:
c21d845836e4 [formwidgets] make the select size a class attribute (more easily tuned)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7411
diff changeset
   471
                size = unicode(min(self.default_size, len(vocab) or 1))
c21d845836e4 [formwidgets] make the select size a class attribute (more easily tuned)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7411
diff changeset
   472
            else:
c21d845836e4 [formwidgets] make the select size a class attribute (more easily tuned)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7411
diff changeset
   473
                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
   474
            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
   475
        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
   476
                           multiple=self._multiple, options=options, **attrs)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   477
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   478
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   479
class CheckBox(Input):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   480
    """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
   481
    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
   482
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   483
    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
   484
    default <br/> is used.
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   485
    """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   486
    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
   487
    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
   488
    vocabulary_widget = True
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   489
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
   490
    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
   491
        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
   492
        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
   493
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5111
diff changeset
   494
    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
   495
        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
   496
        domid = attrs.pop('id', None)
5367
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5111
diff changeset
   497
        # XXX turn this as initializer argument
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5111
diff changeset
   498
        try:
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5111
diff changeset
   499
            sep = attrs.pop('separator')
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5111
diff changeset
   500
            warn('[3.8] separator should be specified using initializer argument',
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5111
diff changeset
   501
                 DeprecationWarning)
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5111
diff changeset
   502
        except KeyError:
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5111
diff changeset
   503
            sep = self.separator
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   504
        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
   505
        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
   506
            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
   507
                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
   508
            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
   509
                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
   510
                oattrs = {}
1367
01bb5b727fe3 set dom id on the first input of radio choices
sylvain.thenault@logilab.fr
parents: 1359
diff changeset
   511
            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
   512
            iattrs.update(oattrs)
1367
01bb5b727fe3 set dom id on the first input of radio choices
sylvain.thenault@logilab.fr
parents: 1359
diff changeset
   513
            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
   514
                iattrs.setdefault('id', domid)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   515
            if value in curvalues:
1367
01bb5b727fe3 set dom id on the first input of radio choices
sylvain.thenault@logilab.fr
parents: 1359
diff changeset
   516
                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
   517
            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
   518
                             type=self.type, value=value, **iattrs)
4593
d0b5ef72a492 add space between a checkbox and its label
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4583
diff changeset
   519
            options.append(u'%s&#160;%s' % (tag, label))
2519
ac1a869e1e93 nicer checkbox widget implementation, avoid extra <br/> at the end
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2518
diff changeset
   520
        return sep.join(options)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   521
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   522
1832
3384264d25cc fix CheckBox multiple dom id and refactor with Radio
Florent <florent@secondweb.fr>
parents: 1771
diff changeset
   523
class Radio(CheckBox):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   524
    """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
   525
    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
   526
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   527
    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
   528
    default <br/> is used.
1832
3384264d25cc fix CheckBox multiple dom id and refactor with Radio
Florent <florent@secondweb.fr>
parents: 1771
diff changeset
   529
    """
3384264d25cc fix CheckBox multiple dom id and refactor with Radio
Florent <florent@secondweb.fr>
parents: 1771
diff changeset
   530
    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
   531
2523
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   532
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   533
# javascript widgets ###########################################################
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   534
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   535
class DateTimePicker(TextInput):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   536
    """<input type='text'> + javascript date/time picker for date or datetime
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   537
    fields. Will return the date or datetime as an unicode string.
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   538
    """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   539
    monthnames = ('january', 'february', 'march', 'april',
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   540
                  'may', 'june', 'july', 'august',
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   541
                  'september', 'october', 'november', 'december')
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   542
    daynames = ('monday', 'tuesday', 'wednesday', 'thursday',
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   543
                'friday', 'saturday', 'sunday')
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   544
1311
4cc6e2723dc7 move ajax.js to base form class
sylvain.thenault@logilab.fr
parents: 1304
diff changeset
   545
    needs_js = ('cubicweb.calendar.js',)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   546
    needs_css = ('cubicweb.calendar_popup.css',)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   547
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   548
    @classmethod
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   549
    def add_localized_infos(cls, req):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   550
        """inserts JS variables defining localized months and days"""
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   551
        _ = req._
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   552
        monthnames = [_(mname) for mname in cls.monthnames]
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   553
        daynames = [_(dname) for dname in cls.daynames]
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   554
        req.html_headers.define_var('MONTHNAMES', monthnames)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   555
        req.html_headers.define_var('DAYNAMES', daynames)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   556
5367
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5111
diff changeset
   557
    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
   558
        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
   559
        self.add_localized_infos(form._cw)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   560
        cal_button = self._render_calendar_popup(form, field)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   561
        return txtwidget + cal_button
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   562
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   563
    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
   564
        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
   565
        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
   566
            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
   567
        inputid = field.dom_id(form)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   568
        helperid = '%shelper' % inputid
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   569
        year, month = value.year, value.month
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   570
        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
   571
<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
   572
                % (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
   573
                   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
   574
                   form._cw._('calendar'), helperid) )
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   575
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   576
4373
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   577
class JQueryDatePicker(FieldWidget):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   578
    """Use jquery.ui.datepicker to define a date picker. Will return the date as
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   579
    an unicode string.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   580
    """
4373
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   581
    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
   582
    needs_css = ('jquery.ui.css',)
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   583
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   584
    def __init__(self, datestr=None, **kwargs):
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   585
        super(JQueryDatePicker, self).__init__(**kwargs)
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   586
        self.datestr = datestr
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   587
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   588
    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
   589
        req = form._cw
6737
de49060d4be3 add localization files for jquery datepicker
Stephanie Marcu <stephanie.marcu@logilab.fr>
parents: 6682
diff changeset
   590
        if req.lang != 'en':
de49060d4be3 add localization files for jquery datepicker
Stephanie Marcu <stephanie.marcu@logilab.fr>
parents: 6682
diff changeset
   591
            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
   592
        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
   593
        # 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
   594
        fmt = req.property_value('ui.date-format')
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   595
        fmt = fmt.replace('%Y', 'yy').replace('%m', 'mm').replace('%d', 'dd')
5909
9af8ac182f53 [javascript] fix some javascript errors and remove some deprecation warnings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5467
diff changeset
   596
        req.add_onload(u'cw.jqNode("%s").datepicker('
4373
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   597
                       '{buttonImage: "%s", dateFormat: "%s", firstDay: 1,'
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   598
                       ' showOn: "button", buttonImageOnly: true})' % (
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
   599
                           domid, req.uiprops['CALENDAR_ICON'], fmt))
4373
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   600
        if self.datestr is None:
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   601
            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
   602
        else:
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   603
            value = self.datestr
7115
1f1d8c35cc3e [web formwidgets] add missing tabindex to jquery date and time widgets (closes #1568475)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 7070
diff changeset
   604
        attrs = {}
1f1d8c35cc3e [web formwidgets] add missing tabindex to jquery date and time widgets (closes #1568475)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 7070
diff changeset
   605
        if self.settabindex:
1f1d8c35cc3e [web formwidgets] add missing tabindex to jquery date and time widgets (closes #1568475)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 7070
diff changeset
   606
            attrs['tabindex'] = req.next_tabindex()
4373
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   607
        return tags.input(id=domid, name=domid, value=value,
7115
1f1d8c35cc3e [web formwidgets] add missing tabindex to jquery date and time widgets (closes #1568475)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 7070
diff changeset
   608
                          type='text', size='10', **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
   609
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   610
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   611
class JQueryTimePicker(FieldWidget):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   612
    """Use jquery.timePicker to define a time picker. Will return the time as an
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   613
    unicode string.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   614
    """
4373
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   615
    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
   616
    needs_css = ('jquery.timepicker.css',)
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   617
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
   618
    def __init__(self, timestr=None, timesteps=30, separator=u':', **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
   619
        super(JQueryTimePicker, self).__init__(**kwargs)
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   620
        self.timestr = timestr
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   621
        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
   622
        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
   623
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   624
    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
   625
        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
   626
        domid = field.dom_id(form, self.suffix)
5909
9af8ac182f53 [javascript] fix some javascript errors and remove some deprecation warnings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5467
diff changeset
   627
        req.add_onload(u'cw.jqNode("%s").timePicker({selectedTime: "%s", step: %s, separator: "%s"})' % (
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
   628
            domid, self.timestr, self.timesteps, self.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
   629
        if self.timestr is None:
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   630
            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
   631
        else:
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   632
            value = self.timestr
7115
1f1d8c35cc3e [web formwidgets] add missing tabindex to jquery date and time widgets (closes #1568475)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 7070
diff changeset
   633
        attrs = {}
1f1d8c35cc3e [web formwidgets] add missing tabindex to jquery date and time widgets (closes #1568475)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 7070
diff changeset
   634
        if self.settabindex:
1f1d8c35cc3e [web formwidgets] add missing tabindex to jquery date and time widgets (closes #1568475)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 7070
diff changeset
   635
            attrs['tabindex'] = req.next_tabindex()
4373
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   636
        return tags.input(id=domid, name=domid, value=value,
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   637
                          type='text', size='5')
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   638
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   639
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   640
class JQueryDateTimePicker(FieldWidget):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   641
    """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
   642
    :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
   643
    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
   644
    """
4373
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   645
    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
   646
        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
   647
        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
   648
        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
   649
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   650
    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
   651
        """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
   652
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   653
        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
   654
        """
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   655
        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
   656
        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
   657
        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
   658
        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
   659
            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
   660
            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
   661
        else:
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   662
            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
   663
            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
   664
                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
   665
            else:
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   666
                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
   667
            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
   668
                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
   669
                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
   670
            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
   671
                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
   672
        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
   673
        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
   674
                                      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
   675
        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
   676
                                            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
   677
                                            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
   678
972143183ea3 new jquery based widgets for Time/Date/DateTime, backported from crm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4372
diff changeset
   679
    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
   680
        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
   681
        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
   682
        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
   683
        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
   684
            return None
6260
e06750b556ad raise ProcessFormError when a problem occurs during date / time parsing
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 5909
diff changeset
   685
        try:
e06750b556ad raise ProcessFormError when a problem occurs during date / time parsing
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 5909
diff changeset
   686
            date = todatetime(req.parse_datetime(datestr, 'Date'))
e06750b556ad raise ProcessFormError when a problem occurs during date / time parsing
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 5909
diff changeset
   687
        except ValueError, exc:
e06750b556ad raise ProcessFormError when a problem occurs during date / time parsing
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 5909
diff changeset
   688
            raise ProcessFormError(unicode(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
   689
        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
   690
            return date
6260
e06750b556ad raise ProcessFormError when a problem occurs during date / time parsing
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 5909
diff changeset
   691
        try:
e06750b556ad raise ProcessFormError when a problem occurs during date / time parsing
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 5909
diff changeset
   692
            time = req.parse_datetime(timestr, 'Time')
e06750b556ad raise ProcessFormError when a problem occurs during date / time parsing
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 5909
diff changeset
   693
        except ValueError, exc:
e06750b556ad raise ProcessFormError when a problem occurs during date / time parsing
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 5909
diff changeset
   694
            raise ProcessFormError(unicode(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
   695
        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
   696
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   697
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   698
# ajax widgets ################################################################
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   699
1337
828bbf500bcc backport AddComboBoxWidget, ajax widgets refactoring
sylvain.thenault@logilab.fr
parents: 1336
diff changeset
   700
def init_ajax_attributes(attrs, wdgtype, loadtype=u'auto'):
828bbf500bcc backport AddComboBoxWidget, ajax widgets refactoring
sylvain.thenault@logilab.fr
parents: 1336
diff changeset
   701
    try:
4597
e872097f2287 use class, not klass, in widget.attrs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4593
diff changeset
   702
        attrs['class'] += u' widget'
1337
828bbf500bcc backport AddComboBoxWidget, ajax widgets refactoring
sylvain.thenault@logilab.fr
parents: 1336
diff changeset
   703
    except KeyError:
4597
e872097f2287 use class, not klass, in widget.attrs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4593
diff changeset
   704
        attrs['class'] = u'widget'
1344
930020cb134b shouldn't use unicode keys in attrs
sylvain.thenault@logilab.fr
parents: 1337
diff changeset
   705
    attrs.setdefault('cubicweb:wdgtype', wdgtype)
930020cb134b shouldn't use unicode keys in attrs
sylvain.thenault@logilab.fr
parents: 1337
diff changeset
   706
    attrs.setdefault('cubicweb:loadtype', loadtype)
1337
828bbf500bcc backport AddComboBoxWidget, ajax widgets refactoring
sylvain.thenault@logilab.fr
parents: 1336
diff changeset
   707
828bbf500bcc backport AddComboBoxWidget, ajax widgets refactoring
sylvain.thenault@logilab.fr
parents: 1336
diff changeset
   708
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   709
class AjaxWidget(FieldWidget):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   710
    """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
   711
    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
   712
    """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   713
    def __init__(self, wdgtype, inputid=None, **kwargs):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   714
        super(AjaxWidget, self).__init__(**kwargs)
1337
828bbf500bcc backport AddComboBoxWidget, ajax widgets refactoring
sylvain.thenault@logilab.fr
parents: 1336
diff changeset
   715
        init_ajax_attributes(self.attrs, wdgtype)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   716
        if inputid is not None:
1344
930020cb134b shouldn't use unicode keys in attrs
sylvain.thenault@logilab.fr
parents: 1337
diff changeset
   717
            self.attrs['cubicweb:inputid'] = inputid
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   718
4372
0c44af150a49 introduce a default render implementation on the base widget, which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4371
diff changeset
   719
    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
   720
        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
   721
        return tags.div(**attrs)
1304
8975c8e520a9 refactor button handling
sylvain.thenault@logilab.fr
parents: 1295
diff changeset
   722
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   723
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   724
class AutoCompletionWidget(TextInput):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   725
    """<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
   726
    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
   727
    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
   728
    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
   729
    """
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
   730
    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
   731
    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
   732
    default_settings = {}
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   733
1966
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   734
    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
   735
        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
   736
                                                self.default_settings)
1966
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   737
        try:
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   738
            self.autocomplete_initfunc = kwargs.pop('autocomplete_initfunc')
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   739
        except KeyError:
5367
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5111
diff changeset
   740
            warn('[3.6] use autocomplete_initfunc argument of %s constructor '
1966
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   741
                 'instead of relying on autocomplete_initfuncs dictionary on '
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   742
                 'the entity class' % self.__class__.__name__,
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   743
                 DeprecationWarning)
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   744
            self.autocomplete_initfunc = None
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   745
        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
   746
5367
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5111
diff changeset
   747
    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
   748
        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
   749
        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
   750
            values = ('',)
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5111
diff changeset
   751
        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
   752
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
   753
    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
   754
        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
   755
        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
   756
        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
   757
            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
   758
        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
   759
            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
   760
        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
   761
                            % (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
   762
                               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
   763
        return super(AutoCompletionWidget, self)._render(form, field, renderer)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   764
1875
7bcb02377516 no rschema attribute on widgets
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1874
diff changeset
   765
    def _get_url(self, entity, field):
1966
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   766
        if self.autocomplete_initfunc is None:
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   767
            # XXX for bw compat
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   768
            fname = entity.autocomplete_initfuncs[field.name]
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   769
        else:
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   770
            fname = self.autocomplete_initfunc
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   771
        return entity._cw.build_url('json', fname=fname, mode='remote',
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   772
                                    pageid=entity._cw.pageid)
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   773
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   774
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
   775
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   776
class StaticFileAutoCompletionWidget(AutoCompletionWidget):
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   777
    """XXX describe me"""
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   778
    wdgtype = 'StaticFileSuggestField'
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   779
1875
7bcb02377516 no rschema attribute on widgets
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1874
diff changeset
   780
    def _get_url(self, entity, field):
1966
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   781
        if self.autocomplete_initfunc is None:
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   782
            # XXX for bw compat
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   783
            fname = entity.autocomplete_initfuncs[field.name]
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   784
        else:
87ce7d336393 stop using autocomplete_initfuncs dict on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1934
diff changeset
   785
            fname = self.autocomplete_initfunc
7070
5f8e52d722c5 [web] provide a data_url() method on req and get_rid of explicit datadir_url usage (#1438736)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6931
diff changeset
   786
        return entity._cw.data_url(fname)
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   787
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   788
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   789
class RestrictedAutoCompletionWidget(AutoCompletionWidget):
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   790
    """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
   791
    default_settings = {'mustMatch': True}
1330
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   792
92343a468e2a add some documentation, backport *CompletionWidget
sylvain.thenault@logilab.fr
parents: 1329
diff changeset
   793
4901
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   794
class LazyRestrictedAutoCompletionWidget(RestrictedAutoCompletionWidget):
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   795
    """remote autocomplete """
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   796
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   797
    def values_and_attributes(self, form, field):
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   798
        """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
   799
        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
   800
        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
   801
        if not values[0]:
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   802
            values = form.cw_extra_kwargs.get(field.name,'')
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   803
            if not isinstance(values, (tuple, list)):
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   804
                values = (values,)
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   805
        try:
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   806
            values = list(values)
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   807
            values[0] = int(values[0])
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   808
            attrs['cubicweb:initialvalue'] = values[0]
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   809
            values = (self.display_value_for(form, values[0]),)
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   810
        except (TypeError, ValueError):
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   811
            pass
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   812
        return values, attrs
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   813
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   814
    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
   815
        entity = form._cw.entity_from_eid(value)
4901
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   816
        return entity.view('combobox')
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   817
19ecbbc4f633 LazySuggestField : remote version of RestrictedSuggestField
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4858
diff changeset
   818
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
   819
# more widgets #################################################################
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1425
diff changeset
   820
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   821
class IntervalWidget(FieldWidget):
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   822
    """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
   823
    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
   824
    fields.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   825
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   826
    Exemple usage::
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   827
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   828
      class MyForm(FieldsForm):
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   829
         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
   830
                                       IntField(name='maxprice')),
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   831
                               label=_('price'),
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   832
                               widget=IntervalWidget())
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   833
    """
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   834
    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
   835
        actual_fields = field.fields
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   836
        assert len(actual_fields) == 2
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   837
        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
   838
            form._cw._('from_interval_start'),
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   839
            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
   840
            form._cw._('to_interval_end'),
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   841
            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
   842
            )
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   843
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   844
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   845
class HorizontalLayoutWidget(FieldWidget):
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   846
    """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
   847
    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
   848
    """
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   849
    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
   850
        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
   851
            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
   852
            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
   853
                              'input': f.render(form, renderer)}
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   854
                      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
   855
        else:
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   856
            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
   857
        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
   858
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   859
4375
6d34e3cf60a3 cleanup base class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4373
diff changeset
   860
class EditableURLWidget(FieldWidget):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   861
    """Custom widget to edit separatly an url path / query string (used by
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   862
    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
   863
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   864
    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
   865
    """
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
   866
4372
0c44af150a49 introduce a default render implementation on the base widget, which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4371
diff changeset
   867
    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
   868
        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
   869
        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
   870
        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
   871
        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
   872
        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
   873
            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
   874
            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
   875
        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
   876
            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
   877
                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
   878
            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
   879
                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
   880
            if value:
d74098d1b69f fix bug when value is None
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4508
diff changeset
   881
                try:
d74098d1b69f fix bug when value is None
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4508
diff changeset
   882
                    path, qs = value.split('?', 1)
d74098d1b69f fix bug when value is None
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4508
diff changeset
   883
                except ValueError:
d74098d1b69f fix bug when value is None
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4508
diff changeset
   884
                    path = value
d74098d1b69f fix bug when value is None
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4508
diff changeset
   885
                    qs = ''
d74098d1b69f fix bug when value is None
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4508
diff changeset
   886
            else:
d74098d1b69f fix bug when value is None
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4508
diff changeset
   887
                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
   888
            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
   889
        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
   890
        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
   891
            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
   892
        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
   893
            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
   894
        # 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
   895
        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
   896
                  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
   897
                  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
   898
                  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
   899
                  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
   900
                  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
   901
                  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
   902
        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
   903
            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
   904
        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
   905
            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
   906
        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
   907
        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
   908
        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
   909
                   u'</td></tr></table>']
4376
839b28a3652e surrounding div necessary for proper error localization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4375
diff changeset
   910
        # surrounding div necessary for proper error localization
4508
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   911
        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
   912
            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
   913
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
   914
    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
   915
        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
   916
        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
   917
        path = req.form.get(field.input_name(form, 'path'))
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   918
        if isinstance(path, basestring):
6682
bdf9424b499c test and fix #1232202: [bookmarks] broken link for startupviews
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6449
diff changeset
   919
            path = path.strip()
bdf9424b499c test and fix #1232202: [bookmarks] broken link for startupviews
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6449
diff changeset
   920
        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
   921
            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
   922
        fqs = req.form.get(field.input_name(form, 'fqs'))
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   923
        if isinstance(fqs, basestring):
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   924
            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
   925
            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
   926
                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
   927
                    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
   928
                    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
   929
                        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
   930
                            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
   931
                        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
   932
                            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
   933
                        # value will be url quoted by build_url_params
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   934
                        values.setdefault(key.encode(req.encoding), []).append(val)
3d731478d9a8 new field's responsibility POC: EditableURLWidget allow to edit Bookmark.path in two separated fields, displaying unquoted values which are requoted on form post processing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   935
        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
   936
            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
   937
        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
   938
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
   939
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
   940
# form controls ######################################################################
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
   941
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
   942
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
   943
    """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
   944
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
   945
    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
   946
    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
   947
    """
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
   948
    type = 'button'
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
   949
    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
   950
                 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
   951
                 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
   952
        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
   953
        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
   954
            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
   955
            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
   956
        else:
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
   957
            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
   958
            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
   959
        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
   960
        self.value = ''
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
   961
        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
   962
        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
   963
        self.attrs.setdefault('class', 'validateButton')
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
   964
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
   965
    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
   966
        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
   967
        attrs = self.attrs.copy()
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
   968
        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
   969
            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
   970
            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
   971
                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
   972
        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
   973
            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
   974
        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
   975
            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
   976
            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
   977
                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
   978
        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
   979
            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
   980
        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
   981
            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
   982
        else:
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
   983
            img = u''
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
   984
        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
   985
                           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
   986
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
   987
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
   988
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
   989
    """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
   990
    type = 'submit'
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
   991
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
   992
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
   993
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
   994
    """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
   995
    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
   996
    """
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
   997
    type = 'reset'
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
   998
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
   999
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1000
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
  1001
    """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
  1002
    javascript call).
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1003
    """
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1004
    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
  1005
        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
  1006
        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
  1007
        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
  1008
        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
  1009
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1010
    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
  1011
        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
  1012
        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
  1013
        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
  1014
               '<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
  1015
            '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
  1016
            'domid': self.domid, 'href': self.href}
b619531ddbd2 [widgets] move form controls at the end of the file
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5383
diff changeset
  1017
6890
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1018
class InOutWidget(Select):
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1019
    needs_js = ('cubicweb.widgets.js', )
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1020
    template = """
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1021
<table id="%(widgetid)s">
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1022
<tr><td>%(inoutinput)s</td>
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1023
    <td><div style="margin-bottom:3px">%(addinput)s</div> <div>%(removeinput)s</div></td>
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1024
    <td>%(resinput)s</td></tr>
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1025
</table>
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1026
"""
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1027
    add_button = """<input type="button" id="cwinoutadd"  class="wdgButton cwinoutadd" value="&gt;&gt;" size="10" />"""
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1028
    remove_button ="""<input type="button" class="wdgButton cwinoutremove" value="&lt;&lt;" size="10" />"""
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1029
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1030
    def __init__(self, attrs=None):
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1031
        super(InOutWidget, self).__init__(attrs, multiple=True)
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1032
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1033
    def render_select(self, form, field, name, selected=False):
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1034
        values, attrs = self.values_and_attributes(form, field)
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1035
        options = []
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1036
        inputs = []
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1037
        for _option in field.vocabulary(form):
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1038
            try:
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1039
                label, value, oattrs = _option
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1040
            except ValueError:
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1041
                label, value = _option
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1042
            if selected:
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1043
                # add values
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1044
                if value in values:
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1045
                    options.append(tags.option(label, value=value))
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1046
                    # add hidden inputs
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1047
                    inputs.append(tags.input(value=value, name=field.dom_id(form), type="hidden"))
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1048
            else:
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1049
                options.append(tags.option(label, value=value))
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1050
        if 'size' not in attrs:
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1051
            attrs['size'] = 5
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1052
        if 'id' in attrs :
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1053
            attrs.pop('id')
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1054
        return tags.select(name=name, multiple=self._multiple, id=name,
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1055
                           options=options, **attrs) + '\n'.join(inputs)
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1056
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1057
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1058
    def _render(self, form, field, renderer):
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1059
        domid = field.dom_id(form)
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1060
        jsnodes = {'widgetid': domid, 'from': 'from_' + domid, 'to': 'to_' + domid}
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1061
        form._cw.add_onload(u'$(cw.jqNode("%s")).cwinoutwidget("%s", "%s");'
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1062
                            % (jsnodes['widgetid'], jsnodes['from'], jsnodes['to']))
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1063
        field.required=True
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1064
        return self.template % {'widgetid': jsnodes['widgetid'],
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1065
                                'inoutinput' : self.render_select(form, field, jsnodes['from']), # helpinfo select tag
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1066
                                'resinput' : self.render_select(form, field, jsnodes['to'], selected=True), # select tag with resultats
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1067
                                'addinput' : self.add_button % jsnodes,
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1068
                                'removeinput': self.remove_button % jsnodes
1b2fcb9356a3 [widgets, js] add a InOutWidget for multiple select
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 6880
diff changeset
  1069
                                }