Multiple Flip Boxes - But only flip the one clicked on - javascript

my challenge is that I have two rows of boxes that I want to flip independently. Can't use hover as that is too chaotic, visually, for some users. So I have a JQuery script that toggles between classes, BUT, when applied to multiple boxes I get all of the boxes turning at once. I'd like to be able to turn over only the one clicked on like the hover effect. I can get that to happen if I give each box a separate class but that is a lot of extra CSS and I know that there has to be a better, cleaner way. Please help. :)
Here is the jquery code: $('.card') is what I'd like to use instead of ('cardOne', '.cardTwo', etc.)
function flip() {
$('.card').toggleClass('flipped');
}
And here is the CSS (it's too cumbersome):
.container {
width: 200px;
height: 200px;
position: relative;
border: 1px solid #ccc;
-webkit-perspective: 800px;
-moz-perspective: 800px;
-o-perspective: 800px;
perspective: 800px;
}
.cardOne, .cardTwo, .cardThree, .cardFour, .cardFive, .cardSix, .cardSeven, .cardEight {
width: 100%;
height: 100%;
position: absolute;
-webkit-transition: -webkit-transform 1s;
-moz-transition: -moz-transform 1s;
-o-transition: -o-transform 1s;
transition: transform 1s;
-webkit-transform-style: preserve-3d;
-moz-transform-style: preserve-3d;
-o-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-transform-origin: 50% 50%;
}
.cardOne div {
display: block;
height: 100%;
width: 100%;
/*line-height: 200px;*/
color: #000;
text-align: center;
/*font-weight: bold;*/
font-size: 18px;
position: absolute;
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
-o-backface-visibility: hidden;
backface-visibility: hidden;
}
.cardOne .front, .cardTwo .front, .cardThree .front, .cardFour .front, .cardFive .front, .cardSix .front, .cardSeven .front, .cardEight .front {
background: #9ddae5;
line-height: 180px;
}
.cardOne .back, .cardTwo .back, .cardThree .back, .cardFour .back, .cardFive .back, .cardSix .back, .cardSeven .back, .cardEight .back {
background: blue;
line-height: 18px;
-webkit-transform: rotateX( -180deg );
-moz-transform: rotateX( -180deg );
-o-transform: rotateX( -180deg );
transform: rotateX( -180deg );
}
.cardOne.flipped, .cardTwo.flipped, .cardThree.flipped, .cardFour.flipped, .cardFive.flipped, .cardSix.flipped, .cardSeven.flipped, .cardEight.flipped {
-webkit-transform: rotateX( -180deg );
-moz-transform: rotateX( -180deg );
-o-transform: rotateX( -180deg );
transform: rotateX( -180deg );
}
And then, of course, the HTML (but I'll cut it to two boxes):
<div class="container">
<div class="cardOne" onclick="flipOne()">
<div class="front">
<!-- front content -->
<p>anxiety</p>
</div>
<div class="back">
<!-- back content -->
<p>Occasional anxiety is a normal part of life. You might feel anxious when faced with a problem at work, before taking a test, or making an important decision. But anxiety disorders involve more than temporary worry or fear. </p>
</div>
</div><!-- end flipper -->
</div>
</div> <!-- end col-1 -->
<div class="col-1">
<div class="container">
<div class="cardTwo" onclick="flipTwo()">
<div class="front">
<!-- front content -->
<p>infertility</p>
</div>
<div class="back">
<!-- back content -->
<p>Grief is a real part of infertility. It may be heightened in miscarriages or stillbirths, but it is just as real when a couple cannot conceive.</p>
</div>
</div>
</div>
</div><!-- end col-1 -->

Use the following:
$('.container').on('click', '.card', function(){
$(this).toggleClass('flipped');
});
Using this logic, we bind with the script an event handler to the parent container of the cards. Any time a card is clicked, it will toggle the flipped class on the card that was clicked.
$('.container').on('click', '.card', function() {
$(this).toggleClass('flipped');
});
.card {
display: inline-block;
min-width: 100px;
min-height: 80px;
border: 1px solid black;
}
.card.flipped { background-color: red; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="card"></div>
<div class="card"></div>
</div>

Try this:
$('.card').on('click', function() {
$(this).toggleClass('flipped');
}
And you'll only need one class .card reducing writng and so on.
Ps: remove the function declation and replaced it with the code above and remove all onclick="flip()" from your HTML.

Related

How to align center with smaller size parent that has a 3d style

My code is about Filping Card. I have 3 elements "flipperContainer" ,"flipper", "CarbBack"("CardBack" is put on page with rotateY 180 first).
I was run into problem when try to align "CardBack"'s center with flipper, when the size of "CardBack" is bigger than "flipper", it seems that "CardBack" always align left with "Flipper".
I have try many methods, using flex layout or using fixed position with "CardBack", but it just doesn't work, seems to because that its parent "flipper" has a 3d style.
Following is my code, I really need some help that can center "CardBack" with "Flipper" while maintaining all the 3d style, thanks!
const root = document.querySelector("#root");
class Card extends React.Component {
constructor(props){
super(props);
}
render(){
return (
<div className="flipperContainer">
<div className="flipper">
<div className="cardBack">
</div>
</div>
</div>
)
}
}
ReactDOM.render(<Card/>, root);
.flipperContainer{
-webkit-perspective: 1000px;
perspective: 1000px;
width: 80px;
height: 50px;
margin: auto;
border-radius:35px;
background-color: black;
}
.flipperContainer:hover .flipper, .flipperContainer.hover .flipper {
-webkit-transform: rotateY(180deg);
transform: rotateY(180deg);
}
.flipper {
width: 40px;
height: 60px;
background-color: red;
-webkit-transition: 1s;
-o-transition: 1s;
transition: 1s;
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
border-radius:35px;
right:50%;
position:relative;
}
/* back, initially hidden pane */
.cardBack {
background-color: green;
-webkit-backface-visibility: visible;
backface-visibility: visible;
-webkit-transform: rotateY(180deg);
transform: rotateY(180deg);
width: 70px;
height: 90px;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

CSS card flip animation

I am trying to build an animation where each time a card is clicked the card flips over and reveals the opposite side. The words on each side of the card will change every time the card is flipped. The problem I am having is that the front face of my card only is visible on sporadic occasions. I cannot find any logic to why the front face is normally not visible but occasionally will be visible.
This is my jsfiddle: https://jsfiddle.net/tdammon/ucf6mx1q/
Here is the HTML structure:
<body>
<section>
<div id="headerSection">
<h1>Heard At Prime</h1>
</div>
<div id='whiteBlock'>
<div id='front'>hey</div>
<div id='back'>hi</div>
</div>
</section>
</body>
</html>
Here is the flipping logic for the #whiteBlock div:
$(document).ready(onReady);
function onReady(){
$('#whiteBlock').on('click', flipIt)
}
quotesArray=['hey','cool saying','funny thing','hahaha'];
function flipIt() {
console.log('flip')
$('#front').empty();
$('#back').empty();
let firstQuote= quotesArray[Math.floor(Math.random()*quotesArray.length)]
let secondQuote= quotesArray[Math.floor(Math.random()*quotesArray.length)]
$('#front').append(firstQuote);
$('#back').append(secondQuote);
$('#whiteBlock').toggleClass('flip');
};
And the CSS animations:
body {
background-color: blue;
}
section{
perspective: 500px;
}
#whiteBlock{
background-color:white;
height: 100px;
width:100px;
transform: scale(1);
transform-style: preserve-3d;
/* transition: transform .5s; */
display: flex;
justify-content: center;
align-items: center;
/* position: absolute;
animation: move 3s linear infinite; */
}
#whiteBlock:active{
transform:scale(.97);
transition: transform .2s
}
#whiteBlock.flip{
transform:rotateY(180deg)
}
#front{
transform: rotateY(180deg);
backface-visibility: hidden;
}
#back{
position:absolute;
backface-visibility: hidden;
}
backface-visibility still requires vendor prefixes. So you'll need -webkit-backface-visibility for Chrome and Safari and -moz for Firefox.
With a couple changes this more of less works for me in Safari and should be a good starting point:
$(document).ready(onReady);
function onReady() {
$('#whiteBlock').on('click', flipIt)
}
let quotesArray = ['hey', 'cool saying', 'funny thing', 'hahaha'];
function flipIt() {
console.log('flip')
$('#front').empty();
$('#back').empty();
let firstQuote = quotesArray[Math.floor(Math.random() * quotesArray.length)]
let secondQuote = quotesArray[Math.floor(Math.random() * quotesArray.length)]
$('#front').append(firstQuote);
$('#back').append(secondQuote);
$('#whiteBlock').toggleClass('flip');
};
section {
perspective: 500px;
}
#whiteBlock {
border: 1px solid #333;
height: 100px;
width: 100px;
transition: 0.6s;
transform-style: preserve-3d;
-webkit-transform-style: preserve-3d;
-moz-transform-style: preserve-3d;
position: relative;
}
#whiteBlock.flip {
transform: rotateY(180deg)
}
#front {
transform: rotateY(0deg);
backface-visibility: hidden;
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
}
#back {
transform: rotateY(180deg);
backface-visibility: hidden;
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section>
<div id="headerSection">
<h1>Heard At Prime</h1>
</div>
<div id='whiteBlock'>
<div id='front'>hey</div>
<div id='back'>hi</div>
</div>
</section>

jQuery card flip requires two clicks to work

On click, I want the clicked card to flip and reveal the backside. Everything is working smoothly, except for the fact that after the first click, two clicks are required to get the desired functionality.
The problem is that I would like this to only work with one click. I am very new to jQuery, so I'm expecting that this is probably a basic issue that I'm overlooking.
Here is the jQuery:
function flip() {
jQuery('.flip').click(function() {
jQuery(this).find('.card').toggleClass('flipped');
});
}
.ot-front {
background-color: blue;
}
.ot-back {
background-color: red;
}
.team-member {
display: inline-flex;
width: 200px;
height: 260px;
position: relative;
border: 1px solid #ccc;
perspective: 800px;
}
.card {
width: 100%;
height: 100%;
position: absolute;
transition: transform .3s;
transform-style: preserve-3d;
}
.card div {
display: block;
height: 100%;
width: 100%;
line-height: 260px;
color: white;
text-align: center;
font-weight: bold;
font-size: 14px;
position: absolute;
backface-visibility: hidden;
}
.card .ot-back {
background: #eee;
transform: rotateY( 180deg);
}
.card.flipped {
transform: rotateY( 180deg);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="team-members">
<div class="team-member flip">
<div class="card" onclick="flip()">
<div class="ot-front">FRONT</div>
<div class="ot-back">BACK</div>
</div>
</div>
<div class="team-member flip">
<div class="card" onclick="flip()">
<div class="ot-front">FRONT</div>
<div class="ot-back">BACK</div>
</div>
</div>
<div class="team-member flip">
<div class="card" onclick="flip()">
<div class="ot-front">FRONT</div>
<div class="ot-back">BACK</div>
</div>
</div>
</div>
If you were to implement it like this:
function flip(wrapperContainingElementToFlip) {
wrapperContainingElementToFlip.find('.card').toggleClass('flipped');
}
jQuery('.flip').click(function () {
flip($(this));
});
You will bind the click when the script is loaded.
You could also bind the click eventhandler on page load, by wrapping your code in a page load event handler, like so:
$(document).ready(function() {
//Put your code here
});
By implementing your code as above, when clicking the element, a function will be called. The click event will be bound before calling the flip function, and will therefore execute.
I think this will solve your issue.
It's probably because of the fact, that you wrapped your jQuery into a function.
So for this to work, you need to click once to call a function to work, and then another one, for jQuery function to work.
Try deleting the outer function flip() and see if it's working.
Just remove the outer function. It should look something like this:
$('.flip').click(function(){
$(this).find('.card').toggleClass('flipped');
});
It does work just fine in codepen.
Your logic is doubled. You invoke flip on click and then subscribe to click, and then only do the flipping in the handler. Removing the outer function, the handlers in the HTML (and jQuery):
Array.from(document.querySelectorAll(".card")).forEach(element =>
element.addEventListener("click", () =>
element.classList.toggle('flipped')
)
);
.ot-front {
background-color: blue;
}
.ot-back {
background-color: red;
}
.team-member {
display: inline-flex;
width: 200px;
height: 260px;
position: relative;
border: 1px solid #ccc;
-webkit-perspective: 800px;
-moz-perspective: 800px;
-o-perspective: 800px;
perspective: 800px;
}
.card {
width: 100%;
height: 100%;
position: absolute;
-webkit-transition: -webkit-transform .3s;
-moz-transition: -moz-transform .3s;
-o-transition: -o-transform .3s;
transition: transform .3s;
-webkit-transform-style: preserve-3d;
-moz-transform-style: preserve-3d;
-o-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-transform-origin: 50% 50%;
}
.card div {
display: block;
height: 100%;
width: 100%;
line-height: 260px;
color: white;
text-align: center;
font-weight: bold;
font-size: 14px;
position: absolute;
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
-o-backface-visibility: hidden;
backface-visibility: hidden;
}
.card .ot-back {
background: #eee;
-webkit-transform: rotateY( 180deg );
-moz-transform: rotateY( 180deg );
-o-transform: rotateY( 180deg );
transform: rotateY( 180deg );
}
.card.flipped {
-webkit-transform: rotateY( 180deg );
-moz-transform: rotateY( 180deg );
-o-transform: rotateY( 180deg );
transform: rotateY( 180deg );
}
<div class="team-members">
<div class="team-member flip">
<div class="card">
<div class="ot-front">FRONT</div>
<div class="ot-back">BACK</div>
</div>
</div>
<div class="team-member flip">
<div class="card">
<div class="ot-front">FRONT</div>
<div class="ot-back">BACK</div>
</div>
</div>
<div class="team-member flip">
<div class="card">
<div class="ot-front">FRONT</div>
<div class="ot-back">BACK</div>
</div>
</div>
</div>

Is there a “Backface-visibility:hidden” alternative for IE11?

I am trying to get a card to look, in IE11, like it does in Google Chrome. So I am looking for:
the front image to not show thru on the back when flipped
the text on the back to be visible once the card is flipped on the back, but not seen on the front
It doesn't do either in IE. The card works in Google Chrome and that is the look I am going for: ****UPDATED FIDDLE***** https://jsfiddle.net/Lance_Bitner/a8sz1765/
.front, .back {
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
-o-backface-visibility: hidden;
backface-visibility: hidden;
It looks awful in IE11. It looks fine to start, but when the card is flipped the front of the card is seen on the back side. Also, the text is not visible on the back side. The “backface-visibility: hidden;” CSS doesn’t work for IE 10 or IE 11. When the card is flipped is there a way to make it so the front side does not show thru? I would like it to remain transparent, but the front of the card to disappear when flipped to the backside.
There is an alternative for "Backface-visibility:hidden" for IE10 and IE11!
<div class="card-container">
<div class="flipcard h">
<div class="front" style="background-image:url 'http://cdn.tutorialzine.com/wp-content/uploads/2010/03/797.jpg'); background-size: 50%;">
</div>
<div class="back">
<img id="" src="http://cdn.tutorialzine.com/wp-content/uploads/2010/03/797.jpg" style="width:80%;padding-bottom:0px">
<hr>
<p style="color:black;">Insert the Text Here</p>
</div>
</div>
</div>
Use the JS and CSS here: https://jsfiddle.net/Lance_Bitner/pcLq688j/
.flipcard {
position: relative;
width: 300px;
height: 220px;
perspective: 500px;
}
.flipcard.v:hover .front, .flipcard.v.flip .front{
transform: rotateX(180deg);
}
.flipcard.v:hover .back, .flipcard.v.flip .back{
transform: rotateX(0deg);
}
.flipcard.v .back{
transform: rotateX(-180deg);
}
.flipcard.h:hover .front, .flipcard.h.flip .front{
transform: rotateY(180deg);
}
.flipcard.h:hover .back, .flipcard.h.flip .back{
transform: rotateY(0deg);
}
.flipcard.h .back{
transform: rotateY(-180deg);
}
.flipcard .front, .flipcard .back
{
position:absolute;
width: 100%;
height: 100%;
box-sizing: border-box;
transition: all 1.0s ease-in;
color: white;
background-color: rgba(255,255,255,.10);
padding: 10px;
backface-visibility: hidden;
margin:25px;
box-shadows: 10px 10px 5px #999798;
border: 1px solid rgba(123, 46, 0, 0.40);
border-radius: 10px;
}
document.querySelector('#cardId').classList.toggle('flip');
// or using jQuery
// $("#cardId").toggleClass("flip");

Adding preventDefault() and stopPropagation()

I am new in coding in general, most especially javascript.
I made a flip div effect. But I noticed that when clicking one .button to trigger the flip effect, all the other divs that are similar in a page are also triggered. So I am trying to add both .preventDefault() and .stopPropagation() when flipping a div, so far its a big FAIL
As a starter, I came up with this code..
$('.insidecontent .button').click(function () {
$('.insidecontent').addClass('flipped');
$('.insidecontent').removeClass('unflipped');
});
$('.insidecontent .button-c').click(function () {
$('.insidecontent').removeClass('flipped');
$('.insidecontent').addClass('unflipped');
});
Demo here: http://jsfiddle.net/uriri/ke7kqvvk/3/
A friend of mine suggested that I should use .parents() on the current target inside the .click() function. But after reading the jQuery documentation, I am totally lost!
You don't need to stop click event or prevent default. You just need to flip right element. Right not you are adding/removing classes to/from all .insidecontent, while you need to select only parent element of the clicked button:
$('.insidecontent .button').click(function () {
$(this).closest('.insidecontent').addClass('flipped').removeClass('unflipped');
});
$('.insidecontent .button-c').click(function () {
$(this).closest('.insidecontent').removeClass('flipped').addClass('unflipped');
});
Demo: http://jsfiddle.net/ke7kqvvk/5/
Or shorter optimized version can be:
$('.insidecontent').find('.button, .button-c').click(function () {
$(this).closest('.insidecontent').toggleClass('flipped unflipped');
});
Demo: http://jsfiddle.net/ke7kqvvk/6/
preventDefault() and stopPropagation() won't help here. You need to use a selector that's more specific than all the elements with the same class.
$('.insidecontent .button').click(function () {
$(this).closest('.insidecontent').addClass('flipped').removeClass('unflipped');
});
$('.insidecontent .button-c').click(function () {
$(this).closest('.insidecontent').removeClass('flipped').addClass('unflipped');
});
.content{
position: relative;
background: #ffffff;
width:100%;
text-align:center;
display: -webkit-box;
display: -moz-box;
display: box;
-webkit-box-orient: vertical;
-moz-box-orient: vertical;
box-orient: vertical;
-webkit-box-align: center;
-moz-box-align: center;
box-align: center;
}
._hasdata .insidecontent {
position: relative;
background: #ffffff;
margin-bottom:30px;
-webkit-perspective: 1000px;
-moz-perspective: 1000px;
-o-perspective: 1000;
perspective: 1000px;
}
._hasdata .insidecontent .front {
position: relative;
z-index: 900;
width: 200px;
height: 200px;
background: #ededed;
-webkit-transform: rotateX(0deg) rotateY(0deg);
-moz-transform: rotateX(0deg) rotateY(0deg);
transform: rotateX(0deg) rotateY(0deg);
}
._hasdata .insidecontent .front .fcontent {
position:relative;
top:30%;
}
._hasdata .insidecontent.flipped .front {
z-index: 900;
-webkit-transform: rotateX(0deg) rotateY(180deg);
-moz-transform: rotateX(0deg) rotateY(180deg);
transform: rotateX(0deg) rotateY(180deg);
}
._hasdata .insidecontent .back {
position: absolute;
width: 200px;
height: 200px;
top: 0;
left: 0;
z-index: 800;
-webkit-transform: rotateX(0deg) rotateY(-180deg);
-moz-transform: rotateY(-180deg);
transform: rotateX(0deg) rotateY(-180deg);
}
._hasdata .insidecontent.flipped .back {
z-index: 1000;
background: #E7E7E7;
-webkit-transform: rotateX(0deg) rotateY(0deg);
-moz-transform: rotateX(0deg) rotateY(0deg);
transform: rotateX(0deg) rotateY(0deg);
}
._hasdata .insidecontent .front,
._hasdata .insidecontent .back {
-webkit-transform-style: preserve-3d;
-moz-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
backface-visibility: hidden;
-webkit-transition: all .8s ease-in-out;
-moz-transition: all .8s ease-in-out;
transition: all .8s ease-in-out;
}
._hasdata .insidecontent .button,
._hasdata .insidecontent.flipped .button-c {
z-index: 15;
display: block;
position: absolute;
bottom: 0;
margin: -30px 20px 20px;
opacity: 0;
-webkit-transition: opacity .1s linear;
-moz-transition: opacity .1s linear;
transition: opacity .1s linear;
}
._hasdata .insidecontent:hover .button,
._hasdata .insidecontent.flipped:hover .button-c {
opacity: 0.8;
}
._hasdata .insidecontent.unflipped .button-c {
display: none;
}
._hasdata .insidecontent.flipped ._lar {
height: 100%;
}
._hasdata .insidecontent.unflipped .bcontent {
display: none;
}
._hasdata .insidecontent.flipped .bcontent {
top: 30%;
position: relative;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="content">
<div class="_hasdata">
<div class="insidecontent initalized unflipped">
<div class="front">
<span class="fcontent">FRONT CONTENT<br />HERE</span>
<a class="btt button">info</a>
</div>
<div class="back _lar">
<div class="bcontent">BACK INFO HERE</div>
<a class="btt button-c">go back</a>
</div>
</div>
</div>
<div class="_hasdata">
<div class="insidecontent initalized unflipped">
<div class="front">
<span class="fcontent">FRONT CONTENT<br />HERE</span>
<a class="btt button">info</a>
</div>
<div class="back _exif">
<div class="bcontent">BACK INFO HERE</div>
<a class="btt button-c">go back</a>
</div>
</div>
</div>
</div>
Have you learned about the "this" keyword yet? In a JQuery click handler, $(this) refers to the element that the handler is called on. So, if you put removeClass and addClass methods on $(this) it will only affect that one element. You can traverse using this too... so your code would look like this:
$('.insidecontent .button').click(function () {
$(this).parent().find('.insidecontent').addClass('flipped');
$(this).parent().find('.insidecontent').removeClass('unflipped');
});
$('.insidecontent .button-c').click(function () {
$(this).parent().find('.insidecontent').removeClass('flipped');
$(this).parent().find('.insidecontent').addClass('unflipped');
});
you may not even need the find method in your case, but it is better to be explicit.

Categories

Resources