Relative Offsets Are Handled Differently Between Versions of jQuery
This post highlights a difference between jQuery 1.2 and later in how relative values are handled, which I recently discovered when upgrading a site from jQuery 1.2 to the new 1.3. If you’re about to do the same, or have recently broken your site after upgrading and don’t know why, this post is for you. It will be easier to explain with an example, so here’s how the problem manifested for us:
On our old website we used jQuery to slide the pages into view when a user clicks on a navigation link. This is a variation of the “Coda Slider”, named because it mimics the website for Panic software’s Coda editor. In a nutshell, we have a div which acts as a viewport (we’ll call it #viewport), with another div inside which contains the pages (which we’ll call #slideContainer). #viewport has its position property set to relative, and its child, #slideContainer, has its position set to absolute. So when we increase or decrease the value of #slideContainer’s left property, it will slide right or left respectively to reveal new pages. Here’s an example:
If the width of one page is 800px, then setting the inner div’s left property to 0 will show the first page, and setting the left property to -800px will bring the second page into view. -1600px shows the third page, -2400px shows the fourth, and so on. So all we have to do is adjust the left property of that div when we want to change what pages is shown, which we would do using jQuery’s animate function. Such a call might look like this:
This works as you would expect when the starting left value is 0 – #slideContainer will end with a value of -800px. The problem arises when we try to adjust the left value when its not starting at 0. For instance, if we were looking at the second page, #slideContainer would have a left value of -800px and the second page would be shown. If we then wanted to move to the third page, meaning left needs a value of -1600px, we would expect this to work:
In jQuery 1.2.1 or later this will work as you would expect, namely #slideContainer’s left is set to -1600px. However, in jQuery 1.2 values beginning with + or – are interpreted as relative values, which means that animate call would be interpreted as “subtract 1600px from the left of #slideContainer.” If left started at -800px, it would end at -2400px instead of -1600px as we intended.
To workaround this, our code was calculating how much the div needed to move relative to its current position and passing that value to the animate function instead. When we upgraded jQuery, this resulted in the pages sliding to arbitrary positions. To fix it, we stopped calculating the relative movement needed and simply pass the desired left value.
Note: you can still use relative offsets in new versions jQuery. Just use += and -= instead.
This is one of many small bug fixes between versions of jQuery that have caused us to dig back through old code. I’ll be posting more as we find them. The takeaway for me is that you should always include a specific version of jQuery (don’t ever include jquery-latest.js from Google Code) and make sure to test thoroughly whenever you’re upgrading to a new version of jQuery.