#javascript #html #css
Вопрос:
У меня есть две кнопки, одна из них открывает форму, а другая-раскрывающийся список.
Я хочу, чтобы оба элемента закрывались при нажатии снаружи, раскрывающийся список в порядке, потому что я хочу, чтобы он закрывался всякий раз, когда пользователь нажимает вне кнопки открытия.
Но второе не работает, я хочу, чтобы оно закрылось, когда эта логическая формула верна:
- (кнопка открытия «fulfillSetButton» не нажата) ИЛИ (форма «Форма данных» не нажата)
Поэтому я сделал прослушиватель событий для всего HTML с формулой внутри оператора if:
html.addEventListener("click", function(e){
if(e.target !== (dateForm || fulfillSetButton)){
dateForm.classList.remove("active");
}
});
Но это не дает никаких идей о том, что не так?
// All the elements
const dropdownButton = document.querySelector("#dropdownToggle"),
fulfillSetButton = document.querySelector("#fulfillSetButton"),
dropdownMenu = document.querySelector('.dropdown-menu'),
html = document.querySelector("html"),
dateForm = document.querySelector(".completion-date");
// Preventing default action of submiting the form
function preventDefault(e) {
e = e || window.event;
if (e.preventDefault) {
e.preventDefault();
} else {
e.returnValue = false;
}
}
// Closing the dropdown *working*
dropdownButton.addEventListener("click", function () {
dropdownMenu.classList.toggle("show");
});
html.addEventListener("click", function(e){
if(e.target !== dropdownButton){
dropdownMenu.classList.remove("show");
}
});
// Opening the date form
fulfillSetButton.addEventListener("click", function() {
dateForm.classList.add("active");
});
// Closing the date form by submiting
dateForm.lastElementChild.addEventListener(
"click", function () {
preventDefault();
dateForm.classList.remove("active");
}
);
// Closing the date form by clicking outside *not working*
html.addEventListener("click", function(e){
if(e.target !== (dateForm || fulfillSetButton)){
dateForm.classList.remove("active");
}
});
:root {
--trans-left:#84fab0;
--trans-right:#8fd3f4;
--background: #fff;
--color: #222;
}
.button-list {
align-self: center;
}
.completion-date {
display: block;
z-index: 10;
position: fixed;
top: -100%;
left: calc(50% - 121px);
min-width: max-content;
padding: 1rem;
border-radius: 0.5rem;
background: var(--background);
text-align: center;
box-shadow: 0 0 18px -6px var(--color);
transition: 0.3s;
}
.completion-date.active {
top: calc(50% - 264px);
}
.completion-date div {
margin: 0.5rem;
}
.completion-date input,
.completion-date button {
margin: auto 0;
}
.completion-date input {
width: 2rem;
text-align: center;
}
.completion-date div > button {
width: 1.5rem;
margin: auto 3px;
box-shadow: none;
font-weight: bold;
}
section {
width: 100vw;
}
input {
box-shadow: inset 0 3px 7px -3px black;
border: none;
line-height: 2rem;
}
button {
padding: 9px;
border: none;
box-shadow: 7px 7px 9px -10px var(--color), inset 0 0 15px -12px var(--color);
border-radius: 6px;
}
.entry {
display: flex;
align-items: flex-end;
height: 30vh;
background-image: linear-gradient(120deg, var(--trans-left) 0%, var(--trans-right) 100%);
}
@media screen and (max-height: 660px) {
.entry {
height: 38vh;
}
}
form {
display: flex;
flex-wrap: wrap;
max-width: 36rem;
justify-content: center;
margin: 0 auto;
}
form > * {
max-height: 100%;
}
form > div {
display: flex;
}
form > input {
margin: 0.5rem;
box-shadow: inset 0px 3px 9px -4px #000000;
border-radius: 6px;
}
.second-item {
flex-wrap: wrap;
justify-content: center;
}
.second-item > * {
margin: 0.5rem;
box-shadow: 4px 4px 8px -6px #000000, -4px -4px 10px -3px #FFFFFF;
border-radius: 6px;
}
.dropdown-wrap > *:first-child {
box-shadow: 4px 4px 8px -6px #000000, -4px -4px 10px -3px #FFFFFF;
border-radius: 6px;
}
.dropdown-wrap > *:first-child {
box-shadow: 4px 4px 8px -6px #000000, -4px -4px 10px -3px #FFFFFF;
border-radius: 6px;
}
.btn.dropdown {
transition: 0.3s ease;
}
.btn.dropdown.low {
background-color: #84fab0;
}
.btn.dropdown.high {
background-color: #ffa0a0;
}
.dropdown-menu {
z-index: 2;
position: absolute;
margin-top: 9px;
list-style: none;
padding-inline-start: 0;
margin-block-end: 0;
background: #fff;
box-shadow: 1px 1px 20px -9px black;
border-radius: 9px;
pointer-events: none;
opacity: 0;
transition: 0.3s ease;
}
.dropdown-menu > li {
padding: 0.4rem;
cursor: pointer;
}
.dropdown-menu.show {
pointer-events: all;
opacity: 1;
}
<section class="entry">
<form autocomplete="off">
<input type="text" id="taskText">
<div class="second-item">
<button type="button" id="fulfillSetButton">Date form</button>
<div class="dropdown-wrap">
<button class="btn dropdown" type="button" id="dropdownToggle">Dropdown button</button>
<ul class="dropdown-menu" id="taskPriority" style="background: linear-gradient(0deg, rgba(132,250,176,1) 0%, rgba(132,250,176,1) 33%, rgba(255,255,255,1) 33%, rgba(255,255,255,1) 50%, rgba(255,255,255,1) 66%, rgba(255,160,160,1) 66%, rgba(255,160,160,1) 100%); color: #000">
<li>Vysoká</li>
<li>Střední</li>
<li>Nízká</li>
</ul>
</div>
<button type="submit">submit</button>
</div>
</form>
<form class="completion-date">
<h2>Dokončit za:</h2>
<div>
<button onclick="increaseValue(months)"> </button>
<input id="months" type="number" value="0" min="0" max="12">
<button onclick="decreaseValue(months)">-</button>
<p>měsíců</p>
</div>
<div>
<button onclick="increaseValue(weeks)"> </button>
<input id="weeks" type="number" value="0" min="0" max="5">
<button onclick="decreaseValue(weeks)">-</button>
<p>týdnů</p>
</div>
<div>
<button onclick="increaseValue(days)"> </button>
<input id="days" type="number" value="0" min="0" max="31">
<button onclick="decreaseValue(days)">-</button>
<p>dní</p>
</div>
<div>
<button onclick="increaseValue(hours)"> </button>
<input id="hours" type="number" value="0" min="0" max="23">
<button onclick="decreaseValue(hours)">-</button>
<p>hodin</p>
</div>
<div>
<button onclick="increaseValue(minutes)"> </button>
<input id="minutes" type="number" value="0" min="0" max="59">
<button onclick="decreaseValue(minutes)">-</button>
<p>minut</p>
</div>
<button>Nastavit</button>
</form>
</section>
Ответ №1:
Попробуй это:
window.addEventListener('click', function(e){
if( div.contains(e.target)){
//click inside of element
} else{
//click outside of element
}
});
Я исправил некоторые CSS и HTML.
// All the elements
const dropdownButton = document.querySelector("#dropdownToggle"),
fulfillSetButton = document.querySelector("#fulfillSetButton"),
dropdownMenu = document.querySelector('.dropdown-menu'),
html = document.querySelector("body"),
dateForm = document.querySelector("#completion-date-id");
// Preventing default action of submiting the form
function preventDefault(e) {
e = e || window.event;
if (e.preventDefault) {
e.preventDefault();
} else {
e.returnValue = false;
}
}
// Closing the dropdown *working*
dropdownButton.addEventListener("click", function () {
dropdownMenu.classList.toggle("show");
});
//new way works every spot on page
window.addEventListener('click', function(e){
if( dropdownButton.contains(e.target)){
} else{
dropdownMenu.classList.remove("show");
}
});
//Old way
//html.addEventListener("click", function(e){
// if(e.target !== dropdownButton){
// dropdownMenu.classList.remove("show");
// }
//});
// Opening the date form
fulfillSetButton.addEventListener("click", function() {
dateForm.classList.add("active");
});
// Closing the date form by submiting
dateForm.lastElementChild.addEventListener(
"click", function () {
preventDefault();
dateForm.classList.remove("active");
}
);
// Closing the date form by clicking outside *working now*
window.addEventListener('click', function(e){
if( dateForm.contains(e.target) || fulfillSetButton.contains(e.target)){
} else{
dateForm.classList.remove("active");
}
});
// Closing the date form by clicking outside *not working*
//html.addEventListener("click", function(e){
// if(e.target !== (dateForm || fulfillSetButton)){
// dateForm.classList.remove("active");
// }
//});
:root {
--trans-left:#84fab0;
--trans-right:#8fd3f4;
--background: #fff;
--color: #222;
}
.button-list {
align-self: center;
}
.completion-date {
z-index: 10;
position: fixed;
top: -100%;
left: calc(50% - 121px);
min-width: max-content;
padding: 1rem;
border-radius: 0.5rem;
background: var(--background);
text-align: center;
box-shadow: 0 0 18px -6px var(--color);
transition: 0.3s;
}
.completion-date.active {
top: calc(50% - 264px);
}
.completion-date div {
margin: 0.5rem;
}
.completion-date input,
.completion-date button {
margin: auto 0;
}
.completion-date input {
width: 2rem;
text-align: center;
}
.completion-date div > button {
width: 1.5rem;
margin: auto 3px;
box-shadow: none;
font-weight: bold;
}
section {
width: 100vw;
}
input {
box-shadow: inset 0 3px 7px -3px black;
border: none;
line-height: 2rem;
}
button {
padding: 9px;
border: none;
box-shadow: 7px 7px 9px -10px var(--color), inset 0 0 15px -12px var(--color);
border-radius: 6px;
}
.entry {
display: flex;
align-items: flex-end;
height: 30vh;
background-image: linear-gradient(120deg, var(--trans-left) 0%, var(--trans-right) 100%);
}
@media screen and (max-height: 660px) {
.entry {
height: 38vh;
}
}
form {
display: flex;
flex-wrap: wrap;
max-width: 36rem;
justify-content: center;
margin: 0 auto;
}
form > * {
max-height: 100%;
}
form > div {
display: flex;
}
form > input {
margin: 0.5rem;
box-shadow: inset 0px 3px 9px -4px #000000;
border-radius: 6px;
}
.second-item {
flex-wrap: wrap;
justify-content: center;
}
.second-item > * {
margin: 0.5rem;
box-shadow: 4px 4px 8px -6px #000000, -4px -4px 10px -3px #FFFFFF;
border-radius: 6px;
}
.dropdown-wrap > *:first-child {
box-shadow: 4px 4px 8px -6px #000000, -4px -4px 10px -3px #FFFFFF;
border-radius: 6px;
}
.dropdown-wrap > *:first-child {
box-shadow: 4px 4px 8px -6px #000000, -4px -4px 10px -3px #FFFFFF;
border-radius: 6px;
}
.btn.dropdown {
transition: 0.3s ease;
}
.btn.dropdown.low {
background-color: #84fab0;
}
.btn.dropdown.high {
background-color: #ffa0a0;
}
.dropdown-menu {
z-index: 2;
position: absolute;
margin-top: 9px;
list-style: none;
padding-inline-start: 0;
margin-block-end: 0;
background: #fff;
box-shadow: 1px 1px 20px -9px black;
border-radius: 9px;
pointer-events: none;
opacity: 0;
transition: 0.3s ease;
}
.dropdown-menu > li {
padding: 0.4rem;
cursor: pointer;
}
.dropdown-menu.show {
pointer-events: all;
opacity: 1;
}
.active{
display: block;
}
<body>
<section class="entry">
<form autocomplete="off">
<input type="text" id="taskText">
<div class="second-item">
<button type="button" id="fulfillSetButton">Date form</button>
<div class="dropdown-wrap">
<button class="btn dropdown" type="button" id="dropdownToggle">Dropdown button</button>
<ul class="dropdown-menu" id="taskPriority" style="background: linear-gradient(0deg, rgba(132,250,176,1) 0%, rgba(132,250,176,1) 33%, rgba(255,255,255,1) 33%, rgba(255,255,255,1) 50%, rgba(255,255,255,1) 66%, rgba(255,160,160,1) 66%, rgba(255,160,160,1) 100%); color: #000">
<li>Vysoká</li>
<li>Střední</li>
<li>Nízká</li>
</ul>
</div>
<button type="submit">submit</button>
</div>
</form>
<form id="completion-date-id" class="completion-date active">
<h2>Dokončit za:</h2>
<div>
<button onclick="increaseValue(months)"> </button>
<input id="months" type="number" value="0" min="0" max="12">
<button onclick="decreaseValue(months)">-</button>
<p>měsíců</p>
</div>
<div>
<button onclick="increaseValue(weeks)"> </button>
<input id="weeks" type="number" value="0" min="0" max="5">
<button onclick="decreaseValue(weeks)">-</button>
<p>týdnů</p>
</div>
<div>
<button onclick="increaseValue(days)"> </button>
<input id="days" type="number" value="0" min="0" max="31">
<button onclick="decreaseValue(days)">-</button>
<p>dní</p>
</div>
<div>
<button onclick="increaseValue(hours)"> </button>
<input id="hours" type="number" value="0" min="0" max="23">
<button onclick="decreaseValue(hours)">-</button>
<p>hodin</p>
</div>
<div>
<button onclick="increaseValue(minutes)"> </button>
<input id="minutes" type="number" value="0" min="0" max="59">
<button onclick="decreaseValue(minutes)">-</button>
<p>minut</p>
</div>
<button>Nastavit</button>
</form>
</section>
</body>
Комментарии:
1. Я также исправил некоторые ошибки JavaScript в некоторых частях.
2. Это сработало для вас?
3. Это так, спасибо, но не могли бы вы объяснить в ответе, почему эта функция работала, а моя-нет? Это действительно помогло бы мне понять это лучше, я не могу найти это в другом месте.
4. Это было связано с тем, что выбранный вами html-тег находился не на том же уровне, что и всплывающий элемент, и, насколько я знаю, использование опции окна-лучший способ сделать это. Пожалуйста, отметьте это как правильный ответ, если он решил вашу проблему. 🙂