This functionality is simple, you can use .split().join()
or regex to replace content with .replace()
.
In its simplest version it would be:
var editavel = document.querySelector('div[contenteditable="true"]');
var novoConteudo = '<span class="format">palavra-chave</span>';
editavel.innerHTML = editavel.innerHTML.split('palavra-chave').join(novoConteudo);
jsFiddle: http://jsfiddle.net/u68b6tz8/
If you want to make that substitution on the fly, with each new letter inserted, then the thing gets more interesting. You can add a Event Listener when a key is released (keyup) and check the content:
var editavel = document.querySelector('div[contenteditable="true"]');
editavel.addEventListener('keyup', function (e) {
var novoConteudo = '<span class="format">palavra-chave</span>';
this.innerHTML = this.innerHTML.split('palavra-chave').join(novoConteudo);
});
The problem now that remains to be solved is the careto/cursor, which moves out of position when HTML is replaced. On Soen I found two questions about this where Tim Down answers about how to read and how to set the cursor/careto. These answers do not solve the problem directly but led me to this solution:
Three steps!
#1 - replace all words when the code first runs. This way we know that when we type it will only appear one new at a time.
#2 - Use replace, with function! This way we can insert a span and to solve the problem of careto we give that span a secret ID.
#3 - So we can select this element and point the gap to the start of the next sibling.
Applied to this case the code would look like this:
var palavraChave = 'palavra-chave';
// fazer substituições antes de começar a escrever
var editavel = document.querySelector('div[contenteditable="true"]');
var novoConteudo = '<span class="format">palavra-chave</span>';
editavel.innerHTML = editavel.innerHTML.split('palavra-chave').join(novoConteudo);
var editavel = document.querySelector('div[contenteditable="true"]');
editavel.addEventListener('keyup', function (e) {
var regExp = new RegExp('(' + palavraChave + ')(?!<)', 'g');
// se não houver nada para substituir, sair
if (!this.innerHTML.match(regExp)) return;
var novoConteudo = this.innerHTML.replace(regExp, function () {
// trocar o match pelo novo conteudo
return '<span id="span_secreto">' + palavraChave + '</span>';
});
this.innerHTML = novoConteudo;
// ir buscar o elemento secreto criado para lhe retirar a ID e colocar a classe
var span = document.getElementById('span_secreto');
span.removeAttribute('id');
span.classList.add('format');
colocarCareto(span);
});
function colocarCareto(node) {
// defenir que elemento o careto deve seguir. Criar um novo placebo se o span fôr o ultimo
var target = node.nextSibling ? node.nextSibling : (function (el) {
var novoTextNode = document.createTextNode(' ');
el.appendChild(novoTextNode);
return novoTextNode
})(node);
// colocar o careto no inicio do proximo elemento
var range = document.createRange();
range.setStart(target, 1);
range.setEnd(target, 1);
var selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
}
.format {
color: red;
font-style: italic;
}
span.format {
color: #aad;
}
<div contenteditable="true">
texto texto texto palavra-chave. texto palavra-chav, texto texto.
</div>
The code still needs more tuning, and maybe later you can shorten it. But the main idea and the functionality is.
@Laerte why deleted his reply?
– ropbla9
Why you asked for the solution in pure Javascript.
– Laerte
@Laerte ah yes.
– ropbla9
It’s the "same" (see I quote) question you posted about Javascript’s "reserved words"?
– Guilherme Nascimento
@Guilhermenascimento is the same algorithm
– ropbla9
In matters of security I personally I disagree with this method of limiting the user, as there are more effective and less "limiting" ways to make safe an online text editor. However, as this is currently out of focus current, Please test my answer.
– Guilherme Nascimento
You only have one div or it could be multiple Ivs?
– Sergio
@Sergio My intention is to repeat this same field several times. It’s a Javascript editor actually, so it’s just a simple text editable div.
– ropbla9