Skip to content

Commit 6cbcc23

Browse files
authored
Merge pull request #100 from WebCoder49/fix-caret-out-of-view
Fix caret out of view
2 parents c068194 + 3ab457c commit 6cbcc23

File tree

3 files changed

+59
-19
lines changed

3 files changed

+59
-19
lines changed

code-input.css

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,16 @@ code-input textarea, code-input:not(.code-input_pre-element-styled) pre code, co
4141
margin: 0px!important;
4242
padding: var(--padding, 16px)!important;
4343
border: 0;
44-
min-width: calc(100% - var(--padding, 16px) * 2);
45-
min-height: calc(100% - var(--padding, 16px) * 2);
44+
min-width: 100%;
45+
min-height: 100%;
46+
box-sizing: border-box; /* Don't need to worry about padding to calculate width! */
4647
overflow: hidden;
4748
resize: none;
4849
grid-row: 1;
4950
grid-column: 1;
5051
display: block;
5152
}
53+
5254
code-input:not(.code-input_pre-element-styled) pre code, code-input.code-input_pre-element-styled pre {
5355
height: max-content;
5456
width: max-content;

code-input.js

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,7 @@ var codeInput = {
482482
* to syntax-highlight it. */
483483

484484
needsHighlight = false; // Just inputted
485+
passEventsToTextarea = true; // Turn to false when unusual internal events are called on the textarea
485486

486487
/**
487488
* Highlight the code as soon as possible
@@ -494,17 +495,6 @@ var codeInput = {
494495
* Call an animation frame
495496
*/
496497
animateFrame() {
497-
// Synchronise the size of the pre/code and textarea elements
498-
if(this.template.preElementStyled) {
499-
this.style.backgroundColor = getComputedStyle(this.preElement).backgroundColor;
500-
this.textareaElement.style.height = getComputedStyle(this.preElement).height;
501-
this.textareaElement.style.width = getComputedStyle(this.preElement).width;
502-
} else {
503-
this.style.backgroundColor = getComputedStyle(this.codeElement).backgroundColor;
504-
this.textareaElement.style.height = getComputedStyle(this.codeElement).height;
505-
this.textareaElement.style.width = getComputedStyle(this.codeElement).width;
506-
}
507-
508498
// Synchronise the contents of the pre/code and textarea elements
509499
if(this.needsHighlight) {
510500
this.update();
@@ -534,6 +524,22 @@ var codeInput = {
534524
if (this.template.includeCodeInputInHighlightFunc) this.template.highlight(resultElement, this);
535525
else this.template.highlight(resultElement);
536526

527+
// Synchronise the size of the pre/code and textarea elements
528+
if(this.template.preElementStyled) {
529+
this.style.backgroundColor = getComputedStyle(this.preElement).backgroundColor;
530+
this.textareaElement.style.height = getComputedStyle(this.preElement).height;
531+
this.textareaElement.style.width = getComputedStyle(this.preElement).width;
532+
} else {
533+
this.style.backgroundColor = getComputedStyle(this.codeElement).backgroundColor;
534+
this.textareaElement.style.height = getComputedStyle(this.codeElement).height;
535+
this.textareaElement.style.width = getComputedStyle(this.codeElement).width;
536+
}
537+
// Scroll to the caret by focusing, though this shouldn't count as a focus event
538+
this.passEventsToTextarea = false;
539+
this.textareaElement.blur();
540+
this.textareaElement.focus();
541+
this.passEventsToTextarea = true;
542+
537543
this.pluginEvt("afterHighlight");
538544
}
539545

@@ -737,7 +743,7 @@ var codeInput = {
737743
if (this.template.preElementStyled) this.classList.add("code-input_pre-element-styled");
738744
else this.classList.remove("code-input_pre-element-styled");
739745
// Syntax Highlight
740-
this.needsHighlight = true;
746+
this.scheduleHighlight();
741747

742748
break;
743749

@@ -769,7 +775,7 @@ var codeInput = {
769775

770776
if (mainTextarea.placeholder == oldValue) mainTextarea.placeholder = newValue;
771777

772-
this.needsHighlight = true;
778+
this.scheduleHighlight();
773779

774780
break;
775781
default:
@@ -806,8 +812,9 @@ var codeInput = {
806812
* @override
807813
*/
808814
addEventListener(type, listener, options = undefined) {
809-
// Save a copy of the callback where `this` refers to the code-input element
810-
let boundCallback = listener.bind(this);
815+
// Save a copy of the callback where `this` refers to the code-input element.
816+
// This callback is modified to only run when the passEventsToTextarea is set.
817+
let boundCallback = function(evt) { if(this.passEventsToTextarea) listener(evt); }.bind(this);
811818
this.boundEventCallbacks[listener] = boundCallback;
812819

813820
if (codeInput.textareaSyncEvents.includes(type)) {
@@ -885,7 +892,7 @@ var codeInput = {
885892
// Save in editable textarea element
886893
this.textareaElement.value = val;
887894
// Trigger highlight
888-
this.needsHighlight = true;
895+
this.scheduleHighlight();
889896
return val;
890897
}
891898

plugins/indent.js

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,33 @@ codeInput.plugins.Indent = class extends codeInput.Plugin {
2828
}
2929
}
3030

31-
/* Add keystroke events */
31+
/* Add keystroke events, and get the width of the indentation in pixels. */
3232
afterElementsAdded(codeInput) {
3333
let textarea = codeInput.textareaElement;
3434
textarea.addEventListener('keydown', (event) => { this.checkTab(codeInput, event); this.checkEnter(codeInput, event); this.checkBackspace(codeInput, event); });
3535
textarea.addEventListener('beforeinput', (event) => { this.checkCloseBracket(codeInput, event); });
36+
37+
// Get the width of the indentation in pixels
38+
let testIndentationWidthPre = document.createElement("pre");
39+
testIndentationWidthPre.setAttribute("aria-hidden", "true"); // Hide for screen readers
40+
let testIndentationWidthSpan = document.createElement("span");
41+
if(codeInput.template.preElementStyled) {
42+
testIndentationWidthPre.appendChild(testIndentationWidthSpan);
43+
testIndentationWidthPre.classList.add("code-input_autocomplete_test-indentation-width");
44+
codeInput.appendChild(testIndentationWidthPre); // Styled like first pre, but first pre found to update
45+
} else {
46+
let testIndentationWidthCode = document.createElement("code");
47+
testIndentationWidthCode.appendChild(testIndentationWidthSpan);
48+
testIndentationWidthCode.classList.add("code-input_autocomplete_test-indentation-width");
49+
testIndentationWidthPre.appendChild(testIndentationWidthCode);
50+
codeInput.appendChild(testIndentationWidthPre); // Styled like first pre, but first pre found to update
51+
}
52+
53+
testIndentationWidthSpan.innerHTML = codeInput.escapeHtml(this.indentation);
54+
let indentationWidthPx = testIndentationWidthSpan.offsetWidth;
55+
codeInput.removeChild(testIndentationWidthPre);
56+
57+
codeInput.pluginData.indent = {indentationWidthPx: indentationWidthPx};
3658
}
3759

3860
/* 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 {
93115
// move cursor
94116
inputElement.selectionStart = selectionStartI;
95117
inputElement.selectionEnd = selectionEndI;
118+
119+
// move scroll position to follow code
120+
console.log("indw", codeInput.pluginData.indent.indentationWidthPx);
121+
if(event.shiftKey) {
122+
console.log("shift");
123+
codeInput.scrollBy(-codeInput.pluginData.indent.indentationWidthPx, 0);
124+
} else {
125+
codeInput.scrollBy(codeInput.pluginData.indent.indentationWidthPx, 0);
126+
}
96127
}
97128

98129
codeInput.value = inputElement.value;

0 commit comments

Comments
 (0)