Forum: Ruby on Rails [Help] How to render or replace a partial page having <script> tag?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
D22781eccd92073acd6a1ed350c3d136?d=identicon&s=25 boblu (Guest)
on 2008-10-25 06:54
(Received via mailing list)
My problem is quite complicated.

In my project, I have to use static <script> tag to generate dynamic
graph with links inside it.
for example in a erb.html file, I wrote.


   1. ### this will generate a tree view in my page.
   2. <script>
   3.  create_tree(){###};
   4. </script>
   5. <div id='tree'></div>


However, the <script> section above is not static, I have to write a
helper to dynamically generate it. so it becomes to


   1. <%= generate_tree_view(:id=>1)  ## this will generate the
<script> section and insert them in the page
   2. <div id='tree'></div>


But, right now, my problem is I have to call this tree view page by
ajax like this

   1. ## view file show.erb.html
   2. ...
   3. <%= link_to_remote
'see_tree', :url=>{:action=>'view_tree', :id=>1} >
   4. <div id='view_tree'></div>
   5. ...


   1. ## controller file tree_controller.rb
   2. ...
   3. def view_tree
   4.   ### get some parameters, say 'tree_parameter' array
   5.   render :update do |page|
   6.     page.replace_html
'view_tree', :partial=>'view_tree', :object=>tree_parameter
   7.   end
   8. end
   9. ...


   1. ## partial page  _view_tree.erb.html
   2. <%= generate_tree_view(:tree_parameter=>view_tree)
   3. <div id='tree'></div>

I thought this should work because it actually worked if I directly
use the generate_tree_view help in the show.erb.html.
But however, when the partial page is called by ajax, the <script>
section which is generated by generate_tree_view didn't show up in the
page.
The final page only shows this:

   1. ## view file show.erb.html, saw by firebug 'cause it is the only
way I can see a rendered page.
   2. ...
   3. <div id='view_tree'>
   4.    <div id='tree'></div>
   5. </div>
   6. ...

It seems they got executed by the javascript call instead of just
display it.

So, what should I do if I just want to inject a <script> section in a
rendered page.

I'm not sure whether you have already got my idea, but I really
appreciate it if you help me solve this problem.
Thank you.
9b4c04c050122bcea16a6f3376d680fa?d=identicon&s=25 Daniel Bush (danb)
on 2008-10-25 14:29
(Received via mailing list)
I don't use RJS although I have used rails to generate javascript
dynamically.  I tend to prefer to see the javascript that's being
executed so that when things go wrong I know exactly why.  Anyway,
someone else reading this thread might have a quick answer whereas I
don't, but ...

On Oct 25, 3:53 pm, boblu <bobl...@gmail.com> wrote:
>    5. <div id='tree'></div>
>
>    4.   ### get some parameters, say 'tree_parameter' array
>    5.   render :update do |page|
>    6.     page.replace_html
> 'view_tree', :partial=>'view_tree', :object=>tree_parameter
>    7.   end
>    8. end
>    9. ...
>
>    1. ## partial page  _view_tree.erb.html
>    2. <%= generate_tree_view(:tree_parameter=>view_tree)
>    3. <div id='tree'></div>

There are no quotes around 'view_tree' above.  Is that right?

Check the javascript console (ctrl+shift+J in firefox) for javascript
errors that your function may be making.

Instead of RJS you could just try rendering the partial (that's just
my preference - it might be easier to see what's going wrong).
  render :partial => 'view_tree' ,
    :locals => { :your_var => 'your val' ... }
(_view_tree.html.erb)
And in your link_to_remote, I think you'll need to include an :update
option with the id of the element whose inner html you are updating.
See the docs
http://api.rubyonrails.org/classes/ActionView/Help...

Any script tag in the partial will probably be eval'd by the
javascript interpreter. (The link_to_remote should generate an
Ajax.Updater with the evalScripts:true option which you can check for
just to make sure).

>    2. ...
>    3. <div id='view_tree'>
>    4.    <div id='tree'></div>
>    5. </div>
>    6. ...
>
> It seems they got executed by the javascript call instead of just
> display it.
>
> So, what should I do if I just want to inject a <script> section in a
> rendered page.

Prototype will remove script tags whether it is set to process them or
not so you will likely not see them in firebug after the update (which
is probably a good thing).  (I'm referring specifically to prototype's
Ajax.Updater)


Also check your output in your functional tests for this controller:

  # Check the partial _element3_1.html.erb.
  def test_1a
    xml_http_request :post,'view_tree',params
    assert_tag :tag => 'script' , :content => /alert/
  end


--
Daniel Bush
81b61875e41eaa58887543635d556fca?d=identicon&s=25 Frederick Cheung (Guest)
on 2008-10-25 14:32
(Received via mailing list)
On Oct 25, 5:53 am, boblu <bobl...@gmail.com> wrote:
> My problem is quite complicated.
>    3. def view_tree
>    4.   ### get some parameters, say 'tree_parameter' array
>    5.   render :update do |page|
>    6.     page.replace_html
> 'view_tree', :partial=>'view_tree', :object=>tree_parameter
>    7.   end
>    8. end

page.replace_html maps onto prototype's Element.update function which
strips script tags from what it's inserting (and due to the way it
does the update I doubt it would make much difference if the scripts
weren't removed).

Two ways out:
a) Use link_to_remote 'Click me', :update => 'view_tree', :url =>
{...}
and then in your controller instead of using render :update just
render the partial

b) call that javascript from the render :update block ie

render :update do |page|
  page.replace_html
'view_tree', :partial=>'view_tree', :object=>tree_parameter
  page << "alert('hello world')
end

whether you do this before or after the replace_html somewhat depends
on whether the JS depends on the page having being updated or not

Fred
D22781eccd92073acd6a1ed350c3d136?d=identicon&s=25 boblu (Guest)
on 2008-10-25 17:59
(Received via mailing list)
@Fred
Thank you for reply. I just tried the two ways you suggested.

1. use link_to_remote :update in view and render :partial in
controller instead of calling render :update
This really does not make any differences. They gave the same output
which all my staff in <script> tag got stripped.

2. directly insert the javascript in the controller.
Actually, this is not allowed in my case.
Because I generated a bunch of quite complicated javascript in the
'generate_tree_view' helper.
And inside this helper, I also called 'remote_function' to give a
javascript call to some link which will be rendered as a tree's node
by the library I am using.
As the remote_function can not be called in the controller, I can not
generate the script inside controller.
And the only way I can generate it is put 'generate_tree_view' helper
in the view.


@Daniel
Thank you for reply. Though I barely understand what your point is.
As far as I understood, if you want to make a ajax call in rails by
using link_to_remote,
you either use 'link_to_remote :update' in view and use
'render :partial' in controller
or use 'link_to_remote'(without update field) in view and use 'render
page.replace' in controller.

But you said 'Prototype will remove script tags whether it is set to
process them or
not'.
Does that mean I actually can not insert a dynamic <script> tag inside
the rendered page by using prototype javascript call?
81b61875e41eaa58887543635d556fca?d=identicon&s=25 Frederick Cheung (Guest)
on 2008-10-25 19:42
(Received via mailing list)
On Oct 25, 4:56 pm, boblu <bobl...@gmail.com> wrote:
> @Fred
> Thank you for reply. I just tried the two ways you suggested.
>
> 1. use link_to_remote :update in view and render :partial in
> controller instead of calling render :update
> This really does not make any differences. They gave the same output
> which all my staff in <script> tag got stripped.
>

It may strip it, but the javascript definitely runs (at least in my
simple test app).

> in the view.
>
the stuff inside the render :update block is not evaluated within the
context of the controller. You can call helper functions in there such
as remote_fuction or generate_tree_view.

Fred
D22781eccd92073acd6a1ed350c3d136?d=identicon&s=25 boblu (Guest)
on 2008-10-26 02:12
(Received via mailing list)
@Fred

I re-checked the script code I generated and found some problem there.
After fixing that problem, everything goes beautifully by using you
method.
Thank you very much for your suggestion.

And I really feel this is the most helpful place when I have some
questions with rails.
Cheers!

On Oct 26, 2:41 am, Frederick Cheung <frederick.che...@gmail.com>
9b4c04c050122bcea16a6f3376d680fa?d=identicon&s=25 Daniel Bush (danb)
on 2008-10-26 05:58
(Received via mailing list)
On Oct 26, 2:56 am, boblu <bobl...@gmail.com> wrote:
> @Fred

>
> @Daniel
> Thank you for reply. Though I barely understand what your point is.
> As far as I understood, if you want to make a ajax call in rails by
> using link_to_remote,
> you either use 'link_to_remote :update' in view and use
> 'render :partial' in controller
> or use 'link_to_remote'(without update field) in view and use 'render
> page.replace' in controller.

I was suggesting you try 'link_to_remote :update' as doing it a
different
way might help you to work out what the bug is.
Ignore my point on RJS though - I've just got "helper-method" fatigue
at the moment; comes from wanting to know and control what's
going on under the covers all the time.

>
> But you said 'Prototype will remove script tags whether it is set to
> process them or
> not'.
> Does that mean I actually can not insert a dynamic <script> tag inside
> the rendered page by using prototype javascript call?

I think you can insert script tags if you really wanted to.  Maybe
with prototype's Ajax.Request
where you grab the response and inject it into the dom using your own
handler.
In firefox it will show up like a tag with a text node so not what you
want unless you set it not to display.  Just inserting it into the dom
may not get the javascript interpreter to execute it.
You might have to eval the contents of the script tag.
Much easier just to use Ajax.Updater with evalScripts:true.



--
Daniel Bush
This topic is locked and can not be replied to.