How can I get a collection of elements by specifying their id attribute? I want to get the name of all the tags which have the same id in the html.
I want to use ONLY getElementById() to get an array of elements. How can I do this?
I know this is an old question and that an HTML page with multiple identical IDs is invalid. However, I ran into this issues while needing to scrape and reformat someone else's API's HTML documentation that contained duplicate IDs (invalid HTML).
So for anyone else, here is the code I used to work around the issue using querySelectorAll:
var elms = document.querySelectorAll("[id='duplicateID']");
for(var i = 0; i < elms.length; i++)
elms[i].style.display='none'; // <-- whatever you need to do here.
The HTML spec requires the id attribute to be unique in a page:
[T]he id attribute value must be unique amongst all the IDs in the element's tree
If you have several elements with the same ID, your HTML is not valid.
So, document.getElementById should only ever return one element. You can't make it return multiple elements.
There are a couple of related functions that will return a list of elements: getElementsByName or getElementsByClassName that may be more suited to your requirements.
Why you would want to do this is beyond me, since id is supposed to be unique in a document. However, browsers tend to be quite lax on this, so if you really must use getElementById for this purpose, you can do it like this:
function whywouldyoudothis() {
var n = document.getElementById("non-unique-id");
var a = [];
var i;
while(n) {
a.push(n);
n.id = "a-different-id";
n = document.getElementById("non-unique-id");
}
for(i = 0;i < a.length; ++i) {
a[i].id = "non-unique-id";
}
return a;
}
However, this is silly, and I wouldn't trust this to work on all browsers forever. Although the HTML DOM spec defines id as readwrite, a validating browser will complain if faced with more than one element with the same id.
EDIT: Given a valid document, the same effect could be achieved thus:
function getElementsById(id) {
return [document.getElementById(id)];
}
document.querySelectorAll("#yourId"); returns all elements whose id is yourId
It is illegal to have multiple elements with the same id. The id is used as an individual identifier. For groups of elements, use class, and getElementsByClassName instead.
The id is supposed to be unique, use the attribute "name" and "getelementsbyname" instead, and you'll have your array.
As others have stated, you shouldn't have the same ID more than once in your HTML, however... elements with an ID are attached to the document object and to window on Internet Explorer. Refer to:
Do DOM tree elements with ids become global variables?
If more than one element with the same ID exists in your HTML, this property is attached as an array. I'm sorry, but I don't know where to look if this is the standard behavior or at least you get the same behavior between browsers, which I doubt.
Class is more than enough for refering anything you want, because it can have a naming with one of more words:
<input class="special use">
<input class="normal use">
<input class="no use">
<input class="special treatment">
<input class="normal treatment">
<input class="no special treatment">
<input class="use treatment">
that's the way you can apply different styles with css (and Bootstrap is the best example of it) and of course you may call
document.getElementsByClassName("special");
document.getElementsByClassName("use");
document.getElementsByClassName("treatment");
document.getElementsByClassName("no");
document.getElementsByClassName("normal");
and so on for any grouping you need.
Now, in the very last case you really want to group elements by id. You may use and refer to elements using a numerically similar, but not equal id:
<input id=1>
<input id="+1">
<input id="-1">
<input id="1 ">
<input id=" 1">
<input id="0x1">
<input id="1.">
<input id="1.0">
<input id="01.0">
<input id="001">
That way you can, knowing the numeric id, access and get an element by just adding extra non-invalidating numeric characters and calling a function to get (by parsing and so on) the original index from its legal string identifying value. It is useful for when you:
Have several rows with similar elements and want to handle its events
coherently. No matter if you delete one or almost all of them.
Since numeric reference is still present, you can then reuse them and
reassign its deleted format.
Run out of class, name and tagname identifiers.
Although you can use spaces and other common signs even when it's a not a requirement strictly validated in browsers, it's not recommended to use them, specially if you are going to send that data in other formats like JSON. You may even handle such things with PHP, but this is a bad practice tending to filthy programming practices.
This is my solution:
<script type="text/javascript">
$(document).ready(function () {
document.getElementsByName("mail")[0].value = "ex_mail1";
document.getElementsByName("mail")[1].value = "ex_mail2";
});
</script>
Or you can use for-loop for that.
You shouldn't do that and even if it's possible it's not reliable and prone to cause issues.
Reason being that an ID is unique on the page. i.e. you cannot have more than 1 element on the page with the same ID.
you can use
document.document.querySelectorAll("#divId")
we can use document.forms[0].Controlid
If you're using d3 for handling multiple objects with the same class / id
You can remove a subset of class elements by using d3.selectAll(".classname");
For example the donut graph here on http://medcorp.co.nz utilizes copies of an arc object with class name "arc" and there's a single line of d3, d3.selectAll(".arc").remove(); to remove all those objects;
using document.getElementById("arc").remove(); only removes a single element and would have to be called multiple times (as is with the suggestions above he creates a loop to remove the objects n times)
I have two HTML elements that are alternatives of each other and I am trying to write a JS function that removes one if the other is present (they originated as words within <sic> and <corr> beneath <choice> in a TEI document). In my transformation, they are both assigned a code (not an #id: #id is randomly generated and has to remain so for other purposes) with a unique prefix:
<a id="abc" choicePOS="sic0">Element1</a>
<a id="xyz" choicePOS="corr0">Element2</a>
In a JS function that 'belongs' to Element1, I want to select Element2 so as to remove it. This is what I have tried (el is element1):
var choicePOS = el.getAttribute("choicePOS").slice(3); // produces 0
var corrID = "corr" + choicePOS; // produces corr0
var corr = document.querySelectorAll("a[choicePOS=corrID]");
This fails, presumably because the corrID variable in the last line is in quote marks and is being taken as a string. I have read various tutorials on CSS selectors and can't find any guidance on how to use them with a variable attribute value. Is this possible? If so, how? If not, any alternatives?
EDIT: A number of other questions relating how to concatenate strings with variables in JS have been suggested as duplicates of this one. To clarify, I am asking specifically about querySelectorAll, as I cannot find any examples this being used with variables. If the answer is that its selector is to be treated as any other JS string (i.e. variables can be concatenated in), then that is perfectly satisfactory.
Use template literals to evaluate that
var corr = document.querySelectorAll(`a[choicePOS=${corrID}]`);
I have a simple form so user send his vote.
There I need to know what radio button user select.
The version I found to solve it was this. How can I get which radio is selected via jQuery?
value = $('input[name=vote]:checked', '#frmSurvey').val();
This work ok. Even when I dont understand how that work, because in Jquery selector documentation there is only 2 example with item separated by coma. And neither match my example where each element is inside a quote and then a coma
.class , .class ---> $(".intro,.demo") All elements with the class "intro" or "demo"
el1 , el2 , el3 ---> $("h1,div,p") All < h1>, < div> and < p> elements
Both looks like OR selector instead of find A and then find B inside A.
So if anyone can tell me what kind of selector is that I would love to take a look into the documentation
Now the optimization I was thinking. If I already inside a function for #frmSurvey won't be faster if I use the this element
$('#frmSurvey').ajaxForm(function () {
value = $('input[name=vote]:checked', '#frmSurvey').val();
console.log('working way ' + value);
value = $(this).find('input[name=vote]:checked').val();
console.log('testing way ' + value);
But I couldn't make the second version to work. Second value get me undefined.
So how I fix second version?
And would be second version better than first one as my instinct suggest or I'm worrying too much?
Your first example shows a selector operating from a context selector, whereas the documentation you've shown shows a "multiple selectors" selector.
You seem to have partially grasped this as
value = $('input[name=vote]:checked', '#frmSurvey').val();
is essentially the same as
value = $('#frmSurvey').find('input[name=vote]:checked').val();
However, the context of "this" inside your function is not clear as it depends upon how the ajaxForm plugin is coded. It isn't necessarily the result of your initial selector. After a short play with the plugin, it would appear that this in the context of ajaxForm is the jQuery ajax request object.
This doesn't work
var name= "#443.selected:first";
selectedEntity = $(name).attr('entityId');
This works
var name= "li.selected:first";
selectedEntity = $(name).attr('entityId');
selectedEntity is undefined but an element does exist with id="443" class="selected".
Why doesn't the first example work?
You can use the attribute selector:
$('[id="443"].selected:first')
See this jsFiddle demo
Though in HTML other than HTML5 IDs which start with a number are not allowed, your selector should work (working Demo). You must have an error elsewhere in your code and/or markup.
There are several issues you should address:
IDs must be unique otherwise your HTML is invalid
overqualifying the ID-Selector is bad for performance and due to 1) even not necessary
ID-Selectors only return the first element so using :first is useless (and also affected by point 1)
Don't use custom attributes like entityId. Instead use the data- prefix. Then you can use jQuerys data method to get/set those attributes. (Beware however that you cannot use camelCase).
If an html element id has no period in it, then copying between elements is of course trivial, e.g.:
var theForm = document.paymentForm;
theForm.BillStreet1.value = theForm.ShipStreet1.value;
I've got a case where I need to have period in my ids, namely id="bill.street1" and id="ship.street1", and the following doesn't work :-(
theForm.bill.street1.value = theForm.ship.street1.value;
Can you please let me know how to handle the period? Does jquery make this simpler?
jQuery makes everything simplier by using css selectors to access elements. However, if you don't want to use jQuery, you can access the element this way, I believe.
theForm['bill.street1'].value = theForm['ship.street1'].value;
I haven't tested this, but it should work because periods are an alternate method to access an array, iirc.
Be sure to use theForm['bill.street1'].value = theForm['ship.street1'].value;
and not theForm.['bill.street1'].value = theForm.['ship.street1'].value;. The extra periods make the format invalid, in the same way using array.[2] instead of array[2] would invalidate it.
theForm['bill.street1'].value
theForm['ship.street1'].value