Best Way to Include JavaScript from partials

/app/helpers/application.rb:

def add_javascript(js_file)
@additional_javascripts ||= []
@additional_javascripts << js_file
end

def import_additional_javascripts
if @additional_javascripts

  javascript_include_tag *@additional_javascripts
end

end

/app/views/some_controller/some_action.rb:

<% add_javascript “path/to/js_file” %>

/app/views/layout/application.rb:

<%= javascript_include_tag :defaults %> <%= import_additional_javascripts %>

To make sure the same file is not required twice, you can use the Array#uniq method on the @additional_javascripts object.

I have thought about this for a while. I’ve not implemented it,
but it’s along the lines of the content_for method. This is
untested and at the moment just my mind rambling

in the application helper

def demand_javascript( *list )
@demanded_javascripts ||= Set.new

find new items in list

tmp = ( @demanded_javascripts | list ) - @demanded_javascripts

content_for :javascripts do
javascript_include_tag *tmp
end
@demanded_javascripts.add list
end

Then in your view you can call as many times as you like

<% demand_javascript “my”,“javascript”,“files” %>

I hope that works. I think I’ll give it a try when I get home.

Robert,
Yes, I use this code regularly in all of my rails apps. As far as I know, the view code is always run before the layout code. If you tried something similar or tried the code I posted, and it failed, I would be willing to help you debug it, just tell me how it failed.

Jimmy

I have just released a really simple plugin for this. It ensures that there is no duplication of javascripts. Stylesheets can also be included similarly.

You can get the lowdown at

http://www.agilewebdevelopment.com/plugins/resource_on_demand

In your head tag of the layout

<%= include_on_demand %>

anywhere in your views

<% demand_javascript “some”, “javascript”, :defaults %>

<% demand_stylesheet “a”, “style”, “sheet” %>

This plugin is very simple but I hope useful :slight_smile:

Cheers
Daniel

Not quite enough information. :frowning: The svn is at

http://svn.devjavu.com/liquid/resource_on_demand

I wouldn’t think it would make a difference. Does it not work in this situation?

I would have thought that you could include the

<%= include_on_demand %> in the head tag and then use

<% demand_javascript “my_script” %> in you partial.

I will check it when I get home (not for about 8 or 9 hours though! )

Ok I’ve had a chance to play with it and I’ve found a way that it can be done. It’s a bit of hackery though.

You can put a yield call in your head tag so that you can get javascripts there. But, before your yield in the head tag, you need to render your partials. You can put them elsewhere in your layout by including these into content_for blocks.

In your layout (HTML interspersed where ever )

<% content_for :my_partial do %>
<%= render :partial => ‘my_partial’ -%>
<% end %>

<%= yield :javascripts %>

<%= yield :my_partial %>

In the context of the plugin that I released, if your interested. (I’ve changed the method names since last night. I wasn’t entirely satisfied with them)

<% content_for :my_partial do %>

<%= render :partial => ‘my_partial’ -%>
<% end %>

<%= require_on_demand %>

<%= yield :my_partial %>

and then anywhere in your partial, or views
<% require_javascript “my”, “javascript”, :defaults %>

At least this works on edge :wink:

I hope that will get you going.

Cheers
Daniel

This content_for and yield looks overly complicated to me. In
particular, as content_for does not do much more than set an instance
variable. A tiny bit of code in ApplicationHelper does all that's
necessary.

Michael

# app/helpers/application_helper.rb
module ApplicationHelper
  def require_js(*js)
    @required_js ||= []
    @required_js |= js
  end
  
  def require_css(*css)
    @required_css ||= []
    @required_css |= css
  end
  
  def include_required_js
    javascript_include_tag(*@required_js)
  end

  def include_required_css
    stylesheet_link_tag(*@required_js)
  end
end

# app/views/layouts/application.rhtml
<html>
  <head>
    <%= include_required_js %>
    <%= include_required_css %>
  </head>
  <body>
  <%= yield %>
  </body>
</html>

# app/views/whatever/index.rhtml
<%= render :partial => 'part1' %>
<%= render :partial => 'part2' %>

# app/views/whatever/_part1.rhtml
<% require_js 'this' -%>
<% require_css 'that', 'another_one' -%>
Partial 1

# app/views/whatever/_part2.rhtml
<% require_js 'this', 'something_else' -%>
<% require_css 'that' -%>
Partial 2

In your layout (HTML interspersed where ever )

<% content_for :my_partial do %>
<%= render :partial => ‘my_partial’ -%>

<% end %>

<%= yield :javascripts %>

<%= yield :my_partial %>

This content_for and yield looks overly complicated to me. In
particular, as content_for does not do much more than set an instance

variable. A tiny bit of code in ApplicationHelper does all that’s
necessary.

Michael

app/helpers/application_helper.rb

module ApplicationHelper
def require_js(*js)
@required_js ||= []

@required_js |= js

end

def require_css(*css)
@required_css ||= []
@required_css |= css
end

def include_required_js
javascript_include_tag(*@required_js)
end

def include_required_css
stylesheet_link_tag(*@required_js)
end
end

app/views/layouts/application.rhtml

<%= include_required_js %> <%= include_required_css %> <%= yield %>

app/views/whatever/index.rhtml

<%= render :partial => ‘part1’ %>
<%= render :partial => ‘part2’ %>

app/views/whatever/_part1.rhtml

<% require_js ‘this’ -%>
<% require_css ‘that’, ‘another_one’ -%>
Partial 1

app/views/whatever/_part2.rhtml

<% require_js ‘this’, ‘something_else’ -%>

<% require_css ‘that’ -%>
Partial 2

Initially this was all I thought it was also. But when you have a partial in you layout it is not so simple.

The partial in the layout does not seem to be processed prior to the layout being rendered. It seems to be rendered more inline than the view.

Following your suggestion above,

app/views/layouts/application

.rhtml

<%= include_required_js %> <%= include_required_css %> <%= yield %>
 <%= render :partial => 'part3' %>

Any javascript required in the part3 partial will not be added. This was the problem, that partials in the layout are not included.

Also thanx for the |= I didn’t know about that one.

Cheers
Daniel