Auto Complete/Suggestion in SharePoint 2010 Search Text box with jQuery – Part 2

As I told, here is the second part of the Auto Complete/Suggestion functionality in SharePoint 2010 Search Text box using jQuery. The first post can be found here.

In this blog post I will explain how to attach the auto complete/suggestion functionality to the search text box in the results page of the Search site. Also, we will see how to add the search query into the Search Keywords list so that the suggestion terms need not be added manually by the users. The code implemented here would be used in the search results page.

UPDATE: I have published this application here in CodePlex as well blogged about it briefly over here about the functionality as well as the deployment steps. Check it out if you do not want to get in to the coding side.

I’m going to explain only the modifications that I have done to the code in the previous post.

1. Modify the onQuerySucceeded function as shown below. I have described the code in comments


function onQuerySucceeded(sender, args) {
   listItemEnumerator = collListItem.getEnumerator();
   // declare a bool variable which we will use later
   termPresent = false;
   // get the query string value of key 'k' which has the search query and store in a variable
   // after decoding it
   srchTerm = decodeURI(JSRequest.QueryString["k"]);
   while (listItemEnumerator.moveNext()) {
       oListItem = listItemEnumerator.get_current();

   // check if the value in the Title columns in equal to search query
   // by converting them in to lowercase
   if( oListItem.get_item('Title').toLowerCase() == srchTerm.toLowerCase())
   {
      // if they are equal then change the value of the bool variable to true
      // which means the search query need not be added to the Search Keywords list
      termPresent = true;
   }
   listItemInfo += ',' + oListItem.get_item('Title');
 }

   $(".ms-sbplain").autocomplete({
   source: listItemInfo.split(",")
   });

   // check the value of the bool variable, if it is false then call the createListItem function
   // which will add the list item to the Search Keywords list
  if(termPresent == false)
  {
    createListItem(srchTerm);
  }
 }

2. Create the createListItem function with the below code.

function createListItem(srchTerm)
 {
   // create a new list item to be added in the Search Keywords list
   itemCreateInfo = new SP.ListItemCreationInformation();
   // add the item to the oList which is the Search Keywords list
   this.oListItem = oList.addItem(itemCreateInfo);
   // set the value of the title column of the list item to the search query
   oListItem.set_item('Title', srchTerm);
   // update the the list item
   oListItem.update();
   // load the list item
   clientContext.load(oListItem);
   // declare the delegates to be executed on success and on failure
   clientContext.executeQueryAsync(Function.createDelegate(this, this.onCreateSucceeded), Function.createDelegate(this, this.onQueryFailed));
 }

3. Create an empty onCreateSucceeded function.

function onCreateSucceeded() {
 // just an empty function
 }

Here is the complete code without comments.

<script type="text/javascript" src="/_layouts/SPAutoSuggestion/jquery-1.7.js"></script>
<script type="text/javascript" src="/_layouts/SPAutoSuggestion/jquery.ui.core.js"></script>
<script type="text/javascript" src="/_layouts/SPAutoSuggestion/jquery.ui.widget.js"></script>
<script type="text/javascript" src="/_layouts/SPAutoSuggestion/jquery.ui.position.js"></script>
<script type="text/javascript" src="/_layouts/SPAutoSuggestion/jquery.ui.autocomplete.js"></script>
<link href="/_layouts/SPAutoSuggestion/jquery-ui.CSS" rel="stylesheet" type="text/css" />

<script type="text/javascript">
JSRequest.EnsureSetup();
var clientContext;
var oList;
var camlQuery;
var listItemInfo = '';
var listItemEnumerator;
var termPresent;
var srchTerm;
var oListItem;
var itemCreateInfo;

$(document).ready(function () {
ExecuteOrDelayUntilScriptLoaded(Post_COM_Load, "sp.js");
});

function Post_COM_Load() {
clientContext = new SP.ClientContext.get_current();
oList = clientContext.get_web().get_lists().getByTitle('Search Keywords');

camlQuery = new SP.CamlQuery();
camlQuery.set_viewXml('<View/>');
this.collListItem = oList.getItems(camlQuery);
clientContext.load(collListItem, 'Include(Title)');
clientContext.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded), Function.createDelegate(this, this.onQueryFailed));
}

function onQuerySucceeded(sender, args) {

listItemEnumerator = collListItem.getEnumerator();

termPresent = false;

srchTerm = decodeURI(JSRequest.QueryString["k"]);
while (listItemEnumerator.moveNext()) {
oListItem = listItemEnumerator.get_current();
if( oListItem.get_item('Title').toLowerCase() == srchTerm.toLowerCase())
{
termPresent = true;
}
listItemInfo +=
',' + oListItem.get_item('Title');
}

$(".ms-sbplain").autocomplete({
source: listItemInfo.split(",")
});

if(termPresent == false)
{
createListItem(srchTerm);
}
}

function createListItem(srchTerm)
{
itemCreateInfo = new SP.ListItemCreationInformation();
this.oListItem = oList.addItem(itemCreateInfo);
oListItem.set_item('Title', srchTerm);
oListItem.update();
clientContext.load(oListItem);
clientContext.executeQueryAsync(Function.createDelegate(this, this.onCreateSucceeded), Function.createDelegate(this, this.onQueryFailed));
}

function onCreateSucceeded() {
}

function onQueryFailed(sender, args) {
alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
}
</script>

4. The above code has to be added to a Content Editor Web Part in the results page of your Search site.

5. After you do a search with a query text, for example “Microsoft SharePoint” in your search site.

you can see that the query text has been added in the Search Keywords list as shown below

which would also eventually appear in the suggestions list as you type in your search text boxes as shown below.

Advertisements

Auto Complete/Suggestion in SharePoint 2010 Search Text box with jQuery- Part 1

Can’t get myself out of exploring jQuery in SharePoint. Last week I was working on how to bring in the Google kind of auto suggestion/complete functionality in to SharePoint 2010 Search text box using jQuery. I will be explaining it in 2 parts on how to achieve this functionality.

UPDATE: I have published this application here in CodePlex as well  as blogged about it briefly over here about the functionality as well as the deployment steps. Check it out if you do not want to get in to the coding side.

Part 1: How to give the Auto suggestion/complete functionality to the Search box with search terms retrieved from a SharePoint list. (You shall use the code implemented here if you want to store the search suggestion content in the SharePoint list by yourself)

Part 2: How to store the users’ searched queries to a SharePoint list dynamically and then show them as suggestions in the search box while searching.

Let me cover the first part in this blog post:

I have used jQuery and the jQuery Autocomplete plug-in to show the suggestion in the search text box.

1. Download the jQuery plug-in form here

2. Download the  jQuery UI plug-in from here.

Note: We need only the Autocomplete functionality of the jQuery UI. So you need to have only the following options selected in the list of functionalities shown in the above URL before downloading:

  • Core
  • Widget
  • Mouse
  • Position
  • Autocomplete
  • Menu

3. Create a folder called SPAutoSuggestion in the Layouts folder.

4. Unzip the above download zip files. Copy all the JS files(not the folders) in to the above created folder.

5. Create a Custom list called “Search Keywords” in your SharePoint Enterprise Search centre site and add some list items in to the list with sample keywords that you would like to appear as suggestions in the Search text box.

4. Open the home page of your Search site. Go to Site Actions and click Edit page to edit the page.

5. Click on Add a Web Part above the Search box and add a Content Editor Web Part as shown below.

6. After adding the web part, click below the web part in order to edit the HTML source as shown in the below figure to open the content editor of the web part.

7. In the content editor add the below script tags referring the jQuery plugins:

<script type="text/javascript" src="/_layouts/SPAutoSuggestion /jquery-1.9.js"></script>
<script src="/_layouts/SPAutoSuggestion/jquery.ui.core.js"></script>
<script src="/_layouts/SPAutoSuggestion/jquery.ui.widget.js"></script>
<script src="/_layouts/SPAutoSuggestion/jquery.ui.position.js"></script>
<script src="/_layouts/SPAutoSuggestion/jquery.ui.autocomplete.js"></script>
<link href="/_layouts/SPAutoSuggestion/jquery-ui.CSS" rel="stylesheet" type="text/css"/>

Note: You may have to change the jQuery version number in the first line based on the jQuery version that you download also make sure the all the files referred are their in the correct path.

8. Now let us start writing the JavaScript code. This JS code will  retrieve the keywords to be suggested from the Search Keywords list through ECMA script Client Object Model and store it in an array.

<script type="text/javascript">
JSRequest.EnsureSetup();
//declare the variable that are going to be used though out the code

var clientContext;
var oList;
var camlQuery;
var listItemInfo=’‘;
var listItemEnumerator;

$(document).ready(function () //executes the function inside after the page finishes loading completely
{
// loads the sp.js file that contains the client object model script and then executes the Post_COM_Load function.
ExecuteOrDelayUntilScriptLoaded(Post_COM_Load, "sp.js");
});

9. Below function is the Post_COM_Load function which retrieves the keywords from the Search Keywords list.

function Post_COM_Load() {
//gets the context of the current site which is our Search center
clientContext = new SP.ClientContext.get_current();
//gets the list by title 'Search Keywords' where we have stored all the keywords
oList = clientContext.get_web().get_lists().getByTitle('Search Keywords');

//camlQuery variable will store the CAML query using which we would retrieve the keywords from the list.
var camlQuery = new SP.CamlQuery();
camlQuery.set_viewXml('<View/>');
//collListItem will store the list items retrieved form the Search Keywords list.
this.collListItem = oList.getItems(camlQuery);
//populate the collListItem with values from the Title column in the Search Keywords list.
clientContext.load(collListItem, 'Include(Title)');

//execute the onQuerySucceeded function if data gets loaded successfully and execute the onQueryFailed if it failed to load the data
clientContext.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded), Function.createDelegate(this, this.onQueryFailed));
}

10.  Add the below script for onQuerySucceeded.

function onQuerySucceeded(sender, args) {
listItemEnumerator = collListItem.getEnumerator();
//looping through collListItem list item collection and storing each value into an array called listItemInfo separated by a comma
while (listItemEnumerator.moveNext()) {
oListItem = listItemEnumerator.get_current();
listItemInfo +=
',' + oListItem.get_item('Title');
}

//bind the Autocomplete functionality to an search textbox whose class name is .ms-sbplain by passing the array as the parameter.
$(".ms-sbplain").autocomplete({
source: listItemInfo.split(",")
});
}
11. Add the below script for onQueryFailed function
function onQueryFailed(sender, args) {
//when the request to load the has failed the error message will be displayed in an alert.
alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
}

12. Click OK in the content editor and click Save & Close in the top ribbon.

13. Now, when you start typing in the search text box, the suggestions would appear from the Search keywords list based on what you are typing as shown below.

Here is the complete code without any comments:

<script src="/_layouts/SPAutoSuggestion/jquery-1.7.js" type="text/javascript"></script>
<script src="/_layouts/SPAutoSuggestion/jquery.ui.core.js"></script>
<script src="/_layouts/SPAutoSuggestion/jquery.ui.widget.js"></script>
<script src="/_layouts/SPAutoSuggestion/jquery.ui.position.js"></script>
<script src="/_layouts/SPAutoSuggestion/jquery.ui.autocomplete.js"></script>
<link href="/_layouts/SPAutoSuggestion/jquery-ui.CSS" rel="stylesheet" type="text/css"/>
<script type="text/javascript">
JSRequest.EnsureSetup();

var clientContext;
var oList;
var camlQuery;
var listItemInfo='';
var listItemEnumerator;

$(document).ready(function()
{
ExecuteOrDelayUntilScriptLoaded(Post_COM_Load,"sp.js")
});

function Post_COM_Load(){
clientContext = new SP.ClientContext.get_current();
oList = clientContext.get_web().get_lists().getByTitle('Search Keywords');
camlQuery = new SP.CamlQuery();
camlQuery.set_viewXml('<View/>');
this.collListItem=oList.getItems(camlQuery);
clientContext.load(collListItem,'Include(Title)');
clientContext.executeQueryAsync(Function.createDelegate(this,this.onQuerySucceeded),
Function.createDelegate(this,this.onQueryFailed))
}

function onQuerySucceeded(sender,args){
var listItemEnumerator = collListItem.getEnumerator();
while(listItemEnumerator.moveNext()){
oListItem = listItemEnumerator.get_current();
listItemInfo+=','+oListItem.get_item('Title')}
$(".ms-sbplain").autocomplete({source:listItemInfo.split(",")})
}
function onQueryFailed(sender,args){
alert('Request failed. '+args.get_message()+'\n'+args.get_stackTrace())
}
</script>

jQuery with Client Object Model in SharePoint 2010

It’s been more than a month since I blogged. Didn’t find much to blog actually. Anyway right now I’m here to blog about accessing SharePoint data using Client Object Model in jQuery.

I started learning jQuery only a few days back and found it really interesting and started to integrate it with SharePoint 2010.

Recipe:

To create a Content Editor Web Part with jQuery script which shows the current sub site’s title.

How to do?

  1. Download the jQuery plug in form here.
  2. Create a folder called jQuery in the layouts folder of your SharePoint server and save it there.
  3. Create a web part page in  your SharePoint site and add a Content Editor Web Part in the web part page.
  4. After adding the web part, click below the web part in order to edit the HTML source as shown in the below figure to open the content editor.
  5. Add the below script which refers the jQuery file in the layouts folder to the top of the editor.



< <script type=”text/javascript” src=”/_layouts/jquery-1.7.js”></script>
6. Now, add the below JavaScript which executed once the web page finishes loading.

             <script type=”text/javascript”>
             JSRequest.EnsureSetup();
            $(document).ready(function() {
             ExecuteOrDelayUntilScriptLoaded(Post_COM_Load, “sp.js”);
             });

The ExecuteOrDelayUntilScriptLoaded(Post_COM_Load, “sp.js”) function in the above script executes the Post_COM_Load method after the sp.js file finishes loading.

7. Now, add the below coding for Post_COM_Load method which implements COM to get the current’s site’s title.

           function Post_COM_Load()
          {
             SP.ClientContext clientContext = new SP.ClientContext.get_current();
             web = clientContext.get_web();
             clientContext.load(web, ‘Title’);
              clientContext.executeQueryAsync(Function.createDelegate(this, this.onSiteLoadSuccess),                Function.createDelegate(this,                 this.onQueryFailed));
             }

8. Add the below script for onSiteLoadSuccess and onQueryFailed respectively.

            function onSiteLoadSuccess(sender, args) {
            $(“h3”).html(“site title : ” + web.get_title()); // h3 refers to the heading element in the UI which we will be adding shortly
             }

           function onQueryFailed(sender, args) {
           alert(‘request failed ‘ + args.get_message() + ‘\n’ + args.get_stackTrace());
            }

9. Close the script with </script> tag.

10. Below the above script design the UI for the CEWP with the below HTML.

           <div>
           <h3></h3> //this is where we will display our sub site’s title
           </div>

11. Click OK to save the content in the editor and click Stop Editing in the top Ribbon.

Here is the complete code of the above solution

<script type=”text/javascript” src=”/_layouts/COM/jquery-1.7.js”></script>
<script type=”text/javascript”>
JSRequest.EnsureSetup();
$(document).ready(function() {

ExecuteOrDelayUntilScriptLoaded(Post_COM_Load, “sp.js”);
});

function Post_COM_Load()
{
SP.ClientContext clientContext = new SP.ClientContext.get_current();
var web = clientContext.get_web();
clientContext.load(web, ‘Title’);
clientContext.executeQueryAsync(Function.createDelegate(this, this.onSiteLoadSuccess), Function.createDelegate(this, this.onQueryFailed));
}

function onSiteLoadSuccess(sender, args) {
$(“h3”).html(“site title : ” + web.get_title());
}

function onQueryFailed(sender, args) {
alert(‘request failed ‘ + args.get_message() + ‘\n’ + args.get_stackTrace());
}
</script>

<div>
<h3></h3>
</div>

Hop it was useful for people looking for accessing the SharePoint data in jQuery.

Advantages and Disadvantages of Client Object Model

I have been implementing Client Object Model (COM) extensively in Silverlight as well as in ECMAScript. I have failed many times in accomplishing certain tasks and succeeded many times too. You may love or hate COM but you cannot ignore it if you are a SharePoint 2010 developer.

So, I’m going to list out the advantages and disadvantages of COM that I have been facing while implementing it. Let us look at the advantages first.

Advantages:

  1. As mentioned everywhere using COM we can access the SharePoint data from the client side browser itself with Silverlight and ECMAScript applications.
  2. Web parts with very rich user interface can be developed with the help of Silverlight and jQuery. For example, we can create web parts like video and image galleries with beautiful animations where the videos and the images can be stored in the SharePoint libraries and retrieved using COM.
  3. COM along with JavaScript or jQuery can be implemented with just a Content Editor Web part within the browser or from the SharePoint designer without opening the Visual Studio. You can read about it here on how to do that.
  4. When we save your site as a template. The application developed with ECMAScript or Silverlight application implemented with Client Object Model would come along with the template which would be very helpful during migrations though we need to take care of any hard coded values.
  5. No IISREST is required while deploying a Silverlight or an ECMAScript application implemented with COM.
  6. We can have SharePoint accessed from the client desktop using Windows forms or WPF applications implemented with COM. We can develop desktop gadget kind of applications which would be displaying the new announcements added to the “Announcements” list.
  7. No SharePoint installation is required in the development machine. Only the dll’s are required if you are going to develop Silverlight applications.

Disadvantages:

  1. We cannot elevate the privilege or Impersonate in COM as in Server Object Model. That is, we cannot use the RunWithElevatedPrivilege kind of a delegate. Therefore, the results retrieved using COM will always be security trimmed by default.
  2. The range of classes available to access SharePoint data is very limited in COM. For example, we do not have Classes for accessing User Profiles. We need to go for SharePoint web services.
  3. We cannot access the objects of another site collection in COM while implementing in Silverlight or in ECMAScript. We will get “The security validation for this page is invalid.” if we try to do so. So, we cannot develop applications to read the data from another site collection.
  4. Silverlight web parts fail to load by giving an error message saying Could not download the Silverlight application or the Silverlight Plugin did not load. To re-configure the Web Part or to provide a different Silverlight application (.xap), open the tool pane and then click Configure.when it takes more than 5 seconds to load.
  5. We cannot retrieve recurring events from a SharePoint calendar list in Client Object Model.

These are the advantages and disadvantages that I have faced. I will update more when I face any.