Rails 3.0 how to create endless page? - ruby-on-rails

I am trying to create a endless page.
After this tutorial: http://railscasts.com/episodes/114-endless-page?view=comments
In my controller I have:
def index
#konkurrencer = Konkurrencer.find(:all).paginate(:page => params[:page], :per_page => 2)
respond_to do |format|
format.html
format.js { render :rjs => #konkurrencer }
end
end
In my view I have:
<% #konkurrencer.each do |kon| %>
<%= render :partial => 'konkurrencers/konkurrencer', :locals => { :kon => kon } %>
<% end %>
My index.js.rjs:
page.insert_html :bottom, :konkurrencer, :partial => 'konkurrencers/konkurrencer'
if #konkurrencer.total_pages > #konkurrencer.current_page
page.call 'checkScroll'
else
page[:loading].hide
end
In my header I this javascript:
<%= javascript_include_tag 'jquery', 'endless' %>
And the endless.js:
var currentPage = 1;
function checkScroll() {
if (nearBottomOfPage()) {
currentPage++;
new Ajax.Request('/konkurrencer.js?page=' + currentPage, {asynchronous:true, evalScripts:true, method:'get'});
} else {
setTimeout("checkScroll()", 250);
}
}
function nearBottomOfPage() {
return scrollDistanceFromBottom() < 150;
}
function scrollDistanceFromBottom(argument) {
return pageHeight() - (window.pageYOffset + self.innerHeight);
}
function pageHeight() {
return Math.max(document.body.scrollHeight, document.body.offsetHeight);
}
document.observe('dom:loaded', checkScroll);
There is no ajax call made or anything. Should move the index.js.rjs to index.js.erb? or is it because I donĀ“t include default javascript?

No, I think the problem your block for responding to js. If you want it to render index.js.rjs, then you just should be able to say:
def index
#konkurrencer = Konkurrencer.find(:all).paginate(:page => params[:page], :per_page => 2)
respond_to do |format|
format.html
format.js
end
end
That should look for a file called index.js.SOMEFORMAT. I dont' believe your :rjs => #koncurrencer is actually working, I bet if you looked at your browser traffic, you'd just see the server return a 500 because of the error.

Related

Multiple render in rails controller

Hello I am trying to retrieve html partials as a single string in an ajax call. I am using public_activity gem. Since I didnt find a way to call the partial(render_activity) from the controller. I tried using the following code, but I am getting an error saying that I can not make more than one render call. Any ideas of how can I achieve what I want?
#new_feeds.each_with_index do |new_feed|
if new_feed.trackable_type == "CompanyDocument"
if new_feed.key == "company_document.create"
html = render partial: 'public_activity/company_document/create', :locals => { :activity => new_feed }
elsif new_feed.key == "company_document.update"
html = render partial: 'public_activity/company_document/update', :locals => { :activity => new_feed }
end
elsif new_feed.trackable_type == "CompanyVideo"
if new_feed.key == "company_video.create"
html = render partial: 'public_activity/company_video/create', :locals => { :activity => new_feed }
elsif new_feed.key == "company_video.update"
html = render partial: 'public_activity/company_video/update', :locals => { :activity => new_feed }
end
end
end
Replace all occurrances of render with render_to_string

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
}
});
});

How to make errored inputs prepopulate with previously inputted data

I'm making a custom AJAX form.
If a user fills out half of the form, it will fail wanting the other half fulfilled.
For some odd reason, the form is not pre-populating with at least what they had already inputted.
Because it's not doing this, how can I manually tell it to do so? When the form returns, the Object it verified is still accessible, so I can withdraw information from it.
a sample of the form
- form_for CardSignup.new do |f|
- unless #card_signup.nil?
- if !#card_signup.errors.empty?
.prefix_1.grid_4
- #card_signup.errors.full_messages.each do |error|
.warning
= error
%br/
.grid_2.prefix_1{:style => "width: 166px;"}
= f.text_field :first_name, :style => "width: 166px;", :value => "first name", :rel => "first name"
%div{:class => 'error_message'}
my Create method
def create
if params[:user] && current_user.admin
#card_signup = User.find(params[:user]).build_card_signup(params[:card_signup])
else
#card_signup = current_user.build_card_signup(params[:card_signup])
end
if #card_signup.valid?
respond_to do |wants|
#wants.html { redirect_to disclaimer_card_signup_path, :locals => { :card_signup => #card_signup } }
wants.json { render :json => { :html => (render_to_string :partial => 'disclaimer') } }
end
else
respond_to do |wants|
#wants.html { redirect_to new_card_signup_path }
wants.json { render :json => {:errors => #card_signup.errors, :html => (render_to_string :partial => '/card_signups/new_form') } }
end
end
end
You're doing this:
form_for CardSignup.new
which will instantiate a new CardSignup object every time you render the form. Move this into the new action and in the create action do this:
#card_signup = CardSignup.new(params[:card_signup])
This will pass the half-filled object back to the form and you'll get the already populated fields.

will_paginate ajax with fade

I'm trying to ajaxify my will_pagniate pagination in rails. I want to have the old page fade out and the new one fade in.
Here's the relevant part of my controller:
respond_to do |format|
format.html # new.html.erb
format.js {
render :update do |page|
page.replace 'page', :partial => 'cur_page'
end
}
format.xml { render :xml => #branch }
end
The aforementioned partial:
<div id="page">
<%= will_paginate %>
<div id="posts">
<%= render #posts %>
</div>
<%= will_paginate %>
</div>
And the relevant part of application.js:
document.observe("dom:loaded", function() {
// the element in which we will observe all clicks and capture
// ones originating from pagination links
var container = $(document.body)
if (container) {
var img = new Image
img.src = '/images/spinner.gif'
function createSpinner() {
return new Element('img', { src: img.src, 'class': 'spinner' })
}
container.observe('click', function(e) {
var el = e.element()
if (el.match('.pagination a')) {
el.up('.pagination').insert(createSpinner())
target = $('posts')
new Effect.fade(target, { duration: 0.3, afterFinish: function()
{
new Ajax.Request(el.href,
{
method: 'get',
onSuccess: function(){ new Effect.Appear(target, {duration:0.3})}
})
}})
e.stop()
}
})
}
})
The script seems to get killed on this line,
new Effect.fade(target, { duration: 0.3, afterFinish: function()
because I see the spinner.gif start, then no fading and the page is refreshed normally. I have got the ajax working before I tried to add Effect.Fade and Effect.Appear.
Is this the right way to go about this? Should I put the effects in the controller instead?
Here is what I did using jQuery and working well too :)
Put your will_paginate helper view call in a div
#tickets_pagination
= will_paginate #tickets
In application.js
$("#tickets_pagination .pagination a").live("click", function() {
$.get("/users/?"+this.href.split("?")[1], null, null, "script");
return false
});
The javascript above will convert the pagination links in #tickets_pagination to ajax links
In your controller as usual
def index
#tickets = Ticket.all.paginate({:page => params[:page], :per_page => 10 })
respond_to do |format|
format.js
format.html
end
end
Now finally in index.js.erb
$("#tickets_list_table").fadeOut('slow');
$("#tickets_list_table").html("<%= escape_javascript(render :partial =>'tickets/tickets_table', :locals => {:tickets => #tickets}) %>");
$("#tickets_list_table").fadeIn('slow');
Here tickets/ticket_table has a table that lists all tickets. The partial is rendered in a div #ticket_list_table
Hope this will work for you as well.
I tried putting more of the work into the javascript helpers:
respond_to do |format|
format.html # new.html.erb
format.js {
render :update do |page|
page.visual_effect :fade, 'posts', :afterFinsh => "function(){" +
page.replace 'page', :partial => 'cur_page' +
page.visual_effect(:appear, 'branches') + "}"
end
}
format.xml { render :xml => #branch }
end
Then removed this part of the javascript:
new Effect.fade(target, { duration: 0.3, afterFinish: function()
I get the effect I want, but all out of order. The request completes and the html is replaced, then the div fades out and then reappears!
Not very familiar with RoR, does it generate its own client-side JS that may possibly be battling your code?
If not, I would say the problem is somewhere in your own client-side code. For testing, get rid of the HREF attribute from the anchor tag and place the URL as a string literal in the Ajax request. If nothing happens, there is a problem with the Ajax request itself. If the page loads as expected, then the event in the original scenario is not being completely stopped.
Also, clean up your JS a bit just to be sure, line-ending semi-colons where needed.
You seem to mix up things a bit.
Either you write $('posts').fade or new Effect.fade('posts').
Secondly, i can't seem to find the afterFinish option in the documentation.
So i would suggest something along the following lines:
container.observe('click', function(e) {
var el = e.element()
if (el.match('.pagination a')) {
el.up('.pagination').insert(createSpinner())
target = $('posts')
new Effect.fade('posts', { duration: 0.3});
setTimeout("new Ajax.Request(el.href, { method: 'get',
onSuccess: function(){
new Effect.Appear('posts', {duration:0.3})
} })", 1000);
e.stop();
}
})
Hope this helps.

Rails keep if false, render if true

I have a div tag that I want to change only if a function returns true, otherwise I want it to keep the same content. I used render: nothing => true but that removes everything.
<%= javascript_include_tag :defaults %>
<div id="x">Hi</div>
<% form_remote_tag :url => {:action => 'get'},
:update => 'x' do %>
<%= text_field_tag 'url' %>
<%= submit_tag "Submit" %>
<% end %>
def getImage
#img = params[:url]
if !verify #img
render :nothing => true
end
end
private
def verify url
return true if url =~ /https?:\/\/.*\.(jpg|png|gif|bmp)$/
return false
end
I want to make my rails code do this
var lastrequest = "";
function ajaxObj() { //Returns the ajax object based on browser
if ( window.XMLHttpRequest ) {
return new XMLHttpRequest(); //Firefox
} else if ( window.ActiveXObject ) {
return new ActiveXObject("Microsoft.XMLHTTP"); //IE
}
}
window.onload = function() {
document.getElementById("Submit").onclick = function() {
var request = ajaxObj();
request.onreadystatechange = function() {
if ( request.readyState == 4 ) {
document.getElementById("imgdisplay").innerHTML = request.responseText;
document.getElementById("imgurl").value = "";
}
}
if ( lastrequest != document.getElementById("imgurl").value ) { // Makes sure it doesn't request the same image twice
var parameters = "url=" + document.getElementById("imgurl").value;
request.open("POST", "imageget.php", true); // Sends the ajax request
request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
request.setRequestHeader("Content-length", parameters.length);
request.setRequestHeader("Connection", "close");
request.send(parameters);
lastrequest = document.getElementById("imgurl").value;
}
}
}
use status codes or a failure to control what happens.
http://api.rubyonrails.org/classes/ActionView/Helpers/PrototypeHelper.html#M001645
You can also remove the :update => 'x' part an use following code in your controller:
def getImage
#img = params[:url]
if !verify #img
render :nothing => true
else
render :update do |page|
page['x'].replace_html :partial => <some partial here>
end
end
end
Or, a bit briefer:
def getImage
#img = params[:url]
render :update do |page|
page['x'].replace_html(:partial => <some partial here>) if verify(#img)
end
end
Greets

Resources