0

I have a ton of modals on a page and I'm using this script to link the ID of an HTML button to the ID of the modal and it's close button:

var target = document.getElementById('show1');
var currentOpacity = 0;
$(document).ready(function () {
  $("#hide1").click(function () {
    $("#details1").hide();
    target.style.opacity = currentOpacity + 1;
  });
  $("#show1").click(function () {
    $("#details1").show();
    target.style.opacity = currentOpacity - 1;
  });
});
const button1 = document.querySelector("#show1");
const readout1 = document.querySelector("p");
button1.addEventListener("mousemove", (e) => {
  const {
    x,
    y
  } = button1.getBoundingClientRect();
  button1.style.setProperty("--x", e.clientX - x);
  button1.style.setProperty("--y", e.clientY - y);
});

This works but I have 56 buttons... How could I write this script so that #show1 #details1 #hide1, #show2 #details2 #hide2, #show3 #details3 #hide3 etc. all the way to 56 work without duplicating this code block 56 times?

EDIT

Here is the HTML for an item:

<section id="photo01" class="item-module-wrap">
  <div class="item-module">
    <div class="blurred-image" style="background-image: url('xxxxx');"></div>
    <div class="dot-texture"></div>
    <article>
      <div class="dgov-grid">
        <div class="dgov-col-sm-7 dgov-col-md-8 dgov-col-lg-9">
          <div class="main-photo-module">
            <div class="sticky">
              <h2>xxxxx</h2>
            </div>
            <div class="sticky"><span>xxxxx</span></div>
            <div class="sticky">
              <button type="button" id="show1" class="details-button shiny">Details</button>
            </div>
            <img src="xxxxx" alt="xxxxx"/> </div>
        </div>
        <div class="dgov-col-sm-5 dgov-col-md-4 dgov-col-lg-3">
          <div class="aside-module">
            <div class="details" id="details1">
              <div class="close" id="hide1"><i class="fa fa-times" aria-hidden="true"></i></div>
              <p class="description">xxxxx</p>
              <p class="extra">xxxxx</p>
              <p class="extra">xxxxx</p>
              <div class="social">
                xxxxx
              </div>
            </div>
            <div class="sticky">
              <time> 1 of 56 </time>
            </div>
            <div class="item-number layer" data-px-per-scroll="0.5" data-initial-position="450">01</div>
          </div>
        </div>
      </div>
    </article>
  </div>
</section>

2
  • Can you also paste the HTML structure for a single module ? Commented Nov 17, 2022 at 22:37
  • @Sushanth-- Sure, I added an item of HTML to the question. Commented Nov 17, 2022 at 22:46

2 Answers 2

1

When attaching similar events or actions to a module ( section in this case ) where in the structure is exactly the same and the only difference is just the variation of certain ids, the first thing that should come to mind is to swap out ids with classes and use the HTML structure to an advantage.

Swap ids with classes for show1, hide1 and details1.

var target = document.getElementById('show1');
var currentOpacity = 0;
$(document).ready(function() {
  // use event delegation and attach event to elements with show class inside a section
  $('section').on('click', '.show', () => {
    // get the closest element with class details inside the current section
    const $details = $(this).closest('section').find('.details');
    // get the closest element with class hide inside the current section
    const $hide = $(this).closest('section').find('.hide');
    
    $details.show();
    $hide.show();
    
  });
  
  // use event delegation and attach event to elements with hide class inside a section
  $('section').on('click', '.hide', () => {
    // get the closest element with class details inside the current section
    const $details = $(this).closest('section').find('.details');
    // get the closest element with class show inside the current section
    const $show = $(this).closest('section').find('.show');
    
    $details.show();
    $show.show();
  });
});
<section id="photo01" class="item-module-wrap">
  <div class="item-module">
    <div class="blurred-image" style="background-image: url('xxxxx');"></div>
    <div class="dot-texture"></div>
    <article>
      <div class="dgov-grid">
        <div class="dgov-col-sm-7 dgov-col-md-8 dgov-col-lg-9">
          <div class="main-photo-module">
            <div class="sticky">
              <h2>xxxxx</h2>
            </div>
            <div class="sticky"><span>xxxxx</span></div>
            <div class="sticky">
              <button type="button" class="details-button shiny show">Details</button>
            </div>
            <img src="xxxxx" alt="xxxxx" /> </div>
        </div>
        <div class="dgov-col-sm-5 dgov-col-md-4 dgov-col-lg-3">
          <div class="aside-module">
            <div class="details">
              <div class="close" class="hide"><i class="fa fa-times" aria-hidden="true"></i></div>
              <p class="description">xxxxx</p>
              <p class="extra">xxxxx</p>
              <p class="extra">xxxxx</p>
              <div class="social">
                xxxxx
              </div>
            </div>
            <div class="sticky">
              <time> 1 of 56 </time>
            </div>
            <div class="item-number layer" data-px-per-scroll="0.5" data-initial-position="450">01</div>
          </div>
        </div>
      </div>
    </article>
  </div>
</section>

Sign up to request clarification or add additional context in comments.

2 Comments

I updated the HTML markup and added this script exactly as you have it but unfortunately it doesn't seem to work.
getting this: Uncaught TypeError: Cannot set properties of undefined (setting 'opacity')
0

Here is one way of doing it (without using jQuery). I chose to work with a delegated event handling. The "onclick" event ist defined on the parent element <section> in which we find all <article> elements and their show-buttons, close-elements and detail-divs.

In the event handler function I used relative DOM navigation:

  • with .closest("article") I find the parent article element to the clicked element in which I then

  • look for the ".details"-div with .querySelector(".details").

  • With if(trg.classList.contains("details-button")) ... I check whether the details button was clicked and then set the display value for the details div accordingly.

The clickable elements and the ".detail" divs still have their id attributes but these are no longer referred to in my script. They can safely be removed.

document.querySelectorAll(".details").forEach(d=>d.style.display="none");
document.querySelector("section").onclick=ev=>{
 const trg=ev.target, dsty=trg.closest("article").querySelector(".details").style;
 if(trg.classList.contains("details-button")) dsty.display="";
 if(trg.classList.contains("fa-times")) dsty.display="none";
}
.close {cursor:pointer}
<section id="photo01" class="item-module-wrap">
  <div class="item-module">
    <div class="blurred-image" style="background-image: url('xxxxx');"></div>
    <div class="dot-texture"></div>
    <article>
      <div class="dgov-grid">
        <div class="dgov-col-sm-7 dgov-col-md-8 dgov-col-lg-9">
          <div class="main-photo-module">
            <div class="sticky">
              <h2>First heading h2</h2>
            </div>
            <div class="sticky"><span>xxxxx</span></div>
            <div class="sticky">
              <button type="button" id="show1" class="details-button shiny">Details</button>
            </div>
            <img src="xxxxx" alt="xxxxx" /> </div>
        </div>
        <div class="dgov-col-sm-5 dgov-col-md-4 dgov-col-lg-3">
          <div class="aside-module">
            <div class="details" id="details1">
              <div class="close" id="hide1"><i class="fa fa-times" aria-hidden="true">close</i></div>
              <p class="description">Hidden description (first p)</p>
              <p class="extra">second p</p>
              <p class="extra">third p</p>
              <div class="social">
                paragraph with social media information
              </div>
            </div>
            <div class="sticky">
              <time> 1 of 56 </time>
            </div>
            <div class="item-number layer" data-px-per-scroll="0.5" data-initial-position="450">01</div>
          </div>
        </div>
      </div>
    </article>

    <article>
      <div class="dgov-grid">
        <div class="dgov-col-sm-7 dgov-col-md-8 dgov-col-lg-9">
          <div class="main-photo-module">
            <div class="sticky">
              <h2>Second heading h2</h2>
            </div>
            <div class="sticky"><span>xxxxx</span></div>
            <div class="sticky">
              <button type="button" id="show2" class="details-button shiny">Details</button>
            </div>
            <img src="xxxxx" alt="xxxxx" /> </div>
        </div>
        <div class="dgov-col-sm-5 dgov-col-md-4 dgov-col-lg-3">
          <div class="aside-module">
            <div class="details" id="details2">
              <div class="close" id="hide2"><i class="fa fa-times" aria-hidden="true">close</i></div>
              <p class="description">Hidden description (first p)</p>
              <p class="extra">second p</p>
              <p class="extra">third p</p>
              <div class="social">
                paragraph with social media information
              </div>
            </div>
            <div class="sticky">
              <time> 2 of 56 </time>
            </div>
            <div class="item-number layer" data-px-per-scroll="0.5" data-initial-position="450">01</div>
          </div>
        </div>
      </div>
    </article>

    <article>
      <div class="dgov-grid">
        <div class="dgov-col-sm-7 dgov-col-md-8 dgov-col-lg-9">
          <div class="main-photo-module">
            <div class="sticky">
              <h2>Third heading h2</h2>
            </div>
            <div class="sticky"><span>xxxxx</span></div>
            <div class="sticky">
              <button type="button" id="show3" class="details-button shiny">Details</button>
            </div>
            <img src="xxxxx" alt="xxxxx" /> </div>
        </div>
        <div class="dgov-col-sm-5 dgov-col-md-4 dgov-col-lg-3">
          <div class="aside-module">
            <div class="details" id="details3">
              <div class="close" id="hide3"><i class="fa fa-times" aria-hidden="true">close</i></div>
              <p class="description">Hidden description (first p)</p>
              <p class="extra">second p</p>
              <p class="extra">third p</p>
              <div class="social">
                paragraph with social media information
              </div>
            </div>
            <div class="sticky">
              <time> 3 of 56 </time>
            </div>
            <div class="item-number layer" data-px-per-scroll="0.5" data-initial-position="450">01</div>
          </div>
        </div>
      </div>
    </article>
  </div>
</section>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.