JQuery para verificar se há ids duplicados em um DOM

106

Estou escrevendo aplicativos com ASP.NET MVC. Em contraste com o ASP.NET tradicional, você é muito mais responsável por criar todos os ids em sua página gerada. ASP.NET forneceria ids desagradáveis, mas exclusivos.

Gostaria de adicionar um pequeno script jQuery rápido para verificar se há ids duplicados em meu documento. Eles podem ser ids para DIVS, imagens, caixas de seleção, botões etc.

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

Estou procurando um utilitário do tipo definir e esquecer que apenas me avisará quando eu fizer algo descuidado.

Sim, eu usaria isso apenas durante os testes, e alternativas (como plug-ins do firebug) também são bem-vindas.

Simon_Weaver
fonte

Respostas:

214

O seguinte registrará um aviso no console:

// 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
fonte
perfeito! obrigado! já descobri três lugares onde tenho IDs duplicados. me frustra um pouco que a solução da maioria das pessoas para este problema seja usar 'firebug' ou 'validador html'. isso não é bom o suficiente! Eu quero pegar as duplicatas inesperadas em situações estranhas.
Simon_Weaver
4
hehe e eu trocamos console.warn para alert (...) então eu TENHO que corrigi-los :)
Simon_Weaver
acharam isso extremamente útil e valioso. Eu acho que deveria ser um padrão em frameworks - especialmente durante a depuração
Simon_Weaver
6
A quantidade de travessias de DOM necessária para que isso funcione é bastante surpreendente
Josh Stodola,
8
Solução muito boa, mas precisa de aspas extras var ids = $('[id=\''+this.id+'\']');para funcionar com pontos e outras coisas estranhas em IDs.
zidarsk8,
33

Esta versão é um pouco mais rápida e você pode copiá-la para um botão de favorito para torná-la um bookmarklet.

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
fonte
3
Este algoritmo é melhor, requer apenas uma passagem de dom em vez de uma por elemento correspondente. Deve ser a resposta aceita.
m_x
1
Fornece falso positivo para formulários que têm entrada com nome = 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 melhor.
alpo
14

Eu tenho uma página grande, então o script é executado muito devagar para terminar (várias mensagens "continue script"). Isso funciona bem.

(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);
            }
        }
    }
}());
AutoSponge
fonte
ótimo! obrigado. Muitas vezes esqueço que estou em produção e realmente devo otimizá-lo agora - ou adicionar uma configuração de depuração para ligá-lo / desligá-lo!
Simon_Weaver
Trabalho constantemente combinando scripts em diferentes configurações e isso certamente vai me ajudar muito. Obrigado :)
Andy Gee
1 para a solução JavaScript simples. Depois de encontrar os ids duplicados, usei a expressão XPath ( $x("//*[@id='duplicated-id']")) no console para consultar os elementos com os ids duplicados.
cassiomolina
12

Você deve tentar HTML Validator (extensão Firefox). Definitivamente, ele dirá que a página tem ids duplicados e muito mais.

Ionuț G. Stan
fonte
8

Por que você simplesmente não valida seu html?

IDs duplos não são permitidos e, normalmente, você obterá um erro de análise.

Natrium
fonte
2
que opções existem para isso?
Simon_Weaver
Também no FF, use a barra de ferramentas do desenvolvedor web em ferramentas que possui validadores
IEnumerator
4
Ao trabalhar com widgets como dialog de jquery ui, acontece frequentemente que você acaba com dupliates no DOM quando não está limpando depois de criar os diálogos.
guido de
4

Mais uma maneira de localizar duplicatas, mas isso adicionará uma classe de erro e terá texto em vermelho:

// 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
fonte
isso é legal! obrigado. Na verdade, achei a resposta original aceita inestimável. peguei tantas coisas e economizou provavelmente horas de tempo!
Simon_Weaver
Legal, mas por que não usar as funções do console e deixá-los fazer o resto? Separação de lógica e apresentação etc etc ...
Will Morgan
3

A principal resposta do jQuery, reescrita em 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
fonte
2

Isso pode funcionar. Ele alertará todos os ids de elementos com duplicatas.

<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
fonte
1

Eu gosto disso porque ele cospe os elementos reais para o console. Isso torna mais fácil investigar o que está acontecendo.

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.";

}

Burton
fonte
Essa função foi extremamente útil quando o validador de HTML de extensão do Chrome sugerido não funcionou para mim, porque ele foi capaz de detectar ids replicados quando um novo HTML foi adicionado à página.
Giselle Serate de
1

Você pode usar esta solução que imprimirá no console uma lista de ids duplicados se houver algum.

Você pode executar o código diretamente no console (copiar / colar) depois que o DOM é carregado e não requer dependência adicional como jQuery.

Você pode usá-lo para descobrir rapidamente possíveis erros em sua marcação 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);

Um exemplo:

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

(aqui o código é adicionado antes de fechar a bodytag)

GibboK
fonte
0

Eu criei uma função onde você pode inspecionar um elemento específico procurando por ids duplicados dentro ou em toda a 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
fonte