How to load a Javascript function before the HTML markup ? - javascript

I have a Javascript script that is sort of heavy to load and I noticed that on slower configurations, the script does load after the html markup, and that make my page to not work properly.
Loading the javascript first and then the html markup fixes my issue.
I found simple way to do it with the following :
Javascript :
jQuery(document).ready(function ($) {
$(window).load(function () {
setTimeout(function(){
$('#preloader').fadeOut('slow', function () {
});
},2000);
});
});
html :
<div id="preloader"></div>
<p>EXEMPLE</p>
and finally css :
#preloader {
position: fixed;
left: 0;
top: 0;
z-index: 999;
width: 100%;
height: 100%;
overflow: visible;
background: #333 url('//cdnjs.cloudflare.com/ajax/libs/file-uploader/3.7.0/processing.gif') no-repeat center center;
}
http://jsfiddle.net/harshdand/593Lqqnm/2/
It is jQuery though. I would like to do the same in vanilla JS since I am not proficient with jQuery and for performance reasons.
Any way someone can show me the vanilla JS equivalent of the script or a better way ?

The (document).ready you use is triggered once the DOM is fully loaded.
In your case, as you mentioned, this means that your JS is also loaded.
So basically you're looking at the DOM to see if JS is loaded. I think a nicer solution would be to look at the JS directly an determine from that is you can remove the preloader.
But to answer your question, the vanilla equivalent could be something like this:
According to youmightnotneedjquery.com you could replace the (document).ready part with this:
function ready(fn) {
if (document.attachEvent ? document.readyState === "complete" : document.readyState !== "loading"){
fn();
} else {
document.addEventListener('DOMContentLoaded', fn);
}
}
You could than use this to trigger a CSS change in opacity, and remove the element completely once the opacity animation is done.
var target = document.getElementById('preloader');
target.style.opacity = '0';
setTimeout(function(){target.parentNode.removeChild(target);}, 1000);
In order to make the opacity fade nicely you need to add a transition to the preloader in CSS:
-webkit-transition: opacity 1000ms linear;
transition: opacity 1000ms linear;
Just make sure the animation in the CSS is the same duration as the timeout in the JS.
The complete code would be something like this: http://jsfiddle.net/8ua69dbL/10/

Related

FadeIn animation using CSS3 in Javascript

As jQuery.fadeIn is not very smooth on mobile devices I try to use CSS but it doesn't work as expected. How to create a smooth CSS animation using Javascript?
In general this is what I'm trying:
$('div')
.css('opacity', 0) // at first, set it transparent
.css('display', 'block') // make it appear
.css('transition', 'opacity 1000ms linear') // set a transition
.css('opacity', 1); // let it fade in
https://jsfiddle.net/8xa89y04/
EDIT1:
I'm not searching a solution using static CSS classes. The point is: I need to set this dynamically in Javascript code - a replacement for jQuerys fadeIn() for example.
Your logic isn't quite right. Firstly you cannot animate display, so to achieve what you require the element has to always be rendered in the DOM (ie. anything but display: none). Secondly, the transition property should be placed within the CSS styling itself. Finally you can make this much more simple by setting all the rules in CSS classes and just turning the class on/off. Try this:
div {
position: absolute;
width: 100px;
height: 100px;
background-color: black;
opacity: 0;
transition: opacity 1000ms linear;
}
.foo {
opacity: 1;
}
$('div').addClass('foo');
Working example
Use this code.
CSS
div {
width: 100px;
height: 100px;
background-color: black;
transition:opacity 2s;
}
JavaScript
$('div').hover(function(){
$(this).css('opacity','0');
})
Without using CSS properly, you are going the long way about it. You'll need to emulate what you would normally do in CSS, using JavaScript, so you'll be setting all your CSS properties, transitions etc, then applying them with js.
I can't personally see any benefit in doing this. Using actual CSS would be cleaner, more efficient, more maintainable, and simply a plain better solution to what you need.
I think this is what you are looking for.
$('div').css({"display":"block", "opacity":"0"}) //Make div visible and opacity as "0"
$('div').animate({opacity :1}, 1000); //Animate div to opacity "1"
Take a look at this Demo
Found the cause here: CSS transitions do not work when assigned trough JavaScript
To give this attention I need to give the browser some time - or better: a working slot to activate the transition as the time seems not to be a problem.
The following code cuts the process in two by using setTimeout()... and it works!
var div = $('div');
// first process
div
.css('opacity', 0) // initial opacity
.css('display', 'block') // make it appear (but still transparent)
.css('transition', 'opacity 1s linear'); // set up a transition for opacity
// break - start the transition in a new "thread" by using setTimeout()
window.setTimeout(function(){
div.css('opacity', 1); // start fade in
}, 1); // on my desktop browser only 1ms is enough but this
// may depend on the device performance
// maybe we need a bigger timeout on mobile devices

javascript add additional attribute change

I Have this Javascript:
<script>
$('.tile').on('click', function () {
$(".tile").addClass("flipOutX");
setTimeout(function(){
$(".tile-group.main").css({ marginLeft:"-40px", width: "1080px"}).load("company-overview.html");
}, 2000);
});
</script>
This is great as it loads another page into the current page and that is helpful.
Question is, how can I change the background color of the a class that is already loaded?
The class is called metro as defined in its css that is included and is used to apply the background color of the main page.
EDIT -------
My JS now looks like this and still doesn't work...
<script>
$('.tile').on('click', function () {
$(".tile").addClass("flipOutX");
setTimeout(function(){
$(".metro.tile-area-darkCrimson").css('background-color', '#f36c20');
$(".tile-group.main").css({ marginLeft:"-40px", width: "1080px"}).load("musability-musictherapy-company-overview.html");
}, 2000);
});
</script>
not sure what is wrong any help really appreciated here !
btw the CSS class for .metro.tile-area-darkCrimson looks like this .....
.metro .tile-area-darkCrimson {
min-width: 100%;
height: 100%;
background-color: #1f255b !important;
transition: background-color .25s ease-in-out;
-moz-transition: background-color .25s ease-in-out;
-webkit-transition: background-color .25s ease-in-out;
}
Maybe you should only load a fragment of the company-overview.html page rather then adding another body element.
From https://api.jquery.com/load/
Loading Page Fragments
The .load() method, unlike $.get(), allows us to specify a portion of
the remote document to be inserted. This is achieved with a special
syntax for the url parameter. If one or more space characters are
included in the string, the portion of the string following the first
space is assumed to be a jQuery selector that determines the content
to be loaded.
$( "#result" ).load( "ajax/test.html #container" );
After the content was load you might also add/remove css classes or alter the css by passing a callback function:
Callback Function
If a "complete" callback is provided, it is executed after
post-processing and HTML insertion has been performed. The callback is
fired once for each element in the jQuery collection, and this is set
to each DOM element in turn.
$( "#result" ).load( "ajax/test.html", function() {
$('.my-class', '#result').removeClass('my-class');
});
you can add a callback to your load method:
$(".tile-group.main").css({ marginLeft:"-40px", width: "1080px"}).load(
"company-overview.html",
function() {
$(".metro").css("background-color", "red");
}
);

Why is setTimeout needed when applying a class for my transition to take effect?

I have an element with a transition applied to it. I want to control the transition by adding a class to the element which causes the transition to run. However, if I apply the class too quickly, the transition effect does not take place.
I'm assuming this is because the .shown is placed onto the div during the same event loop as when .foo is placed onto the DOM. This tricks the browser into thinking that it was created with opacity: 1 so no transition is put into place.
I'm wondering if there is an elegant solution to this rather than wrapping my class in a setTimeout.
Here's a snippet:
var foo = $('<div>', {
'class': 'foo'
});
foo.appendTo($('body'));
setTimeout(function(){
foo.addClass('shown');
});
.foo {
opacity: 0;
transition: opacity 5s ease;
width: 200px;
height: 200px;
background-color: red;
}
.foo.shown {
opacity: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Actually, the point is not about the setTimeout, but about how the element is rendered.
The CSS transition will only appear if the element is rendered with a property value, and then this property is changed.
But once you append the element, it does not mean that it was rendered. Simply adding a setTimeout is not enough. Thought it may work for you, in some browser versions it won't work! (Mostly Firefox)
The point is about the element's render time. Instead of setTimeout, you can force a DOM render by requesting a visual style property, and then changing the class:
var foo = $('<div>', {
'class': 'foo'
});
foo.appendTo($('body'));
//Here I request a visual render.
var x = foo[0].clientHeight;
//And it works, without setTimeout
foo.addClass('shown');
.foo {
opacity: 0;
transition: opacity 5s ease;
width: 200px;
height: 200px;
background-color: red;
}
.foo.shown {
opacity: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
When you do DOM manipulation that that javascript relies on immediately afterwards, you need to pause javascript execution briefly in order to allow rendering to catch up, since that will be done asynchronously. All a blank setTimeout does is move the code within to the end of the current execution pipeline. The browser must complete rendering the new layout before it will obey a trigger for your transition so the setTimeout is a good idea and in my opinion the most elegant solution.

Browser caching image prevents fade in

I have a page where I want all my images to fade in once they have loaded, but separately, and I have it working fine using the following...
<style>
img.imgfade {display:none;}
</style>
<script>
$(document).ready(function() {
$('img.imgfade').load(function() {
$(this).fadeIn('slow');
});
});
</script>
The problem I have here, is after navigating away from the page, and then coming back again, the images are no longer there. This is probably because they are already stored in the browser cache, and so are already loaded before my javascript runs.
I've been researching this all afternoon, but can't find an alternative where the images load and fade in seperately. One method I found says to include an .each() function to the .load(). This each can check if an image is already complete and if so just manually call .load() but when I add it, the images don't even load the first time round.
<script>
$(document).ready(function() {
$('img.imgfade').load(function() {
$(this).fadeIn('slow');
});.each(function() {
if(this.complete) {
jQuery(this).load();
}
});
</script>
SOLVED: The question was solved below, so I am sharing my full code incase it helps anyone else. This will fade in your images one at a time as they load, and also will not be affected by the browser caching images when you return to the page.
<style>
img.imgfade {display:none;}
</style>
<script>
(function ($) {
$(document).ready(function() {
$('img.imgfade').load(function() {
$(this).fadeIn('slow');
})
.each(function() {
if(this.complete) {
jQuery(this).load();
}
});
})(jQuery);
</script>
});.each(function() {
try to remove the semicolon ; otherwise your code will raise a syntax error.
Remember to also add a }); for your each(function()... )
So the code becomes
...
})
.each(function() {
if(this.complete) {
jQuery(this).load();
}
});
You can make this happen with modern CSS3 transitions and a onload attribute like so:
<img src="http://www.hdwallpapersfan.com/wp-content/uploads/2013/10/mountain-4.jpg" onload="this.classList.add('show')">
img {
opacity: 0;
-webkit-transition: 1000ms opacity;
-moz-transition: 1000ms opacity;
-ms-transition: 1000ms opacity;
-0-transition: 1000ms opacity;
transition: 1000ms opacity;
}
img.show {
opacity: 1
}
Example
Granted, I used vanilla JS with this.classList which may not be suitable for you if you need older browser support
But you can always swap out for jQuery: $(this).addClass('show')
And here's an example using jQuery to perform the fade in:
<img src="http://www.hdwallpapersfan.com/wp-content/uploads/2013/10/mountain-4.jpg" onload="$(this).fadeIn(1000)">
img {
display: none;
}
Example

Animation with pure javascript, no jquery

I was using jquery/jquery-ui's slideDown() animation function for a particular task. It now transpires that I will not be able to use jQuery in this project. I also cant use YUI or any other libraries. So I wondering is there a way to perform a slideDown style animation using pure javascript?
Edit: I have to do it without jQuery because I am using selenium to control a webpage and on this particular site adding jQuery to the page breaks event handlers for some reason.
You can do slides and animations using CSS3, e.g.
.slidable {
position: relative;
-webkit-animation: Slider 2s ease-in-out;
}
#-webkit-keyframes Slider {
from {
top: 0px;
}
to {
top: 100px;
}
}
Use -moz- for Firefox. Javascript can do movements as well, just put them in timers, e.g.
var top = 0;
window.Timeout(MoveSomething, 10);
function MoveSomething {
var el = document.getElementById('moveme');
top += 2;
el.style.top = top + 'px';
if (top < 100) window.Timeout(MoveSomething, 10);
}
Just takes coding!
The obvious answer is yes...quick question...couldn't you just do an ASYNC load of jQuery into the document and then use it after the fact, or can you not use it because of other limitations?
Worst case you could rip out the part you needed, but that doesn't make much sense. If you can edit any of the JS you could easily paste jQuery just above your code.

Categories