I'm experimenting with a text editor (just playing around with different ways to make one) and am using a svelte text area. One problem with this text area is that tab is not enabled by default. I was able to implement Ctrl+s quite easily but tab is more tricky.
The current method I'm using is to:
- Prevent default when there is a keydown on tab
- Set variables for the current cursor position, and a flag to indicate tab was pressed
- Manipulate the text area text using the substring method for strings to substring up to the selected area and after the selected area
- On subsequent keydown or keyup to reset my tab flag
This feels quite hacky to me so wanted to see if there was a more efficient way to do this.
Posting code here:
<script> import { onMount } from 'svelte'; const endpoint = "http://localhost:5000/"; // State let planner_text; let textarea_elem; let tab_selected = 0; let tab = false; // Load test.txt on mount onMount(async () => { const response = await fetch(endpoint); const data = await response.json(); planner_text = data["text"]; }); // Save functionality const update_planner = () => { fetch(endpoint, { method: "POST", body: JSON.stringify({ data: planner_text }), headers: {"Content-type": "application/json; charset=UTF-8" } }); } // Key down funcitonality const keydown = e => { tabset(); // save if (e.ctrlKey && e.keyCode == 83) { e.preventDefault(); update_planner(); } /* tab */ else if (e.keyCode == 9) { e.preventDefault(); const {selectionStart, selectionEnd} = textarea_elem; tab_selected = selectionStart + 1; tab = true; planner_text = planner_text.substring(0, selectionStart) +'\t'+ planner_text.substring(selectionEnd) textarea_elem.setSelectionRange(tab_selected, tab_selected) } } const tabset = () => { if (tab) { textarea_elem.setSelectionRange(tab_selected, tab_selected) tab = false; } };</script><main><div class="container"><textarea class="scratch-pad" bind:this={textarea_elem} bind:value={planner_text} on:keydown={keydown} on:keyup={() => {tabset()}}/><button class="lock-in-btn" on:click={update_planner}>Lock in</button></div></main>