dataType override problem
I have dug around in the source of this library and in jquery.iframe-transport and I dont get why this library overrides the default dataType to "script *"? This seems to flat out break the built in functionality of iframe transport, specifically it defining custom AJAX converters for "iframe *" content types, which seamlessly "fixes" the content type handling from the textarea.
Is there a specific reason for this? Why cannot this just be left out, so the forms work based on your rails settings. Right now i would need to set data-type = "json" for my form, although im already doing render :json in the controller.
It sets it to prefer script on this line if no data type is defined (that asterisk means script and then everything else). It does this, because it's what jquery-ujs also does on this line. The idea of remotipart is that it should behave almost exactly as jquery-ujs behaves for forms without file inputs.
If we leave the dataType alone (I'm assuming you mean that you're leaving it blank), then it'll end up getting submitted to your server requesting an HTML response, because we're using a normal form submission behind the scenes via an iframe in order to be able to upload the file. We have to manually set the dataType back to the default (in this case, the default is jquery-ujs's default) to override the fact that it's a normal HTML form submission being sent to the server.
Forgot to mention, it should only be preferring script, not requesting it as the only format. If your action only has a json response type, then that should be what's sent back. Can you inspect the actual headers being sent? Keep in mind that script * is not what's being sent, that's just the key for jquery to look up in its dataType object in order to set the header.
What jquery-ujs does is set the accepts header of the request. This is completely different from setting the actual dataType of the AJAX call. dataType is used to figure out how to parse the response. Now what iframe-transport does is define its own custom transport method, named "iframe" and a set of AJAX response converters for "iframe json" and so forth. These define how the content inside the textarea tags is handled. All in all overriding the "dataType" value causes a situation where the form assumes the response to be of type JS, no matter what the actual headers or the content of the response is.
What jquery-ujs does is set the accepts header of the request. This is completely different from setting the actual dataType of the AJAX call. dataType is used to figure out how to parse the response.
It's not completely different. The dataType both sets the accepts header of the request and determines how to parse the response. Due to the presence of * in the dataType, jquery should know how to parse JSON if that's what the server responds with. Again, please inspect the accepts header in the request and the content-type header in the response, and let me know what they are.
Now what iframe-transport does is define its own custom transport method, named "iframe" and a set of AJAX response converters for "iframe json" and so forth.
I'm not actually sure what you're talking about here. If you look at the relevant part of the source for the iframe-transport being used, the iframe-transport literally just pulls the data out of the response text-area, setting some values, and passing it all back to jquery's response converter process by calling the ajaxTransport completeCallback function with the content object (which maps to the responses object in the jquery ajaxTransport documentation).
If you're talking about the custom dataTypes that the iframe-transport creates, it actually just removes those once the response comes back (see here in the source), so that processing can continue as usual.
All in all overriding the "dataType" value causes a situation where the form assumes the response to be of type JS, no matter what the actual headers or the content of the response is.
This should not be the case. The dataType being set is script *, which is different than script. The asterisk means the response could be anything, and so the jquery converter code will loop through the converters for whatever the response is (see the jquery source for this here).
In other words, if your response is json, it should be fine. If it's not working, however, that is definitely a bug that needs to be figured out.
To give a little more clarity, the reason we're setting dataType for script * instead of just * (or leaving it alone), is for the sake of the accepts header. Doing script * sets the request header to prefer script over other types. This is necessary, because if your rails controller can respond with html, json, script, xml, etc., and no accepts header is defined (or it's just */*), then your controller will respond with whatever the first response type defined in your action is, which is confusing and inconsistent. I.e.:
respond_to do |format|
format.html {}
format.json {}
end
would respond with HTML for your remote form, whereas:
respond_to do |format|
format.json {}
format.html {}
end
would respond with JSON.
This is also the reason that jquery-ujs directly sets the accepts header if dataType is undefined. It gives a default behavior of asking for js type response if there are multiple response types available and none or otherwise specified. So remotipart seeks to mimic the behavior of jquery-ujs in this regard.
Again, this is just for the accepts header, as in terms of response parsing, setting dataType to script * should be no different than setting it to *.
What im doing is a regular form, submitted as type HTML. The controller doesnt have a multiple response type block, but just does render :json => { :foo => "bar" }.
Instead of the ajax:success callback i only get ajax:error called, because of a parse error in jQuery That parse error happens because the response type is assumed to be JS due to dataType set as such. If i remove the line that sets the dataType to "JS" in your library, the whole thing works as expected.
Again, remotipart is not setting the dataType to js, it's setting it to anything, with js preferred, meaning if js isn't available, it should be whatever your controller is returning. I can't do anything to debug this without knowing what exactly is going on, which is why I've asked what the accepts header in the request and the content-type header in the response actually are.