1,804 articles and 15,139 comments as of Sunday, May 15th, 2011

EndUserSharePoint has combined resources with NothingButSharePoint.com. You can now find End User (Mark Miller), Developer (Jeremy Thake) and IT Pro SharePoint content all in one place!

This site is a historical archive and is no longer being updated. Please update your favorites, bookmarks and RSS feeds.

NothingButSharePoint.com
Tuesday, April 7, 2009

JQuery for Everyone: Minimal AOP and Elegant Modularity

If you read the previous articles on AOP, you know I’m a fan. It took some serious digging for me to understand how the JQ-AOP plugin works and how I could use it to fit my needs. I succeeded and I think you’ll really like the result.

But First, A Little About Objects

In JavaScript, we have two basic options for creating “plugins” (extensions of the jQuery library). Like my Print Any Web Parts code, you can create a jQuery method by using jQuery.prototype. or the pseudonym, jQuery.fn.<method name>.

jQuery.fn.<method name>= function(options){…

JQuery is all about “Find Something and Do Something With It.” Most jQuery plugins look like the line above because they want access to this, the array of DOM elements returned by the selector, $(”<selector>”) = “find something.”

However, if you don’t need this (because you’re going to “do something” without the DOM) you can create another object and use it to extend jQuery. The original jquery-AOP code follows this second pattern. jQuery aop is not a method with access to this. The first line looks something like:

jQuery.aop = {
after : function(pointcut, advice)

I bolded the curly brace to emphasize that aop is an object (using the object literal notation) with parameters (stuff before a “:”) to define the methods.

A lot of modern JavaScript will follow one of these less-obtrusive patterns because it does not litter the global namespace.

What Are You Talking About Global Namespace?

Load up one of your SP pages in Firefox. Open the console window and type “window” then click Run. It will return the window object on the left-hand side. Now click window.

You will see a lot of stuff appear on the left side of Firebug. It starts off naming the global variables. These are variables that some SharePoint JavaScript created and couldn’t keep to itself. I counted over 400! After that, you’ll see global functions (methods attached to the window object). There are over 700 global methods! That’s your global namespace in SharePoint, and it’s sort of a mess.

At a minimum, this can raise the risk for namespace collisions, where functions or variables try to have the same name and end up overwriting one another–a very important consideration when you start mashing up various solutions from different authors.

A messy global namespace also obscures how code works because developers will avoid names like init() for a function because it’s probably already used while init() offers the best intuitive description of what the function does.

Before Modifying AOP

In my loadTip-AOP example, I had to use the .around() method to access the original function’s arguments, write the important arguments to the jQuery .data() cache then use the .after() method to retrieve the data and perform our custom function.

It works fine, but it lacks elegance. It’s logically cumbersome.

A Sleak, Trim AOP

Once I tapped into how AOP worked (not an easy feat for my little brain), I was able to pass the arguments (the stuff between the parentheses of the initial function invocation, e.g., ExpGroupRenderData(argument[0],argument[1],argument[2]) ) to my custom function using just one method, .after().

First, I removed everything I did not need from the original AOP code. Then I changed the return for the weave() function to include [arguments].

<script type="text/javascript">
(function(){
	var weave = function(source, method, advice){
		var old = source[method];
		var aspect = function() {
			old.apply(this, arguments);
			return advice.value.apply(this, [arguments]);
		};
		source[method] = aspect;
		return aspect;
	};
	jQuery.aop = {
		after : function(pointcut, advice){
			var source = (typeof(pointcut.target.prototype) != 'undefined') ? pointcut.target.prototype : pointcut.target;
			return weave(source, pointcut.method, { value: advice });
		}
	};
})();
$(function(){ //call a custom function after ExpGroupRenderData using the original arguments
	$.aop.after({target:window,method:"ExpGroupRenderData"}, function(args){
		if (args[2]=='true'){__custom_function__("#tbod"+args[1]+"_");}
	});
});
</script>

As you can tell from the last couple of lines, I still use the same notation to call AOP and weave my custom function, $.aop.after({target:…,method:”some_function”}, my_callback_function(){…});

What changed is that .after() now returns the arguments ExpGroupRenderData was passed when first called. In this case, I’m interested in args[2], “isLoaded” and args[1], “groupName.” (See the original SP code on line 1816 of init.js: function ExpGroupRenderData(htmlToRender, groupName, isLoaded)…)

Note: Since weave is a private variable within a closure, only aop has access to it. Typing “weave” in the console will tell you that “weave is not defined” while typing “aop” in the console will return an object with one method, after.

Why We Like IKEA

IKEA’s furniture is modular. If you buy one end table you have an end table. If you buy two end tables, you can either have two end tables or you can stack them to make a small bookshelf. Or stack 3 bookshelves to make an entertainment center. “Stackable” stuff makes it easier to configure for your particular needs.

A lot of people like this approach and have started websites like IKEA hacker to share their ideas. The ability to create something new from bits and pieces of something else makes IKEA popular. Sometimes the creativity unleashed by the modular approach allows for the creation of something novel.

Sticking with AOP means my solutions will be more modular, more like IKEA furniture. You should be able to mix, match, and stack the solutions in a variety of configurations to achieve your personal goals. With this latest bit of revision, I just made it more elegant. Instead of holding our bookshelves together with duct tape, they fit together naturally.

Paul Grenier

View all entries in this series: PaulGrenier-JQuery for Everyone»
Entries in this series:
  1. JQuery for Everyone: Accordion Left Nav
  2. JQuery for Everyone: Print (Any) Web Part
  3. JQuery for Everyone: HTML Calculated Column
  4. JQuery for Everyone: Dressing-up Links Pt1
  5. JQuery for Everyone: Dressing-up Links Pt2
  6. JQuery for Everyone: Dressing-up Links Pt3
  7. JQuery for Everyone: Cleaning Windows Pt1
  8. JQuery for Everyone: Cleaning Windows Pt2
  9. JQuery for Everyone: Fixing the Gantt View
  10. JQuery for Everyone: Dynamically Sizing Excel Web Parts
  11. JQuery for Everyone: Manually Resizing Web Parts
  12. JQuery for Everyone: Total Calculated Columns
  13. JQuery for Everyone: Total of Time Differences
  14. JQuery for Everyone: Fixing Configured Web Part Height
  15. JQuery for Everyone: Expand/Collapse All Groups
  16. JQuery for Everyone: Preview Pane for Multiple Lists
  17. JQuery for Everyone: Preview Pane for Calendar View
  18. JQuery for Everyone: Degrading Dynamic Script Loader
  19. JQuery for Everyone: Force Checkout
  20. JQuery for Everyone: Replacing [Today]
  21. JQuery for Everyone: Whether They Want It Or Not
  22. JQuery for Everyone: Linking the Attachment Icon
  23. JQuery for Everyone: Aspect-Oriented Programming with jQuery
  24. JQuery for Everyone: AOP in Action - loadTip Gone Wild
  25. JQuery for Everyone: Wiki Outbound Links
  26. JQuery for Everyone: Collapse Text in List View
  27. JQuery for Everyone: AOP in Action - Clone List Header
  28. JQuery for Everyone: $.grep and calcHTML Revisited
  29. JQuery for Everyone: Evolution of the Preview
  30. JQuery for Everyone: Create a Client-Side Object Model
  31. JQuery for Everyone: Print (Any) Web Part(s) Plugin
  32. JQuery for Everyone: Minimal AOP and Elegant Modularity
  33. JQuery for Everyone: Cookies and Plugins
  34. JQuery for Everyone: Live Events vs. AOP
  35. JQuery for Everyone: Live Preview Pane
  36. JQuery for Everyone: Pre-populate Form Fields
  37. JQuery for Everyone: Get XML List Data with OWSSVR.DLL (RPC)
  38. Use Firebug in IE
  39. JQuery for Everyone: Extending OWS API for Calculated Columns
  40. JQuery for Everyone: Accordion Left-nav with Cookies Speed Test
  41. JQuery for Everyone: Email a List of People with OWS
  42. JQuery for Everyone: Faster than Document.Ready
  43. jQuery for Everyone: Collapse or Prepopulate Form Fields
  44. jQuery for Everyone: Hourly Summary Web Part
  45. jQuery for Everyone: "Read More..." On a Blog Site
  46. jQuery for Everyone: Slick Speed Test
  47. jQuery for Everyone: The SharePoint Game Changer
  48. JQuery For Everyone: Live LoadTip
 

Please Join the Discussion

One Response to “JQuery for Everyone: Minimal AOP and Elegant Modularity”

Trackbacks

Check out what others are saying about this post...
  1. SharePoint Daily for April 8, 2009…

    Top News Stories How Collaboration Tools Bring Cost Savings, Business Alignment (Search CIO-Midmarket…




Notify me of comments to this article:


Speak and you will be heard.

We check comments hourly.
If you want a pic to show with your comment, go get a gravatar!