noisegrrrl
noisegrrrl

Reputation: 159

React: Prevent click on scrollbar from propagating

I have a div that is scrollable unfortunately I also have event associated with onMouseDown on the div.

My problem is that when I want to scroll by clicking on the scrollbar those events are then fired.

Is there a way to make it so I can prevent the mouse event on the scrollbar from propagating ?

Upvotes: 4

Views: 3929

Answers (3)

user3267727
user3267727

Reputation: 35

I had the same problem. I had a div element, with another scrollable div inside of it. I wanted the onclick event to fire on both the outside and inside div, but not on the scrollbar.

The problem is that the scrollbar gets the mousedown as well.

The clean solution to prevent the mousedown on the scrollbar is to create a div that contains the scrollable content inside the div that contains the scrollbar. Then, we disable our onmousedown function when the target is the div with the scrollbar. Maybe it is clearer with an example:

document.onmousedown = function(e){
  if(e.target.id != 'scroll'){
    console.log('mousedown');
  }
}
#outside {
  position: relative;
  width: 300px;
  height: 200px;
  background-color: green;
}

#scroll {
  position: relative;
  top: 10px;
  left: 10px;
  background-color: red;
  width: 280px;
  height: 100px;
  overflow-y: scroll;
}
<div id='outside'>
    <div id='scroll'>
      <div id='container'>
        foo<br>
        bar<br>
        eee<br>
        foo<br>
        bar<br>
        eee<br>
        foo<br>
        bar<br>
        eee<br>
      </div>
    </div>
  </div>

The solution works because the 'scroll' div contains the scrollbar, but the 'container' div does not (you can see this really well if you inspect element). The only time the mousedown event's direct target is the 'scroll' div is when we are clicking on the scrollbar. Any clicks on the scrollbar are stopped, but everything else triggers the event.

Hope this helps.

Upvotes: 3

Chris
Chris

Reputation: 59511

There doesn't seem to be a way to do this; not to my knowledge anyway.

However, there is one half-decent solution:


If you click on the scrollbar, the cursor coordinates is equal to the width of your element, in which case you can just return and prevent the event handler from doing its stuff.

Here, I have added an extra 7 pixels to the logic, to account for the width of the scrollbar on Chrome.v.58/MacOS. The width of the scrollbar is determined by browser through, so that value might need a slight tweak.

class MyApp extends React.Component {

  divMouseDown(e) {
    if((e.clientX + 7) >= e.target.clientWidth) return;
    console.log("do stuff on click");
  }
  render() {
    return (
      <div id="my-div" onMouseDown={this.divMouseDown}>
        <p>foo</p>
        <p>bar</p>
        <p>baz</p>
      </div>
    );
  }
}

ReactDOM.render(<MyApp />, document.getElementById("myApp"));
#my-div {
  background: beige;
  height: 60px;
  overflow: auto;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="myApp"></div>

Upvotes: 5

Blarzek
Blarzek

Reputation: 157

Then put this on your onMouseDown function:

function myFunction(event, element) {
  // Your code for div
  // ...

  if (event.stopPropagation) {
      event.stopPropagation();
  } else {
      event.cancelBubble = true;
  }
}

And your div should be something like this:

<div onmousedown="myFunction(event, this);">Click me!</div>

Upvotes: 1

Related Questions