Register onclick events from dynamically created div array? Rails + Jquery?

心已入冬 提交于 2019-12-12 03:11:12

问题


After failing to achieve this with link_to remote, I decided to try jQuery way. Here is the jQuery loop and the rails loop and how they interact. Problem is I getting to register clicks only on one of the div's out of each loop, so the thing is not really working.. Here is the code:

<% @node.parent_relation.videos.each_with_index do |vid, idx| %>
  <%=  image_tag("http://img.youtube.com/vi/#{vid.content}/1.jpg", :id  => "img_div_#{idx}") %>
  <div id="vid_vid_<%=idx%>"  style="display: none"> <%= vid.id %></div>
<% end %>

  <script>
  var ids = "<%= @node.parent_relation.videos.length %>";
  var div_arr = [];
  var img_arr = [];
  var vid_id = 0;
  for( i=0; i < parseInt(ids); i++){
    var x = String("vid_vid_"+String(i));
    var y = String("img_div_"+String(i));
    div_arr.push(x);
    img_arr.push(y);
  }
  for ( i=0; i < parseInt(ids); i++){
    var vst = '#'+String(img_arr[i]);
    var dst = '#'+String(div_arr[i]);
    $(function() {
      $(vst).click(function(){
        var vid_id = $(dst).html();
        console.log(vid_id);
        $.post("/nodes/iframize/", {video_id: vid_id});
      });
    })

}
</script>

And there is an iframize action in nodes controller and an js.erb that updates the div from respond_to format.js in that action, that part works..

Thanks a lot, any advise greatly appreciated..


回答1:


Looks like the problem is the fact that all your handlers are sharing the dst variable. You can use the http://api.jquery.com/event.data/ option so that you're not relying on the shared closure variables. The option suggested by JasonWoof also works, you can choose whichever one seems easier for you.

for ( i=0; i < parseInt(ids); i++){
  var vst = '#'+String(img_arr[i]);
  var dst = '#'+String(div_arr[i]);
  $(function() {

    $(vst).click({dst: dst}, function(event){
      var vid_id = $(event.data.dst).html();
      console.log(vid_id);
      $.post("/nodes/iframize/", {video_id: vid_id});
    });
  })
}

A couple extra comments for your code

  • No need to wrap your calls in $(function(){}) within the loop. There should be just one call to $(function(){}) from the top level.
  • No need to use String(), it just clutters the code, JavaScript does type coercion for you.
  • Don't create global variables (your i variable in the loop)
  • Don't need two loops, or the two arrays you created, it can all be done in a much clearer way

Here's what I suggest the script be changed to,

$(function() {
    var ids = "<%= @node.parent_relation.videos.length %>";
    for( var i=0; i < ids; i++){
        $("img_div_"+i).click({dst: $("vid_vid_" + i)}, function() {
            $.post("/nodes/iframize/", {video_id: event.data.dst.html()});
        });
    }
});



回答2:


The trouble is that dst and vst are changing in your loop. So when your click handler runs, it uses the final versions of dst and vst, not the values they had when you created the click handler.

You need a copy of dst and vst, which you can do by creating a new context. Example

function make_handler(vst, dst) {
    $(vst).click(function(){
        var vid_id = $(dst).html();
        console.log(vid_id);
        $.post("/nodes/iframize/", {video_id: vid_id});
     });
}
$(function() {
    for ( i=0; i < parseInt(ids); i++){
        var vst = '#'+String(img_arr[i]);
        var dst = '#'+String(div_arr[i]);
        make_handler(vst, dst);
    }
});

You can do it inline, but you need a function that takes vst and dst as arguments, because they are copied, and the context is preserved for when the callback happens.

Edit: by "do it inline" I mean replacing the make_handler() call with something like:

 function(vst,dst) { ... } (vst, dst);


来源:https://stackoverflow.com/questions/9980209/register-onclick-events-from-dynamically-created-div-array-rails-jquery

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!