[FIX] web: form view should focus fields if possible

When a form view switches to edit mode, it is supposed to give the focus
to the first field, or, to a field tagged 'default_focus'.
This commit is contained in:
Géry Debongnie
2017-04-24 10:19:18 +02:00
parent d8261d1162
commit e4bf1f1ccc
3 changed files with 64 additions and 4 deletions
@@ -161,17 +161,24 @@ var AbstractField = Widget.extend({
/**
* Activates the field widget. By default, activation means focusing and
* selecting the associated focusable element.
* selecting (if possible) the associated focusable element. The selecting
* part can be disabled. In that case, note that the focused input/textarea
* will have the cursor at the very end.
*
* @param {boolean} [noselect=false] if false and the input is of type text
* or textarea, the content will also be selected
* @returns {boolean} true if the widget was activated, false if the
* focusable element was not found or invisible
*/
activate: function () {
activate: function (noselect) {
var $focusable = this.getFocusableElement();
if ($focusable.length && $focusable.is(':visible')) {
$focusable.focus();
if ($focusable.is('input[type="text"], textarea')) {
setTimeout($focusable.select.bind($focusable), 0);
$focusable[0].selectionStart = $focusable[0].selectionEnd = $focusable[0].value.length;
if (!noselect) {
setTimeout($focusable.select.bind($focusable), 0);
}
}
return true;
}
@@ -284,7 +284,9 @@ var FormRenderer = BasicRenderer.extend({
widget.$el.addClass(FIELD_CLASSES[record.fields[node.attrs.name].type]);
this._addFieldClassNames(widget);
this._handleAttributes(widget.$el, node);
if (JSON.parse(node.attrs.default_focus || "0")) {
this.defaultFocusField = widget;
}
return widget;
},
/**
@@ -700,13 +702,20 @@ var FormRenderer = BasicRenderer.extend({
self.$el.toggleClass('o_form_editable', self.mode === 'edit');
self.$el.toggleClass('o_form_readonly', self.mode === 'readonly');
// Attach the tooltips on the fields' label
var focusWidget = self.defaultFocusField;
_.each(self.allFieldWidgets[self.state.id], function (widget) {
if (!focusWidget) {
focusWidget = widget;
}
if (core.debug || widget.attrs.help || widget.field.help) {
var idForLabel = self.idsForLabels[widget.name];
var $label = idForLabel ? self.$('label[for=' + idForLabel + ']') : $();
self._addFieldTooltip(widget, $label);
}
});
if (focusWidget) {
focusWidget.activate(true);
}
});
},
@@ -3285,5 +3285,49 @@ QUnit.module('Views', {
"there should be 4 read rpcs");
form.destroy();
});
QUnit.test('in edit mode, first field is focused', function (assert) {
assert.expect(2);
var form = createView({
View: FormView,
model: 'partner',
data: this.data,
arch: '<form string="Partners">' +
'<field name="foo"/>' +
'<field name="bar"/>' +
'</form>',
res_id: 1,
});
form.$buttons.find('.o_form_button_edit').click();
assert.strictEqual(form.$('.o_form_input[name="foo"]')[0], document.activeElement,
"foo field should have focus");
assert.strictEqual(form.$('.o_form_input[name="foo"]')[0].selectionStart, 3,
"cursor should be at the end");
form.destroy();
});
QUnit.test('autofocus fields are focused', function (assert) {
assert.expect(1);
var form = createView({
View: FormView,
model: 'partner',
data: this.data,
arch: '<form string="Partners">' +
'<field name="bar"/>' +
'<field name="foo" default_focus="1"/>' +
'</form>',
res_id: 1,
});
form.$buttons.find('.o_form_button_edit').click();
assert.strictEqual(form.$('.o_form_input[name="foo"]')[0], document.activeElement,
"foo field should have focus");
form.destroy();
});
});
});