I am creating a website in Ruby on Rails. I have a controller action that renders a view like so:
def show
time_left = Time.now.to_i - 3.hours.to_i
@character = current_user.characters.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => @character }
end
end
This is fine as it renders the show.html.erb as I like. I would like however to somehow pass time_left to the view as a Javascript variable as this value is use by a countdown JQuery plugin.
I could put a javascript block on the page in the HTML and print a instance variable out like so:
<script type="javascript"> $('#countdown').countdown('<%= @time_left =>')</script>
But I would like to keep all my JS in a external file and off the page could anyone give some advice on how to implement this?
I am creating a website in Ruby on Rails. I have a controller action that renders a view like so:
def show
time_left = Time.now.to_i - 3.hours.to_i
@character = current_user.characters.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => @character }
end
end
This is fine as it renders the show.html.erb as I like. I would like however to somehow pass time_left to the view as a Javascript variable as this value is use by a countdown JQuery plugin.
I could put a javascript block on the page in the HTML and print a instance variable out like so:
<script type="javascript"> $('#countdown').countdown('<%= @time_left =>')</script>
But I would like to keep all my JS in a external file and off the page could anyone give some advice on how to implement this?
Share Improve this question edited Jan 25, 2015 at 8:41 Ciro Santilli OurBigBook. 383k117 gold badges1.3k silver badges1.1k bronze badges asked Apr 27, 2010 at 14:09 RailsSonRailsSon 20.6k31 gold badges84 silver badges105 bronze badges 1- Related: stackoverflow./questions/2464966/…n-in-rails-view – Ciro Santilli OurBigBook. Commented Nov 11, 2014 at 9:58
2 Answers
Reset to default 9Yes, you can!
Rewrite your JS code into function with one argument (timelimit) and put it into some external file. Then you can call the function from view and pass that @timeleft
variable as JS function argument.
Short example:
#controller
@time_left = Time.now.to_i - 3.hours.to_i
.
#javascript
function count_down(time_left) {
$('#countdown').countdown(time_left)
}
.
#view
<%=javascript_tag "count_down(#{@time_left})" -%>
javascript_tag
Example not tested, it is only idea not plete solution. Don't forget to load that JS file. You can use other JS rails helper javascript_include_tag.
retro's technique of using a function parameter is a possibility, but you have to properly escape the variable you are passing with either escape_javascript or to_json + html_safe as explained below.
However, since you want to affect external files, the best techniques will be to use gon. Another good possibility is to use data- attributes.
gon
Gem specialized for the job: https://github./gazay/gon
Probably the most robust solution.
Gemfile:
gem 'gon'
Controller:
gon.timeleft = 1
Layout app/views/layouts/application.html.erb
:
<html>
<head>
<meta charset="utf-8"/>
<%= include_gon %>
<%= javascript_include_tag 'application' %>
Asset file:
gon.timeleft === 1
data- attributes
Add values to attributes, retrieve them with JavaScript DOM operations.
Sometimes called "unobtrusive Javascript".
View head:
<%= javascript_include_tag 'application' %>
View body:
<%= content_tag 'div', '', id: 'data', data: {timeleft: '1'} %>
Asset file:
$(function() {
parseInt($('#data').data('key1')) === 1
})
The following illustrate how escape_javascript
and to_json
work for you to use on top of retro's answer.
escape_javascript
Alias: j
.
Works only on strings.
Escapes characters that can have special meanings in JavaScript strings, like backslash escapes, into a format suitable to put inside JavaScript string literal quotes.
Maintains html_safe
status of input,
so needs html_safe
otherwise special HTML chars like <
would get escaped into <
.
<% a = "\\n<" %>
<%= javascript_tag do %>
f('<%= j(a) %>') // === '\\n<'
f('<%= j(a).html_safe %>') // === '\\n<'
<% end %>
to_json + html_safe
Works because JSON is almost a subset of Javascript object literal notation.
Works not only on hash objects, but also on strings, arrays and integers which are converted to JSON fragments of the corresponding data type.
<% data = { key1: 'val1', key2: 'val2' } %>
<%= javascript_tag do %>
var data = <%= data.to_json.html_safe %>
f(data.key1) \\ === 'val1'
f(data.key2) \\ === 'val2'
<% end %>