Long delay when using Modernizr/yepnope - javascript

I'm starting to use Modernizr for my front-end projects these days and just realized something that bugs me.
(Demo link after code snippets)
But first, here's what's before my <body>:
<script src="js/vendor/modernizr.custom.js" type="text/javascript"></script>
<script src="js/loader.min.js" type="text/javascript"></script>
And here's my loader script (removed some lines for brevity):
Modernizr.load([
// jQuery
{
load: '//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js',
complete: function () {
if (!window.jQuery) {
Modernizr.load('js/vendor/jquery-1.11.1.min.js');
}
}
}
// Slick (slideshow)
,{
load: '//cdn.jsdelivr.net/jquery.slick/1.3.9/slick.min.js',
complete: function() {
if (!window.jQuery.fn.slick) {
Modernizr.load('slick/slick.min.js');
}
}
}
// Main script
,'js/script.min.js'
]);
Demo link: http://toki-woki.net/lab/transbal/
I can see the page load and, almost a second after that, my slideshow initializer (wrapped in a $() call) kicks in. That delay is fairly long and unaesthetic, which is what I want to fix.
I've looked at the Network tab in Chrome and see my Modernizr-loaded scripts are first loaded as images (thus, not executing) and then added as script tags and, eventually, executing. That would explain the delay, because jQuery would be executed late (after the DOMContentLoaded event) and the $() call would fire after that.
Some questions:
Is that how Modernizr/yepnope works?
Is it possible to reduce that delay?
What event is used by Modernizr/yepnope to determine when to inject script tags? Looks like it's load but that seems like a strange choice to me...
I've tried not using Modernizr.load at all and reference my script just before the </body> tag and it works perfectly (no slideshow size jumping) but it is harder and heavier to maintain...
Got tips?
Thanks!

Related

How can I reliably run a jquery script after page load

I'm attempting to get some jquery code to run after a sharepoint page loads, the code being:
$(".ms-commentcollapse-icon").click();
I've been using the following to load the code after the page loads, but it does not seem to be very reliable (it will work sometimes and other times it wont):
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<script type="text/javascript">
$(window).load(function () {
$(".ms-commentcollapse-icon").click();
});
</script>
are there any other good methods for achieving this? I'm not sure what's going on, sharepoint could be at fault, but I figured I would try fiddling around with the script a bit more first.
You could use an auto-executing function:
<script type="text/javascript">
(function () {
$(".ms-commentcollapse-icon").click();
} ());
</script>
If this is SharePoint 2010 or above, you can use ExecuteOrDelayUntilScriptLoaded(yourfunction,"SP.JS") to keep your code from firing until after the SP.JS library has loaded (or you can put any other library in the second parameter for a similar effect).
If this is in a web part and you don't want it to execute until other web parts on the page are fully loaded, make sure the web part containing the script is below the other web parts.
As a last resort, you could execute it on a delay using setTimeout or setInterval, but that's ugly.
You can prevent the default behaviour by using e.preventDefault(); within the function.
<script type="text/javascript">
$(".ms-commentcollapse-icon").click(function(e) {
// We're going to stop the default behavior
e.preventDefault();
//some code here
});
</script>

Properly loading scripts and dependencies in correct order using head.js?

I am not sure if I am utilizing head.js correctly. In the header of my html document I call the head.js file via:
<script src="/scripts/head.min.js" type="text/javascript"></script>
Then right before the closing < / body > tag in the html page, I call the following file:
<script src="/scripts/load.js" type="text/javascript"></script>
In the load.js file I have the following code:
head.js(
{livechat: "/scripts/livechat.js"},
{jquery: "http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"},
{jquerytools: "http://cdn.jquerytools.org/1.2.5/full/jquery.tools.min.js"},
{slider: "/scripts/jquery.nivo.slider.pack.js"},
{prettyphoto: "/scripts/jquery.prettyPhoto.js"},
{sliderfunctions: "/scripts/slidercode.js"},
{functions: "/scripts/functions.js"}
);
Does the above code cause the javascript files to execute in the same exact order they are listed or do they sometimes execute out of order?
I ask because the slider initially only functioned if I utilized the following code within load.js:
head.ready("slider", function() {
$('#slider').nivoSlider({
effect:'sliceDown',
controlNav: false
});
});
I was able to get around this by moving the above code to an external file called slidercode.js which contained the following code:
$(window).load(function() {
$('#slider').nivoSlider({
effect:'sliceDown',
controlNav: false
});
});
But I am not sure if I am going about this the correct and most efficient way as this is my first time using head.js. Basically from the javascript files in loader.js I need to make sure:
jquery loads first.
Once jquery has fully loaded then jquerytools loads
After jquery is fully loaded, it should load slider first and then prettyphoto.
Then sliderfunctions should load as it is dependent on slider,
Lastly, functions should load as it is dependent on jquery and jquerytools.
You should call the scripts like this: (remove the http as well, it's not needed. Also Jquery always loads first of any scripts. in this case headJS has priority then jquery then all your scripts)
<script src="/scripts/head.min.js" type="text/javascript"></script>
// this loads asyncrounously & in parallel
head.load("//ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js", "//cdn.jquerytools.org/1.2.5/full/jquery.tools.min.js", "/scripts/jquery.nivo.slider.pack.js", "/scripts/jquery.prettyPhoto.js", "/scripts/slidercode.js", "/scripts/functions.js");
Then right before the closing < / body > tag in the html page, I call the following file:
<script>
head.ready(function () {
// some callback stuff
$('#slider').nivoSlider({
effect:'sliceDown',
controlNav: false
});
});
<script>
Does the above code cause the javascript files to execute in the same
exact order they are listed or do they sometimes execute out of order?
Yea, they load asyn, but execute in order.
I think head.ready("slider", function() {} );should also work even if you place it outside of load.js. Try adding it after load.js script block.

$(document).ready() fires too early

So, I need to know the width of an element with javascript, the problem I have is that the function fires too early and the width changes when the css is tottally applied. As I understood, the $(document).ready() function was fired when the document is completed, but it doesn't seem to work like that.
Anyways, I'm sure that with the code my problem will be understood (this is a simplified example):
<html>
<head>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<link href='http://fonts.googleapis.com/css?family=Parisienne' rel='stylesheet' type='text/css'>
<style type="text/css">
#target {
font-family: 'Parisienne', cursive;
float: left;
}
</style>
</head>
<body>
<div id="target">Element</div>
</body>
</html>
<script type="text/javascript">
$(document).ready(function(){
console.debug($('#target').outerWidth());
alert('hold on');
console.debug($('#target').outerWidth());
});
</script>
I want to know the width of the #target div, the problem is that the code that's executed before the alert gives a different output than the one after, presumably because the font is not fully loaded and it's measuring the div with the default font.
It works as I expect in Google Chrome, but it doesn't on IE and Firefox.
If you rely on external content to be already loaded (e.g. images, fonts), you need to use the window.load event
$(window).on("load", function() {
// code here
});
The behaviour of these events is described in this article:
There is [a] ready-state however known as DOM-ready. This is when the browser has actually constructed the page but still may need to grab a few images or flash files.
Edit: changed syntax to also work with jQuery 3.0, as noted by Alex H
Quote OP:
"As I understood, the $(document).ready() function was fired when the document is completed,"
$(document).ready() fires when the DOM ("document object model") is fully loaded and ready to be manipulated. The DOM is not the same as the "document".
W3C - DOM Frequently Asked Questions
You can try $(window).load() function instead...
$(window).load(function() {
// your code
});
It will wait for all the page's assets (like images and fonts, etc.) to fully load before firing.
The jQuery .ready() function fires as soon as the DOM is complete. That doesn't mean that all assets (like images, CSS etc) have been loaded at that moment and hence the size of elements are subject to change.
Use $(window).load() if you need the size of an element.
The "ready" event fires when the DOM is loaded which means when it is possible to safely work with the markup.
To wait for all assets to be loaded (css, images, external javascript...), you'd rather use the load event.
$(window).load(function() {
...
});
You could use $(window).load(), but that will wait for all resources (eg, images, etc). If you only want to wait for the font to be loaded, you could try something like this:
<script type="text/javascript">
var isFontLoaded = false;
var isDocumentReady = false;
$("link[href*=fonts.googleapis.com]").load(function () {
isFontLoaded = true;
if (isDocumentReady) {
init();
}
});
$(document).ready(function () {
isDocumentReady = true;
if (isFontLoaded) {
init();
}
});
function init () {
// do something with $('#target').outerWidth()
}
</script>
Disclaimer: I'm not totally sure this will work. The <link> onload event may fire as soon as the stylesheet is parsed, but before its external resources have been downloaded. Maybe you could add a hidden <img src="fontFile.eot" /> and put your onload handler on the image instead.
I have absolutely, repeatably seen the same problem in IE9 and IE10. The jquery ready() call fires and one of my <div>'s does not exist. If I detect that and then call again after a brief timeout() it works fine.
My solution, just to be safe, was two-fold:
Append a <script>window.fullyLoaded = true;</script> at the end of the document then check for that variable in the ready() callback, AND
Check if $('#lastElementInTheDocument').length > 0
Yes, I recognize that these are nasty hacks. However, when ready() isn't working as expected some kind of work-around is needed!
As an aside, the "correct" solution probably involves setting $.holdReady in the header, and clearing it at the end of the document. But of course, the really-correct solution is for ready() to work.
The problem $(document).ready() fires too early can happen sometimes because you've declared the jQuery onReady function improperly.
If having problems, make sure your function is declared exactly like so:
$(document).ready(function()
{
// put your code here for what you want to do when the page loads.
});
For example, if you've forgotten the anonymous function part, the code will still run, but it will run "out of order".
console.log('1');
$(document).ready()
{
console.log('3');
}
console.log('2');
this will output
1
3
2

jquery: on demand plugin loading fails if alert not present

I'm using the jQuery Loader plugin to load files on demand- tagit plugin.
The issue is that if I add an alert to the callback function fired on load the plugin loaded seems to work, if I remove the alert, the plugin fails.
Any ideas why is this happening?
$(document).ready(function(){
$("#mytags").Loader(
{
url: [
'media/plugins/tagit/css/jquery-ui/jquery.ui.autocomplete.custom.css',
'http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.9/jquery-ui.min.js',
'media/plugins/tagit/js/jquery-ui/jquery-ui-1.8.autocomplete.min.js',
'media/plugins/tagit/js/tag-it.js'
],
success: function(target) {
//alert('loaded');
$(target).tagit({
availableTags: ["tag1","tag2", "tag3"],
values: ["tag2"]
});
}
}
});
Im testing this on my local XAMP environment.
The possible reason why blocking code execution with alert() helps is that, while JavaScript execution stops (including intervals and timeouts), external resources (JS, CSS, images, and xmlhttprequests) may finish loading. But, again, until the code following the alert() completes, none of these external scripts will run and no DOM events will fire.
An example when alert() makes a difference: http://jsfiddle.net/p9Nff/
It's problaly related with async, do you try to force async to false?
When the alert open the script have time to load your plugins. or it's what Alexey said, your DOM is not ready, put your code into $(function(){ /code here/ });

jQuery not getting called in all browsers

Disclaimer: I am new to jQuery.
I am trying to implement a fadeOut effect in jQuery for a div block, and then fadeIn effect on two other div blocks.
However, these effects are only working in the Chrome browser (i.e. they won't work in Safari, FireFox, Opera) which is rather perplexing to me. I have tried clearing my cache in case it was storing an old file, but none of that seemed to do anything.
Basic idea (stored in mainsite.js file):
$("#videoThumbnail_XYZ").click(function () {
$("#thumbnailDescription_XYZ").fadeOut(300);
$("#videoPlayer_XYZ").delay(300).fadeIn(100);
$("#videoHiddenOptions_XYZ").delay(300).fadeIn(100);
});
So when a div tag with the id of videoThumbnail_XYZ is clicked, it starts the fadeOut and fadeIn calls on the other div tags.
I am loading my javascript files into the page in this order (so jQuery is loaded first):
<script src="http://code.jquery.com/jquery-1.4.4.js"></script>
<script async="" type="text/javascript" src="javascripts/mainsite.js"></script>
Any guidance you could give is greatly appreciated!
Make sure the DOM is fully loaded before your code runs.
A common way of doing this when using jQuery is to wrap your code like this.
$(function() {
$("#videoThumbnail_XYZ").click(function () {
$("#thumbnailDescription_XYZ").fadeOut(300);
$("#videoPlayer_XYZ").delay(300).fadeIn(100);
$("#videoHiddenOptions_XYZ").delay(300).fadeIn(100);
});
});
This is a shortcut for wrapping your code in a .ready() handler, which ensure that the DOM is loaded before your code runs.
If you don't use some means of ensuring that the DOM is loaded, then the #videoThumbnail_XYZ element may not exist when you try to select it.
Another approach would be to place your javascript code after your content, but inside the closing </body> tag.
<!DOCTYPE html>
<html>
<head><title>your title</title></head>
<body>
<!-- your other content -->
<script src="http://code.jquery.com/jquery-1.4.4.js"></script>
<script async="" type="text/javascript" src="javascripts/mainsite.js"></script>
</body>
</html>
If mainsite.js is being included before your div is rendered, that might be throwing the browsers for a loop. Try wrapping this around your click handler setup:
$(document).ready(function(){
// your function here
});
That'll make sure that isn't run before the DOM is ready.
Also, you might consider putting the fadeIn calls in the callback function of your fadeOut, so if you decide to change the duration later on, you only have to change it in one place.
The way that'd look is like this:
$("#thumbnailDescription_XYZ").fadeOut(300,function(){
$("#videoPlayer_XYZ").fadeIn(100);
$("#videoHiddenOptions_XYZ").fadeIn(100);
});
I see you have a delay set to the same duration your fadeOut is, I would recommend instead of delaying which in essence your waiting for the animation to complete that instead you use the callback function.
$("#videoThumbnail_XYZ").click(function () {
$("#thumbnailDescription_XYZ").fadeOut(300, function() {
$("#videoPlayer_XYZ").fadeIn(100);
$("#videoHiddenOptions_XYZ").fadeIn(100);
});
});
While JavaScript provides the load event for executing code when a page is rendered, this event does not get triggered until all assets such as images have been completely received. In most cases, the script can be run as soon as the DOM hierarchy has been fully constructed. The handler passed to .ready() is guaranteed to be executed after the DOM is ready, so this is usually the best place to attach all other event handlers and run other jQuery code.
$(document).ready(function(){
$("#videoThumbnail_XYZ").click(function () {
$("#thumbnailDescription_XYZ").fadeOut(300);
$("#videoPlayer_XYZ").delay(300).fadeIn(100);
$("#videoHiddenOptions_XYZ").delay(300).fadeIn(100);
});
});
All three of the following syntaxes are equivalent:
* $(document).ready(handler)
* $().ready(handler) (this is not recommended)
* $(handler)

Categories

Resources