简体   繁体   English

如何从作为AJAX调用的回调执行的js.erb触发JS函数?

[英]How do I trigger a JS function from a js.erb executed as a callback on an AJAX call?

I know the title reads a bit funky, but this is what I am doing. 我知道标题读起来有点时髦,但这就是我在做什么。

I have a link that looks like this, as defined in my nodes_helper.rb : 我有一个看起来像这样的链接,如我的nodes_helper.rb所定义:

    link_to(favorite_node_path(node, node_counter: node_counter), class: "card-favorite-count favorited", method: :post, remote: true,  data: {toggle_href: unfavorite_node_path(node) }) do
      concat(content_tag(:i, "", class: "icon-heart"))
      concat(node.cached_votes_total)
    end

That then ultimately, on success, leads to this /views/nodes/favorites.js.erb being executed: 最终, /views/nodes/favorites.js.erb成功,就会导致/views/nodes/favorites.js.erb被执行:

$("#card-<%= @node_counter %> .card-attr").html('<%= favorites_count(@node, @node_counter) %>');
$("#card-<%= @node_counter %> .card-attr").append('<%= comments_count(@node) %>');

All of that works fine, but what I want to do is add some animation to the class card-favorite-count after the link is pressed. 所有这些都可以正常工作,但是我想做的是在按下链接后向class card-favorite-count添加一些动画。 Basically, right before the count gets updated. 基本上,在更新计数之前。

My animation is defined in my app/assets/javascripts/nodes.js.coffee like so: 我的动画是在我的app/assets/javascripts/nodes.js.coffee定义的,如下所示:

animate_favorite = ($favorite) ->
  $favorite.addClass 'active'
  card = $favorite.parent().parent().parent()
  card_id = card.attr('id')
  setTimeout (->
    $('#' + card_id).find('.card-favorite-count').removeClass 'active'
    return
  ), 1200
  return

$(document).ready ->
  $('.card-favorite-count').click ->
    animate_favorite $(this)
    return
  return

The JS version of the above works in a plain old vanilla HTML/JS interface, but I am trying to hook it up with everything else I have going on - hence the conversion to CoffeeScript. 上面的JS版本可在普通的原始HTML / JS接口中使用,但我尝试将其与我正在进行的所有其他操作连接在一起-因此转换为CoffeeScript。

So, how do I call that animate_favorite function, from within my favorite.js.erb ? 因此,如何在我的favorite.js.erb调用该animate_favorite函数?

Edit 1 编辑1

Per Ryan's suggestion, I tried this in my favorite.js.erb : 根据Ryan的建议,我在我的favorite.js.erb尝试:

window.animate_favorite($(this));
$("#card-<%= @node_counter %> .card-attr").html('<%= favorites_count(@node, @node_counter) %>');
$("#card-<%= @node_counter %> .card-attr").append('<%= comments_count(@node) %>');

But I get this error in my JS console: 但是我在JS控制台中收到此错误:

window.animate_favorite($(this));
$("#card-1 .card-attr").html('<a class="card-favorite-count favorited" data-method="post" data-remote="true" data-toggle-href="/nodes/2/favorite" href="/nodes/2/unfavorite?node_counter=1" rel="nofollow"><i class="icon-heart"></i>1</a>');
$("#card-1 .card-attr").append('<span class="card-comment-count"><i class="icon-speech-bubble-1"></i>0</span>');

comments.self.js?body=1:5 parsererror

Edit 2 编辑2

Per The F's questions, here is my controller for this action: 按照F的问题,以下是我对此操作的控制者:

  def favorite
    @node.liked_by current_user
    @node_counter = params[:node_counter]
    current_user.events.create(action: "favorited", eventable: @node)

    respond_to do |format|
      format.js
      format.html{ redirect_to @node }
    end
  end

Edit 3 编辑3

When I followed The F's suggestion of putting the JS I want to execute directly into my favorite.js.erb , everything works like I want it. 当我遵循F的建议,将我想直接执行的JS直接放入我的favorite.js.erb ,一切都按我想要的方式工作。

ie this is what my favorite.js.erb looks like now: 即,这就是我的favorite.js.erb .js.erb现在的样子:

$("#card-<%= @node_counter %> .card-attr").html('<%= favorites_count(@node, @node_counter) %>');
$("#card-<%= @node_counter %> .card-attr").append('<%= comments_count(@node) %>');

$("#card-<%= @node_counter %> .card-attr .card-favorite-count").addClass('favorited active');
setTimeout(function() {
    $("#card-<%= @node_counter %> .card-attr .card-favorite-count").removeClass('active');
},1200);

So the question is, how do I get this to work within my Rails JS files? 所以问题是,如何在Rails JS文件中使用它? Which file do I put this function in so that I can just execute it in my favorite.js.erb and not in the declare it there? 我将这个函数放在哪个文件中,以便可以在我的favorite.js.erb .js.erb中执行它,而不在其中声明它?

Are you calling window.animate_favorite($('.card-favorite-count')); 你在打电话window.animate_favorite($('.card-favorite-count')); before inserting the node to the dom? 在将节点插入dom之前?

updated answer 更新的答案

Favourably you would return a json response that will hold the html partial you want to include and animate. 有利地,您将返回一个json响应,该响应将包含您要包含和设置动画的html部分。 Then you could listen for a successful ajax call from nodes.js.coffee that is triggered by favoriting one of the cards. 然后,您可以侦听来自nodes.js.coffee的成功ajax调用,该调用由收藏其中一张卡触发。 To achieve this you should do some research on how to make efficient use of javascript. 为此,您应该对如何有效使用javascript进行一些研究。 Maybe have a look at layouts & rendering and also passing data to javascript 也许看看布局和渲染 ,还可以将数据传递给javascript

For the moment I would keep the code as it is, as the amount of duplicated code is fairly small and it works the way you intend it to. 目前,我将代码保持原样,因为重复代码的数量非常小,并且可以按您期望的方式工作。

favorite.js.erb favorite.js.erb

$("#card-<%= @node_counter %> .card-attr").html('<%= favorites_count(@node, @node_counter) %>');
$("#card-<%= @node_counter %> .card-attr").append('<%= comments_count(@node) %>');

$("#card-<%= @node_counter %>").addClass('active');
setTimeout(function() { $("#card-<%= @node_counter %>").removeClass('active'); }, 1200);

Also, the js is not very consistent as you're passing $('.card-favorite-count') in your click function but wanted to pass your $('i.icon-heart') in your favorite.js.erb. 另外,js并不是很一致,因为您在click函数中传递了$('.card-favorite-count') ,但想在您的favourite.js.erb中传递$('i.icon-heart') You should try to always a similar selector ( card or icon ), unless there is a specific reason you were using the two. 除非有特定原因,否则您应该尝试始终使用类似的选择器( cardicon )。 Sticking with one however, will also simplify your existing jquery. 但是,坚持使用也会简化您现有的jquery。

You need to put them in the window namespace. 您需要将它们放在窗口名称空间中。 Try something like this in your nodes.js.coffee file: 在您的nodes.js.coffee文件中尝试nodes.js.coffee操作:

window.animate_favorite = ($favorite) ->
  ...code here...

Then, all you need to do to call it (in your favorite.js.erb file) is: 然后,您需要做的所有工作(在您的favorite.js.erb文件中)是:

window.animate_favorite(...element you want to pass in...)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM