Home > Software design >  How to create a Javascript loop to cycle through numbers for HTML IDs
How to create a Javascript loop to cycle through numbers for HTML IDs

Time:11-19

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" >
  <div >
    <div  style="background-image: url('xxxxx');"></div>
    <div ></div>
    <article>
      <div >
        <div >
          <div >
            <div >
              <h2>xxxxx</h2>
            </div>
            <div ><span>xxxxx</span></div>
            <div >
              <button type="button" id="show1" >Details</button>
            </div>
            <img src="xxxxx" alt="xxxxx"/> </div>
        </div>
        <div >
          <div >
            <div  id="details1">
              <div  id="hide1"><i  aria-hidden="true"></i></div>
              <p >xxxxx</p>
              <p >xxxxx</p>
              <p >xxxxx</p>
              <div >
                xxxxx
              </div>
            </div>
            <div >
              <time> 1 of 56 </time>
            </div>
            <div  data-px-per-scroll="0.5" data-initial-position="450">01</div>
          </div>
        </div>
      </div>
    </article>
  </div>
</section>

CodePudding user response:

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" >
  <div >
    <div  style="background-image: url('xxxxx');"></div>
    <div ></div>
    <article>
      <div >
        <div >
          <div >
            <div >
              <h2>xxxxx</h2>
            </div>
            <div ><span>xxxxx</span></div>
            <div >
              <button type="button" >Details</button>
            </div>
            <img src="xxxxx" alt="xxxxx" /> </div>
        </div>
        <div >
          <div >
            <div >
              <div  ><i  aria-hidden="true"></i></div>
              <p >xxxxx</p>
              <p >xxxxx</p>
              <p >xxxxx</p>
              <div >
                xxxxx
              </div>
            </div>
            <div >
              <time> 1 of 56 </time>
            </div>
            <div  data-px-per-scroll="0.5" data-initial-position="450">01</div>
          </div>
        </div>
      </div>
    </article>
  </div>
</section>

CodePudding user response:

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" >
  <div >
    <div  style="background-image: url('xxxxx');"></div>
    <div ></div>
    <article>
      <div >
        <div >
          <div >
            <div >
              <h2>First heading h2</h2>
            </div>
            <div ><span>xxxxx</span></div>
            <div >
              <button type="button" id="show1" >Details</button>
            </div>
            <img src="xxxxx" alt="xxxxx" /> </div>
        </div>
        <div >
          <div >
            <div  id="details1">
              <div  id="hide1"><i  aria-hidden="true">close</i></div>
              <p >Hidden description (first p)</p>
              <p >second p</p>
              <p >third p</p>
              <div >
                paragraph with social media information
              </div>
            </div>
            <div >
              <time> 1 of 56 </time>
            </div>
            <div  data-px-per-scroll="0.5" data-initial-position="450">01</div>
          </div>
        </div>
      </div>
    </article>

    <article>
      <div >
        <div >
          <div >
            <div >
              <h2>Second heading h2</h2>
            </div>
            <div ><span>xxxxx</span></div>
            <div >
              <button type="button" id="show2" >Details</button>
            </div>
            <img src="xxxxx" alt="xxxxx" /> </div>
        </div>
        <div >
          <div >
            <div  id="details2">
              <div  id="hide2"><i  aria-hidden="true">close</i></div>
              <p >Hidden description (first p)</p>
              <p >second p</p>
              <p >third p</p>
              <div >
                paragraph with social media information
              </div>
            </div>
            <div >
              <time> 2 of 56 </time>
            </div>
            <div  data-px-per-scroll="0.5" data-initial-position="450">01</div>
          </div>
        </div>
      </div>
    </article>

    <article>
      <div >
        <div >
          <div >
            <div >
              <h2>Third heading h2</h2>
            </div>
            <div ><span>xxxxx</span></div>
            <div >
              <button type="button" id="show3" >Details</button>
            </div>
            <img src="xxxxx" alt="xxxxx" /> </div>
        </div>
        <div >
          <div >
            <div  id="details3">
              <div  id="hide3"><i  aria-hidden="true">close</i></div>
              <p >Hidden description (first p)</p>
              <p >second p</p>
              <p >third p</p>
              <div >
                paragraph with social media information
              </div>
            </div>
            <div >
              <time> 3 of 56 </time>
            </div>
            <div  data-px-per-scroll="0.5" data-initial-position="450">01</div>
          </div>
        </div>
      </div>
    </article>
  </div>
</section>

  • Related