Skip to content

Commit e4c5fb6

Browse files
committed
fix(helpers): scroll the page the minimal distance in the scrollIntoViewIfNeeded fallback
When only the page itself can reveal the caret line (the editor is half-visible in a small viewport), the fallback used the default block: 'start' and the page jumped like PageDown on every Enter. Use block: 'nearest' so it scrolls one line at a time, like a textarea. Reported by Ralf Pichler (Uniquare, Jodit OEM)
1 parent b12ae55 commit e4c5fb6

3 files changed

Lines changed: 45 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@
99
> - :house: [Internal]
1010
> - :nail_care: [Polish]
1111

12+
## 4.13.21
13+
14+
#### :bug: Bug Fix
15+
16+
- **Helpers**: when the caret line can only be revealed by scrolling the page itself (e.g. the editor is half-visible in a small viewport), `scrollIntoViewIfNeeded` fell back to `scrollIntoView()` with the default `block: 'start'` — the element was aligned to the viewport top and the page jumped as if PageDown was pressed on every Enter. The fallback now uses `block: 'nearest'` and scrolls the minimal distance, one line at a time, like a native textarea. Reported by Ralf Pichler (Uniquare, Jodit OEM).
17+
1218
## 4.13.20
1319

1420
#### :bug: Bug Fix

src/core/helpers/utils/scroll-into-view.test.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,4 +109,38 @@ describe('Helper inView', () => {
109109
}
110110
});
111111
});
112+
113+
// When only the page itself can reveal the element, the fallback must
114+
// scroll the minimal distance (block: nearest) — the default aligns the
115+
// element to the viewport top and the page jumps like PageDown was
116+
// pressed while typing at the bottom edge of a half-visible editor
117+
describe('Page-level fallback', () => {
118+
it('Should call scrollIntoView with block: nearest', () => {
119+
const { scrollIntoViewIfNeeded } = Jodit.modules.Helpers;
120+
121+
// a non-scrollable box below the viewport: the container branch
122+
// cannot help, only the page can be scrolled
123+
const box = document.createElement('div');
124+
box.style.cssText = `position:absolute;left:0;top:${
125+
document.documentElement.clientHeight + 500
126+
}px;width:100px;height:100px;`;
127+
128+
const child = document.createElement('p');
129+
child.style.cssText = 'height:100px;margin:0;';
130+
box.appendChild(child);
131+
document.body.appendChild(box);
132+
133+
let options;
134+
child.scrollIntoView = opt => {
135+
options = opt;
136+
};
137+
138+
try {
139+
scrollIntoViewIfNeeded(child, box, document);
140+
expect(options).deep.equals({ block: 'nearest' });
141+
} finally {
142+
box.remove();
143+
}
144+
});
145+
});
112146
});

src/core/helpers/utils/scroll-into-view.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,11 @@ export function scrollIntoViewIfNeeded(
9393
}
9494

9595
if (!inView(elm, root, doc)) {
96-
elm.scrollIntoView();
96+
// `block: 'nearest'` scrolls the page the minimal distance (one
97+
// line while typing), while the default `block: 'start'` aligns
98+
// the element to the viewport top and the page jumps like
99+
// PageDown was pressed
100+
elm.scrollIntoView({ block: 'nearest' });
97101
}
98102
}
99103
}

0 commit comments

Comments
 (0)