Is it possible to refresh partial frequently using Ajax? - ruby-on-rails

In background, I want it to reload and shows the number how many unread messages are there.
I want that without refreshing page. I mean using ajax.
If I had this in menu, how can I refresh only this section every 30 secs?
<li><%= link_to sanitize('<i class="icon-envelope"></i> ') + "received messages" + sanitize(' <span class="badge badge-info">'+current_user.mailbox.inbox(:read => false).count(:id, :distinct => true).to_s+'</span>'), messages_received_path %></li>
messages_controller.rb
def received
if params[:search]
#messages = current_user.mailbox.inbox.search_messages(#search).page(params[:page]).per(10)
else
#messages = current_user.mailbox.inbox.page(params[:page]).per(10)
end
add_crumb 'Messages Received', messages_received_path
#box = 'inbox'
render :index
end
UPDATE:_______________________________
assets/javascript/refresh_messages_count.js
$(document).ready(function () {
// will call refreshPartial every 3 seconds
setInterval(refreshPartial, 3000)
});
function refreshPartial() {
$.ajax({
url: "messages/refresh_part";
})
}
messages_controller.rb
def refresh_part
#message_count = current_user.mailbox.inbox(:read => false).count(:id, :distinct => true)
# get whatever data you need to a variable named #data
respond_to do |format|
format.js {render :action=>"refresh_part.js"}
end
end
views/layouts/_menu.html.erb
<span id="message_received_count"><%= render :partial => "layouts/message_received_count" %></span>
views/layouts/_message_received_count.html.erb
<% if user_signed_in? && current_user.mailbox.inbox(:read => false).count(:id, :distinct => true) > 0 %>
<li><%= link_to sanitize('<i class="icon-envelope"></i> ') + "Received" + sanitize(' <span class="badge badge-info">'+#message_count.to_s+'</span>'), messages_received_path %></li>
<% else %>
<li><%= link_to sanitize('<i class="icon-envelope"></i> ') + "Received", messages_received_path %></li>
<% end %>
views/messages/refresh_part.js.erb
$('#message_received_count').html("#{escape_javascript(render 'layouts/messages_received_count', data: #message_count)}");

You will use setInterval to send the ajax request:
$(document).ready(function () {
// will call refreshPartial every 3 seconds
setInterval(refreshPartial, 3000)
});
// calls action refreshing the partial
function refreshPartial() {
$.ajax({
url: "whatever_controller/refresh_part"
})
}
Then you make an action in a controller like this:
def refresh_part
# get whatever data you need to a variable named #data
respond_to do |format|
format.js
end
end
then you will write a js file named refresh_part.js.haml (you could erb instead of haml).
refresh_part.js.haml would look like this:
$('#part_you_want_to_refresh').html("#{escape_javascript(render 'name_of_partial', data: #data)}");
make sure you set the correct routes in routes.rb.

FYI, refresh_part.js.erb would look like this:
$("#part").html("<%= escape_javascript(render 'partial', data: #data) %>");
instead of:
$('#part').html("#{escape_javascript(render 'partial', data: #data)}");
also, we can use the alias of "escape_javascript" to simplify this:
$("#part").html("<%= j(render 'partial', data: #data) %>");

Yes you can
<html>
<head>
<script type="text/JavaScript">
<!--
function timedRefresh(timeoutPeriod) {
setTimeout("location.reload(true);",timeoutPeriod);
}
// -->
</script>
</head>
<body onload="JavaScript:timedRefresh(5000);">
<p>This page will refresh every 5 seconds. This is because we're using the 'onload' event to call our function. We are passing in the value '5000', which equals 5 seconds.</p>
<p>But hey, try not to annoy your users too much with unnecessary page refreshes every few seconds!</p>
</body>
</html>
Source: http://www.quackit.com/javascript/javascript_refresh_page.cfm

Related

Ajax Call for load more button in Rails

I want to do load data with load more button. I have implemented like this in posts/index.html.erb:
<div id="posts">
<h1>Posts</h1>
<%= render #posts %>
</div>
<div class="load-more-container">
<%= link_to "Load More", posts_index_path, class: "load-more" %>
</div>
Then _post.html.erb:
<div class="post">
<h2><%= post.title %></h2>
<p><%= post.body %></p>
</div>
Then index.js.erb:
$('#posts').append('<%= escape_javascript render(#posts) %>');
In posts_controller I wrote like this:
##count=2
def index
if params[:id]
#posts = Post.where('id < ?', params[:id])
else
#posts = Post.limit(##count)
end
##count+=2
respond_to do |format|
format.html
format.js
end
end
Then in application.js:
$(document).ready(function () {
$('a.load-more').click(function (e) {
e.preventDefault();
$.ajax({
type: "GET",
url: $(this).attr('href'),
dataType: "script",
success: function () {
$('.load-more').show();
}
});
});
});
I am getting first 2 data:
Post1
Post2
load more
when clicking on load more I am getting like this:
Post1
Post2
Post1
Post2
Post3
Post4
but I want only:
Post1
Post2
Post3
Post4
Could anyone please help me. Thanks in advance.
Since you are fetching all records everytime click on loadmore button, Dont append result and overwrite with html
$('#posts').html('<%= escape_javascript render(#posts) %>');
In your controller, you replace
#posts = Post.limit(##count) => #posts = Post.limit(2).offset(##count - 2)
if you want load more 2 artices.

Pass variable to a Fancybox in Rails with Content

I have this link in Rails:
<%= link_to "Add to Journal", add_post_journal_path(post), :method => :put %>
However I want transform this link to show a fancybox with the content listing my content to choose. First, I use this code:
<%= link_to "fancy", "#add_post", :class=>"fancybox" %>
but I have errors, because I want pass the actual post to fancybox, so I'm using this code: in add_post.html.erb:
<h1>Escolha o Jornal que deseja adicionar:</h1>
<ul>
<% current_user.journals.each do |journal| %>
<li><%= link_to journal.name,add_post_complete_journal_path(journal),:remote=>true %> </li>
<% end %>
</ul>
and my controller is:
def add_post
#journal_post = JournalsPosts.new
session[:post_add] = params[:id]
end
def add_post_complete
#journal_post = JournalsPosts.create(:post_id => session[:post_add],:journal_id => params[:id])
respond_with #journal_post
end
How can I transform this code to use my content in my fancybox?
Add on your action add_post the next respond with js:
def add_post
#journal_post = JournalsPosts.new
session[:post_add] = params[:id]
respond_to do |format|
format.js
end
end
Add on a file on your views add_post.js.erb with the next content:
$.fancybox('<%= escape_javascript(render(:partial => 'path_to/add_post'))%>',
{
openEffect: "fade",
closeEffect: "fade",
autoSize: true,
minWidth: 480,
scrolling: 'auto',
});
For example, you have add a partial _add_post.html.erb on your views. Now inside this partial you can write your code view:
#code for your view inside partial `add_post.html.erb`
<%= #journal_post %>
<h1>Escolha o Jornal que deseja adicionar:</h1>
<ul>
.
.
Regards!

Ajax won't be reloaded properly every 3 seconds. Why?

I'm trying to make it reload the partial that shows the number of messages unread every 3seconds.
But the codes I wrote won't show the numbers at all even if there's 1 unread message...
How can I reload partial that shows correct number of messages unread??
My codes are
assets/javascript/refresh_messages_count.js
$(document).ready(function () {
// will call refreshPartial every 3 seconds
setInterval(refreshPartial, 3000)
});
function refreshParital() {
$.ajax({
url: "messages/refresh_part";
})
}
messages_controller.rb
def refresh_part
#message_count = current_user.mailbox.inbox(:read => false).count(:id, :distinct => true)
# get whatever data you need to a variable named #data
respond_to do |format|
format.js {render :action=>"refresh_part.js"}
end
end
views/layouts/_menu.html.erb
<span id="message_received_count">
<%= render :partial => "layouts/message_received_count" %>
</span>
views/layouts/_message_received_count.html.erb
<% if user_signed_in? && current_user.mailbox.inbox(:read => false).count(:id, :distinct => true) > 0 %>
<li><%= link_to sanitize('<i class="icon-envelope"></i> ') + "Received" + sanitize(' <span class="badge badge-info">'+#message_count.to_s+'</span>'), messages_received_path %>
</li>
<% else %>
<li><%= link_to sanitize('<i class="icon-envelope"></i> ') + "Received", messages_received_path %>
</li>
views/messages/refresh_part.js.erb
$('#message_received_count').html("#{escape_javascript(render 'layouts/messages_received_count', data: #message_count)}");
Change your function refreshPartial to the following:
function refreshPartial() {
$.ajax({
url: "/messages/refresh_part",
type: "GET",
dataType: "script",
success: function(data) {
console.log("Called refresh_part");
},
error: function (xhr, ajaxOptions, thrownError) {
alert("Error: " + xhr.status + " " + thrownError);
}
});
}
(the / in front of messages is important, the other fields are useful as well - you can remove the success option once you get it working).
And change your method in your controller to:
def refresh_part
#message_count = current_user.mailbox.inbox(:read => false).count(:id, :distinct => true)
# get whatever data you need to a variable named #data
respond_to do |format|
format.js
end
end
(removing the render part - rails knows how to do this automatically).
Edit
After discussion - the last problem to be resolved was related to JQuery conflict - JQuery was being included in multiple places and stopping the $(document).ready from firing. Fixed.

Implementing a endless scroll with Rails 3 and Jquery

I'm trying to implementing an endless scroll on my project. I'm using a mix of the Railscast #114 Endless Page and this.
Everything works fine besides a weird behavior when I try to stop sending requests when the page hits its end.
So far I have:
Controller:
def show
#title = Photoset.find(params[:id]).name
#photos = Photoset.find(params[:id]).photo.paginate(:page => params[:page], :per_page => 20)
respond_to do |format|
format.js
format.html
end
end
Show.html.erb:
<% content_for :body_class, '' %>
<%= render 'shared/header' %>
<div id="photos_container">
<div id="photos_header">
<h2><%= #title %></h2>
</div>
<%= render :partial => 'photo', :collection => #photos %>
</div>
<%= render :partial => 'endless_scroll' %>
Javascript (loaded via partial):
<script type="text/javascript">
(function() {
var page = 1,
loading = false,
finish = false;
function nearBottomOfPage() {
return $(window).scrollTop() > $(document).height() - $(window).height() - 200;
}
function finish() {
finish = true;
}
$(window).scroll(function(){
if (loading) {
return;
}
if(nearBottomOfPage() && !finish) {
loading=true;
page++;
$.ajax({
url: '/photosets/<%= params[:id] %>?page=' + page,
type: 'get',
dataType: 'script',
success: function() {
loading=false;
}
});
}
});
}());
</script>
show.js.erb
$("#photos_container").append("<%= escape_javascript(render :partial => 'photo', :collection => #photos) %>");
<% if #photos.total_pages == params[:page].to_i() %>
page.call 'finish'
<% end %>
As you can see, on my show.js.erb I have a page.call that assigns true to the finish variable. This stops the requests.
The wired thing is that it never loads the last page. When #photos.total_pages == params[:page].to_i() instead of just calling the finish function and setting the variable to true, it's also preventing the $("#photos_container").append("<%= escape_javascript(render :partial => 'photo', :collection => #photos) %>"); from running.
It sends the request to the controller, runs the SQL but doesn't append the last page.
If I change the condition to #photos.total_pages < params[:page].to_i() it works, but send an extra request to a page that doesn't exist.
I'd appreciate any help on my implementation. I'm not sure if there's a more adequate (Rails) way to accomplish this.
First of all you can render html from the partial when request is xhr type:
def show
photoset = Photoset.includes(:photos).find(params[:id])
#title = photoset.name
#photos = photoset.photo.paginate(:page => params[:page], :per_page => 20)
if request.xhr?
render '_photo', :layout => false
end
end
Then use ajax call:
$.ajax({
url: '/photosets/<%= params[:id] %>?page=' + page,
type: 'get',
dataType: 'script',
success: function(response) {
$("#photos_container").append(response);
if (response == "") {
//stop calling endless scroll
}
});
});

Rails checkbox AJAX call, don't want to render anything

I've got a little demo setup in which clicking a checkbox toggles an attribute via AJAX. It's working fine, but Rails REALLY wants to render something, so I've basically resorted to creating a blank toggle.js.erb file in my views.
Controller action in question:
def toggle
#task = Task.find(params[:id])
respond_to do |format|
format.js do
if (#task.status != true)
#task.status = true
else
#task.status = false
end
#task.save
render :layout => false
end
end
end
View in question:
<h1>Tasks</h1>
<ul style="list-style-type: none;">
<% #tasks.each do |task| %>
<li id="<%= dom_id(task) %>">
<%= check_box_tag(dom_id(task), value = nil, checked = task.status) %>
<%= task.action %> <%= link_to 'Edit', edit_task_path(task) %>
<%= link_to 'Delete', task, :confirm => 'Are you sure?', :method => :delete, :remote => true %>
</li>
<% end %>
</ul>
<%= link_to 'New Task', new_task_path %>
<script>
$$('input').each(function(el) {
el.observe('click', function(event) {
// Get the task ID
var elId = el.id.split("_")[1];
// Build the toggle action path
var togglePath = '/tasks/' + elId + '/toggle/';
// Create request, disable checkbox, send request,
// enable checkbox on completion
new Ajax.Request(togglePath, {
onCreate: function() {
el.disable();
},
onSuccess: function(response) {
},
onComplete: function() {
el.enable();
}
});
});
});
</script>
Without the blank toggle.js.erb file I've got in the views, Rails still gives me an error saying that it's trying to render something.
Ultimately, I'd like to both not have to have a blank toggle.js.erb file, and I'd like to get that Prototype stuff into my static JavaScript stuff and out of the view.
I'm pretty new to Rails, so there's probably an easier way to be doing this, but I'm kind of stuck here.
render :layout => false means that you want to render 'toggle' view without layout.
If you don't want render anything at all, you should use :nothing => true option
def toggle
#task = Task.find(params[:id])
#task.toggle! :status
# if it used only by AJAX call, you don't rly need for 'respond_to'
render :nothing => true
end
EDIT: In Rails4/5 you can use head :ok instead of render nothing: true, it's more preferable way to do this, but result is the same.

Resources