Search code examples
jqueryhiddenvisible

Adding a "Show All" button to jQuery that collapses certain areas


I am attempting to put a button in my script that will expand all my collapsed elements. This button needs to:

  1. Toggle the arrows
  2. Toggle the collapsible areas
  3. Not change arrows/areas that have already been expanded
  4. Change text as it toggles the rest (from "Show All" to "Hide All")
  5. Work in SharePoint

The toggle on the arrows work when I click the button, and the initial change to "Hide All" works, but nothing else. What am I doing wrong? (The individual toggles work great when they're clicked.)

This is my CSS (to format the arrows), jQuery, and HTML:

$(document).ready(function(){
  $("span").removeClass("arrow2");
  $("span").removeClass("arrow4");
  $(".js-textEdit").text(function () {
    return $(this).text().replace("Hide", "Show"); 
  });
  $("p.showMe").nextUntil("span.endCollapse").hide();
  $("h2.showSec").nextUntil("h2").hide();
  $(".js-textEdit").submit(function(){
    var oldText = $(this).text();
    var newText = $(this).data('text');
    $(this).text(newText).data('text',oldText);
  });
  $("p.showMe").click(function(){
    $(this).nextUntil("span.endCollapse").toggle("fast");
    $(this).find("span.arrow1").toggleClass("arrow2");
    $(this).find(".js-textEdit").trigger("submit");
  });
  $("h2.showSec").click(function(){
      $(this).nextUntil("h2").toggle("fast");
      $(this).find("span.arrow3").toggleClass("arrow4");
  });
  $(".showAll").click(function(){
    $("*").find("span.arrow1").toggleClass("arrow2");
    $("*").find("span.arrow3").toggleClass("arrow4");
    $(this).find(".js-textEdit").text(function(){
      return $(this).text().replace("Show", "Hide");
    });
    $("p.showMe").nextUntil("span.endCollapse").show("fast");
    $("h2.showSec").nextUntil("h2").show("fast");
    $(this).toggleClass("hideAll");
  });
  $(".hideAll").click(function(){
    $("*").find("span.arrow2").toggleClass("arrow1");
    $("*").find("span.arrow4").toggleClass("arrow3");
    $(this).find(".js-textEdit").text(function(){
      return $(this).text().replace("Hide", "Show");
    });
    $("p.showMe").nextUntil("span.endCollapse").hide("fast");
    $("h2.showSec").nextUntil("h2").hide("fast");
    $(this).toggleClass("showAll");
  });
});
.arrow1 {
  line height: 0%;
  width: 0px;
  height: 0px;
  border-style: solid;
  border-width: 5px 0 5px 5px;
  border-color: transparent transparent transparent #000000;
  display: inline-block;
  margin: 0px 11px 0px 12px;
}

.arrow2 {
  width: 0px;
  height: 0px;
  border-style: solid;
  border-width: 5px 5px 5px 5px;
  border-color: #000000 transparent transparent transparent ;
  margin: 0 11px 0px 12px;
}
.arrow3 {
    line height: 0%;
  width: 0px;
  height: 0px;
  border-style: solid;
  border-width: 7px 0 7px 7px;
  border-color: transparent transparent transparent #000000;
  display: inline-block;
  margin: 0px 11px 0px 12px;
}
.arrow4 {
  width: 0px;
  height: 0px;
  border-style: solid;
  border-width: 7px 7px 7px 7px;
  border-color: #000000 transparent transparent transparent ;
  margin: 0 11px 0px 12px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class="showAll" type="button"><span class="js-textEdit" data-text="Hide All">Show All</span></button>
<p class="caption">The system displays the [screen name].</p> 
<p class="showMe">
   <span class="js-textEdit" data-text="Hide screen">Show screen</span><span class="arrow1"></span></p>
<p>InsertImageHere&#160;</p>
<span class="endCollapse"></span>
<h2 class="showSec">Section</h2>
<p>Content</p>
<h2>Non-Collapse Section</h2>
<p>Content</p>

I did also try this:

$(".showAll").click(function(){
    if ($(p.showMe).nextUntil("span.endCollapse").is(":visible"){
        $(this).nextUntil("span.endCollapse").toggle("fast");
        $(this).find("span.arrow1").toggleClass("arrow2");
        $(this).find(".js-textEdit").trigger("submit");
    });
});

Solution

  • I found a solution by making the "show all" button into two, and by using the :visible selector for the first action. It took me a while to find something that would only trigger the text swap if it hadn't already been changed, but :contains('Show') (or 'Hide') worked perfectly when paired with .trigger("submit").

    $(".expand").click(function(){
        $("*").find("span.arrow1").addClass("arrow2");
        $("*").find("span.arrow3").addClass("arrow4");
        $(".showMe").nextUntil(":visible").show("fast");
        $(".showSec").nextUntil(":visible").show("fast");
        $(".js-textEdit:contains('Show')").trigger("submit");
    });
    $(".collapse").click(function(){
        $("span").removeClass("arrow2");
        $("span").removeClass("arrow4");
        $(".showMe").nextUntil("span.endCollapse").hide("fast");
        $(".showSec").nextUntil("h2").hide("fast");
        $(".js-textEdit:contains('Hide')").trigger("submit");
    });
    <button class="expand" type="button">Show All</button>
    <button class="collapse" type="button">Hide All</button>