jQuery and Backward Compatibility
The other day, I was helping Jim (jtandrew on Codeplex) with an issue he was having with SPServices. It took a little back and forth before we realized that he was using an old version of SPServices with a newer version of jQuery. One of the problems with naming your files something consistent like jquery.SPServices.min.js is that it’s sometimes difficult to be sure what version you’re using. There are some decent reasons for using consistent naming (a single point of change being the main one, but that also has drawbacks), but be sure that you always know which true versions of script files you are using. But that’s for a different post…
The jQuery folks manage to break something in my SPServices code with just about every point release. It’s not that I’m doing anything unacceptable, but they sometimes change the rules. Backward compatibilityĀ mayĀ not be the jQuery team’sĀ strong suit,Ā but as with most things, it’s a work in progress.Ā I’m not meaning to disparage the great work they do, but it points out the fact that you simply *must* always test your scripts with new versions of jQuery, just as I do with SPServices.
As an example, as I’ve previously written, in going from version 1.4.x to 1.5, the jQuery team started enforcing the rule which says that you must enclose literal strings in quotes in selectors. In 1.4.x, this was totally valid:
$(xData.responseXML).find("[nodeName=z:row]")
but in jQuery 1.5+, it must be:
$(xData.responseXML).find("[nodeName='z:row']")
Another difference cropped up for me in going from jQuery 1.5.x to 1.6. In 1.5.x and earlier, this worked:
$(childSelect.Obj).attr("length", 0);
but in 1.6+, it needs to be:
$(childSelect.Obj).find("option").remove();
So no longer could I truncate a select’s options by simply setting the select’s length to zero; I needed to remove the options from the DOM.
It’s open to debate whether my original code in either case was so great to begin with. We’re all learning all the time, and in both cases, I’d prefer the method in the latter case over where I started out. However, this makes for a herky-jerky development experience as the jQuery team puts out more releases. For each of theirĀ point releases, I’m finding at least one deal breaking issue which means that I need to release a new version of SPServices just to keep up. I like to do a release or two every quarter to add functionality people are looking for anyway, but it makes it tricky to manage versions for me, and probably for everyone else as well.
So what’s the moral of this story? Test, test, test. Whenever you go from one point release of jQuery to another, you probably should assume that *something* in your perfectly functional existing code may break. In each case I’ve identified, it’s led to better code on my end, but it still means changes.
This is yet another good argument for consistent, organized code management for your scripts. Store as much of your script as as possible (if not all of it) in Document Libraries so that you can easily find the script files you’ve used. You can use a Content Editor Web Part (CEWP) with the Content Link to point to the file, or simply add a new script reference in your page rather than including the script inline.
<script language="javascript" type="text/javascript" src="/Scripts/MyReallyGreatScript.min.js"></script>
I generally shy away from being overlyĀ prescriptive about exactly where you should store your scripts or what your script management practices ought to be. The most important thing is that you come up with a scheme which is consistent and predictable. I always say that this is an important part of your governance, just as important as what type of content your users are allowed to post to a discussion or anything else. Your governance should cover your *coding* rules as well as your *end user* rules. It’s hardly fair to expect all of your users to follow rules if you don’t even give yourself any!
So when a new release of jQuery comes out, test, test, test. Identify *all* of the scripts you have in place which use your existing version and make sure that they still work with the new version. Each new version of jQuery offers great new functionality as well as a tightening up of the existing functionality.
Nice post Marc! I too have ran into similar issues when upgrading or testing different versions of jQuery.
I’ve had to go through a few permutations of clearing out drop down’s as well. I started using the same code you have above, until recently. I found .empty() to solve a lot of my issues when clearing DOM elements. What’s neat about this, is that it works on anything and it’s not specific to drop downs.
Matt:
.empty() was tempting, but I always need to be really careful in my general-purpose code. It’s possible (though highly unlikely) that someone will have added some other child elements to the select, so I need to only “destroy” the specific option elements.
M.
WOW, great point, thanks for the heads up. This will probably save people tons of time and effort troubleshooting down the road.
Cool article Marc,
Even I was facing similar issues couple of days back, when I upgraded the jQuery version from 1.4.2 to 1.6.1 and spent hours on researching about the issue, with no luck finally I pointed back to the older version. After seeing this article I got a clear picture on my issue. Thanks a lot for this write up
.
1.4 to 1.6 is really a big change, e.g. Ajax rewrite(1.5), Attribute rewrite(1.6)
The change log would be always helpful.
Some very good points here.
“consistent and predictable” is the goal, the issue is that we are dealing with a technology that evolves rapidly, and best practices of today may not be relevant in 6 or 12 months!
For me, the other moral is that jQuery doesn’t come for free, and you should only use it if it brings tangible benefits. For several of my scripts, like the Easy Tabs, image rotator and cacading drop-downs, I have been using plain JavaScript. The code is not heavier than with jQuery, and the result is much more predictable.
Christophe:
SPServices couldn’t exist without jQuery, at least without me writing major parts of jQuery-like functionality myself. It *can* be preferable to use straight JavaScript, but the leg up that jQuery gives you is extremely significant. The trade off is that there’s a dependency on others’ code. To me, it’s a no-brainer.
M.
I guess one option is to change the naming convention of your .js file.
You could specify explicit versions – one for your library and another for corresponding jQuery version required, e.g. SPServices-0.6.2-jQuery-1.6.js. It’s a little ugly but pretty clear.
Or you could match your minor revision number with jQuery, so SPServices 0.6.x requires jQuery 1.6.x, SPServices 0.7.x requires jQuery 1.7.x. That gives you less flexibility.