[FIX] barcodes: let focus in number, password, tel, phone inputs

Before this commit, users wasn't able to input values in some
input elements like password, email and phone in mobile.

Steps to reproduce:
- Go to user
- Select Preferences
- Select Change password
- Try to input something
=> The focus was lost and the keyboard disappeared

In fact, a hidden input always have the focus when no other fields
need it. This input is used to intercept a value from a barcode
scanner.

So now, we added some input types to avoid to set the focus on the
barcode input.

The barcode input is now always defined (even if not used in desktop)
to be able to mock a Chrome mobile environment in a test.

opw-1936712
opw-1948266

closes odoo/odoo#31841

Signed-off-by: Pierre Paridans <pparidans@users.noreply.github.com>
This commit is contained in:
Adrien Dieudonne
2019-03-18 13:16:57 +00:00
parent 2940ee6b35
commit 7e33b54771
3 changed files with 97 additions and 20 deletions
+17 -20
View File
@@ -56,20 +56,18 @@ var BarcodeEvents = core.Class.extend(mixins.PropertiesMixin, {
this.isChromeMobile = isMobile && navigator.userAgent.match(/Chrome/i);
// Creates an input who will receive the barcode scanner value.
if (this.isChromeMobile) {
this.$barcodeInput = $('<input/>', {
name: 'barcode',
type: 'text',
css: {
'position': 'fixed',
'top': '50%',
'transform': 'translateY(-50%)',
'z-index': '-1',
},
});
// Avoid to show autocomplete for a non appearing input
this.$barcodeInput.attr('autocomplete', 'off');
}
this.$barcodeInput = $('<input/>', {
name: 'barcode',
type: 'text',
css: {
'position': 'fixed',
'top': '50%',
'transform': 'translateY(-50%)',
'z-index': '-1',
},
});
// Avoid to show autocomplete for a non appearing input
this.$barcodeInput.attr('autocomplete', 'off');
this.__blurBarcodeInput = _.debounce(this._blurBarcodeInput, this.inputTimeOut);
},
@@ -220,7 +218,8 @@ var BarcodeEvents = core.Class.extend(mixins.PropertiesMixin, {
* @param {jQuery.Event} e keydown event
*/
_listenBarcodeScanner: function (e) {
if (!$('input:text:focus, textarea:focus, [contenteditable]:focus').length) {
if ($(document.activeElement).not('input:text, textarea, [contenteditable], ' +
'[type="email"], [type="number"], [type="password"], [type="tel"]').length) {
$('body').append(this.$barcodeInput);
this.$barcodeInput.focus();
}
@@ -263,11 +262,9 @@ var BarcodeEvents = core.Class.extend(mixins.PropertiesMixin, {
* @private
*/
_blurBarcodeInput: function () {
if (this.$barcodeInput) {
// Close the virtual keyboard on mobile browsers
// FIXME: actually we can't prevent keyboard from opening
this.$barcodeInput.val('').blur();
}
// Close the virtual keyboard on mobile browsers
// FIXME: actually we can't prevent keyboard from opening
this.$barcodeInput.val('').blur();
},
start: function(prevent_key_repeat){
@@ -0,0 +1,74 @@
odoo.define('barcodes.barcode_mobile_tests', function () {
"use strict";
QUnit.module('Barcodes', {}, function () {
QUnit.module('Barcodes Mobile');
QUnit.test('barcode field automatically focus behavior', function (assert) {
assert.expect(10);
// Mock Chrome mobile environment
var barcodeEvents = odoo.__DEBUG__.services["barcodes.BarcodeEvents"].BarcodeEvents;
var __isChromeMobile = barcodeEvents.isChromeMobile;
barcodeEvents.isChromeMobile = true;
// Rebind keyboard events
barcodeEvents.stop();
barcodeEvents.start();
var $form = $(
'<form>' +
'<input name="email" type="email"/>' +
'<input name="number" type="number"/>' +
'<input name="password" type="password"/>' +
'<input name="tel" type="tel"/>' +
'<input name="text"/>' +
'<input name="explicit_text" type="text"/>' +
'<textarea></textarea>' +
'<div contenteditable="true"></div>' +
'<select name="select">' +
'<option value="option1">Option 1</option>' +
'<option value="option2">Option 2</option>' +
'</select>' +
'</form>');
$('#qunit-fixture').append($form);
// Some elements doesn't need to keep the focus
$('body').keydown();
assert.strictEqual(document.activeElement.name, 'barcode',
"hidden barcode input should have the focus");
var $element = $form.find('select');
$element.focus().keydown();
assert.strictEqual(document.activeElement.name, 'barcode',
"hidden barcode input should have the focus");
// Those elements absolutely need to keep the focus:
// inputs elements:
var keepFocusedElements = ['email', 'number', 'password', 'tel',
'text', 'explicit_text'];
for (var i = 0; i < keepFocusedElements.length; ++i) {
$element = $form.find('input[name=' + keepFocusedElements[i] + ']');
$element.focus().keydown();
assert.strictEqual(document.activeElement, $element[0],
"input " + keepFocusedElements[i] + " should keep focus");
}
// textarea element
$element = $form.find('textarea');
$element.focus().keydown();
assert.strictEqual(document.activeElement, $element[0],
"textarea should keep focus");
// contenteditable elements
$element = $form.find('[contenteditable=true]');
$element.focus().keydown();
assert.strictEqual(document.activeElement, $element[0],
"contenteditable should keep focus");
$('#qunit-fixture').empty();
barcodeEvents.isChromeMobile = __isChromeMobile;
// Rebind keyboard events
barcodeEvents.stop();
barcodeEvents.start();
});
});
});
@@ -16,4 +16,10 @@
</xpath>
</template>
<template id="qunit_mobile_suite" name="barcode_mobile_tests" inherit_id="web.qunit_mobile_suite">
<xpath expr="//t[@t-set='head']" position="inside">
<script type="text/javascript" src="/barcodes/static/tests/barcode_mobile_tests.js"></script>
</xpath>
</template>
</odoo>