1,804 articles and 14,876 comments as of Saturday, May 14th, 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
Monday, February 16, 2009

JQuery for Everyone: AOP in Action – loadTip Gone Wild

As George pointed out, I need a use case for the Aspect-Oriented Programming (AOP) technique. So, this article mashes up my previous work on a tool-tip-styled, AJAX-powered pop-up with AOP. While more complicated in design than the original loadTip or docTip code, this version has the most potential and should prove easier to modify.

As a beta version, this code comes fully commented with no warranty. Do with it what you will. My personal plans for this code involve the JSON loader and a very happy Content Editor Web Part.

What It Does:

loadTip allows someone with Edit access to a SharePoint page to create a dynamic tool tip that previews display form content. Some possibilities include user information, document metadata, and list item metadata.

As suggested by one of our workshop attendees, loadTip also does a better job of exposing the attachments of a list item without clicking the item.

What It Can’t Do:

loadTip can’t preview documents. loadTip can’t (for now) preview anything inside an Excel Web Access Web Part (EWA). loadTip doesn’t impress the ladies–unless they’re SharePoint end users.

What’s New (features):

Obviously, this version can create a pop-up for documents or items (or other stuff if you rolled your own web part).

I created some default behaviors with the ability to set some of your own parameters. The parameters are:

  • keyword – the link text to search for
  • group – the container the links are located in (defaults to the main content div)
  • delay – how long to delay until starting an AJAX load (default .5 second)

loadTip now looks at where it falls on the screen to decide whether it will open left, right, above, or below the target element. It should help avoid scrolling to see loadTip’s content.

 

What’s New (geeky stuff):

This version of the code has comments–like a ton of comments. Hopefully, anyone learning jQuery can follow it. Also, I hope anyone who has mastered jQuery can improve on it.

I used jquery-AOP to trigger events dynamically after ExpGroupRenderData renders new HTML on the page. Because we’re using AOP and adding advices dynamically, there is no need to change the ExpGroupRenderData function if you add your own “instance” of loadTip–just fire off another initializer (e.g., initLoadTip(”coolstuff”,”inhere”,”2000″)).

Because the AOP script is not hosted publicly (like jQuery), I included it below. This makes it easier to copy-paste and test on your own server. This, however, is not recommended for production environments. You should, at a minimum, remove that code and point to a local version of the file, like this:

<script type="text/javascript">
if(typeof $.aop=="undefined"){
	var aopPath="/path_to_my_javascript_files/";
	document.write("<script src='",aopPath,"aop.js' type='text/javascript'><\/script>");
</script>

I now do more validation to avoid multiple bindings of events to a single element. I use multiple instances of the initialization script so there can be multiple ways to use loadTip on the same page without conflict. There are three examples of this in the code below.

<script type="text/javascript">
//check if jQuery already exists
if(typeof jQuery=="undefined"){
	//set the path to the jQuery library to use
	var jQPath="http://ajax.googleapis.com/ajax/libs/jquery/1.3.1/";
	//add the reference to the page and evaluate

	document.write("<script src='",jQPath,"jquery.min.js' type='text/javascript'><\/script>");
}
</script>
<script type="text/javascript">
/*
* jQuery AOP - jQuery plugin to add features of aspect-oriented programming (AOP) to jQuery.
* http://jquery-aop.googlecode.com/
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/mit-license.php
*
* Version: 1.1
*/

//check if AOP already exists
if(typeof $.aop=="undefined"){
	(function(){var E=1;var B=2;var G=3;var C=4;var F=true;var A=function(K,L,J){var H=K[L];var I;if(J.type==E){I=function(){var M=H.apply(this,arguments);return J.value.apply(this,[M,L])}}else{if(J.type==B){I=function(){J.value.apply(this,[arguments,L]);return H.apply(this,arguments)}}else{if(J.type==C){I=function(){return J.value.apply(this,arguments)}}else{if(J.type==G){I=function(){var M={object:this,args:arguments};return J.value.apply(M.object,[{arguments:M.args,method:L,proceed:function(){return H.apply(M.object,M.args)}}])}}}}}I.unweave=function(){K[L]=H;pointcut=K=I=H=null};K[L]=I;return I};var D=function(I,H){var K=(typeof (I.target.prototype)!="undefined")?I.target.prototype:I.target;var J=[];if(H.type!=C&&typeof (K[I.method])=="undefined"){for(var L in K){if(K[L]!=null&&K[L] instanceof Function&&L.match(I.method)){J[J.length]=A(K,L,H)}}if(J.length==0){throw"No method: "+I.method}}else{J[0]=A(K,I.method,H)}return F?J:J[0]};jQuery.aop={after:function(I,H){return D(I,{type:E,value:H})},before:function(I,H){return D(I,{type:B,value:H})},around:function(I,H){return D(I,{type:G,value:H})},introduction:function(I,H){return D(I,{type:C,value:H})},setup:function(H){F=H.regexMatch}}})();
}
</script>
<script type="text/javascript">
/*
 * Copyright (c) 2008 Paul Grenier (endusersharepoint.com)
 * Licensed under the MIT (MIT-LICENSE.txt)
 */

//function to handle error in IE
function handleError(){
	return true;
}
//global variable for the loadTip container
var loadTip;
//global variable for AOP after advices
var advicesAfter=new Array();
//function to create the loadTip container
function createLoadTip(){
	var html="<span>click to close </span>"
				+"<img style='vertical-align:text-top;' "
				+"src='/_layouts/images/menudark.gif' alt=''/>";
	//set loadTip
	loadTip=$(document.createElement("div")).attr("id","loadTip")
				.html(html).appendTo("body");
	//create content area
	$(document.createElement("div")).attr("id","tipContent")
				.appendTo("#loadTip");
	//set AOP advice to get data from ExpGroupRenderData
	//arguments(htmlToRender[0], groupName[1], isLoaded[2])
	$.aop.around({target:window,method:"ExpGroupRenderData"},
		function(invocation){
			if (invocation.arguments[2]=="true"){
				var group="#tbod"+invocation.arguments[1]+"_";
				//set groupName data to loadTip
				$.data(loadTip[0],"groupName",group);
			}
			return invocation.proceed();
		}
	);
}
//function to bind events to elements
function loadTipEvent(e,a,delay){
	//add target data to element
	$.data(e,"dispTarget",a);
	//bind mouseenter event
	$(e).mouseenter(function(event){
		//create position variables
		var x = event.pageX+10;
		var winx = $(window).width();
		var y = event.pageY;
		var winy = $(window).height();
		var ly;
		var lx;
		//set loadTip out of window
		//height fix 2009-02-17: pg (1/3)
		loadTip.css({"top":-1000, "left":-1000, "height":""});
		//check to see if this target was already loaded
		if($.data(loadTip[0],"dispTarget")&&$.data(loadTip[0],"dispTarget")==$.data(e,"dispTarget")){
			ly = loadTip.height();
			lx = loadTip.width();
			//if the box would run off the page, adjust position
			if (ly+y > winy) y=y-ly-10;
			if (lx+x > winx) x=x-lx-20;
			//part of height fix for big boxes 2009-02-17: pg (2/3)
			if (y < 0) y=0;
			if (ly > winy) loadTip.css({"overflow-y":"auto","height":winy});
			//show loadTip
			loadTip.css({"top":y, "left":x}).show();
		}else{
			//if a timer was started, stop
			if(loadTip.timer)clearTimeout(loadTip.timer);
			//start the delay timer for a data load
			loadTip.timer = setTimeout(function(){
				//&Force=1 prevents redirection on mysites, other pages ignore
				//load ms-formtable into content area
				$("#tipContent").load(a+"&Force=1 .ms-formtable", function(){
					//after data loads, remove width attributes from tds
					loadTip.find("td").removeAttr("width");
					ly = loadTip.height();
					lx = loadTip.width();
					//if the box would run off the page, adjust position
					if (ly+y > winy) y=y-ly-10;
					if (lx+x > winx) x=x-lx-20;
					//part of height fix for big boxes 2009-02-17: pg (3/3)
					if (y < 0) y=0;
					if (ly > winy) loadTip.css({"overflow-y":"auto","height":winy});
					//the following line supports calcHTML columns 2009-03-03: pg (1/2)
					$("#tipContent td[id='SPFieldCalculated']").each(function(){$(this).html($(this).text())});
					//show loadTip
					loadTip.css({"top":y, "left":x}).show();
					//add target data to loadTip
					$.data(loadTip[0],"dispTarget",a);
				});
			},delay);
		}
	});
	//bind mouseleave event
	$(e).mouseleave(function(event){
		if(loadTip.timer)clearTimeout(loadTip.timer);
	});
	//set loadTip to close when clicked
	loadTip.click(function(){
		loadTip.hide();
	});
}
//function to find elements
function initLoadTip(keyword,group,delay){
	//if the loadTip box does not exist, create it
	if(typeof loadTip=="undefined")createLoadTip();
	//use the main content zone as default
	if(!group)group="#MSO_ContentTable";
	//set a default delay for data loads
	if(!delay)delay=500;
	//if no keyword, find links to documents
	//requires change of view on some OOB web parts
	if(!keyword)keyword="initDocs";
	//for documents...
	if(keyword=="initDocs"){
		//find tables with dref and no inner links pointing to the DispForm
		//this prevents double binding
		var arrayList=$(group+" table[dref]:not(:has(a[href*='DispForm']))");
		$.each(arrayList,function(i,e){
			//build a link to the DispForm
			var a="/"+escapeProperly($(e).attr("dref"))
					+"/Forms/DispForm.aspx?ID="
					+$(e).attr("id");
			//find the link to the document
			var e=$(e).find("a");
			//if this link has no dispTarget data
			//prevents multiple bindings
			if (!($.data(e,"dispTarget"))){
				//bind events
				loadTipEvent(e,a,delay);
			}
		});
	}else{
		//find elements matching keyword in the link
		var arrayList=$(group+" a[href*='"+keyword+"']");
		$.each(arrayList,function(i,e){
			//remove any bookmarks from the link
			var a=$(e).attr("href").split("#")[0];
			//if this link has no dispTarget data
			//prevents multiple bindings
			if(!($.data(e,"dispTarget"))){
				//bind events
				loadTipEvent(e,a,delay);
			}
		});
	}
	//check the advices array to see if an advice was loaded for that keyword
	if ($.inArray(keyword,advicesAfter)==-1){
		//add the keyword to the advices array
		advicesAfter.push(keyword);
		//create an advice after ExpGroupRenderData
		$.aop.after({target:window,method:"ExpGroupRenderData"},
		  function(){
			//get the groupName data from loadTip
			var group=$.data(loadTip[0],"groupName");
			//if loadTip has groupName data, reinitialize elements for that keyword
			//after ExpGroupRenderData renders new html
			//loaded by expanding a group
			if(group)initLoadTip(keyword,group,delay);
		  }
		);
	}
}
$(function(){
	//handle the first error in IE
	window.onerror=handleError;
	//example of loadTip with links to DispForm,aspx (the keyword)
	//using the default content zone with 1 second delay
	initLoadTip("DispForm.aspx","",1000);
	//example of loadTip with userdisp (the keyword)
	////using the default content zone and default .5 second delay
	initLoadTip("userdisp");
	//example of loadTip for documents using defaults
	initLoadTip();
});
</script>
<!-- loadTip CSS -->
<style type="text/css">
#loadTip{
    background: #6F9DD9;
	color: #fff;
    border: 2px solid #6F9DD9;
    font-size: 10px;
    padding: 3px;
    width: 342px;
	display: none;
	position: absolute;
	text-align: right;
}
#tipContent {
	background: #fff;
	padding: 3px;
}
</style>

UPDATE: 2009-02-17

I fixed an issue Peter noticed with a small ratio of loadTip height to window height. The new behavior makes the top of the window the highest point the box will appear at and adds a scroll bar to the box if the box is larger than the window.

UPDATE: 2009-03-03

I updated this script to render calcHTML columns (see HTML Calculated Column and jQuery calcHTML

UPDATE: 2009-03-09

With more testing I noticed that the calculated column will “reprocess” when displaying but not loading. This caused some HTML to disappear so it was removed from the script and now only processes when new data loads.

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

85 Responses to “JQuery for Everyone: AOP in Action – loadTip Gone Wild”
  1. AutoSponge says:

    @Marc,

    I have a “live events” version of this script that is not published right now. That might solve the problem. It’s a lot more compact than the AOP version, so I’ll try to get around to providing that.

  2. MarcMoe says:

    Hello,

    thank you for the information. i will try the “live events” version when it is published

  3. DavidD says:

    Great work! This tool helped me work around the relational DB shortcomings of OOB Sharepoint lists using data connections and lookup columns on a web part page. Result: dashboard info and quasi-rollup available at the bottom level.

    It would be nice to be able to use this utility in reverse (by looking downward in the information hierarchy i.e. being able to view details of aggregated data): Any plans afoot or there any way to extend this utility to Sharepoint’s OOB CQWP?

  4. Timmy says:

    How do I go about changing the location of where the pop-up opens? Currently, when I hover over a list item, i open to the close-right of the cursor, which is blocking my document names (depending on where you hover). I would like to move the pop-up to the far right for example, but how?

  5. AutoSponge says:

    @Timmy,

    In the code you see this line: var x = event.pageX+10;
    and this line: var y = event.pageY;

    If you change what gets added or subtracted you will move the box’s pop-up location along the given axis. For instance, to move the box further to the right by 10 pixels, change event.pageX+10 to event.pageX+20.

  6. Robin says:

    Paul,

    Do you plan to update this to work with aop 1.2?

    As usual great post!

  7. Rifter1 says:

    I was able to edit the fields that show up in the hover menu.

    a) In SPD, open the DispForm.aspx file
    b) Insert a new SharePoint Control “Custom List Form”
    c) Close the original form (do not delete it)
    d) Edit the fields however you want
    e) THIS IS THE KEY: The custom SharePoint Control tag in the code will not have a “Class” tag

    ie:

    Change this line to read:

    Now the hover menu will only show the fields you want.

    Thanks to the previous posters for getting me on the right track, this is perfect for our needs.

  8. Rifter1 says:

    The previous post didn’t show up quite right. All you have to do is add a “class=ms-formtable” to the table tag. Then it works.

  9. AutoSponge says:

    @Robin,

    I didn’t know there was another release, thanks!

  10. Rifter1 says:

    Question: I’m using this in a Document Library. When the user points at a file, it shows a “Description” field and a “Trainer guide” link (which is only accessible to trainers). At the bottom of the tool tip I have an email link for users to submit comments/errors regarding the file they are currently pointing at.

    What I want to do is add the name of the file to the subject line of the email.

    Is there a way to determine the text of the hyperlink the mouse is pointing at, and add it to a mailto: href?

  11. Timmy says:

    @ Autosponge

    “AutoSponge on October 8th, 2009 3:53 pm
    @Timmy,

    In the code you see this line: var x = event.pageX+10;
    and this line: var y = event.pageY;

    If you change what gets added or subtracted you will move the box’s pop-up location along the given axis. For instance, to move the box further to the right by 10 pixels, change event.pageX+10 to event.pageX+20.”

    I have even tried setting x=150 and the window still isn’t budging. Also cleared local cache and iisreset on server. Any ideas?

  12. Timmy says:

    Almost forgot – is there a new LoadTip webpart that is required for this new script to work as well? Currently I am calling loadtip.js from my masterpage (thus applying to all sites) and have the LoadTip web part loaded on the pages that I want the popup on.

  13. AutoSponge says:

    @Timmy,

    That’s really the way to change the x/y coordinates. I just tested again to make sure:

    ...
    	$(e).mouseenter(function(event){
    		//create position variables
    		var x = event.pageX+50;
    		var winx = $(window).width();
    		var y = event.pageY;
    ...
    

    However, that also shifts the box to the right if you have a link near the right edge. To make a drastic change to this number, you may need to play with the calculations later in the function as well.

  14. Chaz says:

    Great scripting! Couple of basic questions (sorry).

    You mention pulling out the aop.js script. I don’t see that script in the code – how do I do that?

    If I want to limit the fields displayed in the tool tip, where would I insert the code to filter for fields I don’t want displayed? Would those field names be the SP display or internal names?

    Sorry again for the really basic questions.

  15. AutoSponge says:

    @Chaz,

    AOP objects live outside of this code in a separate file. I recommend they stay that way. You don’t need to do anything.

    This script does not have a way for you to reduce the html coming from the target page. Instead, you would have to develop your own solution or change the target to a page that only shows certain fields (a custom display form). Either one will be a challenge.

  16. Chaz says:

    Thanks – but I’m a bit confused now. I understand that AOP is outside your code, and up above you say:

    “Because the AOP script is not hosted publicly (like jQuery), I included it below. This makes it easier to copy-paste and test on your own server. This, however, is not recommended for production environments. You should, at a minimum, remove that code and point to a local version of the file, like this:”

    Since I’m looking to use your code on a production server, I’m confused when you said in your reply that I don’t need to do anything re AOP – that seems to contradict what you said in your post.

    So my question re AOP is: on a production server, should I just go ahead and use your code as is, or should I change the line under “if(typeof $.aop==”undefined”){” to point to a local copy of the AOP file(s)?

    Related to that: when I downloaded AOP from http://jquery-aop.googlecode.com/ the zip file didn’t include “aop.js”.

    When I tried to follow the example you gave above about pointing to the AOP files I downloaded, your code didn’t work for me. It only works when I use it as posted above.

    Thanks again!

  17. AutoSponge says:

    @Chaz,

    Sorry for the confusion. There are two contradicting schools of thought here and I’ve gone back and forth on it.

    On the one hand, separating the files means that you can maintain them separately and the user can cache it. If you use AOP elsewhere, you don’t need to include it again and the user likely already has it cached. You could also upgrade AOP separately (I did not test this).

    On the other hand, combining (and minifying) files will lead to better performance (when it’s not cached) since the browser does not have to stop processing to download another file.

    So, I think it’s up to you. AOP is very small, so the benefits to breaking it out are mostly about code management.

    If you break it out, make sure you put the AOP reference in its own script tag, just like the example above (and change the directory to match yours). If you leave it as is, the world will not stop on its axis.

  18. John says:

    Paul,

    I am desperately looking to implement this,but unfortunately I am not gettig. I have one document library and I am adding CEWP on top of it. Copying the above code and pasting in the web part. But I dont see the functionality getting implemented. Please let me know if I am missing anything.

    NOTE: Do we also need to add the following with the code:

    if(typeof $.aop==”undefined”){
    var aopPath=”/path_to_my_javascript_files/”;
    document.write(”");

    I appreciate your response.

  19. AutoSponge says:

    @John,

    I’ll publish the latest code tonight which uses live events instead of AOP. Perhaps that will help.

  20. John says:

    Thanks Paul, for your prompt response. I am really looking forward to implement this.

    Thanks
    John

  21. Timmy says:

    Is there any way possible to not have the popup open off screen? I have some list items with a lot of info in them that make the box rather large, and you have to scroll down to see the entire box.

  22. AutoSponge says:

    @Timmy,

    See the newer loadTip Live. It should do what you want.

  23. Timmy says:

    Where is the newer LoadTip Live located? Please link me if possible.

    THANKS!!!

  24. James says:

    Hello -

    Great tool. Question, can this be used on viewpost as well?

    I have some blogs that I would like to use the LoadTip Live on but posts don’t have displayform they used viewpost.

    Can I just simply change all instances of displayform with viewpost?

    Thanks.

  25. Gus says:

    Hi, we have several lists that don’t use DispForm.aspx as its primary form for displaying data, so I’ve tried making the LoadTip target a different .aspx file, however, unsuccessfully. Can’t you hardcode it to target a different form?

  26. AutoSponge says:

    @Gus,

    You will need to change line 149 to fit the link you’re pointing to. You may (or may not) need to change the way you invoke the tip (line 196). If you did not change the default display page to your custom page, you don’t need to change it, otherwise it should match your links on the page. Use the middle parameter on line 196 to use your custom page’s content zone. Find the div that holds your data and use its name (use CSS-style identifier like I did for #MSO_ContentTable).

  27. Patrick says:

    I really like this ToolTip but can’t it work if the list is not on the same subsites .
    Can it work using webservice?
    Thanks

  28. Mike Smith says:

    Hi
    how do I get hold of only the attachments filename?

    Best Regards Mike

  29. Tony says:

    Hi, finally got this to work after trying all sorts. For some reason in my enviroment it would only work when I created a list view that contained a grouped by field.

  30. Vincent Stackhouse says:

    Paul,

    This is brilliant! Especially your latest coding and validations.

    I have been reading and trying each version and this one seems to do everything we need and thensome for any of our list types.

    Keep up the great work,.

  31. Lisa Davis says:

    Hi. My supervisor loves this and really wants to use it on our site. The problem is, we need to restrict what can be seen in the box. We still need to have all the columns visible and in the same order so people can fill out the list, but we’d like to trim it down from 10 columns showing to just 4. It is just too much to show. Thanks for any help you can give me.

    Regards
    Lisa

  32. John says:

    I really like the LoadTip Live and am using it to display the Editform.aspx on our Lists. Is there a way to show the OOB “OK” and “cancel” buttons at the bottom of the pop-over form?

    Thanks in advance !

  33. Lisa Davis says:

    Sorry to be a bother. I was just wondering if anyone knew how to hide certain field in the pop up window. There’s a lot of info in the box and it would be better if we could take out / hide half of them. Thanks for any help you may provide.

Trackbacks

Check out what others are saying about this post...
  1. [...] But if you haven’t had a chance to attend the online workshop, this example code replaces the AOP LoadTip [...]

  2. [...] a little research, AOP could help make the solution clean and simple. This time, like my last AOP article, I needed data from a SharePoint function when called. In this case, I want to key on the call to [...]




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!