简体   繁体   中英

How to use the same javascript function on multiple HTML divs with the same class

So, I'm working on a website and I have a function that expands and contracts a div element upon button press - however I would like to have many of these same divs on the same page without making a separate JS file for each one. I was wondering what I need to do. The HTML, CSS, and JS follow with a brief explanation of what I'm doing:

So basically I have a bunch of classes in the HTML and then through the JS I target the projectDescriptionExpand class and toggle the show-more class. By doing this I change the display from 'none' to 'inline'. Now I'm trying to add another one of these rows in my HTML but I am not able to figure out how. I tried using querySelectorAll and running the JS through a for loop but that doesn't seem to work.

THANKS!!

HTML:

<!-- START OF THE PROJECT HIGHLIGHTS -->
    <div class="row projectHighlightHead greyHighlight">
        <!-- Project description and graphic row -->
        <div class="col-6 justify-content-center" style="padding-right: 7%"> 
            <div class="row"> 

                <!-- PROJECT NAME -->
                <h2 class="projectNameExpand">Project Name</h2>

                <div class="easyButtons"> 
                    <!-- DATE AND STATUS BUTTONS -->
                    <button class="yearStatus" disabled>20XX</button>
                    <button class="yearStatus" disabled>Status</button>
                </div>

                <p class="projectDescriptionExpand"> <strong> Brief project description.</strong> Lorem ipsum Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sem neque venenatis dolor fermentum massa nec<span class="ellipse">...</span><span class="readMore">, auctor mi. Aliquet feugiat rhoncus, egestas integer ultricies facilisi sem neque dolor.</span></p>

                <button class="viewProject">View Project</button>

                <div class="collapsed"> 
                <!-- INSERT THE INSTAGRAM LINK IN THE QUOTE MARKS -->
                    <a href="LINK!!">  
                        <button class="instagramButton"><img style="max-width: 100%;" src="./assets/photos/insta_icon.png"></button>
                    </a> 

                    <a href="LINK!!"> 
                        <button class="projButtons">Case Study</button>
                    </a>

                    <a href="LINK!!"> 
                        <button class="projButtons">Project Link</button>
                    </a>
                </div>
            </div>
        </div>

CSS:

.greyHighlight {
  background-color: #f4f5f6;
  padding-top: 80px;
  padding-bottom: 160px;
}

.whiteHighlight {
  background-color: white;
  padding-top: 80px;
  padding-bottom: 160px;
}

.projectNameExpand {
  font-size: 65px;
  font-family: GreycliffBold;
  color: black;
  width: 100%;
  margin-bottom: 10px;
}

.expand {
  margin-left: -12%;
  margin-top: 50px;
}

.viewProject {
  background-color: transparent;
  border-style: solid;
  border-color: black;
  border-width: 1px;
  border-radius: 3px;
  padding: 5px 30px;

  position: absolute;
  bottom: -80px;

  font-family: GreycliffBold;
  color: black;
  font-size: 25px;
}

.projectDescriptionExpand {
  font-family: GreycliffReg;
  font-size: 25px;
}

.readMore {
  display: none;
}

.show-more .readMore {
  display: inline;
}
.projectImageExpand {
  max-width: 80%;
  box-shadow: 10px -10px #66ffcc;
}
.projectDescription .ellipse {
  display: none;
}

.show-more .ellipse {
  display: none;
}
.collapsed {
  display: none;
}

.show-more {
  display: inline;
}

.projectHighlightHead {
  padding-left: 12%;
}

JS:

const viewProjectButton = document.querySelectorAll(".viewProject");
const projDescription = document.querySelectorAll("projectDescription");

for(var i = 0; i < viewProjectButton.length; i++) { 
    viewProjectButton[i].addEventListener('click', (e)=>{
        document.getElementsByClassName(".projectDescriptionExpand").classList.toggle('show-more');
        document.getElementsByClassName(".collapsed").classList.toggle('show-more');

        if(viewProjectButton[i].innerText === "View Project") {
            viewProjectButton[i].innerText = "Close Project";
            viewProjectButton[i].style.color = "white";
            viewProjectButton[i].style.backgroundColor = "black";
        }
        else {
            viewProjectButton[i].innerText = "View Project";
            viewProjectButton[i].style.color = "black";
            viewProjectButton[i].style.backgroundColor = "white";
        }
    })
}

Rather than set listeners on each button, you can delegate and set one on document , then check to see if it is the button that is being clicked.

To find the associated elements to toggle, you can use closest() to find the common parent, then querySelector to hone in on the element itself. I added a class .project to define a parent tag.

 window.addEventListener('DOMContentLoaded', () => { document.addEventListener('click', e => { if (e.target.classList.contains('viewProject')) { let myParent = e.target.closest('.project'); myParent.querySelector('.collapsed').classList.toggle('show-more'); myParent.querySelector('.projectDescriptionExpand').classList.toggle('show-more'); if (myParent.querySelector('.collapsed').classList.contains('show-more')) { e.target.innerText = "Close Project"; e.target.style.color = "white"; e.target.style.backgroundColor = "black"; } else { e.target.innerText = "View Project"; e.target.style.color = "black"; e.target.style.backgroundColor = "white"; } } }) })
 .greyHighlight { background-color: #f4f5f6; padding-top: 80px; padding-bottom: 160px; } .whiteHighlight { background-color: white; padding-top: 80px; padding-bottom: 160px; } .projectNameExpand { font-size: 65px; font-family: GreycliffBold; color: black; width: 100%; margin-bottom: 10px; } .expand { margin-left: -12%; margin-top: 50px; } .viewProject { background-color: transparent; border-style: solid; border-color: black; border-width: 1px; border-radius: 3px; padding: 5px 30px; position: absolute; bottom: -80px; font-family: GreycliffBold; color: black; font-size: 25px; } .projectDescriptionExpand { font-family: GreycliffReg; font-size: 25px; } .readMore { display: none; } .show-more .readMore { display: inline; } .projectImageExpand { max-width: 80%; box-shadow: 10px -10px #66ffcc; } .projectDescription .ellipse { display: none; } .show-more .ellipse { display: none; } .collapsed { display: none; } .show-more { display: inline; } .projectHighlightHead { padding-left: 12%; }
 <!-- START OF THE PROJECT HIGHLIGHTS --> <div class="row projectHighlightHead greyHighlight"> <!-- Project description and graphic row --> <div class="col-6 justify-content-center" style="padding-right: 7%"> <div class="row project"> <!-- PROJECT NAME --> <h2 class="projectNameExpand">Project Name</h2> <div class="easyButtons"> <!-- DATE AND STATUS BUTTONS --> <button class="yearStatus" disabled>20XX</button> <button class="yearStatus" disabled>Status</button> </div> <p class="projectDescriptionExpand"> <strong> Brief project description.</strong> Lorem ipsum Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sem neque venenatis dolor fermentum massa nec<span class="ellipse">...</span><span class="readMore">, auctor mi. Aliquet feugiat rhoncus, egestas integer ultricies facilisi sem neque dolor.</span></p> <button class="viewProject">View Project</button> <div class="collapsed"> <!-- INSERT THE INSTAGRAM LINK IN THE QUOTE MARKS --> <a href="LINK!!"> <button class="instagramButton"><img style="max-width: 100%;" src="./assets/photos/insta_icon.png"></button> </a> <a href="LINK!!"> <button class="projButtons">Case Study</button> </a> <a href="LINK!!"> <button class="projButtons">Project Link</button> </a> </div> </div> </div>

You could reduce the code further by setting an active class on .project and then having css rules that show/hide the elements wi

 window.addEventListener('DOMContentLoaded', () => { document.addEventListener('click', e => { if (e.target.classList.contains('viewProject')) { e.target.closest('.project').classList.toggle('active'); } }) })
 .greyHighlight { background-color: #f4f5f6; padding-top: 80px; padding-bottom: 160px; } .whiteHighlight { background-color: white; padding-top: 80px; padding-bottom: 160px; } .projectNameExpand { font-size: 65px; font-family: GreycliffBold; color: black; width: 100%; margin-bottom: 10px; } .expand { margin-left: -12%; margin-top: 50px; } .viewProject { background-color: transparent; border-style: solid; border-color: black; border-width: 1px; border-radius: 3px; padding: 5px 30px; position: absolute; bottom: -80px; font-family: GreycliffBold; color: black; font-size: 25px; } .projectDescriptionExpand { font-family: GreycliffReg; font-size: 25px; } .readMore { display: none; } .project.active .readMore { display: inline; } .projectImageExpand { max-width: 80%; box-shadow: 10px -10px #66ffcc; } .projectDescription .ellipse { display: none; } .project.active .projectDescription .ellipse { display: none; } .collapsed { display: none; } .project.active .collapsed { display: inline; } .projectHighlightHead { padding-left: 12%; } .viewProject { content: "View Project"; color: #000; background: #fff; } .project.active .viewProject { content: "Close Project"; color: #fff; background: #000; }
 <!-- START OF THE PROJECT HIGHLIGHTS --> <div class="row projectHighlightHead greyHighlight"> <!-- Project description and graphic row --> <div class="col-6 justify-content-center" style="padding-right: 7%"> <div class="row project"> <!-- PROJECT NAME --> <h2 class="projectNameExpand">Project Name</h2> <div class="easyButtons"> <!-- DATE AND STATUS BUTTONS --> <button class="yearStatus" disabled>20XX</button> <button class="yearStatus" disabled>Status</button> </div> <p class="projectDescriptionExpand"> <strong> Brief project description.</strong> Lorem ipsum Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sem neque venenatis dolor fermentum massa nec<span class="ellipse">...</span><span class="readMore">, auctor mi. Aliquet feugiat rhoncus, egestas integer ultricies facilisi sem neque dolor.</span></p> <button class="viewProject">View Project</button> <div class="collapsed"> <!-- INSERT THE INSTAGRAM LINK IN THE QUOTE MARKS --> <a href="LINK!!"> <button class="instagramButton"><img style="max-width: 100%;" src="./assets/photos/insta_icon.png"></button> </a> <a href="LINK!!"> <button class="projButtons">Case Study</button> </a> <a href="LINK!!"> <button class="projButtons">Project Link</button> </a> </div> </div> </div>

Like the comment above, it's best to use event delegation, to delegate the event from the document node to your viewProject node. You do that by just checking if the current target has the class viewProject .

getElementsByClassName requires the class name without the . and then you select the first element you get by using [0]

if condition checks with innerText , are not that good because if the text changes, then your code breaks. It's best to use data html attributes for that.

 document.addEventListener('click', event => { if (event.target.classList.contains('viewProject')) { clickViewProject(event.target) } }) function clickViewProject (node) { const desc = document.getElementsByClassName('projectDescriptionExpand')[0] desc.classList.toggle('show-more') const collapsed = document.getElementsByClassName('collapsed')[0] collapsed.classList.toggle('show-more') // .. add the rest of the code if (node.innerText === "View Project") { node.innerText = "Close Project" node.style.color = "white" node.style.backgroundColor = "black" } else { node.innerText = "View Project" node.style.color = "black" node.style.backgroundColor = "white" } }
 .greyHighlight { background-color: #f4f5f6; padding-top: 80px; padding-bottom: 160px; } .whiteHighlight { background-color: white; padding-top: 80px; padding-bottom: 160px; } .projectNameExpand { font-size: 65px; font-family: GreycliffBold; color: black; width: 100%; margin-bottom: 10px; } .expand { margin-left: -12%; margin-top: 50px; } .viewProject { background-color: transparent; border-style: solid; border-color: black; border-width: 1px; border-radius: 3px; padding: 5px 30px; position: absolute; bottom: -80px; font-family: GreycliffBold; color: black; font-size: 25px; } .projectDescriptionExpand { font-family: GreycliffReg; font-size: 25px; } .readMore { display: none; } .show-more .readMore { display: inline; } .projectImageExpand { max-width: 80%; box-shadow: 10px -10px #66ffcc; } .projectDescription .ellipse { display: none; } .show-more .ellipse { display: none; } .collapsed { display: none; } .show-more { display: inline; } .projectHighlightHead { padding-left: 12%; }
 <div class="row projectHighlightHead greyHighlight"> <!-- Project description and graphic row --> <div class="col-6 justify-content-center" style="padding-right: 7%"> <div class="row"> <!-- PROJECT NAME --> <h2 class="projectNameExpand">Project Name</h2> <div class="easyButtons"> <!-- DATE AND STATUS BUTTONS --> <button class="yearStatus" disabled>20XX</button> <button class="yearStatus" disabled>Status</button> </div> <p class="projectDescriptionExpand"> <strong> Brief project description.</strong> Lorem ipsum Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sem neque venenatis dolor fermentum massa nec<span class="ellipse">...</span><span class="readMore">, auctor mi. Aliquet feugiat rhoncus, egestas integer ultricies facilisi sem neque dolor.</span></p> <button class="viewProject">View Project</button> <div class="collapsed"> <!-- INSERT THE INSTAGRAM LINK IN THE QUOTE MARKS --> <a href="LINK!!"> <button class="instagramButton"><img style="max-width: 100%;" src="./assets/photos/insta_icon.png"></button> </a> <a href="LINK!!"> <button class="projButtons">Case Study</button> </a> <a href="LINK!!"> <button class="projButtons">Project Link</button> </a> </div> </div> </div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM