I am learning javascript from scratch. I am currently trying to grasp DOM.
I have a HTML page like this:
<html>
<head>
<title>javascript</title>
</head>
<body>
<h1>Welcome to javascript</h1>
Visit me here.
<p> <img id="image" src="kalam.jpg"></p>
<script type="text/javascript" src="code.js">
</script>
</body>
</html>
Now, I want to read a tags.
var links = document.body.getElementsByTagName("a")[0];
console.log(links.href);
It works fine. Now I want to read image.
var imageLink = document.body.getElementById("image");
console.log(imageLink.src);
But, the above code is not working.
I am getting an error:
Uncaught TypeError: document.body.getElementById is not a function.
Changing it to:
var imageLink = document.getElementById("image");
console.log(imageLink.src);
works fine.
My question is about the difference between document.body.getEl... and document.getEl..?
Does document.body reads only body part while document.getEl.. reads whole document including titles etc? If is it so then should not both the above code working?
document.getElementById() gets the element with the matching ID from the document.
document.body.getElementById() does not exist.
document.getElementsByTagName() gets all the elements which match the tag name from the document.
someOtherElement.getElementsByTagName gets all the elements which match the tag name and which are descendants of someOtherElement.
Since an ID must be globally unique within an HTML document, there is generally no need for the getElementById method to exist anywhere other than on the document object itself.
getElementById is a function of document object (so it simply doesn't exist in document.body)
getElementsByTagName is a function of any dom element (including document.body).
Using document.getElementById you are retrieving a specific element with the specified ID on the page. IDs should be unique to each element on a page. when using document.form (or whatever) you are 'filtering down' your selection.
I think if you're new to this it might be worth using
document.querySelectorAll('a')[0]
document.querySelector('#image')
document.querySelector('.someclass')
just because it does tag, id and class all in one.
Related
I have a set of fully functioning codes in Javascript with "document.getElementById". But when I change it to Jquery, it doesn't work (and there are no errors).
<!DOCTYPE html>
<html>
<head>
<style></style>
<script src="jquery-3.3.1.min.js"></script>
<script language="javascript">
function formChk(){
var success=true;
var types = ["Western","Chinese","Local","Beverage"];
var nameTxtBox=$("#name"); <!--This doesn't work-->
var picturesTxtBox=document.getElementById("pictures"); <!--This works fine-->
The corresponding id="name" and id="pictures" are in the codes below:
<p><input type="text" id="name" name="name"></p>
<p><input type="text" id="pictures" name="pictures"></p>
There are no error messages in the console. However, the code doesn't run as per it's supposed to. This entire code is supposed to perform a form validation check - if the user input is left empty, it should throw an error message. However, when I change the "getElementById" to JQuery $(#);, the form validation doesn't work.
Why does this happen?? Isn't $(#); the exact equivalent of document.getElementById?
Isn't $(#); the exact equivalent of document.getElementById?
Absolutely not, they return very different elements, jQuery returns a
collection of matched elements either found in the DOM based on passed argument(s) or created by passing an HTML string.
Jquery() documentation
While document.getElementById() returns
An Element object describing the DOM element object matching the specified ID, or null if no matching element was found in the document.
document.getElementById() documentation
If for compatibility with your previous code you have to access the Element object from the jQuery collection, you can use the array notation.
So if the selector matches a single element, like an id, you can do
let el = $('#selector')[0];
To mimic the behaviour of document.getElementById().
$("#name") return a jQuery object not an Element object like document.getElementById("pictures"); to return a Element object you need to get the Element object from the jQuery object
$("#name")[0]
If you wanted to get the value of #name it would be
$("#name").val()
$('#fileUpload').val('');
We have to pass the value inside the val().
<div id="TheDivIWantTheBelowScriptToAddress"></div>
<script>
document.getPreviousDiv().innerHTML = "YADDA"
</script>
Now I know that in JS I can easily reference an element by its ID like document.getElementById("blah").
However, when the page is being generated from templates, it sometimes might get tricky to ensure that the ids won't repeat. It would be more convenient if I could just reference the first element of a given type (like div or canvas) that lies before the script tag in which this script is included.
Can this be somehow done or do I have to write extra logic to ensure the uniqueness of divs?
I should use this:
<div></div>
<script>
document.currentScript.previousElementSibling.innerHTML = "blah";
</script>
The currentScript gets the current script element.
The previousElementSibling gets the previous element.
This looks like a job for .prev
$('selector').prev()
EDIT: and again without jquery:
var x = document.getElementById("item2").previousSibling.innerHTML;
I never really understood what's happening behind the behavior of dynamically created elements. Here's an example:
$('.some-list').append('<div class="node"></div>');
Where is that stored now? How can I access the div element $('.node')?
I know jQuerys 'on' method for events, but how do I simply access and manipulate that element? Thanks.
Whether $('.some-list') is itself present in the document, or not, you could simply use:
$('.some-list')
// append returns the original collection ("$('.some-ist')"),
// not the newly-added element(s)
.append('<div class="node"></div>')
// so here we can use "find('.node')" to find the newly added
// element(s):
.find('.node')
In the event of the $('.some-list') being present in the document already:
$('.some-list').append('<div class="node">The newly-added Element</div>').find('.node').css('color', '#f90');
.some-list div {
color: #000;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="some-list">
<div>Existing node</div>
</div>
In the event of the $('.node') element not being present in the document:
var someList = $('<div />', {
'class': 'some-list',
'html': '<div>Existing element</div>'
}),
newNode = someList.append('<div class="node">The newly-added Element</div>').find('.node');
console.log(newNode);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
References:
append().
css().
find().
So lets analyse what would happen behind the scenes here.
First we need to understand the HTML that'd look something like below.
<html>
<head>
<!-- Some code here -->
</head>
<body>
<!-- Some Code here -->
<div class="some-list"></div> <!-- Assuming it to be div as that's the most generic way I'd explain, but it could be any element for that matter -->
<!-- Some Code here -->
</body>
</html>
Notice that when you write the $('.some-list'), JQuery will select the div with class=some-list and then you append a random string inside that by .append('<div class="node"></div>'); now when you use JQuery's append, it'll try to see if the passed data (in this case a string) is an object or not. if object it internally does element.appendChild else it internally does element.innerHTML=string.
Now to access the element you write $('.node') as it means you are trying to get the elements from the dom with class names as node. Since you do this after .append it becomes available in the DOM and you can now access it as any other element that was already present in the DOM.
Note: The Confusion is caused as most of the times the event attachment happens at document ready and these dynamically created elements are added later and do not trigger these events. In order to avoid these scenarios Use delegations. Look for JQuery's .on method in detail.
You simply just use $('.node')....
But i think you understand that you can't manipulate a element that doesn't exist yet (you cant access .node before it's appended)
so, html elements such as <title>are sometimes referred as property, but sometimes they are referred as objects. i am kinda confused. are html elements properties of document object? or are they objects? or are they both at the same time? thanks. to make question meet quality standards i will add some random codes.
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
</body>
</html>
The document itself is a document node.
All HTML elements are element nodes.
All HTML attributes are attribute nodes.
Text inside HTML elements are text nodes.
Comments are comment nodes.
In the HTML DOM, the Element object represents an HTML element.
DOM w3schools
The document object has a title property, which is a string, which is an object. But the document object does not have direct properties for the html elements in the page, that's why you have accessor functions like document.getElementById('id'), which return objects representing html elements. Open up a console in chrome and type document. to see all the properties the document object has. Also see that document.title and document.getElementByTagName('title')[0] do not return the same thing.
The DOM, or Document Object Model is a tree. The HTML document available at window.document is the root node of this tree.
Essentially everything else in the document is a node somewhere in this tree, whether it is an element like <p> or an attribute node like class="foo" or a text node. Each of these nodes are objects that you can interact with via Javascript.
They are two separate things.
Element is the HTML element or tag.
Javascript and jQuery (which is also Javascript), for example, modify and control the HTML elements by using the HTML DOM (HTML Document Object Model). The DOM contains the Objects you're referring to. Each DOM object refers to an element and when the Javascript modifies your HTML page, it's actually accessing the DOM, not the HTML elements.
Take a look at: http://www.w3.org/TR/DOM-Level-2-Core/introduction.html.
How do you insert an HTML element dynamically (using prototype) at the current position if you don't know the id of the parent element? All examples I've seen assumes the element has some kind of id.
I.e.
<script>
function addSomeHtmlAtCurrentPosition()
{
current_element = ...; // Magic?
current_element.insert(...);
}
</script>
<div>
<script>
addSomeHtmlAtCurrentPosition();
</script>
<!-- should insert something here... -->
</div>
<div>
<script>
addSomeHtmlAtCurrentPosition();
</script>
<!-- ... and then here -->
</div>
I've tried using prototype with $$('div').last(), but that doesn't seem to work (last() sometimes reports back another div if I use libraries such as livepipe).
What I really want is something similar to document.write, but using prototype instead of raw html.
The only way I can think of is finding the <script> element and insert the element before/after the script. The thing is, all DOM methods need a DOM node to operate on. Executing scripts that modify the DOM before the document has loaded isn't a good and safe idea.
Similar questions linked below.
JavaScript: get the current executing <script> node?
How may I reference the script tag that loaded the currently-executing script?