1

Describe the issue/behavior that seems buggy

❌ when typing it adds the text/code in reverse when typing.

ezgif-4-883a8c0c6e

Sample Code or Instructions to Reproduce

when using contendeditable attribute in the <code> HTML tag element.

<pre>
   <code contenteditable="true"></code>
</pre>

with an input event listener

and using this js library https://highlightjs.org/ for syntax highlighting

const code = document.querySelector("code");

code.addEventListener("input", () => {
    hljs.highlightElement(code); // this came from this js library https://highlightjs.org/
    // other code logic (mostly saving to localStorage)
}

like you saw in every typed letter I will add the highlight functionality,
but seems that completely breaks the typing direction

and yes, input events also work for not <input> tags if they have that attribute (contenteditable)
docs: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event

source code:

https://jsfiddle.net/20zpL5bk/


  • also another bug is that we can't go down the line break. (only if there is hljs.highlightElement(code);)

✅ here without hljs.highlightElement(code); is super fluid and can't do everything (but not syntax highlight):

ezgif com-gif-maker (66)

(how can I have fluid, normal writing with also syntax highlighting in real-time (input event)?
is my code wrong for some reason?)


Expected behavior

✅ how should be: <div></div> or hello world

❌ how it is now: >vid/<>vid< or dlrow olleh

Additional context

I tried to write the code in reverse myself manually >vid/<dlrow olleh>vid<, and yes the highlighting works. image

but the direction is always the wrong way. (also deleting isn't possible)

  • another interesting thing is if you copy and paste (CTRL+V) the correct code <div>hello world</div> it works fine. (but still remain in the same line, no multiple lines)

  • also the cursor of the input doesn't move with the text but remains at the start


source code:

https://jsfiddle.net/20zpL5bk/

let inputs = document.querySelectorAll("textarea");
let langs = ["html", "css", "javascript"];

let outputs = document.querySelectorAll("code");

outputs.forEach((code, index) => {
  // ✅ make it like input 
  code.contentEditable = "true";
  // ✅ if there is some code from localStorage we add it to the website.
  code.innerHTML = localStorage.getItem(`${langs[index]}`) || "";
  // ✅ styling of your library (work great when app start)
  hljs.highlightElement(code);

  code.addEventListener("input", () => {
    localStorage.setItem(`${langs[index]}`, code.innerHTML);
    // ❌ why the typing is reversed here?
    // if the next line isn't there then it work fine, otherwise it will change the values to reversed
    hljs.highlightElement(code);

    // console.log
    // example to type <div></div>
    // what I get >vid/<>vid<
  });
});
body {
  --gap: 2vmin;
  margin: 0;
  height: 100vh;
}

#container {
  display: flex;
  height: 100%;
  gap: var(--gap);
  padding: var(--gap);
  box-sizing: border-box;
}

#container>* {
  flex: 1;
  display: grid;
  grid-template-rows: auto 1fr;
  gap: var(--gap);
}

code {
  overflow: auto;
  white-space: pre;
  border: 0.2rem solid;
  border-radius: 0.5rem;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Document</title>
  <link rel="stylesheet" href="style.css" />
</head>

<body>
  <div id="container">
    <div>
      <span>HTML</span>
      <code class="language-html" style="border-color: orange;"></code>
    </div>

    <div>
      <span>CSS</span>
      <code class="language-css" style="border-color: blue;"></code>
    </div>

    <div>
      <span>JS</span>
      <code class="language-js" style="border-color: yellow;"></code>
    </div>
  </div>

  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/styles/default.min.css" />
  <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/highlight.min.js"></script>

  <script src="./script.js"></script>
</body>

</html>
isherwood
  • 58,414
  • 16
  • 114
  • 157
stackdeveloper
  • 352
  • 2
  • 21
  • For me it works, i typed hello world and it was in order, i have a SecurityError though because of localStorage, it might prevent your bug from happening – Lk77 Sep 01 '22 at 15:11
  • @Lk77 yes, use this https://jsfiddle.net/20zpL5bk/ for the actual bug... the security thing is only for iframe code snippet on stackOverFlow. isn't the problem here, so pls see https://jsfiddle.net/20zpL5bk/ – stackdeveloper Sep 01 '22 at 15:14
  • The problem is in your input listener, that line cause the bug : `hljs.highlightElement(code);` try to use change event instead – Lk77 Sep 01 '22 at 15:16
  • yes, ok i know that, that line is important for highlighting the code and making it syntax colored. why that line reverse it? https://highlightjs.org/ – stackdeveloper Sep 01 '22 at 15:17
  • 3
    it's resetting the input at every character i guess – Lk77 Sep 01 '22 at 15:17
  • @Lk77 so you mean that the cursor at every keypress it moves to the start causing this bug? so we need a way to not reset it or move the cursor to the end? – stackdeveloper Sep 01 '22 at 15:18
  • I think this function override the value which cause a reset of the cursor position – Lk77 Sep 01 '22 at 15:19
  • @Lk77 thanks, how can not make it override, if you have a answer write it and I will upvote and accept it of course, and thanks! – stackdeveloper Sep 01 '22 at 15:20
  • 1
    I would try this solution : https://stackoverflow.com/a/6249440/8126784 to move the caret where it was, which imply that you know where the caret was, don't know if it"s doable, and i don't know if it's still work, it's 2011 afterall. And also it's an input not a code element so perhaps it does not apply here – Lk77 Sep 01 '22 at 15:26
  • don't work, because needs an element node (is good if you want to make the cursor navigate from a tag to another tag), but I want to do something like by index and do `input.length - 1` and move every character (at least go the end). thanks as always I will figure out, thanks for the hint :) – stackdeveloper Sep 01 '22 at 15:34
  • @Lk77 the best solution I found so far and is working https://stackoverflow.com/a/69727327/17716837 simple and modern – stackdeveloper Sep 01 '22 at 15:54
  • i have a potential solution : https://jsfiddle.net/lk77/v69xgw1n/88/ it works but it's blurry, i guess code and textarea don't have exactly the same style – Lk77 Sep 01 '22 at 15:59
  • 1
    I improved it a little : https://jsfiddle.net/lk77/v69xgw1n/114/ but i guess it can happen again if both elements are not on top of each other. And there is still the multiline issue so... not very reliable – Lk77 Sep 01 '22 at 16:07

0 Answers0