8

http://jsfiddle.net/VzbYJ/86/

Please have a look at this link. As it clears that it is going to insert a span node at the caret place. Problem is,after inserting the node if I am pressing any character its color is also green. because it is also coming inside the span element. So how can I put the caret after the span so that the color of next inserted node remains normal.

I tried to find the selected node (based on to caret position), set the range after the element and used collapse(false). But I could not get the desired output.

Code for find the node :

  function findNode(event)
  {
    if (event.type == 'click')
    par = event.target;

    else if (event.type == 'keyup'){        
        if (document.selection)
        par = document.selection.createRange().parentElement();
    else if (window.getSelection){
        var range = window.getSelection().getRangeAt(0);
        par = range.commonAncestorContainer.parentNode;
    }
  }

and next I set the boundary using setEndAfter() ant collapse(false). I am new in this field so I am not sure that what extend I am right. So any suggestion is very much appreciable. Thanks in advance.

DEV
  • 2,106
  • 3
  • 25
  • 40

2 Answers2

13

A quick look at the "Related" section on this very page will give you links to all the information you need. In summary, the browser (unless it's Firefox) prevents it and the easiest workaround is to insert a zero-width space character (Unicode U+200B) after the inserted <span> element. As well as being a very ugly hack, this does have the problem of keeping track of and removing these zero-width spaces once they're no longer required.

I've updated your jsFiddle to use this approach but without any code to remove the zero-width spaces:

http://jsfiddle.net/VzbYJ/87/

For background, here's a list of relevant questions/answers:

I need a stock answer for this, it comes up so often...

Community
  • 1
  • 1
Tim Down
  • 318,141
  • 75
  • 454
  • 536
  • I used this method but couldn't get rid of the unicode character! But I figured it out. Use some regex on your content (via getContent and setContent) to replace "​". But here's the trick, those won't show up unless you use getContent like so: getContent({format: 'numeric'}); – Joel Worsham Nov 20 '14 at 16:54
  • Should the zero width character be in it's own element, or on it's own after the other element as a text node. – Quentin Engles Nov 13 '17 at 02:51
  • @QuentinEngles: I don't think it matters. It may be convenient to put the zero-width space in its own element for clean-up purposes. – Tim Down Nov 13 '17 at 11:08
  • @TimDown I think that's what I'll be using it for (cleanup). Also arrow keys, delete, and backspace have to be double input now with the zero width character. So I'm working to figure out how to get rid of that. – Quentin Engles Nov 13 '17 at 19:43
  • @QuentinEngles: Good luck. On one project I ended up ditching contenteditable entirely and drawing my own selection and caret, along with implementing custom handling for arrow keys, delete, double-click etc. Took a long time but works OK, although not so well on touch devices. – Tim Down Nov 14 '17 at 23:34
  • Yuck. Well whatever. I like a challenge. Maybe if I don't go insane while doing this I'll post some solutions back. I'm not going to support ieeee so at least I don't have to deal with that. – Quentin Engles Nov 15 '17 at 07:47
  • @QuentinEngles: Just to be clear, I'm not saying that ditching contenteditable is definitely what you should do. Just that it's an option, although a big undertaking. – Tim Down Nov 15 '17 at 10:28
  • @TimDown Oh that's fine. I was saying yuck about all of it. Either way it's a lot of work. I was still going to use contenteditable. Thanks for your advice. – Quentin Engles Nov 15 '17 at 22:15
2

This is an old post, and this is part of the solution to the problem. There are more complex approaches I haven't finished working out, but simple is always good.

const editor = document.querySelector('[contenteditable="true"]');
const spans = document.querySelectorAll('span[contenteditable="false"]');

Array.prototype.slice.call(spans).map(span => {
  const empty = document.createTextNode( '\uFEFF' );
  const parentEl = span.parentElement;
  const allchildnodes = editor.childNodes;
  const lastsib = allchildnodes[allchildnodes.length - 1];
  const ended = lastsib.wholeText === '\n';
  const prevsib = ended ? lastsib.previousSibling === span : false;
  if (prevsib) {
    parentEl.appendChild(empty);
  }
}); 

https://codepen.io/augur/pen/MvaKJO

augurone
  • 107
  • 5