Skip to content

Commit a86754b

Browse files
gkalpakSplaktar
authored andcommitted
refactor(docs-infra): improve code readability of CopierService (angular#38244)
This commit improves the code readability of the `CopierService` by: - Adding/Improving JSDoc comments for methods. - Avoiding unnecessary instance-wide properties. - Fixing indentation to be consistent (at two spaces). - Clearly separating the logic for creating and populating a `<textarea>` from the logic for selecting and copying its contents. PR Close angular#38244
1 parent 2968435 commit a86754b

File tree

1 file changed

+67
-43
lines changed

1 file changed

+67
-43
lines changed

aio/src/app/shared/copier.service.ts

Lines changed: 67 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -9,59 +9,83 @@
99

1010

1111
export class CopierService {
12-
private fakeElem: HTMLTextAreaElement|null;
12+
/**
13+
* Copy the contents of a `<textarea>` element to the clipboard.
14+
*
15+
* NOTE: For this method to work, the elements must be already inserted into the DOM.
16+
*
17+
* @param textArea The area containing the text to be copied to the clipboard.
18+
* @return Whether the copy operation was successful.
19+
*/
20+
private copyTextArea(textArea: HTMLTextAreaElement): boolean {
21+
try {
22+
textArea.select();
23+
textArea.setSelectionRange(0, textArea.value.length);
1324

14-
/**
15-
* Creates a fake textarea element, sets its value from `text` property,
16-
* and makes a selection on it.
17-
*/
18-
createFake(text: string) {
19-
const docElem = document.documentElement!;
20-
const isRTL = docElem.getAttribute('dir') === 'rtl';
25+
return document.execCommand('copy');
26+
} catch {
27+
return false;
28+
}
29+
}
2130

22-
// Create a fake element to hold the contents to copy
23-
this.fakeElem = document.createElement('textarea');
31+
/**
32+
* Create a temporary, hidden `<textarea>` element and set its value to the specified text.
33+
*
34+
* @param text The text to be inserted into the textarea.
35+
* @return The temporary `<textarea>` element containing the specified text.
36+
*/
37+
private createTextArea(text: string): HTMLTextAreaElement {
38+
const docElem = document.documentElement!;
39+
const isRTL = docElem.getAttribute('dir') === 'rtl';
2440

25-
// Prevent zooming on iOS
26-
this.fakeElem.style.fontSize = '12pt';
41+
// Create a temporary element to hold the contents to copy.
42+
const textArea = document.createElement('textarea');
43+
const style = textArea.style;
2744

28-
// Reset box model
29-
this.fakeElem.style.border = '0';
30-
this.fakeElem.style.padding = '0';
31-
this.fakeElem.style.margin = '0';
45+
// Prevent zooming on iOS.
46+
style.fontSize = '12pt';
3247

33-
// Move element out of screen horizontally
34-
this.fakeElem.style.position = 'absolute';
35-
this.fakeElem.style[ isRTL ? 'right' : 'left' ] = '-9999px';
48+
// Reset box model.
49+
style.border = '0';
50+
style.padding = '0';
51+
style.margin = '0';
3652

37-
// Move element to the same position vertically
38-
const yPosition = window.pageYOffset || docElem.scrollTop;
39-
this.fakeElem.style.top = yPosition + 'px';
53+
// Move element out of screen horizontally.
54+
style.position = 'absolute';
55+
style[ isRTL ? 'right' : 'left' ] = '-9999px';
4056

41-
this.fakeElem.setAttribute('readonly', '');
42-
this.fakeElem.value = text;
57+
// Move element to the same position vertically.
58+
const yPosition = window.pageYOffset || docElem.scrollTop;
59+
style.top = yPosition + 'px';
4360

44-
document.body.appendChild(this.fakeElem);
61+
textArea.setAttribute('readonly', '');
62+
textArea.value = text;
4563

46-
this.fakeElem.select();
47-
this.fakeElem.setSelectionRange(0, this.fakeElem.value.length);
48-
}
64+
return textArea;
65+
}
4966

50-
removeFake() {
51-
if (this.fakeElem) {
52-
document.body.removeChild(this.fakeElem);
53-
this.fakeElem = null;
54-
}
55-
}
67+
/**
68+
* Copy the specified text to the clipboard.
69+
*
70+
* @param text The text to be copied to the clipboard.
71+
* @return Whether the copy operation was successful.
72+
*/
73+
copyText(text: string): boolean {
74+
// Create a `<textarea>` element with the specified text.
75+
const textArea = this.createTextArea(text);
5676

57-
copyText(text: string) {
58-
try {
59-
this.createFake(text);
60-
return document.execCommand('copy');
61-
} catch (err) {
62-
return false;
63-
} finally {
64-
this.removeFake();
65-
}
77+
// Insert it into the DOM.
78+
document.body.appendChild(textArea);
79+
80+
// Copy its contents to the clipboard.
81+
const success = this.copyTextArea(textArea);
82+
83+
// Remove it from the DOM, so it can be garbage-collected.
84+
if (textArea.parentNode) {
85+
// We cannot use ChildNode.remove() because of IE11.
86+
textArea.parentNode.removeChild(textArea);
6687
}
88+
89+
return success;
90+
}
6791
}

0 commit comments

Comments
 (0)