111

I'm writing applications with ASP.NET MVC. In contrast to traditional ASP.NET you're a lot more responsible for creating all the ids in your generated page. ASP.NET would give you nasty, but unique ids.

I'd like to add a quick little jQuery script to check my document for duplicate ids. They may be ids for DIVS, images, checkboxes, buttons etc.

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

I'm looking for a set and forget type utility that'll just warn me when I do something careless.

Yes i'd be using this only during testing, and alternatives (such as firebug plugins) are welcome too.

Simon_Weaver
  • 140,023
  • 84
  • 646
  • 689

12 Answers12

225

The following will log a warning to the 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);
});
Jess Bowers
  • 2,846
  • 1
  • 22
  • 42
sunsean
  • 2,818
  • 1
  • 17
  • 5
  • perfect! thanks! already discovered three places where I have duplicate IDs. it frustrates me slightly that most peoples solution to this problem is to use 'firebug' or 'html validator'. thats not good enough! i want to catch the unexpected duplicates in wierd situations. – Simon_Weaver Feb 04 '09 at 03:55
  • 5
    hehe and i switched console.warn to alert(...) so i HAVE to fix them :) – Simon_Weaver Feb 04 '09 at 03:57
  • have found this extremely useful and valuable. i think it ought to be a standard in frameworks - especially during debugging – Simon_Weaver Jun 11 '09 at 22:45
  • 6
    The amount of DOM traversals required for this to work is pretty astonishing – Josh Stodola Mar 18 '11 at 18:24
  • 8
    Very nice solution but it needs extra quotes in `var ids = $('[id=\''+this.id+'\']');` so it works with dots and other weird things in IDs. – zidarsk8 Oct 12 '11 at 14:43
  • very useful code. saved me a whole lot of trouble and it can be pasted in to the console area for immediate gratification :) – CommentLuv Sep 24 '13 at 19:35
  • How do I star a answer instead of question in this page? I want this answer to be saved. – Ankit Dec 13 '15 at 14:37
  • Can anybody explain how to make it work for custom attributes, for example `theid` instead of `id` ? – john c. j. Apr 27 '16 at 01:00
  • @john , try this jQuery('[theid]').each(function() { var theid=jQuery(this).attr("theid"); var ids = jQuery('[theid="'+theid+'"]'); if(ids.length>1 && ids[0]==this) {console.warn('Multiple IDs : '+jQuery(this).attr("theid"));}}); – Rajendra Thorat May 04 '16 at 12:16
36

This version is somewhat faster, and you can copy it to a bookmark button to make it a 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
  • 74,049
  • 16
  • 131
  • 175
  • 3
    This algorithm is better, requires only one dom traversal instead of one per matched element. Should be the accepted answer. – m_x Nov 23 '15 at 14:54
  • 1
    It gives false positive for forms which have input with 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'); })();` would be better. – alpo Aug 08 '17 at 07:40
14

I have a big page, so that script runs too slow to finish (multiple "continue script" messages). This works fine.

(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
  • 1,444
  • 10
  • 7
  • great! thanks. i often forget I have this running in production and really ought to optimize it by now - or add a debug setting to turn it on/off! – Simon_Weaver Mar 18 '11 at 19:15
  • I'm constantly working on combining scripts in different configurations and this will certainly help me a lot. Thanks :) – Andy Gee Oct 16 '12 at 11:55
  • +1 for the plain JavaScript solution. After finding the duplicated ids, I used the a XPath expression (`$x("//*[@id='duplicated-id']")`) in the console to query the elements with the duplicated ids. – cassiomolin Oct 30 '15 at 11:34
12

You should try HTML Validator (Firefox extension). It'll definitely tell you the page has duplicate ids and much more.

Ionuț G. Stan
  • 176,118
  • 18
  • 189
  • 202
8

Why don't you just validate your html?

Double ID's are not allowed, and normally you will get a parse-error.

Natrium
  • 30,772
  • 17
  • 59
  • 73
7

The top jQuery answer, rewritten in ES6:

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

    if (dups[1] === el) {
      console.error(`Duplicate IDs #${el.id}`, ...dups);
    }
  });
Rafi
  • 816
  • 9
  • 21
  • 1
    thank you! the days of jQuery are past (or should be) – Anomaly Oct 14 '21 at 22:06
  • Of course it'll take approximately 10 years for this 5-upvoted answer to move to the top near the 220-upvoted accepted answer, and my attempt to create a new question that would make this information more accessible was shut down as a duplicate, but that's StackOverflow for you – Anomaly Oct 15 '21 at 23:13
  • 1
    Seeing this again a year later, there's a more elegant way to check for dups and only log once using a single comparison, `if (dups[1] === el)` – Rafi Oct 18 '21 at 05:41
4

Yet another way of locating duplicates but this will add a class of error so it will have red text:

// 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
  • 10,308
  • 2
  • 18
  • 8
  • thats kinda cool! thanks. i've actually found the original accepted answer invaluable. caught so many things and saved probably hours of time! – Simon_Weaver Jun 11 '09 at 22:44
  • Cool, but why not just use console functions and let them do the rest? Separation of logic and presentation etc etc... – Will Morgan Nov 11 '09 at 13:39
2

This might do the trick It will alert all the ids of elements with duplicates.

<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
  • 6,507
  • 4
  • 32
  • 59
1

I like this because it spits out the actual elements to the console. It makes it easier to investigate what's going on.

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
  • 343
  • 1
  • 10
  • This function was extremely helpful where the suggested Chrome extension HTML validator did not work for me, because it was able to detect replicated ids when new HTML was added to the page. – Giselle Serate Jun 21 '18 at 20:37
1

You can use this solution which will print out in console a list of duplicate ids if any is present.

You can run the code directly in console (copy/paste) after you DOM is loaded and does not require additional dependence like jQuery.

You could use it to quickly found out possible errors in your HTML markup.

    (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);

An example:

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

(here code is added before closing the body tag)

GibboK
  • 71,848
  • 143
  • 435
  • 658
1

We can directly paste the below script into browser console to get duplicate IDs

[...document.querySelectorAll('[id]')].filter(el => [...document.querySelectorAll('[id]')].map(el => el.id).filter(id => id === el.id).length > 1);

Reference: https://www.abeautifulsite.net/getting-duplicate-ids-in-an-html-document

Teela
  • 153
  • 1
  • 3
  • 9
0

I've created a function where you can inspect a specifically element searching for duplicated ids within or the entire page:

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
  • 11
  • 2