Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mark when the user starts typing in a form

I want to add the user to a post's author list when the user starts typing in a form.

For example, when the user types any letter (or press the 'enter' button) in the form, I would call @post.authors.create(user_id: current_user.id) to add the user to the list of authors of that specific post. I thought this would be impossible to implement, but using javascript to submit an ajax request might be sufficient to implement this method. Is it possible to achieve such method in a Rails application? If so, could anyone give me some directions?

like image 652
Maximus S Avatar asked Dec 06 '22 08:12

Maximus S


2 Answers

You must make event handler for keypress and remove after first press.

function typeCatch(){
  $(this).off("keypress",typeCatch)//remove handler
  console.log("User start type");
}

$("$field_id").on("keypress",typeCatch)
like image 145
Mihail Avatar answered Dec 08 '22 22:12

Mihail


For the following answer, I assume you are running Ruby on Rails with jQuery as javascript framework and have the current user (=author) logged in (i.e. the current user id in session). I'm explaining @Mischa's idea: Using the keypress event.

So, as you explained, you have a form to edit a post. I guess you have a textarea inside there with the post's text. For example <textarea id="posting">This is a post</textarea>.

Your next requirement was, to tell the server, "when the user types any letter (or press the 'enter' button) in the form". Hence we define an event handler, for the "keypress" event. This event handler should be removed, after the first key has been pressed. Thanks to @user2257149 for the following code (I adjusted it a little bit):

    function typeCatch(){
      $(this).off("keypress",typeCatch) // remove handler
      console.log("User start type");
    }

    $("#post").on("keypress",typeCatch); // add handler

This javascript code fragment must be below the definition of the <textarea>.

Now we have an event handler which is only fired once. In this handler, we trigger an ajax call to let the server know, the current user is editing the current post. As we're updating a specific attribute in the post object, we should trigger something like the following URL:

PUT http://www.example.com/posts/123/add_current_author

This means, we should use the HTTP PUT method to update the post with ID 123 and trigger method add_current_author in PostsController.

So we adjust the function typeCatch() to:

function typeCatch(){
  $(this).off("keypress",typeCatch)//remove handler
  $.ajax({
    type: "POST",
    url: '/posts/123/add_current_author',
    data: JSON.stringify({_method: 'put'})
  });
}

(As most browsers don't support the PUT method, Ruby on Rails tricks that by sending the POST parameter "_method", I got this from @Michael Koper in his answer to Ruby on rails - PUT method on update ajax)

You might have to add this special route to Ruby on Rails (not sure about the following, my rails is a bit rusty):

resources :posts do
  collection do
    put "add_current_author"
  end
end

Now, in your PostsController, you have to define method add_current_author. I assume you instantiate @post to be the actual post (identified by given :id) in a before_filter and have your current user saved in current_user. So actually it should be as easy as:

def add_current_author
  @post.authors.create(user_id: current_user.id)
end

Though I must admit, it looks a bit weird (it's what you suggested). I guess, I'd have a 1:n connection between "posts" and "users" called "authors" and do the following:

@post.authors << current_user

Again: Thanks to @Micha, @user2257149 and @Michael Koper. I upvoted your answers.

UPDATE: As stated in bounty comment, OP wants to change the current functionality from "mark read by user when shown" to "only mark as read, when user presses a key in comment form".

So currently EssayController has a show action like

def show
  ...
  @essay.reader_links.create(reader_id: current_user.id)
  ...
end

The given line should be removed, as current user should not be added when @essay shown. Furthermore, the <textarea> I defined above is the one in the comment form, so the HTML might look like

<html>
  ...
  <form action="essay/123/comment" method="post">
    ...
    <textarea name="comment_text" id="comment"></textarea>
    ...
  </form>
  <script type="text/javascript">
    function typeCatch() {
      ...
    }
    $("#post").on("keypress", typeCatch);
  </script>
</html>

Finally, action add_current_author should not be, as I assumed, in PostController but in EssayController and the route changed respectively.

UPDATE 2: As @Yarek T stated, instead of $("#post").on("keypress", typeCatch); the jQuery function one can be used:

function typeCatch(){
  $.ajax({
    type: "POST",
    url: '/posts/123/add_current_author',
    data: JSON.stringify({_method: 'put'})
  });
}
$("#post").one("keypress", typeCatch);
like image 24
Raul Pinto Avatar answered Dec 08 '22 22:12

Raul Pinto