Ultimately, for each click of a button, I want to display an element that contains new content. In other words...
You read content contained within a parent container
To see the next item click the button
When the button is clicked, the old content shifts downward. The new content flows down from the top of the container. It pauses in order to read the new content.
To get new content, press the button again.
I'm unclear as to how to accomplish this, and if it's even possible with a CSS Animation. With what I have posted, it just takes both elements and translates them down the vertical axis at once. How can this be refactored so that one element pauses and displays it's content using just vanilla JavaScript?
var div1 = document.querySelector(".first");
var div2 = document.querySelector(".second");
var button = document.querySelector("button");
var divs = [div1, div2];
button.addEventListener("click", function(event) {
event.preventDefault();
for (var i = divs.length - 1; i > -1; i--) {
var div = divs[i];
div.classList.remove("down_shift");
void div.offsetWidth;
div.classList.add("down_shift");
}
});
body {
background: #222;
}
section {
width: 50vw;
height: 300px;
border: 5px solid red;
margin: 50px auto;
overflow: hidden;
}
.first, .second {
width: inherit;
height: 300px;
background: red;
transform: translateY(-300px);
}
.second {
background: pink;
}
h1 {
margin: 0;
padding-top: 50px;
text-align: center;
}
.down_shift {
animation: down 1s ease-out;
}
#keyframes down{
from {
transform: translateY(0);
}
to {
transform: translateY(300px);
}
}
<section>
<div class="first"><h1>1</h1></div>
<div class="second"><h1>2</h1></div>
</section>
<button type="button">Click</button>
You can add a wrapper to the elements, and animate the wrapper
var wrapper = document.querySelector(".wrapper");
var button = document.querySelector("button");
button.addEventListener("click", function(event) {
event.preventDefault();
wrapper.style.transform = 'translateY(-300px)'
});
body {
background: #222;
}
section {
width: 50vw;
height: 300px;
border: 5px solid red;
margin: 50px auto;
overflow: hidden;
}
.first, .second {
width: inherit;
height: 300px;
background: red;
/* transform: translateY(-300px); */
}
.second {
background: pink;
}
.wrapper {
transition: all 1s ease-out;
}
h1 {
margin: 0;
padding-top: 50px;
text-align: center;
}
.down_shift {
animation: down 1s ease-out;
}
#keyframes down{
from {
transform: translateY(0);
}
to {
transform: translateY(300px);
}
}
<section>
<div class="wrapper">
<div class="first"><h1>1</h1></div>
<div class="second"><h1>2</h1></div>
</div>
</section>
<button type="button">Click</button>
Related
I am trying to create a tooltip for whatever that needs it on my website, e.g. a button, text, etc. So far I have something like this:
https://jsfiddle.net/f06q3cLg/
.content {
display: grid;
width: 100vw;
height: 100vh;
place-content: center;
}
.content .parent {
border: 1px red solid;
padding: 10px;
position: relative;
}
.content .parent:hover .tooltip-wrapper {
animation: 0.1s fadeInTooltip;
animation-fill-mode: forwards;
animation-delay: 0.4s;
}
.content .parent:hover:before {
animation: 0.1s fadeInTooltip;
animation-fill-mode: forwards;
animation-delay: 0.4s;
}
.content .parent:active .tooltip-wrapper {
animation: 0.05s fadeOutTooltip;
animation-fill-mode: forwards;
}
.content .parent:active:before {
animation: 0.05s fadeOutTooltip;
animation-fill-mode: forwards;
}
.content .parent:before {
content: "";
display: block;
width: 0;
height: 0;
position: absolute;
border-left: 6px solid transparent;
border-right: 6px solid transparent;
left: 50%;
transform: translateX(-50%);
opacity: 0;
}
.content .parent .tooltip-wrapper {
position: absolute;
display: grid;
left: 0;
width: 300px;
height: 100%;
opacity: 0;
pointer-events: none;
}
.content .parent .tooltip-wrapper.bottom {
top: calc(100% + 8px);
}
.content .parent .tooltip-wrapper .tooltip {
max-width: 300px;
width: fit-content;
padding: 8px;
position: absolute;
display: inline-block;
background: blue;
border-radius: 5px;
padding: 8px;
color: white;
font-size: 11px;
box-shadow: 0px 3px 3px rgba(0, 0, 0, 0.2);
line-height: 1.3;
text-align: left;
}
/* Keyframes */
#keyframes fadeInTooltip {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
#keyframes fadeOutTooltip {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
<div class="content">
<div class="parent">
Hover me
<div class="tooltip-wrapper">
<span class="tooltip">This is my tooltip</span>
</div>
</div>
</div>
As such, it works somewhat fine. My issue is that I would like the tooltip to disappear when I click the button. Now it vanishes, and then comes back with a 0.4s delay as the hover effect actually has. Ideally the tooltip should disappear as long as my mouse is still on the button, but when I remove it and re-enters the button, then the tooltip should re-appear.
I'm not sure if this is even achievable with pure CSS, but any JS would also do.
The problem is that :active is only applied as long as the mouse is down.
mdn: :active:
The :active CSS pseudo-class represents an element (such as a button) that is being activated by the user. When using a mouse, "activation" typically starts when the user presses down the primary mouse button.
What you could do (if you want to stay CSS only) is to use tabindex="0" on the <div class="parent"> and :focus instead of :active. But you need to verify that using tabindex="0" here won't hurt usability.
Ideally the tooltip should disappear as long as my mouse is still on the button, but when I remove it and re-enters the button, then the tooltip should re-appear.
That won't work with :focus either. I'm pretty sure that this behavior can only be achieved with JS. If it is possible with CSS only it likely would be a pretty hacky solution.
But from the perspective of a user, this seems to be counterintuitive that the tooltip won't appear after clicked.
A JavaScript solution that does what you want could look like this.
It is a simplified version of the tooltip to only show the relevant parts.
Every element having a tooltip has an attribute data-has-tooltip.
// event delegation for all mouse down event:
// this ensures that the code also works for elements that have been added to the DOM after that script was executed.
document.addEventListener('mousedown', (evt) => {
// check if the mousedown happened in an element with a tooltip
const element = evt.target.closest('[data-has-tooltip]');
if (element) {
// if the user already clicked on the element ignore the click
if (!element.classList.contains('active')) {
// add the active class to the element so that hover won't show the toolip
element.classList.add('active');
function removeActiveOnLeave() {
// remove the active class
element.classList.remove('active');
// remove the mouseleave event listener again
element.removeEventListener('mouseleave', removeActiveOnLeave)
}
// add an event listener for mouseleave to remove the active class
element.addEventListener('mouseleave', removeActiveOnLeave)
}
}
});
.parent {
display: inline-block;
border: 1px solid red;
padding: 0.5rem;
margin: 0.5rem;
}
.tooltip-wrapper {
display: none;
}
.parent:hover .tooltip-wrapper {
display: block;
}
.parent.active:hover .tooltip-wrapper {
display: none;
}
<div class="content">
<div class="parent" data-has-tooltip>
Hover me A
<div class="tooltip-wrapper">
<span class="tooltip">This is my tooltip A </span>
</div>
</div>
</div>
<div class="content">
<div class="parent" data-has-tooltip>
Hover me B
<div class="tooltip-wrapper">
<span class="tooltip">This is my tooltip B</span>
</div>
</div>
</div>
HTML
<div class="content">
<div class="parent" onClick="myFunction()">
Hover me
<div class="tooltip-wrapper">
<span class="tooltip" id="tooltip">This is mytooltip</span>
</div>
</div>
</div>
Javascript
function myFunction(){
var tooltip=document.getElementById("tooltip");
if (tooltip.style.display=="none") {
document.getElementById("tooltip").style.display="block";
} else {
document.getElementById("tooltip").style.display="none";
}
}
Manipulating 'display' property.
const parent = document.querySelector('.parent');
const toolTip = document.querySelector('.tooltip');
parent.addEventListener('click', () => {
if(toolTip.style.display !== 'none') {
toolTip.style.display = 'none';
}else {
toolTip.style.display = 'grid';
}
});
A solution using jQuery 3.4.1:
$(".parent").click(function () {
$(".tooltip-wrapper").css("display", "none");
});
The only downfall with that solution is once you click and re-hover in the same session, the SCSS :hover doesn't work properly.
No need to stress, just add the following if you want that functionality:
$(".parent").hover(function () {
$(".tooltip-wrapper").css("display", "block");
});
Try it out in the attached snippet:
$(".parent").click(function () {
$(".tooltip-wrapper").css("display", "none");
});
$(".parent").hover(function () {
$(".tooltip-wrapper").css("display", "block");
});
.content {
display: grid;
width: 100vw;
height: 100vh;
place-content: center;
}
.content .parent {
border: 1px red solid;
padding: 10px;
position: relative;
}
.content .parent:hover .tooltip-wrapper {
animation: 0.1s fadeInTooltip;
animation-fill-mode: forwards;
animation-delay: 0.4s;
}
.content .parent:hover:before {
animation: 0.1s fadeInTooltip;
animation-fill-mode: forwards;
animation-delay: 0.4s;
}
.content .parent:active .tooltip-wrapper {
animation: 0.05s fadeOutTooltip;
animation-fill-mode: forwards;
}
.content .parent:active:before {
animation: 0.05s fadeOutTooltip;
animation-fill-mode: forwards;
}
.content .parent:before {
content: "";
display: block;
width: 0;
height: 0;
position: absolute;
border-left: 6px solid transparent;
border-right: 6px solid transparent;
left: 50%;
transform: translateX(-50%);
opacity: 0;
}
.content .parent .tooltip-wrapper {
position: absolute;
display: grid;
left: 0;
width: 300px;
height: 100%;
opacity: 0;
pointer-events: none;
}
.content .parent .tooltip-wrapper.bottom {
top: calc(100% + 8px);
}
.content .parent .tooltip-wrapper .tooltip {
max-width: 300px;
width: fit-content;
padding: 8px;
position: absolute;
display: inline-block;
background: blue;
border-radius: 5px;
padding: 8px;
color: white;
font-size: 11px;
box-shadow: 0px 3px 3px rgba(0, 0, 0, 0.2);
line-height: 1.3;
text-align: left;
}
/* Keyframes */
#keyframes fadeInTooltip {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
#keyframes fadeOutTooltip {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="content">
<div class="parent">
Hover me
<div class="tooltip-wrapper">
<span class="tooltip">This is my tooltip</span>
</div>
</div>
</div>
OR, you can see it working in this Fiddle. with your initial
SCSS.
You can uncomment the second function to see the hover working again after clicking.
I have this cool html css card below, where I now need to have that if you click it, it shows a lightbox with multiple photos. I have tried multiple things before, but the problem is everything gets messed up when you do light box.
this is the code for the picture card alone. and this is the link to see it with me trying the light box. https://codepen.io/gianlucaas/pen/rNzBKVz
what am i doing wrong?
function myFunction() {
var modelName = "Angela"
var height = 'My name is Angela'
var myImage = "https://images.unsplash.com/photo-1633594708103-e6e41891b679?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1040&q=80"
document.getElementById("myText").innerHTML = modelName;
document.getElementById("myHeight").innerHTML = height;
document.getElementById("myImg").src = myImage;
}
.card-content {
position: relative;
overflow: hidden;
}
.card-content-details {
padding: 10px;
}
.card-content-details {
display: flex;
flex-direction: column;
justify-content: flex-end;
padding: 15px;
}
.card-content-details,
.card-content-overlay {
box-sizing: border-box;
height: 100%;
width: 100%;
position: absolute;
top: 0;
left: 0;
opacity: 0;
}
.card-content-details {
transform: translateX(1000px);
transition-duration: 800ms;
z-index: 1;
}
.card-content-overlay {
background-color: #02010100;
transition-duration: 800ms;
transition-property: transform, opacity, background-color;
transform: translateX(-1000px);
z-index: 1;
}
.card-content-image {
transition-duration: 800ms;
width: 100%;
max-width: 100%;
}
.card-content:hover .card-content-image {
transform: scale(1.1);
}
.card-content:hover .card-content-overlay,
.card-content:hover .card-content-details {
transform: translateY(0) translateX(0);
opacity: 1;
}
.card-content:hover .card-content-overlay {
background-color: transparent;
background-image: linear-gradient(200deg, #00000000 81%, #000000ba 14%);
}
.card-content-title {
color: #fff;
font-size: 20px;
text-transform: uppercase;
margin: 0 0 10px;
}
.card-content-text {
color: #fff;
font-size: 16px;
margin: 0;
}
<body onload="myFunction()">
<div class="card-content">
<a href="#" target="_blank">
<div class="card-content-overlay"></div>
<img class="card-content-image" src="" id="myImg">
<div class="card-content-details">
<h4 class="card-content-title" id="myText"></h4>
<p class="card-content-text" id="myHeight"></p>
</div>
</a>
</div>
</body>
You can begin by creating a html container on your file of your lightbox (which will be hidden) with inside the buttons (prev, next, close) and the (empty for now).
When you launch the lightbox (with a js function that you'll have to create) you'll be display:block this html container (position: fixed; in CSS and with the highest z-index)
I'm making my own dropdown with CSS. You hover on it, then some options appear below it, you pick one and that's it. If there are too many options to fit there is a scroll bar. You can see the whole thing here: JSFiddle
let testData = [
"qwertyuiop",
"asdfghjkl",
"zxcvbnm",
"axdxfcbhdhvhv",
"äöäööäöääöää",
"zoinkszoinks",
"brrrrrrrrrr",
"gygygygyasdasda",
];
getTestStuff();
function getTestStuff() {
let content = document.getElementById("content");
let text = document.getElementById("text");
for (let group of testData) {
let div = document.createElement("div");
div.innerHTML = group;
div.addEventListener("click", function() {
text.innerHTML = group; // update button text
}, false);
content.appendChild(div);
}
}
let dropdown = document.getElementById("dropdown");
let arrow = document.getElementById("arrow");
let content = document.getElementById("content");
dropdown.addEventListener("mouseenter", function () {
arrow.className = "open";
content.classList.add("open");
}, false);
dropdown.addEventListener("mouseleave", function () {
arrow.className = "closed";
content.classList.remove("open");
}, false);
.dropdown-wrapper {
height: 40px;
float: left;
margin: 0px 5px;
}
.dropdown-wrapper, .dropdown-content {
width: 300px;
}
.dropdown-wrapper .header {
width: 100%;
height: 100%;
margin: 0;
background-color: #f1f1f1;
text-align: center;
border-radius: 5px;
font-size: 16px;
border: 1px solid grey;
display: table;
}
.dropdown-wrapper .header span {
text-align: center;
vertical-align: middle;
display: table-cell;
width: 100%;
}
.dropdown-wrapper .header div span {
font-size: 20px;
}
.dropdown-wrapper .header div {
margin-left: -40px;
width: 40px;
height: 40px;
float: right;
text-align: center;
display: table;
position: absolute;
}
.dropdown-content {
display: none;
float: none;
max-height: 300px;
overflow-x: hidden;
overflow-y: scroll;
position: absolute;
font-size: 16px;
background-color: #f1f1f1;
min-width: 0px;
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
z-index: 1;
margin-right: auto;
text-align: center;
}
.dropdown-content div {
color: black;
float: none;
padding: 12px 16px;
text-decoration: none;
display: block;
margin-right: -15px;
}
.dropdown-content div:hover {
background-color: #ddd;
}
.dropdown {
height: 100%;
width: 100%;
}
.dropdown:hover .dropdown-content {
display: block;
}
#arrow.open {
-webkit-animation-name: openArrowAnimation;
-webkit-animation-duration: 0.5s;
-webkit-animation-iteration-count: 1;
-webkit-animation-timing-function: ease;
-webkit-animation-fill-mode: forwards;
}
#arrow.closed {
-webkit-animation-name: closeArrowAnimation;
-webkit-animation-duration: 0.5s;
-webkit-animation-iteration-count: 1;
-webkit-animation-timing-function: ease;
-webkit-animation-fill-mode: forwards;
}
#-webkit-keyframes openArrowAnimation {
from {
-webkit-transform: rotate(0deg);
}
to {
-webkit-transform: rotate(180deg);
}
}
#-webkit-keyframes closeArrowAnimation {
from {
-webkit-transform: rotate(180deg);
}
to {
-webkit-transform: rotate(0deg);
}
}
#content.open {
-webkit-animation-name: openDropdownAnimation;
-webkit-animation-duration: 0.5s;
-webkit-animation-iteration-count: 1;
-webkit-animation-timing-function: ease;
-webkit-animation-fill-mode: forwards;
}
#-webkit-keyframes openDropdownAnimation {
from {
max-height: 0px;
}
to {
max-height: 300px;
}
}
<div class="dropdown-wrapper">
<div class="dropdown" id="dropdown">
<div class="header">
<span id="text">Test Thing</span>
<div id="arrow"><span>^</span></div>
</div>
<div id="content" class="dropdown-content">
</div>
</div>
</div>
The Problem:
The scrollbar appears during my animation. Which is not a problem, if it is going to stay, but when the content fits, it disappears again.
When the scroll bar is not there, the space that the scrollbar would take, does not have the right background color, when i hover over the option. Making a very ugly gap.
I know about overflow: auto; but i still use overflow: scroll; with margin-right: -16px; on the children, because my scrollbar moves the children and i only have that scrollbar sometimes.
I need some kind of CSS conditional hack to set overflow to hidden if we don't need it or use JS to change the margin-right but trying to check the parent height after adding the kids gave me this:
content.height: undefined
content.style.height: empty string
So i'm very lost with this.
I got it working with this trick on the children:
margin-right: calc(100% - 300px);
And setting the parent overflow to auto
This works because here 100% is the elements full width. Without a scroll bar, 100% is 300px, so margin is set to 0. With a scroll bar, 100% is around 290px so margin is set to around -10, so the text stays centered.
As #CBroe pointed out, i couldn't get the height of my element, or the children because it had display: none so to get around that:
let content = document.getElementById("content");
content.style.display = "block";
let height = content.offsetHeight;
content.style.display = "";
It's amazing something this dumb works so well. Now i can hide the scrollbar when i don't need it and fix the offset, that the scrollbar creates, when i do need it:
if (height < 300) {
content.style.overflowY = "hidden";
} else {
content.style.overflowY = "scroll";
for (let kid of content.children) {
kid.style.marginRight = "-16px";
}
}
This solution has the added bonus, that it works well with my animation. A problem that the CSS only solution couldn't solve.
I wanted to make a Memory Game. I want to write an CSS animation for the flip in JS so I can then call a function, because I wanted to make a onclick anmation an not an hover animation.
how do I make a CSS flip animation with an oncklicked Function in Javascript?
var card = "<div class='flip-card'><div class='flip-card-inner'><div class='flip-card-front'><button id='button'onclick='Flipfront()'style='width:300px;height:300px; marign:50px; background-image:url(Frontpage.jpg);'></button></div><div class='flip-card-back'><button id='button2' onclick='Flipback()'style='width:300px;height:300px; marign:50px; background-image:url(IMG1.jpg);'></button></div></div></div>"
for (let i = 0; i < 20; i++) {
document.querySelector("#container").innerHTML += card;
}
function Flipfront() {
// ?
}
function Flipback() {
// ?
}
.flip-card {
background-color: transparent;
width: 300px;
height: 200px;
border: 1px solid #f1f1f1;
perspective: 1000px;
/* Remove this if you don't want the 3D effect */
}
/* This container is needed to position the front and back side */
.flip-card-inner {
position: relative;
width: 100%;
height: 100%;
text-align: center;
transition: transform 0.8s;
transform-style: preserve-3d;
}
/* Do an horizontal flip when you move the mouse over the flip box container */
.flip-card:hover .flip-card-inner {
transform: rotateY(180deg);
}
/* Position the front and back side */
.flip-card-front,
.flip-card-back {
position: absolute;
width: 100%;
height: 100%;
-webkit-backface-visibility: hidden;
/* Safari */
backface-visibility: hidden;
}
/* Style the front side (fallback if image is missing) */
.flip-card-front {
background-color: #bbb;
color: black;
}
/* Style the back side */
.flip-card-back {
transform: rotateY(180deg);
}
<div id="outerbackground">
<img src="background.jpg" class="backgorund" border="1" id="BG">
</div>
<div id="container"></div>
To further elabourate on my comment: instead of using :hover, you can use a class, say .flipped instead, to control the flipped state of the card.
Then, in the Flipfront() and Flipback() methods, make sure you accept an argument that will be passed in from your markup, which will be invoked as Flipfront(this) or Flipback(this). This will allow you to access the element that triggered it.
Then, simply use Element.closest() to access the .flip-card parent, and use Element.classList.add() or Element.classList.remove() to toggle the flipped class:
var card = "<div class='flip-card'><div class='flip-card-inner'><div class='flip-card-front'><button id='button'onclick='Flipfront(this)'style='width:300px;height:300px; marign:50px; background-image:url(Frontpage.jpg);'></button></div><div class='flip-card-back'><button id='button2' onclick='Flipback(this)'style='width:300px;height:300px; marign:50px; background-image:url(IMG1.jpg);'></button></div></div></div>"
for (let i = 0; i < 20; i++) {
document.querySelector("#container").innerHTML += card;
}
function Flipfront(el) {
el.closest('.flip-card').classList.add('flipped');
}
function Flipback(el) {
el.closest('.flip-card').classList.remove('flipped');
}
.flip-card {
background-color: transparent;
width: 300px;
height: 200px;
border: 1px solid #f1f1f1;
perspective: 1000px;
/* Remove this if you don't want the 3D effect */
}
/* This container is needed to position the front and back side */
.flip-card-inner {
position: relative;
width: 100%;
height: 100%;
text-align: center;
transition: transform 0.8s;
transform-style: preserve-3d;
}
/* Do an horizontal flip when you move the mouse over the flip box container */
.flip-card.flipped .flip-card-inner {
transform: rotateY(180deg);
}
/* Position the front and back side */
.flip-card-front,
.flip-card-back {
position: absolute;
width: 100%;
height: 100%;
-webkit-backface-visibility: hidden;
/* Safari */
backface-visibility: hidden;
}
/* Style the front side (fallback if image is missing) */
.flip-card-front {
background-color: #bbb;
color: black;
}
/* Style the back side */
.flip-card-back {
transform: rotateY(180deg);
}
<div id="outerbackground">
<img src="background.jpg" class="backgorund" border="1" id="BG">
</div>
<div id="container"></div>
Have you tried dynamically changing classes on click?
When the element is clicked, you can add the class .flip-card-inner and remove '.flip-card-front` by using the classlist property and its methods
Usage is:
elem.classList.add("flip-card-inner");
elem.classList.remove("flip-card-front");
Don't write CSS in JS. Instead simply change the :hover rule to depend on a class which you toggle when each .flip-card is clicked.
Also note that you should not be using onX attributes as they are outdated and bad practice due to violating the separation of concerns principle. Instead use unobtrusive event handlers. The same is also true for inline style attributes. Move those rules in to an external stylesheet. Here's a working example:
let card = '<div class="flip-card"><div class="flip-card-inner"><div class="flip-card-front"><button id="button"></button></div><div class="flip-card-back"><button id="button2"></button></div></div></div>';
for (let i = 0; i < 20; i++) {
document.querySelector("#container").innerHTML += card;
}
document.querySelectorAll('.flip-card').forEach(el => {
el.addEventListener('click', () => el.classList.toggle('flipped'));
});
.flip-card {
background-color: transparent;
width: 300px;
height: 200px;
border: 1px solid #f1f1f1;
perspective: 1000px;
}
.flip-card-inner {
position: relative;
width: 100%;
height: 100%;
text-align: center;
transition: transform 0.8s;
transform-style: preserve-3d;
}
/* remove :hover here */
.flip-card.flipped .flip-card-inner {
transform: rotateY(180deg);
}
.flip-card-front,
.flip-card-back {
position: absolute;
width: 100%;
height: 100%;
-webkit-backface-visibility: hidden;
/* Safari */
backface-visibility: hidden;
}
.flip-card-front {
background-color: #bbb;
color: black;
}
.flip-card-back {
transform: rotateY(180deg);
}
#button {
width: 300px;
height: 300px;
background-image: url(Frontpage.jpg);
}
#button2 {
width: 300px;
height: 300px;
background-image: url(IMG1.jpg);
}
<div id="outerbackground">
<img src="background.jpg" class="backgorund" border="1" id="BG">
</div>
<div id="container"></div>
I want my button to make text in textarea cut to the clipboard and
the button rotates simultaneously each time I click it. I got it to
work, however it only rotates once, next time I click it, it'll cut
the text but button will not rotate.
HTML
my button and textarea
<div class="box-2-wrap">
<textarea class="out-put"></textarea>
<button type="button" id="copyEmailsButton" onclick="copyEmails()">Copy Emails</button>
</div>
CSS
my stylesheet
.box-2-wrap {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
border: 0px solid #333;
}
.box-2-wrap textarea {
flex:1;
padding: 4%;
overflow-y: auto;
background-color: #333;
color: gold;
max-width: 100%;
min-width: 100%;
font-size: 110%;
border: none;
border-radius: 8px;
}
.box-2-wrap button {
align-items: flex-end;
justify-content: center;
padding: 10px 2%;
width: 50%;
margin: 6% auto;
background-color: #178E44;
color: white;
font-size: 120%;
border: none;
border-radius: 4px;
}
#keyframes rotate {
0% {
transform: rotate(0deg);
}
50% {
transform: rotate(360deg);
}
100% {
transform: rotate(0deg);
}
}
JS
my JavaScript
function unSelectAll(){
var output = document.getElementsByClassName("out-put")[0];
output.innerHTML = "";
}
}
function copyEmails(){
var output = document.getElementsByClassName("out-put")[0];
output.select();
document.execCommand('copy');
unSelectAll();
var copyEmailsButton = document.getElementById("copyEmailsButton");
if (copyEmailsButton.style.animation !== "rotate 1s") {
copyEmailsButton.style.animation = "rotate 1s";
}else{
copyEmailsButton.style.animation = "none";
}
}
In the if-else block in copyEmails you specify, that the button will rotate for one second, if the animation-style isn't set "to rotate 1s". But if it is, it will just set the animation-style to none.
If you click on the button a third time, you will notife, that it will rotate again. This is because with the 2nd click, you have set the animation Style to none again.
This means, your Button will switch and rotate every 2nd click!
To let the button rotate everytime you click, change the if-else block to:
copyEmailsButton.style.animation = "rotate 1s";
setTimeout(function() {
copyEmailsButton.style.animation = "none"
}, 1000);
This sets the animation style to none again after the animation is finished, every time you click the button.
1 there is an error in your unselctAll function, one extra close } should be removed
2 reset the button style before next click, as in this example below
function unSelectAll(){
var output = document.getElementsByClassName("out-put")[0];
output.innerHTML = "";
}
function copyEmails(){
var output = document.getElementsByClassName("out-put")[0];
output.select();
document.execCommand('copy');
unSelectAll();
var copyEmailsButton = document.getElementById("copyEmailsButton");
if (copyEmailsButton.style.animation !== "rotate 1s") {
copyEmailsButton.style.animation = "rotate 1s";
}else{
copyEmailsButton.style.animation = "none";
}
}
.box-2-wrap {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
border: 0px solid #333;
}
.box-2-wrap textarea {
flex:1;
padding: 4%;
overflow-y: auto;
background-color: #333;
color: gold;
max-width: 100%;
min-width: 100%;
font-size: 110%;
border: none;
border-radius: 8px;
}
.box-2-wrap button {
align-items: flex-end;
justify-content: center;
padding: 10px 2%;
width: 50%;
margin: 6% auto;
background-color: #178E44;
color: white;
font-size: 120%;
border: none;
border-radius: 4px;
}
#keyframes rotate {
0% {
transform: rotate(0deg);
}
50% {
transform: rotate(360deg);
}
100% {
transform: rotate(0deg);
}
}
<textarea class="out-put" onmouseover="copyEmailsButton.style.animation = 'none';" placeholder="always click here before clicking the button"></textarea>
<button type="button" id="copyEmailsButton" onclick="copyEmails()">Copy Emails</button>
</div>