javascript - name jquery val()
¿Cómo selecciono nodos de texto con jQuery? (11)
Jauco publicó una buena solución en un comentario, así que la estoy copiando aquí:
$(elem)
.contents()
.filter(function() {
return this.nodeType === 3; //Node.TEXT_NODE
});
Me gustaría obtener todos los nodos de texto descendientes de un elemento, como una colección jQuery. ¿Cuál es la mejor manera de hacer eso?
Obtuve muchos nodos de texto vacíos con la función de filtro aceptada. Si solo está interesado en seleccionar nodos de texto que no contengan espacios en blanco, intente agregar un nodeValue
condicional a su función de filter
, como un simple $.trim(this.nodevalue) !== ''''
:
$(''element'')
.contents()
.filter(function(){
return this.nodeType === 3 && $.trim(this.nodeValue) !== '''';
});
O para evitar situaciones extrañas donde el contenido se ve como espacios en blanco, pero no lo es (por ejemplo, el guión suave ­
caracteres, líneas nuevas, pestañas, etc.), puede intentar usar una expresión regular. Por ejemplo, /S
coincidirá con cualquier carácter que no sea un espacio en blanco:
$(''element'')
.contents()
.filter(function(){
return this.nodeType === 3 && //S/.test(this.nodeValue);
});
Para mí, el antiguo .contents()
parecía funcionar para devolver los nodos de texto, solo hay que tener cuidado con sus selectores para que sepa que serán nodos de texto.
Por ejemplo, esto envolvió todo el contenido de texto de los TDs en mi tabla con etiquetas pre
y no tuvo problemas.
jQuery("#resultTable td").content().wrap("<pre/>")
Por alguna razón, los contents()
no funcionaron para mí, así que si no funcionó para usted, he aquí una solución que hice, creé jQuery.fn.descendants
con la opción de incluir nodos de texto o no
Uso
Obtenga todos los descendientes, incluidos los nodos de texto y los nodos de elementos
jQuery(''body'').descendants(''all'');
Consigue que todos los descendientes devuelvan solo nodos de texto
jQuery(''body'').descendants(true);
Consigue que todos los descendientes devuelvan solo nodos de elementos
jQuery(''body'').descendants();
Coffeescript Original :
jQuery.fn.descendants = ( textNodes ) ->
# if textNodes is ''all'' then textNodes and elementNodes are allowed
# if textNodes if true then only textNodes will be returned
# if textNodes is not provided as an argument then only element nodes
# will be returned
allowedTypes = if textNodes is ''all'' then [1,3] else if textNodes then [3] else [1]
# nodes we find
nodes = []
dig = (node) ->
# loop through children
for child in node.childNodes
# push child to collection if has allowed type
nodes.push(child) if child.nodeType in allowedTypes
# dig through child if has children
dig child if child.childNodes.length
# loop and dig through nodes in the current
# jQuery object
dig node for node in this
# wrap with jQuery
return jQuery(nodes)
Drop In Javascript Version
var __indexOf=[].indexOf||function(e){for(var t=0,n=this.length;t<n;t++){if(t in this&&this[t]===e)return t}return-1}; /* indexOf polyfill ends here*/ jQuery.fn.descendants=function(e){var t,n,r,i,s,o;t=e==="all"?[1,3]:e?[3]:[1];i=[];n=function(e){var r,s,o,u,a,f;u=e.childNodes;f=[];for(s=0,o=u.length;s<o;s++){r=u[s];if(a=r.nodeType,__indexOf.call(t,a)>=0){i.push(r)}if(r.childNodes.length){f.push(n(r))}else{f.push(void 0)}}return f};for(s=0,o=this.length;s<o;s++){r=this[s];n(r)}return jQuery(i)}
Versión de Javascript no minada: http://pastebin.com/cX3jMfuD
Este es un navegador cruzado, un pequeño Array.indexOf
polyfill está incluido en el código.
Si quieres quitar todas las etiquetas, prueba esto
función:
String.prototype.stripTags=function(){
var rtag=/<.*?[^>]>/g;
return this.replace(rtag,'''');
}
uso:
var newText=$(''selector'').html().stripTags();
También se puede hacer así:
var textContents = $(document.getElementById("ElementId").childNodes).filter(function(){
return this.nodeType == 3;
});
El código anterior filtra los TextNodes de los nodos hijos secundarios directos de un elemento determinado.
Tuve el mismo problema y lo resolví con:
Código:
$.fn.nextNode = function(){
var contents = $(this).parent().contents();
return contents.get(contents.index(this)+1);
}
Uso:
$(''#my_id'').nextNode();
Es como next()
pero también devuelve los nodos de texto.
jQuery.contents()
se puede usar con jQuery.filter
para encontrar todos los nodos de texto secundarios. Con un pequeño giro, también puede encontrar los nodos de texto de los nietos. No se requiere recursión:
$(function() {
var $textNodes = $("#test, #test *").contents().filter(function() {
return this.nodeType === Node.TEXT_NODE;
});
/*
* for testing
*/
$textNodes.each(function() {
console.log(this);
});
});
div { margin-left: 1em; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="test">
child text 1<br>
child text 2
<div>
grandchild text 1
<div>grand-grandchild text 1</div>
grandchild text 2
</div>
child text 3<br>
child text 4
</div>
Si puede suponer que todos los hijos son Nodos de elemento o Nodos de texto, entonces esta es una solución.
Para obtener todos los nodos de texto secundarios como una colección jquery:
$(''selector'').clone().children().remove().end().contents();
Para obtener una copia del elemento original con hijos sin texto eliminados:
$(''selector'').clone().children().remove().end();
jQuery no tiene una función conveniente para esto. Debe combinar el contents()
, que proporcionará solo nodos secundarios pero incluirá nodos de texto, con find()
, que proporcionará todos los elementos descendientes pero no los nodos de texto. Esto es lo que he encontrado:
var getTextNodesIn = function(el) {
return $(el).find(":not(iframe)").addBack().contents().filter(function() {
return this.nodeType == 3;
});
};
getTextNodesIn(el);
Nota: Si está utilizando jQuery 1.7 o una versión anterior, el código anterior no funcionará. Para arreglar esto, reemplace addBack()
con andSelf()
. andSelf()
está en desuso a favor de addBack()
desde 1.8 en adelante.
Esto es algo ineficiente en comparación con los métodos DOM puros y tiene que incluir una solución fea para la sobrecarga de jQuery de su función de contents()
(gracias a @rabidsnail en los comentarios por señalarlo), por lo que aquí hay una solución no jQuery usando un simple recursivo función. El parámetro includeWhitespaceNodes
controla si los nodos de texto de espacio en blanco se incluyen o no en la salida (en jQuery se filtran automáticamente).
Actualización: error corregido cuando includeWhitespaceNodes es falsy.
function getTextNodesIn(node, includeWhitespaceNodes) {
var textNodes = [], nonWhitespaceMatcher = //S/;
function getTextNodes(node) {
if (node.nodeType == 3) {
if (includeWhitespaceNodes || nonWhitespaceMatcher.test(node.nodeValue)) {
textNodes.push(node);
}
} else {
for (var i = 0, len = node.childNodes.length; i < len; ++i) {
getTextNodes(node.childNodes[i]);
}
}
}
getTextNodes(node);
return textNodes;
}
getTextNodesIn(el);
$(''body'').find(''*'').contents().filter(function () { return this.nodeType === 3; });