jQuery - Click Add/Remove Class - Multiple Buttons - javascript

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

Related

Remove class added with hover and animationend on mouseout

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.

Jquery evenly resize anchor text

I am trying to evenly increase and then decrease the font size of anchor text inside a paragraph without moving the paragraph text. This way the anchor text will look as if it is coming toward the user and then receding back into its original place. The font-size also appears as if it is growing from the lower left corner as opposed to what I want which is evenly from all sides.
HTML:
<p>
<a>[D]</a>I've been workin' on the railroad,
<a>[G]</a>all the live long <a>[D]</a>day.
<a>[D]</a>I've been workin' on the railroad,
just to <a>[E]</a>pass the time a<a>[A]</a>way.
</p>
CSS:
p {
white-space: pre-wrap;
}
a {
-webkit-transition: all .5s ease-in-out;
-moz-transition: all .5s ease-in-out;
-ms-transition: all .5s ease-in-out;
-o-transition: all .5s ease-in-out;
transition: all .5s ease-in-out;
color:red;
}
.increase-font {
font-size: 30px;
background:#FFF;
}
Jquery/Javascript:
$('a').on('click',function(e){
e.preventDefault();
var el = this;
$(el).addClass('increase-font');
setTimeout(function(){
$(el).removeClass('increase-font');
},1000);
});
Here is the fiddle:
https://jsfiddle.net/scooke/ro2tyf6h/
To achieve this, the anchor texts need to be somewhat independent from the parent. Inserting the anchor text with CSS :before or :after selectors will solve the problem. See my example and adjust as needed.
$('a').on('click', function(e) {
e.preventDefault();
var el = this;
$(el).addClass('increase-font');
setTimeout(function() {
$(el).removeClass('increase-font');
}, 1000);
})
p {
white-space: pre-wrap;
padding-left: 30px;
display: inline-block;
width: 100%;
position: relative;
}
a {
-webkit-transition: all .5s ease-in-out;
-moz-transition: all .5s ease-in-out;
-ms-transition: all .5s ease-in-out;
-o-transition: all .5s ease-in-out;
transition: all .5s ease-in-out;
color: red;
display: inline-block;
position: relative;
width: 30px;
height: 10px;
}
a:before {
content: "[D]";
position: absolute;
left: 0;
text-align: center!important;
width: 100%;
top: -5px;
}
.increase-font {
font-size: 30px;
background: #FFF;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p> <a></a>I've been workin' on the railroad,</p>
<p><a></a>all the live long <a></a>day.</p>
<p><a></a>I've been workin' on the railroad, just to <a></a>pass the time a<a></a>way.</p>
Suggestions:
Restructuring your HTML will be a good start
Adding a background to the :hover state will help keep it clean
and distinguishable.
It's relatively simple - just wrap the anchor tags in span tags:
<p><a><span>[D]</span></a>I've been workin' on the railroad,</p>
<p><a><span>[G]</span></a>all the live long <a><span>[D]</span></a>day.</p>
<p><a><span>[D]</span></a>I've been workin' on the railroad, just to <a><span>[E]</span></a>pass the time a<a><span>[A]</span></a>way.</p>
Set the anchor's position to relative (with a margin to give its children spans room), whilst also setting span tags to absolute:
a {
position: relative;
max-height: 0px;
max-width: 0px;
margin-right: 25px;
}
span {
position: absolute;
top: 0;
left: 0;
}
Then just swap the jQuery event handler from registering on all anchor tags to all span tags:
$('span').on('click',function(e){
e.preventDefault();
var el = this;
$(el).addClass('increase-font');
setTimeout(function(){
$(el).removeClass('increase-font');
},1000);
})
Seeing as absolute elements are removed from the DOM flow, resizing the spans doesn't effect the elements around it. Full code here:
https://jsfiddle.net/ro2tyf6h/5/

How to zoom out a div using animations?

I have a DIV that is covering the whole page (height and width are 100%). I am trying to use CSS (and possibly JavaScript) to create a zoom out animation effect so the DIV is smaller (making everything inside the div - its children - smaller as well) to a specific point on the page (middle of the page) and to a specific width and height (let's say 100 * 100px for example).
I am starting with the following code:
<div id="toBeZoomedOut">
<div>something</div>
<div><img src="background.jpg"></div>
</div>
#toBeZoomedOut {
background-color: black;
border: 1px solid #AAAAAA;
color: white;
width: 300px;
height: 300px;
margin-left: auto;
margin-right: auto;
-webkit-transition: 1s ease-in-out;
-moz-transition: 1s ease-in-out;
transition: 1s ease-in-out;
}
#toBeZoomedOut img {
height: 250px;
width: 250px;
}
#toBeZoomedOut:hover {
zoom: 0.5;
}
The issue with this code is that it zooms out on component down (the parent div) and immediately zooms out what's inside it then goes back to zoom in the components.
Basically it is a little buggy. Any helpful fixes to make it zoom out everything together? It would be great if I can zoom out everything together to a specific location on the page and to a specific width/height (for example, zoom everything out to left: 100px, top: 100px and the parent div should be: 100px * 100px and everything else is relative in size).
I understand this might be easier with JavaScript? Any help?
One final note, if you notice the animation is not really reflecting a zoom animation. Although this would be an additional plus, the actual zoom animation would be great.
JSFiddle link to make it easier: http://jsfiddle.net/HU46s/
I am using the universal selector to target everything inside of the parent container to have the css transitions applied to it.
The next thing I did was changed the inside contents width to a % for ease of scaling.
Here is the css:
#toBeZoomedOut * {
-webkit-transition: all 1s ease;
-moz-transition: 1s ease;
transition: 1s ease;
}
Finally, a fiddle: Demo
To make all images and div backgrounds zoom at the same time you have to use percentage size for #zoomer-inside elements and set a specific font-sizes...
However is not smooth, if you want a smoother result, I suggest you use a jQuery in combination with some animation() method or plugin.
Fiddle: http://jsfiddle.net/HU46s/1/
Code:
#toBeZoomedOut {
background-color: black;
border: 1px solid #AAAAAA;
color: white;
width: 300px;
height: 300px;
margin-left: auto;
margin-right: auto;
-webkit-transition: all 1s ease-in-out;
-moz-transition: all 1s ease-in-out;
transition: all 1s ease-in-out;
}
#toBeZoomedOut div, #toBeZoomedOut img {
width: 90%;
font-size: 20px;
}
#toBeZoomedOut img {
height: 90%;
width: 90%;
}
#toBeZoomedOut:hover {
zoom: 0.5;
}
smoother by jQuery:
Fiddle: http://jsfiddle.net/HU46s/5/
Code:
jQuery - smoother solution (even less CSS):
$('#toBeZoomedOut').hover( /* change the animation speed as you want :) */
function(){
$(this).animate({ 'zoom': 0.5}, 400); //animation speed 400=0.4s !
},
function(){
$(this).animate({ 'zoom': 1}, 400); //animation speed 400=0.4s !
}
);
...with this only CSS you need is:
#toBeZoomedOut {
background-color: black;
border: 1px solid #AAAAAA;
color: white;
width: 300px;
height: 300px;
margin-left: auto;
margin-right: auto;
}
#toBeZoomedOut img {
width: 250px;
}

How do I animate this box to have a pop out effect?

I have a simple div set up and I was wondering how I could make it have a 'pop out' effect. For example, I would like it to start as a smaller rectangle and have it animate to a slightly larger rectangle giving it the illusion that it is popping out at you.
HTML
<div id="submit-logged-out">
You must be registered to submit.
</div>
CSS
#submit-logged-out {
background: #000;
color: #fff;
font-size: 2em;
left: 112px;
padding: 40px;
position: absolute;
top: 200px;
}
JSFiddle: http://jsfiddle.net/SSsVx/
This is best done with plain CSS:
.popout {
animation: popout 1s ease;
-webkit-animation: popout 1s ease;
}
#keyframes popout {
from{transform:scale(0)}
80%{transform:scale(1.2)}
to{transform:scale(1)}
}
#-webkit-keyframes popout {
from{-webkit-transform:scale(0)}
80%{-webkit-transform:scale(1.2)}
to{-webkit-transform:scale(1)}
}
Then just add the .popout class to your box.
Updated Fiddle

Advice about how to animate the background of a list item

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);
});

Categories