Cómo insertar elementos de una lista de nodos en una matriz basada en un selector CSS en Vanilla JS

Espero que esto sea algún tipo de desafío de programación, o tarea asignada. .querySelector() y .querySelectorAll() definitivamente harán esto mejor que hacer un equivalente desde cero.

Antes de hablar de código, hablemos de lógica. Estos son los pasos que puede tomar:

  1. Comenzando en document.body , childNodes los childNodes
  2. Si childNode es un elemento (porque no todos lo son), agréguelo a una matriz
  3. si el childNode es un elemento y tiene childNodes propios, childNodes y childNodes a una matriz
  4. Filtrar:
    • Filtre la matriz a esos nodos que coincidan con su selector CSS
    • Solo agregue el nodo si el selector CSS coincide

Cómo abordar el paso 4 depende de usted. Prefiero tareas más pequeñas y dedicadas, así que tomaría la primera opción.

Recorriendo los nodos secundarios

Arrancaría esto creando una función llamada getNodes

función getNodes (elemento) {
var tempArray = [];

for (let child of element.childNodes) {
if (child.nodeType === 1) {
tempArray.push (niño);
}
}
return tempArray;
}

  1. Creamos una matriz vacía.
  2. Recorremos la matriz usando ES6’s lovely for … of sintaxis
  3. Verificamos y vemos si el nodo es un elemento [1]
  4. Si es un elemento, lo agregamos a la matriz

Sin embargo, solo una trampa: esto solo va un nivel de profundidad.

Añade algo de recursión

Siendo totalmente honesto, la recursión es difícil para mí. Es una herramienta de programación increíblemente poderosa, pero a veces todavía asusta mi cerebro. La recursión, simplemente, está usando una función para llamarse a sí misma. Y lo que debemos hacer es que getNodes() llame a sí mismo . Y apuesto a que aquí es donde necesitas ayuda. ¡Así que vamos a ser recursivos!

función getNodes (elemento) {
var tempArray = [];

for (let child of element.childNodes) {
if (child.nodeType === 1) {
tempArray.push (niño);

tempArray.push (getNodes (child)); // recursividad FTW!
}
}
return tempArray;
}

Esto es como helado para mi cerebro; duele pero también se siente tan bien.

Estamos recorriendo estos childNodes , agregándolos a la matriz, y luego, cuando un childNode tiene hijos, ¡también los recorremos! todo el camino hacia abajo.

Sin embargo, la única trampa es que esto producirá una matriz multidimensional (una matriz dentro de las matrices). Esos no son fáciles de buscar y filtrar.

Acoplar la matriz

Resulta que la función reduce() , que está unida al objeto de matriz, puede usarse para aplanar matrices. ¿Pero cómo? ¡Porque también usa la recursividad! Agreguemos una constante cuyo trabajo es aplanar nuestra matriz:

función getNodes (elemento) {
var tempArray = [];
const flatten = arr => arr.reduce ((a, b) => a.concat (Array.isArray (b)? flatten (b): b), []);

for (let child of element.childNodes) {
if (child.nodeType === 1) {
tempArray.push (niño);

tempArray.push (getNodes (child)); // recursividad FTW!
}
}
return flatten (tempArray);
}

Nuestro aplanador está utilizando algunas características sofisticadas de Schmancy ES6:

  • Está utilizando una función de flecha () => {} o argument => return value .
  • reducir es bastante deportivo porque es un acumulador, puede usarlo para combinar un valor actual con un valor siguiente o anterior en una matriz
    • a es la acumulación
    • b es el valor actual
    • A es la concatenación de A y B, pero primero aplanará b
    • [] es solo un valor vacío para comenzar la reducción completa

Esto concluye la primera mitad de nuestro desafío. Cuando ejecutamos getNodes(document.body) , debe obtener con éxito una matriz plana de todos los nodos de elementos en su documento. (pero, por supuesto, puede ejecutar esto en cualquier elemento del DOM).

Filtra la lista

Puede agregar lógica en la función getNodes() para buscar un selector, pero me gusta la idea de mantener las cosas simples y pequeñas. Así que haré una función cuyo trabajo es tomar un nombre de clase y una matriz, y filtrarlos:

función queryNodes (selector, nodeArray) {
return nodeArray.filter ((nodo) => {
return node.classList.contains (selector);
});
};

Estoy usando el método filter () que vive en el objeto de matriz [2].

  • El método filter () acepta una devolución de llamada (y la mía es una función de flecha).
  • el método de filtro quiere un valor de retorno que sea booleano (porque eso es lo que le indica si agregarlo a mi nueva lista)
  • La función en sí misma devuelve esta lista filtrada

Tenga en cuenta que estoy usando node.classList.contains() . [3] Estoy trabajando suponiendo que estoy filtrando mi matriz por nombre de clase. Tendría que agregar lógica adicional si quisiera consultar por ID o atributo.

La aplicación final

Ahora que he creado estas dos funciones, debería poder ejecutar esto en el navegador:

var allTheElements = getNodes (document.body);
var justTheChosenOnes = queryNodes (‘elegido’, allTheElements);

Comentarios finales

Use querySelector() y querySelectorAll() . No reinventes la rueda.

Notas al pie

[1] Node.nodeType

[2] Array.prototype.filter ()

[3] Element.classList

More Interesting

¿Existe un enlace de datos de tres vías en los marcos de JavaScript front-end?

¿Está bien usar RRHH en HTML?

¿Hay alguna herramienta que presente la dependencia del sistema?

Cómo agregar administración de sesión en aplicaciones web usando la sesión HTTP de Java y Apache Tomcat

¿Puedo codificar Bootstrap en Eclipse? ¿Si es así, entonces cómo? ¿Qué es un buen IDE para Bootstrap que no sea Eclipse?

Estoy usando una empresa de desarrollo para ayudar a construir una startup. ¡Nunca más! Quiero un cofundador técnico. Tengo un programador a tiempo parcial (no apto para ser cofundador) y un presupuesto de $ 500 / mes + capital. ¿Es esto suficiente para reclutar un buen cofundador técnico?

Cómo aprender node.js en menos tiempo

¿Qué debo aprender a continuación en PHP después del formulario HTML y el manejo de consultas SQL?

¿Por qué es tan inútil el sistema de clasificación de Netflix? (Después de desplazarse por 100 títulos aleatorios, todos excepto uno estaban en el rango de 2.9 y 4.)

Usando WordPress, ¿cuál fue su primera razón para aplicar el código usted mismo?

¿Quién es la mejor persona para ayudar a crear un sitio web en línea como Airbnb?

¿Cuáles son los problemas asociados con los sitios web, servidores y bases de datos a medida que crecen significativamente? ¿Hay buenos libros, artículos o conferencias en línea que discutan este tema en profundidad?

¿Cuáles son los usos de Angular2, dónde debemos usarlo y cómo lo aplicamos?

¿Cuáles son las habilidades más importantes para Nodejs?

Cómo acceder al editor CSS en mi sitio web gratuito de WordPress