7

I have a page with bunch of 3rd party JS scripts. When I load the page, it scrolls down to a specific div.

I already spent 2 hours trying to find out which code is causing the scroll.

Is there a way to find out which script / part of the code is triggering the scroll?

Old Pro
  • 24,624
  • 7
  • 58
  • 106
user1049961
  • 2,656
  • 9
  • 37
  • 69
  • This video talks about it here in Chrome 71: https://www.youtube.com/watch?v=fJxFZO8OEEs – Adam McGurk Dec 03 '18 at 20:33
  • Can you be more specific, please? I tried something like `monitorEvents(document)`, which works for page that is already loaded, but not on page load – user1049961 Dec 03 '18 at 20:40
  • try montiorEvents(window). It's the window global that controls the page load – Adam McGurk Dec 03 '18 at 20:41
  • 1
    Also, is that page live? Can you post a link to it? – Adam McGurk Dec 03 '18 at 20:43
  • The problem is, that on page refresh, the `monitorEvents` function does not stay in the console, even when I have the `Preserve log` checked, so the page load is not captured at all – user1049961 Dec 03 '18 at 20:46
  • Huh...weird. Can you post a link to the page? – Adam McGurk Dec 03 '18 at 20:47
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/184646/discussion-between-adam-mcgurk-and-user1049961). – Adam McGurk Dec 03 '18 at 20:56
  • The scrolling isn't necessarly due to an event... If it happens on page load without any user interaction, it can be a JS instruction on document ready or on a timeout... Try to find something like `window.scrollTo(y)`. A good tool to keyword search within local files is [Agent Ransak](https://www.mythicsoft.com/agentransack/) (For Windows) – Louys Patrice Bessette Dec 04 '18 at 00:23

2 Answers2

15

Wow, was this hard to debug. Seems like the debugger has some missing features, like tracking the emitter of an event.

The problem is WooCommerce. Specifically, it appears that WooCommerce is setting autofocus on the billing_last_name input field. The browser is then automatically scrolling the page to bring the field into view.

One would hope that there is a configuration option to turn off autofocus, but it appears WooCommerce does not provide this.

You can try adding this to your theme

function disable_autofocus_firstname($fields) {
    $fields['billing']['billing_first_name']['autofocus'] = false;
    return $fields;
}
add_filter('woocommerce_checkout_fields', 'disable_autofocus_firstname');

If that doesn't work, you can create a CSS rule to hide the billing name field and then run a delayed JS function to show the billing name field after the page is fully loaded.


###How I debugged it

Per the OP's request, and considering the bounty offered, I will describe how I debugged this.

I'm a little embarrassed that I didn't just say to myself "Hmm, the page scrolls up to a form, the cursor is in the first field of the form, I wonder if it has autofocus set." Unfortunately, I'm not mainly a front-end programmer, and autofocus did not come to mind at first.

I started with the idea that it was being scrolled via JavaScript, either an explicit call to a scroll function or by setting scrollTop on something. I put an event breakpoint on the scroll event and tried to determine where the scroll event was being generated. Although I found the scroll event, I did not find the source of it. All I could determine at this stage is that the scroll event was targeting the document, not something inside it.

I used monitorEvents to listen for events on document and found only 3, a click and 2 scrolls, the last of which was caused by a delayed scroll-to-top function inserted by the OP to work around the first scroll. I put an execution breakpoint on setting that timeout (not executing the function) in an attempt to "divide and conquer", that is, to see if the scroll was happening before or after that. I maintained that breakpoint for the rest of my debugging effort.

The weird thing was that generally, the page would not scroll before it hit that breakpoint, but sometimes it did. I thought that was odd, and although I didn't know what to make of it, it had me on the lookout for something unusual.

I tried searching all the JavaScript for "scroll" and "update" (text) to look for more breakpoints to set, and set a bunch at JavaScript that did scrolling, but nothing hit.

I noticed that there was a lot of JavaScript dynamically updating the page, and thought that maybe the scroll was due to an update of some sort.

I tried putting a jQuery event listener that logged all events on document (since the JS was using custom events not logged by monitorEvents, and I had already determined that document was the target of the scroll event) to emit all the events and see if it was some custom update event. There were a bunch of custom events, and I later generated the events in the console to see if the page would scroll in response. Since I could not get the page to scroll that way, I concluded that events were likely a dead end.

I switched tactics. I looked at where the page was scrolling to, and saw it was scrolling the WooCommerce form into place. So, while stopped at the execution breakpoint (described above), I deleted the entire WooCommerce form from the DOM, and verified that the page no longer scrolled. This had me convinced that whatever the problem was, it was caused by WooCommerce.

Unfortunately, my Google Fu failed me, and I did not immediately find the problem through a Google search. Instead I found how WooCommerce scrolls the page on errors to make sure the error messages are visible. This led me back to the JavaScript.

Still, there was a lot of JavaScript, a lot of it dynamically creating the form (localizing it on the fly), and a bunch of German (which I don't speak), and I wasn't finding any JavaScript causing scrolling. I really wanted to narrow down which JS file was causing the scroll.

Chrome allows you to set a breakpoint on "script first statement" (under Event Listener Breakpoints -> Scripts), so I did that. In addition to stopping at the first line in every script file, it stops at the beginning of every <script> tag on the page. I found this script tag near the bottom of the page

<script type="text/javascript">

if(typeof jQuery == 'undefined' || typeof jQuery.fn.on == 'undefined') {
    document.write('<script src="https://www.prored3.de/wp-includes/js/jquery/jquery.js"><\/script>');
    document.write('<script src="https://www.prored3.de/wp-includes/js/jquery/jquery-migrate.min.js"><\/script>');
}

</script>

The weird thing about this script tag was that the scroll happened immediately after this script tag was processed, but jQuery was already loaded, so the script actually did nothing. I was also able to confirm via the console that both before and after this script tag (which is before and after the scroll), the DOM was not flagged as ready. This means that all the jQuery ready handlers had not run by the time the scroll happened. That eliminates a lot of JavaScript, and got me thinking about why the scroll happened after but not before this tag.

I guessed that internally, the browser saw the document.write calls and determined that the DOM was not complete until after it passed that tag, but as soon as it was past it, the DOM was complete and it could start processing page-level attributes. That, along with the earlier observations, led me to look at the WooCommerce form more closely and discover the autofocus attribute set on the billing_first_name field.

Oddly enough, I was not able to prevent the scrolling by deleting the autofocus attribute. I don't know why, but I'm guessing it has to do with browser internals and the fact that the DOM was not ready. I was, however, able to prevent the scrolling by hiding the the billing_first_name input element via CSS, which convinced me it was the cause of the scroll.

Adding "autofocus" to my Google search led me to other complaints of similar behavior with WooCommerce, and combining posts led me to the PHP solution I posted.

Old Pro
  • 24,624
  • 7
  • 58
  • 106
8

Updated

As I don't have OP's page for testing, the following method of finding registered event listener actually DO NOT solve the issue OP is addressing.

However, this is the general method when I want to find a specific event, just reserved for someone's reference.


If I understand your meaning correctly, you want a method to tell you where do the specific events occur. Please tell me if this is not doing what you want.

You can try to add a breakpoint on chrome debugger.

F12 -> Sources -> Event Listener Breakpoints (in list with those Breakpoints, Scope, etc) -> Control -> Click the box of scroll.

For Sure it may captures some other scroll event you are not interested, but you can go through it next by next until you find the one you want.

Besides, there may be also event not related to scroll, you may also need to try focus or DOM Mutation -> DOMFocusIn.

Sample

MT-FreeHK
  • 2,462
  • 1
  • 13
  • 29