-
Notifications
You must be signed in to change notification settings - Fork 26
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
Extending <a> with more navigation capabilities #101
Comments
It sounds like |
I think something like this is really critical. Is it out of the realm of possibilities to also (or instead?) include the dataset name/value pair object in info as well? And I guess the question is in my mind -- is there no way to add the "triggering navigation element" somewhere in the event object? |
I think adding the triggering element to the navigation event is possible, although it'd be good to have concrete examples (preferably with code) to support such an expansion in scope. |
We currently rely on both of these patterns:
The latter arises (for example) for things like a [create new foo] link to a data entry state where field values may be initialized based on the link's context. When the link appears in a drill down preview of contact "Bob", the "recipient" field in the form would be initialized to Bob, and associating a state object with the element is one way to achieve that. This sort of thing is currently a natural feeling pattern because generic link click handlers are unavoidable anyway. In some cases, you could instead expand the URL contract with e.g. new query parameters (though this might make it tougher to avoid duplicate API requests - it's not nec a frictionless change). If one of the objectives of AppHistory is to reduce or eliminate the need for generic link click handlers, I agree with @bahrus that being able to tie the navigation to an originating element when applicable would make adapting existing apps to AppHistory a lot easier. OTOH, in an AppHistory-first world I would likely tend to favor the expand-the-URL-contract approach whenever possible. |
I can't yet think of an example where I need to access a property of the anchor tag. It might be sufficient to provide access to the full attribute list. (But see my second example below). Example 1 <a href=ro.html id=myAnchor>ro</a>
<script>
myAnchor.target = 'myIframe';
</script>
<iframe style="display:none" name=myIframe ></iframe> Due to the script setting the target property, the link will open in the iframe below. Suppose I don't want the iframe to display until a link is opened that targets the iframe? I think I would want to set that visibility in the navigate event handler. But to my mild surprise, setting the target property on myAnchor actually reflects to the attribute, so I would be able to fulfill the requirement if I had access to the attribute list. But I wonder if there are some properties of the anchor tag that doesn't automatically reflect? I'll keep pondering that question to see if I hit upon one that is relevant to navigation. Example 2<nav>
<a href=a.html target=myAIframe>A</a>
<a href=b.html target=myBIframe>B</a>
<a href=c.html target=myCIframe>C</a>
</nav>
<iframe style="display:none" name=myAIframe></iframe>
<iframe style="display:none" name=myBIframe></iframe>
<iframe style="display:none" name=myCIframe></iframe> Suppose we only want the last selected link's iframe to display? Sure, we could call out to a function that hardcodes the querySelector strings for the three iframes, passing in the target of the selected anchor tag. But a more general algorithm would be along the lines of:
I'll try to come up with more examples if this doesn't seem sufficient. |
Hmm, my example so far might not be right -- it seems that hyperlinks that target an iframe do not fire a navigate event. |
I guess the scenario that is applicable: <nav>
<a href="/about" data-target=about-us>About us</a>
<a href="/contactus" data-target=contact-us>Contact us</a>
<a href="/home" data-target=home>Home</a>
</nav>
<div id=about style="display:none"></div>
<div id=contact-us style="display:none"></div>
<div id=home style="display:none"></div>
<script>
document.addEventListener("navigate", e => {
//set the innerHTML of the element found by doing:
const trigger = e.triggeringNavigationElement;
document.querySelector(trigger.dataset.target).innerHTML = await loadContentFor(e.destination.url);
document.querySelector(trigger.dataset.target).style.display = 'block';
//now hide the other targeted elements
const nav = trigger.closest('nav');
nav.querySelectorAll('a[data-target]').forEach(const anchorTag => {
if(anchorTag !== trigger){
document.querySelector(anchorTag.dataset.target).style.display = 'none';
}
}
});
}
});
</script> |
@bahrus would it work for you to just derive target names from the URLs? E.g.
|
Yes, @dvoytenko, I'm sure without this feature, workarounds could be found, such as requiring that the url match the id of the target element. (A fleeting question in my mind is if end users can cause navigate events to trigger by playing around with the url, if that might inadvertently cause DOM element manipulation the developer wasn't expecting, based on this assumption). Another issue with this workaround -- id's become global constants , which can break code. The url's might want to be simple strings that are used as genuine constants in the application. So now we can find workarounds to workarounds -- use a class or something instead of an id. This also doesn't address how to hide the targets from previously selected anchor tags, however. Again, workarounds can be found (e.g. keep a variable in memory to remember the last selected url, I guess), but it raises questions in my mind why we need to find such workarounds, when passing in the triggering element would avoid needing to find workarounds? I guess if there is some concern about including a reference to the triggering element, then it would be possible to weigh the costs / benefits. Without that, not sure what to say. If a scenario with no possible workaround occurs to me, I will be sure to bring it up. But the web is robust enough that it is quite rare to find scenarios where some sort of work around can't be found :-), no matter what the situation. |
I'm sure there's a workaround for this, but this one might be a bit challenging: Requirements:
|
This came up again in conversations with @sebmarkbage where there's a desire to link the triggering element so that the navigate event handler can do something with it. I think something as simple as populating the |
That's #225. @natechapin interested in working on that next? Should be relative easy. |
See #225 for a link to a prototype, and discussion of some outstanding questions if we want to go the route of exposing the initiating element. |
An alternative could be to add a traverse="" boolean attribute similar to replace="" which uses the rel attribute with prev or next as a hint. The default behaviour here could be rel="prev" if rel is unspecified. However the key attribute would still be very useful for things like the nested router paradigm where the previous entry might not be the "back" entry of a parent router. |
@dvoytenko mentioned today an interesting potential addition that could come along with the new navigation API: extending the
<a>
element (and<area>
?? Or nah) to allow it more powerful navigation capabilities, similar tonavigation.navigate()
.This is somewhat of a sibling of #82, which talks about extending
navigation.navigate()
to match existing HTML<a>
and<form>
capabilities.There are two relatively easy things we could do:
replace=""
boolean attribute which makes the navigation into a replacement navigation.navigateinfo=""
string attribute which allows you to provide a string value that is used as theinfo
property of the correspondingnavigate
event. (Supporting non-string values is not a good idea here as it mismatches the HTML attribute model.)More interesting would be whether there'd be a way to allow an
<a>
to traverse to a specific history entry, e.g. by navigation API history entry key. This is trickier because for a simple version (like<a key="history entry key">
), to actually figure out the keys you need to use JavaScript, which somewhat defeats the point. So we started discussing some ideas like letting pages declaratively set such keys... it gets complex.Such additions to
<a>
would help encourage more "real"<a>
s and less<a href="javascript:undefined" onclick="navigation.navigate(...)">
. Note also that such "real"<a>
s would haveevent.userInitiated
set to true in the navigate handler, whereas as currently speccedonclick=""
-style<a>
s would not.In general Dima was of the opinion that by thinking about the declarative path as we design the API, we're likely to strengthen the API more generally, which I agree with.
The text was updated successfully, but these errors were encountered: