JQuery pour vérifier les identifiants en double dans un DOM


106

J'écris des applications avec ASP.NET MVC. Contrairement à ASP.NET traditionnel, vous êtes beaucoup plus responsable de la création de tous les identifiants de votre page générée. ASP.NET vous donnerait des identifiants désagréables mais uniques.

Je voudrais ajouter un petit script jQuery rapide pour vérifier mon document pour les identifiants en double. Il peut s'agir d'identifiants de DIVS, d'images, de cases à cocher, de boutons, etc.

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

Je recherche un utilitaire de type set and forget qui me préviendra quand je fais quelque chose d'inattendu.

Oui, je n'utiliserais cela que pendant les tests, et les alternatives (telles que les plugins Firebug) sont également les bienvenues.

Réponses:


214

Les éléments suivants consigneront un avertissement sur la 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);
});

parfait! Merci! déjà découvert trois endroits où j'ai des identifiants en double. cela me frustre légèrement que la solution de la plupart des gens à ce problème soit d'utiliser «firebug» ou «validateur html». ce n'est pas assez bon! je veux attraper les doublons inattendus dans des situations bizarres.
Simon_Weaver

4
hehe et moi avons commuté console.warn pour alerter (...) donc je
DOIS

ont trouvé cela extrêmement utile et précieux. je pense que cela devrait être une norme dans les frameworks - en particulier lors du débogage
Simon_Weaver

6
La quantité de traversées DOM nécessaires pour que cela fonctionne est assez étonnante
Josh Stodola

8
Très bonne solution mais elle a besoin de guillemets supplémentaires var ids = $('[id=\''+this.id+'\']');pour qu'elle fonctionne avec des points et d'autres choses étranges dans les identifiants.
zidarsk8

33

Cette version est un peu plus rapide et vous pouvez la copier dans un bouton de signet pour en faire un 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');
})();

3
Cet algorithme est meilleur, ne nécessite qu'un seul parcours de dom au lieu d'un par élément correspondant. Devrait être la réponse acceptée.
m_x

1
Il donne un faux positif pour les formulaires qui ont une entrée avec nom = 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'); })(); serait mieux.
alpo

14

J'ai une grande page, de sorte que le script s'exécute trop lentement pour finir (plusieurs messages "continue script"). Cela fonctionne très 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);
            }
        }
    }
}());

génial! Merci. J'oublie souvent que cela fonctionne en production et que je devrais vraiment l'optimiser maintenant - ou ajouter un paramètre de débogage pour l'activer / le désactiver!
Simon_Weaver

Je travaille constamment à combiner des scripts dans différentes configurations et cela m'aidera certainement beaucoup. Merci :)
Andy Gee

+1 pour la solution JavaScript simple. Après avoir trouvé les identifiants dupliqués, j'ai utilisé l'expression a XPath ( $x("//*[@id='duplicated-id']")) dans la console pour interroger les éléments avec les identifiants dupliqués.
cassiomoline


8

Pourquoi ne validez-vous pas simplement votre html?

Les doubles ID ne sont pas autorisés, et normalement vous obtiendrez une erreur d'analyse.


2
quelles options existe-t-il pour cela?
Simon_Weaver

Toujours dans FF, utilisez la barre d'outils des développeurs Web sous les outils dont il dispose de validateurs
IEnumerator

4
Lorsque vous travaillez avec des widgets comme le dialogue de jquery ui, il arrive souvent que vous vous retrouviez avec des doublons dans le DOM lorsque vous ne nettoyez pas après la création des boîtes de dialogue.
guido

4

Encore une autre façon de localiser les doublons, mais cela ajoutera une classe d'erreur donc il aura du texte rouge:

// 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>');
}

c'est plutôt cool! Merci. J'ai trouvé la réponse originale acceptée inestimable. attrapé tant de choses et économisé probablement des heures de temps!
Simon_Weaver

Cool, mais pourquoi ne pas simplement utiliser les fonctions de la console et les laisser faire le reste? Séparation de la logique et de la présentation etc etc ...
Will Morgan

3

La meilleure réponse jQuery, réécrite dans 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);
    }
  });

2

Cela pourrait faire l'affaire. Cela alertera tous les identifiants des éléments avec des doublons.

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


1

J'aime cela car il crache les éléments réels sur la console. Cela permet d'enquêter plus facilement sur ce qui se passe.

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

}


Cette fonction était extrêmement utile là où le validateur HTML de l'extension Chrome suggéré ne fonctionnait pas pour moi, car il était capable de détecter les identifiants répliqués lorsqu'un nouveau code HTML était ajouté à la page.
Giselle Serate

1

Vous pouvez utiliser cette solution qui imprimera dans la console une liste des identifiants en double le cas échéant.

Vous pouvez exécuter le code directement dans la console (copier / coller) après le chargement de votre DOM et ne nécessite pas de dépendance supplémentaire comme jQuery.

Vous pouvez l'utiliser pour découvrir rapidement d'éventuelles erreurs dans votre balisage 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 exemple:

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

(ici le code est ajouté avant de fermer la bodybalise)


0

J'ai créé une fonction dans laquelle vous pouvez inspecter un élément spécifiquement à la recherche d'ID dupliqués dans ou sur la page entière:

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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.