document.object Vs. document.getElementById() - javascript

What is the difference between these two syntaxes below-
document.object and document.getElementById().
I want to know when to use which syntax???
e.g.-
CODE1(Implementation with <form>)
<body onload="document.forms[1].innerHTML='hi';">//Alt: onload="document.getElementById('f1').innerHTML='hi';"
<form id=f1>
<input />
</form>
<form id=f2>
<input />
</form>
</body>
both the syntax in onload works the same way. But this doesn't work for the following-
CODE2(Implementation with <div>)
<body onload="document.getElementById('div1').innerHTML='hi';">//cannot use the syntax: onload="document.divs[1].innerHTML='hi';"
<div id=div1>hello</div>
<div id=div2>hello</div>
</body>
So definitely the syntax: document.object does not work with <div>-elements but works with <form>'-element. But **document.getElementById()`** works for both. So when should I use which one???
Someone please highlight the differences between the two syntaxes.
Thanx in advance...

document.forms is a very old method of accessing stuff, along with document.images and document.all, and possibly a few others that I don't remember.
The number one flaw in accessing document.forms[1] is simple: what if another form is added to the page, before the target one? Suddenly you have to search through all your code for references to anything, and change them.
This is where IDs come in. By only allowing one of each ID on a page, getElementById can accurately retrieve it, every time, without caring about what happens to the document in the meantime. The only change that matters is the element being removed altogether.

you can use document.object_name to find anchors, applets, embeds, forms, images, links, plugins.
to find HTML Elemets like div, span, etc. you have to use selectors. you can get this elements by element name, id, class, etc.

The easiest way to access the div in your example is via the "named access on window object" functionality (http://www.whatwg.org/specs/web-apps/current-work/#named-access-on-the-window-object):
Instead of
<body onload="document.getElementById('div1').innerHTML='hi';">
you can use
<body onload="div1.innerHTML='hi';">
Note that "div1" is a property of the window object, not of the document object.

Related

Fetching DOM elements in Javascript

I am complete beginner in JS, so pardon my ignorance. I also didn't manage to find the answer to my question, although, undoubtedly, someone must have asked it before... so I'm posting here.
Here is a simple form I wrote:
<head>
<title>wowzy</title>
<link href="stylesheet.css" type="text/css" rel="stylesheet"/>
</head>
<body>
<form name="forma" id="prvaForma" action="/nonsense.php" method="POST">
<label for="first">1st Value</label>
<input id="first" type="text" name="firstField" value="1st Value here" onClick = 'check();'>
<label for="second">2nd Value</label>
<input id="second" type="text" name="2ndField" value="2nd Value here">
<input type="submit" value="SUBMIT!">
</form>
</body>
and here is the JS function inside the scripts tag following the body
function check() {
var v1 = document.body.prvaForma.first.value;
alert("this is the value: " + v1);
}
Now, this doesn't work and I have been told what to do to make it work, e.g.
var v1 = document.getElementById("first").value
however, I would like to know why does it not work. I just imagined the DOM model in my head, and contructed the path that leads toward the element I want to select, i.e.
document.body.prvaForma.first.value
You can clearly see the DOM hierarchy here, and in the end, selecting the member "value" of the element.
I've been mostly programming in MATLAB and C, and I have some OO background in C++. JS seems awfully confusing right now, so any help is appreciated.
I just imagined the DOM model in my head, and constructed the path that
leads toward the element I want to select, i.e.
document.body.prvaForma.first.value
But DOM nodes do not have properties on them that match such paths! They only would collide with regular properties.
DOM nodes do have properties that allow them to access parent and child nodes (which builds up the DOM tree), and they do store some information about the node itself (tagname, attributes such as id or class).
Usually, you would use methods on them to find nodes in the tree, the most prominent of which is by using DOM selectors (you know them from CSS). Including shortcut methods like getElementById or getElementsByClassName.
And then there are some shortcut properties on the nodes, like .children which yields a collection of all element-typed child nodes. Similarly, there is a .body shortcut on the document which accesses the <body> node in the document. But these are exceptions!
The exception you might be looking for is the .forms collection, which holds all the <form> elements in a document by their name (attribute). And each form has an .elements collection, which holds inputs in that formular by their name (attribute). So you might use
document.forms["forma"].elements["firstField"]
but accessing the input by its id is much cleaner.
As you are taking your first steps in JS, I recommend using the developer console to debug and explore the language. Open in with the F12 key.
Now, being specific to your question, take a look at the documentation of document.forms, you might find it useful to select values inside forms.
This is what DOM level 0 looks like (DOM2 and 3 are almost identical) - http://www.technologyuk.net/the_internet/web/document_object_model.shtml
So to access your form items you would use
var ele = document.forms['prvaForma'].elements;
var val = ele['firstField'].value

access child DOM object from parent in dotted notation

Is there a way to select a child DOM object by treating it as data member of its parent DOM object? Imagine I have this code:
<div id=div1>
<div id=innerdiv1></div>
<div id=innerdiv2></div>
</div>
<div id=div2>
<div id=innerdiv1></div>
<div id=innerdiv2></div>
</div>
This example won't work in real life because both pairs of child divs have the same id's (innerdiv1, innerdiv2), but that's exactly what bothers me about the "id" thing.
Is there some way in javascript to access a child element as a data member, something like document.getElementById('div1.innerdiv1'), which would return a different object from document.getElementById('div2.innerdiv1').
I can't stand that each id has to be unique throughout the document. It becomes a major issue when you have a lot of code and you accidentally use the same id twice. It makes for really nasty bugs that are difficult to squash.
You can use document.querySelector in modern browsers. document.getElementById is pretty much obsolete.
document.querySelector('#div1 #innerdiv1')
You can use classes for the inner divs instead of ids, which do not need to be unique.
The document object has a getElementById method, but the returned elements do not have this method, and it couldn't take a string that isn't exactly the id of an element [if that's what you want try a library, like jQuery or Pumbaa80's suggestion of document.querySelector].
In some browsers you can try:
document.getElementById('div1').getElementsByTagName('div')[0]
As a side note, try dropping these two html documents into html5.validator.nu or http://validator.w3.org/#validate_by_input
<!DOCTYPE html><head><title>t</title></head><body>
<div id=div1><div id=d1>one</div><div id=d2>two</div>three</div>
<div id=div2><div id=d1>four</div><div id=d2>five</div>six</div>
</body>
Now you can totally avoid using the same id twice by just using classes instead.
<!DOCTYPE html><head><title>t</title></head><body>
<div id=div1><div class=d1>one</div><div class=d2>two</div>three</div>
<div id=div2><div class=d1>four</div><div class=d2>five</div>six</div>
</body>
For the first one, you could use document.querySelector('#div2 #d1') or $('#div2 #d1')
but I don't think the result would be guaranteed across all browsers due to the fact that this should be equivalent to writing document.querySelector('#d1') which you can see returns the first occurring id that matches, or $('#d1') which returns both id matching elements in an array.
And for the second one you could use document.querySelector('#div2 .d1') or $('#div2 .d1') or the other statements for very similar results, except that your html is valid this time. You don't even have to have css that defines d1 and d2 and if you used an attribute like class="d1 mySubHeading" and class="d2 mySubHeading" you could style both with mySubHeading and leave d1 and d2 there purely for selection via these methods.

browsing through nodes

this is what an html structure of the webpage looks like:
<body>
<form>
<input type='file'/>
</form>
<div id='list'>
<div>value here<input id='delete' type='button'/></div>
</div>
</body>
i have found javascript code that triggers on 'delete' button click and removes input 'file' element. it uses this piece of code where element is input 'file' mentioned above:
deleteButton.onclick=function(){this.parentNode.element.parentNode.removeChild(
this.parentNode.element );}
i am trying to understand logic(rules) behind 'this.parentNode.element' ? why not accessing element directly 'element.parentNode.remove...'
many thanks
i am trying to understand logic(rules) behind 'this.parentNode.element' ?
There's no element property on the Node, Element, HTMLElement, or HTMLDivElement interfaces. So my guess would be that elsewhere in that code, you'll find something that's explicitly adding that property to the element instance of the div containing the button. You can do that, add arbitrary properties to element instances. These are frequently called "expando" properties and should be done very, very, very carefully.
Not the answer to the question, just opinion. It's better avoid constructions like
this.parentNode.element.parentNode
Because in case when you change your DOM structure, you will need rewrite you JS. So I think it's better to give id attributes to tags, and use next construction to get DOM element:
document.getElementById('element_id')
or if you will use some js framework (like jQuery) you can use even easier construction to get DOM element
$("#ement_id")
Ok, "removeChild" is a strange method, and quite probably, ill-conceived. It should look like:
<div>value here<input id='deleteMe' type='button'/></div>
var node = document.getElementById('deleteMe');
node.remove(); // <--- does not exist, but sure would be nice!!!
No, instead we have to do these shenanigans:
var node = document.getElementById('deleteMe');
node.parentNode.removeChild(node); // verbose! Convoluted!
We have to get the node's parent, call the method, then refer to the node again. This doesn't look like any other DOM methods as far as I recall. The good news is you can make it happen all in one line, chained, like a jQuery method.
You are best served to start over or copy somebody else's code. The use of "this" means it was within an object (or class), referring to other methods or properties within that object. You should stick to non-object variables and functions for now.
Hope that helps.

Is it normal to have two elements with same id in two div elements with other id?

I know, that two elements can't hav the same id. But it's happens so, that in my project I have two elements with same id in other divs, like this
<div id="div1">
<img id="loading" />
</div>
<div id="div2">
<img id="loading" />
</div>
And CSS:
#div1 #loading
{
some style here...
}
#div2 #loading
{
another style here...
}
Works fine for me, but maybe it is not reccomended to do by so?
Yes, I know, thet I can use classes, and it's strongly recomended to do by so, but I want to know is there any potential risk in this usage of id?
I think no, because when I wrote for example
$("#div1 #loading")... it becomes a unique element.
Isn't it?
Change your id to class. It is not a good idea to give duplicate id.
Think two students having same roll no in a class. Imagine them getting examination result. How will the school be able to recognise the marksheet?
Your way is not cross browser compatible, and will affect a lot while coding JavaScript, and posted form etc
You can get the same effect using class
see
<div id="div1">
<img class="loading" />
</div>
<div id="div2">
<img class="loading" />
</div>
and css:
#div1 .loading
{
some style here...
}
#div2 .loading
{
another style here...
}
an id must (should) be unique!!
you will have troubles selecting it via JS in most browsers -
better use class
The big reason is for JavaScript DOM manipulation. In your case, if you do something like this...
document.getElementById("loading")
... JavaScript will return the first element, and the first element only. You'll have no way to access the rest of them without some serious DOM walking.
Just because no-one else has posted it - the HTML spec, section on ID, which says:
id = name [CS]
This attribute assigns
a name to an element. This name must
be unique in a document.
Yes you are right, it is not recommened to do so. An ID should always be unique (e.g. if you want to select the element with javascript).
If you just want to add the same style to the divs, just use css class.
Unique:
In mathematics and logic, the phrase "there is one and only one" is used to indicate that exactly one object with a certain property exists.
#div1 #loading does not remedy the fact that you have two instances of #loading in your document. So, no, don't do that.
IDs should be unique, so id1 and id2 are fine, but for many elements with the same style, use an HTML class and CSS class selector:
.loading
{
styles here
}
These are allowed to be repeated as many times as you want on a page :)
Is it normal? No.
Is it recommended? Definitely not! It's actually prohibited (but enforcement is weak).
But it (apparently) works, so ...
Id are used to distinguish elements, they must be unique for different reason, one of them is the use of javascript, function like getElementById won't work well if you have duplicate ID, you won't be able to predict what it'll do on different browser as JS is self-implemented on each browser differently.
If you wish to use a structure like #div loading and #div2 loading it seem clear that both loading have similar uses so they should be classes and would be used like this
#div1.loading and #div2.loading
Also one plus of using this syntax would be to put the common style in .loading like this
.loading{ style common to both the loading }
#div1.loading{ style used only by the loading in div1 }
#div2.loading{ style used only by the loading in div2 }
https://www.w3.org/TR/1999/REC-html401-19991224/struct/global.html#adef-id
BUT!
If you need it in your project, you can use it, like suggested in my Question Final Update!
validation and purist-ism aside, it is perfectly functional. But I would definitely be annoyed if I use that #loading id and find that a jquery effect or a css effect applies to more than 1 element.Do tell me if IE6 or 7 or Firefox 1.x or 2.x ruins that code.
It's bad practice of using I'd on element. Because I'd giving something for understanding unique with their name identification. And second thing we use its in CSS but in JavaScript this bad practice. So good example for this class and student.
So don't do this.
I disagree on people saying to always use a "unique", meaning different ID everytime you label one. Sometimes its acceptable, such as my case where I am making a calculator.
The javascript is doing the math and outputting the result into the div with the id="total". I need that same exact "total" to be in 2 different places however. In this case, why wouldn't I use two different div's with the same ID? I need the same number in both boxes. With jQuery, I perform and output the math once and it populates both div's at the same time, which is what I want.
So long as you understand the risks where if you were PULLING information from those 2 div's with the same ID, then I say feel free. As long as you dont confuse yourself and need 2 different results in the same div ID.

Opinion: in HTML, Possible Duplicate IDs or Non-Standard Attributes?

It seems pretty common to want to let your javascript know a particular dom node corresponds to a record in the database. So, how do you do it?
One way I've seen that's pretty common is to use a class for the type and an id for the id:
<div class="thing" id="5">
<script> myThing = select(".thing#5") </script>
There's a slight html standards issue with this though -- if you have more than one type of record on the page, you may end up duplicating IDs. But that doesn't do anything bad, does it?
An alternative is to use data attributes:
<div data-thing-id="5">
<script> myThing = select("[data-thing-id=5]") </script>
This gets around the duplicate IDs problem, but it does mean you have to deal with attributes instead of IDs, which is sometimes more difficult. What do you guys think?
Note that an ID cannot start with a digit, so:
<div class="thing" id="5">
is invalid HTML. See What are valid values for the id attribute in HTML?
In your case, I would use ID's like thing5 or thing.5.
<div class="thing" id="myapp-thing-5"/>
// Get thing on the page for a particular ID
var myThing = select("#myapp-thing-5");
// Get ID for the first thing on the page
var thing_id = /myapp-thing-(\d+)/.exec ($('.thing')[0].id)[1];
You'll be giving up some control of the DOM
True, nothing will explode, but it's bad practice. If you put duplicate ids on the page you'll basically loose the ability to be sure about what you're getting when you try to access an element by its id.
var whoKnows = document.getElementById('duplicateId');
The behavior is actually different, depending on the browser. In any case, you can use classNames for duplicate values, and you'll be avoiding the problem altogether.
The browser will try to overlook faults in your markup, but things become messy and more difficult. The best thing to do is keep your markup valid. You can describe both the type of the element and its unique database id in a className. You could even use multiple classNames to differentiate between them. There are a lot of valid possibilities:
<div class="friend04"/>
<div class="featuredFriend04" />
or
<div class="friend friend04" />
<div class="featuredFriend friend04" />
or
<div class="friend objectId04" />
<div class="groupMember objectId04" />
or
<div class="friend objectId04" />
<div class="friend objectId04" id="featured" />
These are all completely legitimate & valid snippets of XHTML. Notice how, in the last snippet, that I've still got an id working for me, which is nice. Accessing elements by their id is very quick and easy, so you definitely want to be able to leverage it when you can.
You'll already spend enough of your time in javascript making sure that you've got the right values and types. Putting duplicate ids on the page will just make things harder for you. If you can find ways to write standards-compliant markup, it has many practical benefits.
IDs should be unique according to the standards and whilst most browsers don't barf when handed duplicate IDs it would not be a good idea to rely on that always being the case.
Making the ID unique by adding a type name to the ID would work but you need to ask why you need it. Giving an element an id is very useful when the element needs to be found, getElementById is very fast. The reason its fast it that most browsers will build an index of IDs as its loads the DOM. However if you have zillions of IDs that you never actually need to use in something like getElementById then you've incurred a cost that is never paid back.
I think you may find most of the time you want the object ID in an event fired by the element or one of its children. In which case I would use an additional attribute on the element and not the ID attribute.
I would leave class attribute to do what its meant to do and not overload it with identification duties.
Considering the fact that you can have multiple classes per element, couldn't you create a unique identifier as an additional class per element? That way, there could be more than one element with the same "id" without HTML ID attribute collisions.
<div class="thing myapp-thing-5" />
<div class="thing myapp-thing-668" />
<div class="thing myapp-thing-5" />
It would be easy to then find these nodes, and find their corresponding DB record with a little string manipulation.
In HTML5, you could do it like this:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script>
window.addEventListener("DOMContentLoaded", function() {
var thing5 = document.evaluate('//*[#data-thing="5"]',
document, null, XPathResult.FIRST_ORDERED_NODE_TYPE ,null);
alert(thing5.singleNodeValue.textContent);
}, false);
</script>
</head>
<body>
<div data-thing="5">test</div>
</body>
</html>
If you set non-standard properties, be sure to either set them programmatically (as everything will be legal that way) or go through the trouble of revising the dtd !-)
But I would use an ID with a meaningful word prepending the DB-id and then use .getElementById, as every necessary informtion is at hand ...
Non-standard attributes are fine, if you're using XHTML and take the time to extend the DTD you're using to cover the new attributes. Personally, I'd just use a more unique id, like some of the other people have suggested.
I don't like John Millikin's solution. It's gonna be performance-intensive on large datasets.
An optimization on his code could be replacing the regular expression with a call to substring() since the first few characters of the id-property are constant.
I'd go with matching class and then a specific id though.
Keeping track of your data via the DOM seems shaky to me; remember, those IDs are global variables, so if there's any chance somebody else's script can find its way onto your page, it's vulnerable. For best results, load your data into an object within an anonymous function and write the table (or the big nested list of DIVs) afterwards.

Categories