[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:
@@ -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);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user