span - obtener contenido de un div javascript
Envolviendo un nodo de texto seleccionado con span (5)
Quiero envolver un texto seleccionado en un contenedor div con span, ¿es posible?
Un usuario seleccionará un texto y hará clic en un botón, en el evento de clic de botón Quiero envolver ese texto seleccionado con un elemento de tramo. Puedo obtener el texto seleccionado usando window.getSelection()
pero ¿cómo saber su posición exacta en la estructura DOM?
Encontrar el siguiente código será útil para ajustar la etiqueta span para todo tipo de etiquetas. Por favor revise el código y use la lógica para su implementación.
getSelectedText(this);
addAnnotationElement(this, this.parent);
function getSelectedText(this) {
this.range = window.getSelection().getRangeAt(0);
this.parent = this.range.commonAncestorContainer;
this.frag = this.range.cloneContents();
this.clRange = this.range.cloneRange();
this.start = this.range.startContainer;
this.end = this.range.endContainer;
}
function addAnnotationElement(this, elem) {
var text, textParent, origText, prevText, nextText, childCount,
annotationTextRange,
span = this.htmlDoc.createElement(''span'');
if (elem.nodeType === 3) {
span.setAttribute(''class'', this.annotationClass);
span.dataset.name = this.annotationName;
span.dataset.comment = '''';
span.dataset.page = ''1'';
origText = elem.textContent;
annotationTextRange = validateTextRange(this, elem);
if (annotationTextRange == ''textBeforeRangeButIntersect'') {
text = origText.substring(0, this.range.endOffset);
nextText = origText.substring(this.range.endOffset);
} else if (annotationTextRange == ''textAfterRangeButIntersect'') {
prevText = origText.substring(0, this.range.startOffset);
text = origText.substring(this.range.startOffset);
} else if (annotationTextRange == ''textExactlyInRange'') {
text = origText
} else if (annotationTextRange == ''textWithinRange'') {
prevText = origText.substring(0, this.range.startOffset);
text = origText.substring(this.range.startOffset,this.range.endOffset);
nextText = origText.substring(this.range.endOffset);
} else if (annotationTextRange == ''textNotInRange'') {
return;
}
span.textContent = text;
textParent = elem.parentElement;
textParent.replaceChild(span, elem);
if (prevText) {
var prevDOM = this.htmlDoc.createTextNode(prevText);
textParent.insertBefore(prevDOM, span);
}
if (nextText) {
var nextDOM = this.htmlDoc.createTextNode(nextText);
textParent.insertBefore(nextDOM, span.nextSibling);
}
return;
}
childCount = elem.childNodes.length;
for (var i = 0; i < childCount; i++) {
var elemChildNode = elem.childNodes[i];
if( Helper.isUndefined(elemChildNode.tagName) ||
! ( elemChildNode.tagName.toLowerCase() === ''span'' &&
elemChildNode.classList.contains(this.annotationClass) ) ) {
addAnnotationElement(this, elem.childNodes[i]);
}
childCount = elem.childNodes.length;
}
}
function validateTextRange(this, elem) {
var textRange = document.createRange();
textRange.selectNodeContents (elem);
if (this.range.compareBoundaryPoints (Range.START_TO_END, textRange) <= 0) {
return ''textNotInRange'';
}
else {
if (this.range.compareBoundaryPoints (Range.END_TO_START, textRange) >= 0) {
return ''textNotInRange'';
}
else {
var startPoints = this.range.compareBoundaryPoints (Range.START_TO_START, textRange),
endPoints = this.range.compareBoundaryPoints (Range.END_TO_END, textRange);
if (startPoints < 0) {
if (endPoints < 0) {
return ''textBeforeRangeButIntersect'';
}
else {
return "textExactlyInRange";
}
}
else {
if (endPoints > 0) {
return ''textAfterRangeButIntersect'';
}
else {
if (startPoints === 0 && endPoints === 0) {
return "textExactlyInRange";
}
else {
return ''textWithinRange'';
}
}
}
}
}
}
Si la selección está completamente contenida dentro de un solo nodo de texto, puede hacerlo utilizando el método surroundContents()
del rango que obtiene de la selección. Sin embargo, esto es muy frágil: no funciona si la selección no puede rodearse lógicamente en un solo elemento (generalmente, si el rango cruza los límites del nodo, aunque esta no es la definición precisa ). Para hacer esto en el caso general, necesita un enfoque más complicado.
Además, DOM Range
y window.getSelection()
no son compatibles con IE <9. Necesitará otro enfoque para esos navegadores. Puede usar una biblioteca como mi propio Rangy para normalizar el comportamiento del navegador y puede encontrar el módulo aplicador de clase útil para esta pregunta.
Simple surroundContents()
ejemplo jsFiddle: http://jsfiddle.net/VRcvn/
Código:
function surroundSelection(element) {
if (window.getSelection) {
var sel = window.getSelection();
if (sel.rangeCount) {
var range = sel.getRangeAt(0).cloneRange();
range.surroundContents(element);
sel.removeAllRanges();
sel.addRange(range);
}
}
}
SurroundContents solo funciona si su selección contiene solo texto y no HTML. Aquí hay una solución más flexible y entre navegadores. Esto insertará un lapso como este:
<span id="new_selection_span"><!--MARK--></span>
El lapso se inserta antes de la selección, delante de la etiqueta HTML de apertura más cercana.
var span = document.createElement("span");
span.id = "new_selection_span";
span.innerHTML = ''<!--MARK-->'';
if (window.getSelection) { //compliant browsers
//obtain the selection
sel = window.getSelection();
if (sel.rangeCount) {
//clone the Range object
var range = sel.getRangeAt(0).cloneRange();
//get the node at the start of the range
var node = range.startContainer;
//find the first parent that is a real HTML tag and not a text node
while (node.nodeType != 1) node = node.parentNode;
//place the marker before the node
node.parentNode.insertBefore(span, node);
//restore the selection
sel.removeAllRanges();
sel.addRange(range);
}
} else { //IE8 and lower
sel = document.selection.createRange();
//place the marker before the node
var node = sel.parentElement();
node.parentNode.insertBefore(span, node);
//restore the selection
sel.select();
}
es posible. Necesita usar el rango API y el método Range.surroundContents (). Coloca el nodo en el que se envuelve el contenido al comienzo del rango especificado. ver surroundContents()
function wrapSelectedText() {
var selection= window.getSelection().getRangeAt(0);
var selectedText = selection.extractContents();
var span= document.createElement("span");
span.style.backgroundColor = "yellow";
span.appendChild(selectedText);
selection.insertNode(span);
}
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam rhoncus gravida magna, quis interdum magna mattis quis. Fusce tempor sagittis varius. Nunc at augue at erat suscipit bibendum id nec enim. Sed eu odio quis turpis hendrerit sagittis id sit amet justo. Cras ac urna purus, non rutrum nunc. Aenean nec vulputate ante. Morbi scelerisque sagittis hendrerit. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nulla tristique ligula fermentum tortor semper at consectetur erat aliquam. Sed gravida consectetur sollicitudin.
<input type="button" onclick="wrapSelectedText();" value="Highlight" />