如何在Rails中调用javascript后期呈现?
这是facebox弹出内容如何在Rails中调用javascript后期呈现?,javascript,jquery,ruby-on-rails,render,facebox,Javascript,Jquery,Ruby On Rails,Render,Facebox,这是facebox弹出内容 <div class="form_container"> <% form_remote_tag :url => { :action => 'custom', :d=>params[:day], :h=>params[:hour] }, :class => 'general-form', :update => 'grid['+params[:day]+']['+params[:h
<div class="form_container">
<% form_remote_tag :url => { :action => 'custom', :d=>params[:day], :h=>params[:hour] },
:class => 'general-form',
:update => 'grid['+params[:day]+']['+params[:hour]+']',
:success => 'handle_success('+params[:day]+','+params[:hour]+')' do -%>
<table width="300px" style="border:none">
<% @availability_hash.each_key do |availability_id| %>
#some view related stuff
<% end %>
</table>
<input type="submit" class="btn" value="Re-assign Coaches" />
<% end %>
</div>
这是部分(_grid_item.html.erb)
:
这是主页面中使用的脚本
<script type="text/javascript">
jQuery(document).ready(function($) {
jQuery('a[rel*=facebox]').facebox()
$.facebox.settings.opacity = 0.5
})
function handle_success(d,h){
jQuery(document).trigger('close.facebox');
var link_div = document.getElementById('link['+d+']['+h+']');
jQuery(link_div).facebox();
}
</script>
<div class="master_view">
<table class="master_scheduler_table" id="master_scheduler_table" >
<% HOURS_IN_A_DAY.each do |hour| %>
<tr>
<td><%= time(hour*2) %></td>
<% DAYS_IN_A_WEEK.each do |day| %>
<td id="grid[<%= day %>][<%= hour %>]" >
<%= render(:partial => "grid_item" , :locals => {:day=>day, :hour=>hour, :data=>@data[day][hour]}) %>
</td>
<% end %>
</tr>
<% end %>
</table>
</div>
jQuery(文档).ready(函数($){
jQuery('a[rel*=facebox]')。facebox()
$.facebox.settings.opacity=0.5
})
函数句柄_成功(d,h){
jQuery(document.trigger('close.facebox');
var link_div=document.getElementById('link['+d+']['+h+']');
jQuery(link_div).facebox();
}
“grid_item”,:locals=>{:day=>day,:hour=>hour,:data=>@data[day][hour]})%>
渲染完成后,我想调用一个脚本。怎么做?我正在视图中使用form_remote_标记
渲染部分是在Ajax上下文中完成的,不会重新加载页面。form_remote_标记有一个:success方法,我可以在其中调用javascript。不幸的是,我放在success方法中的javascript在渲染完成之前被调用。但是,我需要在渲染完成后调用javascript
为了清楚起见,我只是简单地提出了一条警告信息。实际上,我正在对正在渲染的DIV元素调用一个facebox()方法。在呈现DIV元素之后,应该将facebox()(jQuery的)方法应用于该元素,只有这样它才会有效
编辑:我已经添加了完整的代码。如果您可以看到,我将在Ajax返回后调用javascript方法handle_success。(我很抱歉将:success方法放在了partial中)。在实际渲染完成之前调用handle_success。这应该是“在”它完成之后渲染在服务器端完成,一旦组成了整个页面,生成的HTML将返回给客户端。因此,在这种情况下无法执行客户端脚本。要在加载页面后调用某些javascript,可以使用
onload
事件处理程序:
<script type="text/javascript">
window.onload = function() {
// put your code here
};
</script>
window.onload=函数(){
//把你的代码放在这里
};
或者,如果您使用:
$(函数(){
//把你的代码放在这里
});
或者,如果您使用:
document.observe(“dom:loaded”,function()){
//把你的代码放在这里
});
呈现在服务器端完成,一旦组成整个页面,生成的HTML将返回给客户端。因此,在这种情况下无法执行客户端脚本。要在加载页面后调用某些javascript,可以使用onload
事件处理程序:
<script type="text/javascript">
window.onload = function() {
// put your code here
};
</script>
window.onload=函数(){
//把你的代码放在这里
};
或者,如果您使用:
$(函数(){
//把你的代码放在这里
});
或者,如果您使用:
document.observe(“dom:loaded”,function()){
//把你的代码放在这里
});
您的理解有点错误:
“提交标记具有:success方法
在这里我可以调用javascript。
不幸的是,我使用的javascript
投入成功的方法是获得成功
调用“before”,渲染是
完成。”
:success
方法用于提交成功的时间。不适用于提交后发生的任何事件!您需要在部分渲染完成后执行成功方法,而不是在单击提交按钮时执行!如果您熟悉jquery,我建议您采用不引人注目的方式。我从不依赖内置助手,因为它缺乏灵活性,而且我讨厌使用内联javascript。。你将无法缓存它。我将把我所有的javascript都放在一个缩小的js文件中,这个文件可以缓存一次,而不是代码到处传播。无论如何,我只是偏离了重点
其次,您不应该为ajax调用呈现分部。这将始终刷新您的页面。相反,您应该为特定的控制器操作创建一个.js.erb
或.xml.erb
文件
既然你还没有给出你在你的部分文章中所呈现的内容,我将为你提供一个大致的答案。请与我们分享您的部分代码,以便我们知道您到底想要什么。还提供要在成功时修改的HTML标记的选择器id/class
(呈现后即..)
如果您想要更好的方式,我将为您提供我用于ajax的配置:
在application.js中:
$.ajaxSetup({
'beforeSend': function(xhr) {xhr.setRequestHeader("Accept", "text/xml")}
});
$(document).ready(function() {
// All non-GET requests will add the authenticity token
// If not already present in the data packet
$("body").bind('ajaxSend', function(elm, xhr, s) {
if (s.type == "GET") return;
if (s.data && s.data.match(new RegExp("\\b" + window._auth_token_name + "="))) return;
if (s.data) {
s.data = s.data + "&";
} else {
s.data = "";
// if there was no data, $ didn't set the content-type
xhr.setRequestHeader("Content-Type", s.contentType);
}
s.data = s.data + encodeURIComponent(window._auth_token_name) + "=" + encodeURIComponent(window._auth_token);
});
});
在IE和SAFARI中,accept头默认为text/html,而不是text/xml或text/javascript。要更正此问题,请将其添加到application.controller.rb;解决所有跨浏览器问题:
def correct_safari_and_ie_accept_headers
ajax_request_types = [ 'text/javascript', 'application/json', 'text/xml']
request.accepts.sort!{ |x, y| ajax_request_types.include?(y.to_s) ? 1 : -1 } if request.xhr?
end
在版面
your_layout.html.erb
中,将以下内容添加到标题中:
<% if protect_against_forgery? %>
<script type="text/javascript" charset="utf-8">
//<![CDATA[
window._auth_token_name = "#{request_forgery_protection_token}";
window._auth_token = "#{form_authenticity_token}";
//]]>
</script>
<% end %>
<%= javascript_include_tag 'jquery.taconite.js','application.js', :cache => true %>
现在,在用于渲染部分
渲染(:partial=>“grid\u item”)
的操作中,将操作更改为
def your_action_here
# CODE GOES HERE:
# @instance_variable_to_store_stuff = some_stuff
respond_to do |format|
format.html {redirect_to :action => :index}
format.xml #EXTREMELY IMPORTANT. THIS CORRESPONDS TO your_action_here.xml.erb
end
end
现在在您的视图/your\u controller/
中创建一个your\u action\u here.xml.erb
文件。在该文件中,您可以添加渲染发生后执行的javascript代码。这一行动将以两种方式作出回应。如果用户在浏览器中禁用了javascript,它将用html数据响应,否则它将默认为xml数据。现在,这就是塔克尼特进入画面的地方。taconite的妙处在于它将所有基于jquery的DOM修饰符转换为符合XML的标记
不要执行$(“#div”).append('YO!')
您可以执行以下操作:
<append select="#div">
<div>YO!</div>
</append>
如果要执行多个DOM更新,可以执行以下操作,例如:
<taconite>
<replace select="#div">
<%=h @instance_variable_to_store_stuff %>
<replace>
<append select="#someotherelement_id">
<div>I got appended to #someotherelement_id</div>
</append>
<slideUp select=".someelementwithaclass" />
<slideDown select=".someelementwithanotherclass" />
</taconite>
我被附加到了#其他元素_id
您还可以使用eval标记在your_action_here.xml.erb中运行javascript,如下所示:
<taconite>
<append select="#div">
<%=h @instance_variable_to_store_stuff %>
</append>
<eval>
alert("HO! HO! HO!");
setTimeout(($("#flash").effect("highlight", {}, 3000).slideUp("slow")), 5000);
$("form")[0].reset();
</eval>
</taconite>
警惕(“嗬!嗬!嗬!”);
setTimeout($(“#flash”).effect(“highlight”),{},3000.slideUp(“slow”)),5000);
$(“表单”)[0]。重置();
您应该记住的一件事是,所有的xml标记都应该是关闭的,而不是
def your_action_here
# CODE GOES HERE:
# @instance_variable_to_store_stuff = some_stuff
respond_to do |format|
format.html {redirect_to :action => :index}
format.xml #EXTREMELY IMPORTANT. THIS CORRESPONDS TO your_action_here.xml.erb
end
end
<append select="#div">
<div>YO!</div>
</append>
<taconite>
<append select="#div">
<%=h @instance_variable_to_store_stuff %>
</append>
</taconite>
<taconite>
<replace select="#div">
<%=h @instance_variable_to_store_stuff %>
<replace>
<append select="#someotherelement_id">
<div>I got appended to #someotherelement_id</div>
</append>
<slideUp select=".someelementwithaclass" />
<slideDown select=".someelementwithanotherclass" />
</taconite>
<taconite>
<append select="#div">
<%=h @instance_variable_to_store_stuff %>
</append>
<eval>
alert("HO! HO! HO!");
setTimeout(($("#flash").effect("highlight", {}, 3000).slideUp("slow")), 5000);
$("form")[0].reset();
</eval>
</taconite>
<!-- IN HTML.ERB FILE -->
<div class="form_container">
<% form_tag({:action => :custom, :d => params[:day], :h => params[:hour]}, {:class => "general-form"}) do %>
<table width="300px" style="border:none">
<% @availability_hash.each_key do |availability_id| %>
<tr>
<td width="50%"><b><%= CoachAvailability.find(availability_id).coach_availability_template.coach.display_name %></b> (X/8)</td>
<td><%= select_tag('template['+availability_id.to_s+']', options_for_select([["Available", 0],["Scheduled", 1]], :selected => CoachAvailability.find(availability_id).status )) %></td>
</tr>
<% end %>
</table>
<%= submit_tag "Re-assign Coaches", :class => "btn" %>
<% end -%>
//In your JS file
$(".general-form").live('submit', function() {
$.post(this.action, $(this).serialize(), "_method=post");
return false;
})
#In your controller
def custom
master_scheduler
h = params[:h].to_i
d = params[:d].to_i
@day = d
@hour = h
respond_to do |format|
format.xml
end
end
<!-- IN custom.xml.erb -->
<taconite>
<append select="#div_changed_content">
What ever changes you want to make. Your code is bit confusing. So i won't go deep into what should come here. You know what changes you want to make. :)
Maybe you wanted to add this? How did you get data[:commited_coaches] and data[:available_coaches] without passing it through the partial??
Anyways if you want to pass it now you can do so from the controller itself. By creating a @data_commited_coaches and @data_available_coaches and storing the above in that.
<div class ="left_inner_element">
<div class="l_upper_element">
<div class="coaches_committed"><%= data[:committed_coaches] %></div>
<div class="coaches_available"><%= data[:available_coaches] %></div>
</div>
<div class="l_lower_element"><%= data[:classes] %> : <%= data[:avg_attendance] %>
</div>
</div>
<a id="link[<%= day %>][<%= hour %>]" rel="facebox" href="coach_selector_popup?(bla bla)" >
<div class ="right_inner_element right_inner_color_<%= data[:color_code] %>">
#some ui stuff
</div>
</a>
</append>
<eval>
// You can call the handle_success here: If i guessed right, this is what you want to do.
handle_success(<%= @day %>,<%= @hour %>);
</eval>
</taconite>