Bug Tracker

Opened 12 years ago

Closed 12 years ago

#1911 closed bug (fixed)

jQuery-bound events don't have access to jQuery-accessable items

Reported by: mike503 Owned by:
Priority: major Milestone: 1.2.2
Component: event Version: 1.2.1
Keywords: Cc:
Blocked by: Blocking:

Description

I can see this happening in Firefox 2.0.0.9 with FireBug and YSlow.

I tried to find any related tickets, this is the only one it *might* be related to: http://dev.jquery.com/ticket/1320

Otherwise, I think this is unreported so far.

If you try the code below, when the page is loading, mouse over the tabs - you don't need to click or anything. The mouseover alone will trigger the "$ is undefined"

Live example: http://mikehost.com/~mike/tmp/jquery/jquery5.html (note that one of the links is broken, but it's the mouseover action that is what is a concern)

Example code:

<!DOCTYPE html PUBLIC "-W3CDTD XHTML 1.0 TransitionalEN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html>

<head>

<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" /> <meta content="Wed, 26 Feb 1997 08:21:57 GMT" http-equiv="expires" /> <meta content="no-cache" http-equiv="Pragma" /> <script src="jquery.js" type="text/javascript"></script> <style type="text/css"> .tab {

float: left; padding:3px; padding-right: 30px; border-right:1px solid #fff; background-color: #ff9900; min-width: 110px;

} #allEntries, #createNew, #content {

border: solid 1px #7dbeee; padding: 5px; width: 975px;

} </style> <title>Test</title>

</head> <body>

<div id="bodyContainerWide">

<h2>Test</h2> <div id="tabs">

<div class="tab" id="allEntriesTab">page1</div> <div class="tab" id="createNewTab">page2</div>

</div> <div style="clear: both"></div> <div id="main">

This is page #1 click on a tab and mouseover both of the back and forth quick, should throw an error

</div>

</div> <script type="text/javascript"><!--

$(document).ready(function() {

$("#allEntriesTab").mouseover(function() {

$("#allEntriesTab").css("background-color", "#7dbeee").css("cursor", "pointer");

}); $("#allEntriesTab").mouseout(function() {

$("#allEntriesTab").css("background-color", "#ff9900").css("cursor", "default");

}); $("#createNewTab").mouseover(function() {

$("#createNewTab").css("background-color", "#7dbeee").css("cursor", "pointer");

}); $("#createNewTab").mouseout(function() {

$("#createNewTab").css("background-color", "#ff9900").css("cursor", "default");

}); $("#allEntriesTab").click(function() {

location.href = "jquery5.html";

}); $("#createNewTab").click(function() {

location.href = "jquery6.html";

});

}); -->

</script>

</body>

</html>

Here's the email thread:

http://groups.google.com/group/jquery-en/browse_thread/thread/8570c3a4347c6592/4418e9c7360e245f

Change History (6)

comment:1 Changed 12 years ago by mike503

sorry, here it is in a proper code block:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
 <head>
  <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
  <meta content="Wed, 26 Feb 1997 08:21:57 GMT" http-equiv="expires" />
  <meta content="no-cache" http-equiv="Pragma" />
  <script src="jquery.js" type="text/javascript"></script>
  <style type="text/css">
  .tab {
   float: left;
   padding:3px;
   padding-right: 30px;
   border-right:1px solid #fff;
   background-color: #ff9900;
   min-width: 110px;
  }
  #allEntries, #createNew, #content {
   border: solid 1px #7dbeee;
   padding: 5px;
   width: 975px;
  }
  </style>
  <title>Test</title>
 </head>
 <body>
  <div id="bodyContainerWide">
   <h2>Test</h2>
   <div id="tabs">
    <div class="tab" id="allEntriesTab">page1</div>
    <div class="tab" id="createNewTab">page2</div>
   </div>
   <div style="clear: both"></div>
   <div id="main">
    This is page #1
    click on a tab and mouseover both of the back and forth quick, should throw an error
   </div>
  </div>
  <script type="text/javascript"><!--
   $(document).ready(function() {
      $("#allEntriesTab").mouseover(function() {
            $("#allEntriesTab").css("background-color", "#7dbeee").css("cursor", "pointer");
      });
      $("#allEntriesTab").mouseout(function() {
         $("#allEntriesTab").css("background-color", "#ff9900").css("cursor", "default");
      });
      $("#createNewTab").mouseover(function() {
         $("#createNewTab").css("background-color", "#7dbeee").css("cursor", "pointer");
      });
      $("#createNewTab").mouseout(function() {
         $("#createNewTab").css("background-color", "#ff9900").css("cursor", "default");
      });
      $("#allEntriesTab").click(function() {
         location.href = "jquery5.html";
      });
      $("#createNewTab").click(function() {
         location.href = "jquery6.html";
      });
   });
   // -->
  </script>
 </body>
</html>

comment:2 Changed 12 years ago by mike503

perhaps this concept could help: http://remysharp.com/2007/10/01/catch-click-events-before-the-dom-is-loaded

adding some sort of check inside of the binding code in jquery's core to ensure no errors are thrown or something, for objects that get bound with events but perhaps the actual callback function can't access $ or jquery stuff quite yet...?

comment:3 Changed 12 years ago by davidserduke

Interesting. This appears to me to be a FireFox only reload problem. I can't get it to happen the first time it loads after I restart the browser but can get it to happen every time on reload. I put a js script that takes 2 seconds to load (using php) before the jquery script load to make it easier to reproduce.

Another interesting test was I put an alert here:

alert("set ready function now")
$(document).ready(function() {
  /* ... */

And when the problem happens that alert isn't called. This suggests to me that the event handlers were set from the previous load and were not cleared by the reload.

Notice, that even in FireFox with FireBug if you change out the event handlers and instead have:

  $("#allEntriesTab").mouseover(function() {
    console.log("do handler");
  });

Then you still get the error but 'console' is undefined. So this isn't just '$' or 'jQuery' problem. I have to admit, I don't understand why all the event code is working like fix() such. And of course it is difficult to test since console is undefined.

One last clue is if you add:

  window.onunload = function () {
    $("*").unbind();
  };

Then the problem goes away. I'm not sure if that's the best fix or not. With the svn version IE is already doing that to correct IE handler memory leaks.

comment:4 Changed 12 years ago by brandon

Component: coreevent
Resolution: wontfix
Status: newclosed

This is pretty much outside the scope of jQuery. You should bind events that have the potential to be triggered before the page is loaded within $(window).bind('load', fn). This will insure that the page is ready to accept your events ... otherwise the browser just isn't ready for you to interact with the page.

comment:5 Changed 12 years ago by mike503

Resolution: wontfix
Status: closedreopened

i'm sorry but i don't see how this is outside of jquery's scope.

i am using jquery to bind to the events. why can't there be some sort of check to see if the page is ready for interaction prior to binding, or prior to attempting to trigger the action that is already bound?

seems to me something that could easily be put inside of jquery. otherwise i am writing code to work around a limitation... i believe i've already tried $(window).load(function() { foo }); with the same failure as well.

jquery already works to adjust cross-browser issues and wrap common javascript incompatibilities, david's example above shows that this is an overall issue with binding events inside of jquery. what about mouseover/mouseout/other events based on some sort of move that could pre-page load become bound to window.load instead of document.ready or whatever the existing event is? that sounds like a library-wide fix that makes sense...

comment:6 Changed 12 years ago by brandon

Resolution: fixed
Status: reopenedclosed

Try using the built-in browser methods to attach/bind the events (no jQuery). It will result in the same error.

However I was wrong that I thought the page wasn't ready to interact with your events. I did some more investigating and David is correct that it appears the events are being retained on page unload and that is causing the issues.

In Rev [3822] I've opened up the removal of events on window.unload to all browsers and removed window from the list of elements to unbind events from to prevent the premature remove of an existing unload event before it gets fired.

This fixes the issue in my testing. Thanks for re-opening ... I was a little quick to close this one. :)

Note: See TracTickets for help on using tickets.