[web] remove next_tabindex()
authorJulien Cristau <julien.cristau@logilab.fr>
Thu, 19 Nov 2015 12:25:45 +0100
changeset 11875 011730a4af73
parent 11874 ea1d92b677b5
child 11876 b35e21fc1f9b
[web] remove next_tabindex() It's hard to see it work reliably in view of multiple server processes. If something like that is needed it should probably be built on the client (js) side.
cubicweb/web/data/cubicweb.edition.js
cubicweb/web/formwidgets.py
cubicweb/web/request.py
cubicweb/web/test/unittest_form.py
cubicweb/web/test/unittest_formwidgets.py
cubicweb/web/test/unittest_reledit.py
cubicweb/web/views/autoform.py
cubicweb/web/views/basecomponents.py
cubicweb/web/views/boxes.py
cubicweb/web/views/cwproperties.py
doc/book/devweb/edition/dissection.rst
doc/book/devweb/request.rst
--- a/cubicweb/web/data/cubicweb.edition.js	Wed Nov 23 17:19:51 2016 +0100
+++ b/cubicweb/web/data/cubicweb.edition.js	Thu Nov 19 12:25:45 2015 +0100
@@ -9,7 +9,7 @@
 
 //============= Eproperty form functions =====================================//
 /**
- * .. function:: setPropValueWidget(varname, tabindex)
+ * .. function:: setPropValueWidget(varname)
  *
  * called on CWProperty key selection:
  * - get the selected value
@@ -17,16 +17,15 @@
  * - fill associated div with the returned html
  *
  * * `varname`, the name of the variable as used in the original creation form
- * * `tabindex`, the tabindex that should be set on the widget
  */
 
-function setPropValueWidget(varname, tabindex) {
+function setPropValueWidget(varname) {
     var key = firstSelected(document.getElementById('pkey-subject:' + varname));
     if (key) {
         var args = {
             fname: 'prop_widget',
             pageid: pageid,
-            arg: $.map([key.value, varname, tabindex], JSON.stringify)
+            arg: $.map([key.value, varname], JSON.stringify)
         };
         cw.jqNode('div:value-subject:' + varname).loadxhtml(AJAX_BASE_URL, args, 'post');
     }
--- a/cubicweb/web/formwidgets.py	Wed Nov 23 17:19:51 2016 +0100
+++ b/cubicweb/web/formwidgets.py	Thu Nov 19 12:25:45 2015 +0100
@@ -125,9 +125,6 @@
     :attr:`setdomid`
        flag telling if HTML DOM identifier should be set on input.
 
-    :attr:`settabindex`
-       flag telling if HTML tabindex attribute of inputs should be set.
-
     :attr:`suffix`
        string to use a suffix when generating input, to ease usage as a
        sub-widgets (eg widget used by another widget)
@@ -157,21 +154,17 @@
     needs_js = ()
     needs_css = ()
     setdomid = True
-    settabindex = True
     suffix = None
     # does this widget expect a vocabulary
     vocabulary_widget = False
 
-    def __init__(self, attrs=None, setdomid=None, settabindex=None, suffix=None):
+    def __init__(self, attrs=None, setdomid=None, suffix=None):
         if attrs is None:
             attrs = {}
         self.attrs = attrs
         if setdomid is not None:
             # override class's default value
             self.setdomid = setdomid
-        if settabindex is not None:
-            # override class's default value
-            self.settabindex = settabindex
         if suffix is not None:
             self.suffix = suffix
 
@@ -202,14 +195,11 @@
 
     def attributes(self, form, field):
         """Return HTML attributes for the widget, automatically setting DOM
-        identifier and tabindex when desired (see :attr:`setdomid` and
-        :attr:`settabindex` attributes)
+        identifier when desired (see :attr:`setdomid` attribute)
         """
         attrs = dict(self.attrs)
         if self.setdomid:
             attrs['id'] = field.dom_id(form, self.suffix)
-        if self.settabindex and 'tabindex' not in attrs:
-            attrs['tabindex'] = form._cw.next_tabindex()
         if 'placeholder' in attrs:
             attrs['placeholder'] = form._cw._(attrs['placeholder'])
         return attrs
@@ -386,7 +376,6 @@
     """
     type = 'hidden'
     setdomid = False  # by default, don't set id attribute on hidden input
-    settabindex = False
 
 
 class ButtonInput(Input):
@@ -996,8 +985,6 @@
         attrs = dict(self.attrs)
         if self.setdomid:
             attrs['id'] = field.dom_id(form)
-        if self.settabindex and 'tabindex' not in attrs:
-            attrs['tabindex'] = req.next_tabindex()
         # ensure something is rendered
         inputs = [u'<table><tr><th>',
                   req._('i18n_bookmark_url_path'),
@@ -1008,8 +995,6 @@
                   u'</th><td>']
         if self.setdomid:
             attrs['id'] = field.dom_id(form, 'fqs')
-        if self.settabindex:
-            attrs['tabindex'] = req.next_tabindex()
         attrs.setdefault('cols', 60)
         attrs.setdefault('onkeyup', 'autogrow(this)')
         inputs += [tags.textarea(fqs, name=fqsqname, **attrs),
@@ -1057,9 +1042,9 @@
     css_class = 'validateButton'
 
     def __init__(self, label=stdmsgs.BUTTON_OK, attrs=None,
-                 setdomid=None, settabindex=None,
+                 setdomid=None,
                  name='', value='', onclick=None, cwaction=None):
-        super(Button, self).__init__(attrs, setdomid, settabindex)
+        super(Button, self).__init__(attrs, setdomid)
         if isinstance(label, tuple):
             self.label = label[0]
             self.icon = label[1]
@@ -1085,8 +1070,6 @@
             attrs['name'] = self.name
             if self.setdomid:
                 attrs['id'] = self.name
-        if self.settabindex and 'tabindex' not in attrs:
-            attrs['tabindex'] = form._cw.next_tabindex()
         if self.icon:
             img = tags.img(src=form._cw.uiprops[self.icon], alt=self.icon)
         else:
--- a/cubicweb/web/request.py	Wed Nov 23 17:19:51 2016 +0100
+++ b/cubicweb/web/request.py	Thu Nov 19 12:25:45 2015 +0100
@@ -215,13 +215,6 @@
         """
         return self.set_varmaker()
 
-    def next_tabindex(self):
-        nextfunc = self.get_page_data('nexttabfunc')
-        if nextfunc is None:
-            nextfunc = Counter(1)
-            self.set_page_data('nexttabfunc', nextfunc)
-        return nextfunc()
-
     def set_varmaker(self):
         varmaker = self.get_page_data('rql_varmaker')
         if varmaker is None:
--- a/cubicweb/web/test/unittest_form.py	Wed Nov 23 17:19:51 2016 +0100
+++ b/cubicweb/web/test/unittest_form.py	Thu Nov 19 12:25:45 2015 +0100
@@ -200,20 +200,20 @@
     def test_richtextfield_1(self):
         with self.admin_access.web_request() as req:
             req.use_fckeditor = lambda: False
-            self._test_richtextfield(req, '''<select id="description_format-subject:%(eid)s" name="description_format-subject:%(eid)s" size="1" style="display: block" tabindex="1">
+            self._test_richtextfield(req, '''<select id="description_format-subject:%(eid)s" name="description_format-subject:%(eid)s" size="1" style="display: block">
 ''' + ('<option value="text/cubicweb-page-template">text/cubicweb-page-template</option>\n'
 if HAS_TAL else '') +
 '''<option selected="selected" value="text/html">text/html</option>
 <option value="text/markdown">text/markdown</option>
 <option value="text/plain">text/plain</option>
 <option value="text/rest">text/rest</option>
-</select><textarea cols="80" id="description-subject:%(eid)s" name="description-subject:%(eid)s" onkeyup="autogrow(this)" rows="2" tabindex="2"></textarea>''')
+</select><textarea cols="80" id="description-subject:%(eid)s" name="description-subject:%(eid)s" onkeyup="autogrow(this)" rows="2"></textarea>''')
 
 
     def test_richtextfield_2(self):
         with self.admin_access.web_request() as req:
             req.use_fckeditor = lambda: True
-            self._test_richtextfield(req, '<input name="description_format-subject:%(eid)s" type="hidden" value="text/html" /><textarea cols="80" cubicweb:type="wysiwyg" id="description-subject:%(eid)s" name="description-subject:%(eid)s" onkeyup="autogrow(this)" rows="2" tabindex="1"></textarea>')
+            self._test_richtextfield(req, '<input name="description_format-subject:%(eid)s" type="hidden" value="text/html" /><textarea cols="80" cubicweb:type="wysiwyg" id="description-subject:%(eid)s" name="description-subject:%(eid)s" onkeyup="autogrow(this)" rows="2"></textarea>')
 
 
     def test_filefield(self):
@@ -229,11 +229,11 @@
                                      data=Binary(b'new widgets system'))
             form = FFForm(req, redirect_path='perdu.com', entity=file)
             self.assertMultiLineEqual(self._render_entity_field(req, 'data', form),
-                              '''<input id="data-subject:%(eid)s" name="data-subject:%(eid)s" tabindex="1" type="file" value="" />
+                              '''<input id="data-subject:%(eid)s" name="data-subject:%(eid)s" type="file" value="" />
 <a href="javascript: toggleVisibility(&#39;data-subject:%(eid)s-advanced&#39;)" title="show advanced fields"><img src="http://testing.fr/cubicweb/data/puce_down.png" alt="show advanced fields"/></a>
 <div id="data-subject:%(eid)s-advanced" class="hidden">
-<label for="data_format-subject:%(eid)s">data_format</label><input id="data_format-subject:%(eid)s" maxlength="50" name="data_format-subject:%(eid)s" size="45" tabindex="2" type="text" value="text/plain" /><br/>
-<label for="data_encoding-subject:%(eid)s">data_encoding</label><input id="data_encoding-subject:%(eid)s" maxlength="20" name="data_encoding-subject:%(eid)s" size="20" tabindex="3" type="text" value="UTF-8" /><br/>
+<label for="data_format-subject:%(eid)s">data_format</label><input id="data_format-subject:%(eid)s" maxlength="50" name="data_format-subject:%(eid)s" size="45" type="text" value="text/plain" /><br/>
+<label for="data_encoding-subject:%(eid)s">data_encoding</label><input id="data_encoding-subject:%(eid)s" maxlength="20" name="data_encoding-subject:%(eid)s" size="20" type="text" value="UTF-8" /><br/>
 </div>
 <br/>
 <input name="data-subject__detach:%(eid)s" type="checkbox" />
@@ -253,17 +253,17 @@
                                      data=Binary(b'new widgets system'))
             form = EFFForm(req, redirect_path='perdu.com', entity=file)
             self.assertMultiLineEqual(self._render_entity_field(req, 'data', form),
-                              '''<input id="data-subject:%(eid)s" name="data-subject:%(eid)s" tabindex="1" type="file" value="" />
+                              '''<input id="data-subject:%(eid)s" name="data-subject:%(eid)s" type="file" value="" />
 <a href="javascript: toggleVisibility(&#39;data-subject:%(eid)s-advanced&#39;)" title="show advanced fields"><img src="http://testing.fr/cubicweb/data/puce_down.png" alt="show advanced fields"/></a>
 <div id="data-subject:%(eid)s-advanced" class="hidden">
-<label for="data_format-subject:%(eid)s">data_format</label><input id="data_format-subject:%(eid)s" maxlength="50" name="data_format-subject:%(eid)s" size="45" tabindex="2" type="text" value="text/plain" /><br/>
-<label for="data_encoding-subject:%(eid)s">data_encoding</label><input id="data_encoding-subject:%(eid)s" maxlength="20" name="data_encoding-subject:%(eid)s" size="20" tabindex="3" type="text" value="UTF-8" /><br/>
+<label for="data_format-subject:%(eid)s">data_format</label><input id="data_format-subject:%(eid)s" maxlength="50" name="data_format-subject:%(eid)s" size="45" type="text" value="text/plain" /><br/>
+<label for="data_encoding-subject:%(eid)s">data_encoding</label><input id="data_encoding-subject:%(eid)s" maxlength="20" name="data_encoding-subject:%(eid)s" size="20" type="text" value="UTF-8" /><br/>
 </div>
 <br/>
 <input name="data-subject__detach:%(eid)s" type="checkbox" />
 detach attached file
 <p><b>You can either submit a new file using the browse button above, or choose to remove already uploaded file by checking the "detach attached file" check-box, or edit file content online with the widget below.</b></p>
-<textarea cols="80" name="data-subject:%(eid)s" onkeyup="autogrow(this)" rows="3" tabindex="4">new widgets system</textarea>''' % {'eid': file.eid})
+<textarea cols="80" name="data-subject:%(eid)s" onkeyup="autogrow(this)" rows="3">new widgets system</textarea>''' % {'eid': file.eid})
 
     def _modified_tzdatenaiss(self, eid, datestr, timestr):
         ctx = {'tzdatenaiss-subjectdate:%d' % eid: datestr,
@@ -297,9 +297,9 @@
         with self.admin_access.web_request() as req:
             form = PFForm(req, redirect_path='perdu.com', entity=req.user)
             self.assertMultiLineEqual(self._render_entity_field(req, 'upassword', form),
-                                  '''<input id="upassword-subject:%(eid)s" name="upassword-subject:%(eid)s" tabindex="1" type="password" value="" />
+                                  '''<input id="upassword-subject:%(eid)s" name="upassword-subject:%(eid)s" type="password" value="" />
 <br/>
-<input name="upassword-subject-confirm:%(eid)s" tabindex="1" type="password" value="" />
+<input name="upassword-subject-confirm:%(eid)s" type="password" value="" />
 &#160;
 <span class="emphasis">confirm password</span>''' % {'eid': req.user.eid})
 
--- a/cubicweb/web/test/unittest_formwidgets.py	Wed Nov 23 17:19:51 2016 +0100
+++ b/cubicweb/web/test/unittest_formwidgets.py	Thu Nov 19 12:25:45 2015 +0100
@@ -38,7 +38,7 @@
     def test_bitselect_widget(self):
         field = formfields.guess_field(self.schema['CWAttribute'], self.schema['ordernum'])
         field.choices = [('un', '1',), ('deux', '2',)]
-        widget = formwidgets.BitSelect(settabindex=False)
+        widget = formwidgets.BitSelect()
         req = fake.FakeRequest(form={'ordernum-subject:A': ['1', '2']})
         form = mock(_cw=req, formvalues={}, edited_entity=mock(eid='A'),
                     form_previous_values=())
@@ -62,7 +62,7 @@
             field = form.field_by_name('bool')
             widget = field.widget
             self.assertMultiLineEqual(widget._render(form, field, None),
-                '<label><input id="bool" name="bool" tabindex="1" '
+                '<label><input id="bool" name="bool" '
                 'type="checkbox" value="1" />&#160;'
                 'python &gt;&gt; others</label>')
 
--- a/cubicweb/web/test/unittest_reledit.py	Wed Nov 23 17:19:51 2016 +0100
+++ b/cubicweb/web/test/unittest_reledit.py	Thu Nov 19 12:25:45 2015 +0100
@@ -73,13 +73,13 @@
 <table class="">
 <tr class="title_subject_row">
 <td>
-<input id="title-subject:%(eid)s" maxlength="32" name="title-subject:%(eid)s" size="32" tabindex="1" type="text" value="cubicweb-world-domination" />
+<input id="title-subject:%(eid)s" maxlength="32" name="title-subject:%(eid)s" size="32" type="text" value="cubicweb-world-domination" />
 </td></tr>
 </table></fieldset>
 <table class="buttonbar">
 <tr>
-<td><button class="validateButton" tabindex="2" type="submit" value="button_ok"><img alt="OK_ICON" src="http://testing.fr/cubicweb/data/ok.png" />button_ok</button></td>
-<td><button class="validateButton" onclick="cw.reledit.cleanupAfterCancel(&#39;title-subject-%(eid)s&#39;)" tabindex="3" type="button" value="button_cancel"><img alt="CANCEL_ICON" src="http://testing.fr/cubicweb/data/cancel.png" />button_cancel</button></td>
+<td><button class="validateButton" type="submit" value="button_ok"><img alt="OK_ICON" src="http://testing.fr/cubicweb/data/ok.png" />button_ok</button></td>
+<td><button class="validateButton" onclick="cw.reledit.cleanupAfterCancel(&#39;title-subject-%(eid)s&#39;)" type="button" value="button_cancel"><img alt="CANCEL_ICON" src="http://testing.fr/cubicweb/data/cancel.png" />button_cancel</button></td>
 </tr></table>
 </fieldset>
 <iframe width="0px" height="0px" src="javascript: void(0);" name="eformframe" id="eformframe"></iframe>
@@ -108,23 +108,23 @@
 <tr class="title_subject_row">
 <th class="labelCol"><label class="required" for="title-subject:A">title</label></th>
 <td>
-<input id="title-subject:A" maxlength="50" name="title-subject:A" size="45" tabindex="4" type="text" value="" />
+<input id="title-subject:A" maxlength="50" name="title-subject:A" size="45" type="text" value="" />
 </td></tr>
 <tr class="description_subject_row">
 <th class="labelCol"><label for="description-subject:A">description</label></th>
 <td>
-<input name="description_format-subject:A" type="hidden" value="text/html" /><textarea cols="80" cubicweb:type="wysiwyg" id="description-subject:A" name="description-subject:A" onkeyup="autogrow(this)" rows="2" tabindex="5"></textarea>
+<input name="description_format-subject:A" type="hidden" value="text/html" /><textarea cols="80" cubicweb:type="wysiwyg" id="description-subject:A" name="description-subject:A" onkeyup="autogrow(this)" rows="2"></textarea>
 </td></tr>
 <tr class="rss_url_subject_row">
 <th class="labelCol"><label for="rss_url-subject:A">rss_url</label></th>
 <td>
-<input id="rss_url-subject:A" maxlength="128" name="rss_url-subject:A" size="45" tabindex="6" type="text" value="" />
+<input id="rss_url-subject:A" maxlength="128" name="rss_url-subject:A" size="45" type="text" value="" />
 </td></tr>
 </table></fieldset>
 <table class="buttonbar">
 <tr>
-<td><button class="validateButton" tabindex="7" type="submit" value="button_ok"><img alt="OK_ICON" src="http://testing.fr/cubicweb/data/ok.png" />button_ok</button></td>
-<td><button class="validateButton" onclick="cw.reledit.cleanupAfterCancel(&#39;long_desc-subject-%(eid)s&#39;)" tabindex="8" type="button" value="button_cancel"><img alt="CANCEL_ICON" src="http://testing.fr/cubicweb/data/cancel.png" />button_cancel</button></td>
+<td><button class="validateButton" type="submit" value="button_ok"><img alt="OK_ICON" src="http://testing.fr/cubicweb/data/ok.png" />button_ok</button></td>
+<td><button class="validateButton" onclick="cw.reledit.cleanupAfterCancel(&#39;long_desc-subject-%(eid)s&#39;)" type="button" value="button_cancel"><img alt="CANCEL_ICON" src="http://testing.fr/cubicweb/data/cancel.png" />button_cancel</button></td>
 </tr></table>
 </fieldset>
 <iframe width="0px" height="0px" src="javascript: void(0);" name="eformframe" id="eformframe"></iframe>
@@ -152,7 +152,7 @@
 <table class="">
 <tr class="manager_subject_row">
 <td>
-<select id="manager-subject:%(eid)s" name="manager-subject:%(eid)s" size="1" tabindex="9">
+<select id="manager-subject:%(eid)s" name="manager-subject:%(eid)s" size="1">
 <option value="__cubicweb_internal_field__"></option>
 <option value="%(toto)s">Toto</option>
 </select>
@@ -160,8 +160,8 @@
 </table></fieldset>
 <table class="buttonbar">
 <tr>
-<td><button class="validateButton" tabindex="10" type="submit" value="button_ok"><img alt="OK_ICON" src="http://testing.fr/cubicweb/data/ok.png" />button_ok</button></td>
-<td><button class="validateButton" onclick="cw.reledit.cleanupAfterCancel(&#39;manager-subject-%(eid)s&#39;)" tabindex="11" type="button" value="button_cancel"><img alt="CANCEL_ICON" src="http://testing.fr/cubicweb/data/cancel.png" />button_cancel</button></td>
+<td><button class="validateButton" type="submit" value="button_ok"><img alt="OK_ICON" src="http://testing.fr/cubicweb/data/ok.png" />button_ok</button></td>
+<td><button class="validateButton" onclick="cw.reledit.cleanupAfterCancel(&#39;manager-subject-%(eid)s&#39;)" type="button" value="button_cancel"><img alt="CANCEL_ICON" src="http://testing.fr/cubicweb/data/cancel.png" />button_cancel</button></td>
 </tr></table>
 </fieldset>
 <iframe width="0px" height="0px" src="javascript: void(0);" name="eformframe" id="eformframe"></iframe>
--- a/cubicweb/web/views/autoform.py	Wed Nov 23 17:19:51 2016 +0100
+++ b/cubicweb/web/views/autoform.py	Thu Nov 19 12:25:45 2015 +0100
@@ -565,9 +565,9 @@
                 w(u'</tr>')
         w(u'<tr id="relationSelectorRow_%s" class="separator">' % eid)
         w(u'<th class="labelCol">')
-        w(u'<select id="relationSelector_%s" tabindex="%s" '
+        w(u'<select id="relationSelector_%s" '
           'onchange="javascript:showMatchingSelect(this.options[this.selectedIndex].value,%s);">'
-          % (eid, req.next_tabindex(), xml_escape(json_dumps(eid))))
+          % (eid, xml_escape(json_dumps(eid))))
         w(u'<option value="">%s</option>' % _('select a relation'))
         for i18nrtype, rschema, role in field.relations:
             # more entities to link to
--- a/cubicweb/web/views/basecomponents.py	Wed Nov 23 17:19:51 2016 +0100
+++ b/cubicweb/web/views/basecomponents.py	Thu Nov 19 12:25:45 2015 +0100
@@ -66,9 +66,9 @@
             self._cw.add_onload('$("#rql").autocomplete({source: "%s"});'
                                 % (req.build_url('json', fname='rql_suggest')))
         self.w(u'''<div id="rqlinput" class="%s"><form action="%s"><fieldset>
-<input type="text" id="rql" name="rql" value="%s"  title="%s" tabindex="%s" accesskey="q" class="searchField" />
+<input type="text" id="rql" name="rql" value="%s"  title="%s" accesskey="q" class="searchField" />
 ''' % (not self.cw_propval('visible') and 'hidden' or '',
-       req.build_url('view'), xml_escape(rql), req._('full text or RQL query'), req.next_tabindex()))
+       req.build_url('view'), xml_escape(rql), req._('full text or RQL query')))
         if req.search_state[0] != 'normal':
             self.w(u'<input type="hidden" name="__mode" value="%s"/>'
                    % ':'.join(req.search_state[1]))
--- a/cubicweb/web/views/boxes.py	Wed Nov 23 17:19:51 2016 +0100
+++ b/cubicweb/web/views/boxes.py	Thu Nov 19 12:25:45 2015 +0100
@@ -138,11 +138,11 @@
     order = 0
     formdef = u"""<form action="%(action)s">
 <table id="%(id)s"><tr><td>
-<input class="norql" type="text" accesskey="q" tabindex="%(tabindex1)s" title="search text" value="%(value)s" name="rql" />
+<input class="norql" type="text" accesskey="q" title="search text" value="%(value)s" name="rql" />
 <input type="hidden" name="__fromsearchbox" value="1" />
 <input type="hidden" name="subvid" value="tsearch" />
 </td><td>
-<input tabindex="%(tabindex2)s" type="submit" class="rqlsubmit" value="" />
+<input type="submit" class="rqlsubmit" value="" />
  </td></tr></table>
  </form>"""
 
@@ -155,13 +155,10 @@
             rql = self._cw.form.get('rql', '')
         else:
             rql = ''
-        tabidx1 = self._cw.next_tabindex()
-        tabidx2 = self._cw.next_tabindex()
         w(self.formdef % {'action': self._cw.build_url('view'),
                           'value': xml_escape(rql),
-                          'id': self.cw_extra_kwargs.get('domid', 'tsearch'),
-                          'tabindex1': tabidx1,
-                          'tabindex2': tabidx2})
+                          'id': self.cw_extra_kwargs.get('domid', 'tsearch')
+                          })
 
 
 # boxes disabled by default ###################################################
--- a/cubicweb/web/views/cwproperties.py	Wed Nov 23 17:19:51 2016 +0100
+++ b/cubicweb/web/views/cwproperties.py	Thu Nov 19 12:25:45 2015 +0100
@@ -315,9 +315,8 @@
     def render(self, form, renderer):
         wdg = self.get_widget(form)
         # pylint: disable=E1101
-        wdg.attrs['tabindex'] = form._cw.next_tabindex()
-        wdg.attrs['onchange'] = "javascript:setPropValueWidget('%s', %s)" % (
-            form.edited_entity.eid, form._cw.next_tabindex())
+        wdg.attrs['onchange'] = "javascript:setPropValueWidget('%s')" % (
+            form.edited_entity.eid)
         return wdg.render(form, self, renderer)
 
     def vocabulary(self, form):
@@ -335,10 +334,8 @@
     """
     widget = PlaceHolderWidget
 
-    def render(self, form, renderer=None, tabindex=None):
+    def render(self, form, renderer=None):
         wdg = self.get_widget(form)
-        if tabindex is not None:
-            wdg.attrs['tabindex'] = tabindex
         return wdg.render(form, self, renderer)
 
     def form_init(self, form):
@@ -422,7 +419,7 @@
 
 
 @ajaxfunc(output_type='xhtml')
-def prop_widget(self, propkey, varname, tabindex=None):
+def prop_widget(self, propkey, varname):
     """specific method for CWProperty handling"""
     entity = self._cw.vreg['etypes'].etype_class('CWProperty')(self._cw)
     entity.eid = varname
@@ -431,7 +428,7 @@
     form.build_context()
     vfield = form.field_by_name('value', 'subject')
     renderer = formrenderers.FormRenderer(self._cw)
-    return vfield.render(form, renderer, tabindex=tabindex) \
+    return vfield.render(form, renderer) \
            + renderer.render_help(form, vfield)
 
 _afs = uicfg.autoform_section
--- a/doc/book/devweb/edition/dissection.rst	Wed Nov 23 17:19:51 2016 +0100
+++ b/doc/book/devweb/edition/dissection.rst	Thu Nov 19 12:25:45 2015 +0100
@@ -107,14 +107,14 @@
             <th class="labelCol"><label class="required" for="title-subject:763">title</label></th>
             <td>
               <input id="title-subject:763" maxlength="128" name="title-subject:763" size="45"
-                     tabindex="1" type="text" value="let us write more doc" />
+                     type="text" value="let us write more doc" />
             </td>
           </tr>
           ... (description field omitted) ...
           <tr class="priority_subject_row">
             <th class="labelCol"><label class="required" for="priority-subject:763">priority</label></th>
             <td>
-              <select id="priority-subject:763" name="priority-subject:763" size="1" tabindex="4">
+              <select id="priority-subject:763" name="priority-subject:763" size="1">
                 <option value="important">important</option>
                 <option selected="selected" value="normal">normal</option>
                 <option value="minor">minor</option>
@@ -126,7 +126,7 @@
           <tr class="concerns_subject_row">
             <th class="labelCol"><label class="required" for="concerns-subject:763">concerns</label></th>
             <td>
-              <select id="concerns-subject:763" name="concerns-subject:763" size="1" tabindex="6">
+              <select id="concerns-subject:763" name="concerns-subject:763" size="1">
                 <option selected="selected" value="760">Foo</option>
               </select>
             </td>
@@ -134,7 +134,7 @@
           <tr class="done_in_subject_row">
             <th class="labelCol"><label for="done_in-subject:763">done in</label></th>
             <td>
-              <select id="done_in-subject:763" name="done_in-subject:763" size="1" tabindex="7">
+              <select id="done_in-subject:763" name="done_in-subject:763" size="1">
                 <option value="__cubicweb_internal_field__"></option>
                 <option selected="selected" value="761">Foo 0.1.0</option>
                 <option value="762">Foo 0.2.0</option>
@@ -180,7 +180,7 @@
                 <tr><th>&#160;</th><td>&#160;</td></tr>
                 <tr id="relationSelectorRow_763" class="separator">
                   <th class="labelCol">
-                    <select id="relationSelector_763" tabindex="8"
+                    <select id="relationSelector_763"
                             onchange="javascript:showMatchingSelect(this.options[this.selectedIndex].value,763);">
                       <option value="">select a relation</option>
                       <option value="appeared_in_subject">appeared in</option>
@@ -228,7 +228,7 @@
         <tbody>
           <tr>
             <td align="center">
-              <button class="validateButton" tabindex="9" type="submit" value="validate">
+              <button class="validateButton" type="submit" value="validate">
                 <img alt="OK_ICON" src="http://myapp/datafd8b5d92771209ede1018a8d5da46a37/ok.png" />
                 validate
               </button>
@@ -236,13 +236,13 @@
             <td style="align: right; width: 50%;">
               <button class="validateButton"
                       onclick="postForm(&#39;__action_apply&#39;, &#39;button_apply&#39;, &#39;entityForm&#39;)"
-                      tabindex="10" type="button" value="apply">
+                      type="button" value="apply">
                 <img alt="APPLY_ICON" src="http://myapp/datafd8b5d92771209ede1018a8d5da46a37/plus.png" />
                 apply
               </button>
               <button class="validateButton"
                       onclick="postForm(&#39;__action_cancel&#39;, &#39;button_cancel&#39;, &#39;entityForm&#39;)"
-                      tabindex="11" type="button" value="cancel">
+                      type="button" value="cancel">
                 <img alt="CANCEL_ICON" src="http://myapp/datafd8b5d92771209ede1018a8d5da46a37/cancel.png" />
                 cancel
               </button>
--- a/doc/book/devweb/request.rst	Wed Nov 23 17:19:51 2016 +0100
+++ b/doc/book/devweb/request.rst	Thu Nov 19 12:25:45 2015 +0100
@@ -48,8 +48,6 @@
   * etype_rset
   * `form`, dictionary containing the values of a web form
   * `encoding`, character encoding to use in the response
-  * `next_tabindex()`: returns a monotonically growing integer used to
-    build the html tab index of forms
 
 * `HTTP`