I've implemented a Star Rating System using this tutorial http://eighty-b.tumblr.com/post/1569674815/creating-an-ajaxified-star-rating-system-in-rails-3
Everything works in the SHOW PAGE, But in the INDEX PAGE, the JavaScript does not work. When the page is loaded, Every Book in the index page has the same rating as the first Book and it doesn't load the correct Star Rating to each book on the page.
(Am I missing something in the beginning of my JavaScript code, like an ID?)
New to rails please help :)
JAVASCRIPT
rating_ballot.js
### Sets up the stars to match the data when the page is loaded.
### But applies the first Books Rating to all
$(function () {
var checkedId = $('form.rating_ballot > input:checked').attr('id');
$('form.rating_ballot > label[for=' + checkedId + ']').prevAll().andSelf().addClass('bright');
});
$(document).ready(function() {
### Makes stars glow on hover.
$('form.rating_ballot > label').hover(
function() { // mouseover
$(this).prevAll().andSelf().addClass('glow');
},function() { // mouseout
$(this).siblings().andSelf().removeClass('glow');
});
### Makes stars stay glowing after click.
$('form.rating_ballot > label').click(function() {
$(this).siblings().removeClass("bright");
$(this).prevAll().andSelf().addClass("bright");
});
### Submits the form & saves data.
$(document).on('change', '.rating_button', function(){
$(this).parent().submit();
});
});
CSS.SCSS
form.rating_ballot input.rating_button { display: none; }
form.rating_ballot label.rating { cursor: pointer; display: block; height: 20px; width: 20px; float: left; }
form.rating_ballot label.rating span { display: none; }
form.rating_ballot label.rating { background-image: image-url('star-dim.png'); }
form.rating_ballot label.rating.bright { background-image: image-url('star-bright.png'); }
form.rating_ballot label.rating.glow { background-image: image-url('star-glow.png'); }
VIEWS
show.html.erb (show)
<div id="book<%= @book.id %>">
<div id="rating">
<%= render :partial => 'ratings/rating', :locals =>{:book => @book} %>
</div>
</div>
index.hrml.erb (books)
<% @books.each do |book| %>
<table id="book<%= book.id %>">
<tbody>
<tr>
<td>
<%= book.title %>
</td>
</tr>
<tr>
<td id="rating">
<%= render :partial => 'ratings/rating', :locals =>{:book => book} %>
</td>
</tr>
<tbody>
</table>
<% end %>
_rating.html.erb
<%= form_for(rating_ballot(issue.id), :html => { :class => 'rating_ballot' }, remote: true ) do |f| %>
<%= f.label("value_1", content_tag(:span, '1'), {:class=>"rating", :id=>"1"}) %>
<%= radio_button_tag("rating[value]", 1, current_user_rating(issue.id) == 1, :class => 'rating_button') %>
<%= f.label("value_2", content_tag(:span, '2'), {:class=>"rating", :id=>"2"}) %>
<%= radio_button_tag("rating[value]", 2, current_user_rating(issue.id) == 2, :class => 'rating_button') %>
<%= f.label("value_3", content_tag(:span, '3'), {:class=>"rating", :id=>"3"}) %>
<%= radio_button_tag("rating[value]", 3, current_user_rating(issue.id) == 3, :class => 'rating_button') %>
<%= f.label("value_4", content_tag(:span, '4'), {:class=>"rating", :id=>"4"}) %>
<%= radio_button_tag("rating[value]", 4, current_user_rating(issue.id) == 4, :class => 'rating_button') %>
<%= f.label("value_5", content_tag(:span, '5'), {:class=>"rating", :id=>"5"}) %>
<%= radio_button_tag("rating[value]", 5, current_user_rating(issue.id) == 5, :class => 'rating_button') %>
<%= hidden_field_tag("issue_id", issue.id) %>
<%= f.submit :Submit, style: "display: none" %>
<% end %>
create.js.erb & update.js.erb
$('#issue<%= @issue.id%> #rating').html("<%= escape_javascript(render :partial => 'ratings/rating', :locals => {:issue => @issue}) %>");
CONTROLLER
class RatingsController < ApplicationController
before_filter :current_user, only: [:create, :update]
respond_to :html, :js
def create
@book = Book.find_by_id(params[:book_id])
@rating = Rating.create(params[:rating])
@rating.book_id = @book.id
@rating.user_id = current_user.id
if @rating.save
respond_to do |format|
format.js
format.html { redirect_to :back }
end
end
end
def update
@book = Book.find_by_id(params[:book_id])
@rating = current_user.ratings.find_by_book_id(@book_id)
if @rating.update_attributes(params[:rating])
respond_to do |format|
format.js
format.html { redirect_to :back }
end
end
end
end
HELPERS
module IssuesHelper
def rating_ballot(issue_id)
if @rating = current_user.ratings.find_by_issue_id(issue_id)
@rating
else
current_user.ratings.new
end
end
def current_user_rating(issue_id)
if @rating = current_user.ratings.find_by_issue_id(issue_id)
@rating.value
end
end
end
The problem seems to be here:
$(function () {
var checkedId = $('form.rating_ballot > input:checked').attr('id');
$('form.rating_ballot > label[for=' + checkedId + ']').prevAll().andSelf().addClass('bright');
});
It gets the id
of the first checked input, and for all forms sets the star rating to that one.
Try this code:
$(function () {
$('form.rating_ballot').each(function() {
var $form = $(this),
checkedInput = $form.find('input:checked');
checkedInput.prevAll().andSelf().addClass('bright');
});
});