0

I've got a nested div that contains 'additional information'.

When a person clicks the div, it opens the 'additional information' div.

I have used .stopPropagation() to prevent it from closing when the person clicks the text in the 'additional information', but if they click the borders or something, the collapse happens and the information goes away.

I found this SO post - which was seemingly close to what I wanted, but I couldn't figure out how to make it work exactly how I need.

Here is a codepen of what I'm trying to accomplish.

$('#collapsDiv').on('show.bs.collapse', function( event ) {
 event.stopPropagation();
    console.log('Only happen when outter div is opened');
})
$('#collapseDiv').on('hide.bs.collapse', function( event ) {
 event.stopPropagation();
 console.log('Only happen when outter div is collapsed');
})
$('#additionalDiv').on('click', function( event ) {
    event.stopPropagation();
})

$('#collapseDiv').click(function(e) {
     if (e.pageY > $(this).offset().top + $(this).height()) {
          // bottom was clicked
          console.log('bottom clicked!');
          e.stopPropagation();
     } else {
          // up of the div was clicked
          console.log('top clicked');
     }
});
#collapseDiv {
 cursor:pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0/js/bootstrap.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container">
 <div id="collapseDiv" class="alert alert-warning" data-toggle="collapse" href="#additionalDiv" role="button" aria-expanded="false" aria-controls="additionalDiv">
  This Div shows by default - I used an alert to make it more visually obvious. Only this part should remain clickable. The hidden stuff should not be clickable. A bonus would be having the lower portion not have a pointer!
  <div id="additionalDiv" class="collapse">
   <div class="other-stuff">
    <h2>This stuff should not be clickable</h2>
    <p>There may be paragraphs here a user might want to copy/paste!</p>
    <p>In a perfect world - even the bottom / sides would not trigger the collapse. This would only be collapsed by clicking the original div area.</p>
   </div>
  </div>
 </div>
</div>

This is 'working', but it only avoids clicks on the bottom - how would I make it avoid clicks on the sides as well?

side note: it seems there is about a very tiny row on the bottom that causes it to collapse if clicked still.

Hanny
  • 580
  • 3
  • 16
  • 44

3 Answers3

1

The padding space makes it clickable.

You don't need javascript to achieve this. Just add another div for toggling only.

#collapseDiv { 
  padding: 0;
}

.my-toggle {
  cursor: pointer;
  padding: 20px;
}

#additionalDiv {
  padding: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0/js/bootstrap.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet" />
<div class="container">
  <div id="collapseDiv" class="alert alert-warning">
    <div class="my-toggle" data-toggle="collapse" href="#additionalDiv" role="button" aria-expanded="false" aria-controls="additionalDiv">
      This Div shows by default - I used an alert to make it more visually obvious. Only this part should remain clickable. The
      hidden stuff should not be clickable. A bonus would be having the lower portion not have a pointer!
    </div>
    
    <div id="additionalDiv" class="collapse">
      <div class="other-stuff">
        <h2>This stuff should not be clickable</h2>
        <p>There may be paragraphs here a user might want to copy/paste!</p>
        <p>In a perfect world - even the bottom / sides would not trigger the collapse. This would only be collapsed by clicking
          the original div area.</p>
      </div>
    </div>
  </div>
</div>
onyx
  • 1,588
  • 7
  • 14
  • If you try it in the codepen, even adding that to `#collapseDiv` there is still a tiny spot at the bottom that causes it to collapse – Hanny Aug 15 '18 at 19:20
0

I would adjust a couple things - get the additional div outside of the clickable one and put the padding on the sub-containers and styling on the container.

The problem really is that your container padding is clickable around the collapsable div.

.container--nopad {
    padding: 0;
}

#collapseDiv, #additionalDiv {
    padding: 20px;
}


<div class="container container--nopad alert alert-warning">
    <div id="collapseDiv"  data-toggle="collapse" href="#additionalDiv" role="button" aria-expanded="false" aria-controls="additionalDiv">
        This Div shows by default - I used an alert to make it more visually obvious. Only this part should remain clickable. The hidden stuff should not be clickable. A bonus would be having the lower portion not have a pointer!
    </div>
    <div id="additionalDiv" class="collapse">
        <div class="other-stuff">
            <h2>This stuff should not be clickable</h2>
            <p>There may be paragraphs here a user might want to copy/paste!</p>
            <p>In a perfect world - even the bottom / sides would not trigger the collapse. This would only be collapsed by clicking the original div area.</p>
        </div>
    </div>
</div>

codepen: https://codepen.io/dmgig/pen/EpzGLG

dmgig
  • 4,400
  • 5
  • 36
  • 47
  • Semantically, it is probably good to keep the "button" separate from the element it is acting on. – dmgig Aug 15 '18 at 19:29
0

the padding from the container div is what is causing the action. remove the padding and instead add it to both inner elements.

$('#collapsDiv').on('show.bs.collapse', function( event ) {
 event.stopPropagation();
    console.log('Only happen when outter div is opened');
})
$('#collapseDiv').on('hide.bs.collapse', function( event ) {
 event.stopPropagation();
 console.log('Only happen when outter div is collapsed');
})
$('#additionalDiv').on('click', function( event ) {
    event.stopPropagation();
})

$('#collapseDiv').click(function(e) {
     if (e.pageY > $(this).offset().top + $(this).height()) {
          // bottom was clicked
          console.log('bottom clicked!');
          e.stopPropagation();
     } else {
          // up of the div was clicked
          console.log('top clicked');
     }
});
 #collapseDiv {
 cursor:pointer;
 padding-left: 0;
 padding-right: 0;
}
#collapseDiv .triggerDiv, 
#collapseDiv #additionalDiv {
 padding-left: 1.25rem;
 padding-right: 1.25rem;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0/js/bootstrap.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container">
 <div id="collapseDiv" class="alert alert-warning" data-toggle="collapse" href="#additionalDiv" role="button" aria-expanded="false" aria-controls="additionalDiv">
  <div class="triggerDiv">This Div shows by default - I used an alert to make it more visually obvious. Only this part should remain clickable. The hidden stuff should not be clickable. A bonus would be having the lower portion not have a pointer!</div>
  <div id="additionalDiv" class="collapse">
   <div class="other-stuff">
    <h2>This stuff should not be clickable</h2>
    <p>There may be paragraphs here a user might want to copy/paste!</p>
    <p>In a perfect world - even the bottom / sides would not trigger the collapse. This would only be collapsed by clicking the original div area.</p>
   </div>
  </div>
 </div>
</div>
Spencer
  • 116
  • 2
  • 9