0

I have created a webpage that basically displays 2 images side by side.

It has a "download" button, which triggers a vanilla Javascript function, which creates a <canvas> HTML element and concatenates the two images inside of it. It then creates a link with the base64-encoded result image as href and clicks on it:

<a download="image.png" id="dllink" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABQAAAAMnCAYAAABhnf9DAAAgAElEQVR4nOzdR48kD3rn96j03pfv6qo21dVd3qT3JryP9Jll281..."></a>

Here is what the function I'm using looks like:

/** * Create canvas, draw both images in it, create a link with the result * image in base64 in the "href" field, append the link to the document, * and click on it */ function saveImage() { // Get left image var imgLeft = new Image(); imgLeft.setAttribute('crossOrigin', 'anonymous'); imgLeft.src = "imgleft/" + idxImageShownLeft + ".jpg"; imgLeft.onload = function() { // Once the left image is ready, get right image var imgRight = new Image() imgRight.setAttribute('crossOrigin', 'anonymous'); imgRight.src = "imgright/" + idxImageShownRight + ".jpg"; imgRight.onload = function() { // Once the right image is ready, create the canvas var canv = document.createElement("canvas"); var widthLeft = parseInt(imgLeft.width); var widthRight = parseInt(imgRight.width); var width = widthLeft + widthRight; var height = imgLeft.height; canv.setAttribute("width", width); canv.setAttribute("height", height); canv.setAttribute("id", "myCanvas"); canv.setAttribute('crossOrigin', 'anonymous'); var ctx = canv.getContext("2d"); // Draw both images in canvas ctx.drawImage(imgLeft, 0, 0); ctx.drawImage(imgRight, widthLeft, 0); // Create PNG image out of the canvas var img = canv.toDataURL("image/png"); // Create link element var aHref = document.createElement('a'); aHref.href = img; aHref.setAttribute("id", "dllink"); aHref.download = "image.png"; // Append link to document var renderDiv = document.getElementById("render"); renderDiv.replaceChild(aHref, document.getElementById("dllink")); // Click on link aHref.click(); } } }

My problem is that this works fine on Firefox, but not on Chrome.

After a bit of investigating, I realized that by setting a breakpoint before the aHref.click(); line in Chrome, it worked fine. I think that it means that the aHref.click(); is called before the <a href="data:image/png;base64,...></a> is ready to be clicked, but I don't know for sure.

  • I couldn't find a duplicate of this topic. What keywords should I use just to be 100% sure?
  • Am I investigating in the right direction?
  • Is there an event I could rely on in order to call aHref.click(); only when it is ready?
7
  • It works for me, I'm using chrome 46.0.2490.86 (64-bit) on ubuntu. what is the problem ?? Commented Dec 7, 2015 at 19:18
  • What is the purpose of renderDiv.replaceChild(aHref, document.getElementById("dllink")); ? Is aHref , #dlink same element ? Commented Dec 7, 2015 at 19:29
  • @Alessandro.Vegna: The problem is that when I click the "download" button, sometimes, the result image is opened in my image editor, and sometimes nothing happens. Commented Dec 7, 2015 at 19:41
  • @guest271314: What I'm doing is replacing the previous #dllink element with the new one (aHref). Commented Dec 7, 2015 at 19:42
  • Not related to your issue, but canvas doesn't have a crossorigin attribute. For your issue, are you sure the images onload events are triggered? I personally always prefer setting the src after I declared the onload handlers. Also, I think that on some UAs, the link has to be visible so the click() can work. Commented Dec 8, 2015 at 2:09

2 Answers 2

0

You could wrap it in an init function that gets called when the window completes loading.

function init() { aHref.click(); } window.onload = init; 

Its similar to the vanilla equivalent of jQuery's .ready() method.

Sign up to request clarification or add additional context in comments.

3 Comments

I already have a window.onload function in my code unfortunately... Is there any way to bypass this?
You could always put it in a timeout function to give the SVG a chance to load before calling click on it. Set it to like 1 second. Not ideal, but it is a work around.
Thank you for your suggestion, it helped me shed some light on the problem. Apparently, using something like this didn't help: setTimeout(function() { aHref.click(); }, 3000);. However, this worked better, for some reason: setTimeout(function() { alert("About to click..."); aHref.click(); }, 3);. Weird...
0

aHref , document.getElementById("dllink") appear to be same element ? Though "dllink" has not yet been appended to document when .replaceChild called ?

Try substituting

renderDiv.appendChild(aHref); 

for

renderDiv.replaceChild(aHref, document.getElementById("dllink")); 

3 Comments

Yes, document.getElementById("dllink") is the previously used element, and aHref is the newly created one. I use .replaceChild to substitute the old one for the new one. Before doing this, I used to append all the time, thus creating a new element in my document at each click. Unfortunately, the aforementioned problem existed also back then.
@AlfredDupont To avoid possible duplicate ids in document, could remove existing #dllink before appending new #dllink ? Can create stacksnippets blog.stackoverflow.com/2014/09/… , jsfiddle jsfiddle.net to demonstrate issue ? See stackoverflow.com/help/mcve
I am already using repaceChild instead of appendChild so that at any given time, there is only one element whose id is dllink. I have tried making a jsfiddle but for some reason I didn't succeed... Sorry. Tomorrow I will read how to make a Minimal, Complete, and Verifiable example and try again.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.