Patrick Manser
Patrick Manser

Reputation: 1183

Open one element and close all others if open

I have a snippet for some buttons that show more content if you click on them and if you click on them the second time they could shoot a call-to-action before closing. All working fine, but if I click on a closed button then I want all other buttons to close (if they're open).

$('.contact-btn').click(function() {
  if ($(this).hasClass('mobile-open') &&
      !$('#desktop-indicator').is(':visible')) {
    console.log('call-to-action');
    return;
  }
  $(this).find('.contact-text').toggleClass('show');
  if ($(this).find('.contact-text').hasClass('show')) {
    var width = $(this).find('.contact-text')[0].scrollWidth + 55;
    $(this).find('.contact-text').css('max-width',width);
    if ($(this).hasClass('mobile-open') &&
        $('#phone-indicator').is(':visible')) {
      console.log('call-to-action');
      return;
    } else if ($('#desktop-indicator').is(':visible') ||
        $(this).hasClass('footer')) {
      console.log('open');
    }
  } else {
    $(this).find('.contact-text').css('max-width',0);
    if ($('#desktop-indicator').is(':visible') ||
        $(this).hasClass('footer')) {
      console.log('call-to-action');
    }
  }
});
.wrapper {
  display: flex;
  flex-flow: row nowrap;
}

.contact-btn {
  margin: 1rem;
  padding: 1rem;
  background: red;
  color: #FFF;
  display: inline-block;
  width: auto;
  cursor: pointer;
  border: none;
}

.phone {
  white-space: nowrap;
  float: left;
}
.contact-text {
  width: auto;
  overflow: hidden;
  white-space: nowrap;
  float: left;
  visibility: 0;
  padding-left: 0;
  max-width: 0;
  transition: max-width 400ms ease-in-out, padding 400ms ease-in-out;
  &.show {
    padding-left: .5rem;
  }
}

@media (max-width: 479px) {
  .wrapper {
    flex-flow: column nowrap;
    align-items: flex-end;
  }
  .contact-btn.mobile-open > .contact-text {
    visibility: visible !important;
    opacity: 1 !important;
    max-width: 200px !important;
    padding-left: .5rem;
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
  <button class="contact-btn mobile-open">
    <span class="phone"><strong>KLICK</strong></span>
    <span class="contact-text">078 800 70 70</span>
  </button>
  <button class="contact-btn footer">
    <span class="phone"><strong>KLICK</strong></span>
    <span class="contact-text">078 800 70 70</span>
  </button>
  <button class="contact-btn footer">
    <span class="phone"><strong>KLICK</strong></span>
    <span class="contact-text">078 800 70 70</span>
  </button>
  <div id="phone-indicator" class="hidden-sm-up"></div>
  <div id="desktop-indicator" class="hidden-lg-down"></div>
</div>

I played around with placing around the following line(s):

$('.contact-text').not($(this).find('.contact-text')).toggleClass('show');

$('.contact-text').not($(this).find('.contact-text')).removeClass('show');

$('.contact-text').not($(this).find('.contact-text')).hide();

But none of them give me the desired result, I'm starting to believe, my approach may be completely wrong and need to go down a different route.

EDIT: Changed scss to normal css. Explanation if needed: The .mobile-open class is here, because I need this button to be always open when on a mobile device. Doing it like this seemed like the easiest solution to me and it works. Just in case you're wondering, however, I don't think it should hinder the functionality I desire. But I can be wrong!

EDIT 2: In case my explanation wasn't clear: There can never be 2 open buttons, only 2. If I open one and click on another button, the already open button closes. I hope this clarifies my explanation.

Upvotes: 1

Views: 1326

Answers (2)

T.J. Crowder
T.J. Crowder

Reputation: 1074148

As I understand it:

  • Clicking a button should toggle it
  • When toggling it open, we should close any others that are open
  • When toggling it closed, we should issue a call-to-action

See comments:

$('.contact-btn').click(function() {
  var $this = $(this);
  var $thisText = $this.find(".contact-text");
  // Call to action if it's already open
  if ($thisText.hasClass("show")) {
    console.log("call to action");
  }
  // Toggle this one
  $thisText.toggleClass("show");
  // Close any others that might be open
  $this.siblings().find(".contact-text.show").removeClass("show");
});

And I added this CSS:

.contact-btn > .contact-text.show {
      visibility: visible !important;
      opacity: 1 !important;
      max-width: 200px !important;
      padding-left: .5rem;
}

I removed the various max-width things in the JavaScript code (use CSS to handle that; I have to admit not being quite clear what it was doing). You'll probably still have to tweak, but this demonstrates the basic concept:

Running Example:

$('.contact-btn').click(function() {
  var $this = $(this);
  var $thisText = $this.find(".contact-text");
  // Call to action if it's already open
  if ($thisText.hasClass("show")) {
    console.log("call to action");
  }
  // Toggle this one
  $thisText.toggleClass("show");
  // Close any others that might be open
  $this.siblings().find(".contact-text.show").removeClass("show");
});
.wrapper {
  display: flex;
  flex-flow: row nowrap;
}

.contact-btn {
  margin: 1rem;
  padding: 1rem;
  background: red;
  color: #FFF;
  display: inline-block;
  width: auto;
  cursor: pointer;
  border: none;
}

.phone {
  white-space: nowrap;
  float: left;
}
.contact-text {
  width: auto;
  overflow: hidden;
  white-space: nowrap;
  float: left;
  visibility: 0;
  padding-left: 0;
  max-width: 0;
  transition: max-width 400ms ease-in-out, padding 400ms ease-in-out;
}
.contact-text.show {
    padding-left: .5rem;
}

@media (max-width: 479px) {
  .wrapper {
    flex-flow: column nowrap;
    align-items: flex-end;
  }
  .contact-btn.mobile-open > .contact-text {
        visibility: visible !important;
        opacity: 1 !important;
        max-width: 200px !important;
        padding-left: .5rem;
  }
}
.contact-btn > .contact-text.show {
      visibility: visible !important;
      opacity: 1 !important;
      max-width: 200px !important;
      padding-left: .5rem;
}
<div class="wrapper">
  <button class="contact-btn">
    <span class="phone"><strong>KLICK</strong></span>
    <span class="contact-text">078 800 70 70</span>
  </button>
  <button class="contact-btn footer">
    <span class="phone"><strong>KLICK</strong></span>
    <span class="contact-text">078 800 70 70</span>
  </button>
  <button class="contact-btn footer">
    <span class="phone"><strong>KLICK</strong></span>
    <span class="contact-text">078 800 70 70</span>
  </button>
  <div id="phone-indicator" class="hidden-sm-up"></div>
  <div id="desktop-indicator" class="hidden-lg-down"></div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Upvotes: 1

Viplock
Viplock

Reputation: 3319

You have to made some miner change in js for that.

      $('.contact-btn').click(function() {
  if ($(this).hasClass('mobile-open') &&
      !$('#desktop-indicator').is(':visible')) {
    console.log('call-to-action');
    return;
  }
  //changes Here only
  if(!$(this).find('.contact-text').hasClass('show')){
  $(this).parent().find('.contact-text.show').toggleClass('show');
  $(this).parent().find('.contact-text').css('max-width',0);
  }

    $(this).find('.contact-text').toggleClass('show');

    if ($(this).find('.contact-text').hasClass('show')) {

      var width = $(this).find('.contact-text')[0].scrollWidth + 55;
      $(this).find('.contact-text').css('max-width',width);
      if ($(this).hasClass('mobile-open') &&
          $('#phone-indicator').is(':visible')) {
        console.log('call-to-action');
        return;
      } else if ($('#desktop-indicator').is(':visible') ||
          $(this).hasClass('footer')) {
        console.log('open');
      }
    } else {

      $(this).find('.contact-text').css('max-width',0);
      if ($('#desktop-indicator').is(':visible') ||
          $(this).hasClass('footer')) {
        console.log('call-to-action');
      }
    }
  });

changes are before toggleClass and while closing the tabs.

Hope it will help you.

find updated pan

Upvotes: 1

Related Questions