Giter VIP home page Giter VIP logo

Comments (5)

jordanw66 avatar jordanw66 commented on May 19, 2024 1

So what's going on specifically, so there's no confusion, is that location.href = ... will scroll to an element and even expand any number of nested <details> as needed.

Regular <a> tags pretty much work the same way, in fact probably exactly because they also trigger a favicon load in network tab when clicked.

Before submitting the form, <a> works like normal. But <Link> doesn't, it uses element.scrollIntoView(). This fails when the details element is collapsed and the nested element is not visible.

When you submit the form, that forces an SPA reload, which upgrades the current page/history entry to SPA, as a result this now hijacks the same-page (hash/fragment) <a> and forces them into using pushState() and element.scrollIntoView(). (because of Firefox's functional shortcomings)

At this point <a> now no longer works to expand the details element. This happens even if you reload because the page has been upgraded to SPA, so Qwik reboots the SPA and re-hijacks these anchors immediately after a refresh.

The reason <Link> works on stackblitz is because it never manually scrolls, it's broken and always thinks it's navigating to a different website since it's comparing two cross-domain urls ("stackblitz..." vs "localhost"), so it always aborts early and calls location.href = ....

I think the issue you're having with onClick$ is because it's interacting with other handlers of <a> and <Link>. You can verify simply setting the location works because this is what <Link> is actually doing on stackblitz, but also you can just call it yourself in the console and it'll scroll correctly.

Lastly, I'd say real quick be careful with location.url.href = "${location.url.href}#content", if the location already has a fragment then this will just keep adding: ...#content#content#content..., etc.

If the page is already on the fragment, simply calling location.href = location.href will re-trigger the scrolling behavior.

Two solutions to this problem:

  • Replace element.scrollIntoView() with location.href = ... and fix the history state after. (the browser will insert its own history entry)
  • Check if the target element is not visible, and if not then use a selector to get every nested parent <details> element and open them.

First option will probably replicate natural browser behavior and quirks better, second is kind of hacky and probably has unforeseen edge cases. Just have to make sure whichever plays nicely with all browsers.

I'm on a phone so I'll post the relevant sections of code in a following comment.

from qwik.

jordanw66 avatar jordanw66 commented on May 19, 2024

Interesting issue, when upgrading to SPA, QwikCity will hijack all same-page anchor tags because Firefox destroys history state when clicking hash anchors. It also only ever fires a hashchange event the first time and not again (Chrome does), so we can't detect this to fix it. So Qwik forces the anchors to go through the same pipeline as Link, which uses element.scrollIntoView().

Looks like this will only scroll to an element if it's already visible, it won't expand the details element.

The reason Link works on stackblitz is because stackblitz breaks the QwikCity router/useNavigate location and Link thinks it's navigating to a different website so it doesn't scroll, it uses location.href instead. This is why the favicon is requested again in the network tab when clicking it.

The only real solution to this issue I think is to use location.href = ... and let the browser perform its extra scrolling magic then fix the history state after. This works without reloading with Chromium-based browsers but would have to test to make sure it's the same elsewhere.

from qwik.

tzdesign avatar tzdesign commented on May 19, 2024

@jordanw66 thanks a lot. I was pretty sure stackblitz is reloading, but wasn't that smart to check network tab πŸ˜Άβ€πŸŒ«οΈ

we will try with location.href even if this is a downgrade.

Can you point me in the right direction in qwik? Not sure if we could check if the element is visible and if not, use location.href in qwik instead?

from qwik.

ptzar80 avatar ptzar80 commented on May 19, 2024

@jordanw66 it seems that anchor tag works before the first Form submission and it does scroll to the element before it is visible (opens the details element) - it's only Link that will not open the details element (and works if it's already open).

However, we tried setting

location.url.href = `${location.url.href}#content`

both in the onClick$ of the <a> and the Link and when logging the location.url.href after that, the href is really set, but it doesn't help the situation. Link still scrolls only if the details are open and the <a> still only opens and scrolls until the Form is submitted. If we're doing something wrong, could you please drop a few more details how to try this out so that we proceed in the right direction?

In the meantime we'll do a workaround with a custom context.

from qwik.

jordanw66 avatar jordanw66 commented on May 19, 2024

This is the code that scrolls for <Link> and hijacked same-page <a> tags:

https://github.com/QwikDev/qwik/blob/main/packages%2Fqwik-city%2Fruntime%2Fsrc%2Fscroll-restoration.ts#L4-L34

Because of the way Qwik/QwikCity works, there were some subtleties and also time constraints for me that required duplicating some code on refresh/re-initialization. I haven't had time to dedupe yet, so the following code scrolls for hijacked same-page <a> tags on an SPA page but only after a refresh:

https://github.com/QwikDev/qwik/blob/main/packages%2Fqwik-city%2Fruntime%2Fsrc%2Fspa-init.ts#L140-L182

Whatever solution needs to be copied to both locations for now.

(Look for getElementById and scrollIntoView to see the exact lines in the code blocks above that actually trigger what we're talking about)

from qwik.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.