[IMP] web: focus numeric input selects all content

This commit makes the data entry of numeric fields
easier by selecting  all the content of the input on focus.

task 3132899

closes odoo/odoo#110181

Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
This commit is contained in:
Michael (mcm)
2023-02-03 05:08:53 +01:00
parent c59ec25c87
commit 6db4d6904e
2 changed files with 42 additions and 20 deletions
@@ -4,6 +4,23 @@ import { localization } from "@web/core/l10n/localization";
import { useRef, useEffect } from "@odoo/owl";
function onKeydown(ev) {
const decimalPoint = localization.decimalPoint;
if (
!([".", ","].includes(ev.key) && ev.code === "NumpadDecimal") ||
ev.key === decimalPoint ||
ev.target.type === "number"
) {
return;
}
ev.preventDefault();
ev.target.setRangeText(decimalPoint, ev.target.selectionStart, ev.target.selectionEnd, "end");
}
function onFocus(ev) {
ev.target.select();
}
/**
* This hook replaces the decimal separator of the numpad decimal key
* by the decimal separator from the user's language setting when user
@@ -16,33 +33,18 @@ import { useRef, useEffect } from "@odoo/owl";
* case, whatever the user types, we let the browser's default behavior.
*/
export function useNumpadDecimal() {
const decimalPoint = localization.decimalPoint;
const ref = useRef("numpadDecimal");
const handler = (ev) => {
if (
!([".", ","].includes(ev.key) && ev.code === "NumpadDecimal") ||
ev.key === decimalPoint ||
ev.target.type === "number"
) {
return;
}
ev.preventDefault();
ev.target.setRangeText(
decimalPoint,
ev.target.selectionStart,
ev.target.selectionEnd,
"end"
);
};
useEffect(() => {
let inputs = [];
const el = ref.el;
if (el) {
inputs = el.nodeName === "INPUT" ? [el] : el.querySelectorAll("input");
inputs.forEach((input) => input.addEventListener("keydown", handler));
inputs.forEach((input) => input.addEventListener("keydown", onKeydown));
inputs.forEach((input) => input.addEventListener("focus", onFocus));
}
return () => {
inputs.forEach((input) => input.removeEventListener("keydown", handler));
inputs.forEach((input) => input.removeEventListener("keydown", onKeydown));
inputs.forEach((input) => input.removeEventListener("focus", onFocus));
};
});
}
@@ -2,7 +2,13 @@
import { makeFakeLocalizationService } from "@web/../tests/helpers/mock_services";
import { registry } from "@web/core/registry";
import { click, getFixture, nextTick, patchWithCleanup } from "@web/../tests/helpers/utils";
import {
click,
getFixture,
nextTick,
patchWithCleanup,
triggerEvent,
} from "@web/../tests/helpers/utils";
import { makeView, setupViewRegistries } from "@web/../tests/views/helpers";
import { localization } from "@web/core/l10n/localization";
import { useNumpadDecimal } from "@web/views/fields/numpad_decimal_hook";
@@ -374,4 +380,18 @@ QUnit.module("Fields", (hooks) => {
await testInputElements(target.querySelectorAll("main > input"));
}
);
QUnit.test("select all content on focus", async function (assert) {
await makeView({
type: "form",
resModel: "partner",
serverData,
arch: `<form><field name="monetary"/></form>`,
});
const input = target.querySelector(".o_field_widget[name='monetary'] input");
await triggerEvent(input, null, "focus");
assert.strictEqual(input.selectionStart, 0);
assert.strictEqual(input.selectionEnd, 4);
});
});