I want to create a delay upon losing focus of a textarea. Currently I have:
<textarea name="description"></textarea>
My CSS reads
.my-form textarea {
height: 35px;
}
.my-form textarea:focus {
min-height: 100px;
}
There is a radio button toggle right beneath this. It gets pushed down because of the extra pixels added on focus, but when trying to click on a button it loses its focus, the height goes back to the original, and you miss the click.
Is there a way to create a delay when losing focus for say 100 ms, just enough to register the click on the buttons?
Using CSS
.my-form textarea {
height: 35px;
transition: height 0.3s ease 1s;
}
.my-form textarea:focus {
min-height: 100px;
}
Using JQUERY
$(document).ready(function () {
$('.my-form textarea').focusin(function () {
$(this).css('height', '100px');
});
$('.my-form textarea').focusout(function () {
setTimeout(function () { $('.my-form textarea').css('height', '35px'); }, 500);
});
});
you can try css3 transition
.my-form textarea {
height: 35px;
transition: width ease 0.3s 0.5s;
}
.my-form textarea:focus {
min-height: 100px;
}
Here is an example: http://jsfiddle.net/689gv/1/
Related
When I click a certain element, I would like to see a confirm appear and fade out. I have achieved this with the below code, but I am not 100% happy, because it cannot be used quickly twice in a row. I need to wait for the text to disappear (and reappear while hidden) before clicking again. There must be a better way to do this kind of magic.
Here is what I did:
$(".hello").click(function() {
var element = $(".conf");
blink(element);
setTimeout(function() {
reset(element);
}, 2000);
});
function blink(element, callback) {
element.css('visibility', 'visible');
element.css('opacity', '0');
}
function reset(element) {
element.css('visibility', 'hidden');
element.css('opacity', '1');
}
.hello {
visibility: visible;
transition: opacity 1s;
}
.conf {
visibility: hidden;
opacity: 1;
border-radius: 5px;
background-color: lime;
color: black;
transition: opacity 1s;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span class="hello">hello</span>
<span class="conf">confirmation</span>
To fix the issue you can hide the element using display: none, then show() it on click and immediately fade it out. If you also call stop() on each event you will stop the fadeOut() animation and set the element back to a fully visible state. Try this:
$(".hello").click(function() {
$(".conf").stop(true, true).show().fadeOut(1000);
});
.hello {
visibility: visible;
transition: opacity 1s;
}
.conf {
display: none;
border-radius: 5px;
background-color: lime;
color: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span class="hello">hello</span>
<span class="conf">confirmation</span>
I have tried out the transitionend and animationend to change my css after a transition or keyframes animation ends. I made an example with both variants and they worked as expected: I can toggle a class, when a transition or animation ends. On hover, I start the transition/animation and in JavaScript I toggle a class, which changes the background-color, after the transition/animation changes.
The only difference is, that when I do the mouseout and the div goes back to the original state, with transition and transitionend, the class will be removed and the original background-color is visible. For keyframes animations and animationend, the class and background-color stay, also when I do the mouseout. How can I get the same behavoir for the animationend like the transition?
var boxTransition = document.getElementById("transition");
var boxAnimation = document.getElementById("animation");
/* add class after transition ends */
boxTransition.addEventListener("transitionend", changeBackground);
/* add class after keyframes animation ends */
boxAnimation.addEventListener("animationend", changeBackground);
function changeBackground() {
this.classList.toggle("box--end");
}
.box {
height: 100px;
margin-bottom: 30px;
width: 100px;
}
.box--transition {
background-color: lightcoral;
transition: width 0.5s ease-in-out;
}
.box--transition:hover {
width: 300px;
}
.box--animation {
background-color: lightblue;
}
.box--animation:hover {
animation: animateWidth 0.5s ease-in-out;
animation-fill-mode: forwards;
}
.box--end {
background-color: gray;
}
#keyframes animateWidth {
from {
width: 100px;
}
to {
width: 300px;
}
}
<div id="transition" class="box box--transition"></div>
<div id="animation" class="box box--animation"></div>
You should note that animation and transition are not the same, Thus event handling here is a bit trikcy.
I am going to explain what happens on both of them.
Transition: It's just the animating part of an element's changing property.
Example, it could be width or height or color. It is assigned on :hover usually.
Thus, it does not wait for animation if a user takes the mouse out of the element before the transition completes.
On the other hand,
Animation: is a complete set of transition and does not care about the user's mouseout event, once starts, it ends on it's own.
So, here is what you can do. As you assigned the toggle on transitionend it's okay because whenever the user takes the mouse out, transition completes and then the event triggers, but for animation, you should take care of them explicitly.
What I did is, (assuming user will keep the mouse on the element for a few second) added the class once animation has ended (like transitionend) then removed the class once the user takes the mouse out of the element.
Not exactly this is what you should do, but you can now get an idea on what to do and when.
Demo:
var boxTransition = document.getElementById("transition");
var boxAnimation = document.getElementById("animation");
/* add class after transition ends */
boxTransition.addEventListener("transitionend", changeBackground);
/* add class after keyframes animation ends */
boxAnimation.addEventListener("animationend", greyOnStart);
boxAnimation.addEventListener("mouseout", revertOnEnd);
function changeBackground() {
this.classList.toggle("box--end");
}
function greyOnStart(){
this.classList.add('box--end');
}
function revertOnEnd(){
this.classList.remove('box--end');
}
.box {
height: 100px;
margin-bottom: 30px;
width: 100px;
}
.box--transition {
background-color: lightcoral;
transition: width 0.5s ease-in-out;
}
.box--transition:hover {
width: 300px;
}
.box--animation {
background-color: lightblue;
}
.box--animation:hover {
animation: animateWidth 0.5s ease-in-out;
animation-fill-mode: forwards;
}
.box--end {
background-color: gray;
}
#keyframes animateWidth {
from {
width: 100px;
}
to {
width: 300px;
}
}
<div id="transition" class="box box--transition"></div>
<div id="animation" class="box box--animation"></div>
I can see 2 options for you.
First one is to call changeBackground on boxAnimation.onMouseOut():
boxAnimation.addEventListener("mouseout", changeBackground);
That will change background immediately.
Second is to set animation for .box--animation without hover:
#keyframes animateWidth2 {
from {
width: 300px;
}
to {
width: 100px;
}
}
.box--animation {
animation: animateWidth2 0.5s ease-in-out;
animation-fill-mode: forwards;
}
That will work like transition, but will happen on start too.
To prevent this happen from start you can add .box--hovered class to .box in changeBackground() and add animation to .box--animation.box--hovered instead of just .box--animation.
Example for second variant.
For some reason when I add the second click function it stops working completely. I was wondering if anybody could help pin point what the issue might be?
What I'm trying to do:
The default state is "day" and when "night" is clicked, it removes the day class and adds the night class. Which changes the background image. Which works... Sort of. However, when I add the function for the day button to add the day class and remove the night class is breaks and doesn't work.
Here's a fiddle of what I have: http://jsfiddle.net/790hqykq/3/
$(document).ready(function () {
$('.night').click(function () {
$('#room').addClass('night');
$('#room').removeClass('day');
});
$('.day').click(function () {
$('#room').addClass('day');
$('#room').removeClass('night');
});
});
Thanks!!
Edit: Also - Is there any way to fade this class change? Similar to fadeIn/fadeOut? Thanks!
jsFiddle Demo
The problem with your fiddle is that the #room element has the class day. So does the anchor element. When the event handler is setup
$('.day').click(function () {
It is also assigned to the room element, and as a result of that, #room ends up also having the event handler attached to it. This causes day to always be selected as the element's class, even when night is clicked.
You should consider changing the class name to something like daycolor and nightcolor
<div id="room" class="daycolor">
and
#room.daycolor {
background: #00CCFF;
}
The element with ID room has the class day, as one of the elements within it.
When you attach the handler, it's being attached to both elements.
This should solve your problem:
$(document).ready(function () {
$('.timeButton.day').click(function () {
$('#room').addClass('day').removeClass('night');
});
$('.timeButton.night').click(function () {
$('#room').addClass('night').removeClass('day');
});
});
As per your complement about fading, you can use CSS 3 to achieve this:
#room {
-webkit-transition: background 0.5s linear;
-moz-transition: background 0.5s linear;
-ms-transition: background 0.5s linear;
-o-transition: background 0.5s linear;
transition: background 0.5s linear;
}
Demo
Change the classnames on your children elements and use that selector for your events.
jsFiddle
HTML:
<div id="container">
<div id="room" class="day">
<a class="timeButton day1">Day</a>
<a class="timeButton night1">Night</a>
</div>
</div>
JS:
$(document).ready(function () {
$('.night1').click(function () {
$('#room').addClass('night');
$('#room').removeClass('day');
});
$('.day1').click(function () {
$('#room').addClass('day');
$('#room').removeClass('night');
});
});
Style:
#container {
width: 300px;
margin: 0 auto;
}
#container a, #container div {
float: left;
display: block;
}
#room {
width: 300px;
height: 200px;
position: relative;
}
#room.day {
background: #00CCFF;
}
#room.night {
background: #0000CC;
}
#room .day1 {
left: 30px;
border: 1px solid black;
}
#room .night1 {
right: 30px;
border: 1px solid black;
}
#room .timeButton {
position: absolute;
width: 80px;
height: 25px;
top: 30px;
cursor: pointer;
text-align: center;
}
#room .timeButton:hover {
background: #fff;
}
Here is another solution, where I just change the css-style via jquery.
Javascript:
$(document).ready(function () {
$('.day').click(function () {
$('#room').css("background-color", "#00CCFF");
});
$('.night').click(function () {
$('#room').css("background-color", "#0000CC");
});
});
Also you need to add a background-color to #room:
background: #00CCFF;
Fiddle:
http://jsfiddle.net/790hqykq/7/
In your script, you reference to ".night" instead ".nightButton".
$('.nightButton').click(function () {
$('#room').addClass('night');
$('#room').removeClass('day');
});
$('.dayButton').click(function () {
$('#room').addClass('day');
$('#room').removeClass('night');
});
To achieve the transition, you can add this CSS propertie to #room.
-webkit-transition: background 2s; /* For Safari 3.1 to 6.0 */
transition: background 2s;
http://jsfiddle.net/790hqykq/13/
you can add css3 for the transitions from day to night.
it wont working in older IE browsers 9 and under but is excellent in all modern browsers.
browser support. You can use this generator to make the code faster.
#room {
width: 300px;
height: 200px;
position: relative;
-webkit-transition: background 1000ms ease-in-out;
-moz-transition: background 1000ms ease-in-out;
-ms-transition: background 1000ms ease-in-out;
-o-transition: background 1000ms ease-in-out;
transition: background 1000ms ease-in-out;
}
Demo jsfiddle
Given an element that has a CSS animation that changes opacity, why does the animation get rerun when the display property changes? How do I stop this from happening?
Example code:
HTML
<div class="foo"></div>
CSS
#-webkit-keyframes fade-in {
0% { opacity: 0; }
100% { opacity: 1; }
}
.foo {
background-color: red;
width: 200px;
height: 200px;
-webkit-animation: fade-in 600ms forwards 0ms ease;
}
.hidden {
display: none;
}
JS
$(function () {
$(".btn").click(function (e) {
e.preventDefault();
$(".foo").toggleClass("hidden")
})
})
JSFiddle
The behavior I am expecting to see is that the animation runs when the DOM renders, but does not rerun when the display property is changed.
One way to do it is to add a class when the button gets clicked that overwrites the animation property.
FIDDLE
$(function () {
$(".btn").click(function (e) {
e.preventDefault();
$(".foo").addClass('finished').toggleClass("hidden")
})
})
.foo.finished {
-webkit-animation: none;
}
Another option would be to hide it with position: relative instead of changing display:
FIDDLE
.hidden {
position: absolute;
left: -99999px;
}
Curious. It seems that Chrome is acting as if changing from display: none to block was the same as adding the element to the DOM. I tried it in Firefox (jsfiddle), and it works as one would expect. IE, however, does the same as Chrome. One could think that Firefox's behaviour is the correct, but, thinking about it, display: none is like taking the node form the layout and rendering trees, so, if the page loads with the object with display: none, and then it changes to block, I would expect to see the animation.
#keyframes fade-in {
0% { opacity: 0; }
100% { opacity: 1; }
}
.foo {
background-color: red;
width: 200px;
height: 200px;
animation: fade-in 3000ms forwards 0ms ease;
}
.hidden {
display: none;
}
this is how you can do that.. its a bit hacky but you can remove that class and add another class that doesn't have the animation. $("#my_foo").removeClass("foo").addClass("your_foo");
http://jsfiddle.net/s68yf/6/
I was wondering if you can offer me a better way of achieving the effect Ive created in this fiddle: http://jsfiddle.net/YLuKh/1/
Basically I would like to animate the background colour of the anchor tag revealing an image which I've done by positioning an anchor tag on top of a span on top of an image and then on hover animate the width of the span. Can anyone suggest a more straight forward way of doing this?
HTML
<ul id="test">
<li>
This is the link
<span class="bg"></span>
<img src="http://www.ritaxxii.org/wp-content/uploads/Luxury-Bedroom-Furniture-1.jpg" />
</li>
</ul>
JS
$(document).ready(function() {
var li_width = $('#test').find('li').width();
console.log(li_width);
$('#test').find('li').on('mouseover', function() {
$(this).find('.bg').stop().animate({
width: '0'
}, 200);
}).on('mouseout', function() {
$(this).find('.bg').stop().animate({
width: li_width
}, 200);
});
});
As I mentioned in the comments you can use the background position to do the animation. Here's a simple one using only background image positioning ( http://jsfiddle.net/3PESX/ )
$('a').mouseenter(function() {
$(this).stop().animate({ 'background-position-x': '-700px'}, 300);
});
$('a').mouseleave(function() {
$(this).stop().animate({ 'background-position-x': '0'}, 300);
});
a {
display: inline-block;
height: 50px;
width: 300px;
background: transparent url(http://jtrujillo.net/digital-photo-tutorials/8vs16bit/dgr1.jpg) 0 top no-repeat;
color: grey;
text-decoration: none;
line-height: 50px;
}
This is a link text
Beware that the background-position property is a composition of the x and y version. You cannot animate composite properties, you'll need to animate the X and Y version seperately. Alternatively you can use a css hook plugin that makes it possible. You can find those here: https://github.com/brandonaaron/jquery-cssHooks
You can get a referance from this : http://snook.ca/archives/javascript/jquery-bg-image-animations
May I suggest a CSS3-only means of achieving what I think you're trying to do:
li {
border: 1px solid #f90;
width: 504px; /* width of the image, adjust to taste */
overflow: hidden;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-o-box-sizing: border-box;
box-sizing: border-box;
}
li a {
display: block;
position: relative;
width: 100%;
height: 2em;
line-height: 2em;
color: #fff;
background-color: #000;
-webkit-transition: width 1s linear;
-moz-transition: width 1s linear;
-o-transition: width 1s linear;
-ms-transition: width 1s linear;
transition: width 1s linear;
}
li:hover a {
width: 0;
-webkit-transition: width 1s linear;
}
li a::after {
content: url(http://www.ritaxxii.org/wp-content/uploads/Luxury-Bedroom-Furniture-1.jpg);
position: absolute;
top: 0;
right: 0;
left: 100%;
bottom: 0;
}
JS Fiddle demo.
If you're going to have a lot of list items, you might want to consider event delegation to the #test element so you dont have to attach a bunch of different event listeners to each li tag
//attach one event listener for 'mouseover' and one for 'mouseout' on the test element
$('#test').on('mouseover', 'li', function(){
//'this' is still the li element
console.log( $(this));
$(this).find('.bg').stop().animate({width: '0'},200);
}).on('mouseout', 'li', function(){
$(this).find('.bg').stop().animate({width: li_width},200);
});