0

*this question has been updated.

I have a set of boxes which, when clicked open a div called #expander. In my code, after #expander is opened, and if another box is clicked, I check if the new box clicked is the same as the last box clicked. If it is the same, I close #expander, else I briefly close it and then open it again.

This is demonstrated with the this jsfiddle

Here is the same code, in stackoverflow:

$(document).on('click', '.box', function(e) {
  if (!$('#expander').hasClass('active')) {
    $('#expander').addClass('active');
    $('.basic-info').css('border-left', '1px solid black');
    activeBox = $(this).attr('id');
    $('#main').text(activeBox);
  	console.log('activeBox = ' + activeBox);
    return;
  }

  if ($('#expander').hasClass('active')) {
    $('#expander').removeClass('active');
    $('.basic-info').css('border-left', '0px solid black');
    if ($(this).attr('id') !== activeBox) {
      setTimeout(function() {
        $('#expander').addClass('active');
      }, 256);
    }
    activeBox = $(this).attr('id');
    $('#main').text(activeBox);
  	console.log('activeBox = ' + activeBox);
    return;
  }
});
#expander{
  height: 100%;
  width: 0%;
  float: left;
  visibility: hidden;
  overflow: hidden;
  background-color: grey;
  transition: .75s ease-out;
}
#expander.active{
  height: 100%;
  width: 50%;
  z-index: 1;
  visibility: visible;
}
#closer{
  padding: 4px;
  margin: 0px;
  background-color: #707070;
  color: white;
  font-size: 1.5em;
  text-align: center;
  cursor: pointer;
}
#closer:hover{
  background-color: #606060;
  font-size: 2em;
  padding: 0px;
}
.box{
  width: 32px;
  height: 32px;
  padding: 5px 0px;
  margin: 0px 4px;
  display: inline-block;
  background-color: grey;
  overflow: hidden;
  font-size: 1em;
  font-weight: bold;
  text-align: center;
  border: 1px solid transparent;
  border-radius: 2px;
  cursor: pointer;
}
.basic-info{
  padding: 8px 16px;
  color: white;
  background-color: #47a;
  border-top: 1px solid black;
  border-right: 1px solid black;
  border-bottom: 1px solid black;
  transition: .5s ease-out;
  cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="expander">
  <div id="closer" title="Close"><span>&times</span></div>
  <div id="main"></div>
</div>
<div class="basic-info">
  <div id="box1" class="box">1</div>
  <div id="box2" class="box">2</div>
  <div id="box3" class="box">3</div>
</div>

The above code works (although it does not look exactly how it looks in my final layout) BUT what it does not do run this: $('.basic-info').css('border-left', '1px solid black'); after the first time a box is clicked (when it opens the #expander

I realize the reason this is not working is that the JS code first adds the classes and styles, but then the next if statement removes the classes and styles. Also, I have to paste the following code two times:

$('#main').text(activeBox);
console.log('activeBox = ' + activeBox);
return;

Does anyone know a better way to layout my if statements so that code does not conflict? Also, is there a way to not need to use return;s?

P.S. does anyone have a link to a good if statement tricks tutorial so that I can learn these things for the future?

Thank you.


UPDATE:

I have updated the code based on the current answers and have changed the JS to this:

$(document).on('click', '.box', function(e) {
  if ($('#expander').hasClass('active')) {
    $('#expander').removeClass('active');
    if ($(this).attr('id') !== activeBox) {
      setTimeout(function() {
        $('#expander').addClass('active');
      }, 256);
      activeBox = $(this).attr('id');
      console.log('activeBox = ' + activeBox);
      return;
    }
    $('.basic-info').css('border-left', '0px solid white');
    return;
  }
  $('#expander').addClass('active');
  $('.basic-info').css('border-left', '1px solid white');
  activeBox = $(this).attr('id');
  console.log('activeBox = ' + activeBox);
}

(it does the same thing, just laid out differently). All I am trying to figure out now is just how I can write this without any of the return;s and also so I do not have to write activeBox = $(this).attr('id'); console.log('activeBox = ' + activeBox); twice (unless these things are impossible/unavoidable)

thank you.

2
  • You could do if (foo) { ... } else if (bar) { ... }, where the second one is only executed if foo is falsy and bar is truthy. Commented Aug 6, 2016 at 19:44
  • An if statement tutorial? I'm not sure what that would be, just read about JS control structures. Commented Aug 6, 2016 at 19:47

2 Answers 2

1

for the clean up part and get rid of repeated data, you can convert your js code to this

Updated

jsFiddle

// target the #expander 
var Expander = $('#expander'),
  activeBox = '';

$(document).on('click', '.box', function(e) {
  //toggleClass means if #expander hasClass, remove it, if it
  //doesn't have the class, add it.
  Expander.toggleClass('active');
  // same for .basic info, we use toggle class, instead of
  // CSS hardcoded, thus we can toggle
  $('.basic-info').toggleClass('black-border-left');

  if ($(this).attr('id') !== activeBox) {
    Expander.removeClass('active');
    // to get rid of the delay for when one .box div is clicked for the first time
    // when activeBox = ''.
    if(activeBox !== ''){
      setTimeout(function() {
        Expander.addClass('active');
      }, 500);
    }else{
      Expander.addClass('active');
    }
    activeBox = $(this).attr('id');
  }
  $('#main').text(activeBox);
  console.log('activeBox = ' + activeBox);
});
Sign up to request clarification or add additional context in comments.

8 Comments

good idea! +1 from me. any way to not have to toggleClass $('.basic-info.') or is that just unavoidable by going with this method...
it depends on what you're trying to do with that $('.basic-info'); but I don't know what's your ideal approach for it
Sorry had a typo in my code, was toggleClass('.black-border-left') instead of toggleClass('black-border-left'), I removed the extra dot. and updated the answer
okay, got it on the typo (NBD), IDK, I just didn't want to make one random extra class to add the black border but I guess it is not the end of the world...
oh, found one thing which bugs on the above code - the first time you click the box, activeBox is null so the if statement returns true. This is fine as it will still open the box, it just adds the setTimeout lag to open it... any way around this?
|
1
$(document).on('click', '.box', function(e) {
  if (!$('#expander').hasClass('active')) {
    $('#expander').addClass('active');
    $('.basic-info').css('border-left', '1px solid black');
    activeBox = $(this).attr('id');
    $('#main').text(activeBox);
    console.log('activeBox = ' + activeBox);
  } else if ($('#expander').hasClass('active')) {
    $('#expander').removeClass('active');
    $('.basic-info').css('border-left', '0px solid black');
    if ($(this).attr('id') !== activeBox) {
      setTimeout(function() {
        $('#expander').addClass('active');
      }, 256);
    }
    activeBox = $(this).attr('id');
    $('#main').text(activeBox);
    console.log('activeBox = ' + activeBox);
  }
});

2 Comments

thank you, but this still does not change the fact that $('.basic-info').css('border-left', '0px solid black'); is removed after you click on a different box...
Well. You got $('.basic-info').css('border-left', '1px solid black') on Click on unactive box, so obviously it overrides $('.basic-info').css('border-left', '0px')

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.