Tenho feito meus estudos em javaScript e hoje gostaria de apresentar o resultado de um código estruturado (não OO) em javaScript: Um HTMLEDitor.
Eu ví um exemplo de como se navegar entre os DOMs e reimplementei os metodos getTextNodesIn e setSelectionRange. Fonte original:http://stackoverflow.com/questions/6240139/highlight-text-range-using-javascript
Dicas:
1) Pra pegar a seleção do range, é necessário 4 coisas:
o nó onde começa a seleção: startContainer
a posição dentro do nó ende começa a seleção: startOffset
o nó onde termina a seleção: endContainer
e a posição dentro do no onde termina a seleção.: endOffset
2) Prorpiedades da Div
contentEditable = true
Isso determina que a DIV pode ser edivavel.
style.whiteSpace = "pre";
Isso determina que a DIV trabalhe com espaços e enteres no formato "\n" ao invez de "<BR>"
3) o metodo mais complicado é setProperty.
Notem que ele é um método recursivo e seu pseudo código é esse:
setProperty = function (div, node, atributo, valor) { verificar se é a primeira chamada do metodo se for, cria um marcador para sabermos se foi encontrado os nos iniciais e finais e pega o range que armazena os dados da seleção se não existir seleção, apesar do cursor estar na div retorna a mesma coisa. OU seja, não vai ser feito nenhuma alteração. Verifica se o nó é um textNode. { se for, é necessario saber que: os nós possiveis serão de 5 tipos: no sem nenhuma seleção (parte inicial e sem seleção de todo o texto) no com seleção parcial, onde o final é o selecionado no com seleção total (todo o nó) no com seleção parcial, onde o inicio é o selecionado no sem nenhuma seleção (parte final e sem seleção de todo o texto) A primeira condição é a mais fácil se o no é igual ao inicial e ao final do range { marca que encontrou o no inicial e final existe a possibilidade desse texto ser dividida em 3 partes: texto inicial, que não tem seleção texto da seleção texto final, sem seleção nenhuma. } se não, se o nó é igual ao inicial do range { marca que encontrou o no inicial existe a possibilidade desse texto ser dividida em 2 partes: texto inicial, que não tem seleção texto da seleção } se não, se o nó é igual ao final do range { marca que encontrou o no final existe a possibilidade desse texto ser dividida em 2 partes: texto da seleção texto final, que não tem seleção } aqui, é o tratamento para os nos que não fazem parte do range. nossos marcadores serão analizados aqui. os que vem antes e depois da seleção não precisam ser alterados já o que está no meio da seleção, irá receber as novas propriedades antes da seleção : não achou inicio da seleção no meio da seleção : achou inicio mas não achou o fim da seleção. recebetratamento. ou depois da seleção: achou inicio e fim da seleção } se não for { realiza a recursividade nos nós filhos } }
Esboço:
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <script type="text/javascript"> Selector = function() { if (window.getSelection) { return window.getSelection(); } else if (document.getSelection) { return document.getSelection(); } } createRange = function (cell) { var rng=null; if(cell.createRange) { rng=cell.createRange(); } else if(cell.getRangeAt) { rng=cell.getRangeAt(0); if(rng.toString()=="") rng=null; } return rng; } getTextNodesIn = function (node) { var textNodes = []; if (node!=undefined && node.nodeType !=undefined && node.nodeType == Node.TEXT_NODE ) { textNodes.push(node); } else { var children = node.childNodes; for (var i = 0, len = children.length; i < len; ++i) { textNodes = textNodes.concat( getTextNodesIn(children[i]) ); } } return textNodes; } getCursorPosition = function (div) { var se = Selector (); var range = se.getRangeAt(0); textNodes = getTextNodesIn(div); countChar=0; for (var i = 0; i<textNodes.length; i++ ) { if ( range.startContainer==textNodes[i] ) { return countChar+range.startOffset } countChar += textNodes[i].textContent.length } return null; } getStartContainer = function (div) { var se = Selector (); var range = se.getRangeAt(0); textNodes = getTextNodesIn(div); return range.startContainer; } getSelectionPosition = function (div) { var se = Selector (); var range = se.getRangeAt(0); textNodes = getTextNodesIn(div); endCharCount = 0; Int=null end=null for (var i = 0; i<textNodes.length; i++ ) { if ( range.startContainer==textNodes[i] ) { Int = endCharCount+range.startOffset } if ( range.endContainer==textNodes[i] ) { end = endCharCount+range.endOffset break; } endCharCount += textNodes[i].textContent.length } return [Int, end]; } setSelectionPosition = function (div, start, end) { range = createRange(document); range.selectNodeContents(div); var foundStart = false; var charCount=0; textNodes = getTextNodesIn(div); var aa=0 var bb=0 for (var i = 0; i<textNodes.length; i++ ) { velhoCount = charCount; charCount += textNodes[i].textContent.length if (!foundStart && velhoCount <= start && start <= charCount ) { aa = textNodes[i].textContent.length - (charCount - start ); range.setStart(textNodes[i], aa ); foundStart = true; } if (foundStart && end <= charCount) { bb = textNodes[i].textContent.length - (charCount - end) ; range.setEnd(textNodes[i], bb ); break; } } var sel = Selector(); sel.removeAllRanges(); sel.addRange(range); div.focus(); } setCursorPosition = function (div, position) { range = createRange(document); range.selectNodeContents(div); var charCount = 0 var endCharCount; textNodes = getTextNodesIn(div); for (var i = 0; i<textNodes.length; i++ ) { textNode = textNodes[i]; endCharCount = charCount + textNode.length; if (position >= charCount && position <= endCharCount ) { range.setStart(textNode, position - charCount); range.setEnd(textNode, position - charCount); range.collapse(false); break; } charCount = endCharCount; } var sel = Selector(); sel.removeAllRanges(); sel.addRange(range); div.focus(); } enterEvent = function (event) { if (event.keyCode == 13) { event.preventDefault(); var position = getCursorPosition (this) var se = Selector (); var range = se.getRangeAt(0); var posA = 0 ; var posB = range.endOffset ; var posC = range.endContainer.textContent.length ; var a = range.endContainer.textContent.substring( posA, posB ) ; var b = range.endContainer.textContent.substring( posB, posC ) ; range.endContainer.parentNode.innerHTML = (a + '\n' + b) ; setCursorPosition (this, position+1) } } setStyle = function (tag, atributo, valor) { tag.style[atributo] = valor; } setProperty = function (div, node, atributo, valor) { if(node==undefined || node==null ) { div.achouEndContainer = false; div.achouStartContainer = false; var se = Selector (); div.range = se.getRangeAt(0); node = div } if( div.range.startContainer == div.range.endContainer && div.range.startOffset==div.range.endOffset ) { return; } if( node.nodeType == Node.TEXT_NODE ) { var conteudo = node.textContent ; var posA = 0 ; var posB = div.range.startOffset ; var posC = div.range.endOffset ; var posD = conteudo.length ; if(node == div.range.startContainer && node == div.range.endContainer ) { div.achouEndContainer = true; div.achouStartContainer = true; var span = document.createElement("span"); var s1 = document.createElement("span"); s1.textContent = conteudo.substring( posA, posB ) span.appendChild(s1) var s2 = document.createElement("span"); setStyle(s2, atributo, valor) s2.textContent = conteudo.substring( posB, posC ) span.appendChild(s2) var s3 = document.createElement("span"); s3.textContent = conteudo.substring( posC, posD) span.appendChild(s3) var rec = node.parentNode; rec.removeChild(node); rec.appendChild( span ) ; } else if( node == div.range.startContainer) { div.achouStartContainer = true; var span = document.createElement("span"); var s1 = document.createElement("span"); s1.textContent = conteudo.substring( posA, posB ) span.appendChild(s1) var s2 = document.createElement("span"); setStyle(s2, atributo, valor) s2.textContent = conteudo.substring( posB, posD ) span.appendChild(s2) var rec = node.parentNode; rec.removeChild(node); rec.appendChild( span ) ; } else if( node == div.range.endContainer) { div.achouEndContainer = true; var span = document.createElement("span"); var s1 = document.createElement("span"); setStyle(s1, atributo, valor); s1.textContent = conteudo.substring( posA, posC ) span.appendChild(s1) var s2 = document.createElement("span"); s2.textContent = conteudo.substring( posC, posD ) span.appendChild(s2) var rec = node.parentNode; rec.removeChild(node); rec.appendChild( span ) ; } else if( !div.achouStartContainer ) { } else if( div.achouStartContainer && !div.achouEndContainer ) { var span = document.createElement("span"); setStyle(span, atributo, valor); var s1 = document.createTextNode(conteudo); span.appendChild(s1); var rec = node.parentNode; rec.removeChild(node); rec.appendChild( span ) ; } else if( div.achouEndContainer ) { } } else { var children = node.childNodes; for (var i = 0; i<children.length; i++) { setProperty( div, children[i], atributo, valor); } } } load = function() { var divA = document.getElementById("div"); divA.style.whiteSpace = "pre"; divA.contentEditable = true; divA.style.position = "absolute"; divA.style.border = "1px solid #000000"; divA.style.position = "absolute"; divA.style.left = "30px"; divA.style.top = "30px"; divA.style.width = "450"; divA.style.height = "150"; divA.style.border = "1px solid #000000"; divA.innerHTML = "<span>abcdefghij 1234567890a\n1234567890</span>" ; divA.onkeydown = enterEvent; } teste1 = function() { var rec = document.getElementById("div") obj = getSelectionPosition(rec) setProperty (rec, null, 'color', 'red'); setSelectionPosition(rec, obj[0], obj[1] ) } teste2 = function() { var rec = document.getElementById("div") obj = getSelectionPosition(rec) setProperty (rec, null, 'color', 'blue'); setSelectionPosition(rec, obj[0], obj[1] ) } teste3 = function() { var rec = document.getElementById("div") obj = getSelectionPosition(rec) setProperty (rec, null, 'fontWeight', 'bold'); setSelectionPosition(rec, obj[0], obj[1] ) } teste4 = function() { var rec = document.getElementById("div") obj = getSelectionPosition(rec) setProperty (rec, null, 'fontWeight', 'normal'); setSelectionPosition(rec, obj[0], obj[1] ) } teste5 = function() { var rec = document.getElementById("div") obj = getSelectionPosition(rec) setProperty (rec, null, 'fontStyle', 'italic'); setSelectionPosition(rec, obj[0], obj[1] ) } teste6 = function() { var rec = document.getElementById("div") obj = getSelectionPosition(rec) setProperty (rec, null, 'fontStyle', 'normal'); setSelectionPosition(rec, obj[0], obj[1] ) } </script> </head> <body onload="load()"> <div id="div">sdf</div> <button type="button" onclick="teste1()">vermelho</button> <button type="button" onclick="teste2()">azul</button> <button type="button" onclick="teste3()">bold</button> <button type="button" onclick="teste4()">unbold</button> <button type="button" onclick="teste5()">italic</button> <button type="button" onclick="teste6()">normal text</button> </body> </html>
Nenhum comentário:
Postar um comentário