rails change the background of my like button when clicks on it : - javascript

I'm in the last step of my rails application (instagram-clone ) , and the issue is when i click on heart logo the count of number of likes upgraded from 0 to 1 but , i can't find the solution to change the background color of my logo to "red" when i click on it, this is my logo image
this is my vote.js.erb:
<% if current_user.liked? #post %>
$(".like-button").addClass("liked");
<% else %>
$(".like-button").removeClass("like-button");
<% end %>
$(".likes-count").html(" <%= #post.get_upvotes.size%> ")
#i want to modify this lines to change the background color of my heart logo to red when the count of likes was upgraded from 0 to 1 and thanks a lot
this i s my like button code lines :
<%= link_to like_post_path(post), class:"like-button", method: :put, remote: :true do %>
<div>
<i class="fas fa-heart fa-2x"></i>
</div>
<% end %>
<span class="likes-count"><%= post.get_upvotes.size %></span>

Ok here is your option.
There could be many stories/photos you might be looking and scrolling through the list.
Here is the fix that suit this kind of scenarios.
Some changes in vote.js.erb:
<% if current_user.liked? #post %>
$(".like-button-<%= #post.id %> .fas").addClass("liked");
<% else %>
$(".like-button-<%= #post.id %> .fas").removeClass("liked");
<% end %>
$(".likes-count").html(" <%= #post.get_upvotes.size%> ")
As you are using icon, Somewhere in the style add css similar to below.
.liked {
color: red;
}
And some changes in your html button
<%= link_to like_post_path(post), class: "like-button-#{post.id}", method: :put, remote: :true do %>
<div>
<i class="fas fa-heart fa-2x <%= 'liked' if current_user.liked?(post) %>"></i>
</div>
<% end %>

Related

How to make additional forms with with new objects using Javascript/jQuery?

On initial page load, all of the current user's highlights are gathered and each is put into a form. These forms are later shown the user once he clicks a certain button.
The scenario I'm trying to sort out, though, is that through the course of the user's interactions, new highlights can be created. And these new highlights also need to be 'prepared' within the same series of forms.
At the moment, I'm trying to use a gigantic .append() method, but it's failing silently in the background.
Any pointers? I suspect it may have something to do with improper quotation management within the method call and/or incorrect usage of the "j" escape_javascript Rails method...
Is there a better way of approaching the scenario? I've tried 'refreshing' the div with a call to render the partial. While that does achieve the end result of having "current" data on display, the problem there is the associated *.js file becomes 'disconnected' from the page, ruining the user interactions.
Thank you in advance for any help or insight you can offer!
_partial.html.erb This is what I'm essentially trying to 'add to'
<% #current_user_highlights.each do |highlight| %>
<div class="slide">
<%= form_for(highlight, remote: true) do |f| %>
<%= f.fields_for :image_tags_attributes do |image_tag_fields| %>
<%= image_tag_fields.fields_for :tag_content_attributes do |tag_content_attributes_fields| %>
<%= image_tag highlight.file_url(:speck), data: { src: highlight.file_url(:medium),
id: highlight.id } %>
<div class="wrapper">
<%= tag_content_attributes_fields.text_field :content, class: 'form-control',
id: "tag-content-field-#{highlight.id}" %>
<%# id: "tag-content-field-#{highlight.parent_image.id}" %1> %>
<div class="actions display-none">
<%= button_tag "", type: 'submit',
class: "btn btn-lg btn-default glyphicon glyphicon-ok above-interaction-barrier",
id: "highlight-confirmation-submit-button-#{highlight.id}" %>
<%= button_tag "", class: "btn btn-lg btn-default glyphicon glyphicon-remove above-interaction-barrier",
id: "highlight-confirmation-remove-button-#{highlight.id}" %>
<%= button_tag "Skip", class: "btn btn-med btn-default above-interaction-barrier display-none skip-button",
id: "highlight-confirmation-skip-button-#{highlight.id}" %>
</div>
</div>
<% end %>
<%= image_tag_fields.fields_for :tag_title_attributes do |tag_title_attributes_fields| %>
<%= tag_title_attributes_fields.hidden_field :title, value: highlight.tag_titles.first.title %>
<% end %>
<% end %>
<% end %>
</div>
<% end %>
update.js.erb
$('#highlight-confirmation-wrapper div.slide:last').append(
"<div= 'slide' <%= j form_for(#image.crops.last, remote: true) do |f| %>
<%= f.fields_for :image_tags_attributes do |image_tag_fields| %>
<%= image_tag_fields.fields_for :tag_content_attributes do |tag_content_attributes_fields| %>
<%= image_tag #image.crops.last.file_url(:speck), data: { src: #image.crops.last.file_url(:medium),
id: #image.crops.last.id } %>
<div class="wrapper">
<%= tag_content_attributes_fields.text_field :content, class: 'form-control',
id: "tag-content-field-#{#image.crops.last.id}" %>
<%# id: "tag-content-field-#{highlight.parent_image.id}" %1> %>
<div class="actions display-none">
<%= button_tag "", type: 'submit',
class: "btn btn-lg btn-default glyphicon glyphicon-ok above-interaction-barrier",
id: "highlight-confirmation-submit-button-#{#image.crops.last.id}" %>
<%= button_tag "", class: "btn btn-lg btn-default glyphicon glyphicon-remove above-interaction-barrier",
id: "highlight-confirmation-remove-button-#{#image.crops.last.id}" %>
<%= button_tag "Skip", class: "btn btn-med btn-default above-interaction-barrier display-none skip-button",
id: "highlight-confirmation-skip-button-#{#image.crops.last.id}" %>
</div>
</div>
<% end %>
<%= image_tag_fields.fields_for :tag_title_attributes do |tag_title_attributes_fields| %>
<%= tag_title_attributes_fields.hidden_field :title, value: #image.crops.last.tag_titles.first.title %>
<% end %>
<% end %>
<% end %>
</div>");
I was able to get this sorted out by changing the approach I was using.
Rather than have the form partial include the call to #current_user_highlights, and thereby proceed to make numerous forms, I instead broke the form itself into a separate partial. This allows me to reuse the form later to 'render' a single instance based off of the highlight that is sent through along with the update.js.erb file.
I also added an additional wrapper around the slide listing, this allowed me to more easily use the .append() jQuery function.
The resulting update.js.erb file looks something like this:
$('#slides-wrapper').append("<div class='slide'> <%= j render 'tasks/highlight_confirmation_slide_form', highlight: #image.crops.last %> </div>");

Ruby on Rails on rendering with Ajax

I am working on a simple website which has posts in forms of songs, now I have implemented like and dislike feature, but when I click on like/dislike it renders the numbers of likes/dislikes on all posts. And when I reload the page it returns them to normal. Now I would like it to change only the numbers for that particular post, without affecting the numbers on other posts?
My view for posts:
<div class="col-6">
<% for #s in #songs %>
<div class="card border-secondary mb-1">
<div class="card-header">
<div class="col-1">
<%= image_tag User.find(#s.user_id).user_image.url, :size=>"50x50" %>
</div>
<div class="col-11 text-muted">
<a href="/user/<%= User.find(#s.user_id).username %>" class="info-col">
<%= User.find(#s.user_id).username %>
</a>
- <%= #s.created_at.to_formatted_s(:short) %>
</div>
</div>
<div class="card-body">
<h4 class="card-title">
<%= #s.title %>
</h4>
<p class="card-text"><%= simple_format(#s.content) %></p>
</div>
<div class="card-footer text-muted">
<div class="col-12">
<div class="row">
<div class="col-3" id="song_like">
<%= render '/components/song_like' %>
</div>
<div class="col-3" id="song_dislike">
<%= render '/components/song_dislike' %>
</div>
<div class="col-4" id="song_comment">
<%= render '/components/song_comment' %>
</div>
</div>
</div>
</div>
</div>
<% end %>
</div>
The song_like partial has the following code:
<%= link_to like_song_path(#s.id, like: true), remote: true, method: :post do %>
<i class="fa fa-thumbs-o-up fa-lg" aria-hidden="true"></i> &nbsp <span class="songlikes">
<%= #s.thumbs_up_total %>
</span>
<% end %>
The song_dislike partial has the following code:
<%= link_to like_song_path(#s.id, like: false), method: :post, remote: true do %>
<i class="fa fa-thumbs-o-down fa-lg" aria-hidden="true"></i> &nbsp <span class="songdislikes">
<%= #s.thumbs_down_total %>
</span>
<% end %>
And my 'like' controller is like:
def like
#s = Song.find(params[:id])
#like = Like.create(like: params[:like], user: current_user, song: #s)
respond_to do |format|
if #like.valid?
format.html
format.js
else
format.html
format.js
end
end
end
This is how like.js.erb looks like:
$('.songlikes').html("<%= #s.thumbs_up_total %>");
$('.songdislikes').html("<%= #s.thumbs_down_total %>");
Here is the part of routes.rb file:
resources :songs do
member do
post 'like'
end
end
I am assuming there is some issue on rendering or jquery, but can't figure it out. Do You have any instructions?
EDIT: You should remove the redirect_to in your f.html?
This reloads the page - and the js will therefore not work.
An Ajax call is per definition not reloading the page.
If you remove those lines and try the following:
There's no new data in your jQuery.
You need a global attribute, so the view can find the data from your controller.
For example:
#like = ...
Then in your view you can add a local to be rendered:
$("#song_like").load("<%=j render partial: '/components/song_like', locals: {like: #like} %>");
But, you need to change your partial to be a partial. And change the variable to like so it will be rendered in the right way.
Hope it helps!
UPDATE
If you want to hit a specific song you can render it with each and then assign an id to your post's class
For example:
<% #posts.each do |post| %>
<div class="post-content">
... other stuff ...
<div class="likes like-post-<%= post.id %>">
.. number of likes
</div>
<%= link_to "Like", link_route_path(post) %>
</div>
<% end %>
# controller
# So you can use the id in your js view
#id = params[:id]
# view.js
$(".like-post-" + "<%= #id %>").html("<%= #s.thumbs_up_total %>");
Hope the idea helps.
change rendering like this:
<div class="col-3" id="song_like">
<%= render partial: '/components/song_like', locals: {s: #s, like: true} %>
</div>
then in partial:
<%= link_to like_song_path(s.id, like: like), method: :post, remote: true do %>
<i class="fa fa-thumbs-o-up fa-lg" aria-hidden="true"></i> &nbsp <%= s.thumbs_up_total %>
<% end %>
and in controller of like_song
should define
#s= Song.find(params[:id])
like = Like.create(like: params[:like], user: current_user, song: #song)
#like = !like.like # opposite to your current status
rest of the things good and then in like.js.erb
$('#songs_like').html("<%= escape_javascript(render partial: '/components/song_like', locals: { s: #s, like: #like } ) %>")

Rendering a partial to an edit form inside a popover in rails 4

Hi guys I really need help here.
I'm making a todo app and displaying each task through an iteration. Next to each task I have a pencil glyphicon.
When I click on it, I want there to be a popover containing an edit form and edit the task on the spot. I'm having a ton of troubling rendering that form.
***** UPDATE *****
Clark helped me get the popover to work. But The form inside the popover is acting like a link instead of a form so I can't type in the text area.
This is my index.html.erb
<div id='user_tasks'>
<% #tasks.each do |task| %>
<ul>
<li>
<%= task.description %>
<%= link_to edit_task_path(task), :rel => 'popover', method: 'get', remote: 'true' do %>
<span class = 'edit_task_<%=task.id%> glyphicon glyphicon-pencil'> </span>
<% end %>
</li>
</ul>
<% end %>
</div>
This is the edit.js.erb
$(function(){
$('.edit_task_<%=#task.id%>').popover({
html: true,
title: 'edit',
content: <%= escape_javascript render 'edit_form', task:#task %>
}).popover('show'); });
and my controllers look like this:
def index
#new_task= Task.new
#tasks= Task.all
end
def create
#new_task= Task.new(task_params)
#task.save
redirect_to :back
end
def edit
#task= Task.find(params[:id])
end
_edit_form.html.erb looks like this: This isn't the edit form that I plan to use. Its just a copy of the create task form. I plan to fix it once I get the popover working.
<%= form_for task, :html=>{:class=> 'form-inline'} do |f| %>
<div class='form-group'>
<%= f.text_field :description, placeholder: 'create a task' %>
<%= button_tag(type:'submit', class:"btn btn-default btn-xs") do %>
<span class='glyphicon glyphicon-plus'></span>
<% end %>
</div>
<% end %>

Follow button using AJAX only updates first div

I have a _user.html.erb partial that I am rendering on my Users#Index action with a form embedded to allow following and unfollowing of each user. I also have accompanying create.js.erb and destroy.js.erb files in my relationships controller to handle the AJAX. Right now I have to refresh the page in order to see the changes made by clicking the "follow/unfollow" button next to a users name except the first user's record behaves correctly.
_user.html.erb
<div id ="follow_form">
<% if current_user.following?(user) %>
<%= form_for(current_user.relationships.find_by(followed_id: user.id),
html: { method: :delete },
remote: true) do |f| %>
<%= f.submit "Unfollow", class: "btn btn-large" %>
<% end %>
<% else %>
<%= form_for(current_user.relationships.build(followed_id: user.id),
remote: true) do |f| %>
<div><%= f.hidden_field :followed_id %></div>
<%= f.submit "Follow", class: "btn btn-large btn-primary" %>
<% end %>
<% end %>
create.js.erb
$("#follow_form").html("<%= escape_javascript(render('users/unfollow')) %>")
$("#followers").html('<%= #user.followers.count %>')
destroy.js.erb
$("#follow_form").html("<%= escape_javascript(render('users/follow')) %>")
$("#followers").html('<%= #user.followers.count %>')
here is a link to my users_controller.rb https://gist.github.com/anonymous/9608208 and my relationships_controller.rb https://gist.github.com/anonymous/9608284
I've tried changing the div to something dynamic like
<div id ="follow_form_<%= user.id %>">
But when I make the same change to the javascript like this
$("#follow_form_<%= user.id %>").find.html("<%= escape_javascript(render('users/unfollow')) %>")
it doesn't seem to work.
I've been trying to figure out how to pass the user.id attribute into the javascript but am falling flat.
It turns out the problem was in my _follow_form.html.erb partial.
I had to change
<div id="follow_form">
to
<div id="follow_form_<%= #user.id %>">
I thought I only needed to make the change in the _user.html.erb partial but I was wrong. My current user partial uses the same div id to contain the button in the Users#Index view
<div id ="follow_form_<%= user.id %>">

Passing the ID of a DOM element to rails controller

My model has Chords, which have a many-to-many relationship with Notes through Chordnotes. My chords/show looks like this:
<% #chord.notes.each do |note| %>
<li id="NoteID<%= note.id %>" >
<span class="content"><%= note.name %> (<%= note.description %>) (ID: <%= note.id %>)</span>
<span class="timestamp">
Created <%= time_ago_in_words(note.created_at) %> ago.
</span>
<span class="content">
<%= link_to "remove (not working)", '#' %>
</span>
</li>
<% end %>
I want the link_to tag to remove, not the note, but the Chordnote that links the Note to the Chord. I was trying to do this by referencing the #id in the < li > tag, which is the ID of the Note, and passing the Note ID and the Chord ID from the /show page the user was on. My Chordnote controller looks like this:
def destroy
#chord = Chord.find(chord-id) <-- how do I get this chord id??
#note = Note.find(note-id) <-- how do I get this note id??
Chordnote.find_by(note_id: #note.id, chord_id: #chord.id).destroy
redirect_to chord_path(#chord)
end
This destroy action works when I hardcode chord-id and note-id with ID #'s, but I can't figure out how to pass the relevant Note and Chord IDs from the chords/show page.
Any help would be appreciated, thanks!
this is untested, mind you. But have you tried passing the relevant data through the link_to?
<% #chord.notes.each do |note| %>
<li id="NoteID<%= note.id %>" >
<span class="content"><%= note.name %> (<%= note.description %>) (ID: <%= note.id %>)</span>
<span class="timestamp">
Created <%= time_ago_in_words(note.created_at) %> ago.
</span>
<span class="content">
<%= link_to "remove (not working)", {controller: "whatever_controller", action: "destroy", chord_id: #chord.id, note_id: note.id } %>
</span>
</li>
<% end %>
and then you would access these in the destroy method like so
def destroy
#chord = Chord.find( params[:chord_id] )
#note = Note.find( params[:note_id] ) <-- how do I get this note id??
Chordnote.find_by(note_id: #note.id, chord_id: #chord.id).destroy
redirect_to chord_path(#chord)
end

Categories