Bug in Function to detect mouse direction - javascript

i have written a function to detect mouse direction and it works but it has a bug.When i put mouse's pointer from left into the div for the first time the function calculate that mouse's pointer has moved to right direction when it is called for the first time,then it works well.I don't know if i explained wll my issue but you can easily see the bug in your browser's console seeing at the first printed values.
This is my code
<body>
<div id="padre-relative">
</div>
</body>
#padre-relative{
position:relative;
width:300px;
height:300px;
overflow: hidden;
background: red;
margin-left:300px;
}
window.onload=function(){
var storageMousePositionX=0;
var positionMouseX=0;
document.getElementById("padre-relative").onmousemove= function(){
positionMouseX=event.clientX;
if(positionMouseX > storageMousePositionX){
console.log("right");
}
if(positionMouseX < storageMousePositionX){
console.log("left");
}
storageMousePositionX=positionMouseX;
};
};

This is beacause you set your var storageMousePositionX to 0 on load. You should set it for the first time when you enter the div.
document.getElementById("padre-relative").onmouseenter = function(){
storageMousePositionX = event.clientX;
}
See this fiddle

Your issue is that you are initializing storageMousePositionX to 0, so the first time your onmousemove handler fires, event.clientX will always be greater than 0, so it will always log "right" the first time.
One way to fix it would be to initialize it to -1 and then check against that value so you don't log something the first time the mouse moves over the div:
window.onload = function(){
var storageMousePositionX=-1;
document.getElementById("padre-relative").onmousemove = function(){
var positionMouseX=event.clientX;
if (storageMousePositionX > -1) {
if(positionMouseX > storageMousePositionX){
console.log("right");
}
if(positionMouseX < storageMousePositionX){
console.log("left");
}
}
storageMousePositionX = positionMouseX;
};
};

Related

Why the key event causes snappy transitions?

I can't understand why two quick button clicks cause the div shown to transition slowly from its last position to the initial position (as I want) but two quick key events to make it snap to the initial position.
In the following code, the button click and a window key event initially transition the div to the right by 500px. On the next firing, they take it back to its original position. Quick firing will cause the div to quickly go to some position on the right and come back again.
With two button clicks I face no problem. But with two quick right-arrow key clicks I notice snappy behaviour. Any suggestions will really be appreciated, because I couldn't find any explanation to this strange behaviour.
var ele = document.getElementById("f");
var key = true;
var buttons = document.getElementsByTagName("button")
var counter = 0;
var c = [0,500];
function demo() {
counter = !counter + 0;
navigateSlider();
}
// code to account for KEY
if (key) {
window.onkeydown = function (e) {
console.log(e.keyCode);
if (e.keyCode == 39) {
buttons[0].click();
}
}
}
function navigateSlider() {
ele.style.transition = "1s ease";
ele.style.transform = "translateX(" + c[counter] + "px)";
}
<div id="f" style="background-color: grey; border-radius: 10px;border: 1px solid black; padding: 50px;display: inline-block"></div>
<br><br>
<button onclick="demo()">Go Right</button>
Can't say exactly why but if you trigger click event with '0' timeout it works better.
if (e.keyCode == 39) {
setTimeout(function(){
buttons[0].click();
}, 0);
}
It definitely seems handling keyboard events somehow interrupts CSS transitions in Chrome and Firefox.

How to make scroll animation work when you scroll both ways (down AND up)

I'm trying to make a small animation on my web page which is triggered using .scroll() function.
My .js script is:
$(window).scroll(function(){
var s = $(document).scrollTop();
if(s >= 2400)
{
$("#top").animate({
"top":"820px",
"left":"0"
},'linear');
}
})
It works when I scroll down, but I would like element with id #top to get back to it's original position after I scroll back up. Any help would be appreciated :)
CSS:
#top{
height:200px;
width:200px;
display:block;
margin-left:auto;
margin-right:auto;
top: 860px;
position:relative;
}
Ok, I did it. Sort of.
var line = 2500;
var isMyHeadOpen = false;
$(window).scroll(function(){
var s = $(document).scrollTop();
if(s >= line && !isMyHeadOpen) {
isMyHeadOpen = true;
$("#top").animate({
"top":"840px",
"left":"0"
},'linear');
} else if (s < line && isMyHeadOpen) {
isMyHeadOpen = false;
$("#top").animate({
"top":"880px",
"left":"0"
},'linear');
}
})
When I scroll to line 2500, animation triggers. When I scroll back, animation moves back to original place. The thing is variable line depends on monitor resolution so it should somehow be dynamic and I have no idea how to fix that.

scroll to a div when scrolling, and scroll to top when div disappear

I have 2 divs on my webpage. first div is "#pattern" (red one), and second on is "#projets".(blue one)
when use scrolls for the first time, the window scrolls automaticaly to the the second div "#projets". I'm using jquery scroll-To plugin.
it works nice, even if when the users scroll with a large amount of scroll there could be on offset from the "#projets" div... If someone has an idea to correct this would be nice, but that's not my main trouble...
Now i'm trying to scroll back to the top of the page ("#pattern" div) as soon as "#pattern" div reappears when scrolling, the red one. so basically it should be as soon as the offset from the top of my screen of my div "#projets" is supperior to 1.
I've tried so many solutions without results, using flags, multiple conditions... it can be the same kind of thing as on this page, but user should be abble to scroll freely inside the page, not scrolling from hash to hash :
http://www.thepetedesign.com/demos/onepage_scroll_demo.html
here is my html :
<div id="pattern"></div>
<div id="projets"></div>
my css :
#pattern {
height:300px;
width: 100%;
background-color:red
}
#projets {
height:800px;
width: 100%;
background-color:blue
}
and my jquery :
var flag=0 ;
$(window).on('scroll',function(){
var top_projets_position = $("#projets").offset().top - $(window).scrollTop();
if((flag==0) && $(window).scrollTop()>1){
$(window).scrollTo('#projets', 500);
flag=1;
}
if($(window).scrollTop()==0){
flag=0;
}
});
here is jsfiddle :
http://jsfiddle.net/jdf9q0sv/
hope someone can help me with this, I can't figure out what I'm doing wrong, maybe a wrong method ! thanks
It looks like you need to track 3 things:
The scroll direction occurs.
The area you are currently viewing.
If scroll animation is currently happening (we need to wait until it's done, or problems will occur).
http://jsfiddle.net/vx69t5Lt/
var prev_scroll = 0; // <-- to determine direction of scrolling
var current_view ="#pattern"; // <-- to determine what element we are viewing
var allowed = true; // <-- to prevent scrolling confusion during animation
var top_projets_position = $("#projets").offset().top + 1;
$(window).on('scroll',function(){
var current_scroll = $(window).scrollTop();
if(current_scroll < top_projets_position && current_view=="#projets" && current_scroll < prev_scroll){
scrollToTarget("#pattern");
}
if($(window).height() + current_scroll > top_projets_position && current_view=="#pattern" && current_scroll > prev_scroll){
scrollToTarget("#projets");
}
prev_scroll = current_scroll;
});
function scrollToTarget(selector){
if(allowed){
allowed = false;
$(window).scrollTo(selector, {
'duration':500,
'onAfter': function(){ allowed = true; current_view = selector;}
});
}
}
This is just a quick solution based on your original code. A better solution would be to do something more Object Oriented (OOP) and track values in an object. Perhaps take an array of elements on object creation, grab all the boundaries and use the boundaries in your scroll handler to determine when to scroll to the next div.

without jquery i need to find out if the mouse is over an element, not determine when it becomes over (in case it doesn't move to trigger onmouseover)

without jquery
basically what I am looking for is the ability to see if the mouse is over a div when a countdown finishes
if the user is over the div then perform action for that div
onmouseover only triggers when the mouse crosses the threshold of the div, if the mouse hasn't moved it wouldn't trigger, so that wouldn't work
I need to determine if the mouse is currently over a div at a specific point in time, if it has moved or not from the starting point
all of my hunting has only found onmousover, and nothing to see if the mouse just happens to be there to begin with
I don't have the javascript skills to determine overall coords of div, then map mouse coords and see if it fits there... which is what I believe I need to do
After reading the second answer (the one with millions of a elements) on this SO question, I've came up with this method works without moving the mouse on page load, without involving millions of elements.
HTML
<div id=t></div>
CSS
#t {
/* for illustrative purposes */
width: 10em;
height: 5em;
background-color: #0af;
}
#t:hover {
border-top-style: hidden;
}
JavaScript
document.addEventListener('click', function () {
var c = window.getComputedStyle(document.getElementById('t')).getPropertyValue('border-top-style');
if (c === 'hidden') {
alert('Mouse in box');
} else {
alert('Mouse not in box');
}
}, false);
As stated earlier, bind to the finish event of your countdown instead of the click event on the document.
You may also use any CSS style that's changed on :hover, I chose border-top-style as it is conspicuous. If you're using a border, choose something else.
Here's a jsFiddle.
set a flag to true onmouseover and to false onmouseleave. when countdown finishes if flag is true then it is over element.
HTML
<div id="div-name">the section of the code i am working with has a countdown timer, when it reaches 0 i need to know if the mouse is over a specific box</div>
<button id="notification" onclick="javascript: letsCountIt(5);">click to start countdown</button>
JS
window.ev = false;
document.getElementById('div-name').onmouseover = function () {
window.ev = true;
console.log(window.ev);
}
document.getElementById('div-name').onmouseout = function () {
window.ev = false;
console.log(window.ev);
}
window.letsCountIt = function (cdtimer) {
cdtimer--;
document.getElementById('notification').innerHTML = cdtimer;
if (cdtimer == 0) {
if (window.ev === true) {
alert('over');
} else {
alert('not over');
}
} else {
setTimeout(function(){letsCountIt(cdtimer);}, 1000);
}
}
Look into document.elementFromPoint . When you pass an x,y to elementFromPoint, it will return whatever element (or <body>, if no other specific element) is at that point. You can easily check if this element is the element you want.
The problem then is finding out what point your mouse is at. How to get the mouse position without events (without moving the mouse)? seems to say - don't. At least use mouseMove to track the cursor. The linked question gives examples of how to do so. (Look to the lower scoring answers, as the higher ones only got points for being snarky.)
Just want to say that, I think jQuery's mouseenter and mouseleave events would make this a lot easier, but if you can't use them, maybe this will help you.
Depending on how your page is laid out, this may not be too difficult. You can get the position of your element using the following. Quoting from another answer
element.offsetLeft and element.offsetTop are the pure javascript
properties for finding an element's position with respect to its
offsetParent; being the nearest parent element with a position of
relative or absolute
So, if your element is positioned relatively to the body, so far so good (We don't need to adjust anything).
Now, if we attach an event to the document mousemove event, we can get the current coordinates of the mouse:
document.addEventListener('mousemove', function (e) {
var x = e.clientX;
var y = e.clientY;
}, false);
Now we just need to determine if the mouse falls within the element. To do that we need the height and width of the element. Quoting from another answer
You should use the .offsetWidth and .offsetHeight properties. Note
they belong to the element, not .style.
For example:
var element = document.getElementById('element');
var height = element.offsetHeight;
var width = element.offsetWidth;
Now we have all the information we need, and just need to determine if the mouse falls within the element. We might use something like this:
var onmove = function(e) {
var minX = element.offsetLeft;
var maxX = minX + element.offsetWidth;
var minY = element.offsetTop;
var maxY = minY + element.offsetHeight;
if(e.clientX >= minX && e.clientX <= maxX)
//good horizontally
if(e.clientY >= minY && e.clientY <= maxY)
//good vertically
}
This code works, but the mouse has to be moved once after page load.
var coords;
var getMouseCoordinates = function (e) {
'use strict';
return {
x: e.clientX,
y: e.clientY
};
};
document.addEventListener('mousemove', function (e) {
coords = getMouseCoordinates(e);
}, false);
document.addEventListener('click', function () {
var divCoords = document.getElementById('t').getBoundingClientRect();
if (coords.x >= divCoords.left && coords.x <= divCoords.right && coords.y >= divCoords.top && coords.y <= divCoords.bottom) {
alert('Mouse in box');
} else {
alert('Mouse not in box');
}
}, false);
You wouldn't bind to the click event of document, but rather the finish event of your countdown.
Here's an example. Try clicking in the output window.
You don't need any coordinates or mouse events, if you know a selector for that element:
if (document.querySelector('#elementSelector:hover')) {
alert('I like it when you touch me!');
}

JQuery hide mouse if it's not moving

I'm trying to hide the mouse if it hasn't moved for a period of time.
This is the code I'm using:
$(document).ready(function() {
var j;
$(document).mousemove(function() {
clearTimeout(j);
$('html').css({cursor: 'default'});
j = setTimeout('hide();', 1000);
});
});
function hide() {
$('html').css({cursor: 'none'});
}
When the hide() function is called the cursor is hidden, but unhides a split second later. Any help is appreciated.
Your initial problem is that the hiding of the mouse triggers mousemove and thus immediately resets it back to default. So you could solve that like this...
var justHidden = false;
$(document).ready(function() {
var j;
$(document).mousemove(function() {
if (!justHidden) {
justHidden = false;
console.log('move');
clearTimeout(j);
$('html').css({cursor: 'default'});
j = setTimeout('hide();', 1000);
}
});
});
function hide() {
$('html').css({cursor: 'none'});
justHidden = true;
}​
...BUUUUUT...
You face a problem here which at the moment seems unsolvable to me. That is, a hidden mouse does not trigger mousemove ever, so once it's hidden you will not be able to unhide it as far as I can tell.
I'll keep investigating to see if there's a solution I'm missing.
I found this thread when I was looking for solution for this challenge in 2019. Based on answer here and in 'Hiding the mouse cursor when idle using JavaScript' I made a slightly different solution:
var DEMO = {
INI: {
MOUSE_IDLE: 3000
},
hideMouse: function() {
$("#game").css('cursor', 'none');
$("#game").on("mousemove", DEMO.waitThenHideMouse);
},
waitThenHideMouse: function() {
$("#game").css('cursor', 'default');
$("#game").off("mousemove", DEMO.waitThenHideMouse);
setTimeout(DEMO.hideMouse, DEMO.INI.MOUSE_IDLE);
},
showMouse: function() {
$("#game").off("mousemove", DEMO.waitThenHideMouse);
$("#game").css('cursor', 'default');
},
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
This simple and clear example gives you the option to start hiding mouse (DEMO.hideMouse()) and also to turn this off (DEMO.showMouse()). It does not create multiple events on same element. This example shows hiding mouse pointer over #game div element. Just change this to the div of your choice or body.
As of fully updated Chrome and FF in October 2019: it works on both.
I'm 8 years late but I have a solution:
• First of all download an image of a cursor from the internet or copy my svg code:
<svg id="cursor" width="20" height="20" viewBox="0 0 95 92" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M84.6925 46.0105L40.25 20.3516C35.25 17.4648 29 21.0733 29 26.8468L29 78.1645C29 84.9879 37.3721 88.2664 42.0056 83.2575L58.1424 65.8134C58.4853 65.4427 58.9324 65.1846 59.4249 65.0729L82.6003 59.8201C89.255 58.3118 90.6017 49.4222 84.6925 46.0105Z" fill="black" stroke="white" stroke-width="5"/></svg>
And add it to your html file.
•Of course, if you want to made it in jQuery, you need to add this script above your js file:
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
•Then add this (in your JavaScript file):
let timedelay = 1;
function delayCheck() {
if (timedelay == 2) { //Here you can change this value which changes the time it takes the mouse to hide
$('#cursor').fadeOut();
timedelay = 1;
}
timedelay += 1;
}
$(document).mousemove(function() {
$('#cursor').fadeIn();
timedelay = 1;
clearInterval(_delay);
_delay = setInterval(delayCheck, 1000);
});
_delay = setInterval(delayCheck, 1000);
Now you'll see just a cursor on the top left of the screen that does what you asked but it's not YOUR cursor, to replace the cursor with the svg do the following:
//in the same js file as before
$(document).mousemove(function (e) {
$('#cursor').offset({
left: e.clientX,
top: e.clientY
});
});
/* on the css */
html {
cursor: none;
}
If it doesn't work, make sure that you put the jquery file ABOVE the file you wrote.
I hope I have helped someone!
You might want to check if this really works, here's the demo.
(Sorry if my English was bad, I'm italian).
(Tip) You will notice that there are two identical functions, if you want to merge them just replace them with this:
$(document).mousemove(function(e) {
$('#cursor').fadeIn();
timedelay = 1;
clearInterval(_delay);
_delay = setInterval(delayCheck, 1000);
$('#cursor').offset({
left: e.clientX,
top: e.clientY
});
});

Categories

Resources