Obtenga el número n-child de un elemento en JavaScript puro

Estoy haciendo una función para mi sitio donde establezco un atributo de datos que contiene el n-ésimo número de ese elemento.

Mi marcado de HTML:

  
some text, nth-child is one
some text, nth-child is two
some text, nth-child is three
some text, nth-child is four
some text, nth-child is five

Mi JavaScript hasta el momento:

 var selector = document.getElementsByClassName('hardware'); for(var i = 0; i <= selector.length; i++) { var index = selector[i] //get the nth-child number here selector[i].dataset.number = index; } 

¿Cómo puedo obtener el n-ésimo número de un elemento con JavaScript puro (no jQuery), esto es posible incluso en JavaScript?

Cuando dices “número”, ¿te refieres a 1, 2, etc. o “uno”, “dos”, etc.?

Si 1, 2, etc., entonces el número es simplemente i + 1 …

Si es “uno”, “dos”, etc., necesita obtener el texto dentro del elemento, entonces probablemente use un Regexp para analizarlo y obtener el valor que desea.

Mira esta respuesta anterior AQUÍ .

Usa

 var i = 0; while( (child = child.previousSibling) != null ) i++; //at the end i will contain the index. 

Voy a responder las preguntas con las siguientes suposiciones:

  • Sus elementos clasificados de hardware son todos hermanos
  • Usted está interesado en enésimo niño no enésimo niño + 1
  • Se pueden mezclar con otros elementos:
  
some text, nth-child is zero
some text, nth-child is two

(Estoy haciendo estas suposiciones, porque este es el problema al que me estoy enfrentando, pensé que podría ser útil)

Entonces la principal diferencia es que en lugar de consultar los elementos que pertenecen a una clase dada, voy a obtener los hijos (directos) del body y filtrarlos.

 Array.from(document.body.children) .map((element, index) => ({element, index})) .filter(({element}) => element.classList.contains('hardware')) 

La matriz resultante se verá así:

 [ {element: section.hardware, index: 0} {element: section.hardware, index: 2} ] 

Simplemente incrementar el índice linealmente solo funcionará si todos los elementos que coinciden con ese nombre de clase son los únicos elementos :nth-child() del mismo elemento primario, sin otros elementos que puedan interferir con :nth-child() , como se muestra exactamente en el marcado dado. Consulte esta respuesta para obtener una explicación sobre cómo otros elementos pueden interferir. También revise la especificación de selectores en :nth-child() .

Una forma de lograr esto que es más infalible es recorrer los nodos secundarios del nodo primario de cada elemento, incrementando un contador para cada nodo secundario que sea un nodo de elemento (ya que :nth-child() solo cuenta los nodos de elemento):

 var selector = document.getElementsByClassName('hardware'); for (var i = 0; i < selector.length; i++) { var element = selector[i]; var child = element.parentNode.firstChild; var index = 0; while (true) { if (child.nodeType === Node.ELEMENT_NODE) { index++; } if (child === element || !child.nextSibling) { break; } child = child.nextSibling; } element.dataset.number = index; } 

Demostración de JSFiddle

Tenga en cuenta que esto aplicará el índice correcto independientemente de dónde esté el elemento dado en el DOM :

  • Si un elemento particular de section.hardware es el primer y único elemento secundario de una section diferente, se le asignará el índice correcto de 1.

  • Si un elemento .hardware es el segundo hijo de su principal, incluso si es el único con esa clase (es decir, sigue a algún otro elemento sin la clase), se le asignará el índice correcto de 2.

Puede dividir el texto en los espacios al obtener la última palabra de cada matriz dividida:

 var hards = document.getElementsByClassName('hardware'); for (var i=0; i < hards.length; i++) { var hardText = hards[i].innerText || hard[i].textContent; var hardList = hardText.split(' '); var hardLast = hardList[hardList.length - 1]; alert(hardLast); } 

Estoy usando || aquí porque Firefox no es compatible con innerText , mientras que IE no es compatible con textContent .

Si los elementos solo contienen texto, se puede usar innerHTML lugar de innerText/textContent .