I just don't get it. I searched and searched but for this I just can't figure out what's "right".
There are three examples.
1) Fiddle 1.0
Here we have html with onlick="function" and the javascript function right there as well which works fine
<span class="classic one" onclick="someFunction(this,'one')">CLICK HERE</span>
<script type="text/javascript">
function someFunction(obj,nr) {
var string = $(obj).attr('class');
$('.result').text( string );
}
</script>
2) Fiddle 2.0
Then when I move the function to the script section (kind of move it to the .js file) I get an error "ReferenceError: someFunction is not defined"
THIS IS WHERE THE QUESTION BEGINS
3) Fiddle 3
So now I have a function in document ready calling with .on(click which always works fine. This function is calling another function which is outside the docuemnt.ready() and also works fine.
So the question. When do I have to define the functions where AND WHY so it always works?
Thank you!
All the code from Example 3) looks like this:
<div class="result">result</div>
<span class="classic one" onclick="someFunction(this,'one')">CLICK HERE</span>
<span class="classic two" onclick="someFunction(this,'two')">CLICK HERE</span>
<span class="classic three" onclick="someFunction(this,'three')">CLICK HERE</span>
<span class="classic four" onclick="someFunction(this,'four')">CLICK HERE</span>
<div class="ready">ready</div>
<span class="callOtherFunction">Call other function</span>
<script type="text/javascript">
$(document).ready(function(){
$('.ready').text( 'dom is ready' );
function someFunction(obj,nr) {
var string = $(obj).attr('class');
$('.result').text( string );
}
$( "span.callOtherFunction" ).on({
click: function() {
$(this).css("color","red");
$(this).addClass("xyz");
otherFunctionCallingFunction($(this));
}
});
});
function otherFunctionCallingFunction($me) {
$('.callOtherFunction').append( ' --> ' + $me.attr('class') );
}
</script>
A lot of what you're seeing is because of jsFiddle's very surprising default setting, which is to wrap the code in the script pane in an onload handler. So your code is wrapped in a function and no longer at global scope (which is where functions need to be if you use onclick-style attributes). You can change this with the drop-down box on the left (the second one, under the list of libraries and scripts). Change it to "no wrap" to have unwrapped code.
You're not (by far!) the first to be bit by this surprising default.
Answering your main question:
when has a function to be in $(document).ready()
If you control where the script tags loading your script go, you basically never have to use ready; instead, just make sure your script tags are at the end of the HTML, just before the closing </body>.
You can use ready, of course. The reason for doing so is to make sure that all the DOM elements have been created before your code runs. But if you put your script tag at the end, that's already true. You can still define your functions outside of the ready handler (if you want them to be globals), but if you're using ready, you would call them from the ready handler so the elements exist.
FWIW, I would avoid using onclick-style attributes for hooking up event handlers, primarily because they require you to create global functions. I prefer to avoid creating any global symbols when I can avoid it.
The general form I'd recommend:
<!-- ...your page markup here... -->
<script src="any_libraries_you_need_if_you_are_not_combining.js"></script>
<script src="your_script.js"></script>
</body>
</html>
where your script looks like this:
(function($) { // A scoping function that wraps everything
// Hook up event handlers here. You can use `$` for jQuery, even if
// you've used noConflict, because we have a private `$` symbol (see
// the `$` argument above)
// The body of your code goes here
})(jQuery); // <== Note how we're passing the jQuery reference in
// and immediately executing the scoping function
Here's a complete example: Live Copy
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Script Placement Example</title>
</head>
<body>
<input type="button" class="hello-button" value="Click me">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<script>
// This would be in a file, rather than inline
(function($) {
// Hook up handlers
$(".hello-button").click(sayHello);
// Body of the code
function sayHello() {
$("<p>Hello!</p>").appendTo(document.body);
}
})(jQuery);
</script>
</body>
</html>
In JavaScript, scope is handled on a per-function basis. Anything in scope of a function can access other things in scope of that function and things in a wider scope.
Defining a variable with var inside a function will limit the scope of that variable to the function.
Defining a function with a function declaration inside another function will limit the scope of the defined function to the container function.
When you use ready, you pass a function to it. Anything defined in that function is, of course, scoped to that function. Since it is scoped to that function, it is not a global. Your onclick attribute isn't defined in the scope of that function, it can only access globals. This is why you get a reference error.
Avoid globals. They make things hard to maintain. Avoid onclick attributes, they usually depend on globals.
You need to use ready if you want code to run after the DOM has been fully constructed. This is useful if you want to bind event handlers to elements in it with JS (e.g. with jQuery.on). Do this rather then using onclick attributes.
Related
I am new to javascript so I make this thread. I read some post. In this post is the function inside or outside of the document ready. If it is declare outside the document can I re-use / call it in another JScript?.
As my title what should be the contain inside of a document ready?.
$(document).ready is an event which fires up when document is ready.
Suppose you have placed your jQuery code in head section and trying to access a dom element (an anchor, an img etc), you will not be able to access it because html is interpreted from top to bottom and your html elements are not present when your jQuery code runs.
To overcome this problem, we place every jQuery/javascript code (which uses DOM) inside $(document).ready function which gets called when all the dom elements can be accessed.
If you place your jQuery code at the bottom (after all dom elements, just before ) , there is no need for $(document).ready
See the example, which alert calls first that will give you an idea what should be inside the ready.
alert("Without Ready");
$(document).ready(function(){
alert("With Ready");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
.ready makes sure your DOM is ready and good to go for binding, so putting all your functions inside there like the events functions would only be bootstrap at ready state of the document. Normal functions( with name i.e non anonymous functions) can be declared outside the document.ready so you can re-use it somewhere else. since those functions are called from the document.ready events or jquery code to be used.
See more about document.ready here. check the snippet below for a brief example layouting
/**
Global function here, which is not called or bind on page load
*/
function alertWindow(message){
alert ("Window is loaded here with Message: "+message);
$("#console").text(message);
}
$(document).ready(function(){
$("#showBtn").click(function(event){
var ourMessage = $("#message").val();
alertWindow(ourMessage);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="message" placeholder="Enter Message" >
<br>
<button id="showBtn">Show Message</button>
<p>
<h3>Console Here</h3>
<div id="console"></div>
</p>
when we use document.ready all the listeners and all the functions inside the document ready will work only after the page load completed.
So for example if you added any listener to a button and that perform some change in your page then better to write it inside the document.ready.
First things first - In JavaScript a function defines the scope of the code it contains, so if you want to share it you need to define it in a location that your other code can see.
You also don't need to define functions inside the document ready function, you could just define outside of the ready() callback. Eg,
$(document).ready(function(){
$('button').click(function(){
somefunc();
});
});
function somefunc()
{
alert('yes');
}
$(document).ready(function(){
// do something else
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Hope this help..
The ready event occurs when the DOM (document object model) has been loaded.
Because this event occurs after the document is ready, it is a good place to have all other jQuery events and functions. Like in the example above.
source : http://www.w3schools.com/jquery/event_ready.asp
For example: if DOM is not fully loaded and our JS code is trying to access unloaded DOM. We will get Javascript error. To avoid this we need to give some time for loading document. To achieve this, We have a callback function for DOM loaded $(document).ready() or $(function)
We can have functions out side ready and those we can access for other JS also. It is always better to write Jquery add event and other Jquery related code inside ready method.
Refers from here:
A page can't be manipulated safely until the document is "ready."
jQuery detects this state of readiness for you. Code included inside
$(document).ready() will only run once the page Document Object
Model (DOM) is ready for JavaScript code to execute. Code included
inside $(window ).load(function() { ... }) will run once the entire
page (images or iframes), not just the DOM, is ready.
Since usually we've used jQuery to selecting and/or manipulating the DOM, so the best way to that is after the DOM is fully loaded. For those reason, so we need an event to watch the DOM ready state. This method give us flexibility where we'll write our javascript code, either on <head> nor at the end of <body>.
See my snippet samples below:
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script>
// this will not work properly
$('div').html('Hello World!!!');
</script>
</head>
<body>
<div>Hi brother!!</div>
</body>
</html>
Above script will not work properly since the script was executed
before the DOM loaded properly. So, the jquery can not find the
element with div tag.
To make the script running smooth, we need to add additional event listener from jquery named $(document).ready() as you can see at snippet below.
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script>
// this will work properly
$(document).ready(function() {
$('div').html('Hello World!!!');
});
</script>
</head>
<body>
<div>Hi brother!!!</div>
</body>
</html>
But, how if we don't want to add ready method? We still can do that, if we write the script below required DOM, see below snippet for example:
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</head>
<body>
<div></div>
<script>
// this will not work properly
$('div').html('Hello World!!!');
</script>
</body>
</html>
UPDATE :
Refers from OP comment below:
In your reference I read use the shorthand $() for $( document
).ready() so I can use like $() for document.ready?
YES, you can use that shorthand, see my snippet below:
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script>
// this will work properly
$(function() {
$('div').html('Hello World!!!');
});
</script>
</head>
<body>
<div>Hi brother!!!</div>
</body>
</html>
I am just starting out with JavaScript and I have a simple code that sends a value to an element with id p. I am currently declaring this function in a <script> in the <head> element of my document.
function writeP(resultSet) {
document.getElementById('p').innerHTML = resultSet.length;
};
writeP(results);
When I have this listed within the <head> element and run the webpage, firebug throws this error at me: TypeError: document.getElementById(...) is null.
However, if I move the code block into a <script> tag beneath the element and then reload the webpage, no problems and the script works as it should. Is there any reason for this, and a way I could make this work so I wouldn't have to define my functions beneath the element or include a onload on my body element?
Thanks for your help
Reason is that by the time your launch js code, DOM is not yet prepared, and JS can't find such element in DOM.
You can use window.onload (docs on W3schools) trigger to fire your functions after all elements are ready. It's same as having onload property on body element, but is more clear, as you can define it in your js code, not in html.
JS evaluates syncronically. Therefore, it does matter WHEN you declare the function. In this case, you're declaring it before the element actually exists.
Second, when you declare a function with that syntax, it does get eval'd inmediately. If you declared, instead
var writeP=function(resultSet) {
document.getElementById('p').innerHTML = resultSet.length;
};
you could save just the call to the end of the Doc, and leave the declaration at the beggining.
However, I would advise you to read a few jQuery tutorials to learn easier ways to deal with dom manipulation. Nobody runs raw JS for that task anymore.
jQuery includes an useful call to document ready event, which will save you a lot of headaches and is -IMHO- more efficient than the onload event. In this case, you would include the jQuery library somewhere in your code
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
and then add
<script>
jQuery(document).ready(function() {
var writeP=function(resultSet) {
jQuery('#p').html(resultSet.length);
};
writeP(resultSet);
});
</script>
just about anywhere in your document or an external js file, as it suits you.
I have a situation like this in an HTML file:
<script>
var my_function = function(param)
{
alert(param);
}
</script>
<div>
<!-- snip -->
<script>
$(function() {
my_function("Hello world!");
});
</script>
</div>
Will my_function be in scope in the second <script>? Wouldn't my_function be in global scope?
Yes, it will be, since it’s on the global object (as window.my_function).
It will also be ”in scope” (not really meaningful to check, but delete window.my_function won’t work, for example).
All scripts that execute on a page share the same document and window element. So yes. they execute in order, and they are all in the document scope.
my_function as defined in your code is added to the global scope. It will be available in all contexts. This is also how libraries can be made use of. Consider that the script tag contains executable code wether the code is inline:
<script>code</script>
or references remote code:
<script src="my_code.js"></script>
So when you add a script like jQuery or backbone to your html page you are effectively adding their contents to the pages execution context and can access them from your own code.
I thought that script within $(document).ready(...) would always execute after the DOM is loaded. Hence, it wouldn't matter if a $(document.ready(...) went in the head or in the body. However, the code below does not generate "apples" on the screen like I want it to. If I locate the giveApples() function at the bottom of the page though, it works.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script>
$(document).ready(giveApples());
function giveApples() {
$("#appleTree").html("apples");
}
</script>
</head>
<body>
<div id="appleTree"></div>
</body>
<script>
//$(document).ready(giveApples());
</script>
</html>
Can anyone please correct my misconceptions about DOM, page loading, Script-tag location, (document).ready(), or anything else that is causing this problem? I'm still quite new to web programming.
That's because you're not actually binding an event handler to the ready event. You're calling giveApples right away and passing its return value (undefined) as event handler to bind (which silently fails). You need to pass the function to .ready(), not call it!
$(document).ready(giveApples);
Note the missing parentheses.
And it does not. The problem is that you're not passing giveApples as argument, but its returned value, since you are calling it (because of the ()). To make it work, don't put the parenthesis:
$(document).ready(giveApples);
By your current code, the value that is being passed to $(document).ready is undefined, since giveApples doesn't return any value.
You could also do:
$(document).ready(function(){
giveApples(); //However, if you access the 'this' keyword inside the giveApples function, it will point to 'window', and not 'document'
});
You can see what I explained above if you alert these two values:
alert(giveApples); //Shows the giveApples function body, properly
alert(giveApples()); //Shows undefined, since giveApples is being called and does not return any value
Its the same when you use DOM events (onload, onclick, etc). You do this way:
window.onload = myFunction;
And not:
window.onload = myFunction();
You're missing a function
With this syntax:
$(document).ready(giveApples());
you are passing the result of giveApples as the code to be executed at document ready. Also, at the time it is called, this function isn't declared yet.
Correct syntax
This would work:
$(document).ready(function() {
giveApples();
});
As would:
$(document).ready(giveApples);
To answer your titular question since others have identified the source of your problem with the code which is not related to the position of document.ready()...
It doesn't really matter. It is just a standard convention that a lot of people follow.
A lot of people are also proponents of putting the <script> tag as the last element in the <body> tag also.
Proof: See? It's controversial. I even got a downvote. =)
You can put the srcipt wherever you want to put it.The html will execute from up to down.Yes,$(document).ready(...) would always execute after the DOM is loaded.But in your code,you have put the Function outside the $(document).ready.That means it will execute when DOM is loading.Maybe you can do like this:$(document).ready(function giveApples(){$("#appleTree").html("apples");}).
If you want to learn JQuery,I will give you a link and I am new,too.It's very amazing.So have fun.
30-days-to-learn-jquery
w3school
Consider a javascript file script.js which contains the code alert(theVar);
Now, i linked the js file to the document like
<script type="text/javascript">
var theVar= 'a alert';
</script>
<script type="text/javascript" src="script.js"></script> //Contains alert(theVar);
The variable theVar is used and i get a alert. This works fine.
When,
<script type="text/javascript" src="script.js"></script>
<script type="text/javascript">
var theVar= 'a alert';
</script>
is used, i am not getting a alert.
I know the problem is because of the variable, which is declared after loading the js file.
But is there any way to get the variable declared anywhere in the document ?
in script.js do
window.onload = function() { alert ( theVar ) }
Or your favorite library dom ready fn, so it invokes the callback after a certain event instead of immediately.
Though, this really depends on what kind of functionality script.js has, which you have not specified thus far.
The important bit is that code gets executed in the appropriate order. You should delay the call to alert(theVar) until the document gets fully loaded. For instance, you can attach an onload event handler to the window object.
It's also worth noting that calling external *.js files does not affect the way code gets run.
The simple solution:
Move the script.js inclusion to the last row of the body. That way a variable declared at any point in the document can be used.
The technical solution:
Inside script.js, hook on to the window.onload event before doing any evaluating. The result is the same as with the simpler solution, but allows you to keep you script tags in the head (or anywhere for that matter).