Skip to content

Commit c94812d

Browse files
crisbetojelbourn
authored andcommitted
fix(text-field): add fallback for browsers that don't support requestAnimationFrame (#14519)
Currently we've got a block in the autosize textarea that depends on `requestAnimationFrame`, however it won't run if it isn't supported, which means that the fix it's applying won't run on some browsers. These changes add a fallback via `setTimeout`.
1 parent c6dc070 commit c94812d

File tree

1 file changed

+26
-17
lines changed

1 file changed

+26
-17
lines changed

src/cdk/text-field/autosize.ts

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -226,23 +226,13 @@ export class CdkTextareaAutosize implements AfterViewInit, DoCheck, OnDestroy {
226226
textarea.classList.remove('cdk-textarea-autosize-measuring');
227227
textarea.placeholder = placeholderText;
228228

229-
// On Firefox resizing the textarea will prevent it from scrolling to the caret position.
230-
// We need to re-set the selection in order for it to scroll to the proper position.
231-
if (typeof requestAnimationFrame !== 'undefined') {
232-
this._ngZone.runOutsideAngular(() => requestAnimationFrame(() => {
233-
const {selectionStart, selectionEnd} = textarea;
234-
235-
// IE will throw an "Unspecified error" if we try to set the selection range after the
236-
// element has been removed from the DOM. Assert that the directive hasn't been destroyed
237-
// between the time we requested the animation frame and when it was executed.
238-
// Also note that we have to assert that the textarea is focused before we set the
239-
// selection range. Setting the selection range on a non-focused textarea will cause
240-
// it to receive focus on IE and Edge.
241-
if (!this._destroyed.isStopped && document.activeElement === textarea) {
242-
textarea.setSelectionRange(selectionStart, selectionEnd);
243-
}
244-
}));
245-
}
229+
this._ngZone.runOutsideAngular(() => {
230+
if (typeof requestAnimationFrame !== 'undefined') {
231+
requestAnimationFrame(() => this._scrollToCaretPosition(textarea));
232+
} else {
233+
setTimeout(() => this._scrollToCaretPosition(textarea));
234+
}
235+
});
246236

247237
this._previousValue = value;
248238
this._previousMinRows = this._minRows;
@@ -263,4 +253,23 @@ export class CdkTextareaAutosize implements AfterViewInit, DoCheck, OnDestroy {
263253
_noopInputHandler() {
264254
// no-op handler that ensures we're running change detection on input events.
265255
}
256+
257+
/**
258+
* Scrolls a textarea to the caret position. On Firefox resizing the textarea will
259+
* prevent it from scrolling to the caret position. We need to re-set the selection
260+
* in order for it to scroll to the proper position.
261+
*/
262+
private _scrollToCaretPosition(textarea: HTMLTextAreaElement) {
263+
const {selectionStart, selectionEnd} = textarea;
264+
265+
// IE will throw an "Unspecified error" if we try to set the selection range after the
266+
// element has been removed from the DOM. Assert that the directive hasn't been destroyed
267+
// between the time we requested the animation frame and when it was executed.
268+
// Also note that we have to assert that the textarea is focused before we set the
269+
// selection range. Setting the selection range on a non-focused textarea will cause
270+
// it to receive focus on IE and Edge.
271+
if (!this._destroyed.isStopped && document.activeElement === textarea) {
272+
textarea.setSelectionRange(selectionStart, selectionEnd);
273+
}
274+
}
266275
}

0 commit comments

Comments
 (0)