Skip to content

FIX: Input mask cursor position https://github.com/Crocoblock/issues-tracker/issues/15133 - #738

Merged
ObitoTM merged 2 commits into
release/3.6.8from
issue/15133
Oct 25, 2026
Merged

ObitoTM merged 2 commits into
release/3.6.8from
issue/15133

Conversation

@ObitoTM

@ObitoTM ObitoTM commented Oct 25, 2026

Copy link
Copy Markdown
Collaborator

No description provided.

@github-actions

Copy link
Copy Markdown

🤖 AI PR Review

Risk level: medium

Review

Summary

This PR changes the masked text-field input data handling to avoid rewriting the field during internal mask validation — preventing the caret from jumping — by adding an isMaskValidation flag, adjusting maskValidation/changeStateMaskValidation logic, adding an oncleared handler, and overriding onChange to suppress external change handling while internal validation runs. Built frontend bundle was updated accordingly.

What I checked

  • Files changed: modules/blocks-v2/text-field/assets/src/frontend/field.mask/TextFieldMaskedData.js and the compiled build file modules/blocks-v2/text-field/assets/build/frontend/field.mask.js
  • Areas of impact: masked text-field behavior, validation, submit handling (clearOnSubmit), and change reporting.

Positives

  • The fix addresses the common UX problem where inputmask internal validation/update resets the caret — the isMaskValidation guard and the temporary switch when updating value.current is an appropriate approach.
  • Adding oncleared hook ensures validation runs for cleared masks as well.
  • The change avoids rewriting DOM value where it would reset caret (good for keyboard/paste/caret position UX).

Issues / Risks / Suggestions

  1. Defensive checks for node.inputmask
  • changeStateMaskValidation() and maskValidation() call node.inputmask.unmaskedvalue() without confirming node.inputmask exists. In most flows the mask is present, but handlers like oncomplete/onincomplete/oncleared might be called after mask removal in edge cases. Add a guard (if (!node || !node.inputmask) return '' / do nothing) to avoid potential runtime errors.
  1. Behaviour change for validation value used in silenceSet
  • maskValidation() now uses the unmasked value presence to decide silenceSet(unmaskedValue ? value : ''). This is reasonable (avoids treating fixed prefix/placeholder as content), but it's a behavioral change: when the visible value is a fixed prefix/placeholder only, the field will be treated as empty for validation. Ensure this does not break integrations/actions that relied on the previous behaviour (where visible masked value may have been considered non-empty). Callouts:
    • Confirm interactions with actions that map field values to posts/users/CCT — they expect unmasked vs masked values. This PR keeps the internal value.current unmasked, but silenceSet provides an empty string to the public input value in empty masks.
    • Verify clearOnSubmit behaviour across edge cases (clearOnSubmit still respected).
  1. onChange override — potential integration impacts
  • You added TextFieldMaskedData.prototype.onChange to suppress InputData.prototype.onChange when isMaskValidation is true. This changes when change handlers report. Ensure that other parts of the codebase (or third-party add-ons/hooks) that listen to value changes still receive expected notifications. The code does call this.report() even when suppressed, but InputData.prototype.onChange may do extra work beyond reporting. Confirm no required side effects are skipped. If InputData.prototype.onChange does more than reporting (e.g. updates calc values), those may be intentionally skipped; you partially handle calc in isResetCalcValue branch — good, but double-check all behaviors covered.
  1. inputmask "oncleared" support
  • You added inputMaskOpts.oncleared = this.maskValidation.bind(this); Confirm the target Inputmask library version supports oncleared and that the option name is correct for all supported versions. If older versions use a different callback name, consider feature-detecting or documenting the minimum inputmask version required.
  1. Race conditions with removeMask/revertMask
  • removeMask() stores this.maskOptions and then e.inputmask('remove'). If an inputmask callback (oncomplete/onc leared) fires around the same time, ensure changeStateMaskValidation and maskValidation handle when inputmask is gone (see point 1). Also revertMask uses saved maskOptions and jQuery(t).inputmask(e) — ensure maskOptions were captured in all cases and not mutated unexpectedly.
  1. Tests and cross-browser checks
  • This is a behavior-sensitive change. Please add automated tests (integration/browser tests or unit tests for TextFieldMaskedData where possible) covering:
    • Typing/pasting while caret is not at end (verify no jump)
    • Autofill/paste events
    • Clearing the field triggers maskValidation and required validation correctly
    • clearOnSubmit behavior
    • oncleared event behavior
  • Also test with different Inputmask versions supported by the plugin and on major browsers (Chrome, Firefox, Safari) and with different locale/RTL setups if applicable.
  1. Minor code/style suggestions
  • Add small defensive guards as mentioned above.
  • Keep consistent spacing formatting in src file (mostly fine). The built file is minified; no action needed there.

Recommendation

  • Add defensive checks for node.inputmask before calling unmaskedvalue().
  • Verify Inputmask version compatibility for oncleared callback and update docs or add a fallback if necessary.
  • Add integration/browser tests for caret preservation and validation behavior.
  • Run a quick audit of integrations that rely on InputData.prototype.onChange side-effects to confirm nothing else is skipped.

Overall: the approach is sound and addresses the cursor-jump bug. The main remaining concerns are edge-case robustness (guards) and verifying integration compatibility and inputmask version support.

Files/functions to review closely

  • modules/blocks-v2/text-field/assets/src/frontend/field.mask/TextFieldMaskedData.js
    • maskValidation(), changeStateMaskValidation(), setNode(), removeMask(), TextFieldMaskedData.prototype.onChange
  • modules/blocks-v2/text-field/assets/build/frontend/field.mask.js (compiled bundle)

Tests missing

  • No tests in PR. Please add integration tests for the above scenarios (typing with caret change, paste, autofill, clear, clearOnSubmit, oncleared).

Suggested changelog entry

- FIX: Prevent masked text-field input from resetting cursor position during internal validation (improves caret handling for masked inputs)

@ObitoTM
ObitoTM merged commit 7c4aaf5 into release/3.6.8 Oct 25, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant