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 thenlook 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>