admin管理员组文章数量:1405131
This is the facebox popup content
<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>
This is the controller method
def custom
master_scheduler
h = params[:h].to_i
d = params[:d].to_i
render(:partial => "grid_item" , :locals => {:day=>d, :hour=>h})
end
This is the partial, (_grid_item.html.erb)
<div class ="left_inner_element">
<div class="l_upper_element">
<div class="coaches_mitted"><%= data[:mitted_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>
This is the script used in the main page
<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>
After this rendering is done, I would like to invoke a javscript. How to do that? I am using a form_remote_tag from the view.
The render partial is done in Ajax context, no page reloads will happen. The form_remote_tag has a :success method where I can call a javascript. Unfortunately, the javascript that I put in the success method is getting called 'before' the rendering is done. But, I need to invoke a javascript 'after' the rendering is plete.
I have simply put an alert message for clarity in Question. Actually I am calling a facebox() method on the DIV element that I am rendering. The facebox() (jQuery's) method should be applied to the DIV element after it is rendered only then it will be effective.
Edit: I have added the plete code. If you can see, I am calling the javascript method handle_success once the Ajax returns. (I apologize for putting the :success method inside the partial). The handle_success is called before the actual rendering pletes. That should be 'after' it pletes
This is the facebox popup content
<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>
This is the controller method
def custom
master_scheduler
h = params[:h].to_i
d = params[:d].to_i
render(:partial => "grid_item" , :locals => {:day=>d, :hour=>h})
end
This is the partial, (_grid_item.html.erb)
<div class ="left_inner_element">
<div class="l_upper_element">
<div class="coaches_mitted"><%= data[:mitted_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>
This is the script used in the main page
<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>
After this rendering is done, I would like to invoke a javscript. How to do that? I am using a form_remote_tag from the view.
The render partial is done in Ajax context, no page reloads will happen. The form_remote_tag has a :success method where I can call a javascript. Unfortunately, the javascript that I put in the success method is getting called 'before' the rendering is done. But, I need to invoke a javascript 'after' the rendering is plete.
I have simply put an alert message for clarity in Question. Actually I am calling a facebox() method on the DIV element that I am rendering. The facebox() (jQuery's) method should be applied to the DIV element after it is rendered only then it will be effective.
Edit: I have added the plete code. If you can see, I am calling the javascript method handle_success once the Ajax returns. (I apologize for putting the :success method inside the partial). The handle_success is called before the actual rendering pletes. That should be 'after' it pletes
Share Improve this question edited Jun 21, 2010 at 6:04 bragboy asked Jun 20, 2010 at 9:29 bragboybragboy 35.6k30 gold badges116 silver badges175 bronze badges 3- This is a repeat of your previous question: stackoverflow./questions/3069571/…. I would suggest to put in more code. Show us the partial, the js and the remote submit tag. – nathanvda Commented Jun 20, 2010 at 18:32
- @nathanvda: Well, this question is straight forward. I dont want to confuse anyone here, thats y asked a new one. – bragboy Commented Jun 20, 2010 at 18:33
- From your ments i think you are doing it right, but something else is wrong. To be able to help you with that, we need to see more code. – nathanvda Commented Jun 20, 2010 at 19:40
3 Answers
Reset to default 3Here you go:
<!-- 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 e here. You know what changes you want to make. :)
Maybe you wanted to add this? How did you get data[:mited_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_mited_coaches and @data_available_coaches and storing the above in that.
<div class ="left_inner_element">
<div class="l_upper_element">
<div class="coaches_mitted"><%= data[:mitted_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>
I am skeptical about you having added the &hour
and &date
. I would suggest you remove it if you detect firebug throwing an exception as it might not be valid xml. If you do encounter a XML Parsing error in firebug (see the XML tab when you do a AJAX Post in the firebug console) just edit your question with the error. I'll look into it. Also can you explain to me this bit of code:
:update => 'grid['+params[:day]+']['+params[:hour]+']'
? Which element on the page are you updating?
Also as you can see, the custom.xml.erb contains a <taconite>
tag. It has a <append>
tag with an id of div_changed_content
. You will have to create a div tag with that id in your .html.erb
file for it to work.
The rendering is done on the server side and once the whole page is posed the resulting HTML is returned to the client. So you cannot execute client scripts in this case. To invoke some javascript once the page is loaded you could use the onload
event handler:
<script type="text/javascript">
window.onload = function() {
// put your code here
};
</script>
or if you use jQuery:
<script type="text/javascript">
$(function() {
// put your code here
});
</script>
or if you use Prototype:
<script type="text/javascript">
document.observe("dom:loaded", function() {
// put your code here
});
</script>
You got it a bit wrong there:
"The submit tag has a :success method where I can call a javascript. Unfortunately, the javascript that I put in the success method is getting called 'before' the rendering is done."
The :success
method is for when the submit happens successfully. Not for any event that takes place after the submit! You need a success method to be executed after the partial has been rendered and not when the submit button is clicked! If you are familiar with jquery i would suggest you go the unobtrusive way. I never relied on built-in helpers coz of its lack of flexibility and also i hate to use inline javascript.. you won't be able to cache it. I would have all my javascript in one minified js file which can be cached once than the code spread everywhere. Anyways i am just digressing from the main point.
Secondly, you should not render a partial for an ajax call. That will always refresh your page. Instead you should create a .js.erb
or a .xml.erb
file for that particular controller action.
Since you have not given what exactly you are rendering in your partial i will instead provide you with a general answer. Please share with us your partial code so that we know what exactly you want. Also provide the selector id/class
of the HTML tag that you want to modify on success(after rendering that is..).
If you want a better way of going about it i will give you the config that i use for ajax:
In your 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);
});
});
In IE and SAFARI the accept headers default to text/html instead of text/xml or text/javascript. To correct that, add this to your application.controller.rb; Takes care of all your cross browser issues:
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
In your layout your_layout.html.erb
add this to the header:
<% 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 %>
I suggest you get the JQuery taconite plugin! Its just too good if you want to deal with ajax in your app! It can perform multiple DOM modifications at once.
JQuery taconite by Malsup
Will explain how to use this in a bit.
Now add this to your application.js file:
$("form").live('submit', function() {
$.post(this.action, $(this).serialize(), "_method=post");
return false;
})
Now in your action where you used to render your partial render(:partial => "grid_item")
, change the action to this
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
Now in your views/your_controller/
create a your_action_here.xml.erb
file. In this file you can add the javascript code that is executed after the rendering takes place. This action will respond in two ways. If the user has javascript disabled in his browser it will respond with html data if not it will default to xml data. Now this is where taconite es into picture. The beauty of taconite is that it converts all your jquery based DOM modifiers to XML pliant markup.
Instead of doing $("#div").append('<div>YO!</div>')
you can do:
<append select="#div">
<div>YO!</div>
</append>
Also you can do multiple DOM modifications! Forget chaining a 100 different modifiers and cluttering your view code. It feels more natural to use with rails helpers as its simple markup. One of the main reasons I stopped using .js.erb
files.
Say in your views you have a div tag <div>
, with an id of "div"
In your_action_here.xml.erb,
<taconite>
<append select="#div">
<%=h @instance_variable_to_store_stuff %>
</append>
</taconite>
If you want to do multiple DOM updates you can do this for example:
<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>
You can also run javascript inside your your_action_here.xml.erb with a eval tag as follows:
<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>
One thing that you ought to keep in mind is that all xml tags should be closed and none should be left open. Strictly xhtml pliant.
I forgot to mention: Taconite also provides you with debug logging in firebug. A sweet feature if you want to track changes made from the ajax request during development.
本文标签: jqueryHow to call a javascript post render in RailsStack Overflow
版权声明:本文标题:jquery - How to call a javascript post render in Rails? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744891628a2630816.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论