sirve selectores queryselectorall queryselector que por para obtener identifica funcion etiqueta elementos elemento ejemplo div clase javascript dom comments

selectores - queryselectorall javascript



¿Es posible obtener referencia al elemento/bloque de comentario por JavaScript? (6)

Esto suena un poco loco, pero me pregunto si es posible obtener una referencia al elemento de comentario para poder reemplazarlo dinámicamente por otro contenido con JavaScript.

<html> <head> </head> <body> <div id="header"></div> <div id="content"></div> <!-- sidebar place holder: some id--> </body> </html>

En la página anterior, ¿puedo obtener una referencia al bloque de comentarios y reemplazarlo con algún contenido en el almacenamiento local?

Sé que puedo tener un titular de div lugar. Solo me pregunto si se aplica al bloque de comentarios. Gracias.


Aprovechando la respuesta de Hyperslug, puedes hacerlo más rápido usando una pila en lugar de recursión de funciones. Como se muestra en este jsPerf , la función de recursión es 42% más lenta en mi Chrome 36 en Windows y 71% con IE11 en modo de compatibilidad con IE8. Parece que se ejecuta aproximadamente un 20% más lento en IE11 en modo perimetral, pero más rápido en todos los demás casos probados.

function getComments(context) { var foundComments = []; var elementPath = [context]; while (elementPath.length > 0) { var el = elementPath.pop(); for (var i = 0; i < el.childNodes.length; i++) { var node = el.childNodes[i]; if (node.nodeType === Node.COMMENT_NODE) { foundComments.push(node); } else { elementPath.push(node); } } } return foundComments; }

O como se hace en TypeScript:

public static getComments(context: any): Comment[] { var foundComments = []; var elementPath = [context]; while (elementPath.length > 0) { var el = elementPath.pop(); for (var i = 0; i < el.childNodes.length; i++) { var node = el.childNodes[i]; if (node.nodeType === Node.COMMENT_NODE) { foundComments.push(node); } else { elementPath.push(node); } } } return foundComments; }


Esta es una pregunta antigua, pero aquí están mis dos centavos para los "marcadores de posición" de DOM. Un elemento de comentario es perfecto para el trabajo (html válido, no visible y no induce a error de ninguna manera). Sin embargo, atravesar el dom en busca de comentarios no es necesario si crea su código al revés.

Yo sugeriría usar el siguiente método:

  1. Marque los lugares que desea "controlar" con el marcado de su elección (por ejemplo, un elemento div con una clase específica)

    <div class="placeholder"></div> <div class="placeholder"></div> <div class="placeholder"></div> <div class="placeholder"></div> <div class="placeholder"></div>

  2. Encuentre los marcadores de posición de la manera habitual (querySelector / classSelector, etc.)

var placeholders = document.querySelectorAll(''placeholder'');

  1. Reemplácelos con comentarios y guarde la referencia de esos comentarios:

var refArray = [];

[...placeholders].forEach(function(placeholder){ var comment = document.createComment(''this is a placeholder''); refArray.push( placeholder.parentNode.replaceChild(comment, placeholder) ); });

En esta etapa, su marca renderizada debería verse así:

<!-- this is a placeholder --> <!-- this is a placeholder --> <!-- this is a placeholder --> <!-- this is a placeholder --> <!-- this is a placeholder -->

  1. Ahora puedes acceder a cada uno de esos comentarios directamente con tu refArray construido y hacer lo que quieras hacer ... por ejemplo:

reemplazar el segundo comentario con un titular

let headline = document.createElement(''h1''); headline.innerText = "I am a headline!"; refArray[1].parentNode.replaceChild(headline,refArray[1]);


Hay una API para el recorrido de nodos de documentos: Document#createNodeIterator() :

var nodeIterator = document.createNodeIterator( document.body, NodeFilter.SHOW_COMMENT, { acceptNode: function(node) { return NodeFilter.FILTER_ACCEPT; } } ); // Replace all comment nodes with a div while(nodeIterator.nextNode()){ var commentNode = nodeIterator.referenceNode; var id = (commentNode.textContent.split(":")[1] || "").trim(); var div = document.createElement("div"); div.id = id; commentNode.parentNode.replaceChild(div, commentNode); }

#header, #content, #some_id{ margin: 1em 0; padding: 0.2em; border: 2px grey solid; } #header::after, #content::after, #some_id::after{ content: "DIV with ID=" attr(id); }

<html> <head> </head> <body> <div id="header"></div> <div id="content"></div> <!-- sidebar place holder: some_id --> </body> </html>

Edición: use un NodeIterator lugar de un TreeWalker


Parece que hay preocupaciones legítimas (de rendimiento) sobre el uso de comentarios como marcadores de posición. Por un lado, no hay un selector de CSS que pueda coincidir con los nodos de comentarios, por lo que no podrá consultarlos con, por ejemplo, document.querySelectorAll() , lo que hace que sea Complejos y lentos para ubicar elementos de comentario.

Mi pregunta entonces fue: ¿hay otro elemento que pueda colocar en línea, que no tenga efectos secundarios visibles? He visto a algunas personas que usan la etiqueta <meta> , pero miré eso, y usar eso en <body> no es un marcado válido.

Así que me decidí por la etiqueta <script> .

Use un atributo de type personalizado, para que no se ejecute realmente como un script, y use los atributos de data- para los datos de inicialización requeridos por el script que va a inicializar sus marcadores de posición.

Por ejemplo:

<script type="placeholder/foo" data-stuff="whatevs"></script>

Luego simplemente consulta esas etiquetas, por ejemplo:

document.querySelectorAll(''script[type="placeholder/foo"]'')

Luego reemplácelas según sea necesario; aquí hay un ejemplo de DOM sencillo .

Tenga en cuenta que el placeholder de placeholder en este ejemplo no es una cosa "real" definida; debe reemplazarlo con, por ejemplo vendor-name para asegurarse de que su type no coincida con nada "real".


Si usa jQuery, puede hacer lo siguiente para obtener todos los nodos de comentarios

comments = $(''*'').contents().filter(function(){ return this.nodeType===8; })

Si solo quieres los nodos de comentarios del cuerpo, usa

comments = $(''body'').find(''*'').contents().filter(function(){ return this.nodeType===8; })

Si desea que las cadenas de comentarios formen una matriz, puede usar map :

comment_strings = comments.map(function(){return this.nodeValue;})


var findComments = function(el) { var arr = []; for(var i = 0; i < el.childNodes.length; i++) { var node = el.childNodes[i]; if(node.nodeType === 8) { arr.push(node); } else { arr.push.apply(arr, findComments(node)); } } return arr; }; var commentNodes = findComments(document); // whatever you were going to do with the comment... console.log(commentNodes[0].nodeValue);