Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: Remote javascript with " is not executed #89

Closed
dhampik opened this issue Jul 14, 2013 · 29 comments
Closed

Bug: Remote javascript with " is not executed #89

dhampik opened this issue Jul 14, 2013 · 29 comments

Comments

@dhampik
Copy link

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
Copy link
Author

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
Copy link
Author

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
Copy link

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
Copy link
Author

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
Copy link

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
Copy link
Owner

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

@akshayrawat
Copy link

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

@dgbrown
Copy link

dgbrown commented Jan 27, 2014

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

@akaspick
Copy link

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
Copy link

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
Copy link

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
Copy link

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

@asok
Copy link

asok commented May 23, 2014

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

@chellberg
Copy link

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
Copy link

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
Copy link

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

that worked for me ! Thank you!

@pineapplethief
Copy link

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.

@randoum
Copy link

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
Copy link
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
Copy link

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
Copy link
Owner

That would be awesome, if anyone wants to volunteer.

@JangoSteve
Copy link
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
Copy link
Collaborator

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

@randoum
Copy link

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
Copy link

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

This solution worked well for me.
Many thanks!

@sealocal
Copy link

sealocal commented Nov 5, 2015

+1 for string interpolation:

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

@trkrameshkumar
Copy link

Thanks guys, this workes

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

@westonganger
Copy link

My initial solution was the following

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

Which led me to the creation of the following monkey patch:

# config/initializers/remotipart_escape_javascript_patch.rb

if defined?(Remotipart)

  module Remotipart
    module EscapeJavascriptFix
 
      def escape_javascript(javascript)
        if remotipart_submitted?
          super("#{javascript}")
        else
          super
        end
      end

      alias_method :j, :escape_javascript

    end
  end

  ActiveSupport.on_load :action_view do
    ActionView::Base.send(:include, Remotipart::EscapeJavascriptFix)
  end
end

Now you can simply do:

$(".form-wrapper").html("<%= j render 'form' %>");

I would be happy to make a PR for this. Also if help is needed for maintaining this plugin I am interested.

@rileys
Copy link

rileys commented May 19, 2018

For anyone else using escape_utils gem this causes an issue where the data returned is not html safe. Removed escape_utils and works fine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests