texto span obtener nodos nodo hijo eliminar elementos ejemplo div cambiar anterior acceder javascript firefox xhtml firefox-addon selection

span - nodos javascript



Obtener texto seleccionado y nodos seleccionados en una página? (5)

Puede comenzar desde http://javascript.internet.com/page-details/copy-selected-text.html

Al seleccionar un bloque de texto (posiblemente abarcando muchos nodos DOM), ¿es posible extraer el texto y los nodos seleccionados usando Javascript?

Imagina este código HTML:

<h1>Hello World</h1><p>Hi <b>there!</b></p>

Si el usuario inició un evento MouseDown comenzando en "World ..." y luego un mouseUp incluso justo después de "there!", Espero que vuelva:

Text : { selectedText: "WorldHi there!" }, Nodes: [ { node: "h1", offset: 6, length: 5 }, { node: "p", offset: 0, length: 16 }, { node: "p > b", offset: 0, length: 6 } ]

He intentado poner el HTML en un área de texto, pero eso solo me dará el texto seleccionado. No he probado el elemento <canvas> pero puede ser otra opción.

Si no es JavaScript, ¿hay alguna manera de hacerlo posible usando una extensión de Firefox?


Te espera un viaje lleno de baches, pero esto es bastante posible. El principal problema es que IE y W3C exponen interfaces completamente diferentes a las selecciones, por lo que si quieres una funcionalidad de navegador cruzado, básicamente tienes que escribir todo dos veces. Además, algunas funcionalidades básicas faltan en ambas interfaces.

La conexión del desarrollador de Mozilla tiene la historia de las selecciones del W3C . Microsoft tiene su sistema documentado en MSDN . Recomiendo comenzar en la introducción de PPK a los rangos .

Aquí hay algunas funciones básicas que creo que funcionan:

// selection objects will differ between browsers function getSelection () { return ( msie ) ? document.selection : ( window.getSelection || document.getSelection )(); } // range objects will differ between browsers function getRange () { return ( msie ) ? getSelection().createRange() : getSelection().getRangeAt( 0 ) } // abstract getting a parent container from a range function parentContainer ( range ) { return ( msie ) ? range.parentElement() : range.commonAncestorContainer; }


La biblioteca My Rangy obtendrá tu parte del camino al unir las diferentes API en IE <9 y en todos los otros navegadores principales, y al proporcionar una función getNodes() en sus objetos Range:

function getSelectedNodes() { var selectedNodes = []; var sel = rangy.getSelection(); for (var i = 0; i < sel.rangeCount; ++i) { selectedNodes = selectedNodes.concat( sel.getRangeAt(i).getNodes() ); } return selectedNodes; }

Obtener el texto seleccionado es bastante fácil en todos los navegadores. En Rangy es solo

var selectedText = rangy.getSelection().toString();

Sin Rangy:

function getSelectedText() { var sel, text = ""; if (window.getSelection) { text = "" + window.getSelection(); } else if ( (sel = document.selection) && sel.type == "Text") { text = sel.createRange().text; } return text; }

En cuanto a las compensaciones de caracteres, puede hacer algo como esto para cualquier nodo node en la selección. Tenga en cuenta que esto no representa necesariamente el texto visible en el documento porque no tiene en cuenta los espacios colapsados, el texto oculto mediante CSS, el texto colocado fuera del flujo normal de documentos a través de CSS, los saltos de línea implicados en los elementos bloqueados y otras sutilezas .

var sel = rangy.getSelection(); var selRange = sel.getRangeAt(0); var rangePrecedingNode = rangy.createRange(); rangePrecedingNode.setStart(selRange.startContainer, selRange.startOffset); rangePrecedingNode.setEndBefore(node); var startIndex = rangePrecedingNode.toString().length; rangePrecedingNode.setEndAfter(node); var endIndex = rangePrecedingNode.toString().length; alert(startIndex + ", " + endIndex);


Esto devuelve los nodos seleccionados tal como lo entiendo: cuando tengo

<p> ... </p><p> ... </p><p> ... </p><p> ... </p><p> ... </p>... <p> ... </p><p> ... </p><p> ... </p><p> ... </p><p> ... </p>

una gran cantidad de nodos y selecciono solo algunos, entonces solo quiero que estos nodos estén en la lista.

function getSelectedNodes() { // from https://developer.mozilla.org/en-US/docs/Web/API/Selection var selection = window.getSelection(); if (selection.isCollapsed) { return []; }; var node1 = selection.anchorNode; var node2 = selection.focusNode; var selectionAncestor = get_common_ancestor(node1, node2); if (selectionAncestor == null) { return []; } return getNodesBetween(selectionAncestor, node1, node2); } function get_common_ancestor(a, b) { // from http://.com/questions/3960843/how-to-find-the-nearest-common-ancestors-of-two-or-more-nodes $parentsa = $(a).parents(); $parentsb = $(b).parents(); var found = null; $parentsa.each(function() { var thisa = this; $parentsb.each(function() { if (thisa == this) { found = this; return false; } }); if (found) return false; }); return found; } function isDescendant(parent, child) { // from http://.com/questions/2234979/how-to-check-in-javascript-if-one-element-is-a-child-of-another var node = child; while (node != null) { if (node == parent) { return true; } node = node.parentNode; } return false; } function getNodesBetween(rootNode, node1, node2) { var resultNodes = []; var isBetweenNodes = false; for (var i = 0; i < rootNode.childNodes.length; i+= 1) { if (isDescendant(rootNode.childNodes[i], node1) || isDescendant(rootNode.childNodes[i], node2)) { if (resultNodes.length == 0) { isBetweenNodes = true; } else { isBetweenNodes = false; } resultNodes.push(rootNode.childNodes[i]); } else if (resultNodes.length == 0) { } else if (isBetweenNodes) { resultNodes.push(rootNode.childNodes[i]); } else { return resultNodes; } }; if (resultNodes.length == 0) { return [rootNode]; } else if (isDescendant(resultNodes[resultNodes.length - 1], node1) || isDescendant(resultNodes[resultNodes.length - 1], node2)) { return resultNodes; } else { // same child node for both should never happen return [resultNodes[0]]; } }

El código debería estar disponible en: https://github.com/niccokunzmann/spiele-mit-kindern/blob/gh-pages/javascripts/feedback.js

Publiqué esta respuesta aquí porque me hubiera gustado encontrarla aquí.


Hay una manera mucho más corta si solo quieres el rango.

function getRange(){ return (navigator.appName=="Microsoft Internet Explorer") ? document.selection.createRange().parentElement() : (getSelection||document.getSelection)().getRangeAt(0).commonAncestorContainer }