Show 4 images step by step with effect in javascript - javascript

<!DOCTYPE html>
<html>
<head>
<style>
#steps img{
-webkit-transition: background-image 1.0s linear 0s;
transition: background-image 1.0s linear 0s;
float: left;
display: none;
height: 50px;
width: 50px;
}
</style>
<script>
var i = 0;
var elem;
function nextStep(){
i++;
var img = document.createElement("img");
img.src = "image"+i+".png"
img.width = "50px";
img.height = "50px";
img.id = "step" + i;
document.getElementById("steps").appendChild(img);
elem = document.getElementById(img.id);
elem.style.display = "inline-block";
elem.style.opacity = "0";
setTimeout(slide(),5000);
}
function slide(){
elem.style.opacity = "1";
if(i > 3){
clearTimeout(slide());
clearTimeout(nextStep());
}
setTimeout(nextStep(),5000);
}
</script>
</head>
<body>
<h1>Steps</h1>
<div id="steps">
<script>
nextStep();
</script>
</div>
<p id="text"></p>
</body>
</html>
I have 4 images and i want to create and display them step by step with a css3 effect, it start by executing nextStep() function that creates img child to div and change display and opacity. After that slide() is called, the opacity is set to 1 and we call nextStep() again. when i > 3 we stop displaying. When i test it, it displays the 4 images instantly without any effect
EDIT:
<!DOCTYPE html>
<html>
<head>
<style>
#steps img{
/*
-webkit-transition: background-image 1.0s linear 0s;
transition: background-image 1.0s linear 0s;
*/
float: left;
display: none;
height: 50px;
width: 50px;
}
</style>
<script>
var i = 0;
var elem;
//var slide;
//var nextStep;
function nextStep(){
i++;
var img = document.createElement("img");
img.src = "image"+i+".png"
img.width = "50px";
img.height = "50px";
img.id = "step" + i;
document.getElementById("steps").appendChild(img);
elem = document.getElementById(img.id);
elem.style.display = "inline-block";
//elem.style.opacity = "0";
setTimeout(slide(),2000);
}
function slide(){
//elem.style.opacity = "1";
if(i < 3){
//clearTimeout(slide());
//clearTimeout(nextStep());
setTimeout(nextStep(),2000);
}
}
</script>
</head>
<body>
<h1>Steps</h1>
<div id="steps">
<script>
document.onload = function (){
nextStep();
};
</script>
</div>
<p id="text"></p>
</body>
</html>

You should always wait for the DOM to be fully loaded before doing any operations on it. Use document.onload to execute your script when the document is loaded :
<script>
document.onload = function (){
nextSteps()
};
</script>
Edit :
There is more issues with your code. The clearTimeout function is not needed here. Also, you're not using it right. Quote from the docs at w3schools :
The clearTimeout() method clears a timer set with the setTimeout()
method.
The ID value returned by setTimeout() is used as the parameter for the
clearTimeout() method.
Note: To be able to use the clearTimeout() method, you must use a
global variable when creating the timeout method:
myVar = setTimeout("javascript function",milliseconds); Then, if the
function has not already been executed, you will be able to stop the
execution by calling the clearTimeout() method.
Your slide function should look like this :
function slide(){
elem.style.opacity = "1";
if(i < 3){
setTimeout(nextStep,5000);
}
}
Edit 2 :
setTimeout needs a reference to a function, e.g the name of the function without the parenthesis :
setTimeout(nextStep,5000);
nextStep is a reference to a function
nextStep() is the result returned by the function after its execution (undefined in this case)

Related

Different Zoom effect on Desktop and Mobile

I'm using this JS and CSS to add a zoom effect to header image. It's perfectly working on desktop.
Problem is on mobile hero image is not "filling" the entire container.
So I would need to have 2 different JS with 2 different % settings to make it work both on desktop and mobile.
Is there a solution to make one script with my 2 differents needs you'll find below based on screen size ? "this function is for desktop, and this function is for mobile" ?
For the one who knows I'm using GeneratePress's Elements feature to display hero header entire site.
Here is the JS + CSS working for desktop :
JS
<script>
var pagehero = document.querySelector('.page-hero');
function hero_animation(){
pagehero.style.backgroundSize = 100+'%';
pagehero.style.opacity = '1';
}
document.onload = hero_animation();
</script>
CSS
.page-hero {
transition: background-size 1s cubic-bezier(0.1, 0.135, 0.15, 0.86), opacity 1s ease-out 0.1s !important;
opacity: 0; background-size: 150% auto;
}
Here is the JS + CSS that I would need to add for mobile :
JS
<script>
var pagehero = document.querySelector('.page-hero');
function hero_animation(){
pagehero.style.backgroundSize = 200+'%';
pagehero.style.opacity = '1';
}
document.onload = hero_animation();
</script>
CSS
.page-hero {
transition: background-size 1s cubic-bezier(0.1, 0.135, 0.15, 0.86), opacity 1s ease-out 0.1s !important;
opacity: 0; background-size: 300% auto;
}
Thanks for your help !
You're calling the function when the document html/body is loaded.
<script>
var pagehero = document.querySelector('.page-hero');
function hero_animation(){
pagehero.style.backgroundSize = 100+'%';
pagehero.style.opacity = '1';
}
document.onload = hero_animation();
</script>
Change it to this:
<script>
var pagehero = document.querySelector('.page-hero');
function hero_animation(){
pagehero.style.backgroundSize = 100+'%';
pagehero.style.opacity = '1';
}
document.onload = hero_animation;
</script>
Or this:
<script>
var pagehero = document.querySelector('.page-hero');
function hero_animation(){
pagehero.style.backgroundSize = 100+'%';
pagehero.style.opacity = '1';
}
document.onload = function() { hero_animation() };
</script>
Second, you should change 100/200 to a string. JavaScript is case-sensitive:
pagehero.style.backgroundSize = '100' + '%';
Or
pagehero.style.backgroundSize = (Number(100).toString()) + '%';

jQuery animate function to pure JavaScript

I have this simple jQuery logic, How would I convert that into pure JavaScript?
I have no clue where to start unfortunately. Any help would be extremely appreciated.
$(function() {
// OPACITY OF BUTTON SET TO 0%
$(".rollstate").css("opacity", "0");
// ON MOUSE OVER
$(".rollstate").hover(function() {
// SET OPACITY TO 70%
$(this).stop().animate({
opacity: .5
}, "fast");
},
// ON MOUSE OUT
function() {
// SET OPACITY BACK TO 50%
$(this).stop().animate({
opacity: 0
}, "slow");
});
});
EDIT: a CSS solution would probably work best here, but as a learning purpose I would like to see how the pure JS would work in this case.
You can try the code below. The best would be to declare some CSS and call those by javascript or only use CSS. But as you requested I tried a bit using vanilla javascript.
var element = document.getElementById('rollstate');
element.style.opacity = "0";
element.style.filter = 'alpha(opacity=0)';//for IE
document.getElementById("rollstate").onmouseover = function() {mouseOver()};
document.getElementById("rollstate").onmouseout = function() {mouseOut()};
function mouseOver() {
var element1 = document.getElementById('rollstate');
element1.style.opacity = "5";
element1.style.filter = 'alpha(opacity=5)';
element1.className += 'faded';
}
function mouseOut() {
var element2 = document.getElementById('rollstate');
element2.style.opacity = "0";
element2.style.filter = 'alpha(opacity=0)';
element2.className += 'faded';
}
#rollstate {
-webkit-transition: opacity 1s;
opacity: 1;
}
#rollstate.faded {
opacity: 0;
}
<html>
<body>
<p>hover Below</p>
<input type ="button" id="rollstate" value="click me"/>
</body>
</html>

How can you get the final height on an element transitioning with css?

If you have an element whose height is animating using a CSS transition, is there a way to use jQuery or pure Javascript to get its finished height before the transition completes?
Consider the following example: https://jsfiddle.net/qm6zz0kq/
<div id="test"></div>
<style>
#test {
width: 100px;
height: 0;
transition: height 2s ease-in-out;
background: #F00;
}
#test.showing {
height: 100px;
}
</style>
<script>
var testElement = document.getElementById('test');
setTimeout(function() {
testElement.className = 'showing';
}, 100);
setInterval(function() {
testElement.innerHTML = 'Height: ' + testElement.clientHeight;
}, 100);
</script>
How could you modify the interval so it always generates "Height: 100"?
I've considered doing some kind of jQuery clone that doesn't have to transition and measuring its height but in this instance, the CSS is nested enough that I'd have to clone basically of the element's parents to make sure it's correct and that could be expensive.
You can put another hidden div (hidden-test, as an example) that is the same as the div test and add to it the class showing right away (without timeout), then get its height, that will be the same.
Look here an example: https://jsfiddle.net/qm6zz0kq/1/
You could read the actual CSSRule, note though this would just get the value defined in the CSS. For instance if the height was specified as 70% it would give 70% and not the actual px height it would end up as, eg if parents height was 170px, it wouldn't give you the value of 70% of 170px. Also note this will not work if the stylesheet is include from a file <link href="css.css">
var testElement = document.getElementById('test');
setTimeout(function() {
testElement.className = 'showing';
}, 100);
setTimeout(function() {
var rule = getRule("#test.showing");
if(rule){
testElement.innerHTML = 'Height: ' + rule.style.height;
}
}, 100);
function getRule(selector) {
var foundRule = null;
[].slice.call(window.document.styleSheets)
.filter(sheet=>sheet.rules || sheet.cssRules).forEach(sheet=>{
foundRule = foundRule || [].slice.call(sheet.rules||sheet.cssRules)
.filter(rule=>rule.selectorText == selector);
});
if(foundRule && foundRule[0]) return foundRule[0];
}
#test {
width: 100px;
height: 0;
transition: height 2s ease-in-out;
background: #F00;
}
#test.showing {
height: 100px;
}
<div id="test"></div>
You could also put in an element that is a clone. You do not have to also clone the parents like you mention in your question. You just have to insert the element into the same parent. This particular example uses display:none to hide the element, the returned value will not be a calculated value. Again like above if the parent's height is 400px and the height of the element is 75%, 100px will not be returned, 75% would be.
var clone = testElement.cloneNode();
//remove transition so we can get end height
clone.style.transition = "none";
//display:none so we do not have to see the temp element
clone.style.display = "none";
clone.classList.add("showing");
testElement.parentNode.appendChild(clone);
var endHeight = window.getComputedStyle(clone).height;
var testElement = document.getElementById('test');
setTimeout(function() {
testElement.className = 'showing';
}, 100);
//Clone the element
var clone = testElement.cloneNode();
//remove transition so we can get end height
clone.style.transition = "none";
//display:none so we do not have to see the temp element
clone.style.display = "none";
clone.classList.add("showing");
testElement.parentNode.appendChild(clone);
var endHeight = window.getComputedStyle(clone).height;
//Remove it as we dont need it anymore
clone.remove();
setTimeout(function() {
testElement.innerHTML = 'Height: ' + endHeight;
}, 300);
#parent {
height:300px;
}
#test {
width: 100px;
height: 0;
transition: height 2s ease-in-out;
background: #F00;
}
#test.showing {
height: 70%;
}
<div id="parent">
<div id="test"></div>
</div>
If you want the actual calculated height you would need to change the clone to use a couple different stles.
visibility:hidden to hide it instead of display:none as display will make it so we won't get a calculated value.
position:absolute to prevent it from modifying the parents dimensions
clone.style.visibility = "hidden";
clone.style.position = "absolute";
//needed to make sure element is contained by parent
parent.style.position = parent.style.position || "relative";
var endHeight = window.getComputedStyle(clone).height;
var testElement = document.getElementById('test');
setTimeout(function() {
testElement.className = 'showing';
}, 100);
//Clone the element
var clone = testElement.cloneNode();
//remove transition so we can get end height
clone.style.transition = "none";
clone.style.visibility = "hidden";
clone.style.position = "absolute";
clone.classList.add("showing");
var parent = testElement.parentNode;
parent.style.position = parent.style.position || "relative";
parent.appendChild(clone);
var endHeight = window.getComputedStyle(clone).height;
//Remove it as we dont need it anymore
clone.remove();
setTimeout(function() {
testElement.innerHTML = 'Height: ' + endHeight;
}, 300);
#parent {
height:300px;
}
#test {
width: 100px;
height: 0;
transition: height 2s ease-in-out;
background: #F00;
}
#test.showing {
height: 70%;
}
<div id="parent">
<div id="test"></div>
</div>
You can add an 'animationend' event listener to the element .
Example :
testElement.addEventListener('animationend' , showNewHeight);
showNewHeight function(){
// show new height ...do something after animation .
}
Source : http://www.w3schools.com/jsref/event_animationend.asp
hope this helps..

jQuery loading screen into pure JavaScript

I have this loading screen script that I'd like to implement into a project.
However it requires jQuery. And since none of the elements in the page need jQuery, I'd like to save some space and avoid adding it.
Is there any way I can deliver the exact same function with pure JavaScript?
HTML:
<body onload="hide_preloader();">
<div class="preloader"> <div class="loader"></div> </div>
</body>
jQuery:
jQuery(window).load(function() { rotate = 0; $(".preloader").fadeOut(250); });
Thanks
Yes, this is actually surprisingly easy. You can do the fade with CSS transitions instead.
First, let's define some CSS:
.preloader {
transition: opacity 0.25s linear; /* when we change the opacity, use these transition settings */
}
.preloader.fade {
opacity: 0; /* when we add the class fade, set the opacity to 0 using the above transition */
}
Now we simply have to add the fade class with Javascript:
window.onload = function() {
var preloader = document.getElementsByClassName('preloader')[0];
preloader.className += ' fade';
setTimeout(function(){
preloader.style.display = 'none';
}, 300);
};
Browsers that don't understand transition will set opacity to 0 immediately, while as an absolute failsafe (e.g. for browsers that don't understand opacity) we set display to none after a second for everyone.
jsFiddle showing this effect. (Obviously you will style .preloader differently.)
Try something like this:
// taken from http://stackoverflow.com/q/13733912/2332336
function fade(element) {
var op = 1; // initial opacity
var timer = setInterval(function () {
if (op <= 0.1){
clearInterval(timer);
element.style.display = 'none';
}
element.style.opacity = op;
element.style.filter = 'alpha(opacity=' + op * 100 + ")";
op -= op * 0.1;
}, 50);
}
and this html:
<body onload="fade(document.getElementById('preloader'));">
<div id="preloader"> <div class="loader"></div> </div>
</body>
This should work:
window.onload = function(){
var preloader = document.querySelector('.preloader');
var startTime = new Date().getTime();
function fadeOut(){
var passedTime = new Date().getTime() - startTime;
var opacity = Math.max(250 / (250 - passedTime), 0);
preloader.style.opacity = opacity;
if(opacity){
setTimeout(fadeOut, 0);
}
}
setTimeout(fadeOut, 0);
}

Running a javascript function several times onmouseover

I have a function that moves a box when hovering a button. I would like the function to run over and over again every second as long as the mouse hovers over the button. I have tried loops too but I can't get this to work. I would be very thankful if you would look into this.
Here is my code:
<!DOCTYPE html>
<head>
<style>
#box {
position: relative;
top: 20px;
left: 10px;
width: 50px;
height: 50px;
background:#333366;
}
</style>
<script>
function Start() {
setInterval(Move('box'),1000);
}
var value = 0;
function Move(element) {
value += 50;
var box = document.getElementById(element);
box.style.transition = "left 0.2s ease-in-out 0s";
box.style.left = value+'px';
}
</script>
</head>
<body>
<button onmouseover="Start();">Hover to move</button>
<div id="box"></div>
</body>
</html>
Use this:
setInterval(function(){
Move('box')
},1000);
You have to pass a function to setInterval. You were actually calling Move and passing its return value.
something like this maybe?
http://jsfiddle.net/blackjim/HwKb3/1/
var value = 0,
timer,
btn = document.getElementById('btn');
btn.onmouseover = function(){
timer = setInterval(function(){
// your loop code here
Move('box');
}, 1000);
};
btn.onmouseout = function(){
clearInterval(timer);
}
function Move(element) {
value += 50;
var box = document.getElementById(element);
box.style.transition = "left 0.2s ease-in-out 0s";
box.style.left = value + 'px';
}
Try to see jQuery, it might help you in the beginning.
When this line
setInterval(Move('box'),1000);
is executed, Move('box') is evaluated (and executed one), therefore, your argument to setInterval is the return value for it, that is null
Try this:
var value = 0;
function move(element) {
value += 50;
var box = document.getElementById(element);
box.style.transition = "left 0.2s ease-in-out 0s";
box.style.left = value+'px';
// console.log(box);
}
var button = document.getElementById("buttonID");
button.onmouseover = function() {
this.iid = setInterval(function() {
move("boxID");
}, 1000);
};
button.onmouseout = function() {
this.iid && clearInterval(this.iid);
};

Categories