79

I have a page with anchor tags throughout the body like this:

<a id="test" name="Name 1"></a>
<a id="test" name="Name 2"></a>
<a id="test" name="Name 3"></a>

The ID is always the same but the name changes.

I need to populate a list of the names of these anchor tags, for example; Name 1, Name 2, Name 3. This is where I've got to so far:

document.write(document.getElementById("readme").name);

This writes out the name of the first anchor tag. I'm in need of a way to get multiple elements by Id.


Any help is greatly appreciated.

zvava
  • 101
  • 1
  • 3
  • 14
osnoz
  • 1,127
  • 1
  • 11
  • 16
  • 53
    The id **cannot** be the same. The HTML specification requires it to be **unique**. – Quentin Mar 17 '11 at 12:03
  • 5
    For reference, that page is not valid HTML, hence the behaviour of the user agents is undefined when dealing with it. As per [the W3c spec](http://www.w3.org/TR/html401/struct/global.html#h-7.5.2), `id` attributes "must be unique within a document". That's the whole *point* of a unique identifier, and is why you don't have DOM methods to get multiple elements with the same ID (since the latter doesn't make any sense). – Andrzej Doyle Mar 17 '11 at 12:03
  • 1
    possible duplicate of [JavaScript and getElementById](http://stackoverflow.com/questions/3607291/javascript-and-getelementbyid) – Andy E Mar 17 '11 at 12:59
  • 2
    Do you mean `getElementById("test").name`? – Ken Sharp Jan 10 '16 at 05:39
  • 2
    @Quentin in a perfect world yes, but you'd be surprised – Robert Sinclair Jun 14 '19 at 00:09

15 Answers15

107

If you can change the markup, you might want to use class instead.

HTML

<a class="test" name="Name 1"></a>
<a class="test" name="Name 2"></a>
<a class="test" name="Name 3"></a>

JS

var elements = document.getElementsByClassName("test");
var names = '';
for(var i = 0; i < elements.length; i++) {
    names += elements[i].name;
}
document.write(names);

jsfiddle demo

JustCarty
  • 3,839
  • 5
  • 31
  • 51
erickb
  • 6,193
  • 4
  • 24
  • 19
49

Today you can select elements with the same id attribute this way:

document.querySelectorAll('[id=test]');

Or this way with jQuery:

$('[id=test]');

CSS selector #test { ... } should work also for all elements with id = "test". Вut the only thing: document.querySelectorAll('#test') (or $('#test') ) - will return only a first element with this id. Is it good, or not - I can't tell . But sometimes it is difficult to follow unique id standart .

For example you have the comment widget, with HTML-ids, and JS-code, working with these HTML-ids. Sooner or later you'll need to render this widget many times, to comment a different objects into a single page: and here the standart will broken (often there is no time or not allow - to rewrite built-in code).

Alexander Goncharov
  • 1,572
  • 17
  • 20
  • 6
    correctly answers the question + more efficient than the $('*').filter answer. Working with classes is the best solution though unless you know what you're doing. – Berty Jul 31 '17 at 09:28
  • 1
    Thank you for answering the question as asked, rather than frame-challenging it. Working with classes is a lovely solution... unless you're working with someone else's code/web page. For things like a Tampermonkey script, we don't get the luxury of making the page "correct". I want to hide all of Quora's new for-pay "subscription" posts, which all have id="content_paywall_card_title_text" and no other significant distinguishing traits from regular posts. So this answer, which *actually answers the question as asked*, was very helpful. Thank you. – Dewi Morgan Oct 23 '21 at 08:11
23

As oppose to what others might say, using the same Id for multiple elements will not stop the page from being loaded, but when trying to select an element by Id, the only element returned is the first element with the id specified. Not to mention using the same id is not even valid HTML.

That being so, never use duplicate id attributes. If you are thinking you need to, then you are looking for class instead. For example:

<div id="div1" class="mydiv">Content here</div>
<div id="div2" class="mydiv">Content here</div>
<div id="div3" class="mydiv">Content here</div>

Notice how each given element has a different id, but the same class. As oppose to what you did above, this is legal HTML syntax. Any CSS styles you use for '.mydiv' (the dot means class) will correctly work for each individual element with the same class.

With a little help from Snipplr, you may use this to get every element by specifiying a certain class name:

function getAllByClass(classname, node) {

    if (!document.getElementsByClassName) {
        if (!node) {
            node =  document.body;
        }

        var a = [],
            re = new RegExp('\\b' + classname + '\\b'),
            els = node.getElementsByTagName("*");

        for (var i = 0, j = els.length; i < j; i++) {
            if (re.test(els[i].className)) {
                a.push(els[i]);
            }
        }
    } else {
        return document.getElementsByClassName(classname);
    }

    return a;
}

The above script will return an Array, so make sure you adjust properly for that.

Shaz
  • 15,637
  • 3
  • 41
  • 59
  • 4
    @Shaz you are the man, because you keep it real with pure JavaScript +1. – Loktar Mar 17 '11 at 13:01
  • 1
    @Loktar so re-inventing wheels is suddenly desirable? There are dozens of production-quality libraries that reduce the above code to a one-liner. – Sean Patrick Floyd Mar 17 '11 at 14:17
  • 10
    @Sean Patrick Floyd Well for one the OP didn't ask for jQuery, why increase page load times, slightly decreased speed, if the user only needs some functionality? Sure the code you write using jQuery may be shorter, but overall its MUCH larger. I don't buy a whole cow every time I want a steak. – Loktar Mar 17 '11 at 15:18
  • 2
    @Loktar I think if your doing anything non trivial having a javascript DOM manipulation library is a must. Just get it from the CDN, it's cached. Besides that function above falls for a few browser bugs. – Raynos Mar 17 '11 at 15:22
  • @Loktar the OP obviously doesn't have much of a clue, so that's not really relevant, on the contrary, pointing him to a library may make things better. – Sean Patrick Floyd Mar 17 '11 at 15:24
  • 3
    @Sean Patrick Floyd I agree with that, my main point is for 10 lines of code, you shouldn't just resort to using a framework. – Loktar Mar 17 '11 at 15:26
14

Here is a function I came up with

function getElementsById(elementID){
    var elementCollection = new Array();
    var allElements = document.getElementsByTagName("*");
    for(i = 0; i < allElements.length; i++){
        if(allElements[i].id == elementID)
            elementCollection.push(allElements[i]);

    }
    return elementCollection;
}

Apparently there is a convention supported by prototype, and probably other major JavaScript libraries.

However, I have come to discover that dollar sign function has become the more-or-less de facto shortcut to document.getElementById(). Let’s face it, we all use document.getElementById() a lot. Not only does it take time to type, but it adds bytes to your code as well.

here is the function from prototype:

function $(element) {
  if (arguments.length > 1) {
    for (var i = 0, elements = [], length = arguments.length; i < length; i++)
      elements.push($(arguments[i]));
    return elements;
  }
  if (Object.isString(element))
    element = document.getElementById(element);
  return Element.extend(element);
}

[Source]

John
  • 13,197
  • 7
  • 51
  • 101
13

You should use querySelectorAll, this writes every occurrence in an array and it allows you to use forEach to get individual element.

document.querySelectorAll('[id=test]').forEach(element=> 
    document.write(element);
});
akolade
  • 139
  • 1
  • 6
13

You can't have duplicate ids. Ids are supposed to be unique. You might want to use a specialized class instead.

Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
2

If you're not religious about keeping your HTML valid then I can see use cases where having the same ID on multiple elements may be useful.

One example is testing. Often we identify elements to test against by finding all elements with a particular class. However, if we find ourselves adding classes purely for testing purposes, then I would contend that that's wrong. Classes are for styling, not identification.

If IDs are for identification, why must it be that only one element can have a particular identifier? Particularly in today's frontend world, with reusable components, if we don't want to use classes for identification, then we need to use IDs. But, if we use multiples of a component, we'll have multiple elements with the same ID.

I'm saying that's OK. If that's anathema to you, that's fine, I understand your view. Let's agree to disagree and move on.

If you want a solution that actually finds all IDs of the same name though, then it's this:

function getElementsById(id) {
    const elementsWithId = []
    const allElements = document.getElementsByTagName('*')
    for(let key in allElements) {
        if(allElements.hasOwnProperty(key)) {
            const element = allElements[key]
            if(element.id === id) {
                elementsWithId.push(element)
            }        
        }
    }
    return elementsWithId
}

EDIT, ES6 FTW:

function getElementsById(id) {
    return [...document.getElementsByTagName('*')].filter(element => element.id === id)
}
sypl
  • 29
  • 1
  • 5
  • _"Classes are for styling, not identification"_ While that may have been the original intent, that's not the case anymore. Consider these sentences from [the MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/class): _"Classes allows CSS **and Javascript** to select and access specific elements"_ and _"web developers are encouraged to use names that **describe the semantic purpose of the element, rather to the presentation of the element**"_ – James Thorpe Jan 15 '16 at 15:27
  • See, I think that's a fudge because there was a realisation IDs were too limited. Now classes serve two purposes, which can't be a good thing. We probably need another attribute ("taxonomy" maybe?) that is only for identification, but for possible multiple elements. In the absence of that though, I'm happy with a little invalid HTML. – sypl Jan 15 '16 at 15:39
2

More than one Element with the same ID is not allowed, getElementById Returns the Element whose ID is given by elementId. If no such element exists, returns null. Behavior is not defined if more than one element has this ID.

CloudyMarble
  • 36,908
  • 70
  • 97
  • 130
1

With querySelectorAll you can select the elements you want without the same id using css selector:

var elems = document.querySelectorAll("#id1, #id1, #id3");
1

You can get the multiple element by id by identifying what element it is. For example

<div id='id'></div>
<div id='id'></div>
<div id='id'></div>

I assume if you are using jQuery you can select all them all by

$("div#id")

. This will get you array of elements you loop them based on your logic.

1

No duplicate ids, it's the basis. If you have an html structure as

<a id="test1" name="Name_1">a1</a>
<a id="test2" name="Name_2">a2</a>
<a id="test3" name="Name_3">a3</a>

Nowadays, with ES6, you can select multiple elements with different id's using the map() method:

const elements = ['test1', 'test2', 'test3'].map(id => document.getElementById(id));

console.log(elements);
// (3) [a#test1, a#test2, a#test3] 

Of course, it's easier to select them if they have a same class.
The elements with the different ids are in an array. You can, for example, remove them from the DOM with the forEach() method:

elements.forEach(el => el.remove());
xavier bs
  • 1,341
  • 1
  • 12
  • 9
0

An "id" Specifies a unique id for an element & a class Specifies one or more classnames for an element . So its better to use "Class" instead of "id".

0

Yes this can be done by the querySelector. QuerySelector will return all the matching elements with same id in javascript.This can be done in code like this :

<div class="class">
    <p>My name is muneeb.</p>
    <h1>Okay here</h1>
</div>
<p class="class">Sample text for para</p>

<p id="id">This is the id with same class</p>
<h1 id="id">This is the heading with same class</h1>
<script src="script.js"></script>

JS Code:

var q = document.querySelectorAll('#id');
for (var i = 0; i < q.length; i++) {
console.log("Inside the loop");
q[i].innerHTML = "Let's see what query selector has changed";
}

If you want your HTML to be a valid html then you should avoid using it .

-2
Below is the work around to submit Multi values, in case of converting the application from ASP to PHP

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE> New Document </TITLE>
<META NAME="Generator" CONTENT="EditPlus">
<META NAME="Author" CONTENT="">
<META NAME="Keywords" CONTENT="">
<META NAME="Description" CONTENT="">
</HEAD>
<script language="javascript">
function SetValuesOfSameElements() {
    var Arr_Elements = [];
    Arr_Elements = document.getElementsByClassName("MultiElements");

    for(var i=0; i<Arr_Elements.length; i++) {
        Arr_Elements[i].value = '';
        var Element_Name = Arr_Elements[i].name;
        var Main_Element_Type = Arr_Elements[i].getAttribute("MainElementType");
        var Multi_Elements = [];
        Multi_Elements = document.getElementsByName(Element_Name);
        var Multi_Elements_Values = '';
//alert(Element_Name + " > " + Main_Element_Type + " > " + Multi_Elements_Values);
        if (Main_Element_Type == "CheckBox") {
            for(var j=0; j<Multi_Elements.length; j++) {
                if (Multi_Elements[j].checked == true) {
                    if (Multi_Elements_Values == '') {
                        Multi_Elements_Values = Multi_Elements[j].value;
                    }
                    else {
                        Multi_Elements_Values += ', '+ Multi_Elements[j].value;
                    }
                }
            }
        }
        if (Main_Element_Type == "Hidden" || Main_Element_Type == "TextBox") {
            for(var j=0; j<Multi_Elements.length; j++) {
                if (Multi_Elements_Values == '') {
                    Multi_Elements_Values = Multi_Elements[j].value;
                }
                else {
                    if (Multi_Elements[j].value != '') {
                        Multi_Elements_Values += ', '+ Multi_Elements[j].value;
                    }
                }
            }
        }
        Arr_Elements[i].value = Multi_Elements_Values;
    }
}

</script>
<BODY>
<form name="Training" action="TestCB.php" method="get" onsubmit="SetValuesOfSameElements()"/>
    <table>

        <tr>
            <td>Check Box</td>
            <td>
                <input type="CheckBox" name="TestCB" id="TestCB" value="123">123</input>
                <input type="CheckBox" name="TestCB" id="TestCB" value="234">234</input>
                <input type="CheckBox" name="TestCB" id="TestCB" value="345">345</input>
            </td>
            <td>
                <input type="hidden" name="SdPart" id="SdPart" value="1231"></input>
                <input type="hidden" name="SdPart" id="SdPart" value="2341"></input>
                <input type="hidden" name="SdPart" id="SdPart" value="3451"></input>

                <input type="textbox" name="Test11" id="Test11" value="345111"></input>

                <!-- Define hidden Elements with Class name 'MultiElements' for all the Form Elements that used the Same Name (Check Boxes, Multi Select, Text Elements with the Same Name, Hidden Elements with the Same Name, etc 
                -->
                <input type="hidden" MainElementType="CheckBox" name="TestCB" class="MultiElements" value=""></input>
                <input type="hidden" MainElementType="Hidden" name="SdPart" class="MultiElements" value=""></input>
                <input type="hidden" MainElementType="TextBox" name="Test11" class="MultiElements" value=""></input>
            </td>
        </tr>
        <tr>
            <td colspan="2">
                <input type="Submit" name="Submit" id="Submit" value="Submit" />
            </td>
        </tr>
    </table>
</form>

</BODY>
</HTML>


testCB.php 

<?php
echo $_GET["TestCB"];
echo "<br/>";
echo $_GET["SdPart"];
echo "<br/>";
echo $_GET["Test11"];
?>
Chakry
  • 23
  • 2
-2

Use jquery multiple selector.

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>multiple demo</title>
<style>
div,span,p {
width: 126px;
height: 60px;
float:left;
padding: 3px;
margin: 2px;
background-color: #EEEEEE;
font-size:14px;
}
</style>
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
</head>
<body>
<div>div</div>
<p class="myClass">p class="myClass"</p>
<p class="notMyClass">p class="notMyClass"</p>
<span>span</span>
<script>$("div,span,p.myClass").css("border","3px solid red");</script>
</body>
</html>

Link : http://api.jquery.com/multiple-selector/

selector should like this : $("#id1,#id2,#id3")

Mahesh V
  • 358
  • 2
  • 9