Page MenuHomePhabricator

Page preview doesn't trigger when link already hovered at page load time
Open, Stalled, NormalPublic

Description

If your cursor happens to be placed over a link while the page is loading, the page preview for it won't trigger. Presumably this is because it's relying on mouseover events, and there is none in that situation.

However, it's pretty trivial to figure out if any links are already hovered at the time the listener is added, with :

$('a:hover')

I've recorded a video of it happening: https://www.dropbox.com/s/9vx9bqzgcte0044/Hover%20on%20pageload%20issue.mov?dl=0

The window of opportunity for this happening has been made wider by T176211: Page Previews could load less JS on pageload.

Event Timeline

Restricted Application added a subscriber: Aklapper. · View Herald TranscriptMar 19 2018, 12:10 PM
Gilles renamed this task from Page previews doesn't trigger when link already hovered at page load time to Page preview doesn't trigger when link already hovered at page load time.Mar 19 2018, 12:12 PM
ovasileva triaged this task as High priority.Mar 19 2018, 1:44 PM
ovasileva added a project: Readers-Web-Backlog.

Fixing this is certainly possible but comes with added code complexity We talked about this before in various meetings and reasoned that this could actually be favourable behaviour as it might suggest an "accidental/unintentional hover" and that given the code complexity it wasn't worth the trade off. For instance, if I click a link and the subsequent page loads and there is a link in the exact same place it will confusingly show another link.

I now realise in T186016 we never actually wrote down our conclusions.

@Nirzar @Tbayer would you care to write down your thoughts?
@ovasileva it might be worth setting up a meeting to hash this out once and for all.

this could actually be favourable behaviour as it might suggest an "accidental/unintentional hover"

I agree, cursor happens to be in certain position is a very weak signal for intentional previews. from experience standpoint, it might add more unwanted previews. we can verify this with data as well.

Krinkle moved this task from Inbox to Radar on the Performance-Team board.Mar 19 2018, 8:03 PM
Krinkle edited projects, added Performance-Team (Radar); removed Performance-Team.
ovasileva lowered the priority of this task from High to Normal.Mar 20 2018, 7:13 PM

Agree with the reasoning that if the cursor already happens to be in the place where a link is rendered, then it is reasonable to consider this hover as unintentional, and that this may overrule the downside of having an inconsistent user experience (seeing a preview card vs. the standard small browser popup).

But do we know whether there can be a significant time difference between first paint (or whenever the link becomes visible for the first time) and the point where the hover detection (mouseover events being processed by the Popups code) starts to work? I.e. might it be possible that if the user moves the mouse over a link very soon after it has been rendered, the Page previews could mistake it for the case that the cursor was already in this place at page load time?

Yep @Tbayer, that can happen as the page loads first HTML, CSS, and mediawiki scripts, and then the rest of them (which includes popups). Depending on connection speed, browser, and computer running the code, Popups awareness (and event logging, and link processing) will run at a later time.

This may be accentuated by the performance request in T176211: Page Previews could load less JS on pageload so page previews and page load events may start working later for less powerful computers or very slow networks.

Interactive elements not working on a page until the code has loaded is the most normal thing in the world in the web, and shouldn't be surprising. Menus, dropdowns, and other JS features of course won't work until the JS is loaded and run.

In T176211 the performance team deemed page previews not important enough for the performance hit on the critical path so we delayed its loading until the critical resources have been loaded.

@ovasileva should get together as a team and make a decision on this.

ovasileva changed the task status from Open to Stalled.Mar 28 2018, 4:39 PM

Let's wait until full feature deployment to make a decision on this.

We've done some digging and the effect is now exacerbated by the solution that was implemented to get off the critical path. See T190950: ext.popups.main loads after most of all JS in desktop for more detail.

Krinkle added a subscriber: Krinkle.Apr 2 2018, 5:49 PM

What are we questioning exactly, with regards to users expecting to trigger a hover. Is it about their cursor hovering the link since before the JS code started, or is it about their cursor not moving to the link, but the link (and surrounding text) appearing underneath their cursor as the page loads?

These are distinct issues. I see this task as being about the former issue (JS code loading after the hover).

The latter (text rendering underneath cursor) is quite difficult to detect indeed. One could potentially approximate it with Performance Timeline API, but I can't recommend it. Those are not meant for real-time reaction and only have async events.

However, the issue of text rendering under a cursor is imho out of scope for this task, because:

  1. Text rendering is very unlikely to happen after the JS arrives. Text appears when the browser has some of the page HTML, and all of the CSS. The HTML and CSS requests the only thing required for text rendering, and are also the only requests with the highest HTTP bandwidth priority. This means rendering should happen in ~ 2 RTT (HTML initiates CSS req). The JS, on the other hand has a low HTTP bandwidth priority and requires 5 roundtrips (HTML initiates JS-startup req, JS-startup initiates JS-base, after JS-base, fetch for page modules starts). I would be very curious how a browser gets to resourceloader.loadEnd before firstPaint. I won't claim it's impossible, but aside from network failure, I can't think of a realistic scenario.
  2. Browsers already trigger mouseover events when the cursor is over an element regardless of whether the cursor moved. This means the issue can already happen without the change suggested by this task, and is thus orthogonal.

To illustrate point 2, view https://codepen.io/Krinkle/full/NYzpGx, hover the red cube and let go of the mouse/touchpad. Observe that, when the red cube is removed 5 seconds later, the blue box moves up to where the red cube was, and instantly receives a mouseover event. (Confirmed in Firefox, Chrome and Safari.)

s it about their cursor hovering the link since before the JS code started, or is it about their cursor not moving to the link, but the link (and surrounding text) appearing underneath their cursor as the page loads?

We are questioning both. We can already say for sure that we don't care about the latter.

In the case of the former, the worry is that if page load happens significantly later than the hover this could be jarring for a user, as the action of hovering is long in the past. Of course, we could optimise this to only show hovers within say the last 2 seconds, but we are questioning how much of a problem this truly is.. and for that we'll need some data which we can't commit to right now.