React: Prevent click on scrollbar from propagating - javascript

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 ?

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>

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.

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>

Related

Javascript: on div click expand div height, and on second click collapse div height?

I have the following javascript that adjusts my div height when a user clicks trend_exp_bt.
It works fine at the moment. However, if the user clicks trend_exp_bt again, i want to reset the div height (130px).
Please can someone show me how to do this, i've tried to look at toggle function on google but these don't seem to be working for me.
<script>
$('.trend_exp_bt').click(function(){
$('.trending_contain').animate({height:'500'})
$('.trend_exp_bt').css("line-height", "30px");
$('.trend_exp_bt').html("∧");
})
</script>
Maybe toggling a class would work for you?
document.getElementById('trend_exp_bt').onclick = function() {
document.getElementById('exp-panel').classList.toggle('expanded')
}
.panel {
width: 250px;
height: 130px;
border: 1px solid blue;
background-color: lightgrey;
transition: all 0.3s;
}
.expanded {
height: 300px;
}
<button id="trend_exp_bt">Expand</button>
<div id="exp-panel" class="panel">
</div>
If you want to use click handlers, you will have to remove the "expand" handler and add a "collapse" handler after it is expanded. You will have to do the opposite when a user collapses the div element.
function expandDiv() {
$('.trending_contain').animate({height:'500'});
$('.trend_exp_bt').css("line-height", "30px");
$('.trend_exp_bt').html("∧");
$('.trend_exp_bt').off('click').on('click', collapseDiv)
}
function collapseDiv() {
$('.trending_contain').animate({height:'200'});
$('.trend_exp_bt').css("line-height", "30px");
$('.trend_exp_bt').html("∨");
$('.trend_exp_bt').off('click').on('click', expandDiv)
}
$('.trend_exp_bt').click(expandDiv);

How to enable javascript mouse events on overlapping html elements?

This probably cannot be done, but I have a fixed-position div on top of inline html in the page body. The inline html has clickable elements, and the fixed div has a hover event.
The fixed element is an empty div, so it is invisible.
Currently, the fixed element is blocking click events on the item under it.
Is it possible?
This solution is too complicated
https://stackoverflow.com/a/9616491/209942
Possible solution?
https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events
Thx
The fixed element should not be prevent the clicks from the item under it unless you are stopping the event propagation.
See this fiddle: https://jsfiddle.net/pv0mygz5/
-- it demonstrates that without event.stopPropagation the event should be intercepted by the listener on the span element.
$('#click-me').on('click', function (e) {
console.log('click triggered');
});
$('.box').on('mouseover', function (e) {
//don't stop event from bubbling
console.log('hover triggered');
});
Could you also include a code snippet that demonstrates your problem?
although IE10 doesn't support it you can use
pointer-events: none;
http://jsfiddle.net/leaverou/XxkSC/light/
In this fiddle you can see a drop down being covered with other elements, the other elements has pointer-events: none so you can click on the arrow down button and the click actually goes to the select element itself.
BR,
Saar
You can also try using z-index. Depending on your layout it may not be a solution, but if your front div is invisible, then it shouldn't create unwanted effect. Like this for example:
document.querySelector('#under').addEventListener('click', function(e) {
e.target.style.color = "blue";
});
document.querySelector('#notunder').addEventListener('click', function(e) {
e.target.style.color = "blue";
});
#fix {
width: 60px;
height: 200px;
position: fixed;
z-index: -1;
top: 0px;
border: 1px solid black;
}
#under {
display: inline;
}
#fixnozindex {
width: 100px;
height: 200px;
position: fixed;
left: 75px;
top: 0px;
border: 1px solid black;
}
#notunder {
display: inline;
}
<div id="fix"></div>
<div id="under">Clickable</div>
<div id="fixnozindex"></div>
<div id="notunder">Not clickable</div>

How to get top level object under the mouse function?

Title says it all. I've got child div's with absolute positions inside a relative parent div, and would like to know whether the mouse is over a child or a parent div at a "random" point in time.
Hypothetically, I'd like to call the .mouseover method and perform a .hasclass test on the highest level object to see if it has the child class or not. However, .mouseover is an event handler, thus not something I could just call to get the relevant information.
Example HTML below:
$(document).ready(function() {
$(".child").draggable();
setTimeout(doSomething, 31415);
});
var doSomething = function() {
// Edit content based on what is underneath the mouse
}
.parent {
width: 100%;
height: 1000px;
position: relative;
background: #f0f0f0;
}
.child {
width: 300px;
height: 100px;
position: absolute;
background: #cccccc;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.11.4/themes/ui-lightness/jquery-ui.css">
<script src="http://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>
<div class="parent">
<div class="child"></div>
<div class="child"></div>
</div>
Getting an element from a position is what the document.elementFromPoint function was designed to do:
document.elementFromPoint(mousePosition.x, mousePosition.y);
To get the current mouse position, attach a listener to mousemove (as far as I know there is no native method to extract mouse coordinates without a mouse event). Here's an example fiddle showing this: https://jsfiddle.net/xsLwt8Ld/
If I understood correctly, you want to know if at any given time, the mouse is over the child or directly over the parent. You could achieve it by using the :hover pseudoclass
Create a function that checks if there is any .child that has the :hover class:
If there is, that means that the mouse is over a .child (and you have the element) and there's no need to check the parent.
If there isn't, then check if there is any .parent element that also has the class that you created:
If there is: the mouse is over a .parent but not over a .child;
If there is not: the mouse i not over a .parent or a .child.
The code to achieve this is simple:
function checkMouseOver() {
if ($(".child:hover").length) {
// mouse over a .child
} else if ($(".parent:hover").length) {
// mouse over a .parent (but not over .child)
} else {
// mouse not over a .parent or .child;
}
}
A simple working demo:
$(".child").draggable();
// Edit content based on what is underneath the mouse
function checkMouseOver() {
if ($(".child:hover").length) {
alert("You were over " + $(".child:hover").text());
} else if ($(".parent:hover").length) {
alert("You were over " + $(".parent:hover").attr("id"));
} else {
alert("You are not over a .parent or .child");
}
}
.parent {
width: 100%;
height: 1000px;
position: relative;
background: #f0f0f0;
}
.child {
width: 300px;
height: 100px;
position: absolute;
background: #cccccc;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.11.4/themes/ui-lightness/jquery-ui.css">
<script src="http://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>
<button onclick="checkMouseOver()">Check where the mouse is</button>
<div class="parent" id="parent1">
<div class="child">Child 1</div>
<div class="child">Child 2</div>
</div>
<div class="parent" id="parent2">
<div class="child">Child 3</div>
<div class="child">Child 4</div>
</div>
(Click on the page and press tab until you get into the button, then mouse over the different elements and press Enter to trigger the funtion)

Increase width of divs, displayed side by side, using draggable events

I have two divs of fixed length as of now, which loads external URL by dynamically embedding iframes inside them. Divs are appearing next to each other - one on left and other right.
As of now, I have fixed their width to 50% each. But, I want to give user a flexibility to increase the width of any div to view the URL inside easily without scrolling horizontally. Something like dragging the border separating the two divs to either left or right according to his need.
Is there a way I could achieve this? Please suggest any library or something.
I have gone through a library twentytwenty which is used for images. I don't know how will that work for dynamic iframes.
Here is the JSFiddle which displays the divs.
<div>
<div id="originalPage" style="width:54%;height: 730px;float:left">
<p>one div </p>
</div>
<div id="diffReport" style="width:45%; height: 730px;float:right">
<p>another div</p>
</div>
</div>
There is a awesome jQuery plugin, go with jQuery Splitter here:
http://jquery.jcubic.pl/splitter.php
<div>
<div class="resizable" id="originalPage" style="width:54%;height: 730px;float:left">
<p>one div </p>
</div>
<div class="resizable" id="diffReport" style="width:45%; height: 730px;float:right">
<p>another div</p>
</div>
</div>
$(function() {$( ".resizable" ).resizable({animate: true,animateEasing:'swing',imateDuration: 500
});});
#diffReport, #originalPage{
border: 1px solid;
}
.ui-resizable-helper { border: 1px dotted gray; }
.resizable { display: block; width: 400px; height: 400px; padding: 30px; border: 2px solid gray; overflow: hidden; position: relative; }
#diffReport { width: 100%; height: 100%; }
#originalPage { width: 100%; height: 100%; }
Use jQuery UI library in order to do resizing/dragging.
HTML
<div id="demo"></div>
Script
<script>
$(function(){$('#demo').draggable().resizable();});
$('#demo')
.resizable({
start: function(e, ui) {
alert('resizing started');
},
resize: function(e, ui) {
},
stop: function(e, ui) {
alert('resizing stopped');
}
});
</script>
Fiddle is
http://jsfiddle.net/VuqbN/
Updated your fiddle
http://jsfiddle.net/vw9qt/1/
var isDragging = false
var lastPageX = null
Make a new div in the middle of the existing ones.
Attach an event listener to mousedown on that div.
set isDragging to true and lastPageX to event.pageX
Attach an event listener to mousemove on the enclosing div.
only run if isDragging
var diff event.pageX - lastPageX
add diff to the left resizable div
remove diff from the right resizable div
set lastPageX to event.pageX
Attach an event listener to mouseup on the document
set isDragging to false

css+js: div click (and elements inside it)

I'm trying to build a (semi-transparent) overlay that covers all on a web page.
Similar to this: http://www.jankoatwarpspeed.com/use-jquery-to-turn-off-the-lights-while-watching-videos
<div id="overlaySplash" onclick="clickHandler(this)">
<div id="insideBox">
[ label elements here with onclick="dosomething()" ]
</div>
</div>
css
#overlaySplash {
position: absolute;
top: 0;
left: 0;
bottom:0;
right:0;
background: rgb(50, 50, 50);
background: rgba(0, 0, 0, .50);
z-index: 50;
}
#insidebox {
position: absolute;
z-index: 100;
left: 15%;
right: 15%;
bottom: 5%;
line-height: 50px;
text-align: left;
}
The problem is that I'm not using jquery and the overlay div will have some clicable contents on int. I have this function below but when I click on elements inside the main overlay div JS will return e.id as being the overlay div itself, not the clicked element. This way I can't tell where the user really clicked.
function clickHandler(e){ //hide the div overlaySplash
e = e || event;
alert(e.id);
}
THE BOTTOM LINE:
user clicked an label inside the div: dosomething();
user clicked the background (the DIV itself): closeOverlaySplash();
I don't think you need to completely stop propagation as it may serve some purpose later on. It might be easiest to create a separate js & css files that encompass this functionality for ease of use.
The issue you have is basically the event is bubbling up to the parent when it isn't currently needed. You can easily check the event.target.id to see if the parent was clicked or not. With this you can make sure the overlay was clicked vs the content.
eg:
if (event.target.id == "overlay") {
//hide the overlay
}
JSFiddler
Like this:
HTML
<div id="overlaySplash" onclick="clickHandler(event);">
<div id="insideBox" onclick="clickHandlerInner(event);">Inner</div>
</div>
JS
function clickHandler(event) {
alert("no");
}
function clickHandlerInner(event) {
if (!event) var event = window.event;
event.cancelBubble = true; //IE
if (event.stopPropagation) event.stopPropagation()
alert("yes")
}
jsFiddle

Categories

Resources