Showing which list items have tags or notes in SharePoint 2010

One of the great areas of functionality added in SharePoint 2010 is Social Feedback – the ability for users to add tags and notes to content as part of the managed metadata service. As has been discussed many times this is a fantastic feature to increase the classification of content and the overall findability of content. The out-of-the-box My Site includes some great features such as the Activity Feed and the Tag Cloud to help surface some of the information captured by tags and notes – and it works really well. One question that was put to me in a recent engagement however was:

How do I see which items in a list or library have tags and notes?

Without selecting each individual item and viewing the tags and notes dialog for each it seems that it’s just not possible. I won’t go into the long discussions we had about the different ways we could surface both the tags and notes information and the context of that information – but I will show you this screenshot of a library which adds a Tags And Notes Column so that at a glance it’s possible to see which items have tags or notes.

Tags And Notes Column

The steps to recreate this for a document library are:

  1. Create a new column on a library named Tags And Notes
    1. The type isn’t actually important, but I used a simple text field
  2. Add a web part to a page, e.g. your Team Site home page, and then modify the view to include the newly added column
  3. Upload the script (found below) into a suitable location, e.g. the Site Assets library
  4. Reference the script in a Content Editor Web Part (CEWP) added to the page

How It Works
What is happening here, is that the CEWP is loading both jQuery and my custom script on a page (the jQuery could/ should obviously be local). The script then goes away and looks for a table on the page that includes a TH cell with the text Tags And Notes in it. If it finds one it goes through each row and puts in the icon for tags and notes into the last column.

Then, it takes the URL of the item in the title column and passes that through to a function which makes a SOAP request to the SharePoint web services to get any tags on that specific URL. The success method then either repeats the process to find comments (if it found no tags) or simply swaps out the source for the tags and notes icon with the source for a has tags and notes icon.

Next steps and Limitations
I’m fairly happy with the result that this script and technique gives, although there are some nagging annoyances. Whilst investigating this I tried to repeat the same behaviour as the Tags And Notes icon found in the ribbon, i.e. it would be nice to be able to click on the icons and view/ add tags and notes for the individual items. Unfortunately I found that by adding in the functions to open up the dialog with multiple instances on a page it would always refer to the first item clicked. I tried various things here like giving unique identifiers but with no success. I’m still looking into this as this is what I’d really like it to do!

Also, I think there’s something in the way that I’m referencing my scripts that is resulting in a javascript error. I’m trying to track this down. No doubt the code could be tidied up in general too, such as by adding a function for the on error event of the ajax call etc.

In terms of next steps this would obviously be a bit of a pain to repeat many times across an environment and so I would be looking to create a custom site column that could simply be added to a list or library to replicate this behaviour. That step may be a bit beyond my basic coding skills though 🙂

The Script
Here is the script I used. Hopefully the comments are sufficient to make this readable:

var ctrlCount = 100;

$(document).ready(function() {
	// When sp.js is loaded run our function to call the web service
	ExecuteOrDelayUntilScriptLoaded(FindTagsAndNotes(), 'sp.js');	
});

function FindTagsAndNotes() {
	var strUrl;
	// find table with th div displayname Tags and Notes, and loop through each row of that table
	$('table tbody tr th div[displayname=\"Tags And Notes\"]').closest('tr').siblings().each(function() {
			// Grab the url from the title column
			strUrl = location.protocol + '//' + location.hostname + $(this).find('td.ms-vb-title div a').attr('href');
			
			// Output the tags and notes icon image into the last column
			$(this).children('td:last').html(OutputTagsAndNotesImage('social_tag_ctrl' + ctrlCount));

			// Use the web service to find tags and notes on this url
			FindTagsAndNotesOnUrl(strUrl, $(this).children('td:last'));
			ctrlCount ++;
		});
}

function FindTagsAndNotesOnUrl(strUrl, tblCell) {
	// Use the web service to initially find tags
	CallService(strUrl, tblCell, 'tag');
}

function CallService(strUrl, tblCell, strTagOrComment) {
	var webMethod;
	var soapEnv;
	if (strTagOrComment == 'tag') {
		webMethod = '/_vti_bin/SocialDataService.asmx?op=GetTagTermsOnUrl';
		soapEnv = "<soap:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' \
						xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'> \
							<soap:Body>	\
								<GetTagTermsOnUrl xmlns='http://microsoft.com/webservices/SharePointPortalServer/SocialDataService'> \
									<url>" + strUrl + "</url> \
									<maximumItemsToReturn>1</maximumItemsToReturn> \
								</GetTagTermsOnUrl> \
							</soap:Body> \
						</soap:Envelope>";
	}
	else {
		webMethod = '/_vti_bin/SocialDataService.asmx?op=CountCommentsOnUrl';
			var soapEnv = "<soap:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' \
					xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'> \
  						<soap:Body>	\
   							<CountCommentsOnUrl xmlns='http://microsoft.com/webservices/SharePointPortalServer/SocialDataService'> \
								<url>" + strUrl + "</url> \
							</CountCommentsOnUrl> \
						</soap:Body> \
					</soap:Envelope>";
	}
	
	$.ajax({
		type: "POST",
		async: true,
		url: webMethod,
		data: soapEnv,
		contentType: "text/xml; charset=utf-8",
		dataType: "xml",
		success: function(data, textStatus, XMLHttpRequest) {
					proccessTagsAndNotes(data, textStatus, XMLHttpRequest, strUrl, tblCell, strTagOrComment); 
		}
	});
}

function proccessTagsAndNotes(data, textStatus, XMLHttpRequest, strUrl, tblCell, strTagOrComment) {
	var count = 0;
	if (strTagOrComment == 'tag') {
		count = $('SocialTermDetail', data).find('Count').text();
		if (count < 1) {
			// No tags found so search for comments
			CallService(strUrl, tblCell, 'comment');	
		}
		else {
			// Tags found so swap out the icon
			$('img', tblCell).attr('src','/_layouts/images/SocialTagsAndNotesHas_24.png');
		}
	}
	else {
		count = $('CountCommentsOnUrlResponse', data).find('CountCommentsOnUrlResult').text();
		if (count > 0) {
			// Comments found so swap out the icon
			$('img', tblCell).attr('src','/_layouts/images/SocialTagsAndNotesHas_24.png');
		}
		else {
			// Not found any tags or notes, so do nothing...
		}
	}
}

function OutputTagsAndNotesImage(ctrlId) {
	var htmlOut = "<div class=\"ms-mini-socialNotif-Container\" style=\"padding-left:31px;\"> \
						<a class=\"ms-mini-socialNotif\" \
							id=\"TagsAndNotes_" + ctrlId + "\" \
							href=\"javascript:;\" \
							title=\"Tags help you remember links and classify the page.  Notes are public comments.  Tags and notes post to your news feed and work across different sites.\"> \
							<span> \
								<span> \
									<img style=\"border: 0\" \
										id=\"TagsAndNotesImg_" + ctrlId + "\" \
										alt=\"Tags help you remember links and classify the page.  Notes are public comments.  Tags and notes post to your news feed and work across different sites.\" \
										src=\"/_layouts/images/SocialTagsAndNotes_24.png\" /> \
								</span> \
							</span> \
						</a> \
					</div>";
	return htmlOut;
}

And the contents of the CEWP to register the script:

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript" src="/SiteAssets/jquerysocialdata.js"></script>
share and enjoy
  • Print
  • Twitter
  • Digg
  • del.icio.us
  • StumbleUpon
  • Yahoo! Buzz
  • Google Bookmarks
  • Facebook

23 comments to Showing which list items have tags or notes in SharePoint 2010

Leave a Reply

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>