5

How can I show a blinking cursor (allowing for text selection via keyboard) in a div but keep it read-only (disallowing text input)?

I know I can set contentEditable to enable the cursor on a div but then users can edit the contents. I've tried adding both contentEditable and readonly to the div but it seems readonly is only effective on input elements, like textarea or input.

I also have tried using a textarea and setting it to readonly so it shows the cursor but doesn't allow text input, like this:

<textarea readonly>Go ahead and move the cursor here but don't try to add text</textarea>

This is the functionality I'm looking for but I want to do this with a div or some other non-input element. I'm open to using 3rd party libraries.


Note: "Cursor" or "caret" here is referring to the blinking lines that indicates where text selection starts/ends.

Brady Dowling
  • 4,920
  • 3
  • 32
  • 62

2 Answers2

6

Here you go :) . All you need to do is disable cut/copy/paste and key press events.

<div
  contenteditable="true"
  oncut="return false"
  onpaste="return false"
  onkeydown="return false;"
  style="user-drag: none;"
  ondragenter="return false;" 
  ondragleave="return false;" 
  ondragover="return false;" 
  ondrop="return false;">
  Inner content
</div>
Gaurav Saraswat
  • 1,353
  • 8
  • 11
  • This is basically what I am looking for but it disables text selection. For that I guess I'd have to dig into the onkeydown event and make sure it doesn't preventDefault when the user hits the arrow keys or shift. This seems like a good solution. – Brady Dowling Feb 15 '19 at 12:44
  • 1
    to actually detect and allow `ctrl+c` you can use this [answer](https://stackoverflow.com/a/2904944/8397816) – Gaurav Saraswat Feb 15 '19 at 12:54
  • @BradyDowling Can you please accept the answer if it served the purpose. – Gaurav Saraswat Feb 15 '19 at 13:14
  • I still can edit the content. Select the text and move it (drag-drop) to another part of the sentence. – Roko C. Buljan Feb 15 '19 at 13:54
  • Also, inline-JS is a bad habit and can even raise `unsafe-inline` flags. `addEventListener` should be used towards separation of concerns. – Roko C. Buljan Feb 15 '19 at 14:03
  • @RokoC.Buljan fixed drag and drop issue. and i added inline JS just for the sake of code brewity. but it doesn't deserve downvote. no? – Gaurav Saraswat Feb 15 '19 at 19:24
0

In Vanilla JavaScript, This is the simplest example of how you can go about doing it. I am using a class here, but as other answers showed, you could change it to an actual attribute or whatever suits your linking.

  const uneditables = Array.from(
        document.querySelectorAll(".editable-but-not-really")
  );

  const doNothing = e => e.preventDefault();

  uneditables.forEach(element => {
    element.setAttribute("contentEditable", true);
    element.addEventListener("oncut", doNothing, false);
    element.addEventListener("onpaste", doNothing, false);
    element.addEventListener("keydown", doNothing, false);
  });
<div class="editable-but-not-really">I am here to stay</div>
<div class="editable-but-not-really">You cannot edit me</div>
<div class="editable-but-not-really">I was born to stay</div>
<div class="editable-but-not-really">As I am, and I don't</div>
<div class="editable-but-not-really">want anything to do with</div>
<div class="editable-but-not-really">your stinky pointer</div>
Abderrahmane TAHRI JOUTI
  • 3,514
  • 2
  • 26
  • 43