Skip to content

Commit

Permalink
[MacOS] added menu bar items for Copy, Cut, Paste, Select All
Browse files Browse the repository at this point in the history
  • Loading branch information
veler committed Jul 22, 2024
1 parent 6b5f92b commit cff8d8f
Show file tree
Hide file tree
Showing 15 changed files with 1,390 additions and 785 deletions.
94 changes: 94 additions & 0 deletions src/app/dev/DevToys.Blazor/Assets/javascript/dom.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/app/dev/DevToys.Blazor/Assets/javascript/dom.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

113 changes: 113 additions & 0 deletions src/app/dev/DevToys.Blazor/Assets/javascript/dom.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import MonacoEditor from "./monacoEditor";

class DOM {
public static setFocus(element: HTMLElement): boolean {
element.focus();
Expand Down Expand Up @@ -33,6 +35,97 @@ class DOM {
"[contentEditable=true]:not([tabindex='-1']");
}

public static cutFromCurrentFocusedElement(): void {
// Get the currently focused element
const focusedElement: Element = document.activeElement;

// Check if the focused element is an input or textarea
if (focusedElement && (focusedElement.tagName.toLowerCase() === 'input')) {
// Cast the element to HTMLInputElement
const inputElement: HTMLInputElement = <HTMLInputElement>focusedElement;

// Get the current selection
const startPos: number = inputElement.selectionStart;
const endPos: number = inputElement.selectionEnd;

// Copy the selected text to the clipboard
const selectedText: string = inputElement.value.substring(startPos, endPos);
navigator.clipboard.writeText(selectedText);

// Remove the selected text from the input element
inputElement.value = inputElement.value.substring(0, startPos) + inputElement.value.substring(endPos);

// Move the caret to the start of the removed text
inputElement.selectionStart = inputElement.selectionEnd = startPos;
} else if (focusedElement.tagName.toLowerCase() == 'textarea') {
const monacoEditorId: string = DOM.getIdOfMonacoInstanceFromTextarea(focusedElement as HTMLTextAreaElement);
MonacoEditor.cut(monacoEditorId);
}
}

public static copyFromCurrentFocusedElement(): void {
// Get the currently focused element
const focusedElement: Element = document.activeElement;

// Check if the focused element is an input or textarea
if (focusedElement && (focusedElement.tagName.toLowerCase() === 'input')) {
// Cast the element to HTMLInputElement
const inputElement: HTMLInputElement = <HTMLInputElement>focusedElement;

// Get the current selection
const startPos: number = inputElement.selectionStart;
const endPos: number = inputElement.selectionEnd;

// Copy the selected text to the clipboard
const selectedText: string = inputElement.value.substring(startPos, endPos);
navigator.clipboard.writeText(selectedText);
} else if (focusedElement.tagName.toLowerCase() == 'textarea') {
const monacoEditorId: string = DOM.getIdOfMonacoInstanceFromTextarea(focusedElement as HTMLTextAreaElement);
MonacoEditor.copy(monacoEditorId);
}
}

public static pasteInCurrentFocusedElement(clipboardData: string): void {
// Get the currently focused element
const focusedElement: Element = document.activeElement;

// Check if the focused element is an input or textarea
if (focusedElement && (focusedElement.tagName.toLowerCase() === 'input')) {
// Cast the element to HTMLInputElement
const inputElement: HTMLInputElement = <HTMLInputElement>focusedElement;

// Get the current caret position
const startPos: number = inputElement.selectionStart;
const endPos: number = inputElement.selectionEnd;

// Insert the clipboard data at the caret position
inputElement.value = inputElement.value.substring(0, startPos) + clipboardData + inputElement.value.substring(endPos);

// Move the caret to the end of the inserted data
inputElement.selectionStart = inputElement.selectionEnd = startPos + clipboardData.length;
} else if (focusedElement.tagName.toLowerCase() == 'textarea') {
const monacoEditorId: string = DOM.getIdOfMonacoInstanceFromTextarea(focusedElement as HTMLTextAreaElement);
MonacoEditor.paste(monacoEditorId);
}
}

public static selectAllInCurrentFocusedElement(): void {
// Get the currently focused element
const focusedElement: Element = document.activeElement;

// Check if the focused element is an input or textarea
if (focusedElement && (focusedElement.tagName.toLowerCase() === 'input')) {
// Cast the element to HTMLInputElement
const inputElement: HTMLInputElement = <HTMLInputElement>focusedElement;

// Select all text in the input element
inputElement.select();
} else if (focusedElement.tagName.toLowerCase() == 'textarea') {
const monacoEditorId: string = DOM.getIdOfMonacoInstanceFromTextarea(focusedElement as HTMLTextAreaElement);
MonacoEditor.selectAll(monacoEditorId);
}
}

public static addFontToDocument(fontDefinition: string): void {
const css: HTMLStyleElement = document.createElement("style");
css.innerHTML = fontDefinition;
Expand All @@ -51,6 +144,26 @@ class DOM {
document.removeEventListener(eventName, DOM.documentEventListener);
}

private static getIdOfMonacoInstanceFromTextarea(textarea: HTMLTextAreaElement): string | null {
// Start with the parent of the textarea
let parent = textarea.parentElement;

// Traverse up the DOM tree
while (parent) {
// Check if the parent has the class "monaco-editor-standalone-instance"
if (parent.classList.contains('monaco-editor-standalone-instance')) {
// Return the id of the parent
return parent.id;
}

// Move up to the next parent
parent = parent.parentElement;
}

// If no parent with the class "monaco-editor-standalone-instance" is found, return null
return null;
}

private static documentEventListener(e?: Event): void {
const eventJson = DOM.stringifyEvent(e);
const dotNetObjRef = (<DotNet.DotNetObject>(<any>document).documentEventService);
Expand Down
20 changes: 20 additions & 0 deletions src/app/dev/DevToys.Blazor/Assets/javascript/monacoEditor.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Large diffs are not rendered by default.

Loading

0 comments on commit cff8d8f

Please sign in to comment.