views:

519

answers:

1

I'm writing a Rails app and need to plug in this little bit of jQuery code, but I don't really know how to get it to work. Here's my controller code:

class ChatroomController < ApplicationController
def send_data
    @role = Role.find_by_id(session[:role_id])
    render :juggernaut do |page|

      page.insert_html :bottom, 'chat_data', "<b>#{@role.name}:</b> #{h params[:chat_input]}<br>"
    end
    render :nothing => true
  end
end

and view code:

<h2>Chat</h2>
<html>
  <head>
    <%= javascript_include_tag :defaults, :juggernaut %>
    <%= juggernaut %>
  </head>
  <body>
     <div id='chat_data', class="chatbox">
     </div>
     <br>
    <%= form_remote_tag(
          :url => { :action => :send_data },
          :complete => "$('chat_input').value = ''" ) %>
      <%= text_area_tag( 'chat_input', '', { :rows => 3, :cols => 70, :id => 'chat_input'} ) %>
      <%= submit_tag "Send" %>
    </form>
  </body>
</html>

Now, I need to make the chatroom always scroll down to the bottom when any user sends a new message. But also, when the current user has manually scrolled up, disable this sort of behaviour. I found some jQuery code here: http://stackoverflow.com/questions/13362/scrolling-overflowed-divs-with-javascript

Now I don't know to get it to work. I pasted into application.js:

$("#chat_data").each( function() 
{
   var scrollHeight = Math.max(this.scrollHeight, this.clientHeight);
   this.scrollTop = scrollHeight - this.clientHeight;
});

I've also added <%= javascript_include_tag 'jquery', 'application' %> to the head of my view.

But when my chatroom log fills up, the scrollbar appears but does not automatically move to the bottom as new messages come through.

A: 

The problem seems to be that the code you've inserted is only run once, at the beginning of the script.

I don't know a lot about jquery so this is just a general solution.

function sub(data) {
  $('#chat_data').each( function () {
    var s_top = this.scrollHeight - this.clientHeight;
    var scl = this.scrollTop == s_top;
    this.innerHTML += '<br/>' + data;
    if ( scl ) this.scrollTop = s_top + this.clientHeight;
  })
};

problem is that now when you receive new data from the server you must add it into the #chat_data by calling sub("text that goes into chat window").

you'll have to replace

page.insert_html ....

with something that sends the rjs to the client, like:

page.call( :sub, data)

hope it helps.

NixNinja
I just put that into application.js and it doesn't work. But I suspect the auto_scroll(); bit is suppose to go somewhere else? What I don't understand is how a function is going to be called more than once when my page doesn't reload (or at least I don't think it does).
alamodey
Edited my answer, see the first bit about the typo.
NixNinja
Still does nothing. Am I doing something wrong by just throwing the code into application.js and including it in the view?
alamodey
new code added....
NixNinja
hmmm not sure if there is anything like page.run. http://api.rubyonrails.org/classes/ActionView/Helpers/PrototypeHelper/JavaScriptGenerator/GeneratorMethods.html#M001633
alamodey
yea... it was page.call, sory
NixNinja