Project

General

Profile

Actions

Defect #44336

open

Automatic list marker insertion discards the textarea undo history and does not scroll the caret into view

Added by Jonathan Cormier 26 days ago. Updated 1 day ago.

Status:
New
Priority:
Normal
Assignee:
-
Category:
UI
Resolution:
Affected version:

Description

Since #43095 (6.1.0), pressing Enter after a list item runs the list-autofill Stimulus controller. Its insert branch cancels the native line break and splices the marker with:

this.input.value = newValue
this.input.setSelectionRange(newCursor, newCursor)

Assigning input.value programmatically resets the browser's undo stack, and setSelectionRange does not scroll the textarea in Chrome. Two user-visible defects on every Enter inside a list:

1. Undo is destroyed. Everything typed before the Enter becomes unrecoverable with Ctrl+Z. Measured in Chromium on a stock 6.1.3 new-issue form: type * item one, Enter (marker auto-inserted), type item two, then Ctrl+Z 8x -> textarea stops at
"* item one\n* ". With the controller detached, the same keystrokes undo to empty.
2. Caret left off-screen. When the textarea is scrolled (long note, caret at bottom), the native Enter scroll never happens (the event was canceled). The new list line is not visible until the next character is typed.

The remove branch (Enter on an empty item) uses setRangeText, which is also not undoable in Chromium.

Proposed fix (patch attached):

  • insert: do not cancel the event. Let the native line break run — it creates a normal undo entry and scrolls the caret into view — and append the marker at the caret from a one-shot input (insertLineBreak) listener via document.execCommand('insertText'), falling back to setRangeText where execCommand is unavailable.
  • remove: select the marker range and use document.execCommand('delete') (same fallback), so the removal is undoable.

Verified in Chromium (headless, Playwright) against 6.1.3 with the patch applied:

  • markers still auto-insert/remove for Textile and CommonMark lines
  • 8x Ctrl+Z fully reverts a typed list (identical to a controller-less textarea); one Ctrl+Z reverts break+marker in a single step
  • scrollTop after Enter matches native exactly (540 -> 555 in the test layout); Ctrl+Z after marker-removal restores the marker
  • execCommand is deprecated but universally supported for insertText/delete in textareas, and core already relies on it (copy-to-clipboard).
  1. Probe data (2026-08-10, sameersbn/redmine:6.1.3-2, bundled Chromium)
scenario typed after 8x Ctrl+Z
--- --- ---
6.1.3 stock, controller on `* item one\n* item two` `* item one\n* ` (history gone)
controller detached `* item one\n* item two` `` (full undo)
patched, controller on `* item one\n* item two` `` (full undo)

Scroll (textarea 184px client, 40 list lines, caret at bottom; "visible px" = height of caret line inside the viewport right after Enter):

scenario scrollTop before -> after Enter caret line visible
--- --- ---
stock 540 -> 540 0 px
native Enter (no controller) 540 -> 555 15 px
patched 540 -> 555 15 px

Files

Actions #1

Updated by Jonathan Cormier 18 days ago

the toolbar buttons and shortcuts have the same root cause in app/assets/javascripts/jstoolbar/jstoolbar.js (encloseSelection / encloseLineSelection assign textarea.value), which this patch does not touch. That half is #43488, where I have attached a patch for it.

Actions #2

Updated by Mizuki ISHIKAWA 12 days ago

Thank you for the patch. I tested it and it works very well.

I had two concerns: execCommand is deprecated, so it should not raise an error if the function is removed in the future, and I think it would be better to have a system test for this behavior.
I have attached a patch that addresses these two points. It should be applied after the list_autofill_undo_scroll.patch

Actions #3

Updated by Jonathan Cormier 12 days ago

Appreciate the update, makes sense to me. Hopefully they don't fully deprecate this feature

Actions #4

Updated by Go MAEDA 12 days ago

  • Target version set to Candidate for next major release
Actions #6

Updated by Jonathan Cormier 5 days ago

Found a slight modification:

Using setSelectionRange causes the linux middle-click buffer to get filled with whatever we are deleting, instead using setRangeText avoids this.

  • setSelectionRange is a UI action that X11 monitors to sync the "Primary Selection" (middle-click buffer).
  • setRangeText is a programmatic DOM manipulation method. When used with an empty string and the 'end' (or 'preserve') parameter, it modifies the internal value buffer of the textarea without triggering the system-level selection broadcast that "pollutes" the middle-click buffer.
Actions #7

Updated by Jonathan Cormier 5 days ago

Ex: textarea.setRangeText('', lineStart, lineEnd, 'end');

Actions #8

Updated by Jonathan Cormier 1 day ago

nvm, setRangeText just brings back the undo problems.

Actions

Also available in: Atom PDF