1

I have code below for an alphabetical index I am trying to create using HTML, CSS and JavaScript. Is it possible to make the letter panels close when another letter is clicked? Example: Click "A" and the A panel appears, but when you click "B" the B panel appears and the A panel stays visible. Is there anyway to closed the "A" panel when a different letter is clicked? Anything helps, cheers.

function myFunctionA() {
    document.getElementById("panelA").style.display = "block";
}
function myFunctionB() {
    document.getElementById("panelB").style.display = "block";
}
function myFunctionC() {
    document.getElementById("panelC").style.display = "block";
}
.alphabet {
    list-style-type: none;
    margin:0px auto 0;
    padding:0;
    cursor: pointer;
    width:100%;
    text-align:center;
}

.alphabet li {
    float:left;
    margin:0;
    padding:0;
    border-right:1px solid darkgrey;
    font-size: 13px;
    font-family:Verdana;
    -moz-box-sizing:border-box;
    color:black;
    display:inline-block;
    -webkit-box-sizing:border-box;
    -moz-box-sizing:border-box;
    box-sizing:border-box;
    width:3.84%;
}

.alphabet li:last-child {
    border-right: none;
}

.alphabet li:hover {
    color:#005bab;
    background-color: lightgrey;
}

#panelA, #panelB, #panelC {
    display: none;
}
#panelA, #panelB, #panelC, .flip {
    font-size: 16px;
    text-align: center;
    background-color:#fcfcfc;
    border-style:solid;
    border-width:1px;
    border-color:grey;
    color: black;
    margin: auto;
}
<div>
<ul class="alphabet">
                        <li class="flip" onclick="myFunctionA()">A</li>
                        <li class="flip" onclick="myFunctionB()">B</li>
                        <li class="flip" onclick="myFunctionC()">C</li>
                        <li>D</li>
                         <li>E</li>
                        <li>F</li>
                        <li>G</li>
                        <li>H</li>
                        <li>I</li>
                        <li>J</li>
                        <li>K</li>
                        <li>L</li>
                        <li>M</li>
                        <li>N</li>
                        <li>O</li>
                        <li>P</li>
                        <li>Q</li>
                        <li>R</li>
                        <li>S</li>
                        <li>T</li>
                        <li>U</li>
                        <li>V</li>
                        <li>W</li>
                        <li>X</li>
                        <li>Y</li>
                        <li>Z</li>
                    </ul>
  </div>
<br/>
<div id="panelA">
  <p>A</p>
</div>
<div id="panelB">
  <p>B</p>
</div>
<div id="panelC">
  <p>C</p>
</div>
  • Most of the answers here may "work", but are the wrong approach. There is no need for an event handler for each letter "button" and there is no need for explicit instructions to hide one thing while showing another. The correct approach is to default all the "panels" to be `display:none` and then just toggle the use of a "show" class that specifies `display:block`. Just a few lines of code is all you need. See my answer below for the simplest implementation that uses modern, standards compliant code. – Scott Marcus May 05 '17 at 19:45
  • @Display Name Did you solve the problem or you still need some help? – MaxZoom May 05 '17 at 21:47
  • @DisplayName Can you please mark Scotts answer as the accepted one? Thanks :) – Chris May 06 '17 at 12:06
  • @Chris Will do! –  May 08 '17 at 18:20

8 Answers8

2

We actually don't need any JavaScript to do this at all (but, I have provided a JavaScript solution below). Instead, we can leverage the CSS :target pseudo-class selector, which affects elements that are the target of a navigation (usually # locations in a document). It does require a bit more HTML and it doesn't allow for a panel to be closed when clicked a second time, but, in the end there is no JavaScript and it is more efficient because of that.

Take a look:

.alphabet {
        list-style-type: none;
        margin:0 auto 0;
        padding:0;
        cursor: pointer;
        width:100%;
        text-align:center;
}

.alphabet li {
        float:left;
        margin:0;
        padding:0;
        border-right:1px solid darkgrey;
        font-size: 13px;
        font-family:Verdana;
        color:black;
        display:inline-block;
        box-sizing:border-box;
        width:3.84%;
}

.alphabet li:last-child {
        border-right: none;
}

.alphabet li:hover {
        color:#005bab;
        background-color: lightgrey;
}
    
    /* ******************************************************************************** */
    
    a { text-decoration:none; }
    
    /* By default, don't show any panel */
    .flip > div.panel { display:none; }    

    /* This style will only be applied when a click to a target element occurs and
       it will affect the target element. */    
    div.panel:target {
      display:block;
      position:absolute;
      left:0;
      width:100%;
    }

    /* For the <li> and only the panel to be shown: */
    .flip, div.panel:target {
        display: block;
        font-size: 16px;
        text-align: center;
        background-color:#fcfcfc;
        border:1px solid grey;
        color: black;
    }
    
    /* ******************************************************************************** */
<ul class="alphabet">
      <li class="flip"><a href="#panelA">A</a><div id="panelA" class="panel"><p>A</p></div></li>
      <li class="flip"><a href="#panelB">B</a><div id="panelB" class="panel"><p>B</p></div></li>
      <li class="flip"><a href="#panelC">C</a><div id="panelC" class="panel"><p>C</p></div></li> 
      <li class="flip"><a href="#panelD">D</a><div id="panelD" class="panel"><p>D</p></div></li>
      <li class="flip"><a href="#panelE">E</a><div id="panelE" class="panel"><p>E</p></div></li>
      <li class="flip"><a href="#panelF">F</a><div id="panelF" class="panel"><p>F</p></div></li>   
      <li class="flip"><a href="#panelG">G</a><div id="panelG" class="panel"><p>G</p></div></li>
      <li class="flip"><a href="#panelH">H</a><div id="panelH" class="panel"><p>H</p></div></li>
      <li class="flip"><a href="#panelI">I</a><div id="panelI" class="panel"><p>I</p></div></li> 
      <li class="flip"><a href="#panelJ">J</a><div id="panelJ" class="panel"><p>J</p></div></li>
      <li class="flip"><a href="#panelK">K</a><div id="panelK" class="panel"><p>K</p></div></li>
      <li class="flip"><a href="#panelL">L</a><div id="panelL" class="panel"><p>L</p></div></li> 
      <li class="flip"><a href="#panelM">M</a><div id="panelM" class="panel"><p>M</p></div></li>
      <li class="flip"><a href="#panelN">N</a><div id="panelN" class="panel"><p>N</p></div></li>
      <li class="flip"><a href="#panelO">O</a><div id="panelO" class="panel"><p>O</p></div></li> 
      <li class="flip"><a href="#panelP">P</a><div id="panelP" class="panel"><p>P</p></div></li>
      <li class="flip"><a href="#panelQ">Q</a><div id="panelQ" class="panel"><p>Q</p></div></li>
      <li class="flip"><a href="#panelR">R</a><div id="panelR" class="panel"><p>R</p></div></li> 
      <li class="flip"><a href="#panelS">S</a><div id="panelS" class="panel"><p>S</p></div></li> 
      <li class="flip"><a href="#panelT">T</a><div id="panelT" class="panel"><p>T</p></div></li>
      <li class="flip"><a href="#panelU">U</a><div id="panelU" class="panel"><p>U</p></div></li>
      <li class="flip"><a href="#panelV">V</a><div id="panelV" class="panel"><p>V</p></div></li>
      <li class="flip"><a href="#panelW">W</a><div id="panelW" class="panel"><p>W</p></div></li>
      <li class="flip"><a href="#panelX">X</a><div id="panelX" class="panel"><p>X</p></div></li> 
      <li class="flip"><a href="#panelY">Y</a><div id="panelY" class="panel"><p>Y</p></div></li> 
      <li class="flip"><a href="#panelZ">Z</a><div id="panelZ" class="panel"><p>Z</p></div></li>
    </ul>

JavaScript Solution:

If we set up a class called "show" for example, we can apply it as needed and take it away as well using the element.classList.toggle() method. If all the panels default to being hidden, taking the "show" class away causes the style to go back to its default.

Also, by reorganizing the HTML structure and making some slight changes to the CSS, we can simplify the JavaScript significantly.

Lastly (FYI), the vendor-prefixed CSS you have (-moz-box-sizing: border-box;) can all be removed since box-sizing is well supported across all modern browsers.

// Get a "live" collection of all the open panels
var panels = document.getElementsByClassName("show");

// Get all the <li> elements into a collection and loop through them
Array.prototype.slice.call(document.querySelectorAll(".alphabet > li")).forEach(function(item){
  // Set each up to have a click event handler
  item.addEventListener("click", function(e){

    // Hide any previously opened panels exept the current one (if already opened)
    Array.prototype.slice.call(panels).forEach(function(pan){
      e.target.querySelector("div.panel") !== pan ? pan.classList.remove("show"): "";
    });

    // find the panel in the <li> and toggle its display
    item.querySelector("div.panel").classList.toggle("show");

  });
});
.alphabet {
    list-style-type: none;
    margin:0px auto 0;
    padding:0;
    cursor: pointer;
    width:100%;
    text-align:center;
}

.alphabet li {
    float:left;
    margin:0;
    padding:0;
    border-right:1px solid darkgrey;
    font-size: 13px;
    font-family:Verdana;
    color:black;
    display:inline-block;
    box-sizing:border-box;
    width:3.84%;
}

.alphabet li:last-child {
    border-right: none;
}

.alphabet li:hover {
    color:#005bab;
    background-color: lightgrey;
}

/* By default, don't show any panel */
.flip > div { display:none; }

/* For the <li> and only the panel to be shown: */
.flip, div.show {
    display: block;
    font-size: 16px;
    text-align: center;
    background-color:#fcfcfc;
    border-style:solid;
    border-width:1px;
    border-color:grey;
    color: black;
    margin: auto;
}

/* For the panel to be shown, position it correctly. */
div.show {
    position:absolute;
    left:0;
    width:100%;
}
<ul class="alphabet">
  <li class="flip">A<div class="panel"><p>A</p></div></li>
  <li class="flip">B<div class="panel"><p>B</p></div></li>
  <li class="flip">C<div class="panel"><p>C</p></div></li> 
  <li class="flip">D<div class="panel"><p>D</p></div></li>
  <li class="flip">E<div class="panel"><p>E</p></div></li>
  <li class="flip">F<div class="panel"><p>F</p></div></li>   
  <li class="flip">G<div class="panel"><p>G</p></div></li>
  <li class="flip">H<div class="panel"><p>H</p></div></li>
  <li class="flip">I<div class="panel"><p>I</p></div></li> 
  <li class="flip">J<div class="panel"><p>J</p></div></li>
  <li class="flip">K<div class="panel"><p>K</p></div></li>
  <li class="flip">L<div class="panel"><p>L</p></div></li> 
  <li class="flip">M<div class="panel"><p>M</p></div></li>
  <li class="flip">N<div class="panel"><p>N</p></div></li>
  <li class="flip">O<div class="panel"><p>O</p></div></li> 
  <li class="flip">P<div class="panel"><p>P</p></div></li>
  <li class="flip">Q<div class="panel"><p>Q</p></div></li>
  <li class="flip">R<div class="panel"><p>R</p></div></li> 
  <li class="flip">S<div class="panel"><p>S</p></div></li> 
  <li class="flip">T<div class="panel"><p>T</p></div></li>
  <li class="flip">U<div class="panel"><p>U</p></div></li>
  <li class="flip">V<div class="panel"><p>V</p></div></li> 
  <li class="flip">W<div class="panel"><p>W</p></div></li>
  <li class="flip">X<div class="panel"><p>X</p></div></li>
  <li class="flip">Y<div class="panel"><p>Y</p></div></li> 
  <li class="flip">Z<div class="panel"><p>Z</p></div></li>  
</ul>
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
  • I love the toggle() thinking, the only problem is because all you do is toggle(), there are a TON of bugs. You are just displaying the div over the others, so if you toggle Z and then anything else, it will always only display Z. Also if you click any letter twice, whatever else you toggled before will show. In short, you need to toggle off, you can't just toggle everything on. – jeremye May 05 '17 at 19:16
  • @ScottMarcus You commented about one answer's efficiency in toggling EVERYTHING off, when most divs were off (all but one, always). So what you can do is say `if (div.style.display !== 'none') {div.style.display = 'none'}` which would still loop through everything, but only change what is visible. – jeremye May 05 '17 at 19:23
  • @MaxZoom it is because the H div is being displayed on top of the B div. – jeremye May 05 '17 at 19:24
  • @JeremyE. Issue corrected by shutting off all previously shown panels (except the current one if already shown). 3 extra lines of code. – Scott Marcus May 05 '17 at 19:31
  • @MaxZoom Not sure what you mean by that. – Scott Marcus May 05 '17 at 19:31
  • @JeremyE. It's better to stay away from dynamically creating inline styles (using the `style` property) because it requires you to think about styling one property at a time and produces styles that can only be overwritten by replacing the inline style. Instead, it's much simpler to use classes. Then the `element.classList` object provides super easy access to classes via `add`, `remove` and `toggle`. – Scott Marcus May 05 '17 at 19:42
  • @ScottMarcus I agree with using classes to define styles 100%, it's just a lot simpler to say `div.style.display = 'none'` than CSS: `.someClass {display: none;}` JS: `div.classList.toggle("someClass")` – jeremye May 05 '17 at 19:45
  • @JeremyE. Yes, but remember, Stack Overflow is a knowledge base. We should always strive to create answers that go beyond solving the problem that the OP poses. We should answer the questions using the most appropriate code, otherwise we perpetuate not following standards and poor coding habits. That's why, for example, my answer removes the inline HTML event handling attributes (`onclick`) and the outdated vendor prefixed `-moz-box-sizing`. The OP didn't ask about those, but they should no longer be used. – Scott Marcus May 05 '17 at 19:47
1

you need to change this

function myFunctionA() {
    document.getElementById("panelA").style.display = "block";
}
function myFunctionB() {
    document.getElementById("panelB").style.display = "block";
}
function myFunctionC() {
    document.getElementById("panelC").style.display = "block";
}

to this

function myFunctionA() {
    document.getElementById("panelA").style.display = "block";
    document.getElementById("panelB").style.display = "none";
    document.getElementById("panelC").style.display = "none";
}
function myFunctionB() {
    document.getElementById("panelB").style.display = "block";
    document.getElementById("panelA").style.display = "none";
    document.getElementById("panelC").style.display = "none";
}
function myFunctionC() {
    document.getElementById("panelC").style.display = "block";
    document.getElementById("panelB").style.display = "none";
    document.getElementById("panelA").style.display = "none";
}

if you will use all the alphabet I suggest this code

function myFunctionA() {
            ClearAllPanel();
    document.getElementById("panelB").style.display = "block";

}
function myFunctionB() {
    ClearAllPanel();
    document.getElementById("panelB").style.display = "block";
}
function myFunctionC() {
    ClearAllPanel();
    document.getElementById("panelC").style.display = "block";
}
function ClearAllPanel(){
    for (var i = 65; i <=  90; i++) {
        document.getElementById("panel"+String.fromCharCode(i)).style.display = "none";
    }
}
  • No, no no. You don't need multiple click event handlers (especially ones that are essentially the same) at all. See my answer. – Scott Marcus May 05 '17 at 18:57
  • Cannot for the life of me understand why this answer is being up voted. This solution requires no less than 30 functions with over 90 lines of nearly identical code. It relies on creating dynamic inline styles instead of using classes and is incredibly inefficient. – Scott Marcus May 05 '17 at 19:14
  • You should not repeat the code as it is harder to maintain change in multiple places. See DRY rule. – MaxZoom May 05 '17 at 19:18
  • 1
    @BilelKorbosli Remember that Stack Overflow is a knowledge base. Answers should always strive to be "correct" in most possible ways. If the OP is doing something wrong in the first place, the answer shouldn't perpetuate it. – Scott Marcus May 05 '17 at 19:33
1

HTML class attribute will be very helpful for your case

  1. Add a class for all panels ex: panel.
  2. on click on the alphabet a. hide all panels ( all elements with class panel ) b. then show the panel with the id with the same clicked alphabet.

Example:

function showPanel(name) {
    hideAllPanels();
    document.getElementById("panel-"+ name).style.display = "block";
}
var panels = document.getElementsByClassName('panel');
function hideAllPanels () {
  var i;
  for (i = 0; i < panels.length; i+= 1){
    panels[i].style.display = "none";
  }
}
.alphabet {
    list-style-type: none;
    margin:0px auto 0;
    padding:0;
    cursor: pointer;
    width:100%;
    text-align:center;
}

.alphabet li {
    float:left;
    margin:0;
    padding:0;
    border-right:1px solid darkgrey;
    font-size: 13px;
    font-family:Verdana;
    -moz-box-sizing:border-box;
    color:black;
    display:inline-block;
    -webkit-box-sizing:border-box;
    -moz-box-sizing:border-box;
    box-sizing:border-box;
    width:3.84%;
}

.alphabet li:last-child {
    border-right: none;
}

.alphabet li:hover {
    color:#005bab;
    background-color: lightgrey;
}

.panel{
    display: none;
}
.panel, .flip {
    font-size: 16px;
    text-align: center;
    background-color:#fcfcfc;
    border-style:solid;
    border-width:1px;
    border-color:grey;
    color: black;
    margin: auto;
}
<div>
<ul class="alphabet">
                        <li class="flip" onclick="showPanel('a')">A</li>
                        <li class="flip" onclick="showPanel('b')">B</li>
                        <li class="flip" onclick="showPanel('c')">C</li>
                        <li>D</li>
                         <li>E</li>
                        <li>F</li>
                        <li>G</li>
                        <li>H</li>
                        <li>I</li>
                        <li>J</li>
                        <li>K</li>
                        <li>L</li>
                        <li>M</li>
                        <li>N</li>
                        <li>O</li>
                        <li>P</li>
                        <li>Q</li>
                        <li>R</li>
                        <li>S</li>
                        <li>T</li>
                        <li>U</li>
                        <li>V</li>
                        <li>W</li>
                        <li>X</li>
                        <li>Y</li>
                        <li>Z</li>
                    </ul>
  </div>
<br/>
<div id="panel-a" class="panel">
  <p>A</p>
</div>
<div id="panel-b" class="panel">
  <p>B</p>
</div>
<div id="panel-c" class="panel">
  <p>C</p>
</div>
Mohamed Abbas
  • 2,228
  • 1
  • 11
  • 19
  • No reason to have dedicated "hide" and "show" functions. Default all the panels to be hidden and then just toggle the "show" style. See my answer. – Scott Marcus May 05 '17 at 18:59
  • @ScottMarcus What is the big difference! you also make a lopp over all elements ? – Mohamed Abbas May 05 '17 at 20:22
  • The difference is that all you need to do to hide all the panels is this CSS `.panel { display:none; }`. My code has a loop to hide only previously opened panels. Your code relies on creating dynamic inline styles (which are not recommended) instead of using classes (which are). – Scott Marcus May 05 '17 at 20:25
  • I am already use this `.panel { display:none; }. ` check my answer again please. But i got your opinion about the inline style. Thanks :) – Mohamed Abbas May 05 '17 at 20:32
  • I guess the point is that you don't need to hide all panels via JavaScript. You only need to hide the ones that are currently showing. Interacting with DOM elements via JavaScript is very inefficient as changes to an element often trigger "repaints" and "reflows". Even reading properties of DOM objects (without making changes) has an impact, so you should always find ways to "touch" them less. – Scott Marcus May 05 '17 at 20:34
  • @ScottMarcus i got it. Thanks for your comment. – Mohamed Abbas May 05 '17 at 20:36
1

Much shorter version in pure JavaScript:

function letterChange() {
  var panelId = 'panel' + this.innerText;
  var panels = document.querySelectorAll('.js-div');
  [].forEach.call(panels, function(e) {
    if (e.id == panelId)
       e.style.display = "block";
    else
       e.style.display = "none";
  });     
}

// Add click event listener
var lis = document.querySelectorAll('.flip');
[].forEach.call(lis, function(e) {
  e.addEventListener("click", letterChange);
});
.alphabet {
  list-style-type: none;
  margin: 0px auto 0;
  padding: 0;
  cursor: pointer;
  width: 100%;
  text-align: center;
}

.alphabet li {
  float: left;
  margin: 0;
  padding: 0;
  border-right: 1px solid darkgrey;
  font-size: 13px;
  font-family: Verdana;
  -moz-box-sizing: border-box;
  color: black;
  display: inline-block;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  width: 3.84%;
}

.alphabet li:last-child {
  border-right: none;
}

.alphabet li:hover {
  color: #005bab;
  background-color: lightgrey;
}

#panelA,
#panelB,
#panelC {
  display: none;
}

#panelA,
#panelB,
#panelC,
.flip {
  font-size: 16px;
  text-align: center;
  background-color: #fcfcfc;
  border-style: solid;
  border-width: 1px;
  border-color: grey;
  color: black;
  margin: auto;
}
<div>
  <ul class="alphabet">
    <li class="flip">A</li>
    <li class="flip">B</li>
    <li class="flip">C</li>
    <li>D</li>
    <li>E</li>
    <li>F</li>
    <li>G</li>
    <li>H</li>
    <li>I</li>
    <li>J</li>
    <li>K</li>
    <li>L</li>
    <li>M</li>
    <li>N</li>
    <li>O</li>
    <li>P</li>
    <li>Q</li>
    <li>R</li>
    <li>S</li>
    <li>T</li>
    <li>U</li>
    <li>V</li>
    <li>W</li>
    <li>X</li>
    <li>Y</li>
    <li>Z</li>
  </ul>
</div>
<br/>
<div id="panelA" class="js-div">
  <p>A</p>
</div>
<div id="panelB" class="js-div">
  <p>B</p>
</div>
<div id="panelC" class="js-div">
  <p>C</p>
</div>
MaxZoom
  • 7,619
  • 5
  • 28
  • 44
  • The JavaScript can be event much simpler than that. No to mention that your code won't close a panel if you click on the letter of an already opened panel. See my answer. – Scott Marcus May 05 '17 at 18:53
  • Now your solution is even more complex than before. – Scott Marcus May 05 '17 at 19:09
  • 1
    Author only wants to close `A` panel when other letter is clicked. The code is well modularized and pretty easy to follow or/and change. I do not see any complexity here. – MaxZoom May 05 '17 at 21:57
1

Below is a much shorter solution to what you were doing that doesn't require you to write a new function or a new panel div for every letter.

Here, you merely change the innerHTML of the panel div to whatever letter is clicked.

Edit: I'll add some more information to make this answer a little more helpful.

If you need other words to show in the div that aren't just the innerHTML of what is clicked, obviously this solution wouldn't work, and you would need to set display to none for all the divs that you do not want to show, as many answers here suggested.

What I do hope people can learn from this, though, is that you don't need to set everything individually, and anytime you find yourself repeating the same thing with minor changes, there is a more efficient way. I will add a Demo #2 to the bottom to show how you can efficiently set all the undesired divs to display: none; with one function.

Demo

let letters = document.querySelectorAll("#alphabet li");

for (i = 0; i < letters.length; i++){
  letters[i].addEventListener('click', function(){
    document.querySelector("#panel p").innerHTML = this.innerHTML;
    document.querySelector("#panel").style.display = 'block';
  })
}
#alphabet {
    list-style-type: none;
    margin:0px auto 0;
    padding:0;
    cursor: pointer;
    width:100%;
    text-align:center;
}

#alphabet li {
    float:left;
    margin:0;
    padding:0;
    border-right:1px solid darkgrey;
    font-size: 13px;
    font-family:Verdana;
    -moz-box-sizing:border-box;
    color:black;
    display:inline-block;
    -webkit-box-sizing:border-box;
    -moz-box-sizing:border-box;
    box-sizing:border-box;
    width:3.84%;
}

#alphabet li:last-child {
    border-right: none;
}

#alphabet li:hover {
    color:#005bab;
    background-color: lightgrey;
}

#panel {
    display: none;
    font-size: 16px;
    text-align: center;
    background-color:#fcfcfc;
    border-style:solid;
    border-width:1px;
    border-color:grey;
    color: black;
    margin: auto;
}
<div>
<ul id="alphabet">
      <li>A</li>
      <li>B</li>
      <li>C</li>
      <li>D</li>
      <li>E</li>
      <li>F</li>
      <li>G</li>
      <li>H</li>
      <li>I</li>
      <li>J</li>
      <li>K</li>
      <li>L</li>
      <li>M</li>
      <li>N</li>
      <li>O</li>
      <li>P</li>
      <li>Q</li>
      <li>R</li>
      <li>S</li>
      <li>T</li>
      <li>U</li>
      <li>V</li>
      <li>W</li>
      <li>X</li>
      <li>Y</li>
      <li>Z</li>
  </ul>
</div>
<br/>
<div id="panel">
  <p></p>
</div>

Demo #2

let letters = document.querySelectorAll("#alphabet li");

for (i = 0; i < letters.length; i++){
  letters[i].addEventListener('click', function(){
    let letter = this.innerHTML;
    
    let panels = document.getElementsByClassName('panel');
    for (i = 0; i < panels.length; i++){
      if (panels[i].id !== letter){
        panels[i].style.display = 'none';
      }
      else {
        panels[i].style.display = 'block';
      }
    }
  })
}
#alphabet {
    list-style-type: none;
    margin:0px auto 0;
    padding:0;
    cursor: pointer;
    width:100%;
    text-align:center;
}

#alphabet li {
    float:left;
    margin:0;
    padding:0;
    border-right:1px solid darkgrey;
    font-size: 13px;
    font-family:Verdana;
    -moz-box-sizing:border-box;
    color:black;
    display:inline-block;
    -webkit-box-sizing:border-box;
    -moz-box-sizing:border-box;
    box-sizing:border-box;
    width:3.84%;
}

#alphabet li:last-child {
    border-right: none;
}

#alphabet li:hover {
    color:#005bab;
    background-color: lightgrey;
}

.panel {
    display: none;
    font-size: 16px;
    text-align: center;
    background-color:#fcfcfc;
    border-style:solid;
    border-width:1px;
    border-color:grey;
    color: black;
    margin: auto;
}
<div>
<ul id="alphabet">
      <li>A</li>
      <li>B</li>
      <li>C</li>
      <li>D</li>
      <li>E</li>
      <li>F</li>
      <li>G</li>
      <li>H</li>
      <li>I</li>
      <li>J</li>
      <li>K</li>
      <li>L</li>
      <li>M</li>
      <li>N</li>
      <li>O</li>
      <li>P</li>
      <li>Q</li>
      <li>R</li>
      <li>S</li>
      <li>T</li>
      <li>U</li>
      <li>V</li>
      <li>W</li>
      <li>X</li>
      <li>Y</li>
      <li>Z</li>
  </ul>
</div>
<br/>
<div class="panel" id="A">
  <p>Some text for link A</p>
</div>
<div class="panel" id="B">
  <p>Some text for link B</p>
</div>
<div class="panel" id="C">
  <p>Some text for link C</p>
</div>
<div class="panel" id="D">
  <p>Some text for link D</p>
</div>
<div class="panel" id="E">
  <p>Some text for link E</p>
</div>
<div class="panel" id="F">
  <p>Some text for link F</p>
</div>
<div class="panel" id="G">
  <p>Some text for link G</p>
</div>
<div class="panel" id="H">
  <p>Some text for link H</p>
</div>
<div class="panel" id="I">
  <p>Some text for link I</p>
</div>
<div class="panel" id="J">
  <p>Some text for link J</p>
</div>
<div class="panel" id="K">
  <p>Some text for link K</p>
</div>
<div class="panel" id="L">
  <p>Some text for link L</p>
</div>
<div class="panel" id="M">
  <p>Some text for link M</p>
</div>
<div class="panel" id="N">
  <p>Some text for link N</p>
</div>
<div class="panel" id="O">
  <p>Some text for link O</p>
</div>
<div class="panel" id="P">
  <p>Some text for link P</p>
</div>
<div class="panel" id="Q">
  <p>Some text for link Q</p>
</div>
<div class="panel" id="R">
  <p>Some text for link R</p>
</div>
<div class="panel" id="S">
  <p>Some text for link S</p>
</div>
<div class="panel" id="T">
  <p>Some text for link T</p>
</div>
<div class="panel" id="U">
  <p>Some text for link U</p>
</div>
<div class="panel" id="V">
  <p>Some text for link V</p>
</div>
<div class="panel" id="W">
  <p>Some text for link W</p>
</div>
<div class="panel" id="X">
  <p>Some text for link X</p>
</div>
<div class="panel" id="Y">
  <p>Some text for link Y</p>
</div>
<div class="panel" id="Z">
  <p>Some text for link Z</p>
</div>
jeremye
  • 1,368
  • 9
  • 19
  • I think I saw this question about 25 seconds after it was posted, and when I finished writing my snippet, there were 8 answers, :). What a time to be alive. – jeremye May 05 '17 at 18:52
  • While your idea of making a "template" to use as the contents for each panel certainly works. In reality, it won't pan out when each panel's contents varies. – Scott Marcus May 05 '17 at 18:56
  • @ScottMarcus yes very true –  May 05 '17 at 18:57
  • @ScottMarcus, of course, I was basing it off of the HTML specified in the question to show one efficient possibility, but yeah, I just added another demo for that situation. – jeremye May 05 '17 at 19:11
-1

You must set as visible one and not visible others, for example:

document.getElementById("panelA").style.display = "block";
document.getElementById("panelB").style.display = "none";
Fran Cerezo
  • 940
  • 3
  • 8
  • 19
  • No you do not have to do that. Just default all the panels to be hidden and then just toggle the use of a class that shows the specific one. – Scott Marcus May 05 '17 at 19:01
  • Yes, you are right, but i wanted to guide him, not give solved code. On the other hand he is using pure Javascript, and as i remember toggle is a jQuery function. Greetings, – Fran Cerezo May 05 '17 at 19:09
  • There is a JQuery `toggle()` method, but there is also the standard `element.classList.toggle()`, which is not JQuery - that is what I'm using and suggesting. No JQuery needed. Your solution is not a good guide for a couple of reasons: 1) It relies on creating dynamic inline styles (Inline styles should be avoided) and 2) it does twice the work than is actually needed if you just default all the panels to be `display:none` from the start. – Scott Marcus May 05 '17 at 19:12
  • Yes, i know you are right, i was simplifying because i noticed he did not know how to hide an element. And first step is always needed ;) And honestly, i did not know element.classList.toggle() ! Thank you @Scott Marcus – Fran Cerezo May 05 '17 at 19:21
-1
function myFunctionA() {
    document.getElementById("panelA").style.display = "block";
    document.getElementById("panelB").style.display = "none";
    document.getElementById("panelC").style.display = "none";
}
function myFunctionB() {
    document.getElementById("panelB").style.display = "block";
    document.getElementById("panelA").style.display = "none";
    document.getElementById("panelC").style.display = "none";
}
function myFunctionC() {
    document.getElementById("panelC").style.display = "block";
    document.getElementById("panelA").style.display = "none";
    document.getElementById("panelB").style.display = "none";
}
oompahlumpa
  • 495
  • 2
  • 10
  • No, no no. You don't need multiple click event handlers (especially ones that are essentially the same) at all. See my answer. – Scott Marcus May 05 '17 at 18:58
  • He never said he was using Jquery. If he had, I would have said to use toggle(), but he didn't so... – oompahlumpa May 05 '17 at 23:14
  • `.toggle()` is not only a method in JQuery, but it is also a DOM standard method of `element.classList` and that is what I'm using - - no JQuery. See: https://developer.mozilla.org/en-US/docs/Web/API/Element/classList – Scott Marcus May 05 '17 at 23:19
  • Learned something new.. Thanks! – oompahlumpa May 05 '17 at 23:25
-1

what if you do something like this :

function myFunctionA() {
    document.getElementById("panelA").style.display = "block";
    document.getElementById("panelB").style.display = "none";
    document.getElementById("panelC").style.display = "none";
}
function myFunctionB() {
    document.getElementById("panelB").style.display = "block";
    document.getElementById("panelA").style.display = "none";
    document.getElementById("panelC").style.display = "none";
}
function myFunctionC() {
    document.getElementById("panelC").style.display = "block";
    document.getElementById("panelA").style.display = "none";
    document.getElementById("panelB").style.display = "none";
}
.alphabet {
    list-style-type: none;
    margin:0px auto 0;
    padding:0;
    cursor: pointer;
    width:100%;
    text-align:center;
}

.alphabet li {
    float:left;
    margin:0;
    padding:0;
    border-right:1px solid darkgrey;
    font-size: 13px;
    font-family:Verdana;
    -moz-box-sizing:border-box;
    color:black;
    display:inline-block;
    -webkit-box-sizing:border-box;
    -moz-box-sizing:border-box;
    box-sizing:border-box;
    width:3.84%;
}

.alphabet li:last-child {
    border-right: none;
}

.alphabet li:hover {
    color:#005bab;
    background-color: lightgrey;
}

#panelA, #panelB, #panelC {
    display: none;
}
#panelA, #panelB, #panelC, .flip {
    font-size: 16px;
    text-align: center;
    background-color:#fcfcfc;
    border-style:solid;
    border-width:1px;
    border-color:grey;
    color: black;
    margin: auto;
}
<div>
<ul class="alphabet">
                        <li class="flip" onclick="myFunctionA()">A</li>
                        <li class="flip" onclick="myFunctionB()">B</li>
                        <li class="flip" onclick="myFunctionC()">C</li>
                        <li>D</li>
                         <li>E</li>
                        <li>F</li>
                        <li>G</li>
                        <li>H</li>
                        <li>I</li>
                        <li>J</li>
                        <li>K</li>
                        <li>L</li>
                        <li>M</li>
                        <li>N</li>
                        <li>O</li>
                        <li>P</li>
                        <li>Q</li>
                        <li>R</li>
                        <li>S</li>
                        <li>T</li>
                        <li>U</li>
                        <li>V</li>
                        <li>W</li>
                        <li>X</li>
                        <li>Y</li>
                        <li>Z</li>
                    </ul>
  </div>
<br/>
<div id="panelA">
  <p>A</p>
</div>
<div id="panelB">
  <p>B</p>
</div>
<div id="panelC">
  <p>C</p>
</div>
Mehdi Karimi
  • 528
  • 4
  • 25
  • No, no no. You don't need multiple click event handlers (especially ones that are essentially the same) at all. See my answer. – Scott Marcus May 05 '17 at 18:58