0

I've struggled with the title for this one.

I'm sure there is a better way to do this in the real problem case but the question seems to make some sense to me in the abstract case.

There is an existing file submission form which uploads a jpeg to the server. When the response comes back from the server the page reloads and the new page from the server contains information about the image uploaded.

I want to manipulate the image in the browser before upload.

So instead of submitting the form I'm building a FormData object from the form and replacing the file input element with the blob from my canvas and submitting an XMLHttpRequest.

The server is happy with this and returns the new page. So I have the new page in the responseText but I can't load it into the browser the way it would happen with the real form submit.

How do I get the browser to behave the way it does after the form response returns in the submit case?

I've come up with a test document that expresses the case. If you don't check the check box it submits the file. If you do check it, it uses an XMLHttpRequest.

setting the document url to the blob url works but leaves the document url different to what it would be for the submit.

document.write fails with an error.

Julian
  • 1,522
  • 11
  • 26
  • 1
    What is a `DataForm`? Shouldn't you just open the image in the browser with some code, modify it and then submit the form? – Daniel B Dec 14 '15 at 07:53
  • oops, I meant a FormData (https://developer.mozilla.org/en-US/docs/Web/API/FormData). Do you mean by saving the image back to disc and loading it again? – Julian Dec 14 '15 at 08:02
  • 1
    @Julian, do you just want to navigate to the server's response ? If yes, set your `xhr.responseType` to `'blob'` and then `window.open(URL.createObjectURL(this.response))` should do the trick. – Kaiido Dec 14 '15 at 08:29
  • Thanks @Kaiido. That's heading in the right direction but it tries to open a new popup window. I need this to go to the main window. – Julian Dec 14 '15 at 08:40
  • My bad, to keep it in the same frame, use `window.location = URL.createObjectURL(this.response);` – Kaiido Dec 14 '15 at 08:45
  • I find the question unclear. I used [this library](https://fengyuanchen.github.io/cropper/) a while ago to load an image on the client side, crop it and then upload it as a blob. No need, to open, save, then submit. – Daniel B Dec 14 '15 at 09:09
  • @DanielB - It is easy if you are not trying to integrate with an existing framework. I have what I want working here: https://oga-images.herokuapp.com/ but modifying it to work inside an existing UI is what is challenging me. – Julian Dec 14 '15 at 09:55
  • @Kaiido thanks - I will try this tonight. – Julian Dec 14 '15 at 09:55
  • This ihttps://stackoverflow.com/questions/133925/javascript-post-request-like-a-form-submit?rq=1 s similar to what I want to do, but with a file object replaced by a blob. It looks like I could add the blob as a hidden input and add another hidden input for the filename and remove the file input element and let the original submit go ahead and modify the server side to allow either a file input or two hidden inputs. It isn't as nice as the FormData approach though. – Julian Dec 14 '15 at 09:59
  • So, if everything works, why not just display the page in the success handler? Set the handler to something like `function handleXhrSuccess(xhr) { document.open(); document.write(xhr.responseText); document.close(); }` and all should be well. Even though `document.write` isn't recommended to use in most cases, in this situation you want to replace it all with the response. – Daniel B Dec 14 '15 at 10:07
  • Saw the comment from @Bardo - that was a missing part of my understanding. Of course it is window.open that creates a new document. document.close(); document.open(); document.write(xhr.responseText); failed though with a InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable. – Julian Dec 15 '15 at 17:51
  • The invalid state error goes away if I remove the xhr.responseType = 'blob'; line, with a document.close(); after the docuement.write() I think I have what I need. – Julian Dec 15 '15 at 23:23

2 Answers2

0

If you get the HTML response of your server into the AJAX response you can paste it directly into your DOM.

It could get a bit tricky depending how did you get your response, if you use some type of view layout, etc...

But, basically, what you get in your response is HTML code, and you need to post it to your browser so it loads.

You can just document.write it, but if you are working with layouts probably you have a container div where the content should be loaded, then you could do:

referenceToYourContainerObject.innerHTML = yourAJAXResponse;
Bardo
  • 2,470
  • 2
  • 24
  • 42
  • But that isn't what happens when the submit button is pressed. In that case the returned HTML replaces the entire document. That's the behaviour I need to be the same with the normal form submit and the form submit with the file replaced by a blob. – Julian Dec 14 '15 at 08:25
  • When you submit a form your server will process data and return HTML, the same occurs with the AJAX call, the fact that you are passing a blob or an image file shouldn't affect the result you receive from server, that is HTML. Just than you need to post it to the DOM if you are using an AJAX call. – Bardo Dec 14 '15 at 08:30
  • I agree, I just can't work out how to "post it to the dom" in exactly the same way the form/submit function does. – Julian Dec 14 '15 at 09:51
  • That's what my answer does. It depends in how are you working with your server code. Are you using php? .NET? MVC? Are you using server layouts? Depending on what your response HTML contains (a whole page or just a snippet) you can just use document.write with your response or inject it into an existing container through .innerHTML – Bardo Dec 14 '15 at 10:31
  • you can't do document.innerHTML= xxx. But @Kaiido's suggestions might be the answer. – Julian Dec 14 '15 at 12:29
  • Of course, as if you use document you have to do document.write, innerHTML is when you have to insert your response into a container element... – Bardo Dec 14 '15 at 13:12
  • but document.write is only an append. there is no "document.clear()". window.location = URL.createObjectURL(this.response); does seem to have all the right semantics. I'll see how that goes. – Julian Dec 14 '15 at 16:29
  • Excecuting document.write on an already loaded document will call before document.open, which will clear the document https://developer.mozilla.org/en-US/docs/Web/API/Document/write – Bardo Dec 14 '15 at 16:38
  • I didn't know that - you are absolutely right that is what it says. I tried document.write on Iceweasel (Firefox) 38 and got: "InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable" – Julian Dec 15 '15 at 17:48
0

Just make your Ajax response be window.location = "" thereby allowing the form to move on to the next page normally. you may be able to figure out how to replace all of your page html from the ajax response, but then it will be rendered with the original URL in the address bar which is probably not what you want.