jQuery know first transition has been done then make the 2nd one - javascript

In Jquery I am doing a small animation. In that I have taken two divs. So basically the logic is like this when mouse will be hovered it will show one hidden div with transition. The same concept goes for the 2nd div. But my problem is when I am doing hover on 1st div its showing the hidden div in transition. But when I am doing hover on another div the first hidden is hiding and the 2nd hidden div is showing in the 2nd div. So I want that when I will hover on the 2nd div then the 1st hidden div should hide first then the 2nd hidden div will be shown.
Here is my code so far
<div id="wrapper">
<div class="courses-method-left-wrapper">
<div class="courses-method-wrap left">
<p>It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem </p>
</div>
<div class="online-course-price-wrap">
<h3>Left content wrap</h3>
<h6>Left content text</h6>
</div>
</div>
<div class="courses-method-right-wrapper">
<div class="courses-method-wrap right">
<p>It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem </p>
</div>
<div class="offline-course-price-wrap">
<h3>Right content wrap</h3>
<h6>Right content text</h6>
</div>
</div>
</div>
My css so far
#wrapper {
width: 100%;
clear: both;
overflow: hidden;
background: #D7DFE6;
position: relative;
}
.courses-method-left-wrapper, .courses-method-right-wrapper {
width: 45%;
padding: 10px;
overflow: hidden;
float: left;
position: relative;
}
.courses-method-wrap.left {
float: left;
position: relative;
left: 0px;
}
.courses-method-wrap.right {
position: relative;
}
.online-course-price-wrap {
width: 230px;
background: #1C2C39;
position: absolute;
right: -230px;
height: 200px;
}
.offline-course-price-wrap {
left: -200px;
z-index: 0;
width: 200px;
position: absolute;
height: 100%;
top: 0px;
background: #ccc;
height: 200px;
}
.hovered .online-course-price-wrap { right: 0px; }
.hovered .offline-course-price-wrap { left: 0px; }
#wrapper * {
-webkit-transition: all 0.7s ease-out;
transition: all 0.7s ease-out;
-moz-transition: all 0.7s ease-out;
}
and js code is like this
jQuery('body').on('hover','.courses-method-left-wrapper, .courses-method-right-wrapper', function(){
jQuery(this).toggleClass('hovered');
});
Here is the fiddle link
So can some one tell me how to make one transition complete after that another should be start or How can I check the first animation has been done so that the 2nd will be start? Any help and suggestions will be really appreciable. Thanks

A quick solution to your problem would be to use a delay of 700ms to match the 0.7s in your transition like so:
jQuery(this).toggleClass('hovered', function(){
setTimeout(function(){
alert('done');
}, 700);
});
http://jsfiddle.net/aym037ge/2/
This is not an elegant solution, but one nonetheless.
The other option would be to use the transition events as mentioned before and here:
Callback on CSS transition

You can take advantage of the transitioned event with jQuery, to capture when the transition has ended.
jQuery('.courses-method-left-wrapper').mouseenter(function ()
{
//If the previous div is already hovered...
if($('.courses-method-right-wrapper').hasClass('hovered'))
{
$('.courses-method-right-wrapper').removeClass('hovered');
$('.courses-method-right-wrapper').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function () {
$('.courses-method-left-wrapper').addClass('hovered');
});
}
else // The previous div isn't hovered (i.e. on page load...)
{
$('.courses-method-left-wrapper').addClass('hovered');
}
});
jQuery('.courses-method-right-wrapper').mouseenter(function ()
{
//If the previous div is already hovered...
if($('.courses-method-left-wrapper').hasClass('hovered'))
{
$('.courses-method-left-wrapper').removeClass('hovered');
$('.courses-method-left-wrapper').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function () {
$('.courses-method-right-wrapper').addClass('hovered');
});
}
else // The previous div isn't hovered (i.e. on page load...)
{
$('.courses-method-right-wrapper').addClass('hovered');
}
});
Vendor prefixes added for full compatibility, including two for Opera
You can see the code in action in this fiddle I prepared. It can be improved (if you move the mouse too much, the two hidden divs may show up until you hover again) but it should give you a nice head-start.

Related

Why does reflow need to be triggered for CSS transitions?

I was reading this article http://semisignal.com/?p=5298 and the author wrote that
"Reflow needs to be triggered before the invisible class is removed in order for the transition to work as expected. "
My questions are :
1) Why does reflow need to be triggered?
2) I understand that we should avoid using reflow, if that is true why is the author suggesting to use reflow in order to make the transition work?
3) Instead of using reflow, is there a different method to make the transition work?
Thank you.
(Effectively: "Why can't I easily use transitions with the display property")
Short Answer:
CSS Transitions rely on starting or static properties of an element. When an element is set to display: none; the document (DOM) is rendered as though the element doesn't exist. This means when it's set to display: block; - There are no starting values for it to transition.
Longer Answer:
Reflow needs to be triggered because elements set to display: none; are not drawn in the document yet. This prevents transitions from having a starting value/initial state. Setting an element to display: none; makes the document render as if the element isn't there at all.
He suggest reflowing because it's generally accepted to hide and show elements with display: none; and display: block; - typically after the element has been requested by an action (tab or button click, callback function, timeout function, etc.). Transitions are a huge bonus to UX, so reflowing is a relatively simple way to allow these transitions to occur. It doesn't have an enormous impact when you use simple transitions on simple sites, so for general purposes you can trigger a reflow, even if technically you shouldn't. Think of the guy's example like using unminified JavaScript files in a production site. Can you? Sure! Should you? Probably not, but for most cases, it won't make a hugely noticeable difference.
There are different options available that prevent reflowing, or are generally easier to use than the method in the link you provided. Take the following snippet for a few examples:
A: This element is set to height: 0; and overflow: hidden;. When shown, it's set to height: auto;. We apply the animation to only the opacity. This gives us a similar effect, but we can transition it without a reflow because it's already rendered in the document and gives the transitions initial values to work with.
B: This element is the same as A, but sets the height to a defined size.
A and B work well enough for fading in elements, but because we set the height from auto/100px to 0 instantly, they appear to collapse on "fade out"
C: This element is hidden and we attempt to transition the child. You can see that this doesn't work either and requires a reflow to be triggered.
D: This element is hidden and we animate the child. Since the animation keyframes give a defined starting and ending value, this works much better. However note that the black box snaps into view because it's still attached to the parent.
E: This works similarly to D but we run everything off the child, which doesn't solve our "black box" issue we had with D.
F: This is probably the best of both worlds solution. We move the styling off the parent onto the child. We can trigger the animation off of the parent, and we can control the display property of the child and animate the transition as we want. The downside to this being you need use animation keyframes instead of transitions.
G: While I don't know if this triggers a reflow inside the function as I haven't parsed it myself, you can just simply use jQuery's .fadeToggle() function to accomplish all of this with a single line of JavaScript, and is used so often (or similar JS/jQuery fadeIn/fadeOut methods) that the subject of reflowing doesn't come up all that often.
Examples:
Here's a CodePen: https://codepen.io/xhynk/pen/gerPKq
Here's a Snippet:
jQuery(document).ready(function($){
$('button:not(#g)').click(function(){
$(this).next('div').toggleClass('show');
});
$('#g').click(function(){
$(this).next('div').stop().fadeToggle(2000);
});
});
* { box-sizing: border-box; }
button {
text-align: center;
width: 400px;
}
div {
margin-top: 20px;
background: #000;
color: #fff;
}
.a,
.b {
overflow: hidden;
height: 0;
opacity: 0;
transition: opacity 3s;
}
.a.show {
height: auto;
opacity: 1;
}
.b.show {
height: 100px;
opacity: 1;
}
.c,
.d {
display: none;
}
.c.show,
.d.show {
display: block;
}
.c div {
opacity: 0;
transition: 3s all;
}
.c.show div {
opacity: 1;
}
.d div {
opacity: 0;
}
.d.show div {
animation: fade 3s;
}
#keyframes fade {
from { opacity: 0; }
to { opacity: 1; }
}
.e div {
display: none;
}
.e.show div {
display: block;
animation: fade 3s;
}
.f {
background: transparent;
}
.f div {
background: #000;
display: none;
}
.f.show div {
display: block;
animation: fade 3s;
}
.g {
display: none;
}
<button id="a">A: Box Height: Auto</button>
<div class="a">This<br/>Has<br/>Some Strange<br/><br/>Content<br>But<br>That doesn't really<br>Matter<br/>Because shown,<br/>I'll be<br/>AUTO</div>
<button id="b">B: Box Height: 100px</button>
<div class="b">Content For 2</div>
<button id="c">C: Hidden - Child Transitions (bad)</button>
<div class="c"><div>Content<br/>For<br/>3<br/></div></div>
<div style="clear: both;"></div>
<button id="d">D: Hidden - Child Animates (Better)</button>
<div class="d"><div>Content<br/>For<br/>4<br/></div></div>
<div style="clear: both;"></div>
<button id="e">E: Hidden - Child Hidden & Animates</button>
<div class="e"><div>Content<br/>For<br/>5<br/></div></div>
<button id="f">F: Child Has BG & Animates (Works)</button>
<div class="f"><div>Content<br/>For<br/>5<br/></div></div>
<div style="clear: both;"></div>
<button id="g">G: This uses fadeToggle to avoid this</button>
<div class="g">I animate with<br/>JavaScript</div>
<footer>I'm just the footer to show the bottom of the document.</footer>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Creating multiple instances of the same id

I have a question I can't seem to figure out myself.
Say I have created a paragraph that says "+1". When I click a button that already exists in my code, I can make this paragraph appear above the button and I can transform it so that it's 'y' increases and it moves up while fading slowly.
So, you click the button, a +1 appears above and moves up while fading.
How do I make it so I can create a new instance of this +1 without removing the first one if I click the button before the first one has a chance to disappear?
So, if I clicked the button really fast, a stream of +1's would appear above the button and slowly fade out, one by one. Any idea of how I would go about doing this?
Thank you!!
Here's a solution using jQuery:
$('button').on('click', function() {
var $newPlus = $('<div class="plus">+1</div>');
$('#area').append($newPlus);
setTimeout(function(){ $newPlus.addClass('fade'); }, 50);
setTimeout(function(){ $newPlus.remove(); }, 650);
});
#area {
position: relative;
padding: 70px;
}
#area .plus {
position: absolute;
left: 100px;
top: 50px;
opacity: 1;
transition: top 300ms ease-out, opacity 600ms ease-in-out;
}
#area .plus.fade {
top: 0px;
opacity: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="area">
<button>Plus One</button>
</div>

Javascript - Reversing a Modal Animation

I have a few items on a site I'm building that onclick activate a modal like this.
Right now the animation is a one-way in that, when you close it or click off from the modal's focus, it just disappears. From what I've been reading, people seems to use the fadeIn/slideIn animation for one time effects, but is it possible, to reverse the animation so instead of just changing display to none, it slides back out?
#modal{bottom: 0; opacity: 1; transition: bottom 400ms, opacity 400ms; }
#modal.hidden{bottom: -300px; opacity: 0}
Then in button click event:
$("#modal").addClass("hidden")
On close event:
$("#modal").removeClass("hidden")
If you need pure javascript, it would be a bit more code but essentially that's it
Depending on how you've structured your code, you can approach this in a few ways:
Make use of the animation-direction: reverse; CSS property
Use a Javascript framework (like jQuery) that enables manipulation of DOM elements (with jQuery you could do something like: $('element').slideIn(); to show the modal and $('element').slideOut(); to hide the modal).
Use CSS classes and apply / unapply them with Javascript (the option I'd recommend, and have given an example below):
$(document).ready(function() {
$('.open').on('click', function(e) {
e.preventDefault();
if ($('.modal').hasClass('hide')) {
$('.modal').removeClass('hide');
}
$('.modal').addClass('show');
});
$('.close').on('click', function(e) {
e.preventDefault();
$('.modal').addClass('hide');
if ($('.modal').hasClass('show')) {
$('.modal').removeClass('show');
}
});
});
.modal {
position: fixed;
top: 0;
left: 0;
width: 300px;
height: 300px;
left: -305px;
z-index: 999;
transition: all 0.3s ease;
background: #ffffff;
border: 1px solid blue;
}
.modal.show {
left: 150px;
}
.modal.hide {
left: -305px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>Click here to open modal</p>
<div class="modal">
<p>This is a modal window.</p>
<p>Click here to close</p>
</div>
Please note that this example is only there to illustrate a proof of concept - you'll need to tidy it yourself :)

How can I add click events with JavaScript (or CSS) on iOS devices?

I’m having trouble with a hover technique I’m trying to implement on a site. Basically, I have div (.portfolio-item) which is used to display a background-image. The .portfolio-item contains one direct child — <div class="portfolio-item-info"> which is absolutely positioned and is only shown when the user hovers over the parent element.
This works fine on laptops and Android devices but for iOS devices it doesn’t work at all. So if the user touches the .portfolio-item div, nothing happens.
HTML
<div class="portfolio-item" style="background-image: url('path/to/url')">
<div class="portfolio-item-info">
<h3 class="font-secondary-bold">Some Title</h3>
<ul class="list-unstyled list-inline">
<li>Publication</li>
<li>Print</li>
</ul>
Take a look
</div>
</div>
CSS
.portfolio-item {
background-color: #fff;
background-size: cover;
margin-bottom: 24px;
overflow: hidden;
position: relative;
min-height: $portfolioItemHeight;
&:before {
content: "";
background-color: $colorLight;
background-color: rgba(255, 255, 255, 0.8);
min-height: $portfolioItemHeight;
opacity: 0;
position: absolute;
left: 0;
right: 0;
transition: opacity 0.5s ease-in-out;
}
&:hover,
&:focus {
&:before {
opacity: 1;
}
.portfolio-item-info {
top: 0;
}
}
}
To make it work I’m using something really hacky, I’m putting an onclick attribute on the .portfolio-item div e.g.
<div class="portfolio-item" onclick="void(0)" style="background-image: url('path/to/url')">
This hacky solution does work but I’d ideally like something less… hacky.
No standard defines how touch devices should deal with hover and it's up to the browser vendor, so any solution will be a kind of 'hack'. However, the following one is more reliable:
Using jQuery you can turn the class hover on / off on touch start / end
$(document).ready(function() {
$('.portfolio-item').bind('touchstart touchend', function(e) {
e.preventDefault();
$(this).toggleClass('hover');
});
});
In CSS you add the .hover class with the same parameters as existing :hover.

Change how fast "title" attribute's tooltip appears

Is there a way to change how fast the tooltip from an element's "title" attribute? I'd like it if the tooltip appeared immediately, but it seems to take a few seconds to appear.
No, there's no way. The title attribute is implemented in a browser dependent fashion. For example I remember differences between IE and FF when using \r\n inside it.
Mozilla's docs explain the limits and functionality well.
If you want customization you may take a look at third party plugins such as qTip2 which mimic it using divs and stuff and provide you full control.
You could use jqueryUI as suggested. An example of controlling the duration on the show property:
$( ".selector" ).tooltip({ show: { effect: "blind", duration: 800 } });
Jquery UI tooltip is extremely simple and customizable: Just download or include jquery UI in your page.
If you want all the tooltips of your page to show immediately at hover, just use this:
$(document).tooltip({show: null});
Note that this applies to all elements that have a 'title' attribute.
You can modify the selector to affect only a class, and set custom speed or effect:
$('.yourClass').tooltip({show: {effect:"none", delay:0}});
Unfortunately, there is no way to do this yet,
so I am using the following methods to help. (No dependencies required)
<style>
[title] {
position: relative;
}
[title]:after {
content: attr(title);
position: absolute;
left: 50%;
bottom: 100%; /* put it on the top */
background-color: yellow;
width: max-content;
opacity: 0;
-webkit-transition: opacity 0.75s ease-in-out; /* 👈 Change the time to meet your requirements. */
}
[title]:hover:after {
opacity: 1;
}
</style>
<div style="min-height:5rem"></div>
<div style="min-width: 5rem; border: 2px solid red;" title="hello world">my div</div>
<button title="for debug">button</button>
If you don't want the title to conflict with it, you can use data-* w3school.data-* help you, for example.
<style>
[data-tooltip] {
position: relative;
}
[data-tooltip]:after {
content: attr(data-tooltip);
position: absolute;
left: 50%;
bottom: 100%; /* put it on the top */
background-color: yellow;
width: max-content;
opacity: 0;
-webkit-transition: opacity 0.75s ease-in-out;
}
[data-tooltip]:hover:after {
opacity: 1;
}
div[data-tooltip]:after {
left: 5px!important;
}
</style>
<div style="min-height:5rem"></div>
<div style="min-width: 5rem; border: 2px solid red;" data-tooltip="hello world">my div</div>
<button data-tooltip="for debug">button</button>
<button title="for debug">title only</button>
<button data-tooltip="my tool tip msg" title="my title msg">title and tooltip</button>
below link may help you too.
fade in and out on simple css tooltip
It isn't possible to change how fast default browser's tooltip appear, but you can use one of the tooltip plugins (here is few: http://www.1stwebdesigner.com/css/stylish-jquery-tooltip-plugins-webdesign/ ) where you can customise lot's of things, including delay.
TippyJS has a billion customization options.
https://atomiks.github.io/tippyjs
https://github.com/atomiks/tippyjs

Categories