2

I'm using this basic code to hide one block of text and display another and it works well but what do I need to do to have a second click close the text again? Right now it stays open until something else is selected so one or another is always open after the first selection. I added some close links that work but would prefer to click on the title (or anything else) to close it again. Other similar questions seem to either use jQuery or they hide the link after it has been selected.

function showhide(id) {
  if (document.getElementById) {
    var divid = document.getElementById(id);
    var divs = document.getElementsByClassName('hide');
    for (var i = 0; i < divs.length; i++) {
      divs[i].style.display = 'none';
    }
    divid.style.display = 'block';
  }
  return false;
}
<a onclick="showhide('toggle1');">
  <h4>-> Title 1</h4>
</a>
<div class="hide" id="toggle1" style="display:none">
  Some text here. <a onclick="showhide('verify');">close</a>
</div>

<a onclick="showhide('toggle2');">
  <h4>-> Title 2</h4>
</a>
<div class="hide" id="toggle2" style="display:none">
  Other text here. <a onclick="showhide('verify');">close</a>
</div>
DonP
  • 725
  • 1
  • 8
  • 27
  • My original code had a typo: close should have been close but a moot point now with the answers below. – DonP Aug 07 '17 at 02:09
  • Possible duplicate of [JavaScript hide/show element](https://stackoverflow.com/questions/6242976/javascript-hide-show-element) – slevy1 Aug 07 '17 at 08:16

3 Answers3

5

The code below will check to see if the element that is associated with the link that has been clicked is already visible, and if so - will hide it along with the other element. No need for any close links.

Also, as @KScandrett pointed out, it's redundant to check if the browser supports document.getElementById given that all browsers support it, so I haven't carried that over to this answer.

function showhide(id) {
    var divid = document.getElementById(id);
    var divs = document.getElementsByClassName('hide');
    var showElement = true;
    if (divid.style.display === 'block') {
        showElement = false;
    }
    for (var i = 0; i < divs.length; i++) {
        divs[i].style.display = 'none';
    }
    if (showElement) {
        divid.style.display = 'block';
    }
    return false;
}
<a onclick="showhide('toggle1');">
  <h4>-> Title 1</h4>
</a>
<div class="hide" id="toggle1" style="display:none">
  Some text here.
</div>

<a onclick="showhide('toggle2');">
  <h4>-> Title 2</h4>
</a>
<div class="hide" id="toggle2" style="display:none">
  Other text here.
</div>
abagshaw
  • 6,162
  • 4
  • 38
  • 76
  • Thank you but this seems to work exactly like the one I started with. It does not close one unless I open another but I am trying to find a way to close all. – DonP Aug 07 '17 at 00:36
  • It seems to work for me (clicking an open element closes it), is that not what you're looking for? – abagshaw Aug 07 '17 at 00:40
  • Yes, that's exactly what I am looking for but just tried refreshing several more times and it suddenly works so apparently it was caching the original version. Also, I'm using style="display:none" in the div but can the JavaScript be made to NOT show them by default? – DonP Aug 07 '17 at 00:49
  • Not exactly sure what you mean, the best way to have them not shown by default is what you've done (to use `style="display:none"`) or you could use a class such as `hidden` and specify `.hidden{display:none;}` in your CSS – abagshaw Aug 07 '17 at 01:00
  • 2
    The `if (document.getElementById)` check is unnecessary. All browsers support that function – K Scandrett Aug 07 '17 at 01:59
  • @KScandrett Thanks, I missed that. Answer has been edited. – abagshaw Aug 07 '17 at 02:01
1

This code resolves the problem borrowing the technique suggested by @abagshaw with respect to the toggling (comments mine). This solution like my previous one dynamically associates each anchor's click event with an action. Using the JavaScript library jQuery allows for writing less and more robust code.

$(document).ready(function() {

  function showhide(obj) {
    var showFlag = true;

    // first: setup for toggle
    if (obj.css("display") === 'block') {
      showFlag = !showFlag;
    }

    // then: hide all divs ...
    $("div").each(function() {
      $(this).hide("slow");
    });


    // ... and show respective div if showFlag is true
    if (showFlag) {
      obj.toggle("slow");
    }
  }

  $(".hold").each(function(dex) {
    $(this).click(function() {
      let e = $(".hide").eq(dex);
      showhide(e);
    }); 
  }); 
});
div.hide {
  display: none;
}

ul {
  font-size: 18pt;
  list-style-type: none;
}

li {
  padding-bottom: 30px;
}

li:before {
  content: "->";
  /* looks like bullets */
  padding-right: 10px;
  color: green;
  /* Or a color you prefer */
}

a.hold {
  color: #f0c;
  text-decoration: none;
}

a.hold:hover {
  text-decoration: overline;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
  <li><a class="hold">Title 1</a>
    <div class="hide" id="toggle1">
      Some text here.
    </div>
  </li>


  <li><a class="hold">Title 2</a>
    <div class="hide" id="toggle2">
      Other text here.
    </div>
  </li>
</ul>
slevy1
  • 3,797
  • 2
  • 27
  • 33
  • 1
    Thank you and I'll give it a try when I'm back to that area of the site as it appears that it will do all that is needed. However, I prefer not to use jQuery for something so basic as it would be the only call to it on the site. If it were otherwise it use (and it may be at some future date), then no problem. – DonP Aug 10 '17 at 22:27
0
function showhide(id) {
    var divid = document.getElementById(id);
    var divs = document.getElementsByClassName('hide');

    if (divid.style.display === 'none') {
        divid.style.display = 'block';
    } else{
        divid.style.display = 'none';
    }

    for (var i = 0; i < divs.length; i++) {
        if(divs[i].id !== id)
            divs[i].style.display = 'none';
    }

    return false;
}