Bug: Remote javascript with " is not executed #89

Open
dhampik opened this Issue Jul 14, 2013 · 27 comments

Projects

None yet
@dhampik
dhampik commented Jul 14, 2013

I'm using remotipart gem in conjuction with nested_form gem.
And javascript response from the server (which is inside form.js.erb) is not executed.

I studied how remotipart works and did a lot of debugging and found out the root of evil.
Unfortunately I don't know how to fix it.

So, here is the case:

$('.form-wrapper').html("<div data-sample=\"&lt;div id=&quot;test&quot;&gt;&lt;/div&gt;\"></div>");

The above javascript response from the server will not be executed on the client! Because there is &quot; symbol!

And this is exactly what happens if you are using remotipart+nested_form. Nested form gem produces a piece of html with data-attribute on hidden div which contains the template for newly created items which added with javascript. And this template contains &quot; symbol.

Why this is happening with remotipart?
I guess, because it wraps actual javascript in <textarea> tag and when this textarea contents are extracted by javascript the &quot; symbols are converted into "

@dhampik
dhampik commented Jul 14, 2013

Btw, the following workaround works for me (at least I have not found any issues with it yet, though it may cause problems):

<% if remotipart_submitted? %>
    $('.form-wrapper').html("<%= escape_javascript(render('form')).gsub('&quot;', "'") %>");
<% else %>
    $('.form-wrapper').html("<%= escape_javascript render('form') %>");
<% end %>

But it works only in my particular case and that is not a universal solution.

@dhampik
dhampik commented Jul 16, 2013

I went deeper into this and it seems like the actual hacky fix is gsub, but not replacement of &quot; with '. Seems like it relates to this issue in rails and the point is that when we use #gsub, it converts SafeBuffer to string and html entities in this string is escaped then.
There is defenetly something awkward here.
So, this is how I fix my issue now. Maybe I'll investigate futher.

<% if remotipart_submitted? %>
    $('.form-wrapper').html("<%= j "#{render('form')}" %>");
<% else %>
    $('.form-wrapper').html("<%= j render('form') %>");
<% end %>
@asok
asok commented Aug 7, 2013

I came across similar thing. But I think this is not related to rails or remotipart but to the jquery.iframe-transport. As you mentioned:

I guess, because it wraps actual javascript in <textarea> tag and when this textarea contents are extracted by javascript the " symbols are converted into '

So what happens is that reponse arrives to the browser with html entity (like &quot;) inside the textarea. When the js code for evaluation is extracted the html entities are replaced by theirs respective characters (like &quot; to '). That's a characteristic of a textarea.
@cmlenz Couldn't iframe-transport wrap the response in div instead of a textarea?

This is my example response from server that causes the error:

<textarea data-type="text/javascript" data-status="200" data-statusText="OK">alert('This response has got an html entity &#x27; that will be replaced with the char "'" and thus causing a parse error on this line')
</textarea>
@dhampik
dhampik commented Aug 7, 2013

@asok @JangoSteve I think another way out is to escape html entities differently in remotipart's lib/remotipart/render_overrides.rb, but I'm not sure if it's possible. I mean escape

$('.form-wrapper').html("<div data-sample=\"&lt;div id=&quot;test&quot;&gt;&lt;/div&gt;\"></div>");

as

$('.form-wrapper').html("<div data-sample=\"&amp;lt;div id=&amp;quot;test&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;\"></div>");

this is exactly what I do with the above mentioned piece of code:

<% if remotipart_submitted? %>
    $('.form-wrapper').html("<%= j "#{render('form')}" %>");
<% else %>
    $('.form-wrapper').html("<%= j render('form') %>");
<% end %>
@damienromito

my only solution is to close <textarea> and open an other. It's works but it's not very sexy XD

</textarea>
  <script>
     alert('it work');
  </script>
<textarea>

but Jquery is not recognized...

Uncaught ReferenceError: jQuery is not defined 
@JangoSteve
Owner

Is there a test someone could write for this by any chance? The tests for remotipart are located here.

@akshayrawat

This is definitely a problem today, workaround mentioned by dhampik works.

@dgbrown
dgbrown commented Jan 27, 2014

Ugly workaround, but I appreciate it. Thank you gentlemen.

@akaspick

I have a similar issue when uploading a file. Apostrophes in my javascript are encoded as html entities, but the JS doesn't execute when embedded in the texteara. Via a normal form save, the javascript executes fine though.

// the text of the option when rendered should be test'string
$element.html('<option value=\"912\">test&#39;string<\/option>');
@akaspick

If the javascript contains or (newline characters) is also fails to execute the JS properly.

Does anybody have a more reliable solution to dealing with all of these html entities that cause problems?

@akaspick

This seems to work at the moment...

template_html = render('template')
template_html = template_html.gsub('&#39;',"'").gsub('&','&amp;') if remotipart_submitted?
escaped_html = j(template_html)
@DominikLevitsky

Still no fix for this? Can't make it work with HAML.

@asok
asok commented May 23, 2014

Hi @JangoSteve,
I've setup a dead simple application to reveal this bug here.

@chellberg

Just to chime in, I'm having trouble with this bug as well. Jquery-rails 2.3.0 and the latest Remotipart. I've read thread after thread about this error, and all I've found are messy workarounds.

@szyablitsky

Got the same issue. When I change "can't" to "can not" (string without apostrophe) in title attribute within view.js file everything works fine. With apostrophe returned javascript does not execute.

@panSarin

<% if remotipart_submitted? %>
$('.form-wrapper').html("<%= j "#{render('form')}" %>");
<% else %>
$('.form-wrapper').html("<%= j render('form') %>");
<% end %>

that worked for me ! Thank you!

@pineapplethief

I like panSarin solution, thank you! less code than gsub, not sure about perfomance though. I really hope this nasty glitch will be fixed in future version of remotipart.

@palkan palkan referenced this issue in study-and-research/QnA Apr 23, 2015
Merged

Add files attachment to q a #6

@randoum
randoum commented Oct 8, 2015

@JangoSteve you haven't participated to this conversation since 2013, are you still participating to remotipart? Thanks in advance

@JangoSteve
Owner

@randoum You're right, life seems to be getting in the way. Is there a pull request anyone has submitted for this that I could look at and merge in?

@randoum
randoum commented Oct 14, 2015

@JangoSteve Nop there's no pull request, I was about to submit one, then I decided to go another direction.
Anyhow, what about finding a collaborator to second you, someone that could spend a little time on the project?
Cheers

@JangoSteve
Owner

That would be awesome, if anyone wants to volunteer.

@JangoSteve
Owner

*I should mention, I do have someone else who's helping maintain the project, though I think they got a bit busy themselves. Looks like @esbanarango is back in action 😄

@esbanarango
Collaborator

@randoum Could you go ahead and make that PR? I'll check as soon as possible.

@randoum
randoum commented Oct 14, 2015

Sorry @esbanarango I already migrated my code to use another solution, so I don't have an experimentation zone anymore

@SenikTony
$('.form-wrapper').html("<%= j "#{render('form')}" %>");

This solution worked well for me.
Many thanks!

@sealocal
sealocal commented Nov 5, 2015

+1 for string interpolation:

.html("<%= j "#{render('form')}" %>");
@trkrameshkumar

Thanks guys, this workes

$('.response_block').html("<%= j "#{render('some_partial')}" %>");

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment