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`.
This commit is contained in:
Kristiyan Kostadinov
2018-12-18 16:22:51 +01:00
committed by Jeremy Elbourn
parent c6dc070df6
commit c94812de2c
+26 -17
View File
@@ -226,23 +226,13 @@ export class CdkTextareaAutosize implements AfterViewInit, DoCheck, OnDestroy {
textarea.classList.remove('cdk-textarea-autosize-measuring');
textarea.placeholder = placeholderText;
// On Firefox resizing the textarea will prevent it from scrolling to the caret position.
// We need to re-set the selection in order for it to scroll to the proper position.
if (typeof requestAnimationFrame !== 'undefined') {
this._ngZone.runOutsideAngular(() => requestAnimationFrame(() => {
const {selectionStart, selectionEnd} = textarea;
// IE will throw an "Unspecified error" if we try to set the selection range after the
// element has been removed from the DOM. Assert that the directive hasn't been destroyed
// between the time we requested the animation frame and when it was executed.
// Also note that we have to assert that the textarea is focused before we set the
// selection range. Setting the selection range on a non-focused textarea will cause
// it to receive focus on IE and Edge.
if (!this._destroyed.isStopped && document.activeElement === textarea) {
textarea.setSelectionRange(selectionStart, selectionEnd);
}
}));
}
this._ngZone.runOutsideAngular(() => {
if (typeof requestAnimationFrame !== 'undefined') {
requestAnimationFrame(() => this._scrollToCaretPosition(textarea));
} else {
setTimeout(() => this._scrollToCaretPosition(textarea));
}
});
this._previousValue = value;
this._previousMinRows = this._minRows;
@@ -263,4 +253,23 @@ export class CdkTextareaAutosize implements AfterViewInit, DoCheck, OnDestroy {
_noopInputHandler() {
// no-op handler that ensures we're running change detection on input events.
}
/**
* Scrolls a textarea to the caret position. On Firefox resizing the textarea will
* prevent it from scrolling to the caret position. We need to re-set the selection
* in order for it to scroll to the proper position.
*/
private _scrollToCaretPosition(textarea: HTMLTextAreaElement) {
const {selectionStart, selectionEnd} = textarea;
// IE will throw an "Unspecified error" if we try to set the selection range after the
// element has been removed from the DOM. Assert that the directive hasn't been destroyed
// between the time we requested the animation frame and when it was executed.
// Also note that we have to assert that the textarea is focused before we set the
// selection range. Setting the selection range on a non-focused textarea will cause
// it to receive focus on IE and Edge.
if (!this._destroyed.isStopped && document.activeElement === textarea) {
textarea.setSelectionRange(selectionStart, selectionEnd);
}
}
}