'mouseenter' and 'mouseleave' event keeps triggering with div as cursor - javascript

I made a 'custom cursor' by hiding the users cursor and displaying a div where the original cursor would normally be displayed on the screen.
Now the problem is I'd like to add some animations when hovering over an element (e.g. scale the 'cursor', or in this case the div that acts as the cursor).
In this example I made a button, and gave it a 'mouseenter' and 'mouseleave' event.
When you enter the button with your cursor, I console.log("enter");
When you leave the button, console.log("leave");
You can quickly see the problem: the two events are being triggered numerous times when hovering over the button, while the cursor is not actually leaving the element.
Also note that this problem doesn't occur when you're very slowly hovering to the left, or to the top (in a straight line), which is probably because of the 'left: e.pageX and top: e.pageY' piece of code in the script.
What can you do to fix this so the two events trigger properly?
$(document).ready(function() {
var cursor = $(".cursor");
/* Cursor */
$(document).on("mousemove", function(e) {
cursor.css({
left: e.pageX,
/*Or clientX and clientY */
top: e.pageY,
});
});
/* Button */
$(".btn").on("click", function(e) {
e.preventDefault();
});
$(".btn").on("mouseenter", function() {
console.log("entered");
});
$(".btn").on("mouseleave", function() {
console.log("left");
});
});
* {
cursor: none;
}
.cursor {
width: 10px;
height: 10px;
border-radius: 50%;
position: absolute;
background-color: black;
}
.btn {
text-decoration: none;
font-family: sans-serif;
font-weight: bold;
text-transform: uppercase;
color: black;
background-color: white;
border: 4px solid black;
padding: 0.5rem 0.8rem;
display: inline-block;
margin: 100px 100px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<!--Button-->
<div class="center marginB">
<a id="startChat" class="btn">Button</a>
</div>
<!--Cursor-->
<div class="cursor"></div>

Add pointer-events: none to your .cursor to make the cursor (black dot) never a target of any mouse events, and so it will never affect the mouse enter and mouse leave events. You can read more about pointer events here
See working example below:
$(document).ready(function() {
var cursor = $(".cursor");
/* Cursor */
$(document).on("mousemove", function(e) {
cursor.css({
left: e.pageX,
/*Or clientX and clientY */
top: e.pageY,
});
});
/* Button */
$(".btn").on("click", function(e) {
e.preventDefault();
});
$(".btn").on("mouseenter", function() {
console.log("entered");
});
$(".btn").on("mouseleave", function() {
console.log("left");
});
});
* {
cursor: none;
}
.cursor {
width: 10px;
height: 10px;
border-radius: 50%;
position: absolute;
background-color: black;
pointer-events: none;
}
.btn {
text-decoration: none;
font-family: sans-serif;
font-weight: bold;
text-transform: uppercase;
color: black;
background-color: white;
border: 4px solid black;
padding: 0.5rem 0.8rem;
display: inline-block;
margin: 100px 100px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!--Button-->
<div class="center marginB">
<a id="startChat" class="btn">Button</a>
</div>
<!--Cursor-->
<div class="cursor"></div>

The problem is because there is a delay between the actual hidden cursor being moved by the user and the .cursor element moving to match its position, simply due to the performance of JS. As such the real cursor can, for a split second, go outside the bounds of .cursor and cause a mouseenter on the underlying button. The .cursor is then moved and the actual cursor then causes a mouseleave on the button as it's now over the .cursor element.
The simplest workaround would be to use CSS to set the cursor style to an image which matches the dot, as it performs far better than JS:
$(document).ready(function() {
$(".btn").on("click", function(e) {
e.preventDefault();
});
$(".btn").on("mouseenter", function() {
console.log("entered");
});
$(".btn").on("mouseleave", function() {
console.log("left");
});
});
* {
cursor: url('https://i.imgur.com/SyBk5p5.png'), auto;
}
.cursor {
width: 10px;
height: 10px;
border-radius: 50%;
position: absolute;
background-color: black;
}
.btn {
text-decoration: none;
font-family: sans-serif;
font-weight: bold;
text-transform: uppercase;
color: black;
background-color: white;
border: 4px solid black;
padding: 0.5rem 0.8rem;
display: inline-block;
margin: 100px 100px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="center marginB">
<a id="startChat" class="btn">Button</a>
</div>

You should be able to do this with just pure CSS.
Since the div that houses your button and cursor are both part of the body they are siblings of the same container. You could use this to detect the hover on the button and then in turn change the styles of the cursor.
.marginB:hover ~ .cursor { background-color: yellow; }
https://jsfiddle.net/4nrtgx8o/
EDIT: If you remove your 100px margins from your button the hover effect wouldn't happen until you actually hover on the button. With your current CSS the button itself appears much smaller than the space it actually occupies as a piece of code. That's why the hover action happens before actually reaching the button.

Related

How to fire links with jQuery?

I want to fire a link if the div around gets clicked.
This is the general logic:
$("div").click(function() {
$("div a").click();
});
div {
background-color: yellow;
padding: 20px;
margin: 10px;
}
div:active {
background-color: blue;
}
div a {
pointer-events: none;
text-decoration: none;
color: inherit;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>London</div>
<div>Paris</div>
<div>Almaty</div>
Unfortunately, it does not work. I think I would need the different href as variable or something like that. For now, probably all links would be fired at the same time, and not only the belonging one.
How is it possible to do that?
Would be thankful for help! <3
If your code would work, you would end up clicking every link that is in side of a div. It is not going to just click the link in the div you are in. So first thing you need to do is select the link in the div you clicked.
After that, you need to trigger click on the DOM element, not the jQuery object. When you trigger it on the jQuery object, it only triggers the click event listeners you bound to it.
$("div").click(function() {
$(this).find("a").get(0).click();
});
div {
background-color: yellow;
padding: 20px;
margin: 10px;
}
div:active {
background-color: blue;
}
div a {
pointer-events: none;
text-decoration: none;
color: inherit;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>London</div>
<div>Paris</div>
<div>Almaty</div>
Or just make the anchor take up the whole div so you do not need JavaScript at all.
div {
background-color: yellow;
margin: 10px;
}
div:active {
background-color: blue;
}
div a {
padding: 20px;
display :block;
width: 100%;
height: 100%;
text-decoration: none;
color: inherit;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>London</div>
<div>Paris</div>
<div>Almaty</div>
You can select the <a> of the clicked div by selecting the first <a> children of the this clicked element.
$("div").click(function() {
$(this).children('a')[0].click();
});
div {
background-color: yellow;
padding: 20px;
margin: 10px;
}
div:active {
background-color: blue;
}
div a {
pointer-events: none;
text-decoration: none;
color: inherit;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>London</div>
<div>Paris</div>
<div>Almaty</div>
Add an event listener to the elements you are clicking, and in the "onclick" callback, select the a element and click it.
Array.from(document.getElementsByTagName("div")).forEach(e=>{
e.addEventListener("click",(el)=>{
el.target.querySelector("a").click()
})
})

How can I allow a click to pass through a div but still react to hover?

Say I have divA that partially overlaps divB. How can I allow clicks on divA to pass through to divB but still have hover fired when hovering over divA?
I'm aware of pointer-events:none; and this makes the clicks pass through but it also prevents the hover.
I have also tried the below, but it did not allow clicks to fall through
$(document).on('click', '.feedback-helper', function(e){
e.preventDefault();
})
Picture the relation of the divs like:
Here is the why of it (read as: "let's avoid an X Y problem"):
I'm working on an implementation of feedback.js
To see the issue:
view the feedback.js demo
click the feedback button in the bottom right
draw a box on the screen to highlight a section
click the "black out" button
try to draw a box inside the first box you can't because the click is blocked by the first box
I need to allow drawing a blackout box over a highlighted area but if I set pointer-events:none; I will lose other hover functionality I have on those elements.
Here is a jsFiddle example
All solutions welcome
I checked your example page and if you set a slightly lower z-index on data-type="highlight" that could take care of the problem, try a z-index of 29990 in comparison to your current 30000. This should allow you to target the highlighted feedback area and overlay it with the blackout elements.
You could get the click event for the overlaying element to initiate the click event for the underlying element.
Native JS Example:
document.getElementById('divA').addEventListener('click', function() {
alert('Clicked A');
});
document.getElementById('divB').addEventListener('click', function() {
var event = document.createEvent('HTMLEvents');
event.initEvent('click', true, false);
document.getElementById('divA').dispatchEvent(event);
});
div {
cursor: pointer;
border: 1px solid black;
}
#divA {
height: 300px;
width: 300px;
background: whitesmoke;
}
#divB {
height: 30px;
width: 30px;
background: grey;
position: absolute;
left: 100px;
top: 100px;
}
#divB:hover {
background: green;
}
<div id="divA"></div>
<div id="divB"></div>
jQuery Example:
$('#divA').on('click', function() {
alert('Clicked A');
});
$('#divB').on('click', function() {
$('#divA').trigger('click');
});
div {
cursor: pointer;
border: 1px solid black;
}
#divA {
height: 300px;
width: 300px;
background: whitesmoke;
}
#divB {
height: 30px;
width: 30px;
background: grey;
position: absolute;
left: 100px;
top: 100px;
}
#divB:hover {
background: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="divA"></div>
<div id="divB"></div>
Another option is to use a pseudo element instead. Perhaps that will do what you need.
$('#toggleBlack').on('click', function() {
$('#divA').toggleClass('hidden');
});
div {
border: 1px solid black;
}
#divA {
background: whitesmoke;
position: relative;
}
#divA.hidden:before {
position: absolute;
content: ' ';
top: 0;
left: 0;
right: 0;
bottom: 0;
background: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="divA">Highlight the text once I'm hidden and cut/copy/drag</div>
<br />
<br />
<button id="toggleBlack">Toggle Hidden</button>

Animate depending if input box is empty and stay there?

I am trying to make an input box that looks like it has a placeholder that says username, but when the box is selected it moves and changes to a darker color to resemble a label. The problem I am having is whenever I hover over the box it will complete the animation but then immediately undo it, putting the text back to look like a placeholder. I also want to make my Javascript/JQuery code so that if the box has any typing in it that the text will stay as a label and not go back to being the placeholder even without being selected. My other problem is that I do not know the JQuery command to tell if an input box is selected or not. I supply all my code below along with a link to CodePen which has the
<div id='inputdiv'>
<input id='textinp'>
</div>
<h4>Username</h4>
#textinp {
border: none;
width: 200px;
height: 30px;
font-size: 20px;
margin-left: 5px;
font-family: 'Roboto', sans-serif;
background: rgba(0, 0, 0, 0);
}
input:focus {
outline: 0;
}
#inputdiv {
width: 200px;
height: 32px;
margin: 0 auto;
margin-top: 70px;
border-top: 1px solid black;
border-right: none;
border-left: 1px solid black;
border-bottom: none;
z-index: -2;
}
h4 {
font-family: 'Roboto', sans-serif;
font-size: 20px;
position: relative;
bottom: 53px;
left: 575px;
color: #C2C2C2;
z-index: -1;
}
$(document).ready(function() {
$("#inputdiv").mouseenter(function() {
$("h4").animate({
left: '470px',
color: '#00000'
});
if ($('#textinp').val() == '') {
$("h4").animate({
left: '580px',
color: '#C2C2C2'
});
}
});
});
CodePen
Try using hover() method instead. As first parameter define function to be executed on hoverIn (on mouse entering), as second - function to be executed on hoverOut (on mouse leaving).
Here's your example updated:
http://codepen.io/anon/pen/LprybQ

Prevent div from showing after slideUp() - jQuery

I'm trying to make a small piece of code, so when I click on the question mark, it shows another div. However, when I click on the body, it should hide the just revealed div.
The problem I am running into, is that even though I use .slideUp() when the person clicks on the body (note: the body is only clickable on the height of the ?), it also shows after clicking on the body again. How do I make it so clicking on body won't show the .popover again? If I add .hide() after .slideUp(), it just hides it directly and the slideUp effect is gone.
CodePen
HTML
<div class="center">
<span class="qs">? <span class="popover above">Voeg toe aan wensenlijst</span></span>
</div>
CSS
body {
background-color: #e3fbff;
}
/* Just to center things */
.center {
margin: 100px auto;
width: 30px;
}
/* The element to click on */
.qs {
background-color: #02bdda;
border-radius: 16px;
color: #e3fbff;
cursor: default;
display: inline-block;
font-family: 'Helvetica',sans-serif;
font-size: 18px;
font-weight: bold;
height: 30px;
line-height: 30px;
position: relative;
text-align: center;
width: 30px;
.popover {
background-color: rgba(0,0,0,0.85);
border-radius: 5px;
top: 42px;
box-shadow: 0 0 5px rgba(0,0,0,0.4);
color: #fff;
font-size: 12px;
display:none;
font-family: 'Helvetica',sans-serif;
left: -95px;
padding: 7px 10px;
position: absolute;
width: 200px;
z-index: 4;
}
}
jQuery
$(".qs").click(function(){
$(".popover ").slideToggle();
});
$('body').click(function() {
// Hide all hidden content
$('.popover').slideUp();
});
$('.popover').click(function(e) { e.stopPropagation() });
$('.qs').click(function(e) {
// this stops the event from then being caught by the body click binding
e.stopPropagation();
});
Hide the tooltip when clicking, if it is visible.
You don't need more code than this:
var popover = $('.popover');
var qs = $('.qs');
qs.click(function(e){
e.stopPropagation();
popover.slideToggle();
});
$('html').click(function() {
if(popover.is(':visible')) {
popover.slideUp();
}
});
$('.popover').click(function(e) { e.stopPropagation() });
Codepen
You can check if .popover is visible like:
$('body').click(function() {
// Hide all hidden content
if($('.popover').is(":visible"))
$('.popover').slideUp();
});
Also you don't need to use slideup() and hide() together.
codepen
You need to make sure the popup is not click on you can do a check like this
var mouse_is_inside = false;
$('.popover').hover(function() {
mouse_is_inside=true;
}, function() {
mouse_is_inside=false;
});
$("body").live('mouseup', function() {
if(! mouse_is_inside)
$('.popover').slideUp();
});

Strange onclick behavior after add style to div

I have html:
<div>
<div id='icon_zoom_in' class='icon'>+</div>
<div id='icon_zoom_out' class='icon'>-</div>
</div>
And I add CSS:
.icon{
color: white;
font-size: 100px;
background-color: black;
opacity: 0.7;
-webkit-border-radius: 20px;
-moz-border-radius: 20px;
width: 70px;
height: 70px;
text-align: center;
line-height: 50px;
cursor: pointer;
}
The result is nice (ignore the font, I installed a Chrome extension):
But when I add click event on their "buttons", strange things happen:
var $ = function(id) {
return document.getElementById(id);
}
$("icon_zoom_in").addEventListener("click", function() {
console.log("zoom in");
}, false);
$("icon_zoom_out").addEventListener("click", function() {
console.log("zoom out");
}, false);
When I click the "+" button, I got zoom out! I have to click the outer space of it to get zoom in.
jsfiddle: http://jsfiddle.net/wong2/w2dRB/
Super simple: in Chrome the text is overflowing. Actually when you click the plus you are clicking the minus because of this. Use overflow: hidden; and the plus and minus will stick inside the buttons.
Here (JSFiddle) you can test the correct behaviour.

Categories