JQuery para buscar identificadores duplicados en un DOM

106

Estoy escribiendo aplicaciones con ASP.NET MVC. A diferencia de ASP.NET tradicional, usted es mucho más responsable de crear todos los identificadores en su página generada. ASP.NET le daría identificadores desagradables pero únicos.

Me gustaría agregar un pequeño script jQuery rápido para verificar si mi documento tiene identificadores duplicados. Pueden ser identificadores de DIVS, imágenes, casillas de verificación, botones, etc.

<div id="pnlMain"> My main panel </div>
<div id="pnlMain"> Oops we accidentally used the same ID </div> 

Estoy buscando un conjunto y una utilidad de tipo olvido que me avise cuando haga algo descuidado.

Sí, usaría esto solo durante las pruebas, y las alternativas (como los complementos de firebug) también son bienvenidas.

Simon_Weaver
fuente

Respuestas:

214

Lo siguiente registrará una advertencia en la consola:

// Warning Duplicate IDs
$('[id]').each(function(){
  var ids = $('[id="'+this.id+'"]');
  if(ids.length>1 && ids[0]==this)
    console.warn('Multiple IDs #'+this.id);
});
sunsean
fuente
¡Perfecto! ¡Gracias! Ya descubrí tres lugares donde tengo identificaciones duplicadas. Me frustra un poco que la solución de la mayoría de las personas a este problema sea usar 'firebug' o 'html validator'. ¡eso no es lo suficientemente bueno! quiero capturar los duplicados inesperados en situaciones extrañas.
Simon_Weaver
4
jeje y yo cambiamos de consola. Advertir para alertar (...) así que TENGO que arreglarlos :)
Simon_Weaver
he encontrado esto extremadamente útil y valioso. Creo que debería ser un estándar en los marcos, especialmente durante la depuración
Simon_Weaver
6
La cantidad de recorridos de DOM necesarios para que esto funcione es bastante sorprendente
Josh Stodola
8
Muy buena solución, pero necesita comillas adicionales, por var ids = $('[id=\''+this.id+'\']');lo que funciona con puntos y otras cosas raras en las identificaciones.
zidarsk8
33

Esta versión es algo más rápida y puede copiarla en un botón de marcador para convertirla en marcador.

javascript:(function () {
  var ids = {};
  var found = false;
  $('[id]').each(function() {
    if (this.id && ids[this.id]) {
      found = true;
      console.warn('Duplicate ID #'+this.id);
    }
    ids[this.id] = 1;
  });
  if (!found) console.log('No duplicate IDs found');
})();
Sjoerd
fuente
3
Este algoritmo es mejor, requiere solo un recorrido de dom en lugar de uno por elemento emparejado. Debería ser la respuesta aceptada.
m_x
1
Da un falso positivo para los formularios que tienen una entrada con name = id. javascript:(function () { var ids = {}; var found = false; $('[id]').each(function() { var id = this.getAttribute('id'); if (id && ids[id]) { found = true; console.warn('Duplicate ID #'+id); } ids[id] = 1; }); if (!found) console.log('No duplicate IDs found'); })(); seria mejor.
alpo
14

Tengo una página grande, por lo que la secuencia de comandos se ejecuta demasiado lento para terminar (varios mensajes de "continuar secuencia de comandos"). Esto funciona bien.

(function () {
    var elms = document.getElementsByTagName("*"), i, len, ids = {}, id;
    for (i = 0, len = elms.length; i < len; i += 1) {
        id = elms[i].id || null;
        if (id) {
            ids[id] =  ids.hasOwnProperty(id) ? ids[id] +=1 : 0;
        }
    }
    for (id in ids) {
        if (ids.hasOwnProperty(id)) {
            if (ids[id]) {
                console.warn("Multiple IDs #" + id);
            }
        }
    }
}());
Autoesponja
fuente
¡Excelente! Gracias. A menudo olvido que tengo esto ejecutándose en producción y realmente debería optimizarlo ahora, ¡o agregar una configuración de depuración para activarlo / desactivarlo!
Simon_Weaver
Trabajo constantemente en la combinación de scripts en diferentes configuraciones y esto sin duda me ayudará mucho. Gracias :)
Andy Gee
+1 para la solución de JavaScript simple. Después de encontrar los identificadores duplicados, utilicé una expresión XPath ( $x("//*[@id='duplicated-id']")) en la consola para consultar los elementos con los identificadores duplicados.
cassiomolin
12

Debería probar HTML Validator (extensión de Firefox). Definitivamente le dirá que la página tiene identificadores duplicados y mucho más.

Ionuț G. Stan
fuente
8

¿Por qué no valida su html?

No se permiten identificaciones dobles y, normalmente, obtendrá un error de análisis.

Natrio
fuente
2
¿Qué opciones hay para esto?
Simon_Weaver
También en FF, use la barra de herramientas del desarrollador web debajo de las herramientas que tiene validadores
IEnumerator
4
Cuando se trabaja con widgets como el diálogo de jquery ui, sucede a menudo que termina con duplicados en el DOM cuando no se limpia después de crear los diálogos.
guido
4

Otra forma más de localizar duplicados, pero esto agregará una clase de error para que tenga texto rojo:

// waits for document load then highlights any duplicate element id's
$(function(){ highlight_duplicates();});

function highlight_duplicates() {
  // add errors when duplicate element id's exist
  $('[id]').each(function(){ // iterate all id's on the page
    var elements_with_specified_id = $('[id='+this.id+']');
    if(elements_with_specified_id.length>1){
      elements_with_specified_id.addClass('error');
    }
  });


  // update flash area when warning or errors are present
  var number_of_errors = $('.error').length;
  if(number_of_errors > 0)
    $('#notice').append('<p class="error">The '+number_of_errors+
      ' items below in Red have identical ids.  Please remove one of the items from its associated report!</p>');
}
Joshaven Potter
fuente
eso es un poco genial! Gracias. De hecho, he encontrado invaluable la respuesta original aceptada. ¡Atrapé tantas cosas y ahorré probablemente horas de tiempo!
Simon_Weaver
Genial, pero ¿por qué no usar las funciones de la consola y dejar que ellos hagan el resto? Separación de lógica y presentación, etc., etc.
Will Morgan
3

La respuesta principal de jQuery, reescrita en ES6:

  [...document.querySelectorAll('[id]')].forEach(el => {
    const dups = document.querySelectorAll(`[id="${el.id}"]`);

    if (dups.length > 1 && dups[0] === el) {
      console.error(`Duplicate IDs #${el.id}`, ...dups);
    }
  });
Rafi
fuente
2

Esto podría funcionar. Alertará a todos los identificadores de elementos con duplicados.

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>
    	<head>
    		<script type="text/javascript" src="jquery-1.3.1.min.js"></script>
    		<script type="text/javascript">
    			function findDupes()
    			{
    			  var all = $("*");
    			  for(var i = 0; i < all.length; i++)
    			  {
    			      if (all[i].id.length > 0 && $("[id='" + all[i].id + "']").length > 1) alert(all[i].id);
    			  }
    			}
    		</script>
    	</head>
    	<body onload="findDupes()">
    		<div id="s"></div>
    		<div id="f"></div>
    		<div id="g"></div>
    		<div id="h"></div>
    		<div id="d"></div>
    		<div id="j"></div>
    		<div id="k"></div>
    		<div id="l"></div>
    		<div id="d"></div>
    		<div id="e"></div>
    	</body>
    </html>

Syed mohamed aladeen
fuente
1

Me gusta esto porque escupe los elementos reales a la consola. Facilita la investigación de lo que está sucediendo.

function CheckForDuplicateIds() {
var ids = {};
var duplicates = [];

$("[id]").each(function() {
    var thisId = $(this).attr("id");
    if (ids[thisId] == null) {
        ids[thisId] = true;
    } else {
        if (ids[thisId] == true) {
            duplicates.push(thisId);
            ids[thisId] = false;
        }
    }
});
if (duplicates.length > 0) {
    console.log("=======================================================");
    console.log("The following " + duplicates.length + " ids are used by multiple DOM elements:");
    console.log("=======================================================");
    $(duplicates).each(function() {
        console.warn("Elements with an id of " + this + ":");
        $("[id='" + this + "']").each(function() {
            console.log(this);
        });
        console.log("");
    });
} else {
    console.log("No duplicate ids were found.");
}
return "Duplicate ID check complete.";

}

Aparejo
fuente
Esta función fue extremadamente útil donde el validador HTML de extensión de Chrome sugerido no funcionó para mí, porque pudo detectar identificadores replicados cuando se agregó nuevo HTML a la página.
Giselle Serate
1

Puede usar esta solución que imprimirá en la consola una lista de identificadores duplicados, si hay alguno presente.

Puede ejecutar el código directamente en la consola (copiar / pegar) después de que se cargue su DOM y no requiere una dependencia adicional como jQuery.

Puede usarlo para descubrir rápidamente posibles errores en su marcado HTML.

    (function (document) {
        var elms = document.body.querySelectorAll('*[id]'),
            ids = [];
        for (var i = 0, len = elms.length; i < len; i++) {
            if (ids.indexOf(elms[i].id) === -1) {
                ids.push(elms[i].id);
            } else {
                console.log('Multiple IDs #' + elms[i].id);
            }
        }
    })(document);

Un ejemplo:

https://jsbin.com/cigusegube/edit?html,console,output

(aquí se agrega el código antes de cerrar la bodyetiqueta)

GibboK
fuente
0

Creé una función en la que puede inspeccionar un elemento específico en busca de identificadores duplicados dentro o en toda la página:

function duplicatedIDs(container) {

    var $container  = container ? $(container) : $('body'),
        elements = {},
        duplicatedIDs = 0;
        totalIDs = 0;

    $container.find('[ID]').each(function(){
        var element = this;

        if(elements[element.id]){
            elements[element.id].push(element);
        } else  {
            elements[element.id] = [element];
        }
        totalIDs += 1;

    });

    for( var k in elements ){
        if(elements[k].length > 1){
            console.warn('######################################')
            console.warn('        ' + k )
            console.warn('######################################')
            console.log(elements[k]);
            console.log('---------------------------------------');
            duplicatedIDs += elements[k].length
        }
    }
    console.info('totalIDs', totalIDs);
    console.error('duplicatedIDs', duplicatedIDs);
}

duplicatedIDs('#element'); //find duplicated ids under that element
duplicatedIDs(); // entire page
diegodafm
fuente