7

I'm working on chating module. For that I've used private_pub gem. In this module I have made three channels, but I can't mention all those here, because it'll show a very, very large page. So let's stick to one channel.

I click on a link having channel "<%= subscribe_to "/conversations/send_invitation" %>" and then ajax works and goes to "conversations/send_invitation" (only once - which is ok) and in my "/conversations/send_invitation" I have

def send_invitation
 @conversation = Conversation.new(conversation_params)
 respond_to do |format|
 format.js { render :layout => false }
 format.html
 end
end

and then in my send_invitation.js.erb file I've the following

<% publish_to "/conversations/send_invitation" do %>
var recipient_id = "<%=@conversation.recipient.id %>";
var current_temp_user = $("#current_temp_user").val();

if(recipient_id == current_temp_user){
console.log('here')
$("#invitation_div").html("<%=j(render :partial => '/restaurants/invitation')%>");
    card_modal = $('#invitation_card').modal();
    card_modal.modal('show');
}
<% end %>

Here is my application.js file

//= require jquery
// require jquery-ui
//= require jquery_ujs
// require turbolinks
//= require bootstrap
//= require jquery.raty
//= require private_pub
//= require_tree .

And the modal displays at recipient side (which is good).

Now the problem is that I can see two modal with the same id in my firefox console/html. And the buttons for closing/submit the modal also stopped working. Also the console.log in my send_invitation.js.erb file showed two time the console.log result, so it's clear that js.erb file is executing two times. But the point to note is that ajax ran one time only. I've wasted couple of hours on it and found only This link which also didn't work for me, because when I remove either jquery.js or jquery_ujs.js it gives me errors

Community
  • 1
  • 1
Mani
  • 2,391
  • 5
  • 37
  • 81

4 Answers4

0

I could not found a solution , but i thought it'd be worth for someone to inform about the actual issue .

In my case the issue was that I was making two channels on the same page ,that's why it was making handshake with the thin server two times .

Note But in a generic case it can also happen if we included js file two times .

Mani
  • 2,391
  • 5
  • 37
  • 81
  • What does it mean to making to channels on the same page? Having <%= subscribe_to conversation_path(conversation) %> twice on the page and one conversation form or having <%= subscribe_to conversation_path(conversation) %> only once, but having two conversation forms? In my case it's a turbolinks issue for sure. If I do a full page reload everything works fine, but if I create the conversation.message after going to another the page of the app and then coming back it gets displayed more times (it saves only 1 message to the db, only having problem with displaying). Any guesses? – Sean Magyar Jan 11 '16 at 16:17
  • Imran, it seems I could solve this issue. Check out my answer! – Sean Magyar Jan 11 '16 at 17:39
0

With $(document).on('keydown', '.chatboxtextarea', function (event){....}); my message object was created only once, but got displayed several times based on how many times I returned to the page with turbolinks without full page reload. To work around this in the js.erb file I added event.handled to check if partial has been already appended.

application.js

//= require jquery
//= require jquery-ui
//= require jquery_ujs
//= require turbolinks
//= require jquery.remotipart
//= require chat
//= require refile
//= require bootstrap-sprockets
//= require private_pub
//= require local_time
//= require moment
//= require fullcalendar
//= require bootstrap-datetimepicker
//= require_tree .

js file

 //submitting chat message (it's OUTSIDE $(document).on('page:change'..)
 //bind submit to document --> not affected by turbolinks
$(document).on('keydown', '.chatboxtextarea', function (event) {
  var id = $(this).data('cid');
  checkInputKey(event, $(this), id);
});

function checkInputKey(event, chatboxtextarea, conversation_id) {
  if (event.keyCode == 13 && event.shiftKey == 0) {
    event.preventDefault();

    //checking if field is empty and submitting the form
    message = chatboxtextarea.val();
    message = message.replace(/^\s+|\s+$/g, "");
    if (message != '') {
      $('#conversation_form_' + conversation_id).submit();
    }
  }
}

html.erb form

<div class="chatboxinput">
  <%= form_for([@conversation, @message], :remote => true, :html => {id: "conversation_form_#{@conversation.id}"}) do |f| %>
    <%= f.text_area :body, class: "chatboxtextarea", "data-cid" => @conversation.id %>
  <% end %>
</div>
......
<%= subscribe_to conversation_path(@conversation) %>

_message.html.erb

<li class="<%= self_or_other(message) %>">
  <div class="chatboxmessagecontent">
    <p>
      <%= message.body %>
    </p>
  </div>
</li>

create.js.erb

<% publish_to @path do %>
  var id = "<%= @conversation.id %>";
  var chatbox = $(".chatboxcontent");
  var lastMessage = chatbox.children().last();

  //with this one message will be displayed only once
  if(event.handled !== true) {

    $message = $('<%= j render @message %>');
    chatbox.append($message);
    chatbox.scrollTop(chatbox[0].scrollHeight);

    //for displaying incoming and outgoing messages differently
    if(sender_id != receiver_id) {
        chatbox.children().last().removeClass("self").addClass("other");
        chatbox.scrollTop(chatbox[0].scrollHeight);
    }

    event.handled = true;
  };
<% end %>
Sean Magyar
  • 2,360
  • 1
  • 25
  • 57
0

Use unbind method to remove unwanted/multiple calls to be executed with your events. This will do the trick. But reason behind the multiple calls is not yet clear.

$( "#foo" ).unbind( "click", handler );

Hope it helps.

Radz Singh
  • 78
  • 9
0

Use this gem instead

gem "private_pub", :git => 'https://github.com/ryleto/private_pub.git'