I tried asking this in a different way but it was marked as a duplicate, probably because my title was not specific enough.
I'm trying to trigger a download of an SVG file from within the SVG file, using a link and clicking the link with javascript.
I know that I cannot use HTMLElement.click()
as the <a>
is an SVG element, and instead I should use dispatchEvent()
.
But what I don't know is what I need to have in my onclick
function in order to download the file.
This is a working (manual) version of what I want to achieve - when the circle is clicked, a Save As dialog opens with Original-Name-edited.svg as the file name, and when I click OK it correctly saves the SVG to my computer:
<svg xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 100 100">
<a>
<circle cx="50" cy="50" r="25" fill="red"/>
</a>
<script>
// <![CDATA[
const thisSvg = new XMLSerializer().serializeToString(document.getElementsByTagName('svg')[0])
const link = document.getElementsByTagName('a')[0]
const fileName = document.baseURI.replace(/(.*\/)([^\/]*)(\.svg)/, '$2-edited$3')
const data = 'data:image/svg+xml;base64,' + btoa(thisSvg)
link.setAttribute('download', fileName)
link.setAttribute('href', data)
// ]]>
</script>
</svg>
When I create a function to run on click using dispatchEvent
as outlined in this answer I can trigger an alert()
or console.log()
, so it feels like I'm on the right track, but I just can't get it to have the same effect as clicking on the link using the manual method.
<a onclick="downloadSvg()">
<circle cx="50" cy="50" r="25" fill="red"/>
</a>
<script>
// <![CDATA[
const thisSvg = new XMLSerializer().serializeToString(document.getElementsByTagName('svg')[0])
const fileName = document.baseURI.replace(/(.*\/)([^\/]*)(\.svg)/, '$2-edited$3')
const data = 'data:image/svg+xml;base64,' + btoa(thisSvg)
// the function is called but this does not work
const downloadSvg = () => {
window.location.download = fileName
window.location.href = data
}
link.dispatchEvent(new Event('click'))
// ]]>
</script>
</svg>