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?
Yes, 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 complete 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.com/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 %>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With