In this blog we will implement infinite scrolling with kaminari gem. Infinite scrolling appends more content to the end of the page before the viewer gets to it, so they can just keep scrolling unabated and the application doesn't need to initially load a bunch of records only a small percent of viewers will ever scroll down to.
Add 'kaminari' to your Gemfile -
gem 'kaminari'
Run the jQuery generator to download the necessary files and setup your Rails app to use jQuery.
$ rails generate jquery:install
In Controller -
def index
@projects = Project.order(:created_at).page(params[:page])
end
In index.html.erb
<h1>Listing projects</h1>
<table id="projects">
<thead>
<tr>
<th>Title</th>
</tr>
</thead>
<tbody class="project-snippet">
<%= render @projects %>
</tbody>
</table>
<br>
<%= paginate @projects %>
<script>
paginator = new ScrollPaginator({
item: $('.project-snippet'),
items_source_url: '<%= projects_path %>',
total_pages: <%= @projects.count/(Project::PAGINATION_SIZE) %>
}).enable();
</script>
In assets/javascripts/scrollpaginator.js -
ScrollPaginator.VISIBILITIES = ['TOP', 'COMPLETE'];
function ScrollPaginator(options) {
this.options = {
object_visibility: 'TOP',
total_pages: 0
};
$.extend(this.options, options);
this.sample_element = $('<div id="sample_object" class="sample_object"></div>');
$(this.sample_element)
.height(this.options.item.height()).width(this.options.item.width())
.attr('class', $(this.sample_element).attr('class') + this.options.item.attr('class'));
this.last_loaded_page = 1;
this.request_next = true;
}
ScrollPaginator.prototype = {
provision: function () {
this.sample_element.attr('class', this.options.item.attr('class'));
this.options.item.parent().append(this.sample_element)
},
validVisibility: function () {
$.inArray(this.options.object_visibility, ScrollPaginator.VISIBILITIES)
},
increment_page: function () {
this.last_loaded_page += 1;
if (this.last_loaded_page >= this.options.total_pages) {
this.last_loaded_page = this.options.total_pages;
}
},
decrement_page: function () {
this.last_loaded_page -= 1;
if (this.last_loaded_page <= 1) {
this.last_loaded_page = 1;
}
},
activateOnScrollPagination: function () {
var _this = this;
$(window).scroll(function () {
_this.loadItems();
});
},
isSampleVisible: function () {
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $(this.sample_element).offset().top;
var elemBottom = elemTop + $(this.sample_element).height();
switch (this.options.object_visibility) {
case 'TOP':
return ((elemTop <= docViewBottom) && (elemTop >= docViewTop));
break;
case 'COMPLETE':
return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
break;
default:
console.log('Visibility option is not valid.');
return false;
}
},
loadItems: function () {
var _this = this;
if (this.isSampleVisible()) {
if (this.request_next) {
if (this.last_loaded_page < this.options.total_pages) {
this.increment_page();
/*--- For preventing multiple requests ---*/
this.request_next = false;
$.ajax({
method: 'GET',
dataType: 'script',
url: this.options.items_source_url + '?page=' + _this.last_loaded_page
}).success(function () {
_this.request_next = true;
_this.loadItems();
}).fail(function () {
_this.decrement_page();
});
} else {
this.request_next = false;
}
}
}
},
enable: function () {
this.provision();
this.activateOnScrollPagination();
this.loadItems();
}
};
Add 'kaminari' to your Gemfile -
gem 'kaminari'
Run the jQuery generator to download the necessary files and setup your Rails app to use jQuery.
$ rails generate jquery:install
In Controller -
def index
@projects = Project.order(:created_at).page(params[:page])
end
In index.html.erb
<h1>Listing projects</h1>
<table id="projects">
<thead>
<tr>
<th>Title</th>
</tr>
</thead>
<tbody class="project-snippet">
<%= render @projects %>
</tbody>
</table>
<br>
<%= paginate @projects %>
<script>
paginator = new ScrollPaginator({
item: $('.project-snippet'),
items_source_url: '<%= projects_path %>',
total_pages: <%= @projects.count/(Project::PAGINATION_SIZE) %>
}).enable();
</script>
In assets/javascripts/scrollpaginator.js -
ScrollPaginator.VISIBILITIES = ['TOP', 'COMPLETE'];
function ScrollPaginator(options) {
this.options = {
object_visibility: 'TOP',
total_pages: 0
};
$.extend(this.options, options);
this.sample_element = $('<div id="sample_object" class="sample_object"></div>');
$(this.sample_element)
.height(this.options.item.height()).width(this.options.item.width())
.attr('class', $(this.sample_element).attr('class') + this.options.item.attr('class'));
this.last_loaded_page = 1;
this.request_next = true;
}
ScrollPaginator.prototype = {
provision: function () {
this.sample_element.attr('class', this.options.item.attr('class'));
this.options.item.parent().append(this.sample_element)
},
validVisibility: function () {
$.inArray(this.options.object_visibility, ScrollPaginator.VISIBILITIES)
},
increment_page: function () {
this.last_loaded_page += 1;
if (this.last_loaded_page >= this.options.total_pages) {
this.last_loaded_page = this.options.total_pages;
}
},
decrement_page: function () {
this.last_loaded_page -= 1;
if (this.last_loaded_page <= 1) {
this.last_loaded_page = 1;
}
},
activateOnScrollPagination: function () {
var _this = this;
$(window).scroll(function () {
_this.loadItems();
});
},
isSampleVisible: function () {
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $(this.sample_element).offset().top;
var elemBottom = elemTop + $(this.sample_element).height();
switch (this.options.object_visibility) {
case 'TOP':
return ((elemTop <= docViewBottom) && (elemTop >= docViewTop));
break;
case 'COMPLETE':
return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
break;
default:
console.log('Visibility option is not valid.');
return false;
}
},
loadItems: function () {
var _this = this;
if (this.isSampleVisible()) {
if (this.request_next) {
if (this.last_loaded_page < this.options.total_pages) {
this.increment_page();
/*--- For preventing multiple requests ---*/
this.request_next = false;
$.ajax({
method: 'GET',
dataType: 'script',
url: this.options.items_source_url + '?page=' + _this.last_loaded_page
}).success(function () {
_this.request_next = true;
_this.loadItems();
}).fail(function () {
_this.decrement_page();
});
} else {
this.request_next = false;
}
}
}
},
enable: function () {
this.provision();
this.activateOnScrollPagination();
this.loadItems();
}
};
wonderful post . keep updating the post Ruby on Rails Online Training India
ReplyDelete