Insert code in a function - javascript

I am using this code to show loader effect while image load:
$(function(){
jQuery('figure').append('<div class="loader"><div class="bounce1"></div><div class="bounce2"></div><div class="bounce3"></div></div>');
jQuery('.img').load(function(){
jQuery('.loader').remove();
});
});
But I want this code in a function so that I can call it on any image. JSFIDDLE

What you are passing to $() is already a function which is anonymous.
If you want to call it somewhere else you can simply give it a name like
function showSoader(){
jQuery('figure').append('<div class="loader"><div class="bounce1"></div><div class="bounce2"></div><div class="bounce3"></div></div>');
jQuery('.img').load(function(){
jQuery('.loader').remove();
});
}
You can bind it to ready like $(showSoader) and call it anywhere else like showSoader().
If you want to generalize it to work with multiple elements, simply specify a parameter to access the element:
function showSoader(selector){
var $elm = $(selector);
$elm.append('<div class="loader"><div class="bounce1"></div><div class="bounce2"></div><div class="bounce3"></div></div>');
$elm.find('.img').load(function(){
$elm.find('.loader').remove();
});
}
Which you call call like showSoader("#myImgContainer")
worth noticing:
Caveats of the load event when used with images
A common challenge developers attempt to solve using the .load()
shortcut is to execute a function when an image (or collection of
images) have completely loaded. There are several known caveats with
this that should be noted. These are:
It doesn't work consistently nor reliably cross-browser
It doesn't fire correctly in WebKit if the image src is set to the same src as before
It doesn't correctly bubble up the DOM tree
Can cease to fire for images that already live in the browser's cache

JQuery
jQuery.fn.extend({
loadImage: function() {
return this.each(function() {
var loading= jQuery('<div class="loader"><div class="bounce1"></div><div class="bounce2"></div><div class="bounce3"></div></div>').insertBefore(jQuery(this));
jQuery(this).load(function(){
loading.remove();
}).error(function() {
loading.remove();
});
});
}
});
$(".img").loadImage();
DEMO

Related

Why does DOM appendChild() fire on('load', ...) but jQuery append() does not?

I have the following to snippets of code:
$(document).ready(function() {
document.head.appendChild(
$('<script />').attr('src', 'source.js').on('load', function() {
...
})[0]
);
});
This will fire the load handler.
Whereas using the normal jQuery append():
$(document).ready(function() {
$('head').append(
$('<script />').attr('src', 'source.js').on('load', function() {
...
})
);
});
This will not fire the load hander.
What am I missing: why does jQuery append() not work?
Is using document.head.appendChild() a bad idea?
NOTE: I can't use $.getScript(). The code will run on a local file system and chrome throws cross site script errors.
Update
Some people had trouble reading the compact style, so I used extra line feeds to clarify which objects where calling which methods. I also made it explicit that my code is inside a $(document).ready block.
Solution
In the end I went with:
$(document).ready(function() {
$('head')[0].appendChild(
$('<script />').attr('src', 'source.js').on('load', function() {
…
})[0]
);
});
I think #istos was right in that something in domManip is breaking load.
jQuery is doing some funny business in its DOM manipulation code. If you look at jQuery's source, you'll see that it uses a method called domManip() inside the append() method.
This domManip() method creates a document fragment (it looks like the node is first appended to a "safe" fragment) and has a lot of checks and conditions regarding scripts. I'm not sure why it uses a document fragment or why all the checks about scripts exist but using the native appendChild() instead of jQuery's append() method fires the event successfully. Here is the code:
Live JSBin: http://jsbin.com/qubuyariba/1/edit
var url = 'http://d3js.org/d3.v3.min.js';
var s = document.createElement('script');
s.src = url;
s.async = true;
$(s).on('load', function(e) {
console.log(!!window.d3); // d3 exists
$(document.body).append('<h1>Load fired!</h1>');
});
$('head').get(0).appendChild(s);
Update:
appendChild() is a well supported method and there is absolutely no reason not to use it in this case.
Maybe the problem is when you choose DOM appendChild, actually you called the function is document.on('load',function(){});, however when you choose jQuery append(), your code is $('head').on('load', function(){}).
The document and head are different.
You can type the code below:
$(document).find('head').append($('<script />').attr('src', 'source.js').end().on('load', function() {
...
}));
You should probably make sure that the jquery append is fired when the document is ready. It could be that head is not actually in the dom when the append fires.
you don't have to ditch jquery completely, you could use zeptojs. Secondly, I couldn't find out how and why exactly this behavior is happening. Even though i felt answer was to be found in links below. So far i can tell that if you insert element before definig src element then load won't fire.
But for manual insertion it doesn't matter. (????)
However, what i was able to discover is that if you use appendTo it works.
Code :http://jsfiddle.net/techsin/tngxnkk7/
var $ele = $('<script />').attr('src', link).load(function(){ abc(); }) ).appendTo('head');
New Info: As is understood adding script tag to dom with src attribute on it, initiates the download process of script mentioned in src. Manual insertion causes page to load external script, using append or appendTo causes jquery to initiate downloading of external js file. But event is attached using jquery and jquery initiates download then event won't fire. But if it's the page itself initiates the download then it does. Even if event is added manually, without jquery, adding via jquery to dom won't make it fire.
Links in which i think should be the answer...
Append Vs AppendChild JQuery
http://www.blog.highub.com/javascript/decoding-jquery-dommanip-dom-manipulation/
http://www.blog.highub.com/javascript/decoding-jquery-dommanip-dom-manipulation/
https://github.com/jquery/jquery/blob/master/src/manipulation.js#L477-523
http://ejohn.org/blog/dom-documentfragments/

How to execute a function in javascript after an html element is loaded via AJAX without jQuery?

I need to execute a given javascript function after a part of the page is loaded via AJAX. I have no control over how the page loads so trigerring an event from the page is not an option, I suppose I'll need to check the body for the element I need and execute after this element is exists.
I saw that I could do this using jQuery ".on" method, but my jQuery version is from before this feature was introduced so I can't use it. What's the best way to do this using no third-party libraries?
Here's an example using jQuery:
//bind to the body a "load" handler for elements that have class names of "hello"
$('body').on('load','.hello',function(){
alert("Hello is fully loaded, proceed with your program logic");
})
PS: related question that I've read before posting this one. How to bind a function to Element loaded via Ajax
You can create a function to call when the elements are loaded, and another function to check if they are loaded at an interval. Then attach the load checking function to the body's onload attribute. For example:
<body onload="checkLoaded()">
<script type="text/javascript">
var afterLoaded = function() {
// code to execute once elements are in place
console.log("Elements loaded.");
};
var checkLoaded = function() {
var interval = setInterval(function() {
if(document.getElementsByClassName("hello").length) {
clearInterval(interval);
afterLoaded();
}
}, 1000);
};
</script>
Plunker

How to call a function after a div is ready?

I have the following in my javascript file:
var divId = "divIDer";
jQuery(divId).ready(function() {
createGrid(); //Adds a grid to the html
});
The html looks something like:
<div id="divIDer"><div>
But sometimes my createGrid() function gets called before my divIder is actually loaded onto the page. So then when I try to render my grid it can't find the proper div to point to and doesn't ever render. How can I call a function after my div is completely ready to be used?
Edit:
I'm loading in the div using Extjs:
var tpl = new Ext.XTemplate(
'<div id="{divId}"></div>');
tpl.apply({
});
You can use recursion here to do this. For example:
jQuery(document).ready(checkContainer);
function checkContainer () {
if($('#divIDer').is(':visible'))){ //if the container is visible on the page
createGrid(); //Adds a grid to the html
} else {
setTimeout(checkContainer, 50); //wait 50 ms, then try again
}
}
Basically, this function will check to make sure that the element exists and is visible. If it is, it will run your createGrid() function. If not, it will wait 50ms and try again.
Note:: Ideally, you would just use the callback function of your AJAX call to know when the container was appended, but this is a brute force, standalone approach. :)
Thus far, the only way to "listen" on DOM events, like inserting or modifying Elements, was to use the such called Mutation Events. For instance
document.body.addEventListener('DOMNodeInserted', function( event ) {
console.log('whoot! a new Element was inserted, see my event object for details!');
}, false);
Further reading on that: MDN
The Problem with Mutation Events was (is) they never really made their way into any official spec because of inconcistencies and stuff. After a while, this events were implemented in all modern browser, but they were declared as deprecated, in other words
you don't want to use them.
The official replacement for the Mutation Events is the MutationObserver() object.
Further reading on that: MDN
The syntax at present looks like
var observer = new MutationObserver(function( mutations ) {
mutations.forEach(function( mutation ) {
console.log( mutation.type );
});
});
var config = { childList: true };
observer.observe( document.body, config );
At this time, the API has been implemented in newer Firefox, Chrome and Safari versions. I'm not sure about IE and Opera. So the tradeoff here is definitely that you can only target for topnotch browsers.
To do something after certain div load from function .load().
I think this exactly what you need:
$('#divIDer').load(document.URL + ' #divIDer',function() {
// call here what you want .....
//example
$('#mydata').show();
});
Through jQuery.ready function you can specify function that's executed when DOM is loaded.
Whole DOM, not any div you want.
So, you should use ready in a bit different way
$.ready(function() {
createGrid();
});
This is in case when you dont use AJAX to load your div
inside your <div></div> element you can call the $(document).ready(function(){}); execute a command, something like
<div id="div1">
<script>
$(document).ready(function(){
//do something
});
</script>
</div>
and you can do the same to other divs that you have.
this was suitable if you loading your div via partial view

OnSubtreeModified add my function

I use pie.js (http://css3pie.com/) a library that allows me to have css3 on ie6+. I apply pie.js on document.ready :
$(document).ready(function(){
if (window.PIE) {
$('.vexClass, #vexId').each(function(){
PIE.attach(this);
});
}
});
My problem is when the dom was modified the elements for which I have apply pie.js are not rendering well so I must load my function that apply pie.js to my elements when the dom is modified and only for section that was modified using OnSubtreeModified or another technique ... For example I have a panel that is displayed when dom was loaded, in that panel I have a button that is expanding another panel with buttons and other elements for which I want to apply pie.js, so for main panel all elements for which I have applied pie.js are rendered ok but the elements from expanded panel, pie.js is not applied :|
So how can I inject that pie.js when dom is modified for expanded panel?
Thank's.
If you are using wicket the only way to do that is through Wicket.Ajax.registerPostCallHandler
Add this in your project, every time when a ajax request is done your pie will be applied.
window.document.ready = function() {
Wicket.Ajax.registerPostCallHandler(pieStarter);
}
function pieStarter() {
if (window.PIE) {
go();
}
}
function go() {
$(''.vexClass, #vexId'').each(function() {
PIE.attach(this);
});
}
Do you get your data from an Ajax call? If so, you need to add the pie in the callback. There is no possibility (at least afaik) to add anything on something that you don't have at a given time.
If you need to add the pie in the callback, you should make an separate function for that. You can give a dom node to the function and it checks for every child node if pie is applied, and if not it does so.
You can't use the DOMSubtreeModified event since older versions of IE - which you are targeting - don't support this. You can, however, work around this by using this answer Detect changes in the DOM together with this script:
$(document).ready(function () {
function applyPIE() {
if (window.PIE) {
$('.vexClass, #vexId').not('[data-pie=attached]').each(function(){
PIE.attach(this);
$(this).attr('data-pie', 'attached');
});
}
}
onDomChange(function(){
alert('document updated, applying PIE now');
applyPIE();
});
$('#link').click(function () {
$('body').append('<h4>added content</h4>');
});
applyPIE();
});
It creates a local function applyPIE() which is called on document ready and every time the DOM changes - filtering out already processed elements. You may want to expand the .vexClass, #vexId set of selectors to match your needs.
JSFiddle: http://jsfiddle.net/hongaar/y3FaM/1/

onload for div tag

I have div tag, after some event, I insert (change old content) into this tag, several images and also texts, for example:
$("#some_button").on("click", function () {
$("#mydiv").html("<div>aaaa</div><img src='1.jpg'><div>bbb</div><img src='2.jpg'>");
});
I want, that after load "mydiv" tag full content, alert("mydiv contonet is loaded"). That is, some like this:
$("#mydiv").onload( function () {
alert("mydiv contonet is loaded");
});
Tell please, how can this make?
Divs have no onload event. The best you can do is something like this:
<div id="myDiv">I am a div</div>
<script>// do stuff with loaded div</script>
...unless you can/want to specifically address stuff within the div which does support onload, like images.
.html() is a synchronous operation. The actual updating of the DOM depends on what your html content is. If you have <img> or <iframe> tags, they will take time to load. The next statement following the .html() should immediately see the new html contents.
You can have a callback using .load()
http://api.jquery.com/load/
Preload (http://stackoverflow.com/questions/476679/preloading-images-with-jquery) your images then you won't have to worry about this use case.
You'll have to check the loading of the images you have in your div as there is no callback usable in your case.
The typical way is, for each image
to check if the image is loaded (check if (img.width))
add a onload callback on this image
As you have multiple images, you might want a function like this one :
function onLoadAll(images, callback) {
var n=0;
for (var i=images.length; i-->0;) {
if (images[i].width==0) {
n++;
images[i].onload=function(){
if (--n==0) callback();
};
}
}
if (n==0) callback();
}
that you can call like this :
onLoadAll(imagesObj, function(){
// do something with imagesObj when all images are loaded
});

Categories