Jquery script behaving differently when unobtrusive than when inside the rails view

160 Views Asked by At

I have this in my view

<script type='text/javascript'>
$(function(){       
    $('#users').click(function(){
        alert($("tr[aria-selected=true] td:first").html())                      
    })
})
</script>

And inside my users.js

$(function(){       
    $('#users').click(function(){
        alert($("tr[aria-selected=true] td:first").html())                      
    })
})

Having them,obviously not at the same time,gives me different results Basically I'm trying to retrieve the ID of the selected row finding it attr value.\

With the unobtrusive way right after loading the page I'd get "null" on my first click on a row and then every time I hit a row shows me the value that I clicked previously...TWICE!. But when keeping the script inside my view I get the result I want.

What am I doing wrong?

EDIT:

My view

<%=raw jqgrid("List of users", "users", "/users", 
 [    
   { :field => "id", :label => "id",:width => 50 },    
   { :field => "username", :label => "username",:width => 120,:editable => true },    
   { :field => "email", :label => "email",:width => 120,:editable => true },    
   { :field => "name", :label => "name",:width => 100,:editable => true },    
   { :field => "lastname", :label => "lastname",:width => 100,:editable => true },
   { :field => "groups", :label => "roles",:width => 180}   
 ] , {:add => true,:edit => true,:delete => true,:error_handler => "s",:inline_edit => 'true',:edit_url => post_data_users_url,:sortable_rows => 'true'}  
 ) %>
 <p><%= link_to "Edit roles",roles_path%>
 <%= link_to "| Edit user",{:action => 'edit'},{:class => 'editLink hide'}%></p>

 <script type='text/javascript'>
   $(function(){
       var _last = new String()     
       $('#users').click(function(){
           _last = $("tr[aria-selected=true] td:first").html()
           $(".editLink").attr("href","/users/edit/"+ _last)
           $(".editLink").addClass('show')
       })
   })
</script>

My layout

<!DOCTYPE html>
<html>
<head>
  <title>UserManager</title>
  <%= stylesheet_link_tag "application", :media => "all" %>
  <%= javascript_include_tag "application" %>
  <%= csrf_meta_tags %>
  <%=jqgrid_javascripts%>
  <%=jqgrid_stylesheets%>
</head>
<body>
    <div>
        <%if flash[:notice]%>
            <p><%= flash[:notice]%></p>
        <%end%>
        <%if current_user%>
            Logged in as <%= current_user.username%> | <%= link_to 'logout', log_out_path%>
        <%end%>
    </div>
    <%= yield %>
 </body>
</html>

The way I see it...nothing special there

1

There are 1 best solutions below

2
On

Depending on your performance requirements use either .live('click', function(){}) instead of click(function(){}), or create a function inside of your users.js to make the bind and use a callback on jqgrid to run it.

In users.js

$(function(){       
    $('#users').live('click', function(){
        alert($("tr[aria-selected=true] td:first").html())                      
    })
})

Or in users.js:

function bindClickToRow(){
   $(function(){       
     $('#users').click(function(){
        alert($("tr[aria-selected=true] td:first").html())                      
     })
   })
 }

Then use it in the callback of jqgrid ( I don't know how their API works and I couldn't find out quickly, but I am pretty sure a good grid plugin supports this, so consider this as pseudo code):

jQuery('table').jqgrid({
  afterCreate: bindClickToRow
})

Hope this helps.

The reason as far as I can see is that you are using 'click' to bind the click event of the to a function. But you are doing it when the actual itself does not exist yet. So you are basically telling jQuery, bind 'click' on all the s that exist right now.

What would happen if you use 'live' though is the equivalent of telling jQuery to bind that function to a 'click' event on all current AND future 's that match your selector.

The reason that the does not exist yet is because apparently jqgrid is loaded after the bind that is being called. Also, jqgrid probably creates new s regularly, long after the call to the 'click' bind. If you use 'live' jQuery will keep a lookout for all new s and will bind the callback function to them as soon as they are created.