I'm wondering what the best practice is for passing variables to JavaScript functions in a rails view. Right now I'm doing something like:
<% content_for :javascript do %>
<script type="text/javascript">
Event.observe(window, 'load', function(){
js_function(<%= @ruby_array.to_json %>, <%= @rub开发者_开发知识库y_var %>); )}
</script>
<% end %>
Is this the right way to go about it?
A few options:
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 %>
'<%= j(a) %>' === '\\n<'
'<%= j(a).html_safe %>' === '\\n<'
<% end %>
to_json + html_safe
As mentioned by Vyacheslav, go upvote him.
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 %>
data.key1 === 'val1'
data.key2 === 'val2'
<% end %>
data- attributes
Add values to attributes, retrieve them with Javascript DOM operations.
Better with the content_tag
helper:
<%= content_tag 'div', '', id: 'data', data: {key1: 'val1', key2: 'val2'} %>
<%= javascript_tag do %>
$('#data').data('key1') === 'val1'
$('#data').data('key2') === 'val2'
<% end %>
Sometimes called "unobtrusive Javascript".
gon
Library specialized for the job: https://github.com/gazay/gon
Probably the most robust solution.
Gemfile:
gem 'gon'
Controller:
gon.key1 = 'val1'
gon.key2 = 'val2'
Layout app/views/layouts/application.html.erb
:
<html>
<head>
<meta charset="utf-8"/>
<%= include_gon %>
View:
<%= javascript_tag do %>
gon.key1 === 'val1'
gon.key2 === 'val2'
<% end %>
See also
- Injecting variable values into javascript and HAML in RoR
- content_for :javascripts_vars do
= "var costs_data = #{@records[:cost_mode][:data].to_json}".html_safe
= "var graph_data = #{@records[:cost_mode][:graph].to_json}".html_safe
There's a technique called "unobtrusive javascript". Here's a Railscast about it: link text . It works both with prototype an jQuery. There are also plugins that can help simplify some of the tasks described in the article.
I found that gem client variable, it helps you to do it easily.
In HAML can data are presented so:
.position{data: {latitude: @claim.latitude.to_json, longitude: @claim.longitude.to_json}}
:javascript
var latitude = $('.position').data('latitude');
var longitude = $('.position').data('longitude');
Note that if you aren't using escape_javascript
in a view, you can include it in your ruby code like so:
require 'action_view/helpers/javascript_helper'
include ActionView::Helpers::JavaScriptHelper
# escape_javascript is available here.
or if that wont work for you, then copy the source of the function in to your code, if need be:
JS_ESCAPE_MAP = {
'\\' => '\\\\',
"</" => '<\/',
"\r\n" => '\n',
"\n" => '\n',
"\r" => '\n',
'"' => '\\"',
"'" => "\\'"
}
JS_ESCAPE_MAP["\342\200\250".dup.force_encoding(Encoding::UTF_8).encode!] = "
"
JS_ESCAPE_MAP["\342\200\251".dup.force_encoding(Encoding::UTF_8).encode!] = "
"
# Escapes carriage returns and single and double quotes for JavaScript segments.
#
# Also available through the alias j(). This is particularly helpful in JavaScript
# responses, like:
#
# $('some_element').replaceWith('<%= j render 'some/element_template' %>');
def escape_javascript(javascript)
if javascript
result = javascript.gsub(/(\\|<\/|\r\n|\342\200\250|\342\200\251|[\n\r"'])/u) { |match| JS_ESCAPE_MAP[match] }
javascript.html_safe? ? result.html_safe : result
else
""
end
end
精彩评论