Почему этот javascript работает только в теге script, а не в файле .js?

Я погуглил несколько хороших слайдеров изображений и наткнулся на этот. Когда я помещаю javascript в тег script в html, он работает нормально, но когда я пытаюсь поместить его в файл .js, связанный с html, он перестает работать, и я не могу понять, почему. Когда я смотрю на вывод консоли, он говорит, что не может прочитать «addEventListener» в строке 10. Заранее спасибо :)

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html {
  overflow: hidden;
}

body {
  background-color: #262626;

  font-family: "Roboto Slab", serif;

  position: relative;
  overflow-x: hidden;
}

main {
  width: 100vw;
  height: 100vh;
}

#backdrop {
  width: 90%;
  height: 100%;

  margin: 0 auto;
  margin-top: 1rem;
  border-radius: 1rem 1rem 0 0;

  background-color: #727365;
}

#home-link {
  color: #f2f2e4;
  text-decoration: none;
  font-size: 1.7rem;
  font-family: "Space Mono", monospace;
  font-weight: 400;

  position: absolute;
  top: 1.95rem;
  left: 2.6rem;
}

/* Hamburger menu */
#menu a {
  text-decoration: none;
  color: #262626;
}

#menu a:hover {
  color: #0c0c0c;
}

#menu-toggle {
  display: block;

  position: absolute;
  top: 2.5rem;
  right: 3rem;

  z-index: 1;
}

#menu-checkbox {
  display: block;

  width: 40px;
  height: 32px;

  position: absolute;
  top: -7px;
  left: -5px;

  cursor: pointer;

  opacity: 0;
  z-index: 2;
}

#menu-toggle span {
  display: block;

  width: 33px;
  height: 4px;

  margin-bottom: 5px;
  position: relative;

  background: #f2f2e4;
  border-radius: 3px;

  z-index: 1;

  transform-origin: 4px 0px;
  transition: transform 0.5s cubic-bezier(0.77, 0.2, 0.05, 1),
    opacity 0.55s ease;
}

#menu-toggle span:first-child {
  transform-origin: 0% 0%;
}

#menu-toggle span:nth-last-child(2) {
  transform-origin: 0% 100%;
}

#menu-checkbox:checked ~ span {
  opacity: 1;
  transform: rotate(45deg) translate(-2px, -1px);
  background: #3f403b;
}

#menu-checkbox:checked ~ span:nth-last-child(3) {
  opacity: 0;
  transform: rotate(0deg) scale(0.2, 0.2);
}

#menu-checkbox:checked ~ span:nth-last-child(2) {
  opacity: 1;
  transform: rotate(-45deg) translate(0, -1px);
}

#menu {
  width: 60vw;
  height: 70vh;

  position: absolute;
  right: -100px;

  margin: -100px 0 0 0;
  padding: 50px;
  padding-top: 125px;
  border-radius: 1rem;

  background-color: #bfbfae;
  list-style: none;

  transform-origin: 0% 0%;
  transform: translate(100%, 0);
  transition: transform 0.5s cubic-bezier(0.77, 0.2, 0.05, 1);
}

#menu li {
  padding: 10px 0;
  font-size: 22px;
}

#menu-checkbox:checked ~ ul {
  transform: none;
  opacity: 1;
}

/* footer */
#footer {
  position: absolute;
  top: 100vh;
}

/* Scrollbar */
::-webkit-scrollbar {
  width: 13px;
}

::-webkit-scrollbar-thumb {
  border-radius: 100px;
  border: 3px solid transparent;
  background-clip: content-box;
  background-color: rgb(88, 88, 88);
}

::-webkit-scrollbar-thumb:hover {
  background-color: rgb(109, 109, 109);
}

/* Media queries */
@media only screen and (min-width: 600px) {
}

@media only screen and (min-width: 769px) {
  #backdrop {
    margin-top: 2vh;
    width: 98%;
    height: 96.5%;
    border-radius: 1rem;
  }

  #menu-checkbox {
    display: none;
  }

  #menu-toggle span {
    display: none;
  }

  #menu {
    -webkit-transition: none !important;
    -moz-transition: none !important;
    -o-transition: none !important;
    transition: none !important;
    transform: none !important;

    background-color: rgba(160, 160, 160, 0.568);
    backdrop-filter: blur(15px);

    padding: 0 1rem 0 1rem;
    border-radius: 2rem;
    font-family: monospace;

    position: fixed;
    top: 102vh;
    right: 50%;
    translate: 50% 0;

    height: fit-content;
    width: 45vw;

    display: flex;
    justify-content: space-between;
  }

  #menu li {
    display: inline;
    font-size: 1.2rem;
  }

  #active {
    background-color: #f2f2e4;

    border-radius: 3rem;
  }

  .menu-links {
    padding: 8px 35px 8px 35px;
  }

  #home-link {
    display: flex;
    justify-content: center;
    position: static;

    padding-top: 0.5rem;
  }
}

.slider{
  position: relative;
  background: #000116;
  width: 800px;
  min-height: 500px;
  margin: 20px;
  overflow: hidden;
  border-radius: 10px;
}

.slider .slide{
  position: absolute;
  width: 100%;
  height: 100%;
  clip-path: circle(0% at 0 50%);
}

.slider .slide.active{
  clip-path: circle(150% at 0 50%);
  transition: 2s;
}

.slider .slide img{
  position: absolute;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.slider .slide .info{
  position: absolute;
  color: #222;
  background: rgba(255, 255, 255, 0.3);
  width: 75%;
  margin-top: 50px;
  margin-left: 50px;
  padding: 20px;
  border-radius: 5px;
  box-shadow: 0 5px 25px rgb(1 1 1 / 5%);
}

.slider .slide .info h2{
  font-size: 2em;
  font-weight: 800;
}

.slider .slide .info p{
  font-size: 1em;
  font-weight: 400;
}

.navigation{
  height: 500px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  opacity: 0;
  transition: opacity 0.5s ease;
}

.slider:hover .navigation{
  opacity: 1;
}

.prev-btn, .next-btn{
  z-index: 999;
  font-size: 2em;
  color: #222;
  background: rgba(255, 255, 255, 0.8);
  padding: 10px;
  cursor: pointer;
}

.prev-btn{
  border-top-right-radius: 3px;
  border-bottom-right-radius: 3px;
}

.next-btn{
  border-top-left-radius: 3px;
  border-bottom-left-radius: 3px;
}

.navigation-visibility{
  z-index: 999;
  display: flex;
  justify-content: center;
}

.navigation-visibility .slide-icon{
  z-index: 999;
  background: rgba(255, 255, 255, 0.5);
  width: 20px;
  height: 10px;
  transform: translateY(-50px);
  margin: 0 6px;
  border-radius: 2px;
  box-shadow: 0 5px 25px rgb(1 1 1 / 20%);
}

.navigation-visibility .slide-icon.active{
  background: #4285F4;
}

@media (max-width: 900px){
  .slider{
    width: 100%;
  }

  .slider .slide .info{
    position: relative;
    width: 80%;
    margin-left: auto;
    margin-right: auto;
  }
}

@media (max-width: 500px){
  .slider .slide .info h2{
    font-size: 1.8em;
    line-height: 40px;
  }

  .slider .slide .info p{
    font-size: 0.9em;
  }
}

/*.mySlides {
  display: none;
}

/* Slideshow container 
.slideshow-container {
  width: 100%;
  height: 100%;
  max-height: 100vh;
  margin: auto;
}
/* The dots/bullets/indicators 
.dot {
  height: 15px;
  width: 15px;
  margin: 0 2px;
  background-color: #bbb;
  border-radius: 50%;
  display: inline-block;
  transition: background-color 0.6s ease;
}

.active {
  background-color: #717171;
}

/* On smaller screens, decrease text size 
@media only screen and (max-width: 300px) {
  .prev,
  .next,
  .text {
    font-size: 11px;
  }
}

/* Next & previous buttons 
.prev,
.next {
  cursor: pointer;
  position: absolute;
  top: 50%;
  width: auto;
  padding: 16px;
  margin-top: -22px;
  color: white;
  font-weight: bold;
  font-size: 18px;
  transition: 0.6s ease;
  border-radius: 0 3px 3px 0;
  user-select: none;
}

/* Position the "next button" to the right 
.next {
  right: 0;
  border-radius: 3px 0 0 3px;
}

/* On hover, add a black background color with a little bit see-through 
.prev:hover,
.next:hover {
  background-color: rgba(0, 0, 0, 0.8);
}
<!DOCTYPE html>
<html lang = "sv">
  <head>
    <meta charset = "UTF-8" />
    <meta http-equiv = "X-UA-Compatible" content = "IE=edge" />
    <meta name = "viewport" content = "width=device-width, initial-scale=1" />
    <title>Överdäckningen | Startsida</title>
    <link rel = "stylesheet" href = "css/style.css" />
    <script type = "text/javascript" src = "script/js.js"></script>
    <link
      href = "https://fonts.googleapis.com/css2?family=Roboto+Slab:wght@200;300;400&display=swap"
      rel = "stylesheet"
    />
    <link
      href = "https://fonts.googleapis.com/css2?family=Space+Mono&display=swap"
      rel = "stylesheet"
    />
    <link
      rel = "stylesheet"
      href = "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css"
    />
  </head>
  <!--
    Göra så loggan försvinner när man scrollar ner och kommer tillbaka när man scrollar upp

    navbar responsiv, desktop

    mediaquery för ipad

    bilder, text

    göra så bildspelet passar in

    anpassa alla bilder för skärmstorlek, picture element

    (karta kanske?)

    lägga rätt fonter på rubriker och text
  -->
  <body>
    <main>
      <div id = "backdrop">
        <div class = "slider">
          <div class = "slide active">
            <img src = "imgs/1.jpg" alt = "" />
            <div class = "info">
              <h2>Winter Mountains</h2>
              <p>
                Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
                eiusmod tempor incididunt ut labore et dolore magna aliqua.
              </p>
            </div>
          </div>
          <div class = "slide">
            <img src = "imgs/2.jpg" alt = "" />
            <div class = "info">
              <h2>Tropical Desert</h2>
              <p>
                Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
                eiusmod tempor incididunt ut labore et dolore magna aliqua.
              </p>
            </div>
          </div>
          <div class = "slide">
            <img src = "imgs/3.jpg" alt = "" />
            <div class = "info">
              <h2>Steaming Volcanoes</h2>
              <p>
                Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
                eiusmod tempor incididunt ut labore et dolore magna aliqua.
              </p>
            </div>
          </div>
          <div class = "slide">
            <img src = "imgs/4.jpg" alt = "" />
            <div class = "info">
              <h2>Mountain River</h2>
              <p>
                Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
                eiusmod tempor incididunt ut labore et dolore magna aliqua.
              </p>
            </div>
          </div>
          <div class = "slide">
            <img src = "imgs/5.jpg" alt = "" />
            <div class = "info">
              <h2>Egypt Pyramids</h2>
              <p>
                Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
                eiusmod tempor incididunt ut labore et dolore magna aliqua.
              </p>
            </div>
          </div>
          <div class = "navigation">
            <i class = "fas fa-chevron-left prev-btn"></i>
            <i class = "fas fa-chevron-right next-btn"></i>
          </div>
          <div class = "navigation-visibility">
            <div class = "slide-icon active"></div>
            <div class = "slide-icon"></div>
            <div class = "slide-icon"></div>
            <div class = "slide-icon"></div>
            <div class = "slide-icon"></div>
          </div>
        </div>
        <script type = "text/javascript">
          const slider = document.querySelector(".slider");
          const nextBtn = document.querySelector(".next-btn");
          const prevBtn = document.querySelector(".prev-btn");
          const slides = document.querySelectorAll(".slide");
          const slideIcons = document.querySelectorAll(".slide-icon");
          const numberOfSlides = slides.length;
          var slideNumber = 0;

          //image slider next button
          nextBtn.addEventListener("click", () => {
            slides.forEach((slide) => {
              slide.classList.remove("active");
            });
            slideIcons.forEach((slideIcon) => {
              slideIcon.classList.remove("active");
            });

            slideNumber++;

            if (slideNumber > numberOfSlides - 1) {
              slideNumber = 0;
            }

            slides[slideNumber].classList.add("active");
            slideIcons[slideNumber].classList.add("active");
          });

          //image slider previous button
          prevBtn.addEventListener("click", () => {
            slides.forEach((slide) => {
              slide.classList.remove("active");
            });
            slideIcons.forEach((slideIcon) => {
              slideIcon.classList.remove("active");
            });

            slideNumber--;

            if (slideNumber < 0) {
              slideNumber = numberOfSlides - 1;
            }

            slides[slideNumber].classList.add("active");
            slideIcons[slideNumber].classList.add("active");
          });

          //image slider autoplay
          var playSlider;

          var repeater = () => {
            playSlider = setInterval(function () {
              slides.forEach((slide) => {
                slide.classList.remove("active");
              });
              slideIcons.forEach((slideIcon) => {
                slideIcon.classList.remove("active");
              });

              slideNumber++;

              if (slideNumber > numberOfSlides - 1) {
                slideNumber = 0;
              }

              slides[slideNumber].classList.add("active");
              slideIcons[slideNumber].classList.add("active");
            }, 4000);
          };
          repeater();

          //stop the image slider autoplay on mouseover
          slider.addEventListener("mouseover", () => {
            clearInterval(playSlider);
          });

          //start the image slider autoplay again on mouseout
          slider.addEventListener("mouseout", () => {
            repeater();
          });
        </script>
        <header id = "wrapper">
          <nav>
            <a href = "index.html" id = "home-link">ÖVERDÄCKNINGEN</a>
            <div id = "menu-toggle">
              <input id = "menu-checkbox" type = "checkbox" />
              <span class = "hamburger-span"></span>
              <span class = "hamburger-span"></span>
              <span class = "hamburger-span"></span>
              <ul id = "menu">
                <li><a class = "menu-links" id = "active" href = "#">Länk 1</a></li>
                <li><a class = "menu-links" href = "html/link2.html">Länk 2</a></li>
                <li><a class = "menu-links" href = "html/link3.html">Länk 3</a></li>
                <li><a class = "menu-links" href = "html/link4.html">Länk 4</a></li>
              </ul>
            </div>
          </nav>
        </header>
      </div>
      <div>
        <p>
          Lorem ipsum dolor sit amet, consectetur adipisicing elit. Porro amet
          dolores nisi delectus ad inventore laboriosam alias, architecto eos
          sunt quod eum maiores provident aspernatur debitis ratione minus
          quaerat cumque veniam. Delectus commodi odit molestiae excepturi.
          Doloremque rem tempora quod est veritatis earum accusamus vel fugiat
          numquam reprehenderit ad labore repudiandae recusandae neque
          voluptatum a nulla dignissimos sapiente ut, officiis fugit porro.
          Aliquid unde incidunt quisquam. Veniam sunt doloremque modi in
          voluptates inventore. In corrupti hic eos, incidunt iusto dignissimos
          praesentium ut adipisci possimus officiis nesciunt, eveniet asperiores
          illum laudantium aliquid dicta temporibus aut maxime dolor fugit totam
          animi velit repudiandae ea? Esse, quod repudiandae amet iusto
          temporibus aperiam dolore aliquid, magni sunt eveniet deleniti at
          suscipit quasi adipisci, quo officia accusantium repellat nostrum
          nemo! Reiciendis repellat omnis facilis qui excepturi assumenda id
          laborum vero voluptas, vitae aspernatur eius magnam voluptates iusto,
          dolores a fugit tenetur quo nostrum ipsa sequi cumque? Velit voluptate
          et at aut iste obcaecati nisi, vitae repellat placeat quasi iusto.
          Rerum vero eos earum nobis in inventore quos aliquid id, assumenda
          tempora? Modi repudiandae dolorem architecto ut animi doloribus,
          tempore possimus nihil ipsum accusamus fugiat laboriosam culpa iure
          eum mollitia ab? Quidem quas minus necessitatibus voluptate, rem vero
          eligendi possimus totam voluptates laudantium atque illo provident
          quasi! Laboriosam quo odio quia in! Commodi voluptatem facilis eos
          neque non, magni fugiat numquam consectetur, ipsa dolores ut rerum,
          sint sequi quos illo obcaecati omnis harum laudantium error inventore
          praesentium. Commodi fugit nostrum asperiores vel ducimus
          reprehenderit quis suscipit laborum et fugiat libero eius assumenda
          esse nobis, iste, impedit ipsa repudiandae aut aspernatur placeat
          inventore! Eligendi sit in obcaecati quia repudiandae explicabo
          officia eveniet omnis earum. Quibusdam alias amet quas nobis ullam
          vitae enim quod facilis quam maiores! Rem consequatur distinctio
          laudantium harum labore, minus qui molestiae suscipit modi libero quia
          pariatur maxime hic, voluptate totam numquam, illo beatae voluptatibus
          atque ipsa assumenda. Ipsum laudantium, modi nam repellat similique
          vitae asperiores corrupti accusamus voluptate maxime harum expedita,
          ipsa fugiat obcaecati deserunt porro impedit blanditiis error
          reprehenderit temporibus ex at, molestias eius magnam? Voluptatem,
          repellat ratione distinctio sit odio assumenda non ad fugit eligendi
          nemo eveniet enim porro asperiores, aliquam aliquid? Officia
          reiciendis libero tempore cupiditate rem laboriosam odit aspernatur!
          Perferendis, id odit. Laudantium, culpa. Iure placeat deserunt
          consectetur! Cumque, asperiores itaque nobis laudantium fuga fugit,
          nemo autem maiores quo et perferendis laborum illum quis suscipit
          eveniet ullam modi. Soluta cum eaque, sequi eveniet deserunt quia odio
          officia tenetur vero corrupti labore eum voluptatum quam cumque fuga
          hic numquam! Ullam, a dolore omnis nemo beatae at possimus eum
          officiis molestiae exercitationem temporibus ab blanditiis voluptatum
          reiciendis mollitia maxime perspiciatis harum nostrum officia deleniti
          delectus. Hic quos molestias rerum ducimus fugiat consectetur facilis
          perspiciatis animi, incidunt error ut tenetur similique unde molestiae
          labore perferendis sapiente totam mollitia! Qui, similique ad eos,
          cumque laudantium sapiente dolores quas omnis nam fuga exercitationem
          blanditiis quaerat aut animi at beatae explicabo nihil adipisci.
          Voluptatum qui repudiandae provident ratione, tenetur illum fuga quas
          sapiente laborum ipsa obcaecati aut quod perspiciatis, ullam, veniam
          explicabo nulla quaerat incidunt quidem! Est odit corrupti quibusdam
          doloribus! Vel excepturi voluptatum, nobis voluptatem error
          consectetur placeat quibusdam architecto! Molestiae ipsum suscipit est
          aperiam veniam nobis laboriosam porro alias, sit eos repellendus
          labore, ratione unde ducimus, accusantium illum voluptatum. Tempore,
          rem repellat, laboriosam velit aut aliquid ipsa quibusdam consectetur
          soluta veniam architecto totam! Reiciendis aliquid vel voluptatem
          tempore ea, unde officiis. Corrupti perspiciatis voluptates, suscipit
          vero voluptatibus corporis commodi excepturi reprehenderit eos et
          nulla voluptatem fuga porro maxime quam eius distinctio, at id aliquid
          itaque consequuntur ut repudiandae. Officiis, qui eveniet animi
          officia voluptate ipsum, fuga, nisi doloribus in obcaecati quia error
          eaque ad cupiditate aliquam alias modi placeat mollitia quibusdam
          illum quas aliquid sint? Eligendi, nostrum maiores quas iste
          recusandae quae natus impedit consequatur id ipsam dignissimos sequi
          excepturi, nobis ducimus dolorum tenetur repellendus praesentium in
          dicta atque velit voluptatum quia. Placeat culpa aliquid ab natus
          quaerat non quasi cupiditate reprehenderit soluta, unde repellendus
          illum, praesentium distinctio blanditiis quod magnam laborum excepturi
          iusto molestiae accusamus dolorem nihil. Voluptatum, molestias
          debitis? Ipsum veritatis iure suscipit, saepe alias aliquam enim,
          officiis deleniti soluta ratione tempora maxime ab beatae autem
          accusamus nemo sit, porro dolore illum esse hic. Repudiandae expedita
          iste, inventore, officia, ut voluptatibus unde ullam sint debitis enim
          ipsa dolorum ducimus quos. Suscipit tenetur ratione sed iure! Tempora
          maxime, et neque natus dolores aliquam hic magni commodi quod a vel
          delectus quisquam aperiam cupiditate eaque aspernatur tempore atque
          tenetur modi? Exercitationem repellat hic officiis atque aperiam
          repellendus et eos quisquam ratione, quidem enim quae sint facere
          laudantium amet iure? Dolorum esse autem corrupti explicabo laborum
          eum at distinctio dicta aut molestias sunt, totam ab eligendi
          possimus. Ipsa, dolorem numquam sint doloribus reprehenderit
          laboriosam aperiam alias, culpa recusandae minima assumenda tempore
          placeat sunt nesciunt, dolores quidem repudiandae dolor. Ipsa illo, ex
          repellat iusto ea fugit sapiente hic, adipisci nam, soluta numquam
          error eum neque quos commodi quae a architecto voluptas perspiciatis?
          Velit impedit libero ut sit minima exercitationem delectus nobis
          quibusdam ab excepturi, soluta maxime ipsum, maiores laudantium iste?
          Atque corrupti cupiditate non deserunt alias deleniti delectus numquam
          repellendus soluta obcaecati fugit veniam, porro asperiores nesciunt
          sed hic esse iusto ipsam provident est praesentium nam eveniet neque
          at. Eaque aliquid ipsam vitae. Impedit quas est asperiores sunt
          recusandae, iure beatae accusantium quidem quos iste sint sed
          architecto eum perferendis dolorum tempora nihil odio error.
        </p>
      </div>
      <footer id = "footer">
        <p id = "footer-text">Lorem ipsum dolor sit amet consectetur.</p>
      </footer>
    </main>
  </body>
</html>

Включите HTML-код, если он находится в теге скрипта.

asportnoy 14.02.2023 18:09
When I look at the console output, it says it can't read the "addEventListener" at line 10. Что именно там написано? Покажи свой HTML.
tkausl 14.02.2023 18:09

Я не удивлюсь, если скрипт запустится до того, как будет отображен HTML.

evolutionxbox 14.02.2023 18:10
Оптимизация React Context шаг за шагом в 4 примерах
Оптимизация React Context шаг за шагом в 4 примерах
При использовании компонентов React в сочетании с Context вы можете оптимизировать рендеринг, обернув ваш компонент React в React.memo сразу после...
Интервьюер: Почему &apos;[] instanceof Object&apos; возвращает &quot;true&quot;?
Интервьюер: Почему '[] instanceof Object' возвращает "true"?
Все мы знаем, что [] instanceof Array возвращает true, но почему [] instanceof Object тоже возвращает true?
Абстрактное синтаксическое дерево (AST) и как оно работает с ReactJS
Абстрактное синтаксическое дерево (AST) и как оно работает с ReactJS
Абстрактное синтаксическое дерево (AST) - это древовидная структура данных, которая представляет структуру и иерархию исходного кода на языке...
0
3
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Да, что сказал @evolutionxbox. Если у вас есть JS, включенный в заголовок или любое место выше, где вы определили nextBtn в HTML, или любые другие элементы, которые вы планируете использовать, то эти элементы будут нулевыми при выполнении скрипта.

Вы должны убедиться, что ваш сценарий запускается после загрузки документа, поместив вышеуказанное в функцию и запустив ее, присоединив указанную функцию к событию загрузки окна.

Включение JS должно выглядеть примерно так:

function yourScript(){
/* Your script goes here */
}

window.addEventListener("load",yourScript);

Вы также можете использовать

window.addEventListener("DOMContentLoaded",yourscript);

Если вы хотите запустить скрипт после анализа DOM, но до загрузки изображений и другого стороннего контента. Это, вероятно, хорошо для вашего сценария.

Популярный способ сделать это в наши дни — просто поместить тег сценария перед закрывающим тегом </body>. или используйте атрибут defer.

Keith 14.02.2023 18:17

Другие вопросы по теме