rufus
rufus

Reputation: 857

Simplifying hide and show div in jQuery code

I have written some jQuery code that does the job I am looking for it do but being fairly new to jQuery I was just curious to know if there was a simpler way to go about it. All its basically doing is hiding and showing divs on click events.

I have tried playing around with a few different ideas but this seems to be the only way I can get what I want to happen on the click events.

Markup below.

$('#facebook-icon').click(function() {
  $('#facebook-callout, .hero-callout').fadeToggle();
  $('#twitter-icon, #linked-icon').toggleClass('z-index-neg');
});
$('#twitter-icon').click(function() {
  $('#twitter-callout, .hero-callout').fadeToggle();
  $('#facebook-icon, #linked-icon').toggleClass('z-index-neg');
});
$('#linked-icon').click(function() {
  $('#linked-callout, .hero-callout').fadeToggle();
  $('#facebook-icon, #twitter-icon').toggleClass('z-index-neg');
});

$('.close').click(function() {
  $(this).closest('div').fadeOut('slow');
  $('.hero-callout').fadeIn('slow');
  $('.social-icon').removeClass('z-index-neg');
});
a {
  text-decoration: none;
}

.hero-wrapper {
  position: relative;
}

.hero-callout {
  position: relative;
  height: 300px;
  text-align: center;
  margin-top: 150px;
}

.close {
  font-size: 25px;
  color: #151515;
  position: absolute;
  right: 0;
  top: -30px;
  cursor: pointer;
}

.social-callout {
  position: absolute;
  top: 50%;
  left: 50%;
  -webkit-transform: translate(-50%, -50%);
  transform: translate(-50%, -50%);
  display: none;
}

.social-heading {
  color: #151515;
  font-size: 45px;
  text-transform: none;
  position: relative;
}

.z-index-neg {
  z-index: -1;
  opacity: 0 !important;
  -webkit-transition: .5s;
  transition: .5s;
}

.social-heading:after {
  content: "";
  background: #151515;
  height: 3px;
  width: 0;
  display: block;
  margin: 0 auto;
  -webkit-transition: width .5s;
  transition: width .5s;
}

.social-heading:hover:after {
  width: 100%;
  -webkit-transition: width .5s;
  transition: width .5s;
}

#social-icons {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  margin-left: auto;
  margin-right: auto;
  text-align: center;
}

.social-icon {
  position: relative;
  color: #151515;
  font-size: 18px;
  opacity: 1;
  -webkit-transition: .5s;
  transition: .5s;
  cursor: pointer;
  display: inline-block;
  padding: 0 10px;
}

.icons:hover {
  opacity: 0.5;
  -webkit-transition: .3s;
  transition: .3s;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="hero-wrapper">
  <div class="hero-callout">
    <h2>
      Hello World
    </h2>
  </div>
  <div class="social-callout" id="facebook-callout">
    <a href="#">
      <h2 class="social-heading">Facebook.</h2>
    </a>
    <span class="close">X</span>
  </div>
  <div class="social-callout" id="twitter-callout">
    <a href="#">
      <h2 class="social-heading">Twitter.</h2>
    </a>
    <span class="close">X</span>
  </div>
  <div class="social-callout" id="linked-callout">
    <a href="#">
      <h2 class="social-heading">Linked In.</h2>
    </a>
    <span class="close">X</span>
  </div>
  <div id="social-icons">
    <span class="social-icon" id="facebook-icon">Facebook</span>
    <span class="social-icon" id="twitter-icon">Twitter</span>
    <span class="social-icon" id="linked-icon">Linked In</span>
  </div>
</div>

Thanks guys

Upvotes: 1

Views: 45

Answers (3)

Rory McCrossan
Rory McCrossan

Reputation: 337743

The technique you're looking for is called Don't Repeat Yourself, or DRY. The goal is to genericise the logic so that it can be applied to any relevant element in the DOM, so long as it follows the expected structure.

In this case you can add a data attribute to the .social-icon elements which specifies the id of the .social-callout element relates to them and should be used when clicked.

Following this pattern means you can now have an infinite number of .social-icon elements with associated .social-callouts without ever needing to amend your JS code:

$('.social-icon').click(function() {
  var $target = $($(this).data('target'));
  $target.add('.hero-callout').fadeToggle();
  $('.social-icon').not(this).toggleClass('z-index-neg');
})

$('.close').click(function() {
  $(this).closest('div').fadeOut('slow');
  $('.hero-callout').fadeIn('slow');
  $('.social-icon').removeClass('z-index-neg');
});
a {
  text-decoration: none;
}

.hero-wrapper {
  position: relative;
}

.hero-callout {
  position: relative;
  height: 300px;
  text-align: center;
  margin-top: 150px;
}

.close {
  font-size: 25px;
  color: #151515;
  position: absolute;
  right: 0;
  top: -30px;
  cursor: pointer;
}

.social-callout {
  position: absolute;
  top: 50%;
  left: 50%;
  -webkit-transform: translate(-50%, -50%);
  transform: translate(-50%, -50%);
  display: none;
}

.social-heading {
  color: #151515;
  font-size: 45px;
  text-transform: none;
  position: relative;
}

.z-index-neg {
  z-index: -1;
  opacity: 0 !important;
  -webkit-transition: .5s;
  transition: .5s;
}

.social-heading:after {
  content: "";
  background: #151515;
  height: 3px;
  width: 0;
  display: block;
  margin: 0 auto;
  -webkit-transition: width .5s;
  transition: width .5s;
}

.social-heading:hover:after {
  width: 100%;
  -webkit-transition: width .5s;
  transition: width .5s;
}

#social-icons {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  margin-left: auto;
  margin-right: auto;
  text-align: center;
}

.social-icon {
  position: relative;
  color: #151515;
  font-size: 18px;
  opacity: 1;
  -webkit-transition: .5s;
  transition: .5s;
  cursor: pointer;
  display: inline-block;
  padding: 0 10px;
}

.icons:hover {
  opacity: 0.5;
  -webkit-transition: .3s;
  transition: .3s;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="hero-wrapper">
  <div class="hero-callout">
    <h2>
      Hello World
    </h2>
  </div>
  <div class="social-callout" id="facebook-callout">
    <a href="#">
      <h2 class="social-heading">Facebook.</h2>
    </a>
    <span class="close">X</span>
  </div>
  <div class="social-callout" id="twitter-callout">
    <a href="#">
      <h2 class="social-heading">Twitter.</h2>
    </a>
    <span class="close">X</span>
  </div>
  <div class="social-callout" id="linked-callout">
    <a href="#">
      <h2 class="social-heading">Linked In.</h2>
    </a>
    <span class="close">X</span>
  </div>
  <div id="social-icons">
    <span class="social-icon" id="facebook-icon" data-target="#facebook-callout">Facebook</span>
    <span class="social-icon" id="twitter-icon" data-target="#twitter-callout">Twitter</span>
    <span class="social-icon" id="linked-icon" data-target="#linked-callout">Linked In</span>
  </div>
</div>

Upvotes: 1

adeneo
adeneo

Reputation: 318372

You could combine the event handlers, and handle each case based on the clicked icons ID

var icons = $('.social-icon').on('click', function() {
  var id = this.id.replace('icon', 'callout');
  var el = $('#' + id);
  $('.hero-callout').add(el).fadeToggle();
  icons.not(this).toggleClass('z-index-neg')
});

$('.close').on('click', function() {
  $(this).closest('div').fadeOut('slow');
  $('.hero-callout').fadeIn('slow');
  $('.social-icon').removeClass('z-index-neg');
});
a {
  text-decoration: none;
}

.hero-wrapper {
  position: relative;
}

.hero-callout {
  position: relative;
  height: 300px;
  text-align: center;
  margin-top: 150px;
}

.close {
  font-size: 25px;
  color: #151515;
  position: absolute;
  right: 0;
  top: -30px;
  cursor: pointer;
}

.social-callout {
  position: absolute;
  top: 50%;
  left: 50%;
  -webkit-transform: translate(-50%, -50%);
  transform: translate(-50%, -50%);
  display: none;
}

.social-heading {
  color: #151515;
  font-size: 45px;
  text-transform: none;
  position: relative;
}

.z-index-neg {
  z-index: -1;
  opacity: 0 !important;
  -webkit-transition: .5s;
  transition: .5s;
}

.social-heading:after {
  content: "";
  background: #151515;
  height: 3px;
  width: 0;
  display: block;
  margin: 0 auto;
  -webkit-transition: width .5s;
  transition: width .5s;
}

.social-heading:hover:after {
  width: 100%;
  -webkit-transition: width .5s;
  transition: width .5s;
}

#social-icons {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  margin-left: auto;
  margin-right: auto;
  text-align: center;
}

.social-icon {
  position: relative;
  color: #151515;
  font-size: 18px;
  opacity: 1;
  -webkit-transition: .5s;
  transition: .5s;
  cursor: pointer;
  display: inline-block;
  padding: 0 10px;
}

.icons:hover {
  opacity: 0.5;
  -webkit-transition: .3s;
  transition: .3s;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="hero-wrapper">
  <div class="hero-callout">
    <h2>
      Hello World
    </h2>
  </div>
  <div class="social-callout" id="facebook-callout">
    <a href="#">
      <h2 class="social-heading">Facebook.</h2>
    </a>
    <span class="close">X</span>
  </div>
  <div class="social-callout" id="twitter-callout">
    <a href="#">
      <h2 class="social-heading">Twitter.</h2>
    </a>
    <span class="close">X</span>
  </div>
  <div class="social-callout" id="linked-callout">
    <a href="#">
      <h2 class="social-heading">Linked In.</h2>
    </a>
    <span class="close">X</span>
  </div>
  <div id="social-icons">
    <span class="social-icon" id="facebook-icon">Facebook</span>
    <span class="social-icon" id="twitter-icon">Twitter</span>
    <span class="social-icon" id="linked-icon">Linked In</span>
  </div>
</div>

Upvotes: 1

N. Ivanov
N. Ivanov

Reputation: 1823

Yes it is possible. You can attach the same class to all of your elements with IDs ('#twitter-icon', '#facebook-icon', etc). and then bind an event to that class. Lets say you want to put class .icon. Then simply do this:

$("body").on("click", ".icon", function(){
    $(this).fadeToggle();
    $(this).toggleClass('z-index-neg');
});

Where $(this) targets the currently clicked element.

Hope this helps.

Upvotes: 1

Related Questions