2008-10-16 14 views

Respuesta

36

La respuesta más adelante ahora está presionando cuatro años , por lo que vale la pena señalar que el soporte nativo del navegador para getElementsByClassName() ha obtenido un lote mejor. Pero si debe admitir navegadores más antiguos, entonces ...

Use uno que ya se haya escrito. La mayoría de las grandes bibliotecas JS incluyen uno de una forma u otra, pero si no está utilizando uno de ellos, entonces puedo recomendar una excelente aplicación de Robert Nyman:

http://code.google.com/p/getelementsbyclassname/
http://www.robertnyman.com/2008/05/27/the-ultimate-getelementsbyclassname-anno-2008/

Hay demasiadas maneras de haga que esta rutina (conceptualmente simple) lenta y con errores justifique escribir su propia implementación en este punto.

0

No existe una clase de CSS. CSS tiene conjuntos de reglas y selectores (incluido el selector de clases).

¿Te refieres a una clase de HTML? La forma habitual es recorrer todos los elementos del documento (using document.getElementsByTagName('*') (para mayor eficiencia, use un nombre de etiqueta específico si sabe que la clase solo se aplicará a elementos de un tipo determinado) y pruebe la propiedad className de cada uno (teniendo en cuenta que propiedad contiene una lista separada por espacios de nombres de clase, ni un solo nombre de clase).

una serie de bibliotecas (como jQuery o YUI) tienen funciones a simplemente esto.

¿se refiere a un selector CSS? este se vuelve más complejo, y recurrir a una biblioteca es casi seguro que es lo que hay que hacer aquí. De nuevo, jQuery o YUI son elecciones decentes.

38

1) Obtener todos los elementos del documento (document.getElementsByTagName ('*'))
2) Haz una coincidencia de expresiones regulares en el atributo className del elemento para cada elemento

+1

¿Por qué esto bajó su nombre? Esto está perfectamente bien para una solución de todo-JavaScript. –

+4

De acuerdo. Parece haber un sesgo en el marco JS en SO hasta el punto en que las sugerencias de JavaScript puro son menospreciadas. Recomendar y señalar soluciones en frameworks están bien, pero también lo son las soluciones de JavaScript independientes. – AnthonyWJones

+1

Predicando al coro, seguro. Me encanta usar un marco, pero el hecho es que no todos quieren usar uno o pueden hacerlo. Creo que algunos de los que usan frameworks no saben lo suficiente como para saber cómo hacerlo sin uno, entonces ven estas respuestas y las rechazan por ignorancia u orgullo o algo por el estilo. –

2

Use jquery, no puede ser más conveniente.

$ ("theClass ") o $ (". TheClass"), MakeArray() si desea una matriz JS nativa

6

sólo para hacer un poco de seguimiento, basé mi código en el la aplicación Robert Nyman publicado por Shog9, pero se apartó un poco de su versión exacta, por tres razones:

  1. permitió que seleccione un elemento fundamental y tipo de etiqueta para filtrar los resultados.No necesito esa funcionalidad y, al eliminarla, pude simplificar el código significativamente.
  2. Lo primero que su código hace es ver si la función en cuestión ya existe, y si lo hace, proporciona su propia implementación de todos modos. Eso solo parecía ... extraño. Entiendo que estaba agregando funcionalidad al original, pero de nuevo: no estoy usando esas funciones.
  3. Quería un poco más de azúcar sintáctico, para poder llamarlo como llamaría al document.getElementById() o document.getElementsByTagName().

Tenga en cuenta que todavía confié principalmente en su código. Sus habilidades de javascript obviamente van más allá del mío. Intenté factorizar algunas variables redundantes, pero eso es todo.

Con esto en mente, aquí es lo que terminó con (parece a trabajar en IE6, IE7, Firefox 3 y Chrome ver nota nueva al final):

if (!document.getElementsByClassName) 
    document.getElementsByClassName = function (className) 
{ 
    var classes = className.split(" "); 
    var classesToCheck = ""; 
    var returnElements = []; 
    var match, node, elements; 

    if (document.evaluate) 
    {  
     var xhtmlNamespace = "http://www.w3.org/1999/xhtml"; 
     var namespaceResolver = (document.documentElement.namespaceURI === xhtmlNamespace)? xhtmlNamespace:null; 

     for(var j=0, jl=classes.length; j<jl;j+=1) 
      classesToCheck += "[contains(concat(' ', @class, ' '), ' " + classes[j] + " ')]"; 

     try 
     { 
      elements = document.evaluate(".//*" + classesToCheck, document, namespaceResolver, 0, null); 
     } 
     catch(e) 
     { 
      elements = document.evaluate(".//*" + classesToCheck, document, null, 0, null); 
     } 

     while ((match = elements.iterateNext())) 
      returnElements.push(match); 
    } 
    else 
    { 
     classesToCheck = []; 
     elements = (document.all) ? document.all : document.getElementsByTagName("*"); 

     for (var k=0, kl=classes.length; k<kl; k+=1) 
      classesToCheck.push(new RegExp("(^|\\s)" + classes[k] + "(\\s|$)")); 

     for (var l=0, ll=elements.length; l<ll;l+=1) 
     { 
      node = elements[l]; 
      match = false; 
      for (var m=0, ml=classesToCheck.length; m<ml; m+=1) 
      { 
       match = classesToCheck[m].test(node.className); 
       if (!match) break; 
      } 
      if (match) returnElements.push(node); 
     } 
    } 
    return returnElements; 
} 

Actualización:
Una nueva nota sobre esto. Desde entonces he vuelto a leer las notas sobre la implementación original, y ahora entiendo que mi código podría fallar en el caso de que el navegador existente tenga su propia implementación, porque las implementaciones predeterminadas devuelven una lista de nodos donde esto devuelve una matriz. Esto incluye los navegadores más recientes de Firefox y Safari, y Opera. La mayoría de las veces eso no importará, pero en algunas situaciones podría. Eso explica el ítem n. ° 2 de la lista anterior.

Lo que eso significa es que aunque mi código técnicamente funciona en todas partes, podría dar como resultado un comportamiento sutilmente diferente (leer: difícil de depurar) en diferentes lugares, y eso no es bueno. I debería solucionar esto también devolver una lista de nodos o reemplazar el método proporcionado para devolver una matriz (que es lo que hizo el original). Probablemente el primero sería más simple, pero este último sería mejor.

Sin embargo, está funcionando en este momento en el entorno de intranet local (prácticamente todos los IE), así que por el momento dejaré la solución como un ejercicio para el lector.

2

Tenga en cuenta que al menos FF3 ya tiene una implementación nativa de getElementsByClassName afaik.

Si va a implementar su propia solución, tal vez debería intentar encontrar una solución xpath ya que todos los navegadores modernos tienen soporte nativo para xpath.

+0

Sí, ya estoy en el proceso de actualizar mi publicación, pero tomará un poco, repartir varias ediciones. –

5

Si usa un marco, todos tienen selecciones usando selectores de CSS. De lo contrario.

var getElementsByClassName = function(cls, sc){ 
    //Init 
    var elements, i, results = [], curClass; 

    //Default scope is document 
    sc = sc || document; 

    //Get all children of the scope node 
    elements = sc.getElementsByTagName('*'); 
    for(i=0; i < elements.length; i++){ 
     curClass = elements[i].getAttribute('class'); 
     if(curClass != null){ 
      curClass = curClass.split(" "); 
      for(j=0; j < curClass.length; j++){ 
       if(curClass[j] === cls){ 
        results.push(elements[i]); 
        break; 
       } 
      } 
     } 
    } 

    return results; 
}; 

Acabo de escribirlo en este momento, solo para ti. :) Siéntase libre de usar.

+0

Pregunta anterior, pero está bien. El único problema aquí es que si tiene una clase como 'navarea-top' y' navarea 'y solo está buscando' navarea ', también encontrará todos los elementos de' navarea-top '. –

+0

Es cierto. Para expandirlo, uno puede obtener el atributo de clase y usar regexp para verificar en lugar de indexOf. –

+2

Reparado. :) Gracias por los comentarios –

0

Si desea hacer algo para todo el elemento con la misma identificación en un documento. Aunque simple, pero en algún momento la mente no dé señales verdes

var x = document.getElementById(elementid); 
while(x){ 
document.removechild(x); 
x = document.getElementById(elementid); 
} 
+5

Si tiene varios elementos con la misma identificación, está haciendo algo mal. –

1

@ Shog9, @ user28742, @bdukes - que estoy haciendo algunos desarrollos a medida en SharePoint para una cosa modular (definición de campo personalizado) espero que pueda ser re -utilizado en muchos sitios.

Como no puedo saber con anticipación si un determinado sitio de SharePoint tendrá jQuery o cualquier otra biblioteca disponible --- aún necesito escribir cosas en JavaScript sin formato para poder tener un grado de confianza de que el la funcionalidad que estoy tratando de alcanzar se mantendrá por sí misma.

Gracias a Dmitri por su implementación particular. Lo suficientemente corto para mis propósitos.

En otros esfuerzos recientes, tuve que modificar una tienda de comercio electrónico (de la elección de mi cliente) y algunos de mis intentos de incorporar jQuery en ella entraron en conflicto con las bibliotecas personalizadas que habían manipulado previamente. Pude haber sido persistente y haber encontrado una manera de implementar jQuery en su sistema propietario ... o ... aún más rápido ... simplemente escribí un buen javascript antiguo.

¡¡¡Las Librillas NO SIEMPRE SON LA MEJOR RESPUESTA !!!!!!!!!!!!!!!!

(y amo a jQuery más que a mi abuela)

+0

Upvoted: Técnicamente, esta no es una respuesta a esta pregunta, pero es una buena respuesta para las personas que insisten en incluir su biblioteca favorita en estas preguntas. – AnthonyVO

+0

triste abuela, lo siento por ella – EaterOfCode

Cuestiones relacionadas