Javascript - Use onload event , or not - javascript

I'm coding a script that will be used on several websites as a plugin. I have to use only Javascript, no framework. I'm asking myself, what is the best way to load my script without causing any trouble with other scripts or frameworks that can be loaded on these websites.
I thought to do a global function where i call the functions I want to use, and I put this function on the window.load event, like this :
<script>
var global = function(){
object.domain.function1();
object.domain.function2(param1, param2);
object.domain.function3(1);
}
(function(){
if(document.addEventListener){
document.addEventListener('load',global, false);
}
if(document.attachEvent){
document.attachEvent('onload',global);
}
})();
</script>
Or simply :
<script>
object.domain.function1();
object.domain.function2(param1, param2);
object.domain.function3(1);
</script>
Of course, I need some elements are loaded on my page.
Thanks in advance.

If you're ok with putting javascript inside the <body> tag then a fairly reliable way of running javascript after the entire page has loaded is placing your javascript in <script> tags at the very bottom of the page.
It's not my preferred way of handling this issue, but if using the onload event is not working quite right for you this would be a good next step.

what is the best way to load my script without causing any trouble with other scripts or frameworks
The things you need to consider are, are you..
polluting the namespace
obstructing another script
The second point is easy to work around, .addEventListener supports adding many listeners for the same event which won't overwrite each other. There are two different events you might be interested in, 'load' on window and 'DOMContentLoaded' on document. You can always put a <script> at the very end of <body> but I personally don't like doing this because you're mixing HTML with JavaScript or changing the DOM tree.
For the first point, this can be done via the use of anonymous functions and, should you need to occupy the namespace, keeping all of your variables and methods inside one object to minimise your impact.
Putting all this together you may end up with something like this
var myObjectName = { // everything in one object in global namespace
domain: {
function1: function () { /*...*/ },
function2: function () { /*...*/ },
function3: function () { /*...*/ }
}
};
(function (fn) {
if (window.addEventListener) {
window.addEventListener('load', fn, false);
}
else if (window.attachEvent) { // Consider if support for `.attachEvent` is really necessary, people need to move on.
window.attachEvent('onload', fn);
}
})(function () { // pass your function anonymously
myObjectName.domain.function1();
myObjectName.domain.function2(param1, param2);
myObjectName.domain.function3(1);
});

Related

jquery-extension not executing in chrome app

I've encountered a strange problem with my chrome app i'm developing at the moment.
I want to use the "knob" extension to use it for a alarm-clock slider (to set the time)
This wouldn't be a really difficult matter, wouldn't it be for the restrictions and strange issues found while programming a chrome app.
In my index.html file I included the jquery library and the knob extension. And that is where the problems started. Somehow, my scripts only can use the Id's of elements that are above them. So when I include the tags between the tags, nothing executes, if I put them after the first tags they only work with the things that are in this div container. thats why I put the script just before the tag. That works well for "normal" javascript usability. But because I have a that referes to a jquery function (for the knob) the jquery library should be already loaded before the function gets executed (if not, it just doesn't work). I tried to get a workaround by using these posibilities:
document.onload=test();
function test(){
$(function() {
$(".dial").knob();
});
}
document.onload=test();
$(function test() {
$(".dial").knob();
});
}
document.onload=$(function() {
$(".dial").knob();
});
}
well.... It didn't work. I also tried window.onload, with the same reuslt. does someone have a solution? It would be of great help.
Thank you,
neissen
Try like this:
$(function() { //document ready function
function test(){ //inside the ready function
$(".dial").knob();
}
test(); // and call the function here
});
Your Problems:
jQuery may not be loaded but you used some vanilla JS to handle jQuery, which will cause errors.
May be related to global and local.
For the external scripts, functions are only fired locally, which means the global object which contains the html won't be able to be accessed.
To make a global function and a jQuery library - JS:
if ("undefined" === typeof jQuery) {throw new Error("This library requires jQuery"); }
$(function() {
window.myFunction = function() {
doSomething();
}
doSomething();
})
Works calling from HTML - HTML:
<script>
$(function() {
doSomething();
})
</script>
Above is the safest way to approach a jQuery library. The $(function() {... part means exactly the same as $( document ).ready(function() {..., execute if loaded and ready, ensures the browser knows how to deal with all the functions used.

JS namespacing and page-load

I've read about how to make a JS namespace, but my question is how can I make sure the functions inside would only happen on page load?
i.e. instead of:
$(document).ready(function () {...});
(or any other lib then jquery).
also - is there a way to control what will launch on page load and what would before?
Thank you!:)
The following example uses an immediate-function to encapsulate the Code and registers an event-handler on the event DOMContentReady which fires when the Browser has the DOM ready but bevor Images are loaded.
(function () {
'use strict';
var
init = function () {
window.console.info('init()');
};
window.addEventListener('DOMContentReady', init, false);
}());
The immediate-function gets executet as soon as the browser loads the code. From that point there are different events on which further code-execution can be scheduled.
Without using a framework like jquery, which puts some effort in this toppic, you have to handle different events in different browser by your own.
put this code out of jquery code
var MyReallyCoolLibrary = {
awesome: "stuff",
doSomething: function() {
},
doAnotherThing: function() {
}
};
MyReallyCoolLibrary.awesome;
alert(MyReallyCoolLibrary.awesome);

Best place to attach javascript behaviour to the DOM

I'm writing a Javascript file that provides the functionality to create certain DOM elements with ease.
Coming from a jQuery background, normally I'd make this file a plugin and set it up with:
(function($) {
$.fn.entryPoint = function(options) {
//do stuff
}
})(jQuery);
I have no desire to use jQuery for this script, however.
What's the best way to attach the behaviour I've just written to the DOM in a fashion that has the same meaning as the jQuery plugin notation presented above?
There is no universal best code for anything. It all depends on what you are trying to do. I might do something like this, which gives a single global variable named entryPoint, enclosed so that nothing else leaks out into the global namespace.
(function(w) {
w.entryPoint = function(options) {
//do stuff
}
})(window);

Raphael and "global" variables

I'm trying to work with Raphael for some SVG stuff and tried, well, with my limited knowledge, to build something beautiful ;)
I have 3 files:
1x html file and 2xjs files
html file: with an onload function ( + header,body and stuff)
window.onload=function()
{
init();
}
js File1: has the init function and a function to load js files (e.g. Raphael) and a callback to proceed after the file is loaded
function init()
{
getScripts(initTool)
}
function getScripts(callback)
{
$.when($.getScript(scripts[raphael]).then(callback)
}
function initTool()
{
$('body').append("<div id='tool'></div>");
tool=Raphael("tool",5000,5000);
$('body').append("<a href='javascript:void(0)' onclick='newElement'>New element</a>")
}
js File2: Here I have the function newElement which should add (for this example) a single path to the svg element created by Rapahel
function newElement()
{
tool.path("M10,20L30,40");
}
Unfortunately the path does not show up and I have no idea why. I tried referencing the "tool" variable before the onload in case it it related to global/local variables (wild guessing) but this also does not work. changing id's to "tool" to "tool2" for the svg element also does not work.
What else could it be? Where is my (possibly obvious) blind spot?
SHould callback not be declared as a parameter here?
function getScripts(callback)
{
$.when($.getScript(scripts[raphael]).then(callback)
}
To be honest with you I've written quite a bit of javascript and I don't quite grok variables scopes fully yet. However, when calling functions you should use parenthesis to indicate that it should be executed (there are a couple of times when you reference them without parenthesis, but that is beyond the scope of this answer).
So...
$('body').append("<a href='javascript:void(0)' onclick='newElement()'>New element</a>")
But this isn't enough to make it work, you should also declare your function like this:
var newElement = function() {
tool.path("M10,20L30,40");
}
Here is a working solution: http://jsfiddle.net/vAjG2/
(perhaps somebody can expand on why these changes are needed, I don't grasp them myself).
The problem has nothing to do with variable scope. You just need parentheses following the function name in your inline event handler. Rewrite the last line as:
$('body').append("New element")
and you'll be up and running.
However, inline event handlers are frowned upon for a whole variety of reasons. As quirksmode says: "Although the inline event registration model is ancient and reliable, it has one serious drawback. It requires you to write JavaScript behavior code in your XHTML structure layer, where it doesn't belong."
A much cleaner way to do this would separate out the markup and the script, e.g.:
<div id='tool'></div>
<a id="mylink" href='#'>New element</a>
<script>
var tool = Raphael("tool",500,500);
$('#mylink').on("click", function() {
tool.path("M10,20L30,40");
});
</script>
See this jsfiddle for this code in action.
Lastly, as a helpful hint, I would advise running your code on document ready, instead of window load, especially you're using jquery,. Document ready happens when the DOM is first constructed. Window load waits for all assets to be fully loaded, which can take awhile, and typically isn't necessary. It's long considered a best practice.

Best practice for using window.onload

I develop Joomla websites/components/modules and plugins and every so often I require the ability to use JavaScript that triggers an event when the page is loaded. Most of the time this is done using the window.onload function.
My question is:
Is this the best way to trigger JavaScript events on the page loading or is there a better/newer way?
If this is the only way to trigger an event on the page loading, what is the best way to make sure that multiple events can be run by different scripts?
window.onload = function(){}; works, but as you might have noticed, it allows you to specify only 1 listener.
I'd say the better/newer way of doing this would be to use a framework, or to just to use a simple implementation of the native addEventListener and attachEvent (for IE) methods, which allows you to remove the listeners for the events as well.
Here's a cross-browser implementation:
// Cross-browser implementation of element.addEventListener()
function listen(evnt, elem, func) {
if (elem.addEventListener) // W3C DOM
elem.addEventListener(evnt,func,false);
else if (elem.attachEvent) { // IE DOM
var r = elem.attachEvent("on"+evnt, func);
return r;
}
else window.alert('I\'m sorry Dave, I\'m afraid I can\'t do that.');
}
// Use: listen("event name", elem, func);
For the window.onload case use: listen("load", window, function() { });
EDIT I'd like to expand my answer by adding precious information that was pointed by others.
This is about the DOMContentLoaded (Mozilla, Opera and webkit nightlies currently support this) and the onreadystatechange (for IE) events which can be applied to the document object to understand when the document is available to be manipulated (without waiting for all the images/stylesheets etc.. to be loaded).
There are a lot of "hacky" implementations for cross-browsers support of this, so I strongly suggest to use a framework for this feature.
The window.onload events are overridden on multiple creations. To append functions use the
window.addEventListener(W3C standard) or the window.attachEvent(for IE). Use the following code which worked.
if (window.addEventListener) // W3C standard
{
window.addEventListener('load', myFunction, false); // NB **not** 'onload'
}
else if (window.attachEvent) // Microsoft
{
window.attachEvent('onload', myFunction);
}
Modern javascript frameworks have introduced the idea of a "document ready" event. This is an event that will fire when the document is ready to have DOM manipulations performed on it. The "onload" event fires only after EVERYTHING on the page has loaded.
Along with the "document ready" event, the frameworks have provided a way to queue up multiple bits of Javascript code and functions to run when the event fires.
So, if you're opposed to frameworks, the best way to go about this is to implement your own document.onload queue.
If you're not opposed to frameworks, then you'll want to look into jQuery and document.ready, Prototype and dom:loaded, Dojo and addOnLoad or Google for [your framework] and "document ready",.
If you haven't picked a framework but are interested, jQuery is a good place to start. It doesn't change any of Javascript's core functionality, and will generally stay out of your way and let you do things as you like when you want to.
Joomla ships with MooTools, so you'll find it easiest to use the MooTools library for your additional code. MooTools ships with a custom event called domready that fires when the page is loaded and the document tree is parsed.
window.addEvent( domready, function() { code to execute on load here } );
More information about MooTools can be found here. Joomla 1.5 currently ships with MT1.1 while the Joomla 1.6 alpha will include MT1.2
Personally, I prefer this method. Not only does it allow you to have multiple onload functions, but if some script had defined it before you got to it, this method is nice enough to handle that... The only problem left is if a page loads several script which does not use the window.addLoad() function; but that is their problem :).
P.S. Its also great if you want to "chain" more functions later on.
This is the dirty but shorter way :P
function load(){
*code*
}
window[ addEventListener ? 'addEventListener' : 'attachEvent' ]
( addEventListener ? 'load' : 'onload', function(){} )
As of I always include jQuery/bootstrap JS files on bottom of document and have no acces to $ over the document, I developed a tiny "init" plugin which is one and only JS script I include on very top of my pages:
window.init = new function() {
var list = [];
this.push = function(callback) {
if (typeof window.jQuery !== "undefined") {
callback();
} else {
list.push(callback);
}
};
this.run = function() {
if (typeof window.jQuery !== "undefined") {
for(var i in list) {
try {
list[i]();
} catch (ex) {
console.error(ex);
}
}
list = [];
}
};
if (window.addEventListener) {
window.addEventListener("load", this.run, false);
} else if (window.attachEvent) {
window.attachEvent("onload", this.run);
} else {
if (window.onload && window.onload !== this.run) {
this.push(window.onload);
}
window.onload = this.run;
}
};
Using this I can define any anonymous loader over the page, before jQuery and bootstrap inclusion and stay sure that it will fire once jQuery is present:
init.push(function() {
$('[name="date"]').datepicker({
endDate: '0d',
format: 'yyyy-mm-dd',
autoclose: true
}).on('hide', function() {
// $.ajax
});
$('[name="keyword_id"]').select2();
});

Categories