4

I want to register a javascript event for either of these things:

  1. The user hovers any 'a' element
  2. The user is scrolling down/up the page, and the movement of any 'a' element intersects the position of the cursor.

The first is obviously very easy, but I'm struggling with #2 because in Chrome, scrolling is non-smooth and elements will "jump past" the cursor position without firing the typical JS events.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
Bill_Flanders
  • 563
  • 2
  • 7
  • 19
  • not likely you will do this, not without a massively dirty hack anyway. The mouseover event fires when the **mouse** is **over** an element. If it doesn't happen, it doesn't fire – musefan Aug 15 '13 at 12:29
  • Interesting question (+1), but what exactly do you need this for? I think there's a good UX reason for not firing interactions when scrolling past… – Bergi Aug 15 '13 at 12:33
  • Dirty Hack Approach: Whenever the mouse moves (over any part of the document) then you store its position (relative to the document). Register a scroll change event and when that fires, calculate the new mouse position (relative to the document) compare that with the previous "mousemove" position and you can create an effective "line of movement". Check if this line intersects any `a` elements. Good luck! – musefan Aug 15 '13 at 12:34
  • You would probably need to test for intersection between every element in the page and a line drawn between the start and end mouse points. It might get really expensive for pages with lots of elements. Related Question: http://stackoverflow.com/questions/99353/how-to-test-if-a-line-segment-intersects-an-axis-aligned-rectange-in-2d – Splendiferous Aug 15 '13 at 12:35
  • do the `mouseenter` and `mouseout` events not work when you scroll underneath the mousepointer? – bart s Aug 15 '13 at 12:41

2 Answers2

0

Scrolling is also "non-smooth" in FF, etc. if you scroll fast enough.

I just have a feeling this isn't going to be worth it, but what you might need to do is:

  1. onload, get the position of each anchor and determine its area
  2. collect all possible coordinates into an array of objects (an index)
    • { id: 'my-anchor-1', x: 100, y: 100 }
  3. onmousemove, check your coordinates against your array (i.e., check each coordinate between the old mouse position and the new mouse position, as other commenters have said).

This way you do most of the calculations and DOM selection up front and make it much easier for the mousemove event. This could get messy if content added to the page later shifts the anchors around: you'd have to recalculate the array, but that happens less frequently relative to mousemove, and if all you ever do is append, you could simply add to it.

Addressing the resize issue, et al. It really depends on who your audience is and how many anchors you think you're going to have as a worst case scenario. Because this is mousemove, we're talking about desktops/laptops where resizing the window would be very infrequent, especially relative to mousemove events.

If you only have a handful of anchors, and you think there will be a lot of shifting, then creating an index doesn't make as much sense, and you can do the calculation in the event itself (but at least cache the DOM selection). But if you think you'll have a ton of anchors, especially if they aren't likely to shift a lot, I think indexing them makes a lot of sense for performance reasons.

tjb1982
  • 2,257
  • 2
  • 26
  • 39
  • this wont solve the problem of jumping over elements, at best it would provide the ability to detect if the mouse is over an element, but that can be done easily already using mousemove event. Also, pre-loading a list of element position/location data isn't good for pages where the positions may change (browser size change, dynamic content, etc.) – musefan Aug 15 '13 at 12:40
  • I agree. I thought it was obvious by "check your coordinates" that you should check each coordinate between the start and finish, as others have commented – tjb1982 Aug 15 '13 at 12:43
  • @musefan and as far as preloading is concerned, which is better: 1. recalculating a few handfuls of times during a session because of resizing/dynamic content, or 2. recalculating each position of every anchor every single time the mousemove event fires? I think the former – tjb1982 Aug 15 '13 at 13:06
0

I hope you don't mind that I used jQuery as well:

var y = [];  
var ym = [];
$(document).mousemove(function(e) {
  ym.push(e.pageY);
});
$(document).scroll(function(e) { 
  y.push(document.body.scrollTop+ym[ym.length-1]);
  if(y.length-1)  
  {  
    if((y[y.length-2] < $("#a").offset().top && y[y.length-1] > $("#a").offset().top)+$("#a").height() ||
    y[y.length-1] < $("#a").offset().top && y[y.length-2] > $("#a").offset().top)+$("#a").height())
    {
      if($("#a").offset().left < xm[xm.length-1] && $("#a").offset().left+$("#a").width() > xm[xm.length-1])
      {
        HERE IS your desired function
      }
    }
  }
});

I don't know if it will work, but I think you should give it a try.

FloriOn
  • 267
  • 2
  • 12