SPServices and jQuery 1.7 - speeding up service parsing

Nov 11, 2011 at 12:53 PM

Hi everyone,

I attempted to update my jQuery library to 1.7 (released earlier this week) to discover that the old $(xData.XMLResponse).find("[nodeName='z:row']") doesn't work any more.

I raised a bug with the jQuery team who suggested I find some work-arounds for it, and so I did, including finding a 2000% performance increase along the way.

I've blogged about it here: http://www.steveworkman.com/html5-2/javascript/2011/improving-javascript-xml-node-finding-performance-by-2000/ and included JSPerf.com tests and links to the bug reports in jQuery.

I hope this is useful to you guys and I hope that it can go into the next version of SPServices.

Cheers,

Steve

Nov 11, 2011 at 9:37 PM
Edited Nov 12, 2011 at 1:19 PM

Thanks for the timely post, Steve.  I added the little filterNode function and did a find and replace on a version 0.6.2 for all z:row and rs:data operations.  Seems to work great.  I did have another issue though with this block of code . . .

// Get the parent column selection(s)
		switch(parentSelect.Type) {
			case "S":
				parentSelectSelected.push(parentSelect.Obj.find("option:selected").eq(0).text());
				break;
			case "C":
				parentSelectSelected.push(parentSelect.Obj.attr("value"));
				break;
			case "M":
				parentSelections = parentSelect.Obj.closest("span").find("select[ID$='SelectResult'][Title^='" + opt.parentColumn + " ']");
				$(parentSelections).find("option").each(function() {
 					parentSelectSelected.push($(this).html());
				});
				break;
			default:
				break;
		}
. . . where I had to change the underlined statement above to parentSelectSelected.push(parentSelect.Obj.find("option:selected").eq(0).text()); because it was returning the original and new selections concatenated together.
Have you or anyone else run into this? Using SP 2010 and jQuery 1.7 and IE8
Thanks,
Toby
Coordinator
Nov 13, 2011 at 7:04 PM
Edited Nov 13, 2011 at 7:05 PM

Also posted on Steve's blog post as a comment. I also did a post on my blog about this issue.

Steve:

The “SPServices group” (me) is impressed with your work on this. I’m going to look at getting this into the next release, if only for the speed increase.

The harder question may be what we can tell all the folks out there who are using the .find(“[nodeName='z:row']“) method. Obviously, switching all their code to the .find(‘*’).filter() method will be preferable if they want to improve performance. but there’s a lot of code out there that people won’t want to *have* to change just because 1.7 is going to break it. Any thoughts on how I can help in SPServices by converting their .find(“[nodeName='z:row']“) calls to .find(‘*’).filter() calls? Obviously, I can’t help with anything outside an SPServices call, but maybe as a stop-gap I could translate their calls for them, and improve their performance to boot.

I’ll post this back on the thread on the SPServices Discussions as well.

BTW, when you say “(which is, in general, a great library)”, I’m all ears if you can suggest improvements. Obviously you’ve come up with a very important one here.

Thanks,
M.

Coordinator
Nov 14, 2011 at 6:04 AM

I posted a new alpha last night with Steve's method implemented. Toby, perhaps my version will work for you.

http://spservices.codeplex.com/releases/view/68781

M.

Nov 14, 2011 at 10:48 AM

Hi Marc, thanks for the kind words.

Overriding calls like that will be quite tricky. In jQuery, the .find() method is part of the Sizzle selector library – you’d have to find the method for that, look at the selector to try and match “[nodeName='z:row']” and execute .find(‘*’).filter() instead, returning that result. However, I don’t know what else you might break because of that, so I’d be very wary of doing it.

Also, whilst it’s a 200x performance increase in this one function, for small lists it’s only going to take off 5-6ms of processing time. For larger lists it’ll make more difference, but proportionally the time taken to download the extra data will still make the request feel slow. Developers will get far more performance out of enabling gzip and caching AJAX request results than by using this function.

As far as upgrade paths go, I’d do what you’ve done before and split the library on the new jQuery version, making 0.7 a 1.7+ only library. This then lets you take advantage of the .on()/.off() delegate shorthand and any other 1.7+ improvements that will come around.

I’d also recommend that everyone reads this slide set from Addy Osmani (jQuery team member) on javascript performance– it’s what set me off on this path to increasing performance, that and a web page that took 15 seconds to load (now down to 3, limited by network performance).

Coordinator
Nov 14, 2011 at 11:31 AM
Steve:

Thanks for your thoughts. I've been thinking that it makes sense to bump to v0.7 with this version as well. If nothing else, it gives the corresponding "7" in the version.

As for the nodeName thing, I was hoping you'd have a magic idea. ;-) I have thought about trying to intercept that syntax on its way into Sizzle and replacing, but I think, as you say, that it would be hard to do and not necessarily a good idea.

I notice a bit of speed increase in my dev environment for SPServices using your method in the new alpha, but that may be wishful thinking, as I'm not measuring anything. I've tried to be as efficient as I can with my own code, but have chosen to assume that jQuery itself will be efficient. That's not always a valid assumption, of course, but there are only do many hours in the day I can spend on SPServices!

Thanks again fur your great work on this, and rest assured I'll be giving you all the credit you deserve.

M.
Nov 14, 2011 at 6:35 PM

Thanks, Mark--Alpha 10 does work with Jquery 1.7.  My other problem had to do with using DFWP XSLT forms in SharePoint 2010.  You have to leave the default web part in the page and hide it so that the linking as New, Default, etc. remains intact.  Unfortunatly this creates 2 of every control with the same title and breaks the cascading dropdown code.   Any other way around this than hacking your code like I did in my previous post?

Coordinator
Nov 14, 2011 at 9:05 PM
Actually, you don't need to leave the default LFWP in the page. I always delete them. I think that solves your problem!

BTW, I assume that you are editing a COPY of the page. If you delete the LFWP in the default page, you'll have problems.

M.
Nov 14, 2011 at 9:17 PM

Thanks for the quick reply.  In SP Designer 2010, if I edit a copy (or make a new form) and delete the default web part, it doesn't show up in the Forms list and therefore I can't set it to deafult for new forms.  Is there a way to force a form to Type: New and the default form for that type?  I just deleted the fields that I use Cascade on and it works.

Toby

Coordinator
Dec 30, 2011 at 2:49 PM

Toby:

Sorry for the delayed reply. I haven't seen the issue with the form not showing up in the settings, I don't think.

M