repeating id's of element children - javascript

Is it ok to have id names for children of an element the same as the ids of children of another element provided the parent id is different? Any potential conflict?

No, element ids should be unique throughout the entire document. document.getElementById() won't work right with duplicate ids (obviously, as it only returns one element). Now your page will probably work fine with the duplicate ids, it's not like the browser will crash or refuse to render the page or anything, but it's not correct HTML.
If you need non-unique identifiers use the class attribute. That's exactly what it's for, to tag multiple elements with the same name.

Read the spec:
This attribute [id] assigns a name to an element.
This name must be unique in a document.

It is very bad practice and likely to cause errors. A better solution would be to use classes to distinguish the child objects and then descend from the parent ID to locate the element you are looking for.

The ID should always be unique regardless in the context of HTML or Javascript. You are much better off with an unique identifier. For example, you have multiple elements with id named "foo"; in document.getElementById("foo") will only return the first instance by that id.

If you've got different DOM elements with the same ID, it will lead to troubles at some point... don't do it even thought it might work.

Related

How can I direct Javascript to access the second element with a non-unique ID

I am trying to declare a paired list in my automation framework, and to do so I pass in two parameters of that list. The first parameter is the DOM id of the "Available" items list, while the second is the DOM id of the "Selected" items list.
var pairedList: newPairedList( "availableItemsListID" , "selectedItemsListID");
In the specific case I'm working on, both the availableItemsListID and the selectedItemsListID happen to have the same ID in the DOM.
The both ids are 'x-fieldset-bwrap', and I have tried the following to indicate the availableItemsListID is the first instance of the id, and the selectedItemsListID is the second instance of the id:
var pairedList: newPairedList( "/x-fieldset-bwrap/[0]" , "/x-fieldset-bwrap/[1]");
It seems to find the availableItemsList however when it attempts to get the selectedItemsList it fails. Does anyone have any suggestions on how to best handle the problem?
Thanks!
You can use document.querySelectorAll to select all elements that match a CSS selector.
document.querySelectorAll("#x-fieldset-bwrap") will match all elements with a id of x-fieldset-bwrap.
If you have the ability to change your system so that it does not generate elements with repeated IDs concurrently within the DOM, I would highly encourage you to do so.
If you can distinguish the first element from the second one somehow, then you can use that difference in your selection. See below:
function display($div) {
console.log($div.html());
}
display($('#unique'));
$('#unique').addClass('firstUnique');
display($('#unique:not(.firstUnique)'));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div id="unique">One</div>
<div id="unique">Two</div>

jQuery child elements with same ID

Imagine that I have this HTML structure:
<div id="bodyRead">
...
<div id="List"></div>
</div>
...
<div id="bodyWrite">
...
<div id="List"></div>
</div>
As you can see, I have the #List inside two different divs (bodyRead and bodyWrite). For a lighter code, I preferred to work with id instead of class (even knowing that duplicate IDs isn't valid, the code makes more sense to me), and selecting the #List on jQuery like this:
$('#bodyRead #List').off('click').on('click', function() ...
$('#bodyWrite #List').off('click').on('click', function() ...
works. I'm always taking care of make duplicate IDs only on child divs, where I can separate them by their parent div on jQuery selector.
Is this approach very wrong? I mean, this can get me in trouble?
don't duplicate your Id even in child element .. change it to class="List"
then you can use
$('.List').on('click',function(){
var getparent = $(this).parent().attr('id');
alert(getparent);
});
and if class="List" not first level child of any of #bodyRead or #bodyWrite
add class to it
<div id="bodyRead" class="mainDiv">
<div id="bodyWrite" class="mainDiv">
and then use
$('.List').on('click',function(){
var getclosest = $(this).closest('.mainDiv').attr('id');
alert(getclosest);
});
You should expect that CSS and JavaScript (including jQuery and other frameworks) behave in accordance with the HTML specifications. ID must be unique, multiple instances of the same ID is not supported. See below:
From HTML 4.01 spec:
id = name [CS] This attribute assigns a name to an element. This name
must be unique in a document.
class = cdata-list [CS] This attribute
assigns a class name or set of class names to an element. Any number
of elements may be assigned the same class name or names. Multiple
class names must be separated by white space characters.
http://www.w3.org/TR/html401/struct/global.html#h-7.5.2
This is from the HTML 5 spec:
3.2.5.1 The id attribute
The id attribute specifies its element's unique identifier (ID). [DOM]
The value must be unique amongst all the IDs in the element's home
subtree and must contain at least one character. The value must not
contain any space characters.
There are no other restrictions on what form an ID can take; in
particular, IDs can consist of just digits, start with a digit, start
with an underscore, consist of just punctuation, etc.
An element's unique identifier can be used for a variety of purposes,
most notably as a way to link to specific parts of a document using
fragment identifiers, as a way to target an element when scripting,
and as a way to style a specific element from CSS.
Identifiers are opaque strings. Particular meanings should not be
derived from the value of the id attribute.
Well i feel this is a bad approach because the browser creates the DOM(document object model) for the page, which takes into consideration that each Id has a unique value.It would be hard to play with the duplicate Id's in javascript when you want to manipulate you need to consider parent as well as child id each time. So its better to use classes instead.
Although id selectors are meant to be unique your code will work as long as you make sure to use correct nesting. In other words #bodyRead #List and #bodyWrite #List are perfectly fine as long as you don't create ambiguity by leaving out the parent selectors to #List.
Still, using multiple identical ids on the same page is just asking for trouble. You should reconsider switching to class selectors or reevaluate if it is really worth the potential trouble of sticking with your original idea.
You certainly should not use duplicate id's in an html page. If you have a similar concept within two different div's then class makes more sense anyway. So change the List ids to classes and then you can access them like this:
$('#bodyRead .List').off('click').on('click', function() ...
$('#bodyWrite .List').off('click').on('click', function() ...
Even if your code works now due to how jQuery works, because the html specifications say not to do this, you can not know for certain that your code will continue to work in the future.

How to getElementByID in a specific DIV block (JS or JQUery)

I just wanted a fast/easy/simple way to check for existing ID on a specific element (div in this case)..
Can't seem to find code sample for this..im using jquery but i dont think i need to do jquery on this one, just basic getElement.. but i need to isolate the search inside a div block.. because the id does exist in other elements on the page but i need to know if it exist in a specific area/div.
so instead of just
document.getElementById(target_id);
i need something like:
divName.getElementById(target_id);
or
$("document.divName").getElementById(target_id);
or
$(".divName").document.getElementById(target_id);
Can't seem to find something that works.
IDs are supposed to be unique and no two elements in page should have same id. You may search some element with some class in div with specific ID.
$('#divId .someClass')
or using find()
$('#divId').find('.someClass')
or using context, jQuery( selector [, context ] )
$('.someClass', $('#divId'))
var mySubDiv = myParentDiv.querySelector("#mySubDivId")
is equivalent to
var mySubDiv = document.querySelector("#myParentDivId #mySubDivId");
// don't forget the space : #myParentDiv#mySubDivId won't work
where querySelector and querySelectorAll are very useful functions, enough for me to avoid using jQuery : they accept any css selector
in real life, using the same Id for different DOM elements often happens.
id's should be unique, you can check for element using:
$(".your_parent_div").find("div#some_unique_id");
you can use it for the getElementsByTagName or ClassName, but ID is unique over document. so doesn't need to do that. better to use a special ID.
and in every id define as a element in javascript and you can just write id's name and use it, like this :
ID.style.color = red;
According to my understanding on your question, You have used two id's with same name when u execute, It takes only first ID so you are asking to take id from the specific div, well that is bad type of coding to use two id for same name instead go for class if want to use same name.
solution for your question is -this ->
var someDiv = document.getElementsByClassName("divName");
var someId = someDiv[0].getElementById("target_id");

How can I select an element by id and class in javascript?

I want to know if we can select an element by using its id and class at the same time. I know in css we can do that with #x.y, but but how can it be accomplished in javascript? I tried the following code and it worked fine but then all the controls with ui-slider-handle class got affected(which is obvious). I think I need a combination of id and class both so that only that particular element will be affected.
Javascript:
$(".ui-slider-handle").text(ui.value);
A combination of ID and class for selecting elements is useless as IDs are meant to be unique.
never have multiple identifiers with the same value in one page!
If you want multiple elements with the same attributes, use a class. If not, consider an ID or a class.
If you want to have a lot of elements with the same attributes, but one with extra attributes, you can give that one an ID and assign extra attributes to the ID
You will never need to do this since the ID is unique; if you know it, you can already identify the element.
Your problem is actually that your selector matches too many elements. There are other ways to limit the "range" of a selector:
Add a parent element with a certain ID/class: .parent .ui-slider-handle matches only elements with the class ui-slider-handle that are children of all elements with the class parent
You can also limit by parent type: div .ui-slider-handle
Or only direct children: div > .ui-slider-handle
See jQuery selectors for all the goodies.
Since ids should be unique, you should be able to do your selector by only id. If are wanting to apply the same attribute to multiple elements, then you should use a class. In your scenario it seems you should be fine with just using id like this:
$("#id").text(ui.value);
What you can write is:
$("#ID.ui-slider-handle").text(ui.value);
The string inside the quotes is a normal CSS selector, which supports both classes and ids. However, the above code is redundant and slow, and unless you want to select that particular id only if it has a certain class, it would be preferable to write:
$("#ID").text(ui.value);

How can I access a particular div on a page which has the same id in two places?

This is the same question as this:
Referring to a div inside a div with the same ID as another inside another
except for one thing.
The reason there are two elements with the same ID is because I'm adding rows to a table, and I'm doing that by making a hidden div with the contents of the row as a template. I make a new div, copy the innerhtml of the template to my new div, and then I just want to edit bits of it, but all the bits have the same ID as the template.
I could dynamically create the row element by element but it's a VERY complex row, and there's only a few things that need to be changed, so it's a lot easier to just copy from a template and change the few things I need to.
So how do I refer to the elements in my copy, rather than the template?
I don't want to mess up the template itself, or I'll never be able to get at the bits for a second use.
Or is there another simpler way to solve the problem?
It will probably just be easiest when manipulating the innerHtml to do a replace on the IDs for that row. Maybe something like...
var copiedRow = templateRow.innerHTML.replace(/id=/g,"$1copy")
This will make the copied divs be prefixed with "copy". You can develop this further for the case that you have multiple copies by keeping a counter and adding that count variable to the replace() call.
When you want to make a template and use it multiple times its best to make it of DOM, in a documentFragment for example.
That way it doesn't respond to document.getElementById() calls in the "live" DOM.
I made an example here: http://jsfiddle.net/PM5544/MXHRr/
id's should be unique on the page.
PM5544...
In reality, there's no use to change the ID to something unique, even though your document may not be valid.
Browsers' selector engines treat IDs pretty much the same as class names. Thus, you may use
document.querySelector('#myCopy #idToLookFor');
to get the copy.
IDs on a page are supposed to be unique, even when you clone them from a template.
If you dynamically create content on your page, then you must change the id of your newly cloned elements to something else. If you want to access all cloned elements, but not the template, you can add a class to them, so you can refer to all elements with that class:
var clonedElement = template.cloneNode(yes); // make a deep copy
clonedElement.setAttribute("id", "somethingElse"); // change the id
clonedElement.setAttribute("class",
clonedElement.getAttribute("class") + " cloned"
);
To access all cloned elements by classname, you can use the getElementsByClassName method (available in newer browsers) or look at this answer for a more in-depth solution: How to getElementByClass instead of GetElementById with Javascript?
Alternatively, if you have jQuery available, you can do this is far less lines of code:
$("#template").clone().attr("id","somethingElse")
.addClass("cloned").appendTo("#someDiv");
The class lookup is even simpler:
$(".cloned").doSomethingWithTheseElements();
Try to avoid using IDs in the child elements of the cloned structure, as all ids of the cloned element should be changed before adding the clone to the page. Instead, you can refer to the parent element using the new id and traverse the rest of the structure using classnames. Class names do not need to be unique, so you can just leave them as they are.
If you really must use ID's (or unique "name" attributes in form fields), I can strongly suggest using a framework like jQuery or Prototype to handle the DOM traversal; otherwise, it is quite a burden to resolve all the cross-browser issues. Here is an example of some changes deeper in the structure, using jQuery:
$("#template").clone().attr("id","somethingElse")
.addClass("cloned") // add a cloned class to the top element
.find("#foo").attr("id","bar").end() // find and modify a child element
.appendTo("#someDiv"); // finally, add the node to the page
Check out my ugly but functional cheese. I wrote a function that works like getelementbyid, but you give it a start node instead of the document. Works like a charm. It may be inefficient but I have great faith in the microprocessors running today's browsers' javascript engines.
function getelement(node, findid)
{
if (node)
if (node.id)
if (node.id == findid)
return node;
node = node.firstChild;
while(node)
{
var r = getelement(node, findid);
if (r != null)
return r;
node = node.nextSibling;
}
return null;
}
When you copy the row, don't you end up having a reference to it? At that point can't you change the ID?

Categories