Anchors can be used once

If I have a tiddler with a link <a href="#Another">Another tiddler</a>, then clicking it will load the other tiddler. However, if I navigate normally (through wiki links) to another tiddler and back to the first, then clicking the link now doesn’t work. The problem is that the first click added the anchor to the navigation of the browser (I’m using the single file TW5), so now another click is a nop. (If I have another such anchor link it will navigate to the other tiddler).

My use case is that I use the viz (graphviz) plugin and I want the nodes to have links to tiddlers.

Is there a trick to fix this? Maybe something that listens to tiddler navigation events and then removes the anchor from the browser navigation?

As you discovered, <a href="#Another">Another tiddler</a> doesn’t fully replicate the behaviour of a normal tiddler link. The issue is that the browser doesn’t report the location hash as having changed if you click a link that points to the existing location hash.

You can work around it with the event catcher widget. We trap clicks on <a> tags that include an href attribute starting with #. The click handler uses the variable dom-href that is set by the eventcatcher to the value of the href attribute. It then navigates to the target of the link without the #.


\define click-actions()
<$action-navigate $to={{{ [<dom-href>removeprefix[#]] }}}/>
\end

<$eventcatcher events="click" selector="a[href^='#']" actions-click=<<click-actions>>>
...
<a href="#Features">Features</a>
...
<a href="https://google.com" target="_blank">Google</a>
...
</$eventcatcher>
1 Like

Thank you. But, as I mentioned, I need to use this in graphviz. So whatever href I pass to it gets rendered as part of the SVG it produces and I cannot wrap it i event catchers. Is there another alternative?

Hi @Ittayd I’m not familiar with graphviz, perhaps you can outline the constraints of the problem in more detail.

It sounds like the links are appearing in an SVG document and not an HTML document, is that correct? Are you embedding that SVG document in TW?

If you are using the $:/plugins/chanilino/viz plugin you can try wrapping the eventcatcher widget around the entire $viz widget and the svg that it renders.

Yes, the links are in SVG nodes. They are rendered by the graphviz plugin. For example here, there’s a link to ‘#bar’:

<div class="tc-tiddler-body tc-reveal"><p><div class="viz undefined"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="62pt" height="44pt" viewBox="0.00 0.00 62.00 44.00">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 40)">
<title>G</title>
<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-40 58,-40 58,4 -4,4"></polygon>
<!-- foo -->
<g id="node1" class="node">
<title>foo</title>
<g id="a_node1"><a xlink:href="#bar" xlink:title="foo">
<ellipse fill="none" stroke="#000000" cx="27" cy="-18" rx="27" ry="18"></ellipse>
<text text-anchor="middle" x="27" y="-13.8" font-family="Times,serif" font-size="14.00" fill="#000000">foo</text>
</a>
</g>
</g>
</g>
</svg></div></p></div>

I’ll try it, but it’s kind of cumbersome (i’ll wrap in a macro of course)

I tried to wrap the call to $viz in the event catcher, but it seems like nothing changed.

\define click-actions()
<$action-navigate $to={{{ [<dom-href>removeprefix[#]] }}}/>
\end

<$eventcatcher events="click" selector="a[xlink\:href^='#']" actions-click=<<click-actions>>>
<$viz text='
digraph G {
foo [href="#bar"]
}
'/>
</$eventcatcher>

Hi @Ittayd perhaps try inserting a <$action-log/> widget inside click-actions so that you can inspect the variables that are being passed. In particular, you could verify that the link HREF ends up in the variable dom-hred.

After some debugging I finally figured the only selector that worked is a[*|href^=’#’] (since I couldn’t add the namespace declaration anywhere).

But then there’s a failure in eventcatcher.js:83 since the selected node (an ‘a’) doesn’t have an offsetLength property.

Hi @Ittayd I updated my scratchpad to include your sample SVG link and it still works OK:

\define click-actions()
<$action-navigate $to={{{ [<dom-href>removeprefix[#]] }}}/>
\end

<$eventcatcher events="click" selector="a[href^='#']" actions-click=<<click-actions>>>
...
<a href="#Features">Features</a>
...
<a href="https://google.com" target="_blank">Google</a>
...
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="62pt" height="44pt" viewBox="0.00 0.00 62.00 44.00">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 40)">
<title>G</title>
<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-40 58,-40 58,4 -4,4"></polygon>
<!-- foo -->
<g id="node1" class="node">
<title>foo</title>
<g id="a_node1"><a xlink:href="#bar" xlink:title="foo">
<ellipse fill="none" stroke="#000000" cx="27" cy="-18" rx="27" ry="18"></ellipse>
<text text-anchor="middle" x="27" y="-13.8" font-family="Times,serif" font-size="14.00" fill="#000000">foo</text>
</a>
</g>
</g>
</g>
</svg>
...
</$eventcatcher>

Clicking on the oval with the text “foo” opens the tiddler “bar” as expected.

Yes, the tiddler ‘bar’ opens, that was not the issue. The issue is that the ‘#bar’ remains in the address line and so navigating to another tiddler and then back to clicking the ellipsis will not navigate to ‘bar’ again.

Note that you don’t use ‘*|’ before href in the selector, so no event is caught and nothing happens.

Tsk thanks @Ittayd I missed that.

Nonetheless, with the correct selector I am not able to duplicate the crash you encountered with eventcatcher.js.

\define click-actions()
<$action-log/>
<$action-navigate $to={{{ [<dom-href>removeprefix[#]] }}}/>
\end

<$eventcatcher events="click" selector="a[*|href^='#']" actions-click=<<click-actions>>>
...
<a href="#Features">Features</a>
...
<a href="https://google.com" target="_blank">Google</a>
...
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="62pt" height="44pt" viewBox="0.00 0.00 62.00 44.00">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 40)">
<title>G</title>
<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-40 58,-40 58,4 -4,4"></polygon>
<!-- foo -->
<g id="node1" class="node">
<title>foo</title>
<g id="a_node1"><a xlink:href="#bar" xlink:title="foo">
<ellipse fill="none" stroke="#000000" cx="27" cy="-18" rx="27" ry="18"></ellipse>
<text text-anchor="middle" x="27" y="-13.8" font-family="Times,serif" font-size="14.00" fill="#000000">foo</text>
</a>
</g>
</g>
</g>
</svg>
...
</$eventcatcher>

Could it be a browser difference (I’m using Chrome)?
Do you see the anchor gets removed?
Maybe there’s a difference between a verbatim svg and one that is rendered by a widget?

Changing the selector to svg a triggers the crash on Chrome since nodes inside SVG elements don’t have the DOM properties that eventcatcher tries to read and assign as variables.

I can’t duplicate that with Chrome 103.0.5060.53 .

The complete code looks like this. I am trying it on the master branch of TW5.

Clicking on the “foo” in an oval brings up the tiddler “bar”, and the expected logging, and doesn’t cause a crash or change the address bar.

\define click-actions()
<$action-log/>
<$action-navigate $to={{{ [<dom-href>removeprefix[#]] }}}/>
\end

<$eventcatcher events="click" selector="svg a" actions-click=<<click-actions>>>
...
<a href="#Features">Features</a>
...
<a href="https://google.com" target="_blank">Google</a>
...
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="62pt" height="44pt" viewBox="0.00 0.00 62.00 44.00">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 40)">
<title>G</title>
<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-40 58,-40 58,4 -4,4"></polygon>
<!-- foo -->
<g id="node1" class="node">
<title>foo</title>
<g id="a_node1"><a xlink:href="#bar" xlink:title="foo">
<ellipse fill="none" stroke="#000000" cx="27" cy="-18" rx="27" ry="18"></ellipse>
<text text-anchor="middle" x="27" y="-13.8" font-family="Times,serif" font-size="14.00" fill="#000000">foo</text>
</a>
</g>
</g>
</g>
</svg>
...
</$eventcatcher>

@jeremyruston I am away this week without a laptop so cannot debug systematically. I do get the error in TW 5.2.2 using your code but not in 5.2.3 pre-release.

Ah thanks @saqimtiaz, I think that this is the fix concerned:

1 Like

Apologies for my ineptitude on the subject of discussion groups and use of tiddlywiki in general but I have this problem as well i.e Anchors can only be used once. My anchors look like this:

<a
   id="a39707-0-1"
   xlink:href="atkins.htm#Thomas%20Atkins"
   transform="matrix(0.96527778,0,0,0.92405063,326.26109,5993.7641)"
   style="opacity:1;fill:#93d1ff;fill-opacity:1;stroke:#fff429;stroke-opacity:1;stroke-width:38.85903629;stroke-dasharray:none"><rect
     style="font-variation-settings:normal;opacity:1;fill:#93d1ff;fill-opacity:1;stroke:#fff429;stroke-width:38.85903629;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
     id="rect38492-3-1"
     width="2539.053"
     height="1392.9528"
     x="7511.3657"
     y="36781"
     rx="200.25397"
     ry="178.85023" /></a>

I would not know how to proceed correctly to wrap the svg in the event catcher but I have an idea how to, but I seem to have a different layout and would not be sure of the alteration to the code. I am new to tiddlywiki and do not yet understand the use of widgets yet.
Any help would be appreciated; I am delighted with the product which I am using to make a family history.
Peter