0

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
  • Try using .on('click', function() {}) instead. Commented Apr 2, 2012 at 16:53

2 Answers 2

2

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()});
        });
    }
});
Sign up to request clarification or add additional context in comments.

Comments

0

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

2 Comments

The problem is the line that is trying to pass in a for loop into $()
oh, yeah, I forgot to put a function inside the $(). fixed. I didn't test this of course, I'm hoping you can learn how to fix your code my my example.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.