From 78d08c7fbc4f71f5f26f0502ae6e35d0fdbb64e2 Mon Sep 17 00:00:00 2001 From: WebCoder49 Date: Mon, 27 May 2024 12:34:02 +0100 Subject: [PATCH 1/2] Ensure caret visible when text added horizontally --- code-input.css | 6 ++++-- code-input.js | 39 +++++++++++++++++++++++---------------- 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/code-input.css b/code-input.css index 8fd5eb5..ffddc48 100644 --- a/code-input.css +++ b/code-input.css @@ -41,14 +41,16 @@ code-input textarea, code-input:not(.code-input_pre-element-styled) pre code, co margin: 0px!important; padding: var(--padding, 16px)!important; border: 0; - min-width: calc(100% - var(--padding, 16px) * 2); - min-height: calc(100% - var(--padding, 16px) * 2); + min-width: 100%; + min-height: 100%; + box-sizing: border-box; /* Don't need to worry about padding to calculate width! */ overflow: hidden; resize: none; grid-row: 1; grid-column: 1; display: block; } + code-input:not(.code-input_pre-element-styled) pre code, code-input.code-input_pre-element-styled pre { height: max-content; width: max-content; diff --git a/code-input.js b/code-input.js index 844c541..d5b5de9 100644 --- a/code-input.js +++ b/code-input.js @@ -482,6 +482,7 @@ var codeInput = { * to syntax-highlight it. */ needsHighlight = false; // Just inputted + passEventsToTextarea = true; // Turn to false when unusual internal events are called on the textarea /** * Highlight the code as soon as possible @@ -494,17 +495,6 @@ var codeInput = { * Call an animation frame */ animateFrame() { - // Synchronise the size of the pre/code and textarea elements - if(this.template.preElementStyled) { - this.style.backgroundColor = getComputedStyle(this.preElement).backgroundColor; - this.textareaElement.style.height = getComputedStyle(this.preElement).height; - this.textareaElement.style.width = getComputedStyle(this.preElement).width; - } else { - this.style.backgroundColor = getComputedStyle(this.codeElement).backgroundColor; - this.textareaElement.style.height = getComputedStyle(this.codeElement).height; - this.textareaElement.style.width = getComputedStyle(this.codeElement).width; - } - // Synchronise the contents of the pre/code and textarea elements if(this.needsHighlight) { this.update(); @@ -534,6 +524,22 @@ var codeInput = { if (this.template.includeCodeInputInHighlightFunc) this.template.highlight(resultElement, this); else this.template.highlight(resultElement); + // Synchronise the size of the pre/code and textarea elements + if(this.template.preElementStyled) { + this.style.backgroundColor = getComputedStyle(this.preElement).backgroundColor; + this.textareaElement.style.height = getComputedStyle(this.preElement).height; + this.textareaElement.style.width = getComputedStyle(this.preElement).width; + } else { + this.style.backgroundColor = getComputedStyle(this.codeElement).backgroundColor; + this.textareaElement.style.height = getComputedStyle(this.codeElement).height; + this.textareaElement.style.width = getComputedStyle(this.codeElement).width; + } + // Scroll to the caret by focusing, though this shouldn't count as a focus event + this.passEventsToTextarea = false; + this.textareaElement.blur(); + this.textareaElement.focus(); + this.passEventsToTextarea = true; + this.pluginEvt("afterHighlight"); } @@ -737,7 +743,7 @@ var codeInput = { if (this.template.preElementStyled) this.classList.add("code-input_pre-element-styled"); else this.classList.remove("code-input_pre-element-styled"); // Syntax Highlight - this.needsHighlight = true; + this.scheduleHighlight(); break; @@ -769,7 +775,7 @@ var codeInput = { if (mainTextarea.placeholder == oldValue) mainTextarea.placeholder = newValue; - this.needsHighlight = true; + this.scheduleHighlight(); break; default: @@ -806,8 +812,9 @@ var codeInput = { * @override */ addEventListener(type, listener, options = undefined) { - // Save a copy of the callback where `this` refers to the code-input element - let boundCallback = listener.bind(this); + // Save a copy of the callback where `this` refers to the code-input element. + // This callback is modified to only run when the passEventsToTextarea is set. + let boundCallback = function(evt) { if(this.passEventsToTextarea) listener(evt); }.bind(this); this.boundEventCallbacks[listener] = boundCallback; if (codeInput.textareaSyncEvents.includes(type)) { @@ -885,7 +892,7 @@ var codeInput = { // Save in editable textarea element this.textareaElement.value = val; // Trigger highlight - this.needsHighlight = true; + this.scheduleHighlight(); return val; } From 3ab457c8ecb1f501de1657ca3a3d344950227077 Mon Sep 17 00:00:00 2001 From: WebCoder49 Date: Mon, 27 May 2024 13:21:16 +0100 Subject: [PATCH 2/2] Make scrolling horizontally work correctly for indentation --- plugins/indent.js | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/plugins/indent.js b/plugins/indent.js index 113cbcb..b3dbaf9 100644 --- a/plugins/indent.js +++ b/plugins/indent.js @@ -28,11 +28,33 @@ codeInput.plugins.Indent = class extends codeInput.Plugin { } } - /* Add keystroke events */ + /* Add keystroke events, and get the width of the indentation in pixels. */ afterElementsAdded(codeInput) { let textarea = codeInput.textareaElement; textarea.addEventListener('keydown', (event) => { this.checkTab(codeInput, event); this.checkEnter(codeInput, event); this.checkBackspace(codeInput, event); }); textarea.addEventListener('beforeinput', (event) => { this.checkCloseBracket(codeInput, event); }); + + // Get the width of the indentation in pixels + let testIndentationWidthPre = document.createElement("pre"); + testIndentationWidthPre.setAttribute("aria-hidden", "true"); // Hide for screen readers + let testIndentationWidthSpan = document.createElement("span"); + if(codeInput.template.preElementStyled) { + testIndentationWidthPre.appendChild(testIndentationWidthSpan); + testIndentationWidthPre.classList.add("code-input_autocomplete_test-indentation-width"); + codeInput.appendChild(testIndentationWidthPre); // Styled like first pre, but first pre found to update + } else { + let testIndentationWidthCode = document.createElement("code"); + testIndentationWidthCode.appendChild(testIndentationWidthSpan); + testIndentationWidthCode.classList.add("code-input_autocomplete_test-indentation-width"); + testIndentationWidthPre.appendChild(testIndentationWidthCode); + codeInput.appendChild(testIndentationWidthPre); // Styled like first pre, but first pre found to update + } + + testIndentationWidthSpan.innerHTML = codeInput.escapeHtml(this.indentation); + let indentationWidthPx = testIndentationWidthSpan.offsetWidth; + codeInput.removeChild(testIndentationWidthPre); + + codeInput.pluginData.indent = {indentationWidthPx: indentationWidthPx}; } /* Deal with the Tab key causing indentation, and Tab+Selection indenting / Shift+Tab+Selection unindenting lines */ @@ -93,6 +115,15 @@ codeInput.plugins.Indent = class extends codeInput.Plugin { // move cursor inputElement.selectionStart = selectionStartI; inputElement.selectionEnd = selectionEndI; + + // move scroll position to follow code + console.log("indw", codeInput.pluginData.indent.indentationWidthPx); + if(event.shiftKey) { + console.log("shift"); + codeInput.scrollBy(-codeInput.pluginData.indent.indentationWidthPx, 0); + } else { + codeInput.scrollBy(codeInput.pluginData.indent.indentationWidthPx, 0); + } } codeInput.value = inputElement.value;