How to solve - DIV element flashes/disappears immediately after it is rendered - javascript

Here's what is happening:
After the page loads, JavaScript reads an XML from the underlying code
The XML contains a bunch of field-ids, and corresponding content to display in popups when the mouse hovers over a field id listed
My code generates a bunch of popups as div-elements with the styles:
.render{
background-color: #fffc80;
border: .1em solid rgb(200, 128, 0);
padding-left: 2px;
padding-right: 2px;
z-index: 1000;
}
.hide{
display:none;
}
All created popups are attached to the root element.
EDITED: Added script snippets
The event handlers are attached as below
// instantiate a div element
var myDiv = document.createElement('div');
// generate an ID
myDiv.id = generatePopupId(getFieldId());
// attach the content from the XML into the new div element
myDiv.innerHTML = getPopupContent();
// apply mouseover/out handlers to the main element
document.getElementById(getFieldId()).onmouseover = function(){
showPopup(generatePopupId(getFieldId()));
};
document.getElementById(getFieldId()).onmouseout = function(){
hidePopup(generatePopupId(getFieldId()));
};
// read the X coordinate of the present position of the mouse
function getX(){
var e = window.event;
posX = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
return posX;
}
// read the Y coordinate of the present position of the mouse
function getY(){
var e = window.event;
posY = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
return posY;
}
// Show the popup element at the current mouse location
function showPopup(popupId){
var posX = getX();
var posY = getY();
var poppyElement = document.getElementById(popupId);
poppyElement.className = 'render';
poppyElement.style.left = posX;
poppyElement.style.top = poxY;
poppyElement.style.position = 'absolute';
poppyElement.style.display = '';
}
// hide the popup element
function hidePopup(popupId){
var poppyElement = document.getElementById(popupId);
poppyElement.className = 'hide';
}
My question is - Why does the element flash, and disappear immediately instead of hanging around for the mouse-out event?

Changing the elements in the JavaScript may be modifying the element being hovered over, which may trigger the mouse out event by changing, rather than actually moving the mouse out of the co-ordinates.

Firstly, you need to be more careful with case sensitivity. It should be clientWidth (capital W) and top (small t). Secondly, when you set CSS left and top you must add a +'px' suffix to the value; an integer on its own is not valid.
Also if you want to know the height of the viewport, document.body is the wrong place to look. This will only work in IE Quirks Mode, which you generally want to avoid like the plague. Add a Standards Mode <!DOCTYPE declaration and you can use document.documentElement across browsers. (Or branch on window.innerHeight for non-IE browsers.)
In any case unless there is more CSS you aren't showing us, setting the left and top styles will have no effect at all because the .render divs are not position: absolute. You're not showing how exactly they are attached to the document, but since they are apparently not absolutely positioned, they're part of the document flow and may cause the page to shift/reflow when they're unhidden. If that causes the element being moused over to move, it will no longer be under the pointer and you'll get a mouseout event immediately.
(This would also happen with absolute positioning if the hovered item was underneath the place the pop-up appeared.)
(Also, the hiding/unhiding is a bit redundant. Leave style.display alone and just set className to either 'render' or 'render hide'.)

Related

Moving element to specific css coordinates (top and left) not working using javascript

I am trying to move a HTML element (a puzzle piece) back to its original position on the screen after a dragEnd event, if the element is not inside a specified target zone.
I using a javascript object to represent the puzzle piece. The object contains the starting x and y for the element as well as a reference to the element itself (along with some other information). The code is below.
function dragEnd(e) {
if(selectedPiece.ele.id === "correctPiece" && selectedPiece.distanceVector < 30){
window.alert("Game End");
}
else{
console.log("returning piece: ", selectedPiece.ele.id);
console.log("to point ", selectedPiece.startX, selectedPiece.startY);
selectedPiece.ele.style.position = "absolute";
selectedPiece.ele.style.left = selectedPiece.startX;
selectedPiece.ele.style.top = selectedPiece.startY;
}
active = false;
}
Still when I drop the piece it stays wherever it was dropped.
When I look at the console it shows the element id and identifies the correct startX and startY properties. I have also tried appending "px" to the startX and startY with no luck.
Any help appreciated thanks :)
I have tried hard coding the values and the pieces ends up moving but not to the x,y position that has been coded
Then, try this:
selectedPiece.ele.style.left = selectedPiece.startX + "px";
selectedPiece.ele.style.top = selectedPiece.startY + "px";
but not to the x,y position that has been coded
Secondly, make sure you understand how CSS absolute works. From MDN's article:
The absolutely positioned element is positioned relative to its nearest positioned ancestor (i.e., the nearest ancestor that is not static).
Try making dragged element's immediate parent's position relative.

JavaScript(Canvas): How to update the pointer's position inside the animation frame and NOT inside the event listener? [duplicate]

Is it possible to get the mouse position with JavaScript after page loads without any mouse movement event (without moving the mouse)?
Real answer: No, it's not possible.
OK, I have just thought of a way. Overlay your page with a div that covers the whole document. Inside that, create (say) 2,000 x 2,000 <a> elements (so that the :hover pseudo-class will work in IE 6, see), each 1 pixel in size. Create a CSS :hover rule for those <a> elements that changes a property (let's say font-family). In your load handler, cycle through each of the 4 million <a> elements, checking currentStyle / getComputedStyle() until you find the one with the hover font. Extrapolate back from this element to get the co-ordinates within the document.
N.B. DON'T DO THIS.
Edit 2020: This does not work any more. It seems so, that the browser vendors patched this out. Because the most browsers rely on chromium, it might be in its core.
Old answer:
You can also hook mouseenter (this event is fired after page reload, when the mousecursor is inside the page). Extending Corrupted's code should do the trick:
var x = null;
var y = null;
document.addEventListener('mousemove', onMouseUpdate, false);
document.addEventListener('mouseenter', onMouseUpdate, false);
function onMouseUpdate(e) {
x = e.pageX;
y = e.pageY;
console.log(x, y);
}
function getMouseX() {
return x;
}
function getMouseY() {
return y;
}
You can also set x and y to null on mouseleave-event. So you can check if the user is on your page with it's cursor.
What you can do is create variables for the x and y coordinates of your cursor, update them whenever the mouse moves and call a function on an interval to do what you need with the stored position.
The downside to this of course is that at least one initial movement of the mouse is required to have it work. As long as the cursor updates its position at least once, we are able to find its position regardless of whether it moves again.
var cursor_x = -1;
var cursor_y = -1;
document.onmousemove = function(event)
{
cursor_x = event.pageX;
cursor_y = event.pageY;
}
setInterval(check_cursor, 1000);
function check_cursor(){console.log('Cursor at: '+cursor_x+', '+cursor_y);}
The preceding code updates once a second with a message of where your cursor is.
#Tim Down's answer is not performant if you render 2,000 x 2,000 <a> elements:
OK, I have just thought of a way. Overlay your page with a div that
covers the whole document. Inside that, create (say) 2,000 x 2,000
elements (so that the :hover pseudo-class will work in IE 6, see),
each 1 pixel in size. Create a CSS :hover rule for those elements
that changes a property (let's say font-family). In your load handler,
cycle through each of the 4 million elements, checking
currentStyle / getComputedStyle() until you find the one with the
hover font. Extrapolate back from this element to get the co-ordinates
within the document.
N.B. DON'T DO THIS.
But you don't have to render 4 million elements at once, instead use binary search. Just use 4 <a> elements instead:
Step 1: Consider the whole screen as the starting search area
Step 2: Split the search area into 2 x 2 = 4 rectangle <a> elements
Step 3: Using the getComputedStyle() function determine in which rectangle mouse hovers
Step 4: Reduce the search area to that rectangle and repeat from step 2.
This way you would need to repeat these steps max 11 times, considering your screen is not wider than 2048px.
So you will generate max 11 x 4 = 44 <a> elements.
If you don't need to determine the mouse position exactly to a pixel, but say 10px precision is OK. You would repeat the steps at most 8 times, so you would need to draw max 8 x 4 = 32 <a> elements.
Also generating and then destroying the <a> elements is not performat as DOM is generally slow. Instead, you can just reuse the initial 4 <a> elements and just adjust their top, left, width and height as you loop through steps.
Now, creating 4 <a> is an overkill as well. Instead, you can reuse the same one <a> element for when testing for getComputedStyle() in each rectangle. So, instead of splitting the search area into 2 x 2 <a> elements just reuse a single <a> element by moving it with top and left style properties.
So, all you need is a single <a> element change its width and height max 11 times, and change its top and left max 44 times and you will have the exact mouse position.
You could try something similar to what Tim Down suggested - but instead of having elements for each pixel on the screen, create just 2-4 elements (boxes), and change their location, width, height dynamically to divide the yet possible locations on screen by 2-4 recursively, thus finding the mouse real location quickly.
For example - first elements take right and left half of screen, afterwards the upper and lower half. By now we already know in which quarter of screen the mouse is located, are able to repeat - discover which quarter of this space...
Here's my solution. It exports window.currentMouseX and window.currentMouseY properties you can use anywhere. It uses the position of a hovered element (if any) initially and afterwards listens to mouse movements to set the correct values.
(function () {
window.currentMouseX = 0;
window.currentMouseY = 0;
// Guess the initial mouse position approximately if possible:
var hoveredElement = document.querySelectorAll(':hover');
hoveredElement = hoveredElement[hoveredElement.length - 1]; // Get the most specific hovered element
if (hoveredElement != null) {
var rect = hoveredElement.getBoundingClientRect();
// Set the values from hovered element's position
window.currentMouseX = window.scrollX + rect.x;
window.currentMouseY = window.scrollY + rect.y;
}
// Listen for mouse movements to set the correct values
window.addEventListener('mousemove', function (e) {
window.currentMouseX = e.pageX;
window.currentMouseY = e.pageY;
}, /*useCapture=*/true);
}())
Composr CMS Source: https://github.com/ocproducts/composr/commit/a851c19f925be20bc16bfe016be42924989f262e#diff-b162dc9c35a97618a96748639ff41251R1202
The most simple solution but not 100% accurate
$(':hover').last().offset()
Result: {top: 148, left: 62.5}
The result depend on the nearest element size and return undefined when user switched the tab
Yes, It's possible.
If you add "mouseover" event to the document it will fire instantly and you can get the mouse position, of course if mouse pointer was over the document.
document.addEventListener('mouseover', setInitialMousePos, false);
function setInitialMousePos( event ) {
console.log( event.clientX, event.clientY);
document.removeEventListener('mouseover', setInitialMousePos, false);
}
Previously it was possible to read mouse position through window.event but it's deprecated now.
var x = 0;
var y = 0;
document.addEventListener('mousemove', onMouseMove, false)
function onMouseMove(e){
x = e.clientX;
y = e.clientY;
}
function getMouseX() {
return x;
}
function getMouseY() {
return y;
}
I implemented a horizontal/vertical search, (first make a div full of vertical line links arranged horizontally, then make a div full of horizontal line links arranged vertically, and simply see which one has the hover state) like Tim Down's idea above, and it works pretty fast. Sadly, does not work on Chrome 32 on KDE.
jsfiddle.net/5XzeE/4/
You do not have to move the mouse to get the cursor's location. The location is also reported on events other than mousemove. Here's a click-event as an example:
document.body.addEventListener('click',function(e)
{
console.log("cursor-location: " + e.clientX + ',' + e.clientY);
});
Riffing on #SuperNova's answer, here's an approach using ES6 classes that keeps the context for this correct in your callback:
class Mouse {
constructor() {
this.x = 0;
this.y = 0;
this.callbacks = {
mouseenter: [],
mousemove: [],
};
}
get xPos() {
return this.x;
}
get yPos() {
return this.y;
}
get position() {
return `${this.x},${this.y}`;
}
addListener(type, callback) {
document.addEventListener(type, this); // Pass `this` as the second arg to keep the context correct
this.callbacks[type].push(callback);
}
// `handleEvent` is part of the browser's `EventListener` API.
// https://developer.mozilla.org/en-US/docs/Web/API/EventListener/handleEvent
handleEvent(event) {
const isMousemove = event.type === 'mousemove';
const isMouseenter = event.type === 'mouseenter';
if (isMousemove || isMouseenter) {
this.x = event.pageX;
this.y = event.pageY;
}
this.callbacks[event.type].forEach((callback) => {
callback();
});
}
}
const mouse = new Mouse();
mouse.addListener('mouseenter', () => console.log('mouseenter', mouse.position));
mouse.addListener('mousemove', () => console.log('mousemove A', mouse.position));
mouse.addListener('mousemove', () => console.log('mousemove B', mouse.position));
Not mouse position, but, if you're looking for current cursor postion (for use cases like getting last typed character etc) then, below snippet works fine.
This will give you the cursor index related to text content.
window.getSelection().getRangeAt(0).startOffset
I envision that maybe you have a parent page with a timer and after a certain amount of time or a task is completed, you forward the user to a new page. Now you want the cursor position, and because they are waiting, they aren't necessarily touching the mouse. So track the mouse on the parent page using standard events and pass the last value to the new page in a get or a post variable.
You can use JHarding's code on your parent page so that the latest position is always available in a global variable:
var cursorX;
var cursorY;
document.onmousemove = function(e){
cursorX = e.pageX;
cursorY = e.pageY;
}
This won't help users that navigate to this page by means other than your parent page.
I think i may have a reasonable solution with out counting divs and pixels..lol
Simply use animation frame or a time interval of a function. you will still need a mouse event one time though just to initiate, but technically you position this where ever you like.
Essentially we are tracking a dummy div at all times with out mouse movement.
// create a div(#mydiv) 1px by 1px set opacity to 0 & position:absolute;
Below is the logic..
var x,y;
$('body').mousemove(function( e ) {
var x = e.clientX - (window.innerWidth / 2);
var y = e.clientY - (window.innerHeight / 2);
}
function looping (){
/* track my div position 60 x 60 seconds!
with out the mouse after initiation you can still track the dummy div.x & y
mouse doesn't need to move.*/
$('#mydiv').x = x; // css transform x and y to follow
$('#mydiv)'.y = y;
console.log(#mydiv.x etc)
requestAnimationFrame( looping , frame speed here);
}

Function to get position of an element relative to the top-most window

This has probably been asked already, but I was not able to find any fix for what I am trying to do.
I am trying to find the magical combination of properties on the event object, along with scrolling and other offsets, to give me the position of an element relative to the top-most window that may or may not exist within an iframe. I am doing this in an attempt to fade in a small (absolutely positioned) image to the right of the element that is being moused over.
I am trying to get the position inside of a jQuery hover event. I have tried different combinations of the following properties:
$(element).position()
$(element).offset()
$(element).scrollTop()
$(element).scrollLeft();
$(document).scrollTop();
$(document).scrollLeft();
event.clientX
event.clientY
event.pageX
event.pageY
Does anyone have a function or equation that can give these numbers?
The easiest way in modern browsers is document.querySelector('.foo').getBoundingClientRect() which return's and object containing the properties top and left, which are the offsets of the element relative to the viewport.
The above method works in IE >= 5 with a couple of easy hacks see http://ejohn.org/blog/getboundingclientrect-is-awesome/
Alternatively you can use the jQuery.offset() method, if you have jQuery on the page. Which will return the elements offset consistently cross browser.
Getting the offset of said element from an <iframe> can be a bit trickier depending on where your trying to get the position from i.e. is the script running on the same page as the element which might be in an <iframe>, or in the root page with the element in the <iframe>
If you are in the first case, you don't need to do anything as long as your element is being repositioned somewhere inside the <iframe> as you already have the correct offset.
if you are outside the <iframe> you need to take the iframe.getBoundClientRect() offsets into consideration, as the element.getBoundingClientRect() is relative to it's own viewport (the <iframe>)
I've managed to finagle some code that worked for this situation. Hope this helps someone in the future:
var timeoutID;
$(element).hover(function () {
// cancel any pending fades
window.clearTimeout(timeoutID);
var offset = {
left: 0,
top: 0
};
if (top !== self) {
offset = top.$('#divContainingIframes').offset();
}
var that = $(this);
var elementPosition = that.position();
var xCoord = offset.left + // distance between screen and iframe
elementPosition.left + // distance between iframe and element
that.width() + // width of the element
5; // 5 pixel padding
var yCoord = offset.top + // distance between screen and iframe
elementPosition.top; // distance between iframe and element
// call the show function with xCoord and yCoord
}, function () {
// don't fade immediately, wait a half second
timeoutID = setTimeout(function () {
// call some hide function
}, 500);
});

How can I hide this overlay element intelligently?

The site I'm working on has a collection of navigation elements across the top ("Products", "Company", etc.). When you mouse over the Products link, an overlay appears that shows a list of products with links to each. There's a small link at the top of the container that, when clicked, closes the container. All of this works as advertised.
The client has asked that, once a user's mouse pointer is a sufficient distance from the overlay element, the overlay element would close (without them having to click the 'close' link). This element appears on multiple pages that have disparate content, so I'm afraid it won't be as simple as adding a mouseover listener to another single element within the page and have it work everywhere. My question, I suppose, is this: is there a relatively easy way to know when the mouse cursor is x pixels away from this container and trigger an event when this occurs?
My other thought is that I could just find several elements on the page that fit this criteria and add mouseover listeners to each, but I'm assuming there's a more elegant way of handling this.
Thanks in advance - and please let me know if more detail is needed.
Here's one example.
http://jsfiddle.net/CsgFk/
Calculate the bounds you want around the overlay, and set up a mousemove hanlder on the document, which tests to see if the mouse is outside the bounds.
EDIT: It may be worthwhile to unbind the mousemove from the document when the overlay is hidden, and rebind it when revealed so that the mousemove isn't constantly firing for no reason. Or at the very least, have the mousemove handler check to see if the overlay is already hidden before hiding it.
HTML
<div id='overlay'></div>​
CSS
#overlay {
width: 200px;
height: 200px;
background: orange;
position: relative;
top: 123px;
left:23px;
}​
jQuery
var $ovl = $('#overlay');
var offset = $ovl.offset();
var height = $ovl.height();
var width = $ovl.width();
var bounds = {top: offset.top - 100,
bottom: offset.top + height + 100,
left: offset.left - 100,
right: offset.left + width + 100
}
$ovl.mouseenter(function() {
$ovl.stop().animate({opacity:1});
});
$(document).mousemove(function(e) {
if(e.pageX < bounds.left ||
e.pageX > bounds.right ||
e.pageY < bounds.top ||
e.pageY > bounds.bottom) {
$ovl.stop().animate({opacity:.3});
}
});​
EDIT:
Here's another idea (although it is heavily dependent on your layout). Place the overlay inside a container that has a large padding and remove the overlay when the pointer performs a mouseleave on the container. Again, this may not be feasible in your layout.
EDIT:
One other idea would be to set a delay on the code used to remove the overlay. Its not as precise, but may yield a sufficiently desirable effect.
Why not use a mouseout event with a timer?
var zGbl_OverlayCloseTimer = '';
OverlayElement.addEventListener ("mouseout", CloseOverlayWithDelay, false);
function CloseOverlayWithDelay (zEvent)
{
if (typeof zGbl_OverlayCloseTimer == "number")
{
clearTimeout (zGbl_OverlayCloseTimer);
zGbl_OverlayCloseTimer = '';
}
zGbl_OverlayCloseTimer = setTimeout (function() { CloseOverlay (); }, 333);
}
function CloseOverlay ()
{
...
}

How to get the mouse position without events (without moving the mouse)?

Is it possible to get the mouse position with JavaScript after page loads without any mouse movement event (without moving the mouse)?
Real answer: No, it's not possible.
OK, I have just thought of a way. Overlay your page with a div that covers the whole document. Inside that, create (say) 2,000 x 2,000 <a> elements (so that the :hover pseudo-class will work in IE 6, see), each 1 pixel in size. Create a CSS :hover rule for those <a> elements that changes a property (let's say font-family). In your load handler, cycle through each of the 4 million <a> elements, checking currentStyle / getComputedStyle() until you find the one with the hover font. Extrapolate back from this element to get the co-ordinates within the document.
N.B. DON'T DO THIS.
Edit 2020: This does not work any more. It seems so, that the browser vendors patched this out. Because the most browsers rely on chromium, it might be in its core.
Old answer:
You can also hook mouseenter (this event is fired after page reload, when the mousecursor is inside the page). Extending Corrupted's code should do the trick:
var x = null;
var y = null;
document.addEventListener('mousemove', onMouseUpdate, false);
document.addEventListener('mouseenter', onMouseUpdate, false);
function onMouseUpdate(e) {
x = e.pageX;
y = e.pageY;
console.log(x, y);
}
function getMouseX() {
return x;
}
function getMouseY() {
return y;
}
You can also set x and y to null on mouseleave-event. So you can check if the user is on your page with it's cursor.
What you can do is create variables for the x and y coordinates of your cursor, update them whenever the mouse moves and call a function on an interval to do what you need with the stored position.
The downside to this of course is that at least one initial movement of the mouse is required to have it work. As long as the cursor updates its position at least once, we are able to find its position regardless of whether it moves again.
var cursor_x = -1;
var cursor_y = -1;
document.onmousemove = function(event)
{
cursor_x = event.pageX;
cursor_y = event.pageY;
}
setInterval(check_cursor, 1000);
function check_cursor(){console.log('Cursor at: '+cursor_x+', '+cursor_y);}
The preceding code updates once a second with a message of where your cursor is.
#Tim Down's answer is not performant if you render 2,000 x 2,000 <a> elements:
OK, I have just thought of a way. Overlay your page with a div that
covers the whole document. Inside that, create (say) 2,000 x 2,000
elements (so that the :hover pseudo-class will work in IE 6, see),
each 1 pixel in size. Create a CSS :hover rule for those elements
that changes a property (let's say font-family). In your load handler,
cycle through each of the 4 million elements, checking
currentStyle / getComputedStyle() until you find the one with the
hover font. Extrapolate back from this element to get the co-ordinates
within the document.
N.B. DON'T DO THIS.
But you don't have to render 4 million elements at once, instead use binary search. Just use 4 <a> elements instead:
Step 1: Consider the whole screen as the starting search area
Step 2: Split the search area into 2 x 2 = 4 rectangle <a> elements
Step 3: Using the getComputedStyle() function determine in which rectangle mouse hovers
Step 4: Reduce the search area to that rectangle and repeat from step 2.
This way you would need to repeat these steps max 11 times, considering your screen is not wider than 2048px.
So you will generate max 11 x 4 = 44 <a> elements.
If you don't need to determine the mouse position exactly to a pixel, but say 10px precision is OK. You would repeat the steps at most 8 times, so you would need to draw max 8 x 4 = 32 <a> elements.
Also generating and then destroying the <a> elements is not performat as DOM is generally slow. Instead, you can just reuse the initial 4 <a> elements and just adjust their top, left, width and height as you loop through steps.
Now, creating 4 <a> is an overkill as well. Instead, you can reuse the same one <a> element for when testing for getComputedStyle() in each rectangle. So, instead of splitting the search area into 2 x 2 <a> elements just reuse a single <a> element by moving it with top and left style properties.
So, all you need is a single <a> element change its width and height max 11 times, and change its top and left max 44 times and you will have the exact mouse position.
You could try something similar to what Tim Down suggested - but instead of having elements for each pixel on the screen, create just 2-4 elements (boxes), and change their location, width, height dynamically to divide the yet possible locations on screen by 2-4 recursively, thus finding the mouse real location quickly.
For example - first elements take right and left half of screen, afterwards the upper and lower half. By now we already know in which quarter of screen the mouse is located, are able to repeat - discover which quarter of this space...
Here's my solution. It exports window.currentMouseX and window.currentMouseY properties you can use anywhere. It uses the position of a hovered element (if any) initially and afterwards listens to mouse movements to set the correct values.
(function () {
window.currentMouseX = 0;
window.currentMouseY = 0;
// Guess the initial mouse position approximately if possible:
var hoveredElement = document.querySelectorAll(':hover');
hoveredElement = hoveredElement[hoveredElement.length - 1]; // Get the most specific hovered element
if (hoveredElement != null) {
var rect = hoveredElement.getBoundingClientRect();
// Set the values from hovered element's position
window.currentMouseX = window.scrollX + rect.x;
window.currentMouseY = window.scrollY + rect.y;
}
// Listen for mouse movements to set the correct values
window.addEventListener('mousemove', function (e) {
window.currentMouseX = e.pageX;
window.currentMouseY = e.pageY;
}, /*useCapture=*/true);
}())
Composr CMS Source: https://github.com/ocproducts/composr/commit/a851c19f925be20bc16bfe016be42924989f262e#diff-b162dc9c35a97618a96748639ff41251R1202
The most simple solution but not 100% accurate
$(':hover').last().offset()
Result: {top: 148, left: 62.5}
The result depend on the nearest element size and return undefined when user switched the tab
Yes, It's possible.
If you add "mouseover" event to the document it will fire instantly and you can get the mouse position, of course if mouse pointer was over the document.
document.addEventListener('mouseover', setInitialMousePos, false);
function setInitialMousePos( event ) {
console.log( event.clientX, event.clientY);
document.removeEventListener('mouseover', setInitialMousePos, false);
}
Previously it was possible to read mouse position through window.event but it's deprecated now.
var x = 0;
var y = 0;
document.addEventListener('mousemove', onMouseMove, false)
function onMouseMove(e){
x = e.clientX;
y = e.clientY;
}
function getMouseX() {
return x;
}
function getMouseY() {
return y;
}
I implemented a horizontal/vertical search, (first make a div full of vertical line links arranged horizontally, then make a div full of horizontal line links arranged vertically, and simply see which one has the hover state) like Tim Down's idea above, and it works pretty fast. Sadly, does not work on Chrome 32 on KDE.
jsfiddle.net/5XzeE/4/
You do not have to move the mouse to get the cursor's location. The location is also reported on events other than mousemove. Here's a click-event as an example:
document.body.addEventListener('click',function(e)
{
console.log("cursor-location: " + e.clientX + ',' + e.clientY);
});
Riffing on #SuperNova's answer, here's an approach using ES6 classes that keeps the context for this correct in your callback:
class Mouse {
constructor() {
this.x = 0;
this.y = 0;
this.callbacks = {
mouseenter: [],
mousemove: [],
};
}
get xPos() {
return this.x;
}
get yPos() {
return this.y;
}
get position() {
return `${this.x},${this.y}`;
}
addListener(type, callback) {
document.addEventListener(type, this); // Pass `this` as the second arg to keep the context correct
this.callbacks[type].push(callback);
}
// `handleEvent` is part of the browser's `EventListener` API.
// https://developer.mozilla.org/en-US/docs/Web/API/EventListener/handleEvent
handleEvent(event) {
const isMousemove = event.type === 'mousemove';
const isMouseenter = event.type === 'mouseenter';
if (isMousemove || isMouseenter) {
this.x = event.pageX;
this.y = event.pageY;
}
this.callbacks[event.type].forEach((callback) => {
callback();
});
}
}
const mouse = new Mouse();
mouse.addListener('mouseenter', () => console.log('mouseenter', mouse.position));
mouse.addListener('mousemove', () => console.log('mousemove A', mouse.position));
mouse.addListener('mousemove', () => console.log('mousemove B', mouse.position));
Not mouse position, but, if you're looking for current cursor postion (for use cases like getting last typed character etc) then, below snippet works fine.
This will give you the cursor index related to text content.
window.getSelection().getRangeAt(0).startOffset
I envision that maybe you have a parent page with a timer and after a certain amount of time or a task is completed, you forward the user to a new page. Now you want the cursor position, and because they are waiting, they aren't necessarily touching the mouse. So track the mouse on the parent page using standard events and pass the last value to the new page in a get or a post variable.
You can use JHarding's code on your parent page so that the latest position is always available in a global variable:
var cursorX;
var cursorY;
document.onmousemove = function(e){
cursorX = e.pageX;
cursorY = e.pageY;
}
This won't help users that navigate to this page by means other than your parent page.
I think i may have a reasonable solution with out counting divs and pixels..lol
Simply use animation frame or a time interval of a function. you will still need a mouse event one time though just to initiate, but technically you position this where ever you like.
Essentially we are tracking a dummy div at all times with out mouse movement.
// create a div(#mydiv) 1px by 1px set opacity to 0 & position:absolute;
Below is the logic..
var x,y;
$('body').mousemove(function( e ) {
var x = e.clientX - (window.innerWidth / 2);
var y = e.clientY - (window.innerHeight / 2);
}
function looping (){
/* track my div position 60 x 60 seconds!
with out the mouse after initiation you can still track the dummy div.x & y
mouse doesn't need to move.*/
$('#mydiv').x = x; // css transform x and y to follow
$('#mydiv)'.y = y;
console.log(#mydiv.x etc)
requestAnimationFrame( looping , frame speed here);
}

Categories