Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Event property to access the element who triggered a navigation #225

Open
rik opened this issue Apr 12, 2022 · 25 comments
Open

Event property to access the element who triggered a navigation #225

rik opened this issue Apr 12, 2022 · 25 comments
Labels
addition A proposed addition which could be added later without impacting the rest of the API

Comments

@rik
Copy link

rik commented Apr 12, 2022

I think this new API could be very interesting for a library like Hotwire Turbo. The Turbo Frame concept would need to know if the navigation was triggered by an element or not and if that element was configured to do a Turbo navigation or not. As far as I can tell, this information is not available at the moment.

(cc @seanpdoyle from the Turbo community)

@domenic domenic added the addition A proposed addition which could be added later without impacting the rest of the API label Apr 12, 2022
@domenic
Copy link
Collaborator

domenic commented Apr 12, 2022

That seems like a pretty reasonable addition. This information is similar to event.userInitiated and it would just be a matter of hooking up the actual element instead of making it just a boolean.

Any thumbs-up on the issue from community members would be appreciated, to weigh this versus other additions.

@rik
Copy link
Author

rik commented Apr 12, 2022

Other libraries in the same space that might be interested by this new API and/or this issue: htmx (cc @benpate) and Unpoly (cc @triskweline).

@benpate
Copy link

benpate commented Apr 12, 2022

Other libraries in the same space that might be interested by this new API and/or this issue: htmx (cc @benpate) and Unpoly (cc @triskweline).

What is the current status of this API? From this page, it seems like a proposal that hasn't yet been implemented by W3C or major browsers. It certainly looks interesting, and I'll keep an eye on it as it develops!

Also -- thanks for the mention! @1cg is the rockstar behind htmx. I'm just a groupie with a pair of drumsticks :)

@domenic
Copy link
Collaborator

domenic commented Apr 12, 2022

What is the current status of this API? From this page, it seems like a proposal that hasn't yet been implemented by W3C or major browsers.

We are preparing to ship this in Chromium, after having run an origin trial for a while. You can find out some details on other browsers' engagement on that link. The W3C does not implement APIs so I don't know what you mean by that.

@triskweline
Copy link

Thanks for the mention @rik.

Confirming that this would be relevant for Unpoly, as we're trying to update a minimal fragment around the triggering element (link, submit button) that causes a navigation.

In Unpoly the triggering element is called { origin }, but since you're already using { destination } it wouldn't work well here.

@VicGUTT
Copy link

VicGUTT commented Jun 14, 2022

For a use case of where having the element triggering the navigation event would be needed checkout the duplicate issue I previously created: #238 .

tl;dr code

function visit(params) {
    // ...

    navigation.addEventListener('navigate', (e) => {
        const element = e.targetElement; // <- Element or null

        if (!element || !element.hasAttribute('data-visit')) {
            return;
        }

        e.transitionWhile(
            fetch({
                url: element.getAttribute('data-visit-url') || determineUrlToUseFromElement(element),
                method: element.getAttribute('data-visit-method') || determineMethodToUseFromElement(element),
                // ...
            })
            .then(response => response.text())
            .then(html => swapDom(html))
        );
    });
}

@natechapin
Copy link
Collaborator

I prototyped this yesterday.

A few design questions that came up:

  • What should this attribute be named? I used triggeringElement in my prototype, but I'm not hung up on it. sourceElement? srcElement? element? initiator? Something else?
  • What should happen when a link or form targets a different window? In that case, the navigate event fires only in the target window. My gut reaction is that we should not expose an HTML element from a different document, and therefore the element should be null in that case, but I'm wiling to hear arguments to the contrary.
  • In my prototype, when submitting a form, the triggering element is the <form>. Is that ok?

@tbondwilkinson
Copy link
Contributor

tbondwilkinson commented Mar 31, 2023

  1. initiatingElement since this is a type of userInitiated? Just thinking about other precedents, when you have an event, the triggering element is event.target, but I don't think target is a clear word here.
  2. I think the use cases for this are typically not cross-document, and so it would be better to leave this same-document.
  3. I think that's okay. What other options could you imagine besides the <form>?

@natechapin
Copy link
Collaborator

natechapin commented Mar 31, 2023

  1. initiatingElement since this is a type of userInitiated? Just thinking about other precedents, when you have an event, the triggering element is event.target, but I don't think target is a clear word here.

It is often-but-not-always user initiataed, fwiw. At least the way I prototyped it, a form submission will populate the triggering element, even if it was submitted via form.submit() without any user action.

I agree that target isn't really the right word here. initiatingElement is clear, but longer than I was hoping for.

  1. I think the use cases for this are typically not cross-document, and so it would be better to leave this same-document.

Just to clarify: This will be available for cross-document navigations, but not cross-window initiation. <a href="some-other-document.html> will populate the triggering element, but <a href="some-other-document.html target="myIframe"> will not

  1. I think that's okay. What other options could you imagine besides the <form>?

The submitting <input>, if one exists? Idk.

@rik
Copy link
Author

rik commented Mar 31, 2023

In my prototype, when submitting a form, the triggering element is the <form>. Is that ok?

I think it should be the SubmitEvent.submitter. Turbo checks a data-turbo attribute on the submitter to decide wether or not to intercept the navigation.

<form>
    <button type="submit">Intercepts the submission</button>
    <button type="submit" data-turbo="false">Let the browser navigate as usual</button>
</form>

@tbondwilkinson
Copy link
Contributor

Oh and I suppose link.click() would also trigger it.

Just some options:
triggering
activating
originating
initiating

I don't have strong opinions I think most of these would be clear.

Ack with cross-window initiation, that was my understanding as well.

+1 to submitter, that does seem useful, especially if there are multiple ways of submitting. If you call form.submit() would you expect the element to be form?

@rik
Copy link
Author

rik commented Mar 31, 2023

If you call form.submit() would you expect the element to be form?

Yes. Same if you call form.requestSubmit().

@domenic
Copy link
Collaborator

domenic commented Apr 28, 2023

Trying to settle on the final naming:

  • We don't like anything involving "initiate" (initiator, initiating element, etc.) because it's too close to userInitiated. userInitiated and this proposal are almost orthogonal, e.g. if you do aElement.click() then navigateEvent.thisThing === aElement but navigateEvent.userInitiated === false.

  • We don't like anything involving "activate" (initiator, activating element, etc.) because it's too close to navigator.userActivation, which is orthogonal for similar reasons.

  • This leaves "trigger", "source", and "originate" as the main stem concepts to use. Of these "originate" is a bit more unusual and long.

  • We tend to think this would benefit from the Element suffix, but don't feel strongly.

  • So our current front-runners are things like triggeringElement, triggerElement, and sourceElement.

Thoughts welcome. This is a pretty simple addition so let's nail down the name soon.

@annevk
Copy link

annevk commented Apr 28, 2023

Some thoughts:

  • Should this return something useful when it's not an element?
  • What elements do you get to know about? Same-document only, same-origin within same top-level navigable only (though what about A -> B -> A), something else?
  • I kinda like sourceElement given the existing navigate arguments (thinking of sourceDocument).
  • Speaking of, could this partially replace sourceDocument?

@domenic
Copy link
Collaborator

domenic commented Apr 28, 2023

  • Should this return something useful when it's not an element?

My instinct is no. Between this and userInitiated and navigationType, I think you should have the information you need. E.g.:

  • e.userInitiated && (e.navigationType === "traverse" || e.navigationType === "reload") => browser UI
  • e.userInitiated && !(e.navigationType === "traverse" || e.navigationType === "reload") => API methods were used
  • !e.userInitiated && (e.navigationType === "push" || e.navigationType === "replace") && !e.sourceElement => API methods were used
  • !e.userInitiated && (e.navigationType === "push" || e.navigationType === "replace") && e.sourceElement => an element was .click()ed or similar

The only extra thing we could consider giving you is the ability to know exactly which API method was used, e.g. location.reload() vs. navigation.reload(), or history.go(-1) vs. history.back(). I don't think that should be necessary?

  • What elements do you get to know about? Same-document only, same-origin within same top-level navigable only (though what about A -> B -> A), something else?

Great point. I think Nate implemented a same-document restriction, but forgot to mention that in #264. That seems like the right conservative starting point. Although I guess it kind of belies my above breakdown; if a cross-document <a> or <form> navigates you, you'll get incorrect results from those kind of boolean expressions. Hmm.

  • Speaking of, could this partially replace sourceDocument?

Yes. We haven't written the spec yet, but I think the way to do things will be to convert sourceDocument into sourceNode, extract out sourceDocument (always non-null) and sourceElement (sometimes non-null) from it early in the navigate algorithm, and pass sourceDocument on to the rest of the algorithm while passing sourceElement on to the specific parts concerned with firing the navigate event.

@tbondwilkinson
Copy link
Contributor

Fine with sourceElement.

Re: booleans, I suppose you would have to check e.sameDocument as well.

@bathos
Copy link

bathos commented May 25, 2023

I also think sourceElement is clearest among those listed.

@rik
Copy link
Author

rik commented Sep 20, 2023

I'm not seeing this in the merged version within the HTML spec. Are there any blockers to do so?

@domenic
Copy link
Collaborator

domenic commented Sep 24, 2023

Nope, @natechapin is working on it :)

@rd3k
Copy link

rd3k commented Oct 31, 2023

I can see that this has been "Implemented behind the NavigateEventSourceElement flag" in Chromium

How do we enable that flag to try it out? Under what circumstances would it be un-flagged?

@rik
Copy link
Author

rik commented Dec 2, 2023

To give it a try, launch Chrome with this extra argument: --enable-blink-features=NavigateEventSourceElement.

@ryantownsend
Copy link

Is there any movement on when this will be unflagged in Blink? Also, do we know whether sourceElement is being included in the other browsers alongside their new Navigation API implementations?

It's immensely useful to be able to toggle an aria-busy on form submission (and use this for user feedback) without having to add additional submit event listeners.

It's hard to understand the status on w3ctag/design-reviews#867 – for clarity: was this closed because TAG don't need to review and therefore it's just automatically accepted as an addition?

@domenic
Copy link
Collaborator

domenic commented May 8, 2024

I apologize for the lack of progress in shipping sourceElement. It fell through the cracks in a bit of a team transition. I'll try to bump shipping it higher on the priority queue.

@bramus
Copy link

bramus commented May 28, 2024

This would be very helpful for View Transitions, so that one can capture the correct element – by adding a view-transition-name to it – from within the pageswap event.

@ryantownsend

This comment was marked as duplicate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
addition A proposed addition which could be added later without impacting the rest of the API
Projects
None yet
Development

No branches or pull requests