Home > Mobile >  stuck on a close modal problem with javascript
stuck on a close modal problem with javascript

Time:11-06

here is the code of my issue: https://codepen.io/isaflame/pen/yLEazmM

html: `

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>Reservation</title>
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <link rel="stylesheet" href="modal.css" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
    <link
      href="https://fonts.googleapis.com/css?family=DM Sans"
      rel="stylesheet"
    />
  </head>
  <body>
    <div  id="myTopnav">
      <div >
      <img alt="logo" src="Logo.png" width="auto" height="auto" />
    </div>
    <div >
      
      <a href="#" ><span>Accueil</span></a>
      <a href="#"><span>Détails de l'évènement</span></a>
      <a href="#"><span>À propos</span></a>
      <a href="#"><span>Contact</span></a>
      <a href="#"><span>Évènements passés</span></a>
      <a href="javascript:void(0);"  onclick="editNav()">
        <i ></i>
      </a>
    </div>
    </div>
  </div>
    <main>
      <div  >
        <div >
          <h1 >
            Marathon national<br>
            de jeux vidéos
          </h1>
          <p >
            Vous aimez jouer ? Notre prochain évènement gaming est ouvert
            aux réservations... Places limitées !
          </p>
          <button >
            je m'inscris
          </button>
        </div>
        <div >
          <img src="./bg_img.jpg" alt="img" />
        </div>
        <button >
          je m'inscris
        </button>
      </div>

      <div ><!--ouverture et fermeture modale en js-->
        <div  >
          <span  onclick = closeModal()></span>
          <div >
            <!--ajout id tag "reserve"pour le formulaire-->
            <form
              name="reserve"
              id="reserve"
              action="index.html"
              method="get">
              <div
                >
                <label>Prénom</label><br>
                <input
                  
                  type="text" 
                  id="first"
                  name="first"
                  minlength="2"
                >
              </div>
              <div
                >
                <label>Nom</label><br>
                <input
                  
                  type="text" 
                  id="last"
                  name="last"
                  
                /><br>
                
              </div>
              <div
                >
                <label>E-mail</label><br>
                <input
                  
                  type="email" 
                  id="email"
                  name="email"
                /><br>
               
              </div>
              <!--le navigateur comprend la date et affiche un calendrier-->
              <div
                >
                <label>Date de naissance</label><br>
                <input
                  
                  type="date" 
                  id="birthdate"
                  name="birthdate"
                /><br>
           
              </div>
              <div
                >
                <label>À combien de tournois GameOn avez-vous déjà participé ?</label><br>
                <input type="number"   id="quantity" name="quantity" min="0" max="99">
                
              </div>
              <p >A quel tournoi souhaitez-vous participer cette année ?</p>
              <div
                >
                <input
                  
                  type="radio" 
                  id="location1"
                  name="location"
                  value="New York"
                />
                <label  for="location1">
                  <span ></span>
                  New York</label
                >
                <input
                  
                  type="radio"
                  id="location2"
                  name="location"
                  value="San Francisco"
                />
                <label  for="location2">
                  <span ></span>
                  San Francisco</label
                >
                <input
                  
                  type="radio"
                  id="location3"
                  name="location"
                  value="Seattle"
                />
                <label  for="location3">
                  <span ></span>
                  Seattle</label
                >
                <input
                  
                  type="radio"
                  id="location4"
                  name="location"
                  value="Chicago"
                />
                <label  for="location4">
                  <span ></span>
                  Chicago</label
                >
                <input
                  
                  type="radio"
                  id="location5"
                  name="location"
                  value="Boston"
                />
                <label  for="location5">
                  <span ></span>
                  Boston</label
                >
                <input
                  
                  type="radio"
                  id="location6"
                  name="location"
                  value="Portland"
                />
                <label  for="location6">
                  <span ></span>
                  Portland</label
                >
                <br><small></small>
              </div>

              <div
                >
                <input
                  
                  type="checkbox"
                  id="checkbox1"
                  checked
                />
                <label  for="checkbox1" required>
                  <span ></span>
                  J'ai lu et accepté les conditions d'utilisation.
                </label>
                <br>
                <small></small>
                <input  type="checkbox" id="checkbox2" />
                <label  for="checkbox2">
                  <span ></span>
                  Je souhaite être prévenu des prochains évènements.
                </label>
                <br>
              </div>
              <input
                
                type="submit"
                
                value="C'est parti"
              />
            </form>
          </div>
        </div><!--fin content -->
      </div>
    </main>
    <footer>
      <p >
        Copyright 2014 - 2022, GameOn Inc.
      </p>
    </footer>
    <script  src= "modal.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/dayjs@1/dayjs.min.js"></script>
  </body>
</html>

css:

:root {
  --font-default: "DM Sans", Arial, Helvetica, sans-serif;
  --font-slab: var(--font-default);
  --modal-duration: 0.8s;
}
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}
/* Landing Page */

body {
  margin: 0;
  display: flex;
  flex-direction: column;
  background-image: url("background.png");
  font-family: var(--font-default);
  font-size: 18px;
  max-width: 1300px;
  margin: 0 auto;
}

p {
  margin-bottom: 0;
  padding: 0.5vw;
}

img {
  padding-right: 1rem;
}

.topnav {
  overflow: hidden;
  margin: 3.5%;
}
.header-logo {
    float: left;
}
.main-navbar {
    float: right;
}
.topnav a {
  float: left;
  display: block;
  color: #000000;
  text-align: center;
  padding: 12px 12px;
  margin: 5px;
  text-decoration: none;
  font-size: 20px;
  font-family: Roboto, sans-serif;
}

.topnav a:hover {
  background-color: #ff0000;
  color: #ffffff;
  border-radius: 15px;
}

.topnav a.active {
  background-color: #ff0000;
  color: #ffffff;
  border-radius: 15px;
}

.topnav .icon {
  display: none;
}

@media screen and (max-width: 768px) {
  .topnav a {display: none;}
  .topnav a.icon {
    float: right;
    display: block;
  }
}

@media screen and (max-width: 768px) {
  .topnav.responsive {position: relative;}
  .topnav.responsive .icon {
    position: absolute;
    right: 0;
    top: 0;
  }
  .topnav.responsive a {
    float: none;
    display: block;
    text-align: left;
  }
}



 @media screen and (max-width: 540px) {
  .topnav a {display: none;}
  .topnav a.icon {
    float: right;
    display: block;
    margin-top: -15px;
  }
} 

main {
  font-size: 130%;
  font-weight: bolder;
  color: black;
  padding-top: 0.5vw;
  padding-left: 2vw;
  padding-right: 2vw;
  margin: 1px 20px 15px;
  border-radius: 2rem;
  text-align: justify;


}

.modal-btn {
  font-size: 145%;
  background: #fe142f;
  display: flex;
  margin: auto;
  padding: 2em;
  color: #fff;
  padding: 0.75rem 2.5rem;
  border-radius: 1rem;
  cursor: pointer;
}

.modal-btn:hover {
  background: #3876ac;
}

.footer {
  margin: 20px;
  padding: 10px;
  font-family: var(--font-slab);
}

/* Modal form */

.button {
  background: #fe142f;
  margin-top: 0.5em;
  padding: 1em;
  color: #fff;
  border-radius: 15px;
  cursor: pointer;
  font-size: 16px;
}

.button:hover {
  background: #3876ac;
}

.smFont {
  font-size: 16px;
}

.bground {
  display: none;
  position: fixed;
  z-index: 1;
  left: 0;
  top: 0;
  height: 100%;
  width: 100%;
  overflow: auto;
  background-color: rgba(26, 39, 156, 0.4);
}

.content {
  margin: 5% auto;
  width: 100%;
  max-width: 500px;
  animation-name: modalopen;
  animation-duration: var(--modal-duration);
  background: #232323;
  border-radius: 10px;
  overflow: hidden;
  position: relative;
  color: #fff;
  padding-top: 10px;
}

.modal-body {
  padding: 15px 8%;
  margin: 15px auto;
}

label {
  font-family: var(--font-default);
  font-size: 17px;
  font-weight: normal;
  display: inline-block;
  margin-bottom: 11px;
}
input {
  padding: 8px;
  border: 0.8px solid #ccc;
  outline: none;
}
.text-control {
  margin: 0;
  padding: 8px;
  width: 100%;
  border-radius: 8px;
  font-size: 20px;
  height: 48px;
}
.formData[data-error]::after {
  content: attr(data-error);
  font-size: 0.4em;
  color: #e54858;
  display: block;
  margin-top: 7px;
  margin-bottom: 7px;
  text-align: right;
  line-height: 0.3;
  opacity: 0;
  transition: 0.3s;
}
.formData[data-error-visible="true"]::after {
  opacity: 1;
}
.formData[data-error-visible="true"] .text-control {
  border: 2px solid #e54858;
}


/* 
input[data-error]::after {
    content: attr(data-error);
    font-size: 0.4em;
    color: red;
} */
.checkbox-label,
.checkbox2-label {
  position: relative;
  margin-left: 36px;
  font-size: 12px;
  font-weight: normal;
}
.checkbox-label .checkbox-icon,
.checkbox2-label .checkbox-icon {
  display: block;
  width: 20px;
  height: 20px;
  border: 2px solid #279e7a;
  border-radius: 50%;
  text-indent: 29px;
  white-space: nowrap;
  position: absolute;
  left: -30px;
  top: -1px;
  transition: 0.3s;
}
.checkbox-label .checkbox-icon::after,
.checkbox2-label .checkbox-icon::after {
  content: "";
  width: 13px;
  height: 13px;
  background-color: #279e7a;
  border-radius: 50%;
  text-indent: 29px;
  white-space: nowrap;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  transition: 0.3s;
  opacity: 0;
}
.checkbox-input {
  display: none;
}
.checkbox-input:checked   .checkbox-label .checkbox-icon::after,
.checkbox-input:checked   .checkbox2-label .checkbox-icon::after {
  opacity: 1;
}
.checkbox-input:checked   .checkbox2-label .checkbox-icon {
  background: #279e7a;
}
.checkbox2-label .checkbox-icon {
  border-radius: 4px;
  border: 0;
  background: #c4c4c4;
}
.checkbox2-label .checkbox-icon::after {
  width: 7px;
  height: 4px;
  border-radius: 2px;
  background: transparent;
  border: 2px solid transparent;
  border-bottom-color: #fff;
  border-left-color: #fff;
  transform: rotate(-55deg);
  left: 21%;
  top: 19%;
}
.close {
  position: absolute;
  right: 15px;
  top: 15px;
  width: 32px;
  height: 32px;
  opacity: 1;
  cursor: pointer;
  transform: scale(0.7);
}
.close:before,
.close:after {
  position: absolute;
  left: 15px;
  content: " ";
  height: 33px;
  width: 3px;
  background-color: #fff;
}
.close:before {
  transform: rotate(45deg);
}
.close:after {
  transform: rotate(-45deg);
}
.btn-submit,
.btn-signup {
  background: #fe142f;
  display: block;
  margin: 0 auto;
  border-radius: 7px;
  font-size: 1rem;
  padding: 12px 82px;
  color: #fff;
  cursor: pointer;
  border: 0;
}
/* custom select styles */
.custom-select {
  position: relative;
  font-family: Arial;
  font-size: 1.1rem;
  font-weight: normal;
}

.custom-select select {
  display: none;
}
.select-selected {
  background-color: #fff;
}

/* Style the arrow inside the select element: */
.select-selected:after {
  position: absolute;
  content: "";
  top: 10px;
  right: 13px;
  width: 11px;
  height: 11px;
  border: 3px solid transparent;
  border-bottom-color: #f00;
  border-left-color: #f00;
  transform: rotate(-48deg);
  border-radius: 5px 0 5px 0;
}

/* Point the arrow upwards when the select box is open (active): */
.select-selected.select-arrow-active:after {
  transform: rotate(135deg);
  top: 13px;
}

.select-items div,
.select-selected {
  color: #000;
  padding: 11px 16px;
  border: 1px solid transparent;
  border-color: transparent transparent rgba(0, 0, 0, 0.1) transparent;
  cursor: pointer;
  border-radius: 8px;
  height: 48px;
}

/* Style items (options): */
.select-items {
  position: absolute;
  background-color: #fff;
  top: 89%;
  left: 0;
  right: 0;
  z-index: 99;
}

/* Hide the items when the select box is closed: */
.select-hide {
  display: none;
}

.select-items div:hover,
.same-as-selected {
  background-color: rgba(0, 0, 0, 0.1);
}
/* custom select end */
.text-label {
  font-weight: normal;
  font-size: 16px;
}
.hero-section {
  min-height: 93vh;
  border-radius: 10px;
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  overflow: hidden;
  box-shadow: 0 2px 7px 2px rgba(0, 0, 0, 0.2);
  margin-bottom: 10px;
}
.hero-content {
  padding: 51px 67px;
  grid-column: span 4;
  background: #232323;
  color: #fff;
  position: relative;
  text-align: left;
  min-width: 424px;
}
.hero-content::after {
  content: "";
  width: 100%;
  height: 100%;
  background: #232323;
  position: absolute;
  right: -80px;
  top: 0;
}
.hero-content > * {
  position: relative;
  z-index: 1;
}
.hero-headline {
  font-size: 6rem;
  font-weight: normal;
  white-space: nowrap;
}
.hero-text {
  width: 146%;
  font-weight: normal;
  margin-top: 57px;
  padding: 0;
}
.btn-signup {
  outline: none;
  text-transform: capitalize;
  font-size: 1.3rem;
  padding: 15px 23px;
  margin: 0;
  margin-top: 59px;
}
.hero-img {
  grid-column: span 8;
}
.hero-img img {
  width: 100%;
  height: 100%;
  display: block;
  padding: 0;
}
.copyrights {
  color: #fe142f;
  padding: 0;
  font-size: 1rem;
  margin: 60px 0 30px;
  font-weight: bolder;
}
.hero-section > .btn-signup {
  display: none;
}
footer {
  padding-left: 2vw;
  padding-right: 2vw;
  margin: 0 20px;
}
@media screen and (max-width: 800px) {
  .hero-section {
    display: block;
    box-shadow: unset;
  }
  .hero-content {
    background: #fff;
    color: #000;
    padding: 20px;
  }
  .hero-content::after {
    content: unset;
  }
  .hero-content .btn-signup {
    display: none;
  }
  .hero-headline {
    font-size: 4.5rem;
    white-space: normal;
  }
  .hero-text {
    width: unset;
    font-size: 1.5rem;
  }
  .hero-img img {
    border-radius: 10px;
    margin-top: 40px;
  }
  .hero-section > .btn-signup {
    display: block;
    margin: 32px auto 10px;
    padding: 12px 35px;
  }
  .copyrights {
    margin-top: 50px;
    text-align: center;
  }
}

@keyframes modalopen {
  from {
    opacity: 0;
    transform: translateY(-150px);
  }
  to {
    opacity: 1;
  }
}


javascript:

function editNav() {
  var x = document.getElementById("myTopnav");
  if (x.className === "topnav") {
    x.className  = " responsive";
  } else {
    x.className = "topnav";
  }
}

// DOM Elements
const modalbg = document.querySelector(".bground");
const modalBtn = document.querySelectorAll(".modal-btn");
const formData = document.querySelectorAll(".formData");
const modalBody = document.querySelector(".modal-body");

const form = document.getElementById("reserve");

const firstName = document.getElementById("first");
const lastName = document.getElementById("last");
const email = document.getElementById("email");
const birthdate = document.getElementById("birthdate");
const quantity = document.getElementById("quantity"); /* nombre de tournois*/
const city = document.getElementsByName("location");

// launch modal form
function launchModal() {
  modalbg.style.display = "block";
}

// launch modal event
modalBtn.forEach((btn) => btn.addEventListener("click", launchModal));

// close modal form and reset datas in the form
function closeModal() {
  modalbg.style.display = "none";
  form.reset();
}
//close modal event
//modalBtn.forEach((btn) => btn.addEventListener("click", closeModal));

/*form.addEventListener(
  "submit",
  validateForm
); /* when submit form => function validateform start*/
// fonction validation du formulaire.
/*si validatefrom n'est pas retournée, 
alors fonction greetings est lancée*/
function validateForm(event) {
  event.preventDefault();
  event.stopPropagation();
  if (
    !validateFirstName() &&
    !validateLastName() &&
    !validateEmail() &&
    !validateRadio() &&
    !validateTournament() &&
    !validateDate()
  )
    return;
  /* removeEventListener("submit", greetings())*/
}
/*
formIsValid();
function formIsValid() {
  if (!validateForm()) {
     greetings();
  }
}
*/
//!!!! reste le rechargement de la modale avec message de remerciement
function greetings() {
  form.innerHTML = /*html*/ `<div class ="content"> 
  Merci pour votre <br>inscription</div>
  <button  onclick= "closeModal()"> 
  Fermer </button>`;
}

/**
 * fonction validation du prénom et message erreur OK!!
 *
 * @return  {Boolean}  true si valide sinon false
 */
function validateFirstName() {
  const regexFirstName = /^[A-Z a-z]{2,25}$/; /*min 2 caracteres*/
  const parent = document.getElementById("first").parentNode;
  if (firstName.value == "" || !regexFirstName.test(firstName.value)) {
    firstName.focus();
    parent.setAttribute("data-error", "Veuillez entrez un prénom valide");
    parent.setAttribute("data-error-visible", "true");
    return false;
  }
  parent.setAttribute("data-error-visible", "false");
  return true;
}
//fonction validation du nom et message erreur OK!!!
function validateLastName() {
  const regexLastName = /^[A-Z a-z]{2,25}$/; /*min 2 caracteres*/
  const parent = document.getElementById("last").parentNode;
  console.log(parent, "parent1");
  if (lastName.value == "" || !regexLastName.test(lastName.value)) {
    lastName.focus();
    parent.setAttribute("data-error", "Veuillez entrez un nom valide");
    parent.setAttribute("data-error-visible", "true");
    return false;
  }
  parent.setAttribute("data-error-visible", "false");
  return true;
}

//fonction validation du courriel et message erreur OK!!!
function validateEmail() {
  const regexEmail =
    /^[a-zA-Z][a-zA-Z0-9\-\_\.] @[a-zA-Z0-9]{2,}\.[a-zA-Z0-9]{2,}$/;
  const parent = document.getElementById("email").parentNode;
  console.log(parent, "parent2");
  console.log(email.value);
  if (email.value == "" || !regexEmail.test(email.value)) {
    email.focus();
    parent.setAttribute("data-error", "Veuillez entrez un courriel valide");
    parent.setAttribute("data-error-visible", "true");
    return false;
  }
  parent.setAttribute("data-error-visible", "false");
  return true;
}

function setDateLimits() {
  const dateToday = new Date();
  // console.log (dateToday);
  const day = dateToday.getDate(); /* jour du mois en cours */
  // console.log (day);
  const month =
    dateToday.getMonth()  
    1; /* mois de l'année en cours" 1" car renvoie "0" pour janvier*/
  // console.log (month);
  const year = dateToday.getFullYear(); /* année en cours*/
  // console.log (year);
  let date = new Date(`${year - 18}-${month}-${day}`)
    .toISOString()
    .split("T")[0];
  console.log(birthdate, date);
  birthdate.setAttribute("max", date);
  date = new Date(`${year - 100}-${month}-${day}`).toISOString().split("T")[0];
  console.log(birthdate, date);
  birthdate.setAttribute("min", date);
}
function validateDate() {
  const parent = birthdate.parentNode;
  let isValid = true;
  const selectedDate = new Date(birthdate.value);
  const dateToday = new Date();
  const day = dateToday.getDate(); /* jour du mois en cours */
  const month =
    dateToday.getMonth()  
    1; /* mois de l'année en cours" 1" car renvoie "0" pour janvier*/
  const year = dateToday.getFullYear(); /* année en cours*/
  let date = new Date(`${year - 18}-${month}-${day}`);
  if (selectedDate > date) {
    isValid = false;
  } else {
    date = new Date(`${year - 100}-${month}-${day}`);
    if (selectedDate < date) {
      isValid = false;
    }
  }
  if (!isValid) {
    birthdate.focus();
    parent.setAttribute("data-error", "Veuillez entrez une date valide");
    parent.setAttribute("data-error-visible", "true");
    return false;
  }
  parent.setAttribute("data-error-visible", "false");
  return true;
}

console.log(quantity.value);
//validation du champ nombre de tournois OK!!!
function validateTournament() {
  const quantityTournament = document.querySelector("input[name='quantity']");
  const parent = document
    .querySelector(`input[name='quantity']`)
    .closest(`.formData`);
  console.log(parent);
  if (quantityTournament.value == "" || null) {
    quantity.focus();
    parent.setAttribute("data-error", "Veuillez entrez un nombre");
    parent.setAttribute("data-error-visible", "true");
    return false;
  }
  parent.setAttribute("data-error-visible", "false");
  return true;
}

// fonction validation de la ville (bouton radio) OK!!
function validateRadio() {
  const checkradio = document.querySelector("input[name='location']:checked");
  const parent = document
    .querySelector(`input[name='location']`)
    .closest(`.formData`);
  console.log(parent, "parent");
  if (checkradio != null) {
    //Teste si une ville est cochée
    parent.setAttribute("data-error-visible", "false");
    return true;
  }
  parent.setAttribute("data-error", "Veuillez choisir une ville");
  parent.setAttribute("data-error-visible", "true");
  return false;
}

setDateLimits();

` i want to close the modal if the user click on the cross (succeed), outside of the modal window (i do not find a solution). As well, i have this problem: i have created a function called "grettings" in order that when the form in the modal is filled, the user click on the button, then greetings function is launched and insert a greeting message in the modal... i do not find any solution for that.

i have tried to add add a condition (lines 63 to 66 in modal.js file) like "when the form is filled and validate, then, launch the greetings function.. but it daes not work. Anyone can help? thank you in advance;

CodePudding user response:

An idea would be to add a click eventListener to your modal.

Then you can check if the clicked element is inside the modal content or not. If not, then you can close the modal.

I think something like this would work:

modalbg.addEventListener('click', (event) => {
   const clickInsideModalBody = event.target.closest('.modal-body');
   if (clickInsideModalBody) {
      // Close your modal
   }
})

(Maybe you should add this event listener only when the modal opens, and then remove it when the modal closes)

You can read more about the .closest here: https://developer.mozilla.org/en-US/docs/Web/API/Element/closest

CodePudding user response:

You can add an event listener on modalbg and check if you actually click on the background element to close the modal.

modalbg.addEventListener("click",(evt)=>{ 
  if (evt.srcElement===modalbg){
    closeModal()
  }
})
  • Related