refactor button handling tls-sprint
authorsylvain.thenault@logilab.fr
Wed, 08 Apr 2009 20:34:26 +0200
branchtls-sprint
changeset 1304 8975c8e520a9
parent 1303 62be4ece4552
child 1305 395ef7f2b95b
refactor button handling
web/form.py
web/formrenderers.py
web/formwidgets.py
web/views/editforms.py
web/views/massmailing.py
web/views/workflow.py
--- a/web/form.py	Wed Apr 08 20:30:58 2009 +0200
+++ b/web/form.py	Wed Apr 08 20:34:26 2009 +0200
@@ -209,15 +209,14 @@
     cssclass = None
     cssstyle = None
     cwtarget = None
-    buttons = None
     redirect_path = None
     set_error_url = True
     copy_nav_params = False
+    form_buttons = None # form buttons (button widgets instances)
                  
     def __init__(self, req, rset=None, row=None, col=None, submitmsg=None,
                  **kwargs):
         super(FieldsForm, self).__init__(req, rset, row=row, col=col)
-        self.buttons = kwargs.pop('buttons', [])
         for key, val in kwargs.items():
             assert hasattr(self.__class__, key) and not key[0] == '_', key
             setattr(self, key, val)
@@ -290,6 +289,7 @@
             values.update(previous_values)
         for field in self.fields:
             for field in field.actual_fields(self):
+                field.form_init(self)
                 value = self.form_field_value(field, values)
                 context[field] = {'value': field.format_value(self.req, value),
                                   'rawvalue': value,
@@ -335,9 +335,6 @@
     def form_field_vocabulary(self, field, limit=None):
         raise NotImplementedError
 
-    def form_buttons(self):
-        return self.buttons
-
    
 class EntityFieldsForm(FieldsForm):
     __select__ = (match_kwargs('entity') | (one_line_rset & non_final_entity()))
--- a/web/formrenderers.py	Wed Apr 08 20:30:58 2009 +0200
+++ b/web/formrenderers.py	Wed Apr 08 20:34:26 2009 +0200
@@ -169,8 +169,8 @@
 
     def render_buttons(self, w, form):
         w(u'<table class="%s">\n<tr>\n' % self.button_bar_class)
-        for button in form.form_buttons():
-            w(u'<td>%s</td>\n' % button)
+        for button in form.form_buttons:
+            w(u'<td>%s</td>\n' % button.render(form))
         w(u'</tr></table>')
 
 
@@ -243,8 +243,7 @@
             super(EntityFormRenderer, self)._render_fields(fields, w, form, values)
             
     def render_buttons(self, w, form):
-        buttons = form.form_buttons()
-        if len(buttons) == 3:
+        if len(form.form_buttons) == 3:
             w("""<table width="100%%">
   <tbody>
    <tr><td align="center">
@@ -254,7 +253,7 @@
      %s
    </td></tr>
   </tbody>
- </table>""" % tuple(buttons))
+ </table>""" % tuple(button.render(form) for button in form.form_buttons))
         else:
             super(EntityFormRenderer, self).render_buttons(w, form)
         
--- a/web/formwidgets.py	Wed Apr 08 20:30:58 2009 +0200
+++ b/web/formwidgets.py	Wed Apr 08 20:34:26 2009 +0200
@@ -9,6 +9,7 @@
 from datetime import date
 
 from cubicweb.common import tags
+from cubicweb.web import stdmsgs
 
 class FieldWidget(object):
     needs_js = ()
@@ -228,3 +229,56 @@
         self.add_media(form)
         attrs = self._render_attrs(form, field)[-1]
         return tags.div(**attrs)
+
+
+class Button(Input):
+    type = 'button'
+    def __init__(self, label=stdmsgs.BUTTON_OK, attrs=None,
+                 setdomid=None, settabindex=None,
+                 name='', value='', onclick=None, cwaction=None):
+        super(Button, self).__init__(attrs, setdomid, settabindex)
+        self.label = label
+        self.name = name
+        self.value = ''
+        self.onclick = onclick
+        self.cwaction = cwaction
+        self.attrs.setdefault('klass', 'validateButton')
+                
+    def render(self, form, field=None):
+        label = form.req._(self.label)
+        attrs = self.attrs.copy()
+        if self.cwaction:
+            assert self.onclick is None
+            attrs['onclick'] = "postForm('__action_%s', \'%s\', \'%s\')" % (
+                self.cwaction, self.label, form.domid)
+        elif self.onclick:
+            attrs['onclick'] = self.onclick
+        if self.name:
+            attrs['name'] = name
+            if self.setdomid:
+                attrs['id'] = self.name
+        if self.settabindex and not 'tabindex' in attrs:
+            attrs['tabindex'] = form.req.next_tabindex()
+        return tags.input(value=label, type=self.type, **attrs)
+
+    
+class SubmitButton(Button):
+    type = 'submit'
+    
+class ResetButton(Button):
+    type = 'reset'
+
+class ImgButton(object):
+    def __init__(self, domid, href, label, imgressource):
+        self.domid = domid
+        self.href = href
+        self.imgressource = imgressource
+        self.label = label
+        
+    def render(self, form, field=None):
+        self.imgsrc = form.req.external_resource(self.imgressource)
+        return '<a id="%(domid)s" href="%(href)s"><img src="%(imgsrc)s" alt="%(label)s"/>%(label)s</a>' % self.__dict__
+
+    
+# XXX EntityLinkComboBoxWidget, AddComboBoxWidget, AutoCompletionWidget,
+#     StaticFileAutoCompletionWidget, RestrictedAutoCompletionWidget...
--- a/web/views/editforms.py	Wed Apr 08 20:30:58 2009 +0200
+++ b/web/views/editforms.py	Wed Apr 08 20:34:26 2009 +0200
@@ -24,6 +24,7 @@
 from cubicweb.web.form import (FieldNotFound, CompositeForm, EntityFieldsForm,
                                FormMixIn)
 from cubicweb.web.formfields import guess_field
+from cubicweb.web.formwidgets import Button, SubmitButton, ResetButton
 from cubicweb.web.formrenderers import (FormRenderer, EntityFormRenderer,
                                         EntityCompositeFormRenderer,
                                         EntityInlinedFormRenderer)
@@ -61,11 +62,10 @@
           % _('this action is not reversible!'))
         # XXX above message should have style of a warning
         w(u'<h4>%s</h4>\n' % _('Do you want to delete the following element(s) ?'))
-        form = CompositeForm(req, domid='deleteconf', action=self.build_url('edit'),
-                                  onsubmit=self.onsubmit, copy_nav_params=True)
-        # XXX tabindex
-        form.buttons.append(form.button_delete(label=stdmsgs.YES))
-        form.buttons.append(form.button_cancel(label=stdmsgs.NO))
+        form = CompositeForm(req, domid='deleteconf', copy_nav_params=True,
+                             action=self.build_url('edit'), onsubmit=None,
+                             form_buttons=[Button(stdmsgs.YES, cwaction='delete'),
+                                           Button(stdmsgs.NO, cwaction='cancel')])
         done = set()
         w(u'<ul>\n')
         for entity in self.rset.entities():
@@ -110,17 +110,11 @@
         edit_key = make_uid('%s-%s' % (rtype, eid))
         divid = 'd%s' % edit_key
         reload = dumps(reload)
-        # XXX tab index
-        buttons = [tags.input(klass="validateButton", type="submit",
-                              name="__action_apply",
-                              value=self.req._(stdmsgs.BUTTON_OK),
-                              tabindex=self.req.next_tabindex()),
-                   tags.input(klass="validateButton", type="button",
-                              value=self.req._(stdmsgs.BUTTON_CANCEL),
-                              onclick="cancelInlineEdit(%s,\'%s\',\'%s\')" % (eid, rtype, divid),
-                              tabindex=self.req.next_tabindex())]
+        buttons = [SubmitButton(stdmsgs.BUTTON_OK, cwaction='apply'),
+                   Button(stdmsgs.BUTTON_CANCEL,
+                          onclick="cancelInlineEdit(%s,\'%s\',\'%s\')" % (eid, rtype, divid))]
         form = self.vreg.select_object('forms', 'edition', self.req, self.rset,
-                                       row=row, col=col, buttons=buttons,
+                                       row=row, col=col, form_buttons=buttons,
                                        domid='%s-form' % divid, action='#',
                                        cssstyle='display: none',
                                        onsubmit=self.onsubmit % locals())
@@ -147,6 +141,9 @@
     cwtarget = 'eformframe'
     cssclass = 'entityForm'
     copy_nav_params = True
+    form_buttons = [SubmitButton(stdmsgs.BUTTON_OK),
+                    Button(stdmsgs.BUTTON_APPLY, cwaction='apply'),
+                    Button(stdmsgs.BUTTON_CANCEL, cwaction='cancel')]    
     attrcategories = ('primary', 'secondary')
     # class attributes below are actually stored in the uicfg module since we
     # don't want them to be reloaded
@@ -338,12 +335,6 @@
         
     action = property(action, set_action)
     
-    def form_buttons(self):
-        """return the form's buttons (as string)"""
-        return [self.button_ok(tabindex=self.req.next_tabindex()),
-                self.button_apply(tabindex=self.req.next_tabindex()),
-                self.button_cancel(tabindex=self.req.next_tabindex())]
-
     def editable_attributes(self):
         """return a list of (relation schema, role) to edit for the entity"""
         return [(rschema, x) for rschema, _, x in self.relations_by_category(
@@ -548,6 +539,8 @@
 class TableEditForm(CompositeForm):
     id = 'muledit'
     onsubmit = "return validateForm('entityForm', null);"
+    form_buttons = [SubmitButton(_('validate modifications on selected items')),
+                    ResetButton(_('revert changes'))]
     
     def __init__(self, *args, **kwargs):
         super(TableEditForm, self).__init__(*args, **kwargs)
@@ -560,12 +553,6 @@
             form.remove_field(form.field_by_name('eid'))
             self.form_add_subform(form)
 
-    def form_buttons(self):
-        """return the form's buttons (as string)"""
-        okt = self.req._('validate modifications on selected items').capitalize()
-        resett = self.req._('revert changes').capitalize()
-        return [self.button_ok(title=okt), self.button_reset(title=resett)]
-
         
 class TableEditFormView(EntityView):
     id = 'muledit'
--- a/web/views/massmailing.py	Wed Apr 08 20:30:58 2009 +0200
+++ b/web/views/massmailing.py	Wed Apr 08 20:34:26 2009 +0200
@@ -15,7 +15,7 @@
 from cubicweb.web.action import Action
 from cubicweb.web.form import FieldsForm, FormRenderer
 from cubicweb.web.formfields import StringField
-from cubicweb.web.formwidgets import CheckBox, TextInput, AjaxWidget
+from cubicweb.web.formwidgets import CheckBox, TextInput, AjaxWidget, ImgButton
 
 
 class SendEmailAction(Action):
@@ -42,7 +42,11 @@
     subject = StringField(label=_('Subject:'))
     mailbody = StringField(widget=AjaxWidget(wdgtype='TemplateTextField',
                                              inputid='mailarea'))
-
+    form_buttons = [ImgButton('sendbutton', "javascript: $('sendmail').submit()",
+                              _('send email'), 'SEND_EMAIL_ICON'),
+                    ImgButton('cancelbutton', "javascript: history.back()",
+                              stdmsgs.BUTTON_CANCEL, 'CANCEL_EMAIL_ICON')]                    
+                              
     def form_field_vocabulary(self, field):
         if field.name == 'recipient':
             vocab = [(entity.get_email(), entity.eid) for entity in self.rset.entities()]
@@ -55,19 +59,6 @@
         elif field.name == 'mailbody':
             field.widget.attrs['cubicweb:variables'] = self.get_allowed_substitutions()
         return super(MassMailingForm, self).form_field_value(field, values)
-
-    def form_buttons(self):
-        context = {'domid': self.domid,
-                   'cancel' : self.req._(stdmsgs.BUTTON_CANCEL),
-                   'cancelimgpath' : self.req.external_resource('CANCEL_EMAIL_ICON'),
-                   'send' : self.req._('send email'),
-                   'sendimgpath' : self.req.external_resource('SEND_EMAIL_ICON'),
-                   }
-        return ['''<a id="sendbutton" href="javascript: $('%(domid)s').submit()">
-<img src="%(sendimgpath)s" alt="%(send)s"/>%(send)s</a>''' % context,
-                '''<a id="cancelbutton" href="javascript: history.back()">
-<img src="%(cancelimgpath)s" alt="%(cancel)s"/>%(cancel)s</a>''' % context,
-                ]
     
     def get_allowed_substitutions(self):
         attrs = []
--- a/web/views/workflow.py	Wed Apr 08 20:30:58 2009 +0200
+++ b/web/views/workflow.py	Wed Apr 08 20:34:26 2009 +0200
@@ -18,7 +18,7 @@
 from cubicweb.interfaces import IWorkflowable
 from cubicweb.web import stdmsgs, action, component, form
 from cubicweb.web.formfields import StringField,  RichTextField
-from cubicweb.web.formwidgets import HiddenInput
+from cubicweb.web.formwidgets import HiddenInput, SubmitButton, Button
 from cubicweb.web.views import TmpFileViewMixin
 from cubicweb.web.views.boxes import EditBox
 
@@ -37,12 +37,8 @@
     __method = StringField(name='__method', initial='set_state', widget=HiddenInput)
     state = StringField(widget=HiddenInput, eidparam=True)
     trcomment = RichTextField(eidparam=True)
-
-    def form_buttons(self):
-        return [self.button_ok(label=stdmsgs.YES,
-                               tabindex=self.req.next_tabindex()),
-                self.button_cancel(label=stdmsgs.NO,
-                                   tabindex=self.req.next_tabindex())]
+    form_buttons = [SubmitButton(stdmsgs.YES),
+                     Button(stdmsgs.NO, cwaction='cancel')]
 
         
 class ChangeStateFormView(view.EntityView):