When is a DOM element "ready"? - javascript

This might sound like a silly question, and I tend to use:
$(document).ready(function() { });
But basic question.
Let's say I have a list of elements like this:
<body>
<p>Paragraph</p>
<div>Div</div>
<div id="HelloWorld">Hello, World</div>
<script>
var hw = $('#HelloWorld');
$(document).ready(function() {
// hw is available for me here
});
</script>
<p>Another paragraph</p>
</body>
It seems the div is available, and I don't run into errors, but is there anything technically wrong with this? Not talking perfectly organized code, but just curious about the technical question at hand.
So I suppose the question is:
Is a DOM element considered complete and available as soon as the browser reads it, regardless if the rest of the elements have loaded yet?

It seems the div is available, and I don't run into errors, but is there anything technically wrong with this?
No. As long as the script isn't run until after the element exists, you can access it. A script in a script tag that's after the markup for the element it refers to will consistently, cross-browser, be able to access that element.
Always works:
<div id="foo">...</div>
<script>
$("#foo")...
</script>
Never works:
<script>
$("#foo")...
</script>
<div id="foo">...</div>
Works only because jQuery delays executing the ready callback:
<script>
$(document).ready(function() {
$("#foo")...
});
</script>
<div id="foo">...</div>
This is one of the reasons for the common recommendation to put script tags at the end of the document, just before the closing </body> tag. That way, they have access to all of the elements defined above them. (And they don't delay the initial presentation of the page, which is usually, though not always, what you want...)

Related

How to manipulate iframe objects using jquery

I've gone through lot of topics related to this question but unable to get the desired output.
I'm calling a iframe inside and html like this:
<iframe class="full-screen-preview__frame" id="nitseditpreview" src="himu/index.php" name="preview-frame" frameborder="0" noresize="noresize" data-view="fullScreenPreview">
Suppose in this iframe I have h2 tag with a class name like this:
<body>
<section id="about-us">
<div class="container">
<div class="text-center">
<div class="col-sm-8">
<h2 class="maincontent">
Why with Us
</h2>
</div>
</div>
</div>
</section>
</body>
As seen by the inspect element in browser
By using Jquery I want to manipulate this lets say for example I want to put border in this. I've tried a lot of things but I guess this thing will work if anyone fixes the bug, my jquery looks like this:
$(document).load(function () {
$('#nitseditpreview').load(function () { //The function below executes once the iframe has finished loading
$this = $(this);
$('#nitsmenu', this.contents()).css('border', 'solid 1px #777');
});
});
Don't know where I'm doing mistake, even I'm following same origin policy too.
If both framed and framing documents are on the same domain, there shouldn't be any need for sandbox attributes or CORS hoop-jumping. But there are a number of other errors here:
$(document).load(...) should be $(document).ready(...) (since it has already loaded by the time your script runs)
you define $this = $(this), but then in the next line try to use a bare this
You're trying to match a #nitsmenu that doesn't appear to exist in the framed document
The following appears to work, although I'm concerned there may still be a race condition on that iframe's .load():
$(document).ready(function() {
$('#nitseditpreview').load(function() {
$(this).contents().find('.container').css('border', 'solid 1px #777');
});
});
http://plnkr.co/edit/tCEHdU0ckg5q4w4tPVFU

Extract all classes from body element of AJAX-ed page and replace current page's body classes

I am in the process of AJAX-ing a WordPress theme with a persistent music player. Wordpress uses dynamic classes on the <body> tag. The basic structure is as follows:
<html>
<head>
</head>
<body class="unique-class-1 unique-class-2 unique-class-3">
<div id="site-container">
<nav class="nav-primary">
Other Page 01
Other Page 02
</nav>
<div class="site-inner">
<p>Site Content Here</p>
</div>
</div>
<div id="music-player"></div>
</body>
</html>
I am currently successfully loading the content of /other-page-01/, /other-page-02/, etc, using load('/other-page-01/ #site-container'). However, I need to extract all <body> classes from the AJAX loaded page and replace the current page's <body> classes with them dynamically.
Note: Replacing the entire <body> element is not an option due to the persistent <div id="music-player">. I've tried jQuery.get(), but couldn't get it to work.
How do I extract the <body> classes from the AJAX requested page and replace the current page's <body> classes with them?
I am not very familiar with jQuery or Javascript, so the exact code would be extremely helpful. Any help is greatly appreciated.
Thanks,
Aaron
My typical solution would have been to tell you to throw the AJAX code in to a jQuery object and then read it out like normal:
$(ajaxResult).attr('class');
Interestingly though, it appears you can't do this with a <body> element.
I'd say the easiest solution (if you have control over the resulting HTML) is to just use some good ol' regex:
var matches = ajaxResult.match(/<body.*class=["']([^"']*)["'].*>/),
classes = matches && matches[1];
I say "if you have control over the resulting HTML", because this relies on the HTML being reasonably well formed.
The other method would involve parsing it as a DOMDocument and then extracting what you need, but this would take a lot more and is usually overkill in simple cases like this.
Convert the body within your returned html to a div with a specific ID, then target that id to get the classes of the body (which is now a div.)
modifiedAjaxResult = ajaxResult.replace(/<body/i,'<div id="re_body"')
.replace(/<\/body/i,'</div');
$(modifiedAjaxResult).filter("#re_body").attr("class");
Of course, if the body has an id, this will conflict with it, so an arbitrary data attribute might be less likely to break.
modifiedAjaxResult = ajaxResult.replace(/<body/i,'<div data-re-id="re_body"')
.replace(/<\/body/i,'</div');
$(modifiedAjaxResult).filter("[data-re-id=re_body]").attr("class");
http://jsfiddle.net/N68St/
Of course, to use this method, you'll have to switch to using $.get instead.
$.get("/other-page-01/",function(ajaxResult){
var modifiedAjaxResult = ajaxResult.replace(/<body/i,'<div data-re-id="re_body"')
.replace(/<\/body/i,'</div');
alert($(modifiedAjaxResult).filter("[data-re-id=re_body]").attr("class"));
// the following line replicates what `.load` was doing.
$(someElement).append( $("<div>").html(ajaxResult).find("#site-container") );
});

Add button after script tag

I have a javascript that I want my users to be able to put on their sites. In this javascript, I want to generate a simple button, that is located exactly where the javascript has been pasted into the site. How can I do this? It would be simple if I could give my <script> tag an id and then just getting the element with the specific ID and appending after it, but I can't.
For example if I have something like this:
<body>
<p>test para</p>
<p>test para</p><p>test para</p><p>test para</p>
<p>test para</p>
<div>test div</div>
<script src="embed.js" type="text/javascript"></script>
<div>last div</div>
</body>
I want my button to be placed right between test div and last div (before or after the script tag, it doesn't matter). Can I do this?
Could you just use after -
$("div:contains('test div')").after('<input type="button"/>');
This would obviously be better if you could give the 'div' an id or a class rather than finding it by the text it contains.
jQuery can find a script tag using -
$("script[src='embed.js']").after('<input type="button"/>')
Demo - http://jsfiddle.net/7GPx7/1
embedding JavaScript something you may want to consider is your visitors may not have jQuery enabled on their sites, so you could bloat the call by loading jQuery or construct your requirement in pure JavaScript.
The embed snippet for your visitors
<script id="eduard_luca" src="http://cdn.example.com/embed.js" type="text/javascript"></script>
embed.js
var element = document.createElement('a');
element.setAttribute('href','http://google.com');
element.innerHTML = 'Click Me';
document.getElementById("eduard_luca").appendChild(element);
I Hope this help you with your project.

Can't fire click event on the elements with same id

Could you help me to understand - where I made the mistake. I have the following html code:
<div id="container">
Info mail.ru
</div>
<div id="container">
Info mail.com
</div>
<div id="container">
Info mail.net
</div>
and the following js code (using jQuery):
$('#getInfo').click(function(){
alert('test!');
});
example here
"Click" event fired only on first link element. But not on others.
I know that each ID in html page should be used only one time (but CLASS can be used a lot of times) - but it only should (not must) as I know. Is it the root of my problem?
TIA!
upd: Big thx to all for explanation!:)
Use a class for this (and return false in your handler, not inline):
<div id="container">
Info mail.ru
</div>
<div id="container">
Info mail.com
</div>
<div id="container">
Info mail.net
</div>
$('.getInfo').click(function(){
alert('test!');
return false;
});
http://jsfiddle.net/Xde7K/2/
The reason you're having this problem is that elements are retrieved by ID using document.getElementById(), which can only return one element. So you only get one, whichever the browser decides to give you.
While you must, according to the W3 specifications, have only one element with a given id within any document, you can bypass this rule, and the issues arising from the consequences if document.getElementById(), if you're using jQuery, by using:
$('a[id="getInfo"]').click(function() {
alert('test!');
return false;
});
JS Fiddle demo.
But, please, don't. Respect the specs, they make everybody's life easier when they're followed. The above is a possibility, but using html correctly is much, much better for us all. And reduces the impact of any future changes within the browser engines, jQuery or JavaScript itself.
It must only be used once or it will be invalid so use a class instead, return false can also be added to your jQuery code as so: -
$('.getInfo').click(function(){
alert('test!');
return false;
});
<a href="#info-mail.net" **class**="getInfo" ....
First id's are for one element only, you should have same id for several divs.
you can make it class instead.
your example changed:
<div class="container">
<a href="#info-mail.ru" class="getInfo" >Info mail.ru</a>
</div>
<div class="container">
<a href="#info-mail.com" class="getInfo" >Info mail.com</a>
</div>
<div class="container">
<a href="#info-mail.net" class="getInfo" >Info mail.net</a>
</div>
$('.getInfo').click(function(ev){
ev.preventDefault(); //this is for canceling your code : onClick="return false;"
alert('test!');
});
You can use the same id for several element (although the page won't validate), but then you can't use the id to find the elements.
The document.getElementById method only returns a single element for the given id, so if you would want to find the other elements you would have to loop through all elements and check their id.
The Sizzle engine that jQuery uses to find the elements for a selector uses the getElementById method to find the element when given a selector like #getInfo.
I know this is an old question and as everyone suggested, there should not be elements with duplicate IDs. But sometimes it cannot be helped as someone else may have written the HTML code.
For those cases, you can just expand the selector used to force jQuery to use querySelectorAll internally instead of getElementById. Here is a sample code to do so:
$('body #getInfo').click(function(){
alert('test!');
});
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
</head>
<body>
<div id="container">
Info mail.ru
</div>
<div id="container">
Info mail.com
</div>
<div id="container">
Info mail.net
</div>
</body>
However as David Thomas said in his answer
But, please, don't. Respect the specs, they make everybody's life easier when they're followed. The above is a possibility, but using html correctly is much, much better for us all. And reduces the impact of any future changes within the browser engines, jQuery or JavaScript itself.

output with javascript/jquery

I have a script that runs within the body. How can I make it output directly after itself. Similar to echo in php.
e.g.
<div id="text">Text</div>
<div id="someotherdiv">
The text above says
<script>
$('#text').html().echo?;
</script>
</div>
You're looking for document.write, like this:
document.write($('#text').html());
EDIT: document.write will only work while the page is loading (as opposed to in an event handler or timer).
To append content later, use jQuery:
$('#someotherdiv').append($('#text').html());

Categories