Wywołanie funkcji js. Różne plik

0

witam,

Mam kilka plików HTML oraz podpięte pod nie pliki js.
Cała aplikacja jest spięta webpackie.
Jeden plik js (content.js) odpowiada za wyswietlenie treści, a także za wyświetlenie przycisku.
Drugi plik js (index.js) odpowiada za wyswietlenie treści (pop-up) z innego pliku HTML.

zasada działania:

Przycisk powinien wywołać funkcję (funkcja ta pobiera klase btn i za pomocą eventu wywołuje funkcje, która z kolei wywołuje funkcję zaimportowaną z pierwszego pliku (index.js), która uruchomi pop-up. Niestety, po przyciśnięciu przycisku wywoływany jest błąd Uncaught TypeError: Cannot read properties of null (reading 'classList'). Gdy wywołuję tą funkcję w index.js uruchamia się bez problemu.

kod z index.js

kod pobiera klasy z pliku index.html

function ff() {
  if (document.readyState === "loading") {
    document.addEventListener("DOMContentLoaded");
  } else {
    const showPopup = document.querySelector(".main-container__pop-up");
    showPopup.classList.toggle("main-container__pop-up--show-modal");
  }
}

export { ff };

kod z content.js

import { ff } from "./index.js";

const button = document.querySelector(".container__btn");

button.addEventListener('click', showModal)

async function showModal(){

  ff()

}

Pytanie, jak zrobić by kod odpalany z content.js właściwie pobrał querySelector.

1

Wrzuć wszystkie pliki łącznie z index.html. Użyj też formatowania kodu.
screenshot-20220610120056.png

0
<!DOCTYPE html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1, shrink-to-fit=no"
    />
    <meta name="main-page" content="web content" />
    <link rel="stylesheet" href="./src/scss/main.css" />
    <link rel="preconnect" href="https://fonts.googleapis.com" />
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
    <link
      href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,700;1,100&display=swap"
      rel="stylesheet"
    />

  </head>
  <body>
    <div class="main-container">
      <div class="main-container__content">
        <iframe
          title="main content"
          src="./content.html"
          frameborder="0"
          width="100%"
          height="1000"
          scrolling="no"
        ></iframe>
      </div>

      <div class="main-container__pop-up">
        <iframe
          title="pop-up module"
          src="./popUp.html"
          frameborder="0"
          width="100%"
          height="220"
          allowtransparency="yes"
          scrolling="no"
        ></iframe>
      </div>
    </div>
    <script type="module" src="./src/js/index.js" async defer></script>

  </body>
</html>

klasa .main-container__pop-up ma display: none. Z tym jest kłopot.

0
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>Content</title>
        <meta name="content" content="web content">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="./src/scss/main.css" />

    </head>
    <body>
        <div class="container">
            <div class="container__side-left">
              <img
                src="./images/sean-o-KMn4VEeEPR8-unsplash_1_s6zmfh_ar_4_3,c_fill,g_auto__c_scale,w_538.jpg"
                alt="sunset image"
              />
            </div>
            <div class="container__side-right">
              <div class="container__heading">
                <h2></h2>
              </div>
              <div class="container__content">
              </div>
              <div class="container__button">
                <button class="container__btn" type="button">Button</button>
              </div>
            </div>
          </div>
          <script type="module" src="./src/js/content.js" async defer></script>


    </body>
</html>

popup.html

<!DOCTYPE html>

<html>
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <title></title>
    <meta name="Pop-up" content="Pop-up with counter" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link rel="stylesheet" href="./src/scss/main.css" />

  </head>
  <body>
    <div class="popup-container">
      <div class="popup-container__close-btn">
        <button class="popup-container__button" type="button">X</button>
      </div>
      <div class="popup-container__heading">
        <h2>Alert</h2>
      </div>
      <div class="popup-container__content">
      
    </div>

    <script type="module" src="./src/js/popup-modal.js" async defer></script>
  </body>
</html>
0

@qwee123: Czegoś nie rozumiem. W tym ostatnim kodzie jest "popup-modal.js". Nie dałeś kodu tego pliku.
Sory, że nie wnoszę do Twojego problemu nic nowego, ale niestety musisz uporządkować ten kod, bo to co wrzuciłeś
to totalny misorder.

0
finito napisał(a):

@qwee123: Czegoś nie rozumiem. W tym ostatnim kodzie jest "popup-modal.js". Nie dałeś kodu tego pliku.
Sory, że nie wnoszę do Twojego problemu nic nowego, ale niestety musisz uporządkować ten kod, bo to co wrzuciłeś
to totalny misorder.

Tak, ponieważ jest pusty. W pierwszym poscie jest zawartość 2 plików js o które chodzi.

0

@qwee123: Tak przejrzałem to sobie i nie mam 100% pewności, ale wydaje mi się, że próbujesz łączyć programowanie asynchroniczne z synchronicznym. Bo z tego, co mi wiadomo, jeżeli korzystasz z async, to musisz też użyć await.
Tu masz link do dokumentacji: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
Natomiast taki goły przykład:

function DoSynchron(){
  //do something
}
async DoAsynchron(){
  const result = await DoSynchron();
}

Po prostu jeśli używasz async, to musisz też użyć await.

1

Ten kod JavaScript jest wywoływany wewnątrz iframe'a?

qwee123 napisał(a):
<div class="main-container">
 <div class="main-container__content">
   <iframe
     title="main content"
     src="./content.html"
     frameborder="0"
     width="100%"
     height="1000"
     scrolling="no"
   ></iframe>
  </div>

 <div class="main-container__pop-up">
  <iframe
     title="pop-up module"
     src="./popUp.html"
     frameborder="0"
     width="100%"
     height="220"
     allowtransparency="yes"
     scrolling="no"
   ></iframe>
 </div>
</div>

Bo jeśli tak to document.querySelector nam nie zadziała jeśli próbujesz odwołać się poza znacznik iframe. Czyli przykładowo wewnątrz iframe, nie pobierzesz w taki sposób diva o klasie main-container.

Są 2 rozwiązania

  1. Skasować ten iframe jeśli jest niepotrzebny i przenieść cały html do tego samego pliku
  2. Spróbować z window.parent.document.querySelector('.main-container__pop-up'), ale nigdy nie musiałem z tego korzystać i nie wiem, czy zadziała w tym wypadku (https://developer.mozilla.org/en-US/docs/Web/API/Window/parent)

Jeśli window.parent.document.querySelector będzie działać to Twoja funkcja powinna wyglądać mniej więcej tak

function ff() {
   const showPopup = window.parent != window.top
     ? window.parent.document.querySelector(".main-container__pop-up") 
     : document.querySelector(".main-container__pop-up");
     
   showPopup.classList.toggle("main-container__pop-up--show-modal");
}

Wwarunek window.parent != window.top jest po to, żeby wykryć, czy funkcja ff jest wywoływana wewnątrz iframe, czy poza iframe.

1 użytkowników online, w tym zalogowanych: 0, gości: 1