From 7e33b547714e42c4c3c12557c15c843ba138d2e3 Mon Sep 17 00:00:00 2001 From: Adrien Dieudonne Date: Wed, 13 Mar 2019 14:41:26 +0000 Subject: [PATCH] [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 --- .../barcodes/static/src/js/barcode_events.js | 37 +++++----- .../static/tests/barcode_mobile_tests.js | 74 +++++++++++++++++++ addons/barcodes/views/barcodes_templates.xml | 6 ++ 3 files changed, 97 insertions(+), 20 deletions(-) create mode 100644 addons/barcodes/static/tests/barcode_mobile_tests.js diff --git a/addons/barcodes/static/src/js/barcode_events.js b/addons/barcodes/static/src/js/barcode_events.js index 0f2849525de..70463cd590e 100644 --- a/addons/barcodes/static/src/js/barcode_events.js +++ b/addons/barcodes/static/src/js/barcode_events.js @@ -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 = $('', { - 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 = $('', { + 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){ diff --git a/addons/barcodes/static/tests/barcode_mobile_tests.js b/addons/barcodes/static/tests/barcode_mobile_tests.js new file mode 100644 index 00000000000..cb26da64c74 --- /dev/null +++ b/addons/barcodes/static/tests/barcode_mobile_tests.js @@ -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 = $( + '
' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '
' + + '' + + '
'); + $('#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(); + }); + }); + }); diff --git a/addons/barcodes/views/barcodes_templates.xml b/addons/barcodes/views/barcodes_templates.xml index cb16a40c178..45b77bd3301 100644 --- a/addons/barcodes/views/barcodes_templates.xml +++ b/addons/barcodes/views/barcodes_templates.xml @@ -16,4 +16,10 @@ + +