(setting disabled = 'true' didn't seem to work for me so this is another way around it)
How do you disable an HTML range slider, for example when a button is pressed:
<input type="range" class="tempo-slider" max="300" min="1" value="150" />
I couldn't find the answer anywhere but this is my fix to the issue:
My fix for it was constantly resetting the range slider's value when you a user tried to change it using:
event.target.value = bpm;
Where event is the clicking of the event slider.
My full code is here, I hope it can help someone:
//This is code taken from a larger oop project and so some of the logic may look janky, but I just made it work for this example
//These two variable need to be predefined
let bpm = 150;
let playing = false;
//Select your slider and button from your html:
const tempoSlider = document.querySelector(".tempo-slider");
const playButton = document.querySelector(".play");
//Update the html function, essentially purely for styling
updateHTML = function () {
if (!playing) {
tempoSlider.classList.toggle("inactive");
playButton.innerText = "Stop";
playButton.classList.toggle("active");
playing = true;
} else {
tempoSlider.classList.toggle("inactive");
playButton.innerText = "Play";
playButton.classList.toggle("active");
playing = false;
}
};
//this fucntion updates the temp text and the slider
function changeTempo(event) {
//get the temp number from the document
const tempoText = document.querySelector(".tempo-number");
if (!tempoSlider.classList.contains("inactive")) {
//if the slider isnt inactive then update the bpm as usual
bpm = event.target.value;
tempoText.innerText = bpm;
} else {
//else just make the slider reset to the preset bmp, this way it will not change
event.target.value = bpm;
}
}
//add event listeners to the button and the range slider
tempoSlider.addEventListener("input", function (event) {
changeTempo(event);
});
playButton.addEventListener("click", function () {
updateHTML();
});
/*All of this styling just makes it clear when the temp slider is inactive*/
:root {
--background-color: #ffffff;
--text-color: #322e2f;
}
body {
display: flex;
flex-direction: column;
align-items: center;
}
.play {
width: 10rem;
transition: all 0.5s ease;
padding: 1rem 2rem;
font-size: 1.5rem;
background: var(--text-color);
color: var(--background-color);
border: none;
cursor: pointer;
margin-top: 3rem;
outline: none;
border: solid 0.01rem var(--text-color);
}
.play.active {
color: var(--text-color);
background: var(--background-color);
border: solid 0.01rem var(--text-color);
}
.tempo {
margin: 1rem;
width: 20%;
}
.tempo-slider {
transition: all 0.5s ease;
padding: 0.3rem;
-webkit-appearance: none;
appearance: none;
margin: 1rem 0rem;
outline: none;
width: 100%;
position: relative;
background: var(--text-color);
cursor: pointer;
border-radius: 2rem;
border: solid 0.05rem var(--text-color);
}
.tempo-slider::-webkit-slider-thumb {
transition: all 0.5s ease;
-webkit-appearance: none;
appearance: none;
width: 1rem;
height: 1rem;
border-radius: 2rem;
background: var(--background-color);
cursor: pointer;
}
.tempo-slider.inactive {
background: var(--background-color);
}
.tempo-slider.inactive::-webkit-slider-thumb {
background: var(--text-color);
}
.tempo p {
font-size: 1.5rem;
text-align: center;
}
<!--This is part of a larger project I have scaled back to display the slider-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="style.css" />
</head>
<body>
<!--Basic button to say start an audio file-->
<button class="play">Play</button>
<!-- slider to devide the audio's bpm-->
<div class="tempo">
<input type="range" class="tempo-slider" max="300" min="1" value="150" />
<p>Tempo: <span class="tempo-number">150</span></p>
</div>
<script src="app.js"></script>
</body>
</html>
The full project should be done in the next week and available on my github here: https://github.com/MichealNestor01
Related
I'm using the following code to change prices in my pricing table:
function myFunction() {
var x = document.getElementById("prijs-small");
if (x.innerHTML === "17,50") {
x.innerHTML = "13,50";
} else {
x.innerHTML = "17,50";
}
var x = document.getElementById("prijs-medium");
if (x.innerHTML === "58") {
x.innerHTML = "30,50";
} else {
x.innerHTML = "58";
}
var x = document.getElementById("prijs-large");
if (x.innerHTML === "128,50") {
x.innerHTML = "61";
} else {
x.innerHTML = "128,50";
}
}
.prijs-button {
background-color: white;
color: #012d5d;
padding: 10px 20px;
border-radius: 30px;
}
<button class="prijs-button" onclick="myFunction()">150/350</button>
<div id="prijs-small">17,50</div>
<div id="prijs-medium">58</div>
<div id="prijs-large">128,50</div>
Now I want to style a toggle that does the same, with on the one side showing 150 (people icon) and other side 350 (people icon) as shown in this example:
As I'm using a button now to make the prices change, how can I turn this into this toggle? The green half should be the active part.
Thanks so much in advance!
Will this do? I've used a checkbox and styled it to look like a pill. Hopefully it's self-explanatory but if not drop me a comment and I'll elaborate.
body {
background-color: gray;
}
#mybutton {
width: 8rem;
height: 3rem;
border-radius: 100rem;
overflow: hidden;
}
#mybutton input {
display: none;
}
#mybutton>label {
display: flex;
}
.side {
width: 50%;
padding-inline: 0.15rem;
text-align: center;
line-height: 3rem;
background-color: white;
transition: background-color, color 300ms;
cursor: pointer;
}
#mybutton input:not(:checked)~.left {
background-color: #35CB8C;
color: white;
transition: background-color, color 300ms;
}
#mybutton input:checked~.right {
background-color: #35CB8C;
color: white;
transition: background-color, color 300ms;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css" integrity="sha512-xh6O/CkQoPOWDdYTDqeRdPCVd1SpvCA9XXcUnZS2FmJNp1coAFzvtCN9BmamE+4aHK8yyUHUSCcJHgXloTyT2A==" crossorigin="anonymous" referrerpolicy="no-referrer"
/>
<div id='mybutton'>
<label for='mybutton-checkbox'>
<input type=checkbox id='mybutton-checkbox'>
<div class='side left'>25<i class="fa fa-user" aria-hidden="true"></i></div>
<div class='side right'>100<i class="fa fa-user" aria-hidden="true"></i></div>
</label>
</div>
You can put two buttons next to each other with some border radiuses applied to them.
Some POC version here:
div.toggle {
font-size: 0; /* this is to remove empty inline space between two buttons. if you don't like it, you can use flexbox */
}
button {
width: 100px;
height: 50px;
font-size: 14px;
}
button.left {
border-right-width: 0;
border-radius: 20px 0 0 20px;
}
button.right {
border-radius: 0 20px 20px 0;
}
<div class="toggle">
<button class="left">25</button>
<button class="right">100</button>
</div>
Adding an image or icon inside button is totally possible so you can do if if you want.
By inserting two buttons with different images you might get the result you are seeking.
Then by using in CSS border-bottom-left: (The amount of px you want)px and border-top-left: (The amount of px you want)px you can style you buttons.
I have a problem with my div when I write in the text area and hit save nothing is show up. I have a problem with my div when I write in the text area and hit save nothing is show up
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="Go from idea to action in seconds with wesam to do list">
<title>wesam list to do</title>
<script>
function input() {
var name = document.getElementById("text").Value
document.getElementById("output").innerHTML = name;
}
</script>
<style>
#b {
background-color: red;
}
#output {
width: 100%;
height: 200px;
background-color: black;
color: black;
}
</style>
</head>
<body>
<form>
<h1> Add your tasks </h1>
<textarea id="text"></textarea>
<button onClick="input()" id=" b " type="button "> save</button>
<div id="output"></div>
</body>
Try this. There were a few issues with this code. I added comments to the changes.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="Go from idea to action in seconds with wesam to do list">
<title>wesam list to do</title>
<script>
function input(event) {
//added preventDefault() to keep the page from reloading
event.preventDefault();
//changed Value to value - watch your case
var name = document.getElementById("text").value;
document.getElementById("output").innerHTML = name;
}
</script>
<style>
#b {
background-color: red;
}
#output {
width: 100%;
height: 200px;
background-color: black;
/*changed the text color from black to white so you can see when the output is added*/
color: white;
}
</style>
</head>
<body>
<form>
<h1> Add your tasks </h1>
<textarea id="text"></textarea>
<button onClick="input(event)" id="b" type="button"> save</button>
<div id="output"></div>
</form>
</body>
</html>
Cheers!
Your output element has both a black background, and black text, so you won't see anything change.
You were missing a </form> tag.
It looks like you're trying to create a list of tasks, and each time you add a new task, and click "save" it adds a new task under the proceeding ones.
Here's an updated example that uses more modern JS methods that you might find useful. Links to the relevant documentation are at the bottom of the post.
// First we cache all our elements
const task = document.querySelector('textarea');
const list = document.querySelector('ul');
const button = document.querySelector('button');
// Instead of inline JS we add an event listener to
// the cached button element.
button.addEventListener('click', handleClick, false);
// `focus` the cursor in the textarea
task.focus();
function handleClick() {
// We create a new list item
const item = `<li>${task.value}</li>`;
// We add that to the list
list.insertAdjacentHTML('beforeend', item);
// Reset the textarea value
task.value = '';
// And refocus on it so we don't have to
// manually click in it to write a new task
task.focus();
}
button { background-color: red; color: white; }
<form>
<h3>Add your tasks</h3>
<textarea></textarea>
<button type="button">Save task</button>
</form>
<ul></ul>
Addition documentation
querySelector
Template/string literals
insertAdjacentHTML
addEventListener
There are couple problem:
You didn't close the form tag in HTML
you write the first letter of value as capital in input function
And you may did not look but your button background color is not coming that is because there is spaces inside the id in HTML just remove those and you're good to go.
And make a paragraph inside the output div and give him the id of output and than stor that into a variable and do o.innerText o is you output paragraph = i.value i is your input
I have added some features to to your application if you want to copy it i do not mined -
// ES6 Syntax
const render = () =>{
// Getting the value from HTML DOM to inputEl variable
const inputEl = document.getElementById('text');
// Getting the output paragraph from HTML DOM and storig it into output
const outputEl = document.getElementById('output-text');
// Rendering the inputEL value into outputEl
outputEl.textContent = inputEl.value;
}
// ES5-- Syntax
function renderES(){
// Getting the value from HTML DOM to inputEl variable
const inputEl = document.getElementById('text');
// Getting the output paragraph from HTML DOM and storig it into output
const outputEl = document.getElementById('output-text');
// Rendering the inputEL value into outputEl
outputEl.textContent = inputEl.value;
}
#import url('https://fonts.googleapis.com/css2?family=Nunito&display=swap');
:root{
--primary-color: rgb(26, 26, 26);
--secondary-color: white;
--font-family: Nunito, sans-serif;
--box-shadow: rgb(0 0 0) 1px 1px 3px 0px inset, rgb(48 48 48 / 50%) -1px -1px 3px 1px inset;;
--all-transition:transform ease-in-out 0.3s 0s;
}
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
body{
font-family: var(--font-family);
}
.main-content{
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.container{
border-radius: 10px;
box-shadow: var(--box-shadow);
width: 85%;
height: 270px;
display: flex;
justify-content: space-between;
align-items: center;
background-color: var(--primary-color);
flex-direction: column;
}
.container>h1{
margin-top: 15px;
color: var(--secondary-color);
text-transform: uppercase;
}
form{
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
padding: 5px;
width: 100%;
height: 75%;
}
form>textarea{
width: 95%;
height: 30%;
background-color: var(--primary-color);
border: none;
border-radius: 10px;
box-shadow: var(--box-shadow);
padding: 15px;
color: var(--secondary-color);
}
#output{
width: 95%;
height: 40%;
background-color: var(--primary-color);
box-shadow: var(--box-shadow);
color: var(--secondary-color);
padding: 10px;
}
form>button{
background-color: var(--primary-color);
box-shadow: var(--box-shadow);
width: 95%;
height: 30px;
border-radius: 10px;
border: none;
font-weight: bold;
margin-bottom: 10px;
color:var(--secondary-color);
transition: var(--all-transition);
cursor: pointer;
}
/* NTH CHILD */
form>textarea::placeholder{
color: var(--secondary-color);
}
/* Animations */
form>button:hover{
transform: scale(1.02)
}
form>button:active{
border: 1px solid var(--secondary-color);
}
<!doctype HTML>
<html>
<head>
<title>codedamn HTML Playground</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/style.css" />
</head>
<body>
<div class="main-content">
<div class="container">
<h1> Add your tasks </h1>
<form>
<textarea id="text" placeholder="Enter you task here.."></textarea>
<div id="output">
<p id="output-text"></p>
</div>
<button
type="button"
id="addtask-btn"
onclick="render()">
Save
</button>
<form>
</div>
</div>
<script src="/script.js"></script>
</body>
</html>
It seems that you haven't ended the
<form>
tag
I am trying to change the text every time the text hits the bottom of the scroll!
I haven't been able to figure out how to do it.
Also, Can someone help me remove the "undefined" from the end of the text?
(i want everything to be automatic, no buttons nor interactivity required please!)
my code is below!
<!DOCTYPE html>
<script>
function randomText() {
//array splashes
var say = [];
say[0] = "Welcome.";
say[1] = "Coming Soon";
say[2] = "eek";
//pick a random greeting
var howmany = 2;
var bRand = 0;
bRand = Math.random();
bRand = Math.floor(bRand * howmany);
//prepare and docwrite the greeting
sayWhat = say[bRand];
document.write(sayWhat)
document.close()
//direct type in html p element
//document.getElementById("splash").innerHTML ='javascript:alert("' + '");'
// I tried to make this work but it says no.
}
// Change Interval here to test. For eg: 5000 for 5 sec </script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</script>
<html lang="en" dir="ltr">
<head>
<link rel="preload" href="https://fonts.googleapis.com/css?family=Montserrat:ital,wght#0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" as="style" onload="this.rel = 'stylesheet'">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>Webpage is Under Maintenance</title>
</head>
<body class="red">
<style media="screen">
body{
font-family: 'Montserrat', sans-serif;
text-align: center;
color: white;
margin: 0;
}
h1{
color: white;
}
marquee{
height: 5rem;
text-align: center;
}
.red{
background: #c60929;
}
.green{
background: #106b03;
}
.play{
background: #ffdd33;
color: #333333;
}
.container{
background: rgba(0,0,0,0.3);
}
a{
color: white;
}
footer{
margin-top: 0.5rem;
background: rgba(0,0,0,0.7);
padding: 0.5rem;
}
</style>
<div class="container">
<h1>Site is Under Maintenance</h1>
<p>
This Webpage is Currently Under Maintenance. In other words, We are recoding or changing the code on this website!
<br>
<br>
If we have downloaded javascript or other files to this site. An Update will be Required after!
<br>
In the meantime, Check other Webpages! This Webpage may be down currently, but there should still be webpages at AstraOnline that are still functioning!
</p>
<noscript>
I see you have Javascript Disabled. You should try Enabling it, This Site Runs on Javascript!
</noscript>
<p>Current state: <span id="status" class="red">Under Maintenance</span></p>
<marquee direction="down"> <script> document.write(randomText()) </script> </marquee>
</div>
<script>
</script>
<style>
.simon{
margin: auto;
display: flex;
width: 15rem;
height: 15rem;
-webkit-flex-wrap: wrap;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
}
.simon > button{
flex: 50%;
border: 0.25rem solid black;
appearance: none;
}
.simon > button:active{
opacity: 0.8;
}
#r{
background: #e21b3c;
}
#b{
background: #1368ce;
}
#y{
background: #ffa602;
}
#g{
background: #26890c;
}
#alt{
background: #ffdd33;
border-radius: 0.5rem;
padding: 1rem;
box-shadow: 0.25rem 0.25rem rgba(0,0,0,0.5);
color: black;
font-weight: 800;
}
#alt a{
color: black;
}
</style>
```
"use strict";
const openModal = document.querySelector('[data-create]');
const exitModal = document.querySelector('[data-close]');
const saveBtn = document.querySelector('#save');
openModal.addEventListener('click', showModal);
exitModal.addEventListener('click', closeModal);
saveBtn.addEventListener('click', saveCard);
/*
Detects if text has been inputed. If not, an error is shown
if yes the createFlashCard and closed modal function are called.
*/
function saveCard() {
let questionArea = document.querySelector('#question');
let answerArea = document.querySelector('#answer');
let showAlert = document.querySelector('.show-error-message');
if (questionArea = null || questionArea.value == '') {
if (answerArea = null || answerArea.value == '') {
showAlert.classList.remove("hide-error");
}
setTimeout(() => {
showAlert.classList.add("hide-error");
}, 3000);
} else {
closeModal();
createFlashCard();
}
}
/*
Removes the is-hidden css class to open modal
*/
function showModal(e) {
let modal = document.querySelector('.modal-design');
modal.classList.remove("is-hidden");
}
/*
Adds the is-hidden css class to close modal
*/
function closeModal() {
let modal = document.querySelector('.modal-design');
modal.classList.add('is-hidden');
}
/*
Creates a flash card using input string values.
Then renders a card using the .innerHTML property.
Each card rendered will be clickable to show the answer.
*/
function createFlashCard() {
let questionText = document.querySelector('.question-text').value;
let answerText = document.querySelector('.answer-text').value;
let cardSection = document.querySelector('.card-container');
let createArticle = document.createElement('article');
createArticle.className += "card";
createArticle.innerHTML = `
<div class="card-question-button">
<h4 id="title">${questionText}</h4>
<button id="show">></button>
</div>
<div id="answer-card">
<p id="answer-card-p">${answerText}</p>
</div>`;
cardSection.appendChild(createArticle);
openCloseCards();
}
function openCloseCards() {
let buttons = document.querySelectorAll('.card-question-button');
buttons.forEach(function (btn) {
btn.addEventListener('click', function (e) {
let questions = e.currentTarget.parentElement;
questions.classList.toggle("show-text");
})
})
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
line-height: 1.5;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
}
/*
variables
*/
:root {
--primary-color:#5dcbd8;
--secondary-color: hsl(186, 100%, 94%);
--third-color: #F6F6F8;
--fourth-color: #fff;
--button-border: none;
--error-color: hsl(0deg 58% 70%);
--shadow: 0px 2px 3px 0 hsla(0 , 0%, 0%, 0.2);
}
header {
padding: 15px;
color: var(--third-color);
height: 100px;
background-color: var(--primary-color);
}
/**
Prompt question card
*/
.prompt-question {
display: flex;
padding: 15px;
align-items: center;
justify-content: space-around;
}
#create {
border: var(--button-border);
border-radius: 5px;
background-color: var(--secondary-color);
height: 60px;
width: 70px;
font-size: 25px;
transition: .3s ease-in-out;
}
#create:hover {
cursor: pointer;
background-color: #b5f0f7;
}
/*
Modal Design
*/
.modal-placement{
display: flex;
justify-content: center;
}
.modal-design {
width: 600px;
padding: 20px;
display: flex;
flex-direction: column;
justify-content: space-between;
background-color: #F6F6F8;
box-shadow:var(--shadow);
border-radius: 4px;
margin: 30px;
}
.is-hidden {
visibility: hidden;
opacity: 1;
}
.erase-modal-c {
display: flex;
justify-content: flex-end;
}
#erase {
background-color:var(--error-color);
display: flex;
justify-content: center;
border: none;
padding: 5px;
height: 25px;
width: 25px;
}
#close {
margin-top: -8px;
margin-left: 3px;
font-size: 20px;
transform: rotate(45deg);
}
#erase:hover {
cursor: pointer;
}
h3 {
padding-top: 15px;
}
/**
Textarea design
*/
#question, #answer {
height: 90px;
}
textarea {
font-size: 15px;
padding: 4px;
resize: vertical;
}
#save {
border: var(--button-border);
margin-top: 25px;
height: 45px;
font-size: 15px;
background-color:var(--primary-color);
color: var(--third-color);
}
#save:hover {
cursor: pointer;
background-color: #90d8e0;
}
.show-error-message {
background-color: var(--error-color);
color: var(--fourth-color);
margin-top: 15px;
padding: 10px;
text-align: center;
}
.hide-error {
visibility: hidden;
opacity: 0;
}
/*
Card container
*/
.card-container {
display: grid;
background-color: var(--third-color);
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr;
margin-top: 40px;
}
#title {
margin-left: 10px;
}
.card {
display: flex;
margin: 20px;
flex-direction: column;
align-items: center;
background-color:var(--fourth-color);
padding: 7px;
justify-content: space-between;
box-shadow:var(--shadow);
border-radius: 5px;
transition: .3s ease-in-out;
z-index: 1000;
}
.card-question-button {
display: flex;
justify-content: space-between;
padding: 5px;
width: 100%;
}
.card-question-button:hover {
cursor: pointer;
}
/*
Answer card
*/
#answer-card {
display: none;
border-top: 1px solid rgba(0, 0, 0, 0.2);
padding: 15px;
text-align: left;
}
#answer-card-p {
text-align: left;
}
.show-text #answer-card {
display: block;
}
#show {
border: none;
background-color: var(--fourth-color);
font-size: 20px;
transition: .2s ease-in-out;
}
#show:hover {
cursor:pointer;
transform: translateX(-2px);
}
/* Media Queries */
#media screen and (max-width: 800px) {
.prompt-question {
box-shadow:var(--shadow);
border-radius: 4px;
margin: 20px;
}
.card-container {
grid-template-columns: 1fr;
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<header>
<h1>Flash Cards +</h1>
</header>
<article class="prompt-question">
<button id="create" data-create>+</button>
<p class="info">
Create a new card
</p>
</article>
<article class="modal-placement">
<section class="modal-design is-hidden">
<div class="erase-modal-c">
<button id="erase" data-close>
<p id="close">+</p>
</button>
</div>
<h3>Question</h3>
<textarea class="question-text textA" id="question"></textarea>
</div>
<h3>Answer</h3>
<textarea class="answer-text textA" id="answer"></textarea>
<button id="save">Save</button>
<div class="show-error-message hide-error">Please Submit Values</div>
</section>
</article>
<section class="card-container">
</section>
<script src="js/script.js"></script>
</html>
This is a flashcard project I am building. I am fairly new to programming and was looking for help on this particular bug that I cannot wrap my head around. Included in the gist is the css, html, and javascript code. Any tips on code structure is also appreciated.
Question:
When I dynamically create cards using JavaScript I want to show open and close behavior for each of them. The first card created does open and close as expected. However, the following cards do not. For example, one stays open while the other one closes.
I would like each card to open and close independently when clicked after dynamically being created. It seems the behavior is depending on the previous card.
When you call createFlashCard() The html that is generated:
<div class="card-question-button">
<h4 id="title">${questionText}</h4>
<button id="show">></button>
</div>
<div id="answer-card">
<p id="answer-card-p">${answerText}</p>
</div>
These elements will have the same ID's used more than once in a page when they should be unique. Add a unique identifier or remove the id attribute if its not needed. For example:
let cardCount=0;
function createFlashCard() {
cardCount++;
let questionText = document.querySelector('.question-text').value;
let answerText = document.querySelector('.answer-text').value;
let cardSection = document.querySelector('.card-container');
let createArticle = document.createElement('article');
createArticle.className += "card";
let title="title"+ cardCount;
let buttonID="show"+cardCount;
...
<button id=${buttonID}>
...
}
When you are executing your openCloseCards function, you are creating multiple event listeners based on the number of items in buttons.
I'd recommend adding the event listener in your createFlashCard function and removing the function definition of openCloseCards and it's call.
With this change the code seems to working as it should.
function createFlashCard() {
let questionText = document.querySelector('.question-text').value;
let answerText = document.querySelector('.answer-text').value;
let cardSection = document.querySelector('.card-container');
let createArticle = document.createElement('article');
createArticle.className += "card";
createArticle.innerHTML = `
<div class="card-question-button">
<h4 id="title">${questionText}</h4>
<button id="show">></button>
</div>
<div id="answer-card">
<p id="answer-card-p">${answerText}</p>
</div>`;
cardSection.appendChild(createArticle);
createArticle.addEventListener('click', function(e) {
let questions = e.target.parentElement;
questions.classList.toggle("show-text");
console.log(questions.classList)
})
}
I've added a search bar in the header that is set to display: none by default and I used js to make it appear on a button click via assigning a .show class which contains display: block !important to the search bar element (#search). It's working fine but my only problem is the rough transition from display: none to block, so I've been looking into ways to make this transition smooth and most of the answers I found were using jQuery, which I don't really want to do since I'm still in the learning phase of js, so if there's a way I can do this using vanilla js, please help me with it.
Here's my code https://jsfiddle.net/5jxLq9ck/
In CSS line 38, I add the .show utility class
.show {
display: block !important;
}
And I'm assuming I'll have to edit something in here (js) to get the desired effect:
function showSearch(e) {
e.preventDefault;
if (
e.target.classList.contains("show-btn") ||
e.target.classList.contains("fas")
) {
const searchBar = document.querySelector("#search");
searchBar.classList.add("show");
}
}
Additional question: is my use of e.preventDefault correct here? The functionality didn't work until I used it.
Thanks a lot in advance.
Here is an updated snippet, I've changed the input width for the animation. You can make it even more smooth by set the input height.
const searchDiv = document.querySelector("#search-div");
// ADD EVENT LISTENERS
searchDiv.addEventListener("click", showSearch);
// FUNCTION: SHOW SEARCH BAR ON BUTTON CLICK
function showSearch(e) {
e.preventDefault;
if (
e.target.classList.contains("show-btn") ||
e.target.classList.contains("fas")
) {
const searchBar = document.querySelector("#search");
searchBar.classList.add("show");
}
}
/* GENERAL */
:root {
--light-color: #ccc;
--lighter-color: #f4f4f4;
--dark-color: #333;
--darker-color: #222;
--brand-color: #ff4;
--danger: #f44;
--danger-dark: #c00;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background: var(--dark-color);
color: var(--light-color);
font-family: "Trebuchet MS";
}
ul li {
list-style: none;
}
button,
input {
outline: none;
}
/* UTILITY */
.highlight {
color: var(--brand-color);
}
.show {
width: 300px !important;
border: black 2px solid;
padding: 0.6rem 1rem;
}
/* HEADER */
header {
background: var(--darker-color);
display: flex;
flex-direction: row;
align-items: center;
text-align: center;
justify-content: space-between;
padding: 1.4rem 6rem;
width: 100%;
}
#logo {
font-size: 2.4rem;
font-weight: 200;
}
#search-div {
width: auto;
height: auto;
display: flex;
gap: 0.4rem;
}
.show-btn {
padding: 0.6rem 0.7rem;
background: var(--light-color);
border-radius: 5px;
border: none;
transition: ease-in 300ms;
font-size: 1.2rem;
cursor: pointer;
height: 100%;
margin-top: 2px;
}
.show-btn:hover {
background: var(--brand-color);
transition: ease-in 300ms;
}
#search {
width: 0;
background: var(--lighter-color);
color: var(--darker-color);
height: 100%;
font-size: 1.2rem;
border-radius: 2px;
transition: ease-in 300ms;
border: none;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Contact List</title>
<link rel="stylesheet" href="css/style.css">
<script src="https://kit.fontawesome.com/3ad7573e76.js" crossorigin="anonymous"></script>
</head>
<body>
<header>
<div id="logo-div">
<h1 id="logo">
<span class="highlight"><i class="fas fa-user-friends"></i></span> My<span
class="highlight">Contact</span>List
</h1>
</div>
<div id="search-div">
<button class="show-btn"><i class="fas fa-search"></i></button>
<input id="search" type="text" placeholder="Search contacts...">
</div>
</header>
<script src="js/main.js"></script>
</body>
</html>
You can make the transition from no display to block display smooth by playing with the opacity property so that when the element is given the "show" class it animates from an opacity of 0 to an opacity of 1 like so.
function showSearch(e) {
e.preventDefault;
if (
e.target.classList.contains("show-btn") ||
e.target.classList.contains("fas")
) {
const searchBar = document.querySelector("#search");
searchBar.classList.add("show");
}
}
document.getElementById("show").addEventListener("click", e => {
showSearch(e);
});
#keyframes smooth {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.show {
animation: smooth 1s ease;
display: block !important;
}
.none {
display: none;
}
<div class="none" id="search">Example</div>
<button class="show-btn fas" id="show">Show</button>