Personal project:JS innerhtml DOM issue

Hi,
I’m doing a personal project but stuck on making a gallery work.
The error is: Uncaught TypeError: Cannot set properties of null (setting ‘innerHTML’)
I suspect it’s either a DOM issue or maybe I’m not referencing the correct element in my HTML.
The error on my browser is pointing to “placeName” being the issue.
I’ve starred the place where the error is “showGallery()” and “placeName” in the JS file.

//HTML file
    <article class="coloured-container" id="what-to-do">
        <section class="things-to-do">
          <h1>Things to do at your stay</h1>
          <div class="gallery-container">
            <div class="gallery">
              <div class="gallery-left-column">
                <div class="inside-information">
                  <h2 class="placeName">Wineries and Restaurants</h2>
                  <p class="description2">
                    There are more than 55 wineries to choose from - offering
                    cellar door sales, restaurants, cafes and tours. Along the
                    way discover a foodie’s paradise. Meet the growers,
                    producers, providers and chefs. Experience the fun of
                    picking your own produce or buying dinner ingredients at the
                    farm gate. Dine with views of the sea, lakes and vineyards.
                  </p>
                </div>
              </div>
              <div class="gallery-right-column">
                <img src="images/gallery-wineries.png" alt="wineries" />
              </div>

              <div class="counter">
                <span class="number">1</span>
                <span>of</span>
                <span>8</span>
              </div>
            </div>

            <div class="arrows">
              <span class="gallery-left-arrow">&#10094;</span>
              <span class="gallery-right-arrow">&#10095;</span>
            </div>
          </div>
        </section>
      </article>
/*JS Script */
/* Gallery slideshow for home page */

let galleryIndex = 1;

const gallery_previous = document.querySelector(".gallery-left-arrow");
const gallery_next = document.querySelector(".gallery-right-arrow");

gallery_previous.addEventListener("click", previousGallery);
gallery_next.addEventListener("click", nextGallery);

**showGallery();**

function showGallery() {
  //list of gallery objects
  const gallery1 = {
    file: "gallery-wineries.png",
    alt: "wineries",
    placeName: "Wineries and Restaurants",
    description2:
      " There are more than 55 wineries to choose from - offering cellar door sales, restaurants, cafes and tours. Along the way discover a foodie’s paradise. Meet the growers, producers, providers and chefs. Experience the fun of picking your own produce or buying dinner ingredients at the farm gate. Dine with views of the sea, lakes and vineyards.",
    count: "1",
  };

  const gallery2 = {
    file: "gallery-golf.png",
    alt: "golf",
    placeName: "Golf",
    description2:
      "The Mornington Peninsula is blessed with 19 courses that both challenge and excite. Many golf courses provide the most exhilarating views over Port Phillip Bay, Western Port and Bass Strait. The sand hills and coastal hinterland provide wonderful examples of links, resort and traditional courses. Visitors are always welcome.",
    count: "2",
  };

  const gallery3 = {
    file: "gallery-hotsprings.png",
    alt: "hotsprings",
    placeName: "Penisula Hot Spring",
    description2:
      "Another world awaits. Enjoy the thermal bathing area or book a private indoor or outdoor hot springs bath experience. Activities include reflexology treatments, foot and hand baths, sauna, steam baths, cold plunges and yoga. The cafe at the bath house provides light meals and gourmet pizzas. Feel revitalised and relaxed at the same time.",
    count: "3",
  };

  const gallery4 = {
    file: "gallery-sorrento-ferry.png",
    alt: "ferry",
    placeName: "Queenscliff-Sorrento Ferry",
    description2:
      "There's no better way to cross the Bay either with your car or as a foot passenger. It only takes 40 minutes. Spot the playful dolphins whilst enjoying a coffee and light refreshments. The ferries run every day of the year on the hour. Wonderful restaurants at historic Queenscliff on the Bellarine peninsula offer perfect lunchtime adventures.",
    count: "4",
  };

  const gallery5 = {
    file: "gallery-walking-tracks.png",
    alt: "walking-tracks",
    placeName: "Walking Tracks",
    description2:
      " Fabulous walking tracks in any direction for all ages. Beautiful beach walks, amazing cliff top strolls and for the more serious walkers, a 100km walk combines the Bay trial, National Parks and the two Bays walk through the hinterland.",
    count: "5",
  };

  const gallery6 = {
    file: "gallery-arts-culture.png",
    alt: "artsNCulture",
    placeName: "Arts and Culture",
    description2:
      "The Mornington Peninsula hosts an array of exhibitions and galleries, featuring fine art, sculpture, ceramics, jewelry, hand blown glass and clothing. Small local galleries and craft markets are in abundance across the region.",
    count: "6",
  };

  const gallery7 = {
    file: "gallery-shopping.png",
    alt: "shopping",
    placeName: "Shopping Escapades",
    description2:
      'Lovely, leisurely shopping - for pure pleasure - is listed as the number one activity for holidaymakers.<br /><br /> Sorrento and Mornington will not disappoint. Bookshops, giftware, home living and of course the odd handbag or "must have that" top is yours for the exploring.',
    count: "7",
  };

  const gallery8 = {
    file: "gallery-Water-sports.png",
    alt: "water-sports",
    placeName: "Water Sports",
    description2:
      "Endless Fun for all the family. Sailing, fishing, kayaking, paddle boarding, snorkeling, scuba diving and surfing are all on offer, not to mention the cricket match on the beach.",
    count: "8",
  };

  //store objects into an array
  const gallery = [
    gallery1,
    gallery2,
    gallery3,
    gallery4,
    gallery5,
    gallery6,
    gallery7,
    gallery8,
  ];

  //check the length of the slides
  if (galleryIndex > gallery.length) {
    galleryIndex = 1;
  }

  //checking to see we are not displaying slide 0
  if (galleryIndex === 0) {
    //go to last slide
    galleryIndex = gallery.length;
  }

  //display the image in the slide
  const slideGallery = document.querySelector(".gallery img");
  slideGallery.src = "images/" + gallery[galleryIndex].file;
  slideGallery.alt = gallery[galleryIndex].alt;

  //display the description in the slide
  const description2 = document.querySelector(".gallery description2");
  description2.innerHTML = gallery[galleryIndex].description2;
  **const placeName = document.querySelector(".placeName");**
**  placeName.innerHTML = gallery[galleryIndex].placeName;**

  //display the count in the slide
  const number = document.querySelector(".number");
  number.innerHTML = gallery[galleryIndex].count + " of 8";
}

function previousGallery() {
  galleryIndex--;
  showGallery();
}

function nextGallery() {
  galleryIndex++;
  showGallery();
}

````Preformatted text`

I found a problem here:

const description2 = document.querySelector(".gallery description2");

description2 is missing a period in front (because its a class). It should be .description2

Also, your indices are off (meaning galleryIndex) when you check the indices:

  //check the length of the slides
  if (galleryIndex > gallery.length) {
    galleryIndex = 1;
  }

  //checking to see we are not displaying slide 0
  if (galleryIndex === 0) {
    //go to last slide
    galleryIndex = gallery.length;
  }

will cause problems because it is set up to handle galleryIndex being from 1 to 8;
however, the actual indices of the gallery array are 0 to 7.

Notice that gallery[0] would give you the gallery1 object.

1 Like

Thank you! It’s working now!

Something to consider when querying a class, there are expected to be more than one element in the collection, and the above selector is only selecting the first one.

Aside

Critically speaking, while this strategy might be okay in a finite sense, how well does it scale?

What if the data structure contained the objects and used it as a controller? An array of objects allows for anonymity but access by index. Regardless the complexity of our object data, we can iterate the array with array.forEach() and gain internal access, regardless the length of the array. It supports adding new objects without having to name them.

This is where object constructors have real value. If we only ever add that class of object to our data structure, it is future proof and portable.

Along this line we would populate our controller with identically blueprinted objects

class Image {
  constructor (src, alt, loc, cap, num) {
    this.src = src;
    this.alt = alt;
    this.loc = loc;
    this.cap = cap;
    this.num = num;
  }
}

For good measure we could make our gallery a class with the software built to ensure that only Image class objects are inserted into the data.

class Gallery {
  constructor () {
    this.collection = []
  }
  addImage (imageInstance) {
    if (imageInstance instanceof Image) {
      this.collection.push(imageInstance)
    }
  }
}
const gallery = new Gallery();
gallery.addImage(new Image(
  "gallery-shopping.png",
  "shopping",
  "Shopping Escapades",
  `Lovely, leisurely shopping - for pure pleasure - is listed as the number one activity for holidaymakers.

 Sorrento and Mornington will not disappoint. Bookshops, giftware, home living and of course the odd handbag or "must have that" top is yours for the exploring.`,
  "7"
))
console.log(gallery.collection)
[ Image {
    src: 'gallery-shopping.png',
    alt: 'shopping',
    loc: 'Shopping Escapades',
    cap: 'Lovely, leisurely shopping - for pure pleasure - is listed as the number one activity for holidaymakers.\n\n Sorrento and Mornington will not disappoint. Bookshops, giftware, home living and of course the odd handbag or "must have that" top is yours for the exploring.',
    num: '7' } ]
2 Likes