The difference between using a self invoking function and document ready - javascript

How come this doesn't work in loading header content...
(function ($) {
var mheaderwrapper = '<div id="header"></div><div class="header-menu"></div>';
var mheadercontent = '/shop/Pages/global_header.html';
var mmenucontent = '/shop/Pages/global_megamenu.html';
var mjqueryhover = 'js/jquery.hoverIntent.minified.js';
var mjquerymenu = 'js/jquery.custom-menu.js';
$('#wrapper').prepend(mheaderwrapper);
$('#header').load(mheadercontent);
$('.header-menu').load(mmenucontent, function(){
$.getScript(mjqueryhover);
$.getScript(mjquerymenu);
});
})(jQuery);
but this does...
$.mheader = function() {
var mheaderwrapper = '<div id="header"></div><div class="header-menu"></div>';
var mheadercontent = '/shop/Pages/global_header.html';
var mmenucontent = '/shop/Pages/global_megamenu.html';
var mjqueryhover = 'js/jquery.hoverIntent.minified.js';
var mjquerymenu = 'js/jquery.custom-menu.js';
$('#wrapper').prepend(mheaderwrapper);
$('#header').load(mheadercontent);
$('.header-menu').load(mmenucontent, function(){
$.getScript(mjqueryhover);
$.getScript(mjquerymenu);
});
}
$(function() {
$.mheader();
});

This :
(function ($) {....})(jQuery);
executes immediately, and only maps jQuery to $ to make sure the dollar sign really is "jQuery" within the self executing function. It's not a "DOM ready" function.
This:
$(function() {....});
will wait until the DOM is ready before any code is executed.
You can use the second one inside the first one :
(function ($) {
$(function() {
//code here
});
})(jQuery);
to do both!

When you have a function in the <head> section like that, it is executing immediately, and is doing so before your HTML elements have started loading. Your elements #wrapper, #header, and anything with the .header-menu class do not yet exist at the time your code is executing, which is why it fails.
In the second example, using the domready event delays the firing of your code until after the DOM is ready (and your HTML elements exist), so the code works.
By the way,
$(function() {
// executes when DOM is ready
});
is just a shortcut for:
$(document).ready(function() {
// executes when DOM is ready
});
The above examples are specifically functionality provided by jQuery. Don't confuse the former with the immediately-executing function structure, which is pure JavaScript:
(function() {
// executes NOW
})();
See adeneo's answer for how to properly combine the two.

$(document).ready actually runs after the DOM is created.
Self-invoking functions run instantly if inserted into <head> section, before the DOM is constructed.

Related

Waiting with $(document).ready, $(element).ready, and windows.load all trigger before content is ready

Would you please help me delay execution of my function until the content has loaded? I've streamlined my code to the essentials, bear with my typos:
function Phase1()
{
$(".Hidden").load("hidden.html");
$(window).load(Phase2());
/* I've also tried $(document).ready(Phase2()); */
/* and $(."Hidden").load("hidden.html",Phase2()); */
/* and window.onload... */
}
function Phase2()
{
var Loop;
var Source_Array = document.getElementsByClassName("Random");
for (Loop=0;Loop<Source_Array.length,Loop++)
{ alert(Source_Array[Loop].innerHTML; };
}
The Random class contains several items. On the first pass the alerts are never called (length is 0), on the 2nd iteration it's had time to load everything.
I see no errors in the console when executing.
I have a small and neat solution for your problem, all you need to do is,
Call a setInterval for very short span to check the element is present in DOM or not, if its not your interval will go on, once the element is present, trigger your functions and clear that interval.
code will look like this..
var storeTimeInterval = setInterval(function() {
if (jQuery('.yourClass').length > 0) {
//do your stuff here..... and then clear the interval in next line
clearInterval(storeTimeInterval);
}
}, 100);
The page will load the elements from top to bottom.
If you want your JS code to execute after all elements have loaded, you may try any of the following:
Move your script to the bottom of the page.
<html>
<head></head>
<body>
<!-- Your HTML elements here -->
<script>
// Declaring your functions
function Phase1()
{
$(".Hidden").load("hidden.html");
}
function Phase2()
{
var Loop;
var Source_Array = document.getElementsByClassName("Random");
for (Loop=0;Loop<Source_Array.length,Loop++)
{ alert(Source_Array[Loop].innerHTML; };
}
// Executing your functions in that order.
Phase1();
Phase2();
</script>
</body>
</html>
Bind your functions to document ready using Vanilla JS.
document.addEventListener("DOMContentLoaded", function() {
Phase1();
Phase2();
});
Bind your functions to document using jQuery.
$(document).ready(function() {
Phase1();
Phase2();
});

Accessing an element inside and outside of $( document ).ready()

I need to access an element, both inside and outside of the $( document ).ready() scope.
Assume the following code:
var text__holder = $('#text__holder');
$(function() {
text__holder.text('Inside DOM ready');
/*
SOME MORE ACTION WITH ELEMENT
*/
});
var writeSomeTxt = function () {
text__holder.text('Outside DOM ready');
};
writeSomeTxt();
In this case I can't access the element inside the function. The JS is also in external .js file which is included in <head> part of the page and I cant replace it elsewhere.
My current "workaround" for this is:
var text__holder = $('#text__holder');
$(function() {
text__holder.text('Inside DOM ready');
/*
SOME MORE ACTION WITH ELEMENT
*/
});
var writeSomeTxt = function () {
$(function() {
text__holder.text('Outside DOM ready');
});
};
writeSomeTxt();
The issue is likely that you can't just this line of code:
var text__holder = $('#text__holder');
Until the DOM has been loaded. If you do, you just get an empty jQuery object because it will not find any matching DOM objects.
If you know that writeSomeTxt() won't be called until after the DOM has been loaded, then you could do this:
var text__holder;
$(function() {
text__holder = $('#text__holder');
text__holder.text('Inside DOM ready');
/*
SOME MORE ACTION WITH ELEMENT
*/
});
var writeSomeTxt = function () {
text__holder.text('Outside DOM ready');
};
// don't call this until after the DOM is loaded
// presumably based on some DOM event
writeSomeTxt();
But, really, there's no point in trying to cache a single DOM reference like that anyway so the better way to write your code would be this:
$(function() {
$('#text__holder').text('Inside DOM ready');
/*
SOME MORE ACTION WITH ELEMENT
*/
});
var writeSomeTxt = function () {
$('#text__holder').text('Outside DOM ready');
};
// don't call this until after the DOM is loaded
// presumably based on some DOM event
writeSomeTxt();
Or, if all this code is supposed to run at page initialization time, then just put it all inside of the .ready() handler.
$(function() {
var text__holder = $('#text__holder');
text__holder.text('Inside DOM ready');
/*
SOME MORE ACTION WITH ELEMENT
*/
var writeSomeTxt = function () {
text__holder.text('end of DOM ready');
};
writeSomeTxt();
});
You can declare functions and variables outside document.ready and define the variable inside as well as call function inside once variable is defined:
var text__holder;//declare undefined varible
$(function() {
text__holder = $('#text__holder');// can now define varible
text__holder.text('Inside DOM ready');
// call function now that variable is defined
writeSomeTxt();
});
var writeSomeTxt = function () {
text__holder.text('Outside DOM ready');
};

Function out of scope?

I have a function defined as follows:
window.onload = function() {
var ids = document.getElementById("idname");
function myFunction(){
/...*use ids var in here*./
}
}
I am trying to call myFunction from button onclick in html:
<button onclick="myFunction();"></button>
But it says myFunction is not defined. I understand because this is inside window.onload. How can I fix this? I need window.onload because I need to use document.getElementById("testID") to get content.
I need window.onload because I need to use document.getElementById("testID") to get content
No, you don't need window.onload. You simply have to put the code somewhere after the element with ID testID in the document.
Example:
<div id="testID"></div>
<script>
var ids = document.getElementById("testID");
function myFunction(){
/...*use ids var in here*./
}
</script>
However, if you want to keep using window.onload, then I suggest to not use inline event handlers, but bind the handler with JS:
window.onload = function() {
var ids = document.getElementById("testID");
ids.onclick = function(event){
/...*use ids var in here*./
}
};
(that might be a good thing to do anyway).
Lastly, you can get the a reference to the element inside the event handler using this or event.target:
<div id="testID"></div>
<script>
document.getElementById("testID").onclick = function(event) {
// access element via `this` or `event.target`
};
</script>
Learn more about event handling.
You defined it within a function so it's locked to that scope. Maybe you want to define it outside of that:
function myFunction() {
var ids = document.getElementById("idname");
// ...
}
window.onload = function() {
// ...
}
As a note, this is extremely old-school JavaScript. You could clean this up considerably using something like jQuery which would look something like this:
$(function() {
// Any initialization after page load.
});
function myFunction() {
var ids = $('#idname');
// ...
}

Javascript Singleton design pattern and closure

I'm trying to create a Singleton object that deals with servicing an event listener:
var ChildParent = (function () {
var html_element = document.getElementById("quoteNum");
var row_number = 0;
return {
init: function(){
html_element["parenttype"+row_number].addEventListener("click", ChildParent.fire, false);
},
add: function(total) { //Adding a row
},
fire: function() {
alert("it fired!");
}
}
})();
However, when I call ChildParent.init(), the document-element will not get assigned to html_element, so i can't attach the listener. Oddly enough, the row_number variable is initialized to zero. Is there some sort of scoping conflict that I don't understand? When i use the step-into feature of opera's dragonfly, I can't create var assignments when in the init() function.
Make sure element with id "quoteNum" is available on the page when you are executing your script.
It may happen that you are executing the script without waiting for all the page elements to be rendered.
You may think about handling window.onload.
Update
the following change could help you fix the issue with html_element being initialized before the page is rendered.
var ChildParent = (function () {
function getElement(){
return html_element ? html_element : html_element = document.getElementById("quoteNum");
}
var html_element;
var row_number = 0;
return {
init: function(){
getElement()["parenttype"+row_number].addEventListener("click", ChildParent.fire, false);
},
add: function(total) { //Adding a row
},
fire: function() {
alert("it fired!");
}
}
})();
Is the above code executed after the element with id quoteNum exists in the DOM?
If not html_element will be null.
So make sure that all the above code is in a script tag that occurs somewhere in the document below the element (or is in a window.onload jQuery's document ready type event).

Question about cache in javascript/jquery

I wonder if selector "$cacheA" will be cached on page load in the example below?
// MY JQUERY FUNCTION/PLUGIN
(function( $ ){
$.fn.myFunction = function() {
var $cacheA = this,
$cacheB = $cacheA.children(),
$cacheC = $cacheB.eq(0);
$cacheD = $cacheA.parent();
$cacheD.click(function(){
$cacheA.toggle();
$cacheB.fadeIn();
$cacheC.slideUp();
});
};
})( jQuery );
// END JQUERY FUNCTION/PLUGIN
$(window).load(function(){
$('#mySelector').myFunction();
});
Would it be any reason to do this:
$(window).load(function(){
var $mySelector = $('#mySelector');
$mySelector.myFunction();
});
If, inside your "load" handler, you were to do many jQuery operations with "$mySelector", then saving that in a variable would be a good idea. However, in your example, you only use the value once, so it really makes no difference at all.
Firstable, $cacheA and others inside click function will be undefined.
$cacheD.click(function(){
$cacheA.toggle();
$cacheB.fadeIn();
$cacheC.slideUp();
});
Second,
$.fn.myFunction = function() {
var $cacheA = this,
$cacheB = $cacheA.children(),
$cacheC = $cacheB.eq(0);
$cacheD = $cacheA.parent();
}
So, after $('selector').myFunction() how can I use $cacheB, $cacheC and $cacheD? Where they are will store?

Categories

Resources