Skip to content

Commit 17f2546

Browse files
crisbetojelbourn
authored andcommitted
fix(cdk-experimental/clipboard): avoid changing layout with temporary textarea (#17227)
Currently the clipboard service creates a temporary invisible `textarea` from which to copy the text into the clipboard, however since it only has `opacity: 0`, it has the potential of changing the layout in a noticeable way if it is present for longer. These changes add some extra styles to avoid changing the layout. I also did some small cleanup to make it a bit more robust.
1 parent aab0894 commit 17f2546

File tree

1 file changed

+15
-7
lines changed

1 file changed

+15
-7
lines changed

src/cdk-experimental/clipboard/clipboard.ts

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,14 @@ export class PendingCopy {
7070

7171
constructor(text: string, private readonly _document: Document) {
7272
const textarea = this._textarea = this._document.createElement('textarea');
73+
const styles = textarea.style;
7374

74-
// Hide the element for display and accessibility.
75-
textarea.setAttribute('style', 'opacity: 0;');
75+
// Hide the element for display and accessibility. Set an
76+
// absolute position so the page layout isn't affected.
77+
styles.opacity = '0';
78+
styles.position = 'absolute';
79+
styles.left = styles.top = '-999em';
7680
textarea.setAttribute('aria-hidden', 'true');
77-
7881
textarea.value = text;
7982
this._document.body.appendChild(textarea);
8083
}
@@ -86,13 +89,13 @@ export class PendingCopy {
8689

8790
try { // Older browsers could throw if copy is not supported.
8891
if (textarea) {
89-
const currentFocus = document.activeElement;
92+
const currentFocus = this._document.activeElement;
9093

9194
textarea.select();
9295
textarea.setSelectionRange(0, textarea.value.length);
9396
successful = this._document.execCommand('copy');
9497

95-
if (currentFocus instanceof HTMLElement) {
98+
if (currentFocus && currentFocus instanceof HTMLElement) {
9699
currentFocus.focus();
97100
}
98101
}
@@ -106,8 +109,13 @@ export class PendingCopy {
106109

107110
/** Cleans up DOM changes used to perform the copy operation. */
108111
destroy() {
109-
if (this._textarea) {
110-
this._document.body.removeChild(this._textarea);
112+
const textarea = this._textarea;
113+
114+
if (textarea) {
115+
if (textarea.parentNode) {
116+
textarea.parentNode.removeChild(textarea);
117+
}
118+
111119
this._textarea = undefined;
112120
}
113121
}

0 commit comments

Comments
 (0)