Because of performance purposes I put loading of jQuery scripts at the bottom of the page (just before the closing body tag).
My question is how to enable page specific scripts? I don't want to put everything inside $(document).ready method (again because of performance purposes).
Update: I'm using a template system so I put jQuery loading in the template. That way jQuery calls don't get recognized even if I put them at the end of a specific page because jQuery is not loaded at that point.
I'm not 100% sure what you're asking, but if it's what I think it is, the answer is that you can't have your cake and eat it too.
It seems that you've moved jQuery to the button of the page but have some elements of the page that you want to use JavaScript on, but don't want to wait for document.ready for all of the? Maybe something like the following?
<html>
<body>
<ul id="maybe-some-menu-that-needs-js-initialization-for-example">
...
</ul>
<script>
/* javascript goes here that uses jquery for the above menu (or whatever)
AND you don't want to wait for document.ready for this to happen */
</script>
...
<script src="including jquery here"></script>
<script src="including other scripts here"></script>
</body>
</html>
If that's the case, then refer to what I said from the get-go. You'll have to move jQuery (at least the library, not necessarily all your other JavaScript) back to the top of the page. Either that or don't us jQuery for the things you don't want to wait for document.ready for.
Edit: If you want to perform actions based on the page that you are, then there are two methods, each better and more preferable then the last.
Use location.pathname to determine what functionality you need.
Organize your JavaScript into separate, modular files by their functionality and include only those that are needed for the specific page.
The $(document).ready() will not be overridden when using it more than once, so you can load 2 script files that both adds functionality to be run when the document is loaded.
using $(document).ready, it doesn't matter where in the page it is, as it will only execute when the DOM has finished loading. The only code that should go inside $(document).ready is code that needs to be set up when the DOM has loaded, e.g. event handlers, any effects/animations that you want to run as soon as the DOM has finished loading, etc. Other functions do not need to be in $(document).ready, such as a function used in sorting an array, named functions called when events are raised, etc.
As has been pointed out, you can have more than one $(document).ready function on a page, as what you are doing is specifying a function (named or anonymous) to execute when the ready event (a jQuery event) is raised.
EDIT:
That article that you have linked to in the comments on this answer provides and example of what you are trying to achieve. As an example, you would have a JavaScript file with the following setup to declare a global variable
var myPageLibrary = {
homePage : {
init : function() {
$(document).ready(function() {
/* page specific functions that need to run,
for exmaple, binding event handlers, etc */
});
}
},
aboutPage : {
init : function() {
$(document).ready(function() {
/* page specific functions that need to run,
for exmaple, binding event handlers, etc */
});
}
}
}
/* you might have functions here that are bound to events.
Here is an example */
function showSubMenu(e) {
$(e.target).next('div').show();
}
function hideSubMenu(e) {
$(e.target).next('div').hide();
}
Then in your pages, you would have the following structure (this example uses the home page)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<title>This is my Home Page</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script src="path-to-myPageLibrary.js"></script>
<script type="text/javascript">
myPageLibrary.homePage.init();
</script>
</head>
<body>
<!-- Page content -->
</body>
</html>
with jQuery script file referenced first, followed by myPageLibrary script file, followed by the script block calling myPageLibrary.homePage.init();
If I understand correctly, you need to put some javascript code that calls jquery in the middle of your page. But your jquery include is at the bottom of the body. You can do this by calling the jquery at the window.load event. This event fires after all async scripts have loaded and executed. e.g.:
<body>
<script>
$("#myElem").val(); // fails, "$" not defined
window.addEventListener("load", function(evt) {
$("#myElem").val(); // ok, jquery is loaded
});
</script>
<span id="myElem>hi</span>
<script src="//cdn.jquery.com"></script>
</body>
This allows you to call jQuery plugin methods in the body and load jQuery plugin on to bottom of the page headjs
Just have a page-specific $(document).ready().
Have you tried "#section script"? It will automatic add the codes at the end of the page, thus you can have page specific jQuery scripts.
#section scripts {
<script>
jQuery(document).ready(function () {
//put your jQuery codes here
});
</script>
}
As I understand your issue:
jQuery is not available on the page before it loads.
You use templates and each has it's own js code to run when page loads
You want them to run with jQuery.
If I got you right, here is the solution:
In <head> define global task array:
...
<script>
const JQUERY_READY_TASKS = []
</script>
</head>
After you load jQuery and other scripts define:
...
<script>
jQuery(document).ready(() => {
// Execute all tasks added by templates
for (let n=0; n<JQUERY_READY_TASKS.length; n++)
JQUERY_READY_TASKS[n](jQuery)
}
});
</script>
</body>
Wrap initialization code of your templates in functions:
...
<script>
// Within template
JQUERY_READY_TASKS.push(($) => {
// Template init code
// You can use $ as jquery here
})
</script>
...
Related
I want to run this javascript on my homepage when it loads:
$(".mm-page").css({"position":"inherit"});
I added this at the bottom of my home.html.erb:
<% content_for(:after_js) do %>
<script type="text/javascript">
console.log("before");
$(".mm-page").css({"position":"inherit"});
console.log("after");
</script>
<% end %>
Both console.log appear in the console, but the jquery has no effect. If I manually run the jquery line in the console, it works as expected.
How should I proceed to fix this ?
Since you want to make it work on page when it load you should wrap it inside ready handler.The ready() method specifies what happens when a ready event occurs.
Two syntaxes can be used:
$(document).ready(function(){
$(".mm-page").css({"position":"inherit"});
});
OR
$(function() {
$(".mm-page").css({"position":"inherit"});
});
Also be sure that the element .mm-page exists in the moment you're using it with the jQuery selector.
To ensure that all of the DOM elements it operates on exist, put the script tag at the very bottom of the HTML, just prior to the closing </body> tag. All of the elements defined by the HTML above it will then be available for use. This also ensures that the browser can show the user the page prior to downloading any external script files you reference. E.g.:
<!doctype html>
<html>
<!-- ...your page here... -->
<script src="jquery.js"></script>
<script>
console.log("before");
$(".mm-page").css({"position":"inherit"});
console.log("after");
</script>
</body>
</html>
You'll need to translate that to whatever rendering engine you're using, but you get the idea. The end result going to the browser should look like that.
Alternately, you can use jQuery's ready callback, but with the script tags in the correct location, it's unnecessary.
Side note: The default type is JavaScript, there's no need to specify it on the script tag.
console.log appear in the console
Because your DOM has finished loading and it is now ready to use.
That's why you are getting jQuery effect.
In your current script,it is not waiting to finish DOM loading and directly operating on it which is not available as it is not finished loading.
Eiher write script it in
$( document ).ready(function() {
// Handler for .ready() called.
});
OR :
$(function() {
// Handler for .ready() called.
});
I am new to Java script. I am practicing code.When i put my code in the head section, then i get element null, and when i put it inside body, but before element, then i also get null, but if i put it inside body, but after element then i get the element. I want to ask why i am getting null in case of the first two cases. Here is my code
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="js/attributes.js"></script> // null
</head>
<body>
<script type="text/javascript" src="js/attributes.js"></script> // null
<a id="braingialink"
onclick="return showAttributes();"
href="http://www.braingia.org" >Steve Suehring's Web Site
</a>
<script type="text/javascript" src="js/attributes.js"></script> // ok
</body>
Here is my javascript
var a1 = document.getElementById("braingialink"); //get null in first two cases
window.alert(a1.getAttribute("href"));
a1.setAttribute("href", "www.google.com");
window.alert(a1.getAttribute("href"));
function showAttributes() {
var e = document.getElementById("braingialink");
var elementList = "";
for (var element in e) {
/**
* Sometimes, especially when first programming with JavaScript, you might not know what
* attributes are available for a given element. But you don’t have to worry about that, because
* of a loop that calls the getAttribute() method.
*/
var attrib = e.getAttribute(element);
elementList = elementList + element + ": " + attrib + "\n";
} //end of for()
alert(elementList);
} //end of function showAttributes
And also tell me, placing <script type="text/javascript" src="js/attributes.js"></script>
after the a element, is the same as i write script in the script tag , like
Steve Suehring's Web Site
<script type="text/javascript">
var a1 = document.getElementById("braingialink");
alert(a1.getAttribute("href"));
a1.setAttribute("href","http://www.microsoft.com");
alert(a1.getAttribute("href"));
</script>
Are both things mean to same?
Thanks
The browser parses the document from top to bottom, and if it encounters a <script> block (whether inline script or inclusion of an external JS file) it runs that JavaScript before parsing any more of the document. If that particular code block tries to refer to any elements it can only access the ones above it in the source, i.e., the ones already parsed.
The document.getElementById() method returns null if no element is found for the id you supply, so if you try to use it to access elements below it in the source they've not yet been parsed and can't be found.
The two most common practices to deal with this are:
Put all of your script at the bottom of the <body> such that when it runs all of the elements will have been parsed.
Create an "onload" handler, that is, define a function that will be run as soon as the document finishes loading. You can do this from a script block in the <head> - the JavaScript that defines the onload function is run immediately, but then the function is executed later after everything has loaded.
Following is the simplest way to do option 2:
window.onload = function() {
var x = document.getElementById("x");
// other element manipulation here
};
There is nothing stopping you doing 1 and 2 in the same document, along with throwing some <script> blocks in the middle of the document, but most people find it neater to keep all their code in the one spot.
You're getting null in the head because the DOM has not loaded - your objects are nonexistent at that time. Use this:
window.onload = function () {
// Your code
}
Oh and also take a look at the .ready() function of jQuery here. It would certainly help the headache later on.
Normally you should put script blocks inside the head tag. You can put them in the body tag if you have a special reason, for example to make the script load later because it comes from a slow server.
The reason that you can't access the element, is that the code runs before the browser has parsed the code for the element, so the element simply doesn't exist yet.
You use the load event to run the code after the document is loaded:
window.onload = function() {
// here you put the code that needs to access the elements
}
see http://www.w3schools.com/js/ and http://www.w3schools.com/js/js_whereto.asp
You can place an unlimited number of scripts in your document, and you can have scripts in both the body and the head section at the same time.
It is a common practice to put all functions in the head section, or at the bottom of the page. This way they are all in one place and do not interfere with page content.
You need to understand how web browsers load resources into a page. Firefox -> Firebug add-on Net tab shows the timeline of how resources are loaded. If you are using jQuery or something like it (and you aught to) - then stick your code inside $(document).ready(function() { .. } - that will ensure the page has fully loaded.
Also, it's a good practise to to include your custom js last thing before </body> tag - that way page DOM would have loaded.
Have a read if you want to understand this deeper:
http://www.goodreads.com/book/show/6438581-even-faster-web-sites
and
http://www.goodreads.com/book/show/1681559.High_Performance_Web_Sites
Best would be right before the closing body tag, to not disturb the page loading and rendering at all! It's also recommended by google, for example for analytics snippet and also by facebook!
you get nulls because your script executes while the browser is still loading the page. Since the page might not yet have all elements rendered, you get nulls. you need to run the script when the page has finished loading.
put your script in to the HEAD element, and invoke it on body's onload event.
Can we you get our JavaScript to run in the first place to
assign an event handler?
How can we get an initial piece of JavaScript to run without referencing a function in your XHTML page?
Just put a script tag in the body of your page and it will run as the page is rendered.
<script type="text/javascript">
// code goes here
</script>
Any code you put in a <script type="text/javascript"> tag will be executed immediately. Put it in your <head> and it will run before anything else. Put at the end of the <body> and it will run last.
Do keep in mind that the DOM may not be fully initialized in either of those cases. If you need the DOM use window.onload or jQuery's $(document).ready()
Also 'XHTML' and 'HTML' are not the same. XHTML is a very strict subset of HTML that in my opinion does nothing to improve upon regular HTML but it does allow for some fanciness. It has no effect whatsoever on JavaScript.
As you've tagged jQuery the way to do this is simply by including a ready function, e.g.
$(document).ready(function () {
// Assign your event handlers
});
Just put this code within a <script type="text/javascript"> block within your page.
I am new to jQuery and am stuck at some strange issue. I am using jQuery's change and click methods. They are working fine when used in my HTML file in the <script> tag.
Like:
<script>
$("select,input").change(function ()
{
// My code and some alerts
});
</script>
When I copied the same in external JavaScript code without <script> and imported that in my HTML it was not at all working.
Are there any changes which are needed to use jQuery in external JavaScript code?
PS: Some other non-jQuery functions present in same external JavaScript code are successfully called from HTML.
First off, you don't want a <script> tag in an external JavaScript file, if that's how I'm reading your post.
The trick with jQuery is that your code is set to execute immediately.
You want to wrap your script so that it loads when the document is ready, in something like:
$(document).ready(function(){
$("select,input").change(function ()
{
// My code and some alerts
})
});
And you want to make sure that your file is loaded after jQuery (otherwise the $ global will not be set).
Additions:
Here is what your HTML should look like:
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
<script type="text/javascript" src="jscript/myExternalJs.js"></script>
Here is what your JavaScript code should look like (note there is no script tag inside the JavaScript file):
$(document).ready(function(){
$("select,input").change(function ()
{
// My code and some alerts
})
// Other event handlers.
});
As far as your other script... it sort of depends on what you're doing. The most important thing is to not try to hook event listeners up to objects that don't yet exist, which is why we use document.ready.
Did you make sure jquery is defined before your own jquery code?
You should also make sure the DOM is ready when dealing with jquery:
$(document).ready(function() {
$("select,input").change(function() {
// my code and some alerts
});
// more code here if needed, etc.
});
I am trying to understand how to use jQuery when it is loaded using Google CDN's google.load method.
Putting the init code in the setOnLoadCallback function works great but defining functions for event handlers in the markup doesn't seem to work. In the example below, the P button works as expected but the Div button does nothing.
Yes, in this example, I can put the div's onclick handler also in the setOnLoadCallback function but does that mean that all jQuery code has to be there?
Help? Thanks
<p id="p">Content</p><button type="button" id="btn1">P</button>
<div id="div">Div</div><button type="button" id="btn2" onclick="btn2()">Div</button>
<script src="http://www.google.com/jsapi"></script>
<script>
function btn2() {
$("#div").toggle("slow");
}
google.load("jquery", "1.3.2");
google.setOnLoadCallback(function() {
$("#btn1").click(function () {
$("p").toggle("slow");
});
});
</script>
Put your Google jsapi script call and google.load at the top of <head> in your document. When run, it will just output
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"
type="text/javascript"></script>
where google.load was.
Then put all your jQuery code inside:
$(function() {
// all your jQuery code here
});
which is shorthand for $(document).ready(function(){ });
One of the key points of JQ is to be unobtrusive thus you shouldnt be using <element onclick="..."></element>. You should always be using $(selector).click(). Furthermore you generally want to have this consolidated in a single $(document).ready();, or in exeternal scripts.
Yes, you need to have all your jQuery code inside setOnLoadCallback if you want to load jQuery this way. Until that event fires, there is no guarantee that the jQuery script has loaded, and thus any jQuery code outside that function may be invalid. If you want to define jQuery code outside of that event, you can do it by loading jQuery from Google's CDN URL instead of dynamically by google.load().
The url for jQuery from Google's CDN looks like this:
http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js
You can just include it in the head of the document as an external script resource as usual. You still get the benefits of the Google CDN because most browsers will have a cached copy of jQuery at that location (assuming they have visited another site that used the Google CDN).