JS: how to make sure only one html element is visible - javascript

i have two lists, currently Both lists are toggling at once,
i want only one lists items should be visible at one time,
if i click on list one only list one items should be visible and vice versa.
CODE
currently both lists items are showing on click.
var dropdown = document.getElementsByClassName("dropdown-btn");
var i;
for (i = 0; i < dropdown.length; i++) {
dropdown[i].addEventListener("click", function() {
this.classList.toggle("active");
var dropdownContent = this.nextElementSibling;
if (dropdownContent.style.display === "block") {
dropdownContent.style.display = "none";
} else {
dropdownContent.style.display = "block";
}
});
}
<div class=" dropdown-btn font-bold text-lg text-gray-700 ml-4 mt-3 cursor-pointer">LIST ONE</div>
<div class="hidden">
<div class="cursor-pointer w-full border-gray-100 items-start border-b-2 " style="height:40px">
<div class=" text-base text-gray-700 ml-10 mt-7 ">option 1</a>
</div>
</div>
<div class="w-full border-gray-100 items-start border-b-2" style="height:40px">
<div class=" text-base text-gray-700 ml-10 mt-3"> option 2</a>
</div>
</div>
</div>
<div class="w-full border-gray-100 items-start border-b-2">
<div class="dropdown-btn font-bold text-lg text-gray-700 ml-4 mt-8 cursor-pointer" style="height:40px">LIST TWO
</div>
<div class="hidden">
<div class="w-full border-gray-100 items-start border-b-2" style="height:40px">
<div class=" text-base text-gray-700 ml-10 mt-1"><a href=>option 1</a></div>
</div>
<div class="w-full border-gray-100 items-start border-b-2" style="height:40px">
<div class=" text-base text-gray-700 ml-10 mt-3"><a href=>option 2</a></div>
</div>
</div>
</div>
</div>

You can delegate and toggle the hidden you already have
Note I added a class to the hidden div
const lists = document.querySelectorAll(".list")
const buttons = document.querySelectorAll(".dropdown-btn")
document.getElementById("container").addEventListener("click", function(e) {
const tgt = e.target;
if (tgt.classList.contains("dropdown-btn")) {
tgt.classList.toggle("active");
const thisList = tgt.nextElementSibling;
const show = tgt.classList.contains('active')
lists.forEach(list => list.classList.toggle("hidden", !show || list !=thisList))
buttons.forEach(btn => btn.classList.toggle("active",btn === tgt && show))
}
});
.hidden {
display: none;
}
.active {
color: red;
}
<div id="container">
<div class=" dropdown-btn font-bold text-lg text-gray-700 ml-4 mt-3 cursor-pointer">LIST ONE</div>
<div class="hidden list">
<div class="cursor-pointer w-full border-gray-100 items-start border-b-2 " style="height:40px">
<div class=" text-base text-gray-700 ml-10 mt-7 ">option 1
</div>
</div>
<div class="w-full border-gray-100 items-start border-b-2" style="height:40px">
<div class="text-base text-gray-700 ml-10 mt-3">option 2
</div>
</div>
</div>
<div class="w-full border-gray-100 items-start border-b-2">
<div class="dropdown-btn font-bold text-lg text-gray-700 ml-4 mt-8 cursor-pointer" style="height:40px">LIST TWO
</div>
<div class="hidden list">
<div class="w-full border-gray-100 items-start border-b-2" style="height:40px">
<div class=" text-base text-gray-700 ml-10 mt-1">option 1</div>
</div>
<div class="w-full border-gray-100 items-start border-b-2" style="height:40px">
<div class=" text-base text-gray-700 ml-10 mt-3">option 2</div>
</div>
</div>
</div>
</div>

Related

JQuery duplicate HTML div and edit its content before appending to html body

I have a that contains some input fields like so:
<div class="px-4 py-6 mb-4 border rounded-lg border-gray-400" id="datarow"
<div class="flex flex-row space-x-4 pb-5">
<div class="relative z-0 w-full mb-5">
<input type="text" id="f_name" name="f_name" placeholder="Enter Name here"
required class="pt-3 pb-2 block w-full px-4 mt-0 rounded bg-white border-0 border-b appearance-none" />
<label for="f_name" class="absolute duration-300 pl-2 text-lg top-3 z-1 origin-0 text-gray-500">Name</label>
</div>
<div class="flex z-0 w-full justify-end">
<input type="text" id="f_dest" name="f_dest" placeholder="Enter Destination here"
required class="pt-3 pb-2 block w-full px-4 mt-0 rounded bg-white border-0 border-b appearance-none" />
<label for="f_dest" class="absolute duration-300 pl-2 text-lg top-3 z-1 origin-0 text-gray-500">Destination</label>
</div>
</div>
And in jQuery I am duplicating the above div (on button click) and just appending to the main html body which would be displayed just below the original #datarow div. Heres the full snippet as how I have in my program.
$("#btn_addsector").click(function () {
var div = document.getElementById("datarow"),
clone = div.cloneNode(true);
//neither of the lines work
$(clone).find("#f_name").text = "Tisha";
$("#maincontent").append(clone);
$(clone).find("#f_name").text = "Tisha";
$(clone).find("#f_name").text("Tisha");
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="maincontent" >
<button id="btn_addsector"
class="bg-transparent hover:bg-secondary-dark text-secondary-dark font-semibold hover:text-white py-2 px-4 border border-secondary-dark hover:border-transparent rounded">
Add Sector
</button>
<div class="px-4 py-6 mb-4 border rounded-lg border-gray-400" id="datarow">
<div class="flex flex-row space-x-4 pb-5">
<div class="relative z-0 w-full mb-5">
<input type="text" id="f_name" name="f_name" placeholder="Enter Name here" value="Hannah"
required class="pt-3 pb-2 block w-full px-4 mt-0 rounded bg-white border-0 border-b appearance-none" />
<label for="f_name" class="absolute duration-300 pl-2 text-lg top-3 z-1 origin-0 text-gray-500">Name</label>
</div>
<div class="flex z-0 w-full justify-end">
<input type="text" id="f_dest" name="f_dest" placeholder="Enter Destination here" value="Smallville"
required class="pt-3 pb-2 block w-full px-4 mt-0 rounded bg-white border-0 border-b appearance-none" />
<label for="f_dest" class="absolute duration-300 pl-2 text-lg top-3 z-1 origin-0 text-gray-500">Destination</label>
</div>
</div>
</div>
</div>
I can get the cloned div to appended properly but it does not alter the text of the input field.
There is multiple problem with your code:
1: You can't have multiple elements with the same ID, use class for this. So I've removed the id="f_name" and added it to the class selector class="the previous classes f_name"
2: To set the value of an input, you have to use .val() and not .text()
$(clone).find(".f_name").val("Tisha");
Demo
$("#btn_addsector").click(function() {
var div = document.getElementById("datarow"),
clone = div.cloneNode(true);
//neither of the lines work
$(clone).find(".f_name").val("Tisha");
$("#maincontent").append(clone);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="maincontent">
<button id="btn_addsector" class="bg-transparent hover:bg-secondary-dark text-secondary-dark font-semibold hover:text-white py-2 px-4 border border-secondary-dark hover:border-transparent rounded">
Add Sector
</button>
<div class="px-4 py-6 mb-4 border rounded-lg border-gray-400" id="datarow">
<div class="flex flex-row space-x-4 pb-5">
<div class="relative z-0 w-full mb-5">
<input type="text" name="f_name" placeholder="Enter Name here" value="Hannah" required class="pt-3 pb-2 block w-full px-4 mt-0 rounded bg-white border-0 border-b appearance-none f_name" />
<label for="f_name" class="absolute duration-300 pl-2 text-lg top-3 z-1 origin-0 text-gray-500">Name</label>
</div>
<div class="flex z-0 w-full justify-end">
<input type="text" name="f_dest" placeholder="Enter Destination here" value="Smallville" required class="pt-3 pb-2 block w-full px-4 mt-0 rounded bg-white border-0 border-b appearance-none f_dest" />
<label for="f_dest" class="absolute duration-300 pl-2 text-lg top-3 z-1 origin-0 text-gray-500">Destination</label>
</div>
</div>
</div>
</div>

Close popover in JS when another is opened with popper.js

I have some basic HTML and load popper.js.
I have about 3 popovers but they don't close when I click open another one.
I use tailwind as css and vanilla JS. I don't want to use jQuery to get this to work. It also shows some error about the event being deprecated but not sure how to fix it.
Please help!
Here is my pen: https://codepen.io/RobineSavert/pen/xxLMqpX
Here is my code:
function openPopover(event, tooltipID, position) {
let element = event.target;
while (element.nodeName !== "BUTTON") {
element = element.parentNode;
}
var popper = Popper.createPopper(
element,
document.getElementById(tooltipID), {
placement: position,
}
);
document.getElementById(tooltipID).classList.toggle("hidden");
}
<link href="https://unpkg.com/tailwindcss#^2/dist/tailwind.min.css" rel="stylesheet"/>
<script src="https://unpkg.com/#popperjs/core#2.10.2/dist/umd/popper.min.js"></script>
<section class="bg-gradient-to-b from-night to-babyblue w-full h-95vh justify-center">
<div class="flex flex-1 pr-2 pt-2">
<button onclick="openPopover(event,'popover-cv-bottom', 'bottom')" class="mr-4 bg-red-400 flex h-12 justify-center p-3 rounded-full text-center text-white w-12" type="button">
click
</button>
<button onclick="openPopover(event,'popover-email-bottom', 'bottom')" type="button" class="mr-4 bg-red-400 flex h-12 justify-center p-3 rounded-full text-center text-white w-12">
click
</button>
<button onclick="openPopover(event,'popover-save-bottom', 'bottom')" type="button" class="mr-4 bg-red-400 flex h-12 justify-center p-3 rounded-full text-center text-white w-12">
click </button>
<div class="hidden bg-white border mr-3 block z-50 font-normal leading-normal text-sm max-w-xs text-left no-underline break-words rounded-lg" id="popover-cv-bottom">
<div>
<div
class="text-gray-700 opacity-75 font-semibold p-3
mb-0
border-b border-solid border-gray-100
uppercase
rounded-t-lg
"
>
Popover 1 - title
</div>
<div class="text-gray-700 p-3">
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Saepe,
non.
</div>
</div>
</div>
<div class="hidden bg-white border mr-3 block z-50 font-normal leading-normal text-sm max-w-xs text-left no-underline break-words rounded-lg" id="popover-email-bottom">
<div>
<div
class="
text-gray-700
opacity-75
font-semibold
p-3
mb-0
border-b border-solid border-gray-100
uppercase
rounded-t-lg
"
>
Popover 2 - title
</div>
<div class="text-gray-700 p-3">
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Saepe,
non.
</div>
</div>
</div>
<div class="hidden bg-white border mr-3 block z-50 font-normal leading-normal text-sm max-w-xs text-left no-underline break-words rounded-lg" id="popover-save-bottom">
<div>
<div
class="
text-gray-700
opacity-75
font-semibold
p-3
mb-0
border-b border-solid border-gray-100
uppercase
rounded-t-lg
"
>
Popover 3 - title
</div>
<div class="text-gray-700 p-3">
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Saepe,
non.
</div>
</div>
</div>
</div>
</section>
You can try this:
allPoppers = [];
function openPopover(event, tooltipID, position)
{
var el = document.getElementById(tooltipID);
var state = el.style.visibility;
// Close all popovers
hideElements(allPoppers);
let element = event.target;
while (element.nodeName !== "BUTTON") {
element = element.parentNode;
}
Popper.createPopper(
element,
el, {
placement: position,
}
);
allPoppers.push(tooltipID);
toggle(el, state);
}
function toggle(el, state)
{
if (state == "hidden") {
el.style.visibility = "visible";
} else if (state == "visible") {
el.style.visibility = "hidden";
} else {
el.style.visibility = "visible";
}
}
function hideElements(elements)
{
var length = elements.length;
if (length > 0) {
for (var i = 0; i < length; i++) {
document.getElementById(elements[i]).style.visibility = "hidden";
}
}
}
.popover {
visibility: hidden;
}
<link href="https://unpkg.com/tailwindcss#^2/dist/tailwind.min.css" rel="stylesheet"/>
<script src="https://unpkg.com/#popperjs/core#2.10.2/dist/umd/popper.min.js"></script>
<section class="bg-gradient-to-b from-night to-babyblue w-full h-95vh justify-center">
<div class="flex flex-1 pr-2 pt-2">
<button onclick="openPopover(event,'popover-cv-bottom', 'bottom')" class="mr-4 bg-red-400 flex h-12 justify-center p-3 rounded-full text-center text-white w-12" type="button">
click
</button>
<button onclick="openPopover(event,'popover-email-bottom', 'bottom')" type="button" class="mr-4 bg-red-400 flex h-12 justify-center p-3 rounded-full text-center text-white w-12">
click
</button>
<button onclick="openPopover(event,'popover-save-bottom', 'bottom')" type="button" class="mr-4 bg-red-400 flex h-12 justify-center p-3 rounded-full text-center text-white w-12">
click </button>
<div class="bg-white border mr-3 block z-50 font-normal leading-normal text-sm max-w-xs text-left no-underline break-words rounded-lg popover" id="popover-cv-bottom">
<div>
<div
class="text-gray-700 opacity-75 font-semibold p-3
mb-0
border-b border-solid border-gray-100
uppercase
rounded-t-lg
"
>
Popover A
</div>
<div class="text-gray-700 p-3">
A
</div>
</div>
</div>
<div class="bg-white border mr-3 block z-50 font-normal leading-normal text-sm max-w-xs text-left no-underline break-words rounded-lg popover" id="popover-email-bottom">
<div>
<div
class="
text-gray-700
opacity-75
font-semibold
p-3
mb-0
border-b border-solid border-gray-100
uppercase
rounded-t-lg
"
>
Popover B
</div>
<div class="text-gray-700 p-3">
B
</div>
</div>
</div>
<div class="bg-white border mr-3 block z-50 font-normal leading-normal text-sm max-w-xs text-left no-underline break-words rounded-lg popover" id="popover-save-bottom">
<div>
<div
class="
text-gray-700
opacity-75
font-semibold
p-3
mb-0
border-b border-solid border-gray-100
uppercase
rounded-t-lg
"
>
Popover C
</div>
<div class="text-gray-700 p-3">
C
</div>
</div>
</div>
</div>
</section>

Adding comments to video with jQuery

I want to comment dynamically on a video with jQuery, but when I comment on what I'm doing, the old comment changes and all comments receive the same text. The value I get from the input is written to all comments. How can I fix this?
$(document).ready(function() {
$("#addCommentBtn").click(function() {
var comment = $("#commentText").val();
if (comment === "") {
$("#error-msg").fadeIn();
setTimeout(function() {
$("#error-msg").fadeOut();
}, 3000);
} else {
$('<li class="w-full comment mt-4"><div class="w-full md:w-1/2 comment flex flex-col"><div class="flex gap-4 items-center text-lg font-bold"><img src="assets/media/svg/NoPath - Kopya (75).png" class="rounded-full" alt=""><h1>André Potchinka</h1></div><div class="ml-16 flex flex-col justify-center"><div class=" mt-2 flex gap-1 items-center"><h1 class="comment-content text-gray-500 font-bold"></h1><span class="flex gap-2 -mt-1"><i class="fas fa-thumbs-up" aria-hidden="true"></i>0</span><span class="flex gap-2 -mt-1"><i class="fas fa-thumbs-down" aria-hidden="true"></i>0</span></div><div class="w-full flex flex-col"><input type="text" class="responseText border-b focus:outline-none bg-transparent mt-4" placeholder="Please login to leave a comment..."><ul class="responses p-4 flex flex-col gap-2"> </ul><button class="responseBtn text-right mt-2 text-gray-500">Answer</button></div></div></div></li>').appendTo(".comments");
$(".comment-content").text(comment);
$("#commentText").val("");
$("#valid-msg").fadeIn();
setTimeout(function() {
$("#valid-msg").fadeOut();
}, 3000);
}
});
});
<link href="https://unpkg.com/tailwindcss#^2/dist/tailwind.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="comments" class="hidden p-4">
<div class="container mx-auto">
<div class="w-full flex gap-4">
<img src="assets/media/svg/Group 199.png" alt="">
<input type="text" required id="commentText" class="pt-4 flex-1 focus:outline-none border-b border-gray-500 py-1 px-2 bg-transparent" placeholder="Please login to leave a comment...">
</div>
<div class="w-full flex gap-4 justify-end items-center mt-4">
Cancel
<button id="addCommentBtn" class="focus:outline-none bg-black px-6 border border-black py-1 rounded-full text-gray-500 flex items-center pt-3">Comment</button>
</div>
<ul class="w-full comments">
<li class="w-full comment mt-4">
<div class="w-full md:w-1/2 comment flex flex-col">
<div class="flex gap-4 items-center text-lg font-bold">
<img src="assets/media/svg/NoPath - Kopya (75).png" class="rounded-full" alt="">
<h1>André Potchinka</h1>
</div>
<div class="ml-16 flex flex-col justify-center">
<div class=" mt-2 flex gap-1 items-center">
<h1 class="text-gray-500 font-bold">Nice work, congragulations.</h1>
<span class="flex gap-2 -mt-1"><i class="fas fa-thumbs-up"></i>0</span>
<span class="flex gap-2 -mt-1"><i class="fas fa-thumbs-down"></i>0</span>
</div>
<div class="w-full flex flex-col">
<input type="text" class="responseText border-b focus:outline-none bg-transparent mt-4" placeholder="Please login to leave a comment...">
<ul class="responses p-4 flex flex-col gap-2 text-gray-500">
<li>Yoruma yanıt verildi :)</li>
</ul>
<div class="flex justify-end">
<button class="responseBtn mt-2 text-gray-500 w-24 text-center">Answer</button>
</div>
</div>
</div>
</div>
</li>
</ul>
</div>
</div>
With the selector .comment-content, you are selecting all the elements with that class, so of course all comments' text content will be overwritten. Save your new element into a variable and restrict the class selector on that new element instead:
$(document).ready(function() {
$("#addCommentBtn").click(function() {
var comment = $("#commentText").val();
if (comment === "") {
$("#error-msg").fadeIn();
setTimeout(function() {
$("#error-msg").fadeOut();
}, 3000);
} else {
let newComment = $('<li class="w-full comment mt-4"><div class="w-full md:w-1/2 comment flex flex-col"><div class="flex gap-4 items-center text-lg font-bold"><img src="assets/media/svg/NoPath - Kopya (75).png" class="rounded-full" alt=""><h1>André Potchinka</h1></div><div class="ml-16 flex flex-col justify-center"><div class=" mt-2 flex gap-1 items-center"><h1 class="comment-content text-gray-500 font-bold"></h1><span class="flex gap-2 -mt-1"><i class="fas fa-thumbs-up" aria-hidden="true"></i>0</span><span class="flex gap-2 -mt-1"><i class="fas fa-thumbs-down" aria-hidden="true"></i>0</span></div><div class="w-full flex flex-col"><input type="text" class="responseText border-b focus:outline-none bg-transparent mt-4" placeholder="Please login to leave a comment..."><ul class="responses p-4 flex flex-col gap-2"> </ul><button class="responseBtn text-right mt-2 text-gray-500">Answer</button></div></div></div></li>').appendTo(".comments");
$(".comment-content", newComment).text(comment);
$("#commentText").val("");
$("#valid-msg").fadeIn();
setTimeout(function() {
$("#valid-msg").fadeOut();
}, 3000);
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="comments" class="hidden p-4">
<div class="container mx-auto">
<div class="w-full flex gap-4">
<img src="assets/media/svg/Group 199.png" alt="">
<input type="text" required id="commentText" class="pt-4 flex-1 focus:outline-none border-b border-gray-500 py-1 px-2 bg-transparent" placeholder="Please login to leave a comment...">
</div>
<div class="w-full flex gap-4 justify-end items-center mt-4">
Cancel
<button id="addCommentBtn" class="focus:outline-none bg-black px-6 border border-black py-1 rounded-full text-gray-500 flex items-center pt-3">Comment</button>
</div>
<ul class="w-full comments">
<li class="w-full comment mt-4">
<div class="w-full md:w-1/2 comment flex flex-col">
<div class="flex gap-4 items-center text-lg font-bold">
<img src="assets/media/svg/NoPath - Kopya (75).png" class="rounded-full" alt="">
<h1>André Potchinka</h1>
</div>
<div class="ml-16 flex flex-col justify-center">
<div class=" mt-2 flex gap-1 items-center">
<h1 class="text-gray-500 font-bold">Nice work, congragulations.</h1>
<span class="flex gap-2 -mt-1"><i class="fas fa-thumbs-up"></i>0</span>
<span class="flex gap-2 -mt-1"><i class="fas fa-thumbs-down"></i>0</span>
</div>
<div class="w-full flex flex-col">
<input type="text" class="responseText border-b focus:outline-none bg-transparent mt-4" placeholder="Please login to leave a comment...">
<ul class="responses p-4 flex flex-col gap-2 text-gray-500">
<li>Yoruma yanıt verildi :)</li>
</ul>
<div class="flex justify-end">
<button class="responseBtn mt-2 text-gray-500 w-24 text-center">Answer</button>
</div>
</div>
</div>
</div>
</li>
</ul>
</div>
</div>

Close custom modal when click outside the modal in vanilla JS

I've done this but the modal won't open whatsoever
document.addEventListener('click', ({ target }) => {
if (!target.closest('#modal-submit')) {
document.getElementById('modal-submit').classList.add('hide-visibility');
}
})
The trickier part is that there's a form inside the modal.
This to trick "mostly code" error: ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
document.getElementById('show-modal').onclick = (e) => {
document.getElementById('modal-submit').classList.remove('hide-visibility')
}
.hide-visibility {
opacity: 0;
visibility: hidden;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.1.2/tailwind.min.css" rel="stylesheet"/>
<div
id="modal-submit"
class="fixed z-10 inset-0 overflow-y-auto hide-visibility"
style="z-index: 9999; transition: all .5s;"
aria-labelledby="modal-title"
role="dialog"
aria-modal="true"
>
<div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<!--
Background overlay, show/hide based on modal state.
Entering: "ease-out duration-300"
From: "opacity-0"
To: "opacity-100"
Leaving: "ease-in duration-200"
From: "opacity-100"
To: "opacity-0"
-->
<div class="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" aria-hidden="true"></div>
<!-- This element is to trick the browser into centering the modal contents. -->
<span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">​</span>
<!--
Modal panel, show/hide based on modal state.
Entering: "ease-out duration-300"
From: "opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
To: "opacity-100 translate-y-0 sm:scale-100"
Leaving: "ease-in duration-200"
From: "opacity-100 translate-y-0 sm:scale-100"
To: "opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
-->
<div class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full">
<div class="bg-white px-4 pb-4 sm:p-3 sm:pb-4">
<h3 class="text-lg leading-6 font-medium text-gray-900" id="modal-title">
Submit Exam
</h3>
<div class="mt-5">
<p class="text-sm text-gray-500">
<input id="certify-checkbox" type="checkbox" class="form-checkbox h-3 w-3 text-gray-600">
I certify that
</p>
</div>
<div class="mt-5">
<p class="text-sm text-gray-500">
<input id="final-checkbox" type="checkbox" class="form-checkbox h-3 w-3 text-gray-600">
I have conducted a final round of proofing before submitting this project.
</p>
</div>
</div>
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
<button type="button" class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:w-auto sm:text-sm">
Submit
</button>
</div>
</div>
</div>
</div>
<button id="show-modal" class="border border-indigo-600">Show</button>
document.getElementById("show-modal").onclick = (e) => {
document.getElementById("modal-submit").classList.remove("hide-visibility");
};
document.addEventListener('click', (event) => {
const boolIsOutside = document.getElementById("grey-bg").isSameNode(event.target);
if (boolIsOutside) {
document.getElementById("modal-submit").classList.add("hide-visibility");
}
});
.hide-visibility {
opacity: 0;
visibility: hidden;
}
<div
id="modal-submit"
class="fixed z-10 inset-0 overflow-y-auto hide-visibility"
style="z-index: 9999; transition: all .5s; border: 2px solid black"
aria-labelledby="modal-title"
role="dialog"
aria-modal="true"
>
<div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<!--
Background overlay, show/hide based on modal state.
Entering: "ease-out duration-300"
From: "opacity-0"
To: "opacity-100"
Leaving: "ease-in duration-200"
From: "opacity-100"
To: "opacity-0"
-->
<div id="grey-bg" class="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" aria-hidden="true"></div>
<!-- This element is to trick the browser into centering the modal contents. -->
<span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">​</span>
<!--
Modal panel, show/hide based on modal state.
Entering: "ease-out duration-300"
From: "opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
To: "opacity-100 translate-y-0 sm:scale-100"
Leaving: "ease-in duration-200"
From: "opacity-100 translate-y-0 sm:scale-100"
To: "opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
-->
<div class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full">
<div class="bg-white px-4 pb-4 sm:p-3 sm:pb-4">
<h3 class="text-lg leading-6 font-medium text-gray-900" id="modal-title">
Submit Exam
</h3>
<div class="mt-5">
<p class="text-sm text-gray-500">
<input id="certify-checkbox" type="checkbox" class="form-checkbox h-3 w-3 text-gray-600">
I certify that
</p>
</div>
<div class="mt-5">
<p class="text-sm text-gray-500">
<input id="final-checkbox" type="checkbox" class="form-checkbox h-3 w-3 text-gray-600">
I have conducted a final round of proofing before submitting this project.
</p>
</div>
</div>
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
<button type="button" class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:w-auto sm:text-sm">
Submit
</button>
</div>
</div>
</div>
</div>
<button id="show-modal" class="border border-indigo-600">Show</button>
Using the concept of event propagation, you can use this,
// You can use any other selector according to your need
const ele = document.getElementById('someId');
// adding click event listener to the selected elem (can use any other event)
document.addEventListener('click', (event) => {
const boolIsInside = ele.contains(event.target);
if (boolIsInside) {
// logic if the click was inside the modal
} else {
// logic if the click was outside the modal
}
});

how to use django formset with custom template?

i have used Inlineformset in my django project , but i have to use my own js for increasing forms ! but i didnt find any way to make it work
this is my models.py
class Invoice(models.Model):
seller = models.ForeignKey(User,on_delete=models.CASCADE)
customer = models.CharField(max_length=50)
items = models.ManyToManyField(Item,through='InvoiceItem')
class InvoiceItem(models.Model):
item = models.ForeignKey(Item,on_delete=models.CASCADE)
invoice = models.ForeignKey(CustomerInvoice,on_delete=models.CASCADE,related_name='invoice')
quantity = models.IntegerField()
price = models.DecimalField(max_digits=20,decimal_places=3)
cash = models.DecimalField(max_digits=20,decimal_places=3)
discount = models.DecimalField(max_digits=20,decimal_places=3)
and this code is my views.py , i have used Class Based View
class CreateClientInvoiceView(LoginRequiredMixin,SuccessMessageMixin,CreateView):
model = CustomerInvoice
form_class = ClientInvoiceForm
template_name = 'invoiceapp/create_invoice.html'
def get_context_data(self,*args,**kwargs):
data = super().get_context_data(*args,**kwargs)
if self.request.POST:
data['items'] = CustomerInvoiceInlineFormset(self.request.POST)
data['items'].full_clean()
else:
data['items'] = CustomerInvoiceInlineFormset()
return data
def form_valid(self, form):
res = super().form_valid(form)
self.object = form.save()
context = self.get_context_data()
items = context['items']
with transaction.atomic:
form.instance.seller = self.request.user
if form.is_valid() and items.is_valid() and items.cleaned_data !={}:
items.instance = self.object
items.save()
form.save()
else:
return render(self.request,self.template_name,context)
return super().form_valid(form)
def get_success_url(self):
return reverse_lazy('invoiceapp:customer-invoice',kwargs={'pk':self.object.pk})
this is my html + js code
{% extends 'base.html' %}
{% load widget_tweaks %}
{% load static %}
{% block title %}
create new invoice
{% endblock %}
{% block content %}
<form method="POST">{% csrf_token %}
{{items.management_form}}
<div class="w-full md:w-11/12 mx-auto realative p-2 bg-gray-200 invoice" style="direction: ltr !important;">
<div class="p-1 pr-2 pb-1 text-xs border border-black rounded-lg flex flex-wrap">
<div class="flex w-8/12 lg:w-9/12">
<div class="w-10/12 ml-8 border-b border-gray-600 border-dotted">
{{form.customer | add_class:'bg-transparent w-full text-right focus:outline-none'}}
</div>
<div class="">
: ناو
</div>
</div>
</div>
<!-- table -->
<div class="mt-1 border border-black">
<!-- header -->
<div class="flex flex-wrap grayBG text-sm text-white">
<div class="w-1/12 text-center border-r">
<i class="fas fa-cog"></i>
</div>
<div class="w-2/12 border-r text-center">
total price
</div>
<div class="w-2/12 border-r text-center">
discount
</div>
<div class="w-1/12 border-r text-center">
cash
</div>
<div class="w-1/12 border-r text-center">
loan
</div>
<div class="w-1/12 border-r text-center">
price
</div>
<div class="w-2/12 border-r text-center">
quantity
</div>
<div class="w-2/12 border-r text-center">
product
</div>
</div>
<!-- inputs -->
<div id="allInp">
<div class="flex flex-wrap grayBG text-sm text-black inp">
<div class="w-1/12 border-r">
</div>
<div class="w-2/12 p-2 border-r text-center">
<input type="number" class="totalSumField rounded-lg focus:outline-none py-1 w-full">
</div>
<div class="w-2/12 p-2 border-r text-center">
<input type="text" onkeyup="totalSum()" class="rounded-lg discount focus:outline-none py-1 w-full">
</div>
<div class="w-1/12 p-2 border-r text-center ">
<input type="number" onkeyup="totalSum()" class="rounded-lg cash focus:outline-none py-1 w-full">
</div>
<div class="w-1/12 p-2 border-r text-center ">
<input type="number" onkeyup="totalSum()" class="rounded-lg loan focus:outline-none py-1 w-full">
</div>
<div class="w-1/12 p-2 border-r text-center ">
<input type="number" onkeyup="totalSum()" class="rounded-lg price focus:outline-none py-1 w-full">
</div>
<div class="w-2/12 p-2 border-r text-center ">
<input type="number" onkeyup="totalSum()" class="rounded-lg quantity focus:outline-none py-1 w-full">
</div>
<div class="w-2/12 p-2 border-r text-center">
<datalist id="jor">
<option value="test">
<option value="test">
<option value="test">
<option value="test">
<option value="test">
</datalist>
<input type="text" list="jor" class="w-full rounded-lg focus:outline-none py-1">
</div>
</div>
</div>
<div class="flex flex-wrap grayBG justify-between text-sm mt-2 text-black">
<button class=" grayBG border border-white focus:outline-none text-white m-2 rounded-lg py-1 px-4 text-sm" id="addRow">
add new row <i class="fas fa-plus"></i>
</button>
<div class="w-6/12 flex">
<div class="w-6/12 p-2 border-r text-center">
<p class="mb-2 text-white">total invoice price </p>
<input type="number" id="total" class="rounded-lg focus:outline-none py-1 w-full text-center" placeholder="total invoice price">
</div>
<div class="w-6/12 p-2 border-r text-center">
<p class="mb-2 text-white">total loan</p>
<input type="number" id="loan" class="rounded-lg focus:outline-none py-1 w-full text-center" placeholder="loan">
</div>
</div>
</div>
<!-- clone -->
<div class="hidden">
<div class="inp flex flex-wrap grayBG text-sm text-black" id="inputs">
<div class="w-1/12 border-r flex flex-wrap justify-center items-center">
<button id="removeRow" class="bg-white rounded-lg text-red-500 px-3">
<i class="fas fa-trash"></i>
</button>
</div>
<div class="w-2/12 p-2 border-r text-center">
<input type="text" class="rounded-lg totalSumField focus:outline-none py-1 w-full">
</div>
<div class="w-2/12 p-2 border-r text-center">
<input type="text" onkeyup="totalSum()" class="rounded-lg focus:outline-none discount py-1 w-full">
</div>
<div class="w-1/12 p-2 border-r text-center ">
<input type="number" onkeyup="totalSum()" class="rounded-lg cash focus:outline-none py-1 w-full">
</div>
<div class="w-1/12 p-2 border-r text-center ">
<input type="number" onkeyup="totalSum()" class="rounded-lg loan focus:outline-none py-1 w-full">
</div>
<div class="w-1/12 p-2 border-r text-center ">
<input type="number" onkeyup="totalSum()" class="rounded-lg price focus:outline-none py-1 w-full">
</div>
<div class="w-2/12 p-2 border-r text-center ">
<input type="number" onkeyup="totalSum()" class="rounded-lg quantity focus:outline-none py-1 w-full">
</div>
<div class="w-2/12 p-2 border-r text-center">
<datalist id="jor">
<option value="test">
<option value="test">
<option value="test">
<option value="test">
<option value="test">
</datalist>
<input type="text" list="jor" class="w-full rounded-lg focus:outline-none py-1">
</div>
</div>
</div>
</div>
</div>
<div class="w-6/12 text-center mt-1 mx-auto mb-6">
<button type="submit" class= w-full bg-white text-gray-900" id="print">print</button>
</div>
</form>
</div>
</div>
</body>
</html>
<script>
$('#print').click(function(){
$('.invoice').printThis();
})
$("#addRow").click(function () {
totalSum();
var html = $("#inputs").clone();
$('#allInp').append(html);
});
$(document).on('click', '#removeRow', function () {
$(this).closest('#inputs').remove();
totalSum();
});
function counting(result) {
document.getElementById("total").value= result;
}
function countingloan(result) {
document.getElementById("loan").value= result;
}
counting(0);
countingloan(0);
function totalSumField () {
let inp = document.querySelectorAll("#allInp > .inp");
let result=0;
for(let i=0;i<inp.length;i++){
let price=inp[i].getElementsByClassName("price")[0].value;
let quantity=inp[i].getElementsByClassName("quantity")[0].value;
let cash=inp[i].getElementsByClassName("cash")[0].value;
let discount=inp[i].getElementsByClassName("discount")[0].value;
inp[i].getElementsByClassName("totalSumField")[0].value=(price*quantity)-discount;
inp[i].getElementsByClassName("loan")[0].value=((price*quantity)-discount)-cash;
}
}
function totalSum () {
let inp = document.querySelectorAll("#allInp > .inp");
let result=0;
let loan=0;
for(let i=0;i<inp.length;i++){
let price=inp[i].getElementsByClassName("price")[0].value;
let quantity=inp[i].getElementsByClassName("quantity")[0].value;
let cash=inp[i].getElementsByClassName("cash")[0].value;
let discount=inp[i].getElementsByClassName("discount")[0].value;
result+=(price*quantity)-discount;
loan+=((price*quantity)-discount)-cash;
}
countingloan(loan);
counting(result)
totalSumField()
}
</script>
{% endblock %}
the problem is here i want to make my own html and js instead of using jquery.formset.js because i have to when someone write the price and quantity , then it will automatically multiply them and write the total price in a field , now i want to know how to add input fields in order to get what i expect the result to be?
this work only for the first form
<div id="allInp">
{% for item in items.forms %}
{{item.id}}
<div class="flex flex-wrap grayBG text-sm text-black inp">
<div class="w-1/12 border-r">
</div>
<div class="w-2/12 p-2 border-r text-center">
<input type="number" class="totalSumField rounded-lg focus:outline-none py-1 w-full">
</div>
<div class="w-2/12 p-2 border-r text-center">
{{item.discount | add_class:'rounded-lg discount focus:outline-none py-1 w-full'}}
</div>
<div class="w-1/12 p-2 border-r text-center ">
{{item.cash|add_class:'rounded-lg cash focus:outline-none py-1 w-full'}}
</div>
<div class="w-1/12 p-2 border-r text-center ">
<input type="number" onkeyup="totalSum()" class="rounded-lg qarz focus:outline-none py-1 w-full">
</div>
<div class="w-1/12 p-2 border-r text-center ">
{{item.price | add_class:'rounded-lg price focus:outline-none py-1 w-full'}}
</div>
<div class="w-2/12 p-2 border-r text-center ">
{{item.quantity | add_class:'rounded-lg quantity focus:outline-none py-1 w-full'}}
</div>
<div class="w-2/12 p-2 border-r text-center">
{{item.item|add_class:'w-full rounded-lg focus:outline-none py-1'}}
</div>
</div>
{% endfor %}
</div>
<div class="hidden">
<div class="inp flex flex-wrap grayBG text-sm text-black" id="inputs">
<div class="w-1/12 border-r flex flex-wrap justify-center items-center">
<button id="removeRow" class="bg-white rounded-lg text-red-500 px-3">
<i class="fas fa-trash"></i>
</button>
</div>
<div class="w-2/12 p-2 border-r text-center">
<input type="text" class="rounded-lg totalSumField focus:outline-none py-1 w-full">
</div>
<div class="w-2/12 p-2 border-r text-center">
{{item.discount | add_class:'rounded-lg discount focus:outline-none py-1 w-full'}}
</div>
<div class="w-1/12 p-2 border-r text-center ">
{{item.cash|add_class:'rounded-lg cash focus:outline-none py-1 w-full'}}
</div>
<div class="w-1/12 p-2 border-r text-center ">
<input type="number" onkeyup="totalSum()" class="rounded-lg qarz focus:outline-none py-1 w-full">
</div>
<div class="w-1/12 p-2 border-r text-center ">
{{item.price | add_class:'rounded-lg price focus:outline-none py-1 w-full'}}
</div>
<div class="w-2/12 p-2 border-r text-center ">
{{item.quantity | add_class:'rounded-lg quantity focus:outline-none py-1 w-full'}}
</div>
<div class="w-2/12 p-2 border-r text-center">
{{item.item|add_class:'w-full rounded-lg focus:outline-none py-1'}}
</div>
</div>
</div>
i much appreciate your helps please is its possible let me know
most regards ..

Categories

Resources