0

As a javascript newbie, I need some help. I'm building html pages that have certain multiple elements (in my case, different translations of the bible) switching in or out based upon a user's preferences. I need to change the display property of a given css class between "display:block" and "display:none" with a button click. My current code works for changing the first instance of a paragraph in a css class, but what I want is to be able to change the display properties of ALL instances of a css with a button click. My research tells me I probably need a "for" loop in my javascript, but I haven't been able to figure out the proper syntax for how to write and implement that so that the button clicks will show/hide ALL instances of the same css class. Here's my code:

<style>
p.niv {display:block;}
p.esv {display:none;}
p.kjv {display:none;}
</style>

<p>Click the buttons to display your preferred Bible version:</p>

<button onclick="niv()">NIV</button>
<button onclick="kjv()">KJV</button>
<button onclick="esv()">ESV</button>

<p>Regular paragraph, blah blah</p>
<p class="niv">this NIV paragraph will become hidden when the KJV or ESV button is clicked</p>
<p class="niv">but this NIV paragraph stays visible even though I want it to be hidden too</p>
<p class="kjv">this KJV paragraph will become hidden when the NIV or ESV button is clicked</p>
<p class="kjv">but this KJV paragraph stays visible even though I want it to be hidden too</p>
<p class="esv">this ESV paragraph will become hidden when the KJV or NIV button is clicked</p>
<p class="esv">but this ESV paragraph stays visible even though I want it to be hidden too</p>

<script>
    var n = document.getElementsByClassName("niv") [0];
    var k = document.getElementsByClassName("kjv") [0] ;
    var e = document.getElementsByClassName("esv") [0];
         
function niv() {

    n.style.display = "block";
    k.style.display = "none";
    e.style.display = "none";
  }

function kjv() {
 
    n.style.display = "none";
    k.style.display = "block";
    e.style.display = "none";    
  }

function esv() {
  
    n.style.display = "none";
    k.style.display = "none";
    e.style.display = "block";
  }

</script>

How can I loop my javascript functions to change the display properties of every instance of a css class? Thanks in advance for helping out a newbie!

  • Does this answer your question? [JS: iterating over result of getElementsByClassName using Array.forEach](https://stackoverflow.com/questions/3871547/js-iterating-over-result-of-getelementsbyclassname-using-array-foreach) – CBroe Dec 07 '20 at 13:52
  • (Since your class names are very limited in number, and static, this could also be done without any looping - by creating rules in your stylesheet, that hide all those elements of a certain class, when a common ancestor gets a specific class assigned - then you just need to set/remove a class in one single place.) – CBroe Dec 07 '20 at 13:54
  • CBroe thank you for responding. Since html is only one of many jobs I have, I'm afraid I'm not knowledgable enough to understand what I'm looking at in the examples you've provided thus far. I'm guessing that you've answered my question, but I'm not sharp enough to know what to do with it! – imaginizer Dec 07 '20 at 13:59
  • https://stackoverflow.com/a/6523513/1427878 has a really simple example of how to loop over the result of getElementsByClassName using a simple `for` loop, and shows how to access an element via the loop counter variable. – CBroe Dec 07 '20 at 14:01
  • CBroe thank you, I'll fiddle with that and see if I can make sense of it. I really appreciate your responses. I'll let you know if I get it worked out. – imaginizer Dec 07 '20 at 14:11

3 Answers3

1

Instead of selecting all the paragraphs and iterating through them I would suggest delegating that job to the browser. So, you can wrap your paragraphs in a container and operate with its className.

<p>Click the buttons to display your preferred Bible version:</p>

<button onclick="changeVersion('niv')">NIV</button>
<button onclick="changeVersion('kjv')">KJV</button>
<button onclick="changeVersion('esv')">ESV</button>

<p>Regular paragraph, blah blah</p>

<div id='container' class='niv-active'>
    <p class="niv">this NIV paragraph will become hidden when the KJV or ESV button is clicked</p>
    <p class="niv">but this NIV paragraph stays visible even though I want it to be hidden too</p>
    <p class="kjv">this KJV paragraph will become hidden when the NIV or ESV button is clicked</p>
    <p class="kjv">but this KJV paragraph stays visible even though I want it to be hidden too</p>
    <p class="esv">this ESV paragraph will become hidden when the KJV or NIV button is clicked</p>
    <p class="esv">but this ESV paragraph stays visible even though I want it to be hidden too</p>
</div>
.niv, .esv, .kjv {
  display: none;
}
#container.niv-active .niv {
  display: block;
}
#container.kjv-active .kjv {
  display: block;
}
#container.esv-active .esv {
  display: block;
}
const container = document.getElementById("container");
         
function changeVersion(v) {
    container.className = v + '-active';
  }
gubnich
  • 61
  • 2
  • This is an interesting solution! – secan Dec 07 '20 at 15:33
  • Thank you for your answer as well. I've shied away from wrapping my paragraph classes in divs or containers because (in my use-case) the paragraphs I need to show/hide will be interspersed within a lot of other text in multiple locations throughout my document, and based upon my limited understanding, I would need each paragraph I want to show/hide to be wrapped in a container. It's likely that I'm just not understanding your solution, but I'm certainly thankful for it! I have a lot to learn! – imaginizer Dec 07 '20 at 16:31
  • @imaginizer, gubnich's solution can be used in your scenario too because it targets only the paragraphs whose class list includes the desired one (`niv` or `kjv` or `esv`). You can test it here: https://jsfiddle.net/8p6uLnys/1/ – secan Dec 09 '20 at 09:30
  • Aha! Now I understand. This is slick! Thanks gubnich! And thanks again secan! You've really helped me to understand what I'm looking at. I really appreciate everyone's help! – imaginizer Dec 10 '20 at 19:17
0

May I suggest a different approach, requiring fewer lines of code?

<style>
  /*1. you create a single class whose only purpose is to hide the element*/
  .hide {
    display: none;
  }
</style>

<p>Click the buttons to display your preferred Bible version:</p>

<button onclick="showVersion('.niv')">NIV</button>
<button onclick="showVersion('.kjv')">KJV</button>
<button onclick="showVersion('.esv')">ESV</button>

<p>Regular paragraph, blah blah</p>
<p class="niv">this NIV paragraph will become hidden when the KJV or ESV button is clicked</p>
<p class="niv">but this NIV paragraph stays visible even though I want it to be hidden too</p>
<p class="kjv hide">this KJV paragraph will become hidden when the NIV or ESV button is clicked</p>
<p class="kjv hide">but this KJV paragraph stays visible even though I want it to be hidden too</p>
<p class="esv hide">this ESV paragraph will become hidden when the KJV or NIV button is clicked</p>
<p class="esv hide">but this ESV paragraph stays visible even though I want it to be hidden too</p>

<script>
  /* 2. you create a single function that hides all versions but the selected one */
  function showVersion(selector) {
    // first hide all versions...
    document.querySelectorAll('.niv, .kjv, .esv').forEach(elem => elem.classList.add('hide'));
    // ... then show only the desired one
    document.querySelectorAll(selector).forEach(elem => elem.classList.remove('hide'));
  }
</script>
secan
  • 2,622
  • 1
  • 7
  • 24
  • Brilliant. This is exactly what I needed. I know this may seem elementary to you, but for this pastor who is multitasking into javascript, you're an answer to prayer. Thank you so much for taking the time to show me through this! – imaginizer Dec 07 '20 at 15:06
  • Well, I am pretty sure you know JavaScript better than I know the Holy Scriptures. :)) Jokes aside, I am happy I could help. – secan Dec 07 '20 at 15:18
0

If you are beginner you should try using this code @secan use ES6 which is not easy for newbie to understand

 var n = document.getElementsByClassName("niv");
 var k = document.getElementsByClassName("kjv");
 var e = document.getElementsByClassName("esv");
   

//This hideTag and showTag is use to hide your niv,kjv,esv

function hideTag(tagName) {
    for(let i=0;i<tagName.length;i++){
        tagName[i].style.display = 'none'
    } 
}

function showTag(tagName) {
    for(let i=0;i<tagName.length;i++){
        tagName[i].style.display = 'block'
    } 
}
   
function niv() {
  showTag(n)
  hideTag(k)
  hideTag(e)
}

function kjv() {
  showTag(k)
  hideTag(n)
  hideTag(e)
}

function esv() {
  showTag(e)
  hideTag(k)
  hideTag(n)
}
p.niv {display:block;}
p.esv {display:none;}
p.kjv {display:none;}
<p>Click the buttons to display your preferred Bible version:</p>

<button onclick="niv()">NIV</button>
<button onclick="kjv()">KJV</button>
<button onclick="esv()">ESV</button>

<p>Regular paragraph, blah blah</p>
<p class="niv">this NIV paragraph will become hidden when the KJV or ESV button is clicked</p>
<p class="niv">but this NIV paragraph stays visible even though I want it to be hidden too</p>
<p class="kjv">this KJV paragraph will become hidden when the NIV or ESV button is clicked</p>
<p class="kjv">but this KJV paragraph stays visible even though I want it to be hidden too</p>
<p class="esv">this ESV paragraph will become hidden when the KJV or NIV button is clicked</p>
<p class="esv">but this ESV paragraph stays visible even though I want it to be hidden too</p>
Isaac.mm
  • 76
  • 6
  • 1
    May I ask you why you consider ES6 syntax harder to understand than pre-ES6 ones, for newbies? My personal opinion is that it might be true the opposite: "seasoned" developer, who coded for a lot of time with the "old" syntax, might need some time to adapt to and adopt the new syntax but for newbies this is not a problem and the ES6 syntax itself is more clear/intuitive, IMVHO. – secan Dec 07 '20 at 15:42
  • Thanks Isaac.mm for your input. As a newbie who only works with code every "so often," I'm not into it deep enough to really understand what I'm doing, since I'm not really a web developer but just a guy who learns what I need to in order to accomplish a specific goal. You might say that I only know just enough to be dangerous! Thanks for taking the time to help me out! – imaginizer Dec 07 '20 at 16:33