La siguiente solución no funciona para IE, necesitará aplicar objetos TextRange, etc. para eso. Este utiliza selecciones para realizar esto, no debe romper el código HTML en los casos normales, por ejemplo:
<div>abcd<span>efg</span>hij</div>
Con highlight(3,6);
salidas:
<div>abc<em>d<span>ef</span></em><span>g</span>hij</div>
tomar nota de cómo se envuelve la primera personaje fuera del lapso en em
, y luego el resto dentro del span
en uno nuevo. Donde como si acaba de abrir al carácter 3 y terminará a las de carácter 6, daría marcas inválidas como:
<div>abc<em>d<span>ef</em>g</span>hij</div>
El código:
var r = document.createRange();
var s = window.getSelection()
r.selectNode($('div')[0]);
s.removeAllRanges();
s.addRange(r);
// not quite sure why firefox has problems with this
if ($.browser.webkit) {
s.modify("move", "backward", "documentboundary");
}
function highlight(start,end){
for(var st=0;st<start;st++){
s.modify("move", "forward", "character");
}
for(var st=0;st<(end-start);st++){
s.modify("extend", "forward", "character");
}
}
highlight(2,6);
var ra = s.getRangeAt(0);
var newNode = document.createElement("em");
newNode.appendChild(ra.extractContents());
ra.insertNode(newNode);
Ejemplo: http://jsfiddle.net/niklasvh/4NDb9/
editar Parece que al menos mi FF4 tuvo algunos problemas con
s.modify("move", "backward", "documentboundary");
pero al mismo tiempo, parece que funciona sin él, así que sólo lo cambió a
if ($.browser.webkit) {
s.modify("move", "backward", "documentboundary");
}
edición como Tim señalado, modificar solo están disponibles en FF4 en adelante , así que tomé un enfoque diferente para obtener la selección, que no necesita el método de modificación, con la esperanza de que sea un poco más compatible con el navegador (IE aún necesita su propia solución).
El código:
var r = document.createRange();
var s = window.getSelection()
var pos = 0;
function dig(el){
$(el).contents().each(function(i,e){
if (e.nodeType==1){
// not a textnode
dig(e);
}else{
if (pos<start){
if (pos+e.length>=start){
range.setStart(e, start-pos);
}
}
if (pos<end){
if (pos+e.length>=end){
range.setEnd(e, end-pos);
}
}
pos = pos+e.length;
}
});
}
var start,end, range;
function highlight(element,st,en){
range = document.createRange();
start = st;
end = en;
dig(element);
s.addRange(range);
}
highlight($('div'),3,6);
var ra = s.getRangeAt(0);
var newNode = document.createElement("em");
newNode.appendChild(ra.extractContents());
ra.insertNode(newNode);
ejemplo: http://jsfiddle.net/niklasvh/4NDb9/
¿Puedes quitar las etiquetas en una cadena temporal y luego subsergir desde esa cadena? – mc10
No puede ignorar las etiquetas, de lo contrario terminará con html no válido: 'ab cd ef f'. Usted tendría que hacer algo como 'ab cd ef g' –
serg
Por supuesto que no puedo ignorar las etiquetas, pero sería bueno si el navegador podría resolver esos problemas para mí de alguna manera. – Vincent