2

I'm trying to reproduce a behavior of syntax Highlight.

How need to work ?

When I write they need to review the text to find some especific words and put a color.

So, what I already try:

HTML:

<div id="text" contenteditable="true">O </ div>

JS:

var text = document.getElementById('text');

text.onkeyup = function(evt) {
  if (this.textContent.indexOf("Brasil") > 0) {
    text.innerHTML = this.textContent.replace("Brasil", "<b class='green'>Brasil<b>");
  }
};

CSS:

.green{
  color:green;
}

Run on jsfiddle

The problems:

1 - The cursor moves to start.

2 - After write one word using the indexOf they will always replace with the same data.

Gabriel Rodrigues
  • 510
  • 1
  • 8
  • 29
  • Asking for help writing a plugin like [syntax highlighter](http://alexgorbatchev.com/SyntaxHighlighter/) is a pretty big request. ;-) What code have you tried to solve problems 1 and 2? – Adam Konieska Mar 04 '16 at 15:00

3 Answers3

0

You'd need to set the cursor back to the end of your inputted text. Refer to https://stackoverflow.com/a/512542/5448324 for details on how to do that.

As for finding all instances of specific text in a string, I'd refer you to https://stackoverflow.com/a/3365999/5448324

Community
  • 1
  • 1
  • 1
    You should copy some of the material into your answer, while keeping the hyperlinks. Link-only answers are discouraged. – mbomb007 Mar 04 '16 at 15:17
0

I've created a fiddle based on your code https://jsfiddle.net/d24z9ka4/ It's lousy but it works :-), and here is how:

text.onkeyup = function(evt) {
  // get how many times 'Brasil' occurs 
  var counter = this.textContent.split(/(Brasil)/ig).length;

  // lastCount is the place of the last occurrence, or nothing 
  if (counter > 1 && (!this.lastCount || this.lastCount < counter) ) {
    this.lastCount = counter;
    // get's all places where 'Brasil' is written
    this.innerHTML = this.textContent.replace(/(Brasil)/ig, "<b class='green'>Brasil</b>&nbsp;");

    // this moves cursor to last position available
    // based on this https://stackoverflow.com/questions/6249095/how-to-set-caretcursor-position-in-contenteditable-element-div
    var range = document.createRange();
    var sel = window.getSelection();

    // this is last node available, we'll go there
    var lastNode = text.childNodes.item(text.childNodes.length -1)
    range.setStart(lastNode, 1);
    range.collapse(true);
    sel.removeAllRanges();
    sel.addRange(range);
  }
};
nenadg
  • 420
  • 11
  • 16
  • @akinuri well it works in Chrome 48.0.2564.116 (64-bit) Linux, and in Firefox 44.0.2 at my box – nenadg Mar 04 '16 at 17:20
  • 1
    Typing "trees in brasil...". As soon as I finish typing brasil, cursor jumps to the beginning of the text and the word brasil isn't highlighted. Tested again on both FF 42 and Chrome 49 on Win 8.1. Doesn't work. – akinuri Mar 04 '16 at 17:54
  • yes, that's a bug in my code, you see: var counter = this.textContent.split(/(Brasil)/i).length; (case ignored) but in second regex this.textContent.replace(/(Brasil)/g I'm not ignoring case, thus resulting in behavior you mentioned. Going to fix it. – nenadg Mar 04 '16 at 17:57
0

You can try the following:

var text = document.getElementById('text');
var closingTag = "</b>";

text.onkeyup = function(evt) {
  // replace the string
  this.innerHTML = this.textContent.replace(/Brasil/ig, '<b class="green">Brasil</b>');
  // add an empty text node to the contenteditable element
  // so that we can move the cursor to it
  this.appendChild(document.createTextNode(""));
  // moving the cursor at the end of the element
  setCaret();
};

function setCaret() {
  var el = document.getElementById("text");
  var range = document.createRange();
  var sel = window.getSelection();
  // get the last child node from the contenteditable element
  // it's an empty node, so set the offset to 0
  range.setStart(el.childNodes[el.childNodes.length - 1], 0);
  range.collapse(true);
  sel.removeAllRanges();
  sel.addRange(range);
  el.focus();
}
.green {
  color: green;
}
#text {
  border: 1px solid rgba(0,0,0,.2);
}
<div id="text" contenteditable="true"></ div>

setCaret function is taken from Tim's answer.


I don't why but once you start typing, the js part of the code is printed into the div in SO's snippet. So here's a JSFiddle.

Community
  • 1
  • 1
akinuri
  • 10,690
  • 10
  • 65
  • 102