Make a background fade in every time "onclick" - javascript

I would like the DIV to show a confirmed message where the css effect "animation" or "fade out" is activated with each click. It works fine on the first click, but not on the clicks that follow.
function clientedetail() {
document.getElementById("guardadoC").innerHTML = "Guardado.";
document.getElementById("guardadoC").style.cssText = "animation: background-fade 3s;padding:5px;";
}
#keyframes background-fade {
0% {
background-color: green;
}
100% {
background-color: none;
}
}
<input type="button" onclick="clientedetail()"></input>
<div id="guardadoC"></div>

You can add a addEventListener('animationend', function() { ... }); to reset the animation so you can run it again.
It's also a good idea to keep your CSS into your CSS file and not write it as a strings in JavaScript. Now, we are adding a class to the element to do what we want.
function clientedetail() {
var el = document.getElementById("guardadoC");
el.innerHTML = "Guardado.";
el.classList.add("animating");
//This function runs when the CSS animation is completed
var listener = el.addEventListener('animationend', function() {
el.classList.remove("animating");
//this removes the listener after it runs so that it doesn't get re-added every time the button is clicked
el.removeEventListener('animationend', listener);
});
}
#keyframes background-fade {
0% {
background-color: green;
}
100% {
background-color: none;
}
}
#guardadoC {
padding:5px;
}
#guardadoC.animating {
animation: background-fade 3s;
}
<button type="button" onclick="clientedetail()">click me</button>
<div id="guardadoC"></div>

You can use the animationend event to reset the animation.
The animationend event is fired when a CSS Animation has completed
(but not if it aborts before reaching completion, such as if the
element becomes invisible or the animation is removed from the
element).
You'll notice in this demo that I'm not using anonymous functions. With anonymous functions, we end up redefining the function over and over, which is not what you want regarding performance. Using a functional reference, we declare a function once and tie an event to it.
const btn = document.querySelector(".myButton");
const guardadoC = document.getElementById("guardadoC");
btn.addEventListener("click", clientedetail);
function clientedetail() {
guardadoC.innerHTML = "Guardado.";
guardadoC.style.cssText = "animation: background-fade 3s;padding:5px;";
}
function resetAnimation() {
guardadoC.innerHTML = "";
guardadoC.style.cssText = "";
}
guardadoC.addEventListener("animationend", resetAnimation);
#keyframes background-fade {
0% {
background-color: green;
}
100% {
background-color: none;
}
}
<input type="button" class="myButton">
<div id="guardadoC"></div>
jsFiddle
More about animationend

You could recreate the element each time you click the button. This will be a complete reset, and so it will even work when you interrupt the previous animation.
function clientedetail() {
var elem = document.getElementById("guardadoC");
var newElem = elem.cloneNode(true);
elem.parentNode.replaceChild(newElem, elem);
newElem.innerHTML = "Guardado.";
newElem.style.cssText = "animation: background-fade 3s;padding:5px;";
}
#keyframes background-fade {
0% {
background-color: green;
}
100% {
background-color: none;
}
}
<input type="button" onclick="clientedetail()"></input>
<div id="guardadoC"></div>

Trigger it based on class if you can, the way you're doing it it will only do it once.
Or you can destroy the element and re-create it kinda like this.
function clientedetail() {
var element = document.getElementById("guardadoC");
if (typeof(element) != 'undefined' && element != null)
{
document.getElementById("guardadoC").remove();
var remakeDiv = document.createElement("div");
remakeDiv.setAttribute("id", "guardadoC");
document.body.appendChild(remakeDiv)
}
document.getElementById("guardadoC").innerHTML = "Guardado.";
document.getElementById("guardadoC").style.cssText = "animation: background-fade 3s;padding:5px;";
}

Related

I have a js script which should disable a button but it's not working

I have a button which makes an image spin for 3s. I want the button to be disabled during the spinning. But this is not working. Below are the js functions and the css class which creates the spin.
<script>
function spin() {
document.getElementById("spin_switch").disabled = true;
document.getElementById("image-map").classList.toggle("spin");
setTimeout(stop_spin, 3000);
document.getElementById("spin_switch").disabled = false;
}
function stop_spin() {
document.getElementById("image-map").classList.toggle("spin");
}
</script>
<style>
.spin {
transform: rotate(360deg);
webkit-transform: rotate(360deg);
overflow: hidden;
transition-duration: 3s;
transition-property: transform;
}
</style>
You have to move this line
document.getElementById("spin_switch").disabled = false;
into the stop_spin function:
function spin() {
document.getElementById("spin_switch").disabled = true;
document.getElementById("image-map").classList.toggle("spin");
setTimeout(stop_spin, 3000);
}
function stop_spin() {
document.getElementById("image-map").classList.toggle("spin");
document.getElementById("spin_switch").disabled = false;
}
Otherwise the spin_switch will be enabled again immediately. setTimeout does not stop the entire script. It just registers a callback to be executed after the given timeout has expired.

Wait for element to be displayed to user

How do I wait for an element to be displayed/seen by the user? I have the following function, but it only checks to see if the element exists and not whether it is visible to the user.
function waitForElementDisplay (selector, time) {
if (document.querySelector(selector) != null) {
return true;
} else if (timeLimit < timeSince) {
return false;
} else {
timeSince += time;
setTimeout(function () {
waitForElementDisplay(selector, time, timeLimit, timeSince);
}, time);
}
}
It's a bit confuse, are you trying a simple "sleep"?
You can wait element load using:
document.querySelector(selector).onload = function() {
// Your code ...
}
Some working snippet, run it:
// Triggering load of some element
document.querySelector("body").onload = function() {
// Setting the timeout and visible to another element
setTimeout(function () {
document.querySelector("#my_element").style.display = "block" /* VISIBLE */
}, 1000);
}
#my_element{
width: 100px;
height: 100px;
background-color: red;
display: none; /* INVISIBLE */
}
<div id="my_element"></div>
If you want to wait time as you have set to the function and the selector which should appear after this time.. You can mind about a simple setTimeout() and CSS.
Run the example below, hope it helps:
// Triggering, in my exemple i've used: WINDOW ONLOAD
window.onload = function() {
waitForElementDisplay("#my_element", 1000);
}
function waitForElementDisplay (selector, time) {
// Check the DOM Node in console
console.log(document.querySelector(selector));
// If it's a valid object
if (typeof document.querySelector(selector) !== "undifined") {
// Setting the timeout
setTimeout(function () {
document.querySelector(selector).style.display = "block" /* VISIBLE */
}, time);
}
}
#my_element{
width: 100px;
height: 100px;
background-color: red;
display: none; /* INVISIBLE */
}
<div id="my_element"></div>
You could use jQuery .ready()
selector.ready(function(){
// do stuff
})

Avoid mouseover mouseleave conflicts

I'm working with this js fiddle here: http://jsfiddle.net/tPx6x/
The animation works like so
You hover over the text, a circle fades in & begins to pulse 1 second later for as long as your mouse is over the text.
When your mouse pointer leaves the text, the pulse stops after one second and the circle fades out.
The issue arises when you do this:
Put your mouse over the text, remove the pointer from the text, THEN place the pointer back over the text before the script has a chance to finish(1-1.4s).
You won't be able to make the circle appear properly agin...you will have to allow the script to reset. That is the problem.
What is the best way to tackle this issue?
Example code:
<div class='circle__title_project-management'>
<h1>project management</h1>
</div>
<div class='circle__project-management hidden'></div>
.circle__project-management, .circle__title_project-management
{
display: inline-block;
cursor: pointer;
}
.circle__project-management
{
margin-left: 8px;
vertical-align: -4.07px;
background-color: transparent;
border: 2px solid #00DBFF;
width: 30px;
height: 30px;
border-radius: 90px;
top: 280px;
left: 40px;
}
.hidden
{
visibility: hidden;
}
.visible
{
visibility: visible;
}
.animate-infinite
{
animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-webkit-animation-iteration-count: infinite;
}
var circleTitle = $('.circle__title_project-management h1');
var circle = $('.circle__project-management');
var initTimeout = 1000;
var initTimeoutPlus = 1400;
circleTitle.mouseover( function() {
circle.removeClass('hidden');
circle.addClass('animated fadeIn');
setTimeout( function() {
circle.addClass('pulse animate-infinite');
circle.removeClass('fadeIn');
}, initTimeout);
});
circleTitle.mouseleave( function() {
setTimeout( function() {
circle.stop().removeClass('pulse animate-infinite visibility');
circle.addClass('fadeOut');
}, initTimeout);
setTimeout( function() {
circle.removeClass('fadeOut');
circle.addClass('hidden');
}, 1400);
});
You should note that setTimeout has a return value. You want to clear previous timeouts before you start new ones; otherwise you can get a timeout queue which completely skews your animations. Something like this:
var myTimeout;
...
clearTimeout(myTimeout);
myTimeout = setTimeout(...);
Not sure if this is exactly what you were going for, but along these lines: http://jsfiddle.net/FYY38/
More info here: http://www.w3schools.com/js/js_timing.asp
Also, it looks like the circle.stop() call is doing nothing (as it's css-animated)
To avoid antagonist behaviours, maybe add a class to your element to tag it when the event is triggered and remove it when another is triggered.
That way you can stay in control of what's going on.
you can set time out to mouse over function to cover the time delay for mouseleave.
note that the first run must be without delay
var initTimeout = 1000;
var initTimeoutPlus = 1400;
var firstrun = true;
circleTitle.mouseover( function() {
if (firstrun) {
initTimeoutPlus = 0;
firstrun = false;
} else initTimeoutPlus = 1400;
setTimeout(function() {
circle.removeClass('hidden');
circle.addClass('animated fadeIn');
setTimeout( function() {
circle.addClass('pulse animate-infinite');
circle.removeClass('fadeIn');
}, initTimeout);
}, initTimeoutPlus);
});
Probably if you just add a key on mouseover, and toggle it after mouseleave, and before you trigger any mouseleave timeout events, check the key, if it is set, ignore, else go ahead and execute mouseleave
this way if the key is "on" it means a mouse over occurred, if it was off, it means the mouseleave occurred and it is still occurring
var key = false;
circleTitle.mouseover( function() {
key = true;
circle.removeClass('hidden');
circle.addClass('animated fadeIn');
setTimeout( function() {
circle.addClass('pulse animate-infinite');
circle.removeClass('fadeIn');
}, initTimeout);
});
circleTitle.mouseleave( function() {
key = false;
setTimeout( function() {
if (!key){
circle.stop().removeClass('pulse animate-infinite visibility');
circle.addClass('fadeOut');
}
}, initTimeout);
setTimeout( function() {
if (!key){
circle.removeClass('fadeOut');
circle.addClass('hidden');
}
}, 1400);
});

javascript delay popup

im having a prob with javascript which has been bugging me for hours now. I need to delay a css popup so that if you just scroll mouse around page you wont get loads of popups.
Whatever i try it either makes the popup act goofy, poping up after x seconds with a swipe of any link, auto closing etc etc. if i add a timer to the mouseover it starts acting weird, if i then delete the timer for mouseout it works fine but you can no longer mouseover menu before it closes, also tried adding negative margin and it autocloses
cheers all
javscript
<script type="text/javascript">
var span = document.querySelectorAll('.pop');
for (var i = span.length; i--;) {
(function () {
var t;
span[i].onmouseover = function () {
hideAll();
clearTimeout(t);
this.className = 'popHover';
};
span[i].onmouseout = function () {
var self = this;
t = setTimeout(function () {
self.className = 'pop';
}, 300);
};
})();
}
function hideAll() {
for (var i = span.length; i--;) {
span[i].className = 'pop';
}
};
</script>
css
.pop {
position:relative;
}
.pop div {
display: none;
}
.popHover {
position:absolute;
}
.popHover div {
background-color:#FFFFFF;
border-color:#AAAAAA;
border-style:solid;
border-width:1px 2px 2px 1px;
color:#333333;
padding:5px;
position:absolute;
z-Index:9999;
width:150px;
display: inline-block;
margin-top: -20px;
}
Using jquery might be a little more helpful for what you are trying to do. Try something like this:
// Use a CDN to take advantage of caching
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<script type="text/javascript">
var t;
$('.pop').on('mouseover', $.proxy(function () {
hideAll();
clearTimeout(t);
this.addClass('popHover');
this.removeClass('pop');
}, this));
$('.pop').on('mouseout', $.proxy(function () {
var self = this;
t = setTimeout(function () {
self.addClass('pop');
self.removeClass('popHover');
}, 300);
},this));
function hideAll() {
// Since you are calling this from the mouseover function of all the
// elements with the 'pop' class, I dont understand what the purpose of this class
// is so it might not be entirely correct.
$('.pop').addClass('pop');
}
</script>
Let me know if this helps. If you still need it. It would be helpful to have a fiddle to maybe tweak to give you a more accurate response.

How do I clear this setInterval inside a function?

Normally, I’d set the interval to a variable and then clear it like var the_int = setInterval(); clearInterval(the_int); but for my code to work I put it in an anonymous function:
function intervalTrigger() {
setInterval(function() {
if (timedCount >= markers.length) {
timedCount = 0;
}
google.maps.event.trigger(markers[timedCount], "click");
timedCount++;
}, 5000);
};
intervalTrigger();
How do I clear this? I gave it a shot and tried var test = intervalTrigger(); clearInterval(test); to be sure, but that didn’t work.
Basically, I need this to stop triggering once my Google Map is clicked, e.g.
google.maps.event.addListener(map, "click", function() {
//stop timer
});
The setInterval method returns a handle that you can use to clear the interval. If you want the function to return it, you just return the result of the method call:
function intervalTrigger() {
return window.setInterval( function() {
if (timedCount >= markers.length) {
timedCount = 0;
}
google.maps.event.trigger(markers[timedCount], "click");
timedCount++;
}, 5000 );
};
var id = intervalTrigger();
Then to clear the interval:
window.clearInterval(id);
// Initiate set interval and assign it to intervalListener
var intervalListener = self.setInterval(function () {someProcess()}, 1000);
function someProcess() {
console.log('someProcess() has been called');
// If some condition is true clear the interval
if (stopIntervalIsTrue) {
window.clearInterval(intervalListener);
}
}
the_int=window.clearInterval(the_int);
Simplest way I could think of: add a class.
Simply add a class (on any element) and check inside the interval if it's there. This is more reliable, customisable and cross-language than any other way, I believe.
var i = 0;
this.setInterval(function() {
if(!$('#counter').hasClass('pauseInterval')) { //only run if it hasn't got this class 'pauseInterval'
console.log('Counting...');
$('#counter').html(i++); //just for explaining and showing
} else {
console.log('Stopped counting');
}
}, 500);
/* In this example, I'm adding a class on mouseover and remove it again on mouseleave. You can of course do pretty much whatever you like */
$('#counter').hover(function() { //mouse enter
$(this).addClass('pauseInterval');
},function() { //mouse leave
$(this).removeClass('pauseInterval');
}
);
/* Other example */
$('#pauseInterval').click(function() {
$('#counter').toggleClass('pauseInterval');
});
body {
background-color: #eee;
font-family: Calibri, Arial, sans-serif;
}
#counter {
width: 50%;
background: #ddd;
border: 2px solid #009afd;
border-radius: 5px;
padding: 5px;
text-align: center;
transition: .3s;
margin: 0 auto;
}
#counter.pauseInterval {
border-color: red;
}
<!-- you'll need jQuery for this. If you really want a vanilla version, ask -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p id="counter"> </p>
<button id="pauseInterval">Pause/unpause</button></p>

Categories