I am working on a program that is not functioning as I am expecting it. I have a page that allows people to add multiple links to my application, but there is something going on under the hood that is not making logical sense.
The application uses JQUERY to add a new section with HTML inputs for an emoji, title, URL, and visibility. This runs whenever the user starts to type, so theoretically there could be unlimited links added.
On the surface, the script seems to duplicate and add new fields like it should. However, whenever I fill out the form and send the form data through POST method to a PHP page, the data inserted into the last duplicated section does not send at all.
Here is a screenshot of me filling out the form. Below is the output from that form generated through a simple php script of print_r($_POST). This shows where the google link is completely left out despite me typing it in correctly.
Array
(
[method] => assign
[assEmoji] => ✏️
[title] => testing system
[directions] =>
[subID] => 1
[points] =>
[due] =>
[attach] => Array
(
[1] => Array
(
[linkEmoji] => 📎
[linkTitle] => Youtube
[linkURL] => https://youtube.com
[linkClass] => NULL
)
[2] => Array
(
[linkEmoji] => 📎
[linkTitle] =>
[linkURL] =>
[linkClass] => NULL
)
[3] => Array
(
[linkEmoji] => 📎
[linkTitle] =>
[linkURL] =>
[linkClass] => NULL
)
)
[submitType] => scan
[assType] => Assignment
)
Here is the code I am using to create the page.
// This section handles adding new links to page //
function appendSection() {
$(this).off('change');
const newSection = $(this).closest('section').clone();
newSection.find('input, select').each((i, el) => {
el.value = '';
el.name = el.name.replace(/\[(\d)\]/, (match, p1) => `[${parseInt(p1) + 1}]`);
});
newSection.on('change', appendSection);
$('.attachments').append(newSection);
}
$(".attachments section input").change(appendSection);
// This section handles navigation //
function nav(arg) {
var destination = arg.dataset.nav;
var pages = document.querySelectorAll("[data-page]");
var nav = document.querySelectorAll("[data-nav]");
for (i = 0; i < nav.length; i++) { // Remove the class 'active' if it exists
nav[i].classList.remove('active')
}
arg.classList.add('active');
for (i = 0; i < pages.length; i++) { // Hide/show the correct pages
if (pages[i].dataset.page != destination) {
pages[i].style.display = "none";
} else {
if (destination == 'basic') {pages[i].style.display = "flex";}
if (destination != 'basic') {pages[i].style.display = "block";}
}
}
}
.modal {display: block !Important}
.modal {
display: none;
position: fixed;
z-index: 20;
right: 0; top: 0;
width: 100%; height: 100%;
overflow: auto;
background-color: rgba(0,0,0,0.4);
-webkit-animation-name: fadeIn;
-webkit-animation-duration: 0.4s;
animation-name: fadeIn;
animation-duration: 0.4s}
.assignment-window{
display: grid;
position: fixed;
overflow: hidden;
padding: 10px;
padding-bottom: 16px;
box-sizing: border-box;
width: 100vw; height: 70vh;
bottom: 0; left: 0;
border-top-left-radius: 40px;
border-top-right-radius: 40px;
background-color: white;
grid-template-rows: auto 1fr;
grid-template-columns: 0.9fr 2.5fr;
grid-template-areas:
"asstop asstop"
"assnav asscontent"}
/* ----------[ASS TOP]---------- */
.asstop {
grid-area: asstop;
padding: 24px 20px;
box-sizing: border-box;
border-bottom: 2px solid #581F98;}
.asstop .title {
display: flex;
align-items: center;}
.asstop .title input {
flex: 1 1;
font-size: 24px;
border-radius: 8px;
margin-right: 20px;
border: 1px solid lightgray}
.asstop select {
outline: none;
-webkit-appearance: none;
padding: 12px 16px;
font-size: 24px;
box-sizing: border-box;
border-radius: 8px;
border: 1px solid lightgray}
.asstop button {
margin-top: -5px;}
/* ----------[ASS NAV]---------- */
.assnav {
grid-area: assnav;
padding-top: 20px;
padding-right: 10%;
border-right: 1px solid lightgray}
.assnav ul {
margin: 0;
padding: 0;
overflow: hidden;
list-style-type: none}
.assnav li {
display: block;
text-decoration: none;
color: #484848;
font-size: 20px;
padding: 14px 20px;
margin-bottom: 10px;
border-top-right-radius: 40px;
border-bottom-right-radius: 40px;}
.assnav li:hover {background-color: #F2F2F2}
.assnav li.active {background-color: #EEEEEE}
/* ----------[ASS CONTENT]---------- */
.asscontent {
grid-area: asscontent;
display: flex;
flex-direction: column;
padding: 30px;
box-sizing: border-box;
overflow: scroll}
.asscontent input, .asscontent select {
flex: 1;
outline: none;
-webkit-appearance: none;
padding: 8px 16px;
font-size: 18px;
box-sizing: border-box;
border-radius: 8px;
border: 1px solid lightgray}
/* ==== Basic Styling ==== */
.asscontent .basic {
display: flex;
height: 100%;
flex-direction: column}
.asscontent .basic textarea {
flex: 1;
font-size: 18px;
border-radius: 8px;
box-sizing: border-box;}
.asscontent .basic .config {
display: flex;
justify-content: space-between;
padding-top: 20px;}
.asscontent .basic input {text-align: center;}
.asscontent .basic .points {width: 80px;}
/* ==== Attachment Styling ==== */
.asscontent .attachments {display: none}
.asscontent .attachments section {
display: flex;
justify-content: space-between;
padding-bottom: 15px;
margin-bottom: 15px;
border-bottom: 1px solid lightgray}
/* ==== Delete Styling ==== */
.asscontent .advanced {display: none}
/* ==== Delete Styling ==== */
.asscontent .delete {display: none;}
.asscontent .delete ul {margin-bottom: 30px;}
.asscontent .delete li {margin-bottom: 10px;}
<form action='assign.int.php' method="post">
<input type='hidden' name='method' value='assign'>
<div class='modal'>
<div class='assignment-window'>
<div class='asstop'>
<div class='title'>
<select name='assEmoji'>
<option>✏️</option>
<option>💻</option>
<option>📚</option>
<option>💯</option>
<option>🧪</option>
</select>
<input name='title' type='text' placeholder='Type assignment title..' required>
<button class='button purple-btn'>Save Changes</button>
</div>
</div>
<div class='assnav'>
<ul>
<li data-nav='basic' onclick='nav(this);' class='active'>Basic Setup</li>
<li data-nav='attachments' onclick='nav(this);'>Attachments</li>
<li data-nav='advanced' onclick='nav(this);'>Advanced Settings</li>
</ul>
</div>
<div class='asscontent'>
<div class='basic' data-page='basic'>
<textarea name='directions' placeholder='Type assignment directions..'></textarea>
<div class='config'>
<section>
<span>Subject: </span>
<select name='subID'>
<option value='1'>Reading</option>
<option value='2'>Social Studies</option>
<option value='3'>Math</option>
<option value='4'>Science</option>
<option value='5'>Writing</option>
</select>
</section>
<section>
<span>Points:</span>
<input name='points' class='points' type='text'>
</section>
<section>
<span>Due Date:</span>
<input name='due' type='datetime-local'>
</section>
</div>
</div>
<div class='attachments' data-page='attachments'>
<section>
<div class='displayName'>
<select name='attach[1][linkEmoji]'>
<option>📎</option>
<option>🎬</option>
<option>📖</option>
</select>
<input name='attach[1][linkTitle]' placeholder='Title of website..' type='text'>
</div>
<div class='url'>
<input name='attach[1][linkURL]' placeholder='Insert website URL..' type='url'>
</div>
<div class='visible'>
<span>Visible: <span>
<select name='attach[1][linkClass]'>
<option value='NULL'>- All Students -</option><option value='1'>🟣 Reading/Social</option><option value='2'>🔴 Reading/Social</option><option value='3'>🔵 Reading/Social</option><option value='4'>🟢 Reading/Social</option>
</select>
</div>
</section>
</div>
<div class='advanced' data-page='advanced'>
<section>
<span>Submission: </span>
<select name='submitType'>
<option value='scan'>Require students to scan.</option>
<option value='button'>Allow scanning or turn in button.</option>
</select>
</section>
<section>
<span>Assignment Type: </span>
<select name='assType'>
<option>Assignment</option>
<option>Assessment</option>
<option>Daily Work</option>
<option>Quiz</option>
<option>Participation</option>
<option>Project</option>
</select>
</section>
</div>
<div class='delete' data-page='delete'>
<p>Deleting the assignment? The following will happen: </p>
<ul>
<li>All recorded scores will be deleted.</li>
<li>Student averages will adjust from the deleted scores.</li>
<li>The assignment will be removed from student view.</li>
<li>This action cannot be undone.</li>
</ul>
<button class='button grey-btn'>Cancel</button>
<button class='button red-btn'>Permanently Delete</button>
</div>
</div>
</div>
</div>
</form>
Any advice is greatly appreciated. What is going on?
#Mathew Try this
$('.section-group-js').on('keyup', 'input[type="url"]', function() {
var section = $(this).closest('section');
if (section.is(':last-child')) {
var index = section.data('index');
var newSection = section.clone();
newSection.find('input').val('');
newSection.data('index', index + 1);
newSection.attr('data-index', index + 1);
updateAttributes(newSection, 'title', index);
updateAttributes(newSection, 'url', index);
updateAttributes(newSection, 'visible', index);
newSection.insertAfter(section);
}
})
function updateAttributes( newSection, key, index ) {
newSection.find(`[name="attach[${index}][${key}]"]`).attr('name', `attach[${index+1}][${key}]`);
}
.modal {
display: block !Important
}
.modal {
display: none;
position: fixed;
z-index: 20;
right: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(0, 0, 0, 0.4);
-webkit-animation-name: fadeIn;
-webkit-animation-duration: 0.4s;
animation-name: fadeIn;
animation-duration: 0.4s
}
.assignment-window {
display: grid;
position: fixed;
overflow: hidden;
padding: 10px;
padding-bottom: 16px;
box-sizing: border-box;
width: 100vw;
height: 85vh;
bottom: 0;
left: 0;
border-top-left-radius: 40px;
border-top-right-radius: 40px;
background-color: white;
grid-template-rows: auto 1fr;
grid-template-columns: 0.9fr 2.5fr;
grid-template-areas: "asstop asstop""assnav asscontent"
}
/* ----------[ASS TOP]---------- */
.asstop {
grid-area: asstop;
padding: 24px 20px;
box-sizing: border-box;
border-bottom: 2px solid #581F98;
}
.asstop .title {
display: flex;
align-items: center;
}
.asstop .title input {
flex: 1 1;
font-size: 24px;
border-radius: 8px;
margin-right: 20px;
border: 1px solid lightgray
}
.asstop select {
outline: none;
-webkit-appearance: none;
padding: 12px 16px;
font-size: 24px;
box-sizing: border-box;
border-radius: 8px;
border: 1px solid lightgray
}
.asstop button {
margin-top: -5px;
}
/* ----------[ASS NAV]---------- */
.assnav {
grid-area: assnav;
padding-top: 20px;
padding-right: 10%;
border-right: 1px solid lightgray
}
.assnav ul {
margin: 0;
padding: 0;
overflow: hidden;
list-style-type: none
}
.assnav li {
display: block;
text-decoration: none;
color: #484848;
font-size: 20px;
padding: 14px 20px;
margin-bottom: 10px;
border-top-right-radius: 40px;
border-bottom-right-radius: 40px;
}
.assnav li:hover {
background-color: #F2F2F2
}
.assnav li.active {
background-color: #EEEEEE
}
/* ----------[ASS CONTENT]---------- */
.asscontent {
grid-area: asscontent;
display: flex;
flex-direction: column;
padding: 30px;
box-sizing: border-box;
}
.asscontent input,
.asscontent select {
flex: 1;
outline: none;
-webkit-appearance: none;
padding: 8px 16px;
font-size: 18px;
box-sizing: border-box;
border-radius: 8px;
border: 1px solid lightgray
}
/* ==== Basic Styling ==== */
.asscontent .basic {
display: none
}
.asscontent .basic textarea {
flex: 1;
font-size: 18px;
border-radius: 8px;
box-sizing: border-box;
}
.asscontent .basic .config {
display: flex;
justify-content: space-between;
padding-top: 20px;
}
.asscontent .basic input {
text-align: center;
}
.asscontent .basic .points {
width: 80px;
}
/* ==== Attachment Styling ==== */
.asscontent .attachments section {
display: flex;
justify-content: space-between;
padding-bottom: 15px;
margin-bottom: 15px;
border-bottom: 1px solid lightgray
}
<head>
<link rel="stylesheet" href="https://classcolonies.com/resources/style.css">
<link href="https://fonts.googleapis.com/css2?family=Raleway&display=swap" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<nav></nav>
</head>
<div class="modal">
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">
<div class="assignment-window">
<div class='asstop'>
<div class='title'>
<select>
<option>✏️</option>
<option>💻</option>
<option>📚</option>
<option>💯</option>
<option>🧪</option>
</select>
<input type='text' placeholder='Type assignment title..' value=''>
<button type="submit" class='button purple-btn'>Save Changes</button>
</div>
</div>
<div class='assnav'>
<ul>
<li>Basic Setup</li>
<li>Attachments</li>
<li>Advanced Settings</li>
<li>Delete Assignment</li>
</ul>
</div>
<div class='asscontent'>
<div class='attachments section-group-js'>
<section data-index="1">
<div class='displayName'>
<span> Title: </span>
<input name='attach[1][title]' type='text'>
</div>
<div class='url'>
<span>URL: <span>
<input name='attach[1][url]' type='url'>
</div>
<div class='visible'>
<span>Visible: <span>
<select name='attach[1][visible]'>
<option>- All Students -</option>
<option>🟣 Reading/Social</option>
</select>
</div>
</section>
</div>
</div>
</div>
</form>
</div>
<?php
if ( isset($_POST['attach']) ) {
echo "<pre>";
print_r($_POST);
echo "</pre>";
die;
}
?>
And the output is below
Related
How can I add icons before the form fields?
This is how looks now:
And here how I want:
Here is css code (front.css):
body .qb-form {
width: auto;
height: auto;
}
#media (max-width: 660px) {
body .qb-form {
width: 100%;
}
}
body .qb-form h2 {
background: #3482C3;
padding: 15px 25px;
margin-bottom: 0;
color: white;
margin-top: 0;
}
body .qb-form .moreinfo {
background: #3482C3;
color: white;
padding: 0 25px 15px 25px;
margin-bottom: 15px;
}
body .qb-form label {
text-align: left;
font-size: 14px;
display: block;
padding-bottom: 0;
}
body .qb-form .qb-gdpr-label {
padding-bottom: 0;
}
body .qb-form .quickbuy_input {
height: 31px;
width: 190px;
border: 1px solid #ABADB3;
padding: 5px;
}
body .qb-form textarea {
width: 100%;
height: 60px;
border: 1px solid #abadb3;
}
body .qb-form .crow {
padding: 0 25px 25px 25px;
}
body .qb-form .buttons_wrp {
padding: 10px 25px 25px 25px;
}
body .qb-form .buttons_wrp .button {
padding: 10px 20px;
border: none;
border-radius: 4px;
text-transform: uppercase;
color: white;
background: #3482C3;
overflow: hidden;
}
body .qb-form .buttons_wrp .qb-btn-submit {
padding: 10px 20px 10px 62px;
background: #3482C3 url('../img/cart-icon.png') no-repeat 15px center;
}
body .qb-form .buttons_wrp .button:hover {
background-color: #388bd1;
}
body .qb-wrp .qb-btn span {
border-bottom: 1px dashed;
}
.product-simple .qb-btn {
background: none;
color: #1F679B;
font-size: 13px;
border-bottom: 1px dashed #1F679B;
padding: 0 0 1px 0;
}
body .qb-form sup {
color: red;
font-weight: bold;
}
body .qb-form .quickbuy_errors,
body .qb-form .quickbuy_success {
margin: 0 15px;
display: none;
padding: 10px;
line-height: 1.5;
}
body .qb-form .qb-product-name {
padding: 5px;
border: 1px dashed white;
font-weight: bold;
display: inline-block;
}
body .qb-form body .qb-form_loader {
position: relative;
top: -3px;
}
body .qb-form .qb-loader {
visibility: hidden;
}
body .qb-form .qb-loader.visible {
visibility: visible;
}
.qb-form .qb-gdpr-label .qb_gdpr_wrp {
float: left;
position: relative;
top: 3px;
margin-right: 10px;
}
.qb-form .qb-btn-close {
display: none;
}
.qb-form .qb-btn-close span {
font-size: 2rem;
line-height: 0;
display: inline-block;
vertical-align: middle;
margin-right: 0.5rem;
position: relative;
top: -1px;
border: none;
}
.qb-gdpr-label p:last-child {
margin-bottom: 0;
}
#media (max-width: 767px) {
.qb-wrap,
#product .qb-wrap {
flex-wrap: wrap;
}
}
And here is the hook.tpl:
<div class="crow">
<label for="quickbuy_name">{l s='Your name' mod='quickbuy'}:</label>
<input type="text" class="qb_name qb-input-field form-control" id="quickbuy_name" name="qb_customer_name" value="{$qb_name|escape:'html':'UTF-8'}" />
</div>
<div class="crow">
<label for="quickbuy_address">{l s='Your address' mod='quickbuy'}:</label>
<input type="text" class="qb_address qb-input-field form-control" id="quickbuy_address" name="qb_address" value="{$qb_address|escape:'html':'UTF-8'}" />
</div>
<div class="crow">
<label for="quickbuy_phone">{l s='Your phone number' mod='quickbuy'}: <sup>*</sup></label>
<input type="text" class="qb_phone qb-input-field form-control" id="quickbuy_phone" name="qb_phone" value="{$qb_phone|escape:'html':'UTF-8'}" />
</div>
{if $qb_gdpr}
<div class="crow">
<label class="qb-gdpr-label">
<span class="qb_gdpr_wrp">
<input type="checkbox" class="qb_gdpr" name="qb_gdpr">
</span>
{if $qb_gdpr_text}
{$qb_gdpr_text nofilter}{* HTML *}
{else}
{l s='I agree to processing of my personal data' mod='quickbuy'}
{if $qb_gdpr_link}(<a target="_blank" href="{$qb_gdpr_link|escape:'html':'UTF-8'}">{l s='read' mod='quickbuy'}</a>){/if}
{/if}
</label>
</div>
{/if}
<div class="crow quickbuy_errors error"></div>
<div class="crow quickbuy_success success"></div>
<div class="buttons_wrp">
<input type="hidden" name="qb_id_product" value="{$qb_product->id|intval}" />
<input type="hidden" name="qb_id_product_attribute" value="{$qb_product->id_product_attribute|intval}" />
<input type="hidden" name="qb_token" value="{$qb_token|escape:'html':'UTF-8'}" />
<input type="hidden" name="qb_action" value="submitQB" />
<input type="submit" class="qb-btn-submit btn btn-default button button-small" value="{l s='Buy' mod='quickbuy'}" />
<button class="qb-btn-close btn btn-default button button-small"><span>×</span> {l s='Close' mod='quickbuy'}</button>
<img class="qb-loader" src="/img/loader.gif" alt="{l s='Loading...' mod='quickbuy'}" />
</div>
</div>
</div>
</div>
I will be happy if anyone can help.
Thank you in advance.
Best regards
You can select the input fields from your HTML template by using their id's.
You you use icons8 to find the correct icons.
There you can get the Link (CDN) for each item by clicking on the download button and copy HTML.
You can paste the copied code in your HTML (just before the respective input field).
Afterwards you can style the respective item in your CSS file.
So that it has the same border and height as your input field.
I have a text input nested in a parent div. When you type in the text input, a "delete text" button appears. When the "delete text" button appears, it causes its parent div "headerSearch" to decrease in height from 71px to 70px in Safari only.
When the "delete text" button is hidden again, the parent div "headerSearch" has it's height go back from 70px to 71px.
Why does displaying the "delete text" button cause the parent div "headerSearch" to change its height in Safari, and how do I prevent it?
Try the code snippet below using Safari where I reproduced the problem.
function deleteSearchBarContents() {
document.getElementById('searchBox').value = "";
document.getElementById("searchBox").focus();
document.getElementById("deleteSearchBarContentsButton").style.display = "none";
}
document.getElementById("deleteSearchBarContentsButton").addEventListener("click", deleteSearchBarContents);
function showDeleteSearchBarContentsButton() {
// If value is not empty
if (document.getElementById("searchBox").value.trim() == "") {
// Hide the element
document.getElementById("deleteSearchBarContentsButton").style.display = "none";
} else {
// Otherwise show it
document.getElementById("deleteSearchBarContentsButton").style.display = "inline-block";
}
}
document.getElementById("searchBox").addEventListener("keyup", showDeleteSearchBarContentsButton);
.wrapperSearch {
max-width: 100%;
overflow: hidden;
min-height: 1111px;
margin: 0 auto;
position: relative;
}
.headerSearch {
background: #3f3f3f;
position: relative;
display: inline-block;
width: 100%;
}
.entireSearchContainer {
margin-left: 29.034px;
}
.entireSearchContainer .searchBar {
display: inline-block;
width: 400px;
margin-top: 22.82px;
height: 46.978px;
background-color: #fff;
}
.entireSearchContainer .searchBar .searchBarInner {
display: inline-flex;
display: -webkit-inline-flex;
width: 100%;
height: 47px;
}
.entireSearchContainer .searchBar .searchBox {
flex: 1;
border: none;
background-color: transparent;
padding: 17.944px;
font-size: 16px;
outline: 0;
box-shadow: none;
-webkit-appearance: none;
}
.deleteSearchBarContentsButton {
display: none;
border: none;
background-color: transparent;
height: 46.978px;
border-radius: 2.618px;
margin-top: 0;
justify-content: center;
outline: 0!important;
cursor: pointer;
display: inline;
color: #252525!important;
display: none;
padding-right: 0;
width: 17.944px;
margin-left: 11.09px;
color: #888;
margin-right: 0;
overflow: hidden;
}
.entireSearchContainer .searchBar .searchButton {
border: none;
background-color: transparent;
height: 46.978px;
border-radius: 2.618px;
margin-top: 0;
width: 46.978px;
padding-right: 17.944px;
justify-content: center;
outline: 0!important;
cursor: pointer;
display: inline-block;
overflow: hidden;
}
.searchButton img {
width: 16px;
height: 16px;
vertical-align: middle!important;
-webkit-filter: grayscale(100%);
filter: grayscale(100%);
}
.deleteSearchBarContentsButton {
display: none;
padding-right: 0!important;
width: 17.944px!important;
margin-left: 11.09px!important;
}
.deleteSearchBarContentsButton img {
width: 11px!important;
height: 11px!important;
vertical-align: middle!important;
}
<div class="wrapperSearch">
<div class="headerSearch">
<div class="entireSearchContainer" id="entireSearchContainer">
<form id="searchForm" name="test" action="https://example.com/" method="GET">
<div class="searchBar" id="searchBar">
<div class="searchBarInner">
<input class="searchBox" id="searchBox">
<button class="deleteSearchBarContentsButton" id="deleteSearchBarContentsButton" type="button"><img src="https://th.bing.com/th/id/R.f8232e70a6e015e91560068ebde56fb4?rik=LZu9qZIqj6SnLw&riu=http%3a%2f%2fcdn.onlinewebfonts.com%2fsvg%2fimg_376399.png&ehk=mpYEtMisrcWebqodks%2fXno%2fbN9QmLfHuo7tMTVFKGnE%3d&risl=&pid=ImgRaw&r=0"></button>
<button class="searchButton" type="submit" value="Search"><img src="https://th.bing.com/th/id/OIP.-9A-FOvJIk9-zy2b0vofXAHaHX?pid=ImgDet&rs=1"></button>
</div>
</div>
</form>
</div>
</div>
</div>
.entireSearchContainer .searchBar {
display: block;
}
I'm embarrassed this is the solution. Safari didn't like it when the "searchBar" was display: inline-block; even though other browsers it was fine.
I have this piece of code:
function dropdown() {
let dropdownText = document.querySelector(".dropdown-button");
let item = document.querySelector(".dropdown-items").getElementsByTagName("div")[0];
var aux = dropdownText.innerHTML;
dropdownText.innerHTML = item.innerHTML;
item.innerHTML = aux;
document.querySelector(".dropdown-items").style.display = "none";
}
.btn {
width: 150px;
height: 30px;
border-radius: 5px;
border: none;
box-shadow: 0 3px 1px 0 black;
text-align: center;
line-height: 30px;
color: black;
font-family: Consolas, monaco, monospace;
}
.dropdown {
margin: 0 50px 0 50px;
position: relative;
}
.dropdown-items {
display: none;
position: absolute;
}
.dropdown:hover .dropdown-button {
background: red;
}
.dropdown:hover .dropdown-items {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.dropdown-button {
background: orange;
font-size: 15px;
color: white;
}
.dropdown-button:hover {
cursor: pointer;
}
.dropdown-items div {
margin-top: 5px;
transform: scaleX(90%);
height: 20px;
line-height: 20px;
background: lightgray;
padding: 5px 0 5px 0;
text-align: center;
}
.dropdown-items div:hover {
cursor: pointer;
background: gray;
}
<div class="dropdown">
<button class="btn dropdown-button" type="button">Terminate</button>
<div class="dropdown-items">
<div class="btn" onclick="dropdown();">Interrupt</div>
</div>
</div>
As you can see, I am trying to make a dropdown. I also want to make it so that when I click an option in the dropdown, the dropdown items stop showing as the option has been selected. That's why I added the line document.querySelector(".dropdown-items").style.display = "none"; in the JS file as I thought the .dropdown:hover .dropdown-items part of my CSS would change back the display of those elements to visible when hovering again, but when hovering again after the first click, the dropdown does not show anymore. Why is happening and how can I fix this?
Inline styles override any stylesheet styles, as they have maximum CSS specificity.
Instead of working with inline styles (el.style.display = "none"), work with a CSS class open that you toggle. Also don't make use of inline event listeners like onclick. Those are insecure and widely considered bad practice for a whole bunch of reasons. Use addEventListener instead.
// get all the dropdowns in a NodeList
const dropdowns = document.querySelectorAll('.dropdown');
// iterate over the list
for (const dropdown of dropdowns) {
// for each dropdown, add a mouseenter and mouseleave listener
dropdown.addEventListener('mouseenter', function(event) {
dropdown.classList.add('open');
});
dropdown.addEventListener('mouseleave', function(event) {
dropdown.classList.remove('open');
});
// Now add a click listener to each <div class="dropdown-items">
// that transfers the text and closes the dropdown
dropdown.querySelector('.dropdown-items').addEventListener(
'click',
function(event) {
this.previousElementSibling.textContent = this.textContent;
dropdown.classList.remove('open');
}
);
}
.btn {
width: 150px;
height: 30px;
border-radius: 5px;
border: none;
box-shadow: 0 3px 1px 0 black;
text-align: center;
line-height: 30px;
color: black;
font-family: Consolas, monaco, monospace;
}
.dropdown {
display: inline-block;
position: relative;
}
.dropdown-items {
display: none;
position: absolute;
}
.dropdown:hover .dropdown-button {
background: red;
}
.dropdown.open .dropdown-items {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.dropdown-button {
background: orange;
font-size: 15px;
color: white;
}
.dropdown-button:hover {
cursor: pointer;
}
.dropdown-items div {
margin-top: 5px;
transform: scaleX(90%);
height: 20px;
line-height: 20px;
background: lightgray;
padding: 5px 0 5px 0;
text-align: center;
}
.dropdown-items div:hover {
cursor: pointer;
background: gray;
}
<div class="dropdown">
<button class="btn dropdown-button" type="button">Terminate</button>
<div class="dropdown-items">
<div class="btn">Interrupt</div>
</div>
</div>
<div class="dropdown">
<button class="btn dropdown-button" type="button">Terminate</button>
<div class="dropdown-items">
<div class="btn">Whatever</div>
</div>
</div>
<div class="dropdown">
<button class="btn dropdown-button" type="button">Terminate</button>
<div class="dropdown-items">
<div class="btn">Another one</div>
</div>
</div>
<div class="dropdown">
<button class="btn dropdown-button" type="button">Terminate</button>
<div class="dropdown-items">
<div class="btn">Here we go</div>
</div>
</div>
I am struggling with the footer when the modal pops up. The footer doesn't get the opacity that the rest of the HTML page gets. There's anyway to fix it?
PS: It may not be clear in the snippet, so here's the image of the problem:
Codes:
/*Abre e fecha o modal*/
const Modal = {
open(){
document.querySelector('.modal-overlay').classList.toggle('active')
}
}
const transactions = [
{
id: 1,
description: 'Luz',
amount: -50000,
date: '23/01/2021'
},
{
id: 2,
description: 'Website',
amount: 500000,
date: '23/01/2021'
},
{
id: 3,
description: 'Internet',
amount: -2000,
date: '23/01/2021'
},
{
id: 3,
description: 'App',
amount: 2000,
date: '23/01/2021'
},
]
//transaçoes
const Transaction = {
entry(){
//grana que entra
},
out(){
//grana que subtrai
},
total(){
//entry - out
}
}
/* const Modal = {
open(){
document.querySelector('.modal-overlay').classList.add('active')
},
close(){
document.querySelector('.modal-overlay').classList.remove('')
}
}
*/
//criando o HTML pelo JavaScript
const DOM = {
transactionsCointainer: document.querySelector('#data-table tbody'),
addTransaction(transaction, index){
const tr = document.createElement('tr')
tr.innerHTML = DOM.innerHTMLTransaction(transaction)
DOM.transactionsCointainer.appendChild(tr)
console.log(tr.innerHTML)
},
innerHTMLTransaction(transaction) {
const CSSclass = transaction.amount> 0 ? "income" : "expense"
const amount = Utils.formatCurrency(transaction.amount)
const html =
`
<td class="description">${transaction.description}</td>
<td class="${CSSclass}">${amount}</td>
<td class="date">${transaction.date}</td>
<td>
<img src="/assets/minus.svg" alt="Remover Transação">
</td>
`
return html
}
}
const Utils = {
formatCurrency(value){
const signal = Number(value) < 0 ? "-" : ""
value = String(value).replace(/\D/g, "")
value = Number(value) / 100
value = value.toLocaleString("pt-br", {
style: "currency",
currency: "BRL"
})
return signal + value
}
}
transactions.forEach(function(transaction){
DOM.addTransaction(transaction)
})
#import url('https://fonts.googleapis.com/css2?family=Nunito:ital,wght#0,400;0,700;1,400&display=swap');
:root {
--color-dark : #363f5f;
--color-green : #2D4A22;
--color-light-green: #49aa26;
}
* {
padding: 0;
margin : 0;
border : 0;
}
body {
font-family : 'Nunito', sans-serif;
background-color: #f0f2f5;
}
html {
font-size: 93.75%;
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0;
}
.container {
width : min(90vw, 800px);
margin: 0 auto;
}
/* === HEADER === */
header {
background: var(--color-green);
padding : 2rem 0 10rem;
text-align: center;
}
#logo {
color : #fff;
font-weight: 100;
}
/*=== TITLES === */
h2{
margin-top : 3.2rem;
margin-bottom: 0.8rem;
color : var(--color-dark);
font-weight : normal;
}
/*=== BALANCE === */
#balance {
margin-top: -8rem;
}
#balance h2 {
color : white;
font-weight: bold;
}
/*=== CARDS === */
.card {
background : white;
padding : 1.5rem 2rem;
border-radius: 0.25rem;
margin-bottom: 2rem;
}
.card h3 {
font-weight: normal;
font-size : 1rem;
display: flex;
align-items: center;
justify-content: space-between;
}
.card p {
font-size : 2rem;
line-height: 3rem;
margin-top : 1rem;
}
.card.total {
background: var(--color-light-green);
color : white;
}
/* === TRANSAÇÕES === */
#transaction {
display: block;
overflow-x: auto;
width: 100%;
}
#data-table {
width : 100%;
border-spacing: 0 0.5rem;
}
table thead tr th:first-child,
table tbody tr td:first-child{
border-radius: 0.25rem 0 0 0.25rem;
}
table thead tr th:last-child,
table tbody tr td:last-child{
border-radius: 0 0.25rem 0.25rem 0;
}
table th {
color : #969CB3;
font-weight : normal;
padding : 1rem 2rem;
text-align : left;
background-color: white;
border-radius : 0.25rem;
font-weight : bold;
}
td.description {
color: var(--color-dark);
}
td.income {
color: #12a454;
}
td.expense {
color: rgb(228, 67, 67);
}
td.date {
color: var(--color-dark);
}
table td {
background : white;
padding : 1rem 2rem;
color : #969CB3;
font-weight: bold;
}
table tbody tr {
opacity: 0.7;
}
table tbody tr:hover{
opacity: 1;
}
button {
width: 100%;
height: 50px;
border: none;
background-color: var(--color-light-green);
color: #fff;
font-weight: bold;
text-transform: uppercase;
cursor: pointer;
border-radius: 0.25rem;
}
button:hover {
background: rgb(0, 140, 0);
}
.button-new {
color: var(--color-light-green);
text-decoration: none;
font-weight: bold;
margin-bottom: .8rem;
display: inline-block;
}
a .button {
width: 100%;
color: white;
}
.button-new:hover {
color: #06bd4c;
transition: color 700ms;
}
td img {
cursor: pointer;
}
/* === MODAL === */
.modal-overlay {
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.7);
position: fixed;
top: 0;
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
visibility: hidden;
}
.modal-overlay.active {
opacity: 1;
visibility: visible;
}
.modal {
background: #f0f2f5;
padding: 2.4rem ;
max-width: 500px;
width: 90%;
}
/*=== MODAL FORM === */
#form {
max-width: 500px;
}
#form h2 {
margin-top: 0;
}
input {
border: none;
width: 100%;
border-radius: 0.2rem;
padding: 0.8rem;
}
.input-group {
margin-top: 0.8rem;
}
.input-group small {
opacity: .4;
font-weight: bold;
}
/*=== MODAL BUTTON === */
.input-group-actions {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 1.8rem;
}
.input-group-actions .button,
.input-group.actions button {
width: 48%;
}
.input-group-actions .button {
padding: 1rem;
width: 100%;
text-align: center;
border: 1px solid #FF4136;
border-radius: 0.25rem;
text-decoration: none;
color: white;
margin-right: 5px;
background-color: #FF4136;
text-transform: uppercase;
font-weight: bold;
}
.input-group-actions .button:hover {
background: rgb(143, 0, 0);
}
/* === FOOTER === */
footer {
text-align: center;
margin-top: 20px;
}
/* === RESPONSIVE === */
#media (min-width: 800px) {
html { font-size: 87.5%;
}
#balance {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 2rem;
}
}
#media (min-width: 992px) {
footer{
display: block;
background-color: var(--color-green);
color: #fff;
padding: 2rem 0 10rem;
bottom: 0;
position: absolute;
width: 100%;
}
}
<!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">
<title>dev.finance$</title>
</head>
<body>
<header>
<img src="/assets/logo.svg" alt="Logo Dev Finance">
</header>
<main class="container">
<section id="balance">
<h2 class="sr-only">Balanço</h2>
<div class="card">
<h3>
<span>Entradas</span>
<img src="/assets/income.svg" alt="Imagem de Entradas">
</h3>
<p>R$ 5.000,00</p>
</div>
<div class="card">
<h3>
<span>Saídas</span>
<img src="/assets/expense.svg" alt="Imagem de Saídas">
</h3>
<p>R$ 2.000,00</p>
</div>
<div class="card total">
<h3>
<span>Total</span>
<img src="/assets/total.svg" alt="Imagem de Total">
</h3>
<p>R$ 3.000,00</p>
</div>
</section>
<section id="transaction">
<h2 class="sr-only">Transações</h2>
+ Nova Transação
<table id="data-table">
<thead>
<tr>
<th>Descrição</th>
<th>Valor</th>
<th>Data</th>
<th></th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</section>
</main>
<div class="modal-overlay">
<div class="modal">
<div id="form">
<h2>Nova Transação</h2>
<form action="">
<div class="input-group">
<label class="sr-only" for="description">Descrição</label>
<input type="text" id="description" name="description" placeholder="Descrição">
</div>
<div class="input-group">
<label class="sr-only" for="amount">Valor</label>
<input type="number" id="amount" name="amount" placeholder="0,00" step="0.01">
<small>Usar o sinal - (negativo) para despesas e , (vírgula) para casas decimais.</small>
</div>
<div class="input-group">
<label class="sr-only" for="date">Data</label>
<input type="date" id="date" name="date">
</div>
<div class="input-group-actions">
Cancelar
<button>Salvar</button>
</div>
</div>
</div>
</div>
<footer>
<img src="/assets/logo-footer.svg" alt="Logo Dev Finance">
</footer>
<script src="scripts.js"></script>
</body>
</html>
Your modal-overlay is displaying behind your footer.
Add a z-index: 1000 to your modal-overlay rule.
.modal-overlay.active {
opacity: 1;
visibility: visible;
z-index: 1000; /* <- add this */
}
I have a problem that my delete button (the yellow one) works perfectly on preloaded book library items, but it isn't on the new entry when I add a book and want to delete it... I also want you to ask what it would be the easiest way to delete books also from myLibrary array... Thanks.
I've attached my code here. Any help will be appreciated. Thanks in advance.
//DOM
const bookForm = document.querySelector(".book-form");
// Calling a form when clicking on add book button
function openNav() {
document.getElementById("myNav").style.height = "100%";
console.log("dsafsa");
}
function closeNav() {
document.getElementById("myNav").style.height = "0%";
}
// where the books will be saved...
let myLibrary = [{
title: "Harry Potter - and the Philosopher's Stone",
author: "J. K. Rowling",
pages: 223,
readStatus: "no",
},
{
title: "The Hobbit",
author: "J.R.R. Tolkien",
pages: 304,
readStatus: "yes",
},
];
// book object
function Book(title, author, pages, readStatus) {
(this.title = title),
(this.author = author),
(this.pages = pages),
(this.readStatus = readStatus);
}
let i = "";
// render the book on page load...
function render() {
const books = myLibrary;
books.forEach((book) => {
addNewBookUI(book);
});
}
render();
document.querySelector(".book-form").addEventListener("submit", (e) => {
// prevent actual submit
e.preventDefault();
// get values
const title = document.querySelector("#title").value;
const author = document.querySelector("#author").value;
const pages = document.querySelector("#pages").value;
const readStatus = document.querySelector('input[name="yes_no"]:checked')
.value;
// prevent empty fields ...
if (title === "" || author === "" || pages === "0") {
alert("Missing data");
} else {
const book = new Book(title, author, pages, readStatus);
myLibrary.push(book);
addNewBookUI(book);
clearFormFields()
}
});
function addNewBookUI(book) {
if (book.readStatus === "yes") {
i = "checked";
} else {
i = "";
}
const main = document.querySelector(".main");
const bookCard = document.createElement("div");
bookCard.classList.add("book-card");
bookCard.innerHTML = `<div class="delete_button"><button class="delete btn"><i class="fa fa-trash">
</i></button></div><div class="title">${book.title}</div><div class="author">${book.author}
</div><div class="pages">${book.pages}</div><div class="read_status">Read: <input type="checkbox" id="yes" name="readstatus" value="yes" ${i}>
</div>`;
main.appendChild(bookCard);
}
// clear form fields after submit
function clearFormFields() {
const myForm = document.getElementById("myForm");
myForm.reset();
}
// Add event listener to all deleteButton
const deleteButton = document.querySelectorAll(".delete");
// deletes book UI;
deleteButton.forEach((el) => {
el.addEventListener("click", function () {
el.parentElement.parentElement.remove()
console.log("sas")
})
})
*,
*::before,
*::after {
box-sizing: border-box;
}
body {
font-family: 'Roboto', sans-serif;
margin: 0;
padding: 0;
}
header {
color: #ffffff;
display: flex;
font-size: 1.4rem;
justify-content: space-between;
align-items: center;
background-color: #155999;
border-bottom: #172f4f solid 10px;
}
.logo {
margin-left: 10px;
}
header button {
background-color: #183153;
border: none;
text-align: left;
font-size: 0.9rem;
border-radius: 5px;
color: #ffffff;
padding: 10px 50px;
margin-right: 10px;
cursor: pointer;
}
.plus-sign {
padding-right: 7px;
}
.main {
position: absolute;
width: 100%;
height: 100%;
background-color: #183153;
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
}
.book-card {
text-align: center;
font-weight: 1000;
display: flex;
flex-direction: column;
justify-content: space-evenly;
width: 250px;
height: 350px;
border-radius: 10px;
background-color: #155999;
margin-left: 20px;
margin-top: 10px;
color: #ffffff;
border: #172f4f solid 8px;
line-height: 30px;
position: relative;
padding-left: 7px;
padding-right: 7px;
box-shadow: 10px 4px 22px -5px rgba(21, 89, 153, 1);
}
.overlay {
height: 0%;
width: 100%;
position: fixed;
z-index: 1;
top: 0;
left: 0;
background-color: rgb(21, 89, 153);
background-color: rgba(21, 89, 153, 0.7);
overflow-y: hidden;
transition: 0.5s;
}
.overlay-content {
position: relative;
top: 25%;
width: 100%;
text-align: center;
margin-top: 30px;
display: flex;
flex-direction: column;
font-size: 30px;
}
.overlay a {
padding: 8px;
text-decoration: none;
font-size: 36px;
color: #ffffff;
display: block;
transition: 0.3s;
}
.overlay a:hover,
.overlay a:focus {
color: #c3c6d1;
}
.overlay .closebtn {
position: absolute;
top: 20px;
right: 45px;
font-size: 60px;
}
#media screen and (max-height: 450px) {
.overlay {
overflow-y: auto;
}
.overlay a {
font-size: 20px
}
.overlay .closebtn {
font-size: 40px;
top: 15px;
right: 35px;
}
}
.book-card div {
margin-top: 15px;
}
/* Style buttons */
.btn {
background-color: #ffd43b;
/* Blue background */
border: none;
/* Remove borders */
color: red;
/* White text */
padding: 12px 16px;
/* Some padding */
font-size: 16px;
/* Set a font size */
cursor: pointer;
/* Mouse pointer on hover */
border-radius: 50%;
position: absolute;
top: -20px;
right: -15px;
}
/* Darker background on mouse-over */
.btn:hover {
background-color: #183153;
}
.delete_button {
top: 0;
right: 0;
}
form div {
margin-top: 15px;
font-family: 'Roboto', sans-serif;
color: white;
font-weight: bold;
font-size: 30px;
margin-bottom: 10px;
}
.radiobutton {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.form-flex {
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
}
.form-flex input {
width: 50%;
border-radius: 5px;
height: 30px;
margin-top: 5px
}
.form-flex input::placeholder {
text-align: center;
}
input[type=submit] {
background-color: #183153;
border: none;
text-align: left;
font-size: 0.9rem;
border-radius: 5px;
color: #ffffff;
padding: 10px 50px;
margin-top: -30px;
cursor: pointer;
}
.radiobutton p {
margin-top: 10px;
margin-bottom: 30px;
}
.flexbuttons {
display: flex;
margin-top: -50px;
margin-bottom: -25px;
}
input[type="text"] {
font-size: 24px;
text-align: center;
}
<!-- The overlay -->
<div id="myNav" class="overlay">
<!-- Button to close the overlay navigation -->
×
<!-- Overlay content -->
<div class="overlay-content">
<form id="myForm" class="book-form">
<div class="form-flex">
<label for="title">Book name:</label>
<input type="text" id="title" name="title" placeholder="Book name...">
</div>
<div class="form-flex">
<label for="author">Book author:</label>
<input type="text" id="author" name="author" placeholder="Book author...">
</div >
<div class="form-flex">
<label for="pages">Pages:</label>
<input type="number" id="pages" placeholder="0" name="pages">
</div>
<div class="radiobutton">
<p>Have you read a book?</p>
<div class="flexbuttons">
<div>
<p><input type="radio" id="huey" name="yes_no" value="yes" checked>
<label for="huey">yes</label>
</p>
</div>
<div>
<p><input type="radio" id="no" name="yes_no" value="no">
<label for="dewey">no</label>
</p>
</div>
</div>
</div>
<div><input type="submit" value="Add Book"></div>
</form>
</div>
</form>
</div>
</div>
</div>
<header>
<div class="logo">
<h1><i class="fa fa-book" aria-hidden="true"></i>
</i>Library
</h1>
</div>
<div class="button">
<button onclick="openNav()" class="add-book">
<i class="fa fa-plus plus-sign"></i>
Add book</button>
</div>
</header>
<div class="main">
</div>
<script src="./index.js" defer></script>
<script src="https://use.fontawesome.com/30a34909cc.js"></script>
You assigned the click event at loading time to all existing buttons with class=="delete". This will naturally not include the ones you might add dynamically at a later stage.
If you want all ".delete" buttons to have the click-event attached to them you need to do a "delegated event attachment" (edited, removes myLibrary element too now):
// Add event listener to all current and future deleteButtons
document.querySelector('.main').onclick=ev=>{
let el= ev.target.classList.contains('fa-trash')? ev.target.parentElement : ev.target.classList.contains('delete') ? ev.target : false;
if (el) {
let card=el.parentElement.parentElement; // book-card DOM element
// remove myLibrary array-element here:
myLibrary.splice( [...card.parentElement.children].indexOf(card) ,1);
console.log(myLibrary)
// remove card DOM element:
card.remove()
}
}
This will bind the click event handler to the .main div and will react only if the clicked element has a class=='fa-trash' or class=='delete'. In the first case it will "move up" one level (assign the parent element, i. e. the button to el), otherwise the clicked element is the button itself. If none of these classes are found, el becomes false and nothing happens. Otherwise the "Grandparent" of el is removed with `el.parentElement.parentElement.remove()' .
And please try and make your MCVE a little smaller next time, as it no fun to handle this amount of code in a small Stackoverflow snippet window! A true MCVE will get you more and faster responses!
Below is a working snippet, check it out:
//DOM
const bookForm = document.querySelector(".book-form");
// Calling a form when clicking on add book button
function openNav() {
document.getElementById("myNav").style.height = "100%";
console.log("dsafsa");
}
function closeNav() {
document.getElementById("myNav").style.height = "0%";
}
// where the books will be saved...
let myLibrary = [
{
title: "Harry Potter - and the Philosopher's Stone",
author: "J. K. Rowling",
pages: 223,
readStatus: "no",
},
{
title: "The Hobbit",
author: "J.R.R. Tolkien",
pages: 304,
readStatus: "yes",
},
];
// book object
function Book(title, author, pages, readStatus) {
(this.title = title),
(this.author = author),
(this.pages = pages),
(this.readStatus = readStatus);
}
let i = "";
// render the book on page load...
function render() {
const books = myLibrary;
books.forEach((book) => {
addNewBookUI(book);
});
}
render();
document.querySelector(".book-form").addEventListener("submit", (e) => {
// prevent actual submit
e.preventDefault();
// get values
const title = document.querySelector("#title").value;
const author = document.querySelector("#author").value;
const pages = document.querySelector("#pages").value;
const readStatus = document.querySelector('input[name="yes_no"]:checked')
.value;
// prevent empty fields ...
if (title === "" || author === "" || pages === "0") {
alert("Missing data");
} else {
const book = new Book(title, author, pages, readStatus);
myLibrary.push(book);
addNewBookUI(book);
clearFormFields()
}
});
function addNewBookUI(book) {
if (book.readStatus === "yes") {
i = "checked";
} else {
i = "";
}
const main = document.querySelector(".main");
const bookCard = document.createElement("div");
bookCard.classList.add("book-card");
bookCard.innerHTML = `<div class="delete_button"><button class="delete btn"><i class="fa fa-trash">
</i></button></div><div class="title">${book.title}</div><div class="author">${book.author}
</div><div class="pages">${book.pages}</div><div class="read_status">Read: <input type="checkbox" id="yes" name="readstatus" value="yes" ${i}>
</div>`;
main.appendChild(bookCard);
}
// clear form fields after submit
function clearFormFields() {
const myForm = document.getElementById("myForm");
myForm.reset();
}
// Add event listener to all deleteButton
document.querySelector('.main').onclick=ev=>{
let el= ev.target.classList.contains('fa-trash')? ev.target.parentElement : ev.target.classList.contains('delete') ? ev.target : false;
if (el) {
let card=el.parentElement.parentElement;
myLibrary.splice( [...card.parentElement.children].indexOf(card) ,1);
console.log(myLibrary)
card.remove()
}
}
*, *::before, *::after {
box-sizing: border-box;
}
body {
font-family: 'Roboto', sans-serif;
margin: 0;
padding: 0;
}
header {
color: #ffffff;
display: flex;
font-size: 1.4rem;
justify-content: space-between;
align-items: center;
background-color:#155999;
border-bottom: #172f4f solid 10px;
}
.logo {
margin-left: 10px;
}
header button {
background-color: #183153;
border: none;
text-align: left;
font-size: 0.9rem;
border-radius: 5px;
color: #ffffff;
padding: 10px 50px;
margin-right: 10px;
cursor: pointer;
}
.plus-sign {
padding-right: 7px;
}
.main {
position: absolute;
width: 100%;
height: 100%;
background-color: #183153;
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
}
.book-card {
text-align: center;
font-weight: 1000;
display: flex;
flex-direction: column;
justify-content: space-evenly;
width: 250px;
height: 350px;
border-radius: 10px;
background-color: #155999;
margin-left: 20px;
margin-top:10px;
color: #ffffff;
border: #172f4f solid 8px;
line-height: 30px;
position: relative;
padding-left: 7px;
padding-right: 7px;
box-shadow: 10px 4px 22px -5px rgba(21,89,153,1);
}
.overlay {
height: 0%;
width: 100%;
position: fixed;
z-index: 1;
top: 0;
left: 0;
background-color: rgb(21,89,153);
background-color: rgba(21,89,153,0.7);
overflow-y: hidden;
transition: 0.5s;
}
.overlay-content {
position: relative;
top: 25%;
width: 100%;
text-align: center;
margin-top: 30px;
display: flex;
flex-direction: column;
font-size: 30px;
}
.overlay a {
padding: 8px;
text-decoration: none;
font-size: 36px;
color: #ffffff;
display: block;
transition: 0.3s;
}
.overlay a:hover, .overlay a:focus {
color: #c3c6d1;
}
.overlay .closebtn {
position: absolute;
top: 20px;
right: 45px;
font-size: 60px;
}
#media screen and (max-height: 450px) {
.overlay {overflow-y: auto;}
.overlay a {font-size: 20px}
.overlay .closebtn {
font-size: 40px;
top: 15px;
right: 35px;
}
}
.book-card div {
margin-top:15px;
}
/* Style buttons */
.btn {
background-color: #ffd43b; /* Blue background */
border: none; /* Remove borders */
color: red; /* White text */
padding: 12px 16px; /* Some padding */
font-size: 16px; /* Set a font size */
cursor: pointer; /* Mouse pointer on hover */
border-radius: 50%;
position:absolute;
top:-20px;
right:-15px;
}
/* Darker background on mouse-over */
.btn:hover {
background-color: #183153;
}
.delete_button {
top:0;
right:0;
}
form div {
margin-top: 15px;
font-family: 'Roboto', sans-serif;
color:white;
font-weight: bold;
font-size: 30px;
margin-bottom: 10px;
}
.radiobutton {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.form-flex {
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
}
.form-flex input {
width: 50%;
border-radius: 5px;
height: 30px;
margin-top: 5px
}
.form-flex input::placeholder {
text-align: center;
}
input[type=submit] {
background-color: #183153;
border: none;
text-align: left;
font-size: 0.9rem;
border-radius: 5px;
color: #ffffff;
padding: 10px 50px;
margin-top: -30px;
cursor: pointer;
}
.radiobutton p {
margin-top:10px;
margin-bottom: 30px;
}
.flexbuttons {
display: flex;
margin-top: -50px;
margin-bottom: -25px;
}
input[type="text"]
{
font-size:24px;
text-align: center;
}
JS:
//DOM
const bookForm = document.querySelector(".book-form");
<!-- The overlay -->
<div id="myNav" class="overlay">
<!-- Button to close the overlay navigation -->
×
<!-- Overlay content -->
<div class="overlay-content">
<form id="myForm" class="book-form">
<div class="form-flex">
<label for="title">Book name:</label>
<input type="text" id="title" name="title" placeholder="Book name...">
</div>
<div class="form-flex">
<label for="author">Book author:</label>
<input type="text" id="author" name="author" placeholder="Book author...">
</div >
<div class="form-flex">
<label for="pages">Pages:</label>
<input type="number" id="pages" placeholder="0" name="pages">
</div>
<div class="radiobutton">
<p>Have you read a book?</p>
<div class="flexbuttons">
<div><p><input type="radio" id="huey" name="yes_no" value="yes" checked>
<label for="huey">yes</label></p>
</div>
<div><p><input type="radio" id="no" name="yes_no" value="no">
<label for="dewey">no</label></p>
</div>
</div>
</div>
<div><input type="submit" value="Add Book"></div>
</form>
</div>
</form>
</div>
</div>
</div>
<header>
<div class="logo">
<h1><i class="fa fa-book" aria-hidden="true"></i>
</i>Library</h1>
</div>
<div class="button">
<button onclick="openNav()" class="add-book">
<i class="fa fa-plus plus-sign"></i>
Add book</button>
</div>
</header>
<div class="main">
</div>
<script src="./index.js" defer></script>
<script src="https://use.fontawesome.com/30a34909cc.js"></script>