Tuesday, June 26, 2012

Full Text Search in SharePoint on multiple document libraries using SPServices

A while ago, I needed a way to do a full text search of several SharePoint document libraries and display it in one page in a friendly way. I decided to use SPServices to do my querying and output the results using Javascript.

This script does a full text search on the keywords passed into an input box on the current scope of the site. After getting the query results, it then iterates through each search result and displays only the results where the path matches the list names passed in.

Documents in 2 different libraries:











Search output:














Refined search output:









Steps:
1. Ensure search is configured and working on your site
2. Add this script to a content editor web part on your page (View Code)
3. Update the script tags with the location of SPServices and JQuery on your site
4. Make sure to update the listUrl div with the correct list paths that you would like to restrict the output to









<div id="divSearch">
	<div>
		<b>Search Keyword: </b><br/><input type="text" id="tbSearch" size="50%" />
		<input type="button" id="btnSearch" value="Search Policies" onclick="RunSearch();" />
	</div>
</div>

<div id="divErrorMsg"></div>
<div id="divSearchResults"></div> 
<div id="divTestQueryResult"></div>
<div id="divTestQuery"></div>

<script language="javascript" type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript" language="javascript" src="/policy/SiteAssets/js/jquery.SPServices-0.7.2.min.js"></script>

<script type="text/javascript"> 

//author: sparsee
//DCSharePointchick.blogspot.com
/**configurable**/
var m_searchCap = 5000;
var m_listUrls = "https://site/policy/Procedure;https://site/policy/Policy;https://site/policy/Supplement;";
var m_displayQueryResults = false;
/**************/

var m_searchQueryForList = "";
var m_arrSearchResults = new Array();
var m_searchResultCount = 0;
var m_output = "";

var imgTxt = '<img src="_layouts/images/ictxt.gif" BORDER=0>';
var imgDoc = '<img src="/_layouts/images/icdocx.gif" BORDER=0>';
var imgPdf = '<img src="_layouts/images/pdf16.gif" BORDER=0>';
var imgDefault = '<img src="_layouts/images/STS_ListItem16.gif" BORDER=0>';

$(document).ready( function() 
{
	//get document properties
	var listUrls = m_listUrls;
	listUrls = listUrls.slice(1,listUrls.length);  
	listUrls = listUrls.substring(0, listUrls.length-1); 
	var arrlistUrls = listUrls.split(';');

	for( var y = 0; y < arrlistUrls.length; y++)
	{
		var curUrl = arrlistUrls[y];
		
		if( curUrl != null && curUrl != "" )
		{
			var url = curUrl.toLowerCase();
			if( m_searchQueryForList != "" )
			{
				m_searchQueryForList += "OR CONTAINS(Path, '\""+ url +"*\"')";
			}
			else
			{
				m_searchQueryForList += "CONTAINS(Path, '\""+ url +"*\"')";
			}
		}
	} 
	
	$("#tbSearch").keyup(function(){
		RunSearch();
	});
});


function RunSearch()
{
	$("#divSearchResults").html("Searching...");
	$("#divErrorMsg").html("");
	m_arrSearchResults = new Array();

	var tbSearch = document.getElementById("tbSearch").value; 

	var myQuery = "<QueryPacket xmlns='urn:Microsoft.Search.Query' Revision='1000'>" + 
		"<Query>" + 
		"<Range><Count>" + m_searchCap + "</Count></Range>" +
		"<Context>" +
		"<QueryText language='en-US' type='MSSQLFT'>" +
		"SELECT Title, Rank, Size, Author, HitHighlightedSummary, Description, Path, Write FROM Scope() WHERE FREETEXT('" + tbSearch + "') AND (" + m_searchQueryForList + ") ORDER BY \"Rank\" DESC" +
		"</QueryText>" +
		"</Context>" +
		"</Query>" +
		"</QueryPacket>";


	$().SPServices({
		operation: "Query",
		async: true,
		queryXml: myQuery,
		//debug: true,
		completefunc: function (xData, Status) {

			$("#divSearchResults").html("Searching...");
			$("#divErrorMsg").html("");
			m_arrSearchResults = new Array();


			if (Status != "success") 
			{
				DisplayErrorMesssage(Status);
				return;
			}

			var queryResult = $(xData.responseXML).find("QueryResult").text();

			if( m_displayQueryResults )
			{
				$("#divTestQueryResult").text(queryResult);
				$("#divTestQuery").text("<br/>" + myQuery);
			}
			else
			{
				$("#divTestQueryResult").text("");
				$("#divTestQuery").text("");
			}

			$(xData.responseXML).find("QueryResult").each(function() 
			{  
				var xml = $("<xml>" + $(this).text() + "</xml>");  
				xml.find("Document").each(function() 
				{  
					var curPath = $("Action>LinkUrl", $(this)).text().toLowerCase();  

					var curTitle = "";  
					$(this).find("Property").each(function() 
					{  
						if ($("Name", $(this)).text() == "TITLE") 
						{  
							curTitle = $("Value", $(this)).text(); 
						}  
					});  

					var curHithighlighted = "";
					$(this).find("Property").each(function() 
					{  
						if ($("Name", $(this)).text() == "HITHIGHLIGHTEDSUMMARY") 
						{  
							curHithighlighted = $("Value", $(this)).text(); 
						}  
					});  

					var curWrite = "";
					$(this).find("Property").each(function() 
					{  
						if ($("Name", $(this)).text() == "WRITE") 
						{  
							curWrite = $("Value", $(this)).text(); 
						}  
					});  
		 
					var curAuthor = "";
					$(this).find("Property").each(function() 
					{  
						if ($("Name", $(this)).text() == "AUTHOR") 
						{  
							curAuthor = $("Value", $(this)).text(); 
						}  
					});   
		
					var arrayRows = new Array();
					arrayRows.push([curTitle, curPath, curHithighlighted, curWrite, curAuthor]);

					m_arrSearchResults.push([ curTitle, arrayRows ]);
				});  
			});
			
			PrintOutput();
		}
	});
}

function PrintOutput()
{ 
	m_searchResultCount = 0;
	m_output = '<table class="section-body">';
	
	var tb = document.getElementById("tbSearch").value; 

	for( var x = 0; x < m_arrSearchResults.length; x++ )
	{
		var searchTitle = m_arrSearchResults[x][0];
		var arrayRows = m_arrSearchResults[x][1];

		if( arrayRows.length > 0 )
		{
			var tableID = '"' + x + 'Table"';
			
			m_output += "<tr><td><table id=" + tableID + " class='tablesorter section-table table_summary' width='800px' style='margin-top:0px !important;'>";

			for( var y = 0; y < arrayRows.length; y++)
			{			
				var row = arrayRows[y];
				
				var title = row[0];
				var path = row[1];
				var highlighted = row[2];
				var write = row[3];
				var author = row[4];

				highlighted = GetFormattedHighlightedText(highlighted);
				title = GetHighlightedTitle(title, tb);
				title = GetFormattedTitle(path, title);

				write = GetFriendlyDate(write);

				var highlightedPath = GetHighlightedPath(path, tb);

				m_output += PrintRow(path, title, highlighted, highlightedPath, write, author);
				m_searchResultCount++;  
			}
			
			m_output += "</table></td></tr>";
		}
	}

	var returnedResults = "<br/><span style='color:red'>Showing Results for: <b>" + document.getElementById("tbSearch").value + "</b></span> (Returned: <font color='green'>" + m_searchResultCount + "</font> results)";

	m_output += "</table>";
	m_output = returnedResults + m_output;

	$("#divSearchResults").html(m_output);
}

function PrintRow(path, title, highlighted, highlightedPath, write, author)
{
	var row = '<tr><td><a href="' + path + '" target="_blank">' + title + '</a></td></tr>' + 
	'<tr><td>' + highlighted + '</td></tr>' +
	'<tr><td><a style="color:green;" href="'+ highlightedPath + '">' + highlightedPath +'</a><font color="grey"> - ' + author + ' - ' +  write + '</font></td></tr>';
	
	return row;
}

function GetFormattedTitle(path, title)
{
	if( path.indexOf(".pdf") >= 0 )
		title = imgPdf + title;
	else if( path.indexOf(".doc") >= 0 )
		title = imgDoc + title;
	else if( path.indexOf(".txt") >= 0 )
		title = imgTxt + title;
	else
		title = imgDefault + title;
		
	return title;
}

function GetHighlightedTitle(title, searchText)
{
	if( searchText != "" )
		return highlight(title, searchText);
	else
		return title;
}

function GetHighlightedPath(path, searchText)
{
	if( searchText != "" )
		return highlight(path, searchText);
	else
		return path;
}

function highlight( data, search ) { return data.replace( new RegExp( "(" + preg_quote( search ) + ")" , 'gi' ), "<b>$1</b>" ); } 
function preg_quote( str ) {  return (str+'').replace(/([\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:])/g, "\\$1"); } 


function GetFormattedHighlightedText(highlighted)
{
	if( highlighted != null )
	{
		highlighted = highlighted.replace("<c0>", "<font color='green'><b>");
		highlighted = highlighted.replace("</c0>", "</b></font>");

		highlighted = highlighted.replace("<c1>", "<font color='green'><b>");
		highlighted = highlighted.replace("</c1>", "</b></font>");

		highlighted = highlighted.replace("<c2>", "<font color='green'><b>");
		highlighted = highlighted.replace("</c2>", "</b></font>");

		highlighted = highlighted.replace("<c3>", "<font color='green'><b>");
		highlighted = highlighted.replace("</c3>", "</b></font>");

		highlighted = highlighted.replace("<c4>", "<font color='green'><b>");
		highlighted = highlighted.replace("</c4>", "</b></font>");

		//highlighted = "<i>" + highlighted + "</i>";

		return highlighted;
	}
	return "";
}

function GetFriendlyDate(dateField)
{
	var datetimeparts = dateField.split('T');
	var dateparts = datetimeparts[0].split('-');
	var month = dateparts[1];
	var date = dateparts[2];
	var yr = dateparts[0]

	var formatteddateandtime = month + "/" + date + "/" +  yr ;
	
	return formatteddateandtime;
}

function DisplayErrorMesssage( errorMsg )
{
	$("#divErrorMsg").html("Error occurred. " + errorMsg );
}

function CheckSubmit() 
{
    if (event.keyCode == 13) 
	{
		$("#btnSearch").focus();
    }
}
</script>

1 comment:

  1. The above code is not working in our scenario getting response error message System.Servicemodel.ServerTooBusyException.Please suggest me a solution

    ReplyDelete