JS EventListener animationend firing too early - javascript

I need to change the width and height of an element using js with a smooth transition. My idea was to add a class to the element which makes the transition smooth, change the width and height, and once the transition is done, removing the class again. I use the following code:
element.classList.add("smoothTransition")
element.classList.toggle("fullscreen")
element.addEventListener("webkitAnimationEnd", element.classList.remove("smoothTransition"));
element.addEventListener("animationend", element.classList.remove("smoothTransition"));
Sadly no transition is happening. Without the eventListener the transition is happening. Also the eventListener does trigger, right after the transition starts.

Your issue is in your addEventListener:
element.addEventListener("webkitAnimationEnd", element.classList.remove("smoothTransition"));
element.addEventListener("animationend", element.classList.remove("smoothTransition"));
The second argument of addEventListener must be a a function and not the result of a function call (in your case undefined). Hence, change the previous lines to:
element.addEventListener("webkitAnimationEnd", function(e) {
this.classList.remove("smoothTransition")
});
element.addEventListener("animationend", function(e) {
this.classList.remove("smoothTransition")
});
You may consider to add your event listeners before transitions.
document.addEventListener("DOMContentLoaded", function(e) {
var element = document.querySelector('.box');
element.addEventListener("webkitAnimationEnd", function(e) {
this.classList.remove("smoothTransition");
console.log('webkitAnimationEnd');
});
element.addEventListener("animationend", function(e) {
this.classList.remove("smoothTransition");
console.log('animationend');
});
element.classList.add("smoothTransition")
element.classList.toggle("fullscreen")
});
.box {
width: 150px;
height: 150px;
background: red;
margin-top: 20px;
margin-left: auto;
margin-right: auto;
}
#keyframes colorchange {
0% { background: yellow }
100% { background: blue }
}
.smoothTransition {
animation: colorchange 2s;
}
.fullscreen {
width: 100%;
height: 100vh;
}
<div class="box"></div>

Related

How to animate the css zoom property

Is it possible to get a smooth transition for the css zoom property?
I googled a lot, but the results for the keywords "css" and "zoom" are always about transform and transition. So, I don't want to know how to do it with transform and scale and so on. Just with the css zoom property.
document.querySelector('div').addEventListener('click', function(e) {
e.target.classList.toggle('zoom');
});
div {
width: 50px;
height: 50px;
background: red;
cursor: pointer;
}
.zoom {
zoom: 200%;
}
<div>click me!</div>
Non-standard This feature is non-standard and is not on a standards
track. Do not use it on production sites facing the Web: it will not
work for every user. There may also be large incompatibilities between
implementations and the behavior may change in the future.
The non-standard zoom CSS property can be used to control the
magnification level of an element. transform: scale() should be used
instead of this property, if possible. However, unlike CSS Transforms,
zoom affects the layout size of the element.
MDN
So, you can use scale for this.
document.querySelector('div').addEventListener('click', function(e) {
e.target.classList.toggle('zoom');
});
div {
width: 50px;
height: 50px;
background: red;
cursor: pointer;
transition:.5s;
transform-origin:left top;
}
.zoom {
transform:scale(2);
}
<div>click me!</div>
function zoomIn(tg) {
let fr = 100;
setInterval(function() {
if(fr < 200) {
fr++;
tg.style.zoom = fr + "%";
};
}, 5);
}
function zoomOut(tg) {
let fr = 200;
setInterval(function() {
if(fr > 100) {
fr--;
tg.style.zoom = fr + "%";
};
}, 5);
}
document.querySelector('div').addEventListener('click', function(e) {
if(e.target.classList.contains('zoom')) {
e.target.classList.remove("zoom")
zoomOut(e.target);
} else {
e.target.classList.add("zoom");
zoomIn(e.target);
}
});
div {
width: 50px;
height: 50px;
background: red;
cursor: pointer;
transition: .5s;
}
<div>click me!</div>
You can use css transition, for your case:
.zoom {
transition: width 1s, height 1s;
}
Here all times that this width and height div changes will get 1 second

Sliding div out with css and jquery without triggering scrollbar?

I've been wrestling with this for way too long.
Problem: I'm trying to make the image slide off of screen when the button is pressed, which I have successfully done, but not adequately. There are two problems:
I don't want to hide overflow on the body to hide the horizontal scroll being triggered when the div moves off the screen.
When I click on the button for a second time, I want the div to slide in from the right back to the original position. I haven't been able to figure this one out. I know I can do it, but creating another css class, but I know there has to be an easier way.
JSFiddle
CSS:
#abs {
position: absolute;
height: 200px;
width: 200px;
background-color: grey;
left: 0;
top:0;
transition: transform 3s;
}
.open {
transform: translateX(1050px);
}
.hide {
display: none;
}
p {
text-align: center;
}
JS:
$('#clickMe').on('click', function(){
$('#abs').toggleClass('open');
if($("#abs").hasClass("open")) {
setTimeout(
function() {
$("#abs").hide();
},
2500);
} else {
$("#abs").show();
}
})
Hi Please refer to the fiddle.https://jsfiddle.net/cdx7zeo2/1/
I modified your code to use jQuery animate.
$('#clickMe').on('click', function(){
var right = parseInt($('#abs').css('left'));
console.log(right);
if(right === 0){
$( "#abs" ).animate({
left:'2500px'
}, 1500);
}else{
$( "#abs" ).animate({
left:'0px'
}, 1500);
}
})
Also modified the id test to have overflow-y hidden, so that you don't need to tough overflow property of body. Note, here we are not using open class anymore.
#test {
position: relative;
height: 500px;
width: 500px;
background-color: black;
overflow-y:hidden;
}

background image event handler

If a HTML element (e.g. div) has a CSS background image is it possible to assign an event handler that is triggered when the user clicks on the background image, but not any other part of the element?
If so, a JQuery example would be much appreciated.
While it's not possible to detect a click on the background image, you can use some clever JS and CSS wizardry and come up with a masking element over the background image like this: http://jsfiddle.net/ahmednuaman/75Rxu/, here's the code:
HTML:
<div id="bg_img_1"></div>
<div id="bg_img_2">
<div id="hit"></div>
</div>
CSS:
div
{
display: block;
position: relative;
width: 200px;
height: 200px;
background-repeat: no-repeat;
background-position: center center;
}
#bg_img_1
{
background-image: url('http://placekitten.com/100/100');
}
#bg_img_2
{
background-image: url('http://placekitten.com/100/100');
}
#hit
{
display: block;
position: absolute;
width: 100px;
height: 100px;
background: #000000;
opacity: .3;
margin: 50px;
}
JS:
function handleClick(e)
{
console.log(e.target.id);
}
$( '#bg_img_1' ).click( handleClick );
$( '#hit' ).click( handleClick );
I think there is a better and simple way to achieve this here is my solution
$(document).ready(function() {
$("*").click(function(event)
{
if(event.target.nodeName == 'BODY')
{
alert('you have just clicked the body background');
}
});
Here is a very basic code that only work in x axis to show it's possible with injection of an img element with background-image url value as it's src and detecting the background image height and width to calculate if click happened on background image or not.
This code needs tons of improvement. It doesn't work in y axis. Also background-position and background-size are not involved. But it's easy to add those futures.
Here is Fiddle:
And here is jQuery code:
$('#d').bind('click', function(e){
var d = $(this),
bg = {};
//insert an image to detect background-image image size
$('body').append(
$('<img/>').attr('src',
d.css('background-image').split('(')[1].split(')')[0]
).attr('class', 'testImage'));
bg.h = $('.testImage').height();
bg.w = $('.testImage').width();
console.log(bg, e.offsetX, $('.testImage').width());
if(e.offsetX > $('.testImage').width()){
$('#l').text('it was NOT on background-image');
}
else{
$('#l').text('it was on background-image');
}
$('.testImage').hide();
})

mousedown. propagation on siblings event.targets

I have 2 sibling-nodes with 'position absolute' which both handle mousedown event. How can I trigger the handler of 'div 1' when I am clicking on the transparent area of the 'div 2' (on the pic.)
If the overlapping elements are dynamic, I don't believe it is possible to accomplish this using regular event bubbling since the two overlapping elements in question are "siblings".
I had the same problem and I was able to solve it with more of a hitTest scenerio where I test if the user's mouse position is within the same area.
function _isMouseOverMe(obj){
var t = obj.offset().top;
var o = obj.offset().left;
var w = obj.width();
var h = obj.height();
if (e.pageX >= o+1 && e.pageX <= o+w){
if (e.pageY >= t+1 && e.pageY <= t+h){
return true;
}
}
return false
}
You'll want to use 3 event handlers, one for div1, one for div2, and one for contentArea. The contentArea handler should stop propagation so that the div2 handler is not called. The div2 handler should call the div1 handler:
function div1Click (e)
{
// do something
}
function div2Click (e)
{
div1Click.call(div1, e);
}
function contentAreaClick (e)
{
e = e || window.event;
if (e.stopPropagation) e.stopPropagation();
e.cancelBubble = true;
// do something
}
div1.onclick = div1Click;
div2.onclick = div2Click;
contentArea.onclick = contentAreaClick;
What you were looking was CSS's pointer-events property. I didn't make a research to learn whether it was available at the times the question been asked, but that I faced the same thing I'm taking a liberty of covering it.
Here're your two DIVs:
<body>
<div class="inner div-1"></div>
<div class="inner div-2">
<div class="div-2__content-area"></div>
</div>
</body>
Styling:
.inner {
height: 10em;
position: absolute;
width: 15em;
}
.div-1 {
/* Intrinsic styling & initial positioning, can be arbitrary */
background: #ff0;
left: 50%;
top: 50%;
transform: translate(-75%, -75%);
}
.div-2 {
/* Intrinsic styling & initial positioning, can be arbitrary */
background: rgba(0, 255, 0, 0.25);
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
/* Centering content area */
align-items: center;
display: flex;
justify-content: center;
/* Key feature -- making visible part of transparent DIV insensitive to mouse (pointer) events), letting them fire on the underlying element */
pointer-events: none;
}
.div-2__content-area {
/* Styling content area */
background: #f00;
height: 75%;
width: 75%;
/* Reverting 'pointer-events' perception to regular */
pointer-events: auto;
}
Event listeners and displaying:
document.querySelector(".div-1").addEventListener("mousedown", (_) => {
alert("div 1");
});
document.querySelector(".div-2__content-area").addEventListener("mousedown", (_) => {
alert("Content area");
});
This all on codepen:
https://codepen.io/Caaat1/pen/RwZEJVP

jQuery fadeIn fadeOut background problem

When I fadeIn a div, and this animation finished, the background suddenly disappears (this time only in Firefox).
I have a container, with two nested elements in it. The second element has a negative margin, so it appears on top of the first.
My script:
jQuery(document).ready(function($) {
$(".second_element").hide();
$(".container").each(function () {
$(this).mouseover(function () {
$(this).children(".second_element").stop(true, true);
$(this).children(".second_element").fadeIn(250, 'linear');
});
$(this).mouseout(function () {
$(this).children(".second_element").stop(true, true);
$(this).children(".second_element").fadeOut(100, 'linear');
});
});
});
CSS:
.container{
width: 221px;
height: 202px;
display: block;
float: left;
position: relative;
}
.first_element {
height: 200px;
width: 219px;
}
.second_element {
display:none;
background: #fff !important;
margin-top: -51px;
width: 219px;
height: 50px;
}
And for clarity, this a HTML example
<td class="container">
<div id="first_element">...</div>
<div id="second_element">...</div>
</td>
My second problem is, that when my mouse is hovering above the second element, the function is executed again (so the second element fades out and in). While the second element is just IN the container
This is shorter, and also, for first run, it is better that hide target by fadeOut() instead of hide()
$(".caption").fadeOut(1);
$(".container").each(function() {
$(this).mouseover(function() {
$(".caption", this).stop().fadeIn(250);
});
$(this).mouseout(function() {
$(".caption", this).stop().fadeOut(250);
});
});
Complementing the last comments; I got it. I tried it in several ways, and also with the caption to position: absolute, but instead I had to set the first element to position: absolute... now it works (however not with fading, but this is fine). I thank you very much for all your help and support!

Categories