refactor(docs-infra): improve code readability of `CopierService` (#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 #38244
This commit is contained in:
George Kalpakas 2020-07-29 17:38:10 +03:00 committed by Misko Hevery
parent d8c07b83c3
commit 9ebd461a22
1 changed files with 68 additions and 44 deletions

View File

@ -9,59 +9,83 @@
export class CopierService { export class CopierService {
private fakeElem: HTMLTextAreaElement|null; /**
* Copy the contents of a `<textarea>` element to the clipboard.
*
* NOTE: For this method to work, the elements must be already inserted into the DOM.
*
* @param textArea The area containing the text to be copied to the clipboard.
* @return Whether the copy operation was successful.
*/
private copyTextArea(textArea: HTMLTextAreaElement): boolean {
try {
textArea.select();
textArea.setSelectionRange(0, textArea.value.length);
return document.execCommand('copy');
} catch {
return false;
}
}
/** /**
* Creates a fake textarea element, sets its value from `text` property, * Create a temporary, hidden `<textarea>` element and set its value to the specified text.
* and makes a selection on it. *
* @param text The text to be inserted into the textarea.
* @return The temporary `<textarea>` element containing the specified text.
*/ */
createFake(text: string) { private createTextArea(text: string): HTMLTextAreaElement {
const docElem = document.documentElement!; const docElem = document.documentElement!;
const isRTL = docElem.getAttribute('dir') === 'rtl'; const isRTL = docElem.getAttribute('dir') === 'rtl';
// Create a fake element to hold the contents to copy // Create a temporary element to hold the contents to copy.
this.fakeElem = document.createElement('textarea'); const textArea = document.createElement('textarea');
const style = textArea.style;
// Prevent zooming on iOS // Prevent zooming on iOS.
this.fakeElem.style.fontSize = '12pt'; style.fontSize = '12pt';
// Reset box model // Reset box model.
this.fakeElem.style.border = '0'; style.border = '0';
this.fakeElem.style.padding = '0'; style.padding = '0';
this.fakeElem.style.margin = '0'; style.margin = '0';
// Move element out of screen horizontally // Move element out of screen horizontally.
this.fakeElem.style.position = 'absolute'; style.position = 'absolute';
this.fakeElem.style[ isRTL ? 'right' : 'left' ] = '-9999px'; style[ isRTL ? 'right' : 'left' ] = '-9999px';
// Move element to the same position vertically // Move element to the same position vertically.
const yPosition = window.pageYOffset || docElem.scrollTop; const yPosition = window.pageYOffset || docElem.scrollTop;
this.fakeElem.style.top = yPosition + 'px'; style.top = yPosition + 'px';
this.fakeElem.setAttribute('readonly', ''); textArea.setAttribute('readonly', '');
this.fakeElem.value = text; textArea.value = text;
document.body.appendChild(this.fakeElem); return textArea;
this.fakeElem.select();
this.fakeElem.setSelectionRange(0, this.fakeElem.value.length);
} }
removeFake() { /**
if (this.fakeElem) { * Copy the specified text to the clipboard.
document.body.removeChild(this.fakeElem); *
this.fakeElem = null; * @param text The text to be copied to the clipboard.
} * @return Whether the copy operation was successful.
*/
copyText(text: string): boolean {
// Create a `<textarea>` element with the specified text.
const textArea = this.createTextArea(text);
// Insert it into the DOM.
document.body.appendChild(textArea);
// Copy its contents to the clipboard.
const success = this.copyTextArea(textArea);
// Remove it from the DOM, so it can be garbage-collected.
if (textArea.parentNode) {
// We cannot use ChildNode.remove() because of IE11.
textArea.parentNode.removeChild(textArea);
} }
copyText(text: string) { return success;
try {
this.createFake(text);
return document.execCommand('copy');
} catch (err) {
return false;
} finally {
this.removeFake();
}
} }
} }