I have a todo list and I want to have editable task so I gave contenteditable = "true" attribute to p tag which contains the task content but when I left click on it, it does not work but when I right click it works! I gave this attribute to heading and it works just fine but its not working on tasks( p tag).
so my question is how can I make tasks editable when I click on them?(not by right click I want left click)
here is my code, please first make a task buy clicking on + button
const taskInput = $(".main__input");
const taskRow = $(".task-row");
const task = $("li");
let id = 0;
// adding task
const addTask = function() {
const markup = `
<li data-id=${id}>
<div class="main">
<div class="task__checkbox">
<input type="checkbox" class="checkbox">
</div>
<p class="task" contenteditable="true">${taskInput.val()}</p>
</div>
<div class="btn-task btn-delete icon" data-id=${id}>
<i class="fa-sharp fa-solid fa-trash"></i>
</div>
</li>
`;
taskRow.append(markup);
id++;
taskInput.val("");
};
$(".btn-plus").on("click", function() {
if (taskInput.val() !== "") addTask();
});
// remove element first solution
taskRow.on("click", ".btn-delete", function(e) {
$(this).parent().remove();
});
taskRow.on("change", ".task__checkbox", function() {
$(this).siblings(".task").toggleClass("checked");
});
$(window).on("keypress", function(e) {
if (e.which === 13 && taskInput.val() !== "") addTask();
});
taskRow.sortable();
*,
*::after,
*::before {
margin: 0;
padding: 0;
box-sizing: inherit;
list-style: none;
}
html {
font-size: 62.5%;
box-sizing: border-box;
}
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
.todo {
width: 40rem;
border-radius: 15px;
overflow: hidden;
box-shadow: 0 0 10px rgb(122, 122, 122);
}
h1 {
background-color: rgb(46, 89, 89);
font-size: 3rem;
font-weight: bold;
color: #fff;
padding: 2rem 1rem;
text-align: center;
}
.row {
display: flex;
}
.main__input {
padding: 1.4rem;
border: none;
/* border-bottom: 1px solid rgb(116, 116, 116);
border-left: 1px solid rgb(116, 116, 116); */
width: 100%;
}
.main__input:focus {
outline: none;
}
.icon {
display: flex;
justify-content: center;
align-items: center;
background-color: rgb(37, 115, 115);
color: #fff;
width: 20%;
font-size: 2rem;
transition: all 0.3s;
}
.icon:hover {
cursor: pointer;
background-color: rgb(52, 81, 81);
}
.icon:active {
background-color: rgb(37, 115, 115);
}
.task-row {
display: flex;
}
.task-block {
width: 80%;
display: flex;
}
.task__checkbox {
width: 10%;
}
.main {
display: flex;
width: 80%;
}
.task__checkbox {
display: flex;
justify-content: center;
align-items: center;
background-color: rgb(37, 115, 115);
padding: 1rem;
}
.checkbox {
width: 1.8rem;
height: 1.8rem;
}
.task {
font-size: 1.8rem;
font-weight: bold;
padding: 1.4rem 1rem;
border: 0.01px solid #999;
width: 100%;
}
.task-row {
flex-direction: column;
}
li {
width: 100%;
display: flex;
}
.checked {
text-decoration: line-through;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.13.1/jquery-ui.min.js"></script>
<div class="todo">
<h1 class="heading" contenteditable="true">To-do list</h1>
<div class="todo-body">
<div class="row add-block">
<div class="main">
<input type="text" class="main__input" placeholder="A task you want to compelete">
</div>
<div class="btn-plus icon">
<i class="fa-solid fa-plus"></i>
</div>
</div>
<ul class="row task-row"></ul>
</div>
</div>
As #cbroe and I have mentioned in the comments, the behavior is caused by jQuery UI Sortable Plugin.
The fix is fairly easy, we'll simply use the cancel option of the sortable method to prevent sorting if you start on elements matching the selector. Source: Sortable Widget - jQuery UI
We will pass the p[conteneditable] selector (or any other selector you see fit) to prevent dragging from the p tag that contains the todo text.
Here's a live demo:
const taskInput = $(".main__input");
const taskRow = $(".task-row");
const task = $("li");
let id = 0;
// adding task
const addTask = function() {
const markup = `
<li data-id=${id}>
<div class="main">
<div class="task__checkbox">
<input type="checkbox" class="checkbox">
</div>
<p class="task" contenteditable="true">${taskInput.val()}</p>
</div>
<div class="btn-task btn-delete icon" data-id=${id}>
<i class="fa-sharp fa-solid fa-trash"></i>
</div>
</li>
`;
taskRow.append(markup);
id++;
taskInput.val("");
};
$(".btn-plus").on("click", function() {
if (taskInput.val() !== "") addTask();
});
// remove element first solution
taskRow.on("click", ".btn-delete", function(e) {
$(this).parent().remove();
});
taskRow.on("change", ".task__checkbox", function() {
$(this).siblings(".task").toggleClass("checked");
});
$(window).on("keypress", function(e) {
if (e.which === 13 && taskInput.val() !== "") addTask();
});
/** drag & drop is disabled on p tags having content attribute set. You still able to move the item around by dragging from elsewhere (from the delete button for example) */
taskRow.sortable({
cancel: 'p[contenteditable=true]'
});
*,
*::after,
*::before {
margin: 0;
padding: 0;
box-sizing: inherit;
list-style: none;
}
html {
font-size: 62.5%;
box-sizing: border-box;
}
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
.todo {
width: 40rem;
border-radius: 15px;
overflow: hidden;
box-shadow: 0 0 10px rgb(122, 122, 122);
}
h1 {
background-color: rgb(46, 89, 89);
font-size: 3rem;
font-weight: bold;
color: #fff;
padding: 2rem 1rem;
text-align: center;
}
.row {
display: flex;
}
.main__input {
padding: 1.4rem;
border: none;
/* border-bottom: 1px solid rgb(116, 116, 116);
border-left: 1px solid rgb(116, 116, 116); */
width: 100%;
}
.main__input:focus {
outline: none;
}
.icon {
display: flex;
justify-content: center;
align-items: center;
background-color: rgb(37, 115, 115);
color: #fff;
width: 20%;
font-size: 2rem;
transition: all 0.3s;
}
.icon:hover {
cursor: pointer;
background-color: rgb(52, 81, 81);
}
.icon:active {
background-color: rgb(37, 115, 115);
}
.task-row {
display: flex;
}
.task-block {
width: 80%;
display: flex;
}
.task__checkbox {
width: 10%;
}
.main {
display: flex;
width: 80%;
}
.task__checkbox {
display: flex;
justify-content: center;
align-items: center;
background-color: rgb(37, 115, 115);
padding: 1rem;
}
.checkbox {
width: 1.8rem;
height: 1.8rem;
}
.task {
font-size: 1.8rem;
font-weight: bold;
padding: 1.4rem 1rem;
border: 0.01px solid #999;
width: 100%;
}
.task-row {
flex-direction: column;
}
li {
width: 100%;
display: flex;
}
.checked {
text-decoration: line-through;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.13.1/jquery-ui.min.js"></script>
<div class="todo">
<h1 class="heading" contenteditable="true">To-do list</h1>
<div class="todo-body">
<div class="row add-block">
<div class="main">
<input type="text" class="main__input" placeholder="A task you want to compelete">
</div>
<div class="btn-plus icon">
<i class="fa-solid fa-plus"></i>
</div>
</div>
<ul class="row task-row"></ul>
</div>
</div>
I also recommend looking at portlets as they provide a better way (in my opinion) to introduce drag & drop into your elements.
Related
newbie here...
I am working on some simple project where I am trying to simulate bank app.
Thing is that when I click on send money button, I want to take value from input value, and then subtract this value from my whole account balance.
Really simple, but after first transaction I get value which I want, but after second time I get innerText displaying "Nan" instead of some number value.
Here it is javascript file, if you can see from this why I get error.
Also here it is html and css if you don't understand what I am talking about.
////////////////// TOTAL MONEY FROM CARDS ///////////////////////
const totalMoney = document.querySelector(`.totalMoney`);
const allcards = document.querySelectorAll(`.cards`);
let totalMoneyAccount = 0;
allcards.forEach((kartica) => {
let novacNaKartici = kartica.querySelector(`.novacNaKartici`).innerText;
novacNaKartici = parseInt(novacNaKartici);
totalMoneyAccount += novacNaKartici;
totalMoney.innerText = ` ${replika2} $`;
});
//////////////////////////// TRANSFER MONEY TO SOMEONE /////////////////////////////
const reciver = document.querySelector(`input[name='recivier']`);
let amount = document.querySelector(`input[name='amount']`);
const sendMoneyBtn = document.querySelector(`.sendBtn`);
const transakcijeParent = document.querySelector(`.transakcije`);
sendMoneyBtn.addEventListener(`click`, () => {
amount = parseInt(amount.value);
totalMoneyAccount = totalMoneyAccount - amount;
updateProfile(totalMoneyAccount);
});
function updateProfile(totalMoneyAccount) {
totalMoney.innerHTML = totalMoneyAccount;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD#20..48,100..700,0..1,-50..200"
/>
<link rel="stylesheet" href="style.css" />
<title>Bank app</title>
</head>
<body>
<div class="container">
<div class="profile">
<div class="header">
<span class="material-symbols-outlined"> notifications </span>
<span class="material-symbols-outlined"> search </span>
</div>
<div class="person">
<img src="/img/cost1.jpg" alt="" />
<p>Random user</p>
<span class="totalMoney" style="font-size: 20px;"></span>
</div>
<div class="menu">
<div class="account flex">
<span class="material-symbols-outlined"> manage_accounts </span>
<p>Accounts</p>
</div>
<div class="transactions flex">
<span class="material-symbols-outlined"> receipt_long </span>
<p>Transactions</p>
</div>
<div class="bonus flex">
<span class="material-symbols-outlined"> star </span>
<p>Bonus</p>
</div>
<div class="invest flex">
<span class="material-symbols-outlined"> trending_up </span>
<p>Investments</p>
</div>
<div class="logOut flex">
<span class="material-symbols-outlined"> logout </span>
<p>Log Out</p>
</div>
</div>
</div>
<div class="main">
<div class="left">
<div class="naslov">
<p>Cards</p>
<span class="material-symbols-outlined">
add_circle
</span>
</div>
<div class="allCards">
<div class="cards changeJustify">
<div class="singleCard">
<img src="/img/visa.png" alt="" class="changeImg"/>
</div>
<div class="opis">
<p style="color: grey; font-size:20px">VISA</p>
<p style="color: black; font-size:16px" class="balance1 changeBalance">Balance:</p>
</div>
<div class="balance">
<span class="material-symbols-outlined changeSpan dots">
more_vert
</span>
<span style="font-size: 22px; color:grey(59, 59, 59);" class="novacNaKartici">2500$</span>
</div>
</div>
<div class="cards changeJustify">
<div class="singleCard ">
<img src="/img/american.jpg" alt="" class="changeImg"/>
</div>
<div class="opis ">
<p style="color: grey; font-size:20px">VISA</p>
<p style="color: grey; font-size:16px" class="balance1 changeBalance">Balance:</p>
</div>
<div class="balance ">
<span class="material-symbols-outlined changeSpan dots" >
more_vert
</span>
<span style="font-size: 22px; color:black;" class="novacNaKartici">3500$</span>
</div>
</div>
</div>
<p style="font-size: 30px;
color: grey;
font-weight: bold;">Transactions</p>
<div class="transakcije">
</div>
</div>
</div>
<div class="right">
<p style="font-size: 30px;
color: grey;
font-weight: bold;">Transfer money</p>
<div class="transfer">
<label for="recivier">Transfer to</label>
<input type="text" placeholder="antonio3101" name="recivier">
<label for="amount">Amount</label>
<input type="number" placeholder="$300..." name="amount">
<button class="sendBtn">Send</button>
</div>
</div>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
body {
padding: 0;
margin: 0;
box-sizing: border-box;
font-family: sans-serif;
}
.container {
width: 100vw;
height: 100vh;
display: flex;
background-color: #f1f2f6;
}
.profile {
height: 100vh;
width: 20%;
background-color: #1d1c57;
display: flex;
flex-direction: column;
color: white;
}
.profile .header {
display: flex;
padding: 30px;
align-items: center;
justify-content: space-between;
color: #7979a6;
}
.profile .header span {
font-size: 26px;
}
.profile .header span:hover {
color: white;
}
.profile .person {
margin-top: 40px;
display: flex;
flex-direction: column;
align-items: center;
}
.profile .person img {
width: 150px;
height: 150px;
border-radius: 50%;
}
.profile .person p {
font-size: 26px;
color: #c6c5d8;
}
.profile .menu {
margin-top: 100px;
padding: 20px;
background-color: #262467;
border-radius: 30px;
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
height: 100%;
position: relative;
font-size: 22px;
color: #7c7eaa;
}
.profile .flex {
margin-left: 20px;
display: flex;
align-items: center;
gap: 20px;
}
.profile .flex:hover {
margin-left: 40px;
color: white;
transition: ease-in-out;
}
.logOut {
position: absolute;
bottom: 50px;
}
/*-------------------------- KARTICE ----------------------------------------- */
.main .naslov {
color: grey;
font-size: 30px;
font-weight: bold;
}
.naslov {
display: flex;
align-items: center;
justify-content: space-between;
}
.naslov span {
font-size: 32px;
}
.naslov span:hover {
color: black;
}
.main .left {
display: flex;
flex-direction: column;
margin-left: 30px;
}
.main .left .cards {
background-color: #ffffff;
padding: 20px;
display: flex;
padding: 20px;
border-radius: 20px;
}
.cards {
margin-top: 10px;
}
.cards .singleCard {
display: flex;
width: 100%;
}
.allCards {
display: flex;
flex-direction: column;
}
.cards .singleCard img {
width: 250px;
padding-right: 10px;
}
.cards .opis p {
margin: 0;
padding: 0;
margin-left: 10px;
}
.cards .opis {
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
}
.cards .balance {
margin-left: 30px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
}
/*------------------------------- CHANGE CARD -------------------------------- */
.changeImg {
height: 50px;
object-fit: cover;
}
.changeSpan {
display: none;
}
.changeJustify {
display: flex;
align-items: center;
}
.changeBalance {
display: none;
}
/*-------------------------- TRANSAKCIJE ----------------------------------------- */
.transakcije {
background-color: white;
display: flex;
flex-direction: column;
padding: 10px;
}
.single-transaction {
display: flex;
margin-left: 10px;
justify-content: space-between;
align-items: center;
padding: 10px;
border-bottom: 1px solid grey;
}
.single-transaction img {
height: 60px;
width: 60px;
border-radius: 50%;
object-fit: cover;
}
.single-transaction .destination {
font-size: 16px;
color: rgb(73, 73, 73);
font-weight: bold;
}
.single-transaction .amount {
color: rgb(30, 149, 30);
font-weight: bold;
font-size: 16px;
}
.single-transaction:last-child {
border-bottom: 0;
}
/*-------------------------- RIGHT SECTIONS ----------------------------------------- */
/*-------------------------- TRANSFER MONEY ----------------------------------------- */
.right {
display: flex;
flex-direction: column;
margin-left: 100px;
}
.right .transfer {
background-color: #1d1c57;
padding: 50px 20px;
border-radius: 10px;
margin-left: 10px;
margin-right: 20px;
}
.right .transfer input {
height: 30px;
font: 24px;
margin-left: 10px;
}
.right .transfer label {
margin-left: 20px;
color: white;
}
.right .transfer button {
padding: 10px 15px;
color: black;
background-color: white;
border-radius: 5px;
border: 0;
margin-left: 20px;
margin-right: 20px;
}
You are overwriting your amount variable (which points to an input element) with the value inputted into said input.
Hence, after the first click you no longer have a reference to the input element: your code tries to read the value property of the integer amount of the last transaction. This results in the following evaluation: parseInt(amount.value) -> parseInt(undefined) -> NaN.
Change this code:
sendMoneyBtn.addEventListener(`click`, () => {
amount = parseInt(amount.value);
totalMoneyAccount = totalMoneyAccount - amount;
updateProfile(totalMoneyAccount);
});
to something like this:
sendMoneyBtn.addEventListener(`click`, () => {
const amountValue = parseInt(amount.value);
totalMoneyAccount = totalMoneyAccount - amountValue;
updateProfile(totalMoneyAccount);
});
Credit to #JohnnyMopp for noticing it first.
This question already has answers here:
How do I detect a click outside an element?
(91 answers)
Closed 1 year ago.
The community reviewed whether to reopen this question 1 year ago and left it closed:
Original close reason(s) were not resolved
My current code opens up an input via a click by adding a class. I'm having trouble adding a second click that removes the added class when the user clicks off the input. I added a second click event but it just stops my first click event from working.
Is there a different way to approach this using pure JavaScript?
(Commented out failed attempt.)
let searchElement = document.querySelector('#searchElement');
let offCanvas = document.querySelector('#main');
searchElement.addEventListener('click', () => {
searchElement.classList.add('extendInputSearch');
});
// offCanvas.addEventListener('click', () => {
// searchElement.classList.remove('extendInputSearch');
// });
* {
padding: 0;
margin: 0;
}
html,
body {
height: 100%;
width: 100%;
}
main {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
background-color: #e1e2f1;
}
form {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
}
input {
width: 100%;
height: 32px;
border: none;
outline: none;
font-size: 1rem;
}
.inputSearch {
display: flex;
align-items: center;
width: 100%;
max-width: 15px;
padding: 8px 20px;
background-color: #ffffff;
border: 1px solid transparent;
border-radius: 6px;
transition: all 0.6s cubic-bezier(0.16, 1, 0.3, 1);
}
.inputSearch:hover {
border: 1px solid #7e51fa;
}
.inputSearch i {
color: #7e51fa;
margin-right: 20px;
}
.extendInputSearch {
max-width: 400px;
}
<link rel="stylesheet" href="https://pro.fontawesome.com/releases/v5.10.0/css/all.css" integrity="sha384-AYmEC3Yw5cVb3ZcuHtOA93w35dYTsvhLPVnYs9eStHfGJvOvKxVfELGroGkvsg+p" crossorigin="anonymous"/>
<main id="main">
<form>
<div id="searchElement" class="inputSearch">
<i class="fas fa-search"></i>
<input type="text" placeholder="Search">
</div>
</form>
</main>
The problem with your attempt is that the event listener to remove the class is applied to the entire #main element, which includes searchElement. That means both event listeners are applied to the searchElement, and when you click on the searchElement, the class is first added (with the first listener) and then removed (with the second listener).
To make it work, you need to change the second listener to specifically exclude the searchElement. For example, in this code, we add a click listener to the whole document. In the listener, we check if the click is outside the searchElement by using the Node.contains() function on the event parameter. If the clicked element is not a child of searchElement (that is, the click is outside searchElement), we remove the extendInputSearch class from searchElement.
let searchElement = document.querySelector('#searchElement');
searchElement.addEventListener('click', () => {
searchElement.classList.add('extendInputSearch');
});
document.addEventListener('click', (e) => {
if(!searchElement.contains(e.target)){
searchElement.classList.remove('extendInputSearch');
}
});
* {
padding: 0;
margin: 0;
}
html,
body {
height: 100%;
width: 100%;
}
main {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
background-color: #e1e2f1;
}
form {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
}
input {
width: 100%;
height: 32px;
border: none;
outline: none;
font-size: 1rem;
}
.inputSearch {
display: flex;
align-items: center;
width: 100%;
max-width: 15px;
padding: 8px 20px;
background-color: #ffffff;
border: 1px solid transparent;
border-radius: 6px;
transition: all 0.6s cubic-bezier(0.16, 1, 0.3, 1);
}
.inputSearch:hover {
border: 1px solid #7e51fa;
}
.inputSearch i {
color: #7e51fa;
margin-right: 20px;
}
.extendInputSearch {
max-width: 400px;
}
<link rel="stylesheet" href="https://pro.fontawesome.com/releases/v5.10.0/css/all.css" integrity="sha384-AYmEC3Yw5cVb3ZcuHtOA93w35dYTsvhLPVnYs9eStHfGJvOvKxVfELGroGkvsg+p" crossorigin="anonymous"/>
<main id="main">
<form>
<div id="searchElement" class="inputSearch">
<i class="fas fa-search"></i>
<input type="text" placeholder="Search">
</div>
</form>
</main>
try it:
let searchElement = document.querySelector('#searchElement');
let offCanvas = document.querySelector('#main');
searchElement.addEventListener('click', () => {
searchElement.classList.add('extendInputSearch');
});
document.addEventListener('click', (e) => {
const searchElement = document.querySelector('#searchElement');
if (e.target != searchElement && e.target != searchElement.querySelector('i') && e.target != searchElement.querySelector('input')) {
searchElement.classList.remove('extendInputSearch');
}
});
* {
padding: 0;
margin: 0;
}
html,
body {
height: 100%;
width: 100%;
}
main {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
background-color: #e1e2f1;
}
form {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
}
input {
width: 100%;
height: 32px;
border: none;
outline: none;
font-size: 1rem;
}
.inputSearch {
display: flex;
align-items: center;
width: 100%;
max-width: 15px;
padding: 8px 20px;
background-color: #ffffff;
border: 1px solid transparent;
border-radius: 6px;
transition: all 0.6s cubic-bezier(0.16, 1, 0.3, 1);
}
.inputSearch:hover {
border: 1px solid #7e51fa;
}
.inputSearch i {
color: #7e51fa;
margin-right: 20px;
}
.extendInputSearch {
max-width: 400px;
}
<link rel="stylesheet" href="https://pro.fontawesome.com/releases/v5.10.0/css/all.css" integrity="sha384-AYmEC3Yw5cVb3ZcuHtOA93w35dYTsvhLPVnYs9eStHfGJvOvKxVfELGroGkvsg+p" crossorigin="anonymous"/>
<main id="main">
<form>
<div id="searchElement" class="inputSearch">
<i class="fas fa-search"></i>
<input type="text" placeholder="Search">
</div>
</form>
</main>
Hello everyone~ I am a beginner in programming, and I am completing a task today! But I have some difficulties~
I hope everyone can help me. My English is not very good, but I try to describe my problem completely!
Expected effect
Click the input box to pop up the window
Click the item, the selected item will have a yellow background, and then press confirm to put the selected item in the input input box, and then the pop-up window will disappear.
If you click cancel, the original options will be kept, and the pop-up window will disappear.
However, I just learned jquery recently. I don't know how to implement click confirm and put the item in the input, and how to click cancel to keep the original item and pop out of the window.
Hope you can get help here, thank you again for watching.
$(function(){
$('.input_box').on('click',function(){
$('.sport').css('display','block');
})
$('.sport').click(function(e){
if(e.target.classList.contains('sport')){
$(this).css('display','none');
}
})
$('.sport').click(function(e){
if(e.target.classList.contains('sport')){
$(this).css('display','none');
}
})
$('.item').on('click',function(){
$(this).toggleClass('active');
})
// How to rewrite this program
$('.confirm').on('click',function(e){
// only a little change here
const val = e.target.getAttribute("value");
$('.input_box').val(val);
$('.sport_content').trigger("click");
})
});
.input_box {
width: 500px;
height: 60px;
font-size: 30px;
}
.sport {
background-color: rgba(0, 0, 0, 0.3);
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
position: absolute;
top: 0;
display: none;
}
.sport_content {
width: 500px;
padding: 20px;
margin: 0 auto;
background-color: red;
}
.sport_content .title {
text-align: center;
padding: 10px;
font-size: 30px;
font-weight: 800;
}
.sport_content .category {
display: flex;
}
.sport_content .category .item {
width: 100px;
border: 1px solid #fff;
text-align: center;
border-radius: 10px;
padding: 10px;
margin: 10px;
}
.sport_content .category .active {
background-color: yellow;
}
.sport_content .footer {
display: flex;
justify-content: space-between;
margin-top: 30px;
}
.sport_content .footer .cancel {
padding: 20px;
background-color: #fff;
}
.sport_content .footer .confirm {
padding: 20px;
background-color: yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<label for="">Choose your favorite sport</label><br>
<input type="text" placeholder="Put in your favorite sports" class="input_box">
<div class="sport">
<div class="sport_content">
<h2 class="title">Aerobic exercise</h2>
<ul class="category">
<li class="item" value="RUN">RUN</li>
<li class="item" value="SWIM">Swim</li>
<li class="item" value="bicycle">bicycle</li>
</ul>
<h2 class="title">Strength training</h2>
<ul class="category">
<li class="item" value="weightlifting">weightlifting</li>
<li class="item" value="Stand up">Stand up</li>
<li class="item" value="Barbell">Barbell</li>
</ul>
<div class="footer">
<button class="cancel">cancel</button>
<button class="confirm">confirm</button>
</div>
</div>
</div>
There is no big differents between one and multi.hope you can learn it by youself
$(function(){
$('.input_box').on('click',function(){
$('.sport').css('display','block');
})
$('.sport').click(function(e){
if(e.target.classList.contains('sport')){
$(this).css('display','none');
}
})
$('.sport').click(function(e){
if(e.target.classList.contains('sport')){
$(this).css('display','none');
}
})
$('.item').on('click',function(){
$(this).toggleClass('active');
})
// How to rewrite this program
$('.confirm').on('click',function(e){
// still only a little change here
$(".sport").trigger('click');
var texts = ""
$(".item.active").each(function(idx,item){
texts += $(item).attr("value")+" "
})
$(".input_box").val(texts)
})
});
.input_box {
width: 500px;
height: 60px;
font-size: 30px;
}
.sport {
background-color: rgba(0, 0, 0, 0.3);
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
position: absolute;
top: 0;
display: none;
}
.sport_content {
width: 500px;
padding: 20px;
margin: 0 auto;
background-color: red;
}
.sport_content .title {
text-align: center;
padding: 10px;
font-size: 30px;
font-weight: 800;
}
.sport_content .category {
display: flex;
}
.sport_content .category .item {
width: 100px;
border: 1px solid #fff;
text-align: center;
border-radius: 10px;
padding: 10px;
margin: 10px;
}
.sport_content .category .active {
background-color: yellow;
}
.sport_content .footer {
display: flex;
justify-content: space-between;
margin-top: 30px;
}
.sport_content .footer .cancel {
padding: 20px;
background-color: #fff;
}
.sport_content .footer .confirm {
padding: 20px;
background-color: yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<label for="">Choose your favorite sport</label><br>
<input type="text" placeholder="Put in your favorite sports" class="input_box">
<div class="sport">
<div class="sport_content">
<h2 class="title">Aerobic exercise</h2>
<ul class="category">
<li class="item" value="RUN">RUN</li>
<li class="item" value="SWIM">Swim</li>
<li class="item" value="bicycle">bicycle</li>
</ul>
<h2 class="title">Strength training</h2>
<ul class="category">
<li class="item" value="weightlifting">weightlifting</li>
<li class="item" value="Stand up">Stand up</li>
<li class="item" value="Barbell">Barbell</li>
</ul>
<div class="footer">
<button class="cancel">cancel</button>
<button class="confirm">confirm</button>
</div>
</div>
</div>
I'm trying to create a project card with user info when the user clicks on a button. When the user clicks the new project button, a modal form pops up that takes the user info and has a create button. The program should add a new project card whenever the user clicks the create button. To achieve this I added a click event listener to the Add new project button and another to Create button. I nested the create event listener inside the add new project event listener.
Here's the event listener.
addTileBtn.addEventListener("click", (e) => {
e.preventDefault();
modal.style.display = "block";
const titleField = document.querySelector("#title");
const descriptionField = document.querySelector("#description");
const create = document.querySelector("#create");
const close = document.querySelector("#close");
create.addEventListener("click", (e) => {
e.preventDefault();
title = titleField.value;
description = descriptionField.value;
function createProjectTile() {
const projectTile = document.createElement("div");
projectTile.classList.add("cards-grid__tile");
projectTile.textContent = title;
console.log(title, description);
return projectTile;
}
cardsGrid.appendChild(createProjectTile());
modal.style.display = "none";
});
close.addEventListener("click", (e) => {
e.preventDefault();
modal.style.display = "none";
});
});
The problem is that when I create the first card it works fine. But the second time, it creates two cards and 3 cards on the 3rd time and so on.
Here is the JSFiddle link for the full code.
I've edited your code, this should be what you wanted:
const logoutBtn = document.querySelector("#logout");
const addTileBtn = document.querySelector("#add-tile");
const cardsGrid = document.querySelector(".cards-grid");
const modal = document.querySelector(".modal");
const titleField = document.querySelector("#title");
const descriptionField = document.querySelector("#description");
const create = document.querySelector("#create");
const close = document.querySelector("#close");
addTileBtn.addEventListener("click", (e) => {
e.preventDefault();
modal.style.display = "block";
titleField.value = "";
descriptionField.value = "";
});
create.addEventListener("click", (e) => {
e.preventDefault();
title = titleField.value;
description = descriptionField.value;
function createProjectTile() {
const projectTile = document.createElement("div");
projectTile.classList.add("cards-grid__tile");
projectTile.textContent = title;
console.log(title, description);
return projectTile;
}
cardsGrid.appendChild(createProjectTile());
modal.style.display = "none";
});
close.addEventListener("click", (e) => {
e.preventDefault();
modal.style.display = "none";
});
:root {
--main-red: #be3144;
--main-white: #f0f0f0;
--main-gray: #303841;
--main-blue: #45567d;
--main-blue3: #1c262f;
--main-blue2: #27333d;
--main-blue1: #2e3d49;
--main-light-blue: #02b3e4;
--main-black: #000000;
--main-light-black: #3a3d40;
--main-dark-black: #181719;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html,
body {
height: 100%;
}
img {
display: block;
max-width: 100%;
height: auto;
}
body {
font-family: "Poppins", sans-serif;
font-size: 1.8rem;
font-weight: 400;
line-height: 1.4;
color: var(--main-white);
}
h1,
h2 {
font-family: "Raleway", sans-serif;
font-weight: 700;
text-align: center;
}
h1 {
font-size: 3.5rem;
}
h2 {
font-size: 2rem;
color: var(--main-blue);
display: block;
}
p {
font-size: 1.8rem;
font-weight: 200;
font-style: italic;
color: var(--main-white);
}
a {
text-decoration: none;
text-align: center;
display: block;
}
.main {
display: flex;
flex-direction: row;
justify-content: space-between;
height: 100vh;
background-color: var(--main-white);
}
.box {
border: none;
box-shadow: 0 2px 4px rgb(0 0 0 / 10%), 0 8px 16px rgb(0 0 0 / 10%);
border-radius: 8px;
background-color: #fff;
}
.box__fields {
padding: 20px;
}
.box-field {
margin-bottom: 20px;
display: flex;
justify-content: center;
}
.icon {
position: absolute;
padding: 10px;
color: gray;
min-width: 50px;
text-align: center;
font-size: 20px;
top: 50%;
transform: translateY(-50%);
}
input,
textarea {
font-size: 17px;
padding: 14px 16px;
width: 300px;
cursor: text;
border: 1px solid var(--main-gray);
border-radius: 6px;
outline: none;
padding-left: 45px;
}
.box-btn {
border: none;
border-radius: 6px;
font-size: 20px;
line-height: 48px;
padding: 0 16px;
}
.app,
.main-content {
height: 100%;
}
.title-area {
background-color: var(--main-blue3);
width: 100%;
font-size: 18px;
min-height: 60px;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
position: fixed;
top: 0;
left: 0;
}
.title-area__item {
padding: 10px 30px;
}
.logout-btn {
border: none;
border-radius: 6px;
font-size: 20px;
line-height: 30px;
padding: 0 16px;
width: 100px;
cursor: pointer;
color: #fff;
background-color: var(--main-light-blue);
}
.logout-btn:hover {
background-color: #029be4;
}
.content-area {
margin-top: 60px;
width: 100%;
height: 100%;
overflow: auto;
background-color: var(--main-blue);
}
.cards-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
grid-gap: 50px;
margin-bottom: 3rem;
padding: 5rem 3rem;
}
.cards-grid__tile {
background-color: var(--main-blue2);
max-width: 200px;
padding: 30px;
text-align: center;
font-size: 1.2rem;
}
.add-tile-btn {
border: none;
border-radius: 6px;
font-size: 15px;
line-height: 48px;
padding: 0 10px;
cursor: pointer;
color: #fff;
background-color: var(--main-light-blue);
}
.modal {
display: none;
width: 350px;
font-size: 1.2rem;
position: relative;
top: 10%;
left: 50%;
transform: translateX(-50%);
overflow: visible;
}
.box {
background-color: var(--main-blue1);
opacity: 0.95;
}
.box-field {
flex-direction: column;
}
input,
textarea {
padding: 5px 10px;
resize: none;
}
.wrapper {
position: relative;
text-align: center;
}
.create-btn {
width: 100px;
cursor: pointer;
color: #fff;
background-color: var(--main-light-blue);
}
.close {
cursor: pointer;
position: absolute;
top: 20px;
left: 290px;
}
#modal-form {
position: absolute;
}
.icon {
color: var(--main-blue3);
}
<div class="app">
<div class="nav-wrapper">
<nav id="nav" class="nav"></nav>
</div>
<div class="main-content">
<div class="title-area">
<div class="title-area__item">Menu</div>
<div class="title-area__item">Boards</div>
<div class="title-area__item">
<button id="logout" class="logout-btn btn">
Logout
</button>
</div>
</div>
<div class="content-area">
<div class="modal">
<form id="modal-form" class="box">
<a id="close" class="close">
<i class="fa fa-times icon">close</i>
</a>
<div class="box__fields">
<div class="box-field">
<label for="title"> Title </label>
<input
id="title"
type="text"
name="title"
required
autofocus
/>
</div>
<div class="box-field">
<label for="description">
Description
</label>
<textarea
id="description"
name="title"
rows="6"
cols="40"
></textarea>
</div>
<div class="box-field">
<div class="wrapper">
<button
id="create"
class="create-btn box-btn btn"
>
Create
</button>
</div>
</div>
</div>
</form>
</div>
<div class="cards-grid">
<div class="cards-grid__tile">
<button id="add-tile" class="add-tile-btn btn">
+ Add new project
</button>
</div>
</div>
</div>
</div>
</div>
I want to create two button which will float next to each other and also when we click one of them it will change background-color to #474e5d and some shadow effect. I am very new to design please help me to do this.
Click here to see the button design
//js
const span2 = document.getElementById("span2")
const span1 = document.getElementById("span1")
span2.addEventListener("click",function ( ) {
const span3 = document.getElementById("span3")
span3.style.left="150px"
span3.innerHTML="Search by dictric"
span3.style.transition = "all 0.5s";
})
span1.addEventListener("click",function () {
const span3 = document.getElementById("span3")
span3.style.left="0px"
span3.innerHTML="Search by pin code"
span3.style.transition = "all 0.5s";
})
/* css */
.sld_btn{
display: flex;
width: 300px;
height: 40px;
border-radius: 25px;
position: relative;
background-color: rgb(102, 102, 102);
}
.sld_btn span{
width: 100%;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
transition: all 0.5;
}
#span3{
border-radius: 25px;
position: absolute;
height: 100%;
width:150px ;
background-color: rgb(151, 151, 151);
box-shadow: 5px 5px 5px rgba(41, 41, 41, 0.5);
}
<!-- HTML -->
<div class="sld_btn">
<span class="span1" id="span1">Search by pin code</span>
<span id="span2">Search by dictric</span>
<span class="span3" id="span3">Search by pin code</span>
</div>
I think this is close to what you are looking for. I can explain individual parts if you want.
Click on Run Code Snippet to see it working.
const buttons = document.querySelectorAll('.button');
function onButtonClick(event) {
for (button of buttons) button.classList.remove('clickedButton');
event.target.classList.add('clickedButton');
}
.container {
display: flex;
border-radius: 32px;
background-color: grey;
width: max-content;
}
.button {
cursor: pointer;
padding: 16px;
text-align: center;
border-radius: 32px;
font-size: 14px;
transition: all 0.25s ease;
}
.clickedButton {
background-color: #474e5d;
box-shadow: 0px 0px 15px #444;
color: white;
}
<div class="container">
<div class="button" onclick="onButtonClick(event)">Search by Pin Code</div>
<div class="button" onclick="onButtonClick(event)">Search by District</div>
</div>