【问题标题】:Mark when the user starts typing in a form标记用户何时开始输入表单
【发布时间】:2013-04-07 23:46:24
【问题描述】:

当用户开始输入表单时,我想将用户添加到帖子的author 列表中。

例如,当用户在表单中键入任何字母(或按“输入”按钮)时,我会调用 @post.authors.create(user_id: current_user.id) 将用户添加到该特定帖子的作者列表中。我认为这不可能实现,但使用 javascript 提交 ajax 请求可能足以实现此方法。是否可以在 Rails 应用程序中实现这种方法?如果是这样,谁能给我一些指示?

【问题讨论】:

  • 您应该在表单上监听keydown 事件。如果发生这种情况,请使用 $.post 将当前用户发布到您的控制器。
  • 在用户实际提交表单之前是否需要将用户添加为作者(可能会保存任何更改)?我认为您想要这样做的方式会更难,并且可能会给您带来进一步的复杂性,特别是如果用户要删除他们所做的任何更改,或者从不实际保存它们。如果您确实需要这样做,那肯定是可能的。
  • 根本不是惯例。如果我只是在这里输入而不点击“添加评论”,您将永远看不到我的评论。
  • 我非常清楚其中的逻辑。用户之后是否不提交表单对我来说并不重要。我想实现这个功能,让用户知道是否有人(将被临时添加为“作者”)正在编辑某个帖子。
  • @Mischa 你能再解释一下吗?我知道我必须听一个keydown 事件,但对将当前用户发布到控制器知之甚少。

标签: javascript ruby-on-rails ajax jquery


【解决方案1】:

您必须为按键创建事件处理程序并在第一次按下后删除。

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

$("$field_id").on("keypress",typeCatch)

【讨论】:

    【解决方案2】:

    对于以下答案,我假设您正在使用 jQuery 作为 javascript 框架运行 Ruby on Rails,并且当前用户 (=author) 已登录(即会话中的当前用户 ID)。我在解释@Mischa 的想法:使用按键事件。

    因此,正如您所解释的,您有一个表单来编辑帖子。我猜你里面有一个带有帖子文本的文本区域。例如<textarea id="posting">This is a post</textarea>

    您的下一个要求是,告诉服务器“当用户在表单中键入任何字母(或按'输入'按钮)时”。因此,我们为“keypress”事件定义了一个事件处理程序。在按下第一个键后,应删除此事件处理程序。感谢@user2257149 提供以下代码(我稍微调整了一下):

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

    此 javascript 代码片段必须低于 <textarea> 的定义。

    现在我们有了一个只触发一次的事件处理程序。在这个处理程序中,我们触发了一个 ajax 调用,让服务器知道当前用户正在编辑当前帖子。当我们更新 post 对象中的特定属性时,我们应该触发类似以下 URL 的内容:

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

    这意味着,我们应该使用 HTTP PUT 方法来更新 ID 为 123 的帖子,并在 PostsController 中触发方法 add_current_author

    所以我们将函数typeCatch()调整为:

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

    (由于大多数浏览器不支持 PUT 方法,Ruby on Rails 通过发送 POST 参数“_method”来欺骗它,这是我从@Michael Koper 在他的answer to Ruby on rails - PUT method on update ajax 中得到的)

    您可能需要将此特殊路由添加到 Ruby on Rails(不确定以下内容,我的 Rails 有点生锈):

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

    现在,在您的PostsController 中,您必须定义方法add_current_author。我假设您将@post 实例化为before_filter 中的实际帖子(由给定的:id 标识)并将您的当前用户保存在current_user 中。所以实际上它应该很简单:

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

    虽然我必须承认,它看起来有点奇怪(这是你的建议)。我想,我会在“帖子”和称为“作者”的“用户”之间建立 1:n 连接,并执行以下操作:

    @post.authors << current_user
    

    再次感谢@Micha、@user2257149 和@Michael Koper。我赞成你的答案。

    更新: 如赏金评论中所述,OP 希望将当前功能从“显示时标记为已读”更改为“仅在用户按下评论表单中的键时标记为已读”。

    所以目前EssayController 有一个show 类似的操作

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

    应该删除给定的行,因为在显示@essay 时不应添加当前用户。此外,我上面定义的 &lt;textarea&gt; 是评论表单中的那个,所以 HTML 可能看起来像

    <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>
    

    最后,操作add_current_author 不应该像我假设的那样在PostController 中,而是在EssayController 中,并且路线分别改变了。

    更新 2: 正如@Yarek T 所说,可以使用 jQuery 函数 one 代替 $("#post").on("keypress", typeCatch);

    function typeCatch(){
      $.ajax({
        type: "POST",
        url: '/posts/123/add_current_author',
        data: JSON.stringify({_method: 'put'})
      });
    }
    $("#post").one("keypress", typeCatch);
    

    【讨论】:

      【解决方案3】:

      大家忘了jQuery的$.one()函数了吗?它的功能与 $.on() 然后在 $.off() 内部执行相同。

      【讨论】:

        【解决方案4】:
        var flag = 0;
        $(document).on('keypress', function(e) {
            if(flag == 0) {
                 doSomething();
                 flag = 1;
            }   
        });
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-01-24
          • 1970-01-01
          相关资源
          最近更新 更多