Month: February 2011

Fetching the current user’s office location with SPServices

Today’s post is just a small code snippet that retrieves the current user’s office location from his/her user profile (assuming that the field Office is in use, which should be the cast most of the time) with the help of SPServices. In fact, the code below is nearly identical with some that Marc D Anderson posted a few months back (had I seen this earlier, it would have saved me some time writing my own code….at least I know that my approach was right, and I learned a bit while doing it), he gives a bit more information on other possible fields that you could fetch.

GetCurrentUserOffice = function() {     var thisUser = $().SPServices.SPGetCurrentUser();     var Location;      $().SPServices({           operation: "GetUserProfileByName",           async: false,           AccountName: thisUser,           completefunc: function (xData, Status) {                $(xData.responseXML).find("PropertyData > Name:contains('Office')").each(function() {                     Location = ($(this).parent().find("Values").text());                });           }      });     return Location;}

A possible use for this is showing content based on the user’s office location, for example "The latest News from the Auckland Office". Use this function to determine the user’s office location, and use that result to fetch other content accordingly with the right filter.

Adding a custom Search Input to a SharePoint page

Sometimes you may need to add a search web part to your page, but you then discover that WSS 3.0 and SharePoint Foundation 2010 don’t offer them (only included in MOSS 2007 / SharePoint Server 2010). Or you want to add a small search box somewhere within your page and provide some descriptive text around it ("If you can’t find what you’re looking for, enter your search terms in the following box to search this site:") to make it more user-friendly.
Image(7)

Whenever the standard web parts in SharePoint can’t help you, the following solution might be able to solve your needs. While it doesn’t offer the full functionality of said web parts (naturally), it still offers you a very simple, yet effective way to provide a search box and make it easier for your visitors to find relevant content.

What this solution does it to provide a dropdown with search scopes and an input box for the search terms, and combines the selections of both to submit searches to a predefined destination. Depending on your requirements, you can define which search results page should be used here. For example, this can be MOSS 2007’s or SharePoint Server 2010’s Search Center. Alternatively, or also if you’re using WSS 3.0 / SharePoint Foundation 2010, you can submit it to the default search page. In case you have a customised search page, you could even submit it to that one!

All you need to do to get it to run is to add the following code onto your page at your preferred location, for example inside a Content Editor Web Part

<SCRIPT type="text/javascript">function CustomSearch() {var currentSitePath = makeAbsUrl(L_Menu_BaseUrl);var resultsPage = currentSitePath + "/_layouts/OSSSearchResults.aspx";  // other option: "/SearchCenter/Pages/Results.aspx";var targetURL = resultsPage + "?k=" + document.getElementById('SearchString').value;// search within a site onlyif (document.getElementById('Scope').value =="ThisSite")targetURL += "&cs=This Site&u=" + currentSitePath;// do not search within current site and not everywhere, thus within a provided listelse if (document.getElementById('Scope').value !="All")targetURL += "&cs=This List&u=" + currentSitePath + "/" + document.getElementById('Scope').value;window.location.href = targetURL ;}</SCRIPT><div class="CustomSearch"><table class="ms-sbtable ms-sbtable-ex"><tr class="ms-sbrow"><td class="ms-sbscopes ms-sbcell" colspan="3"><span>I am looking for:</span></td><td class="ms-sbLastcell"/></tr><tr class="ms-sbrow"><td class="ms-sbscopes ms-sbcell"><select name="Scope" id="Scope" ><option value="ThisSite" selected="selected">This Site</option><option value="Documents">Documents</option><option value="My Presentations">Presentations</option><option value="All">Everywhere</option></select></td><td class="ms-sbcell"><input name="SearchString" type="text" class="ms-sbplain" alt="Enter search criteria" onkeypress="if(IsKeyDownSubmit(event)) CustomSearch();" id="SearchString"/></td><td class="ms-sbgo ms-sbcell"><a title="Go Search" href="javascript:CustomSearch()"><img style="border-right-width: 0px;border-top-width: 0px;border-bottom-width: 0px;border-left-width: 0px"onmouseover="this.src="/_layouts/images/gosearch.gif" mce_src="/_layouts/images/gosearch.gif"" title="Go Search" onmouseout="this.src="/_layouts/images/gosearch.gif" mce_src="/_layouts/images/gosearch.gif""alt="Go Search" src="/_layouts/images/gosearch.gif"></a></td><td class="ms-sbLastcell"/></tr></table></div>

If you want to provide the option to search within one or more given lists, you need to update the corresponding dropdown values (in my example above Documents and My Presentations). The value of the OPTION tag has to be the name of the list/library that was used when it was created (when you open it, you can see it as part of the URL), as for the display name you can choose what you prefer.

Extensive List of SharePoint Blogs

Over the past few years, I’ve subscribed to the RSS feeds of a lot of SharePoint blogs. Personally, I use Google reader for this as I prefer to be able to read it (theoretically) from anywhere.

I suppose some people (anyone just starting with SharePoint; people who haven’t really subscribed to a lot of feeds (yet); blog junkies like myself) could be quite interested in the (currently 203 feeds long) list of blogs that I subscribe to, so here it is:

Follow this link for the OPML file which you can import in different RSS readers, like for example Google Reader, Firefox, or Internet Explorer.

Here’s the direct link to my “bundle” created by Google reader which you could subscribe to.

And lastly, here’s the overview of all blogs that I read: (not working at the moment, use links above)

If you know any other interesting SharePoint blogs that I haven’t added here, PLEASE let me know! I’ll gladly add more valuable feeds to my list.

Providing Filter Dropdowns for a SharePoint List/Library with jQuery

Let’s say your users want to have an easy way to filter items in a SharePoint list or library, but for some specific reason they should be able to do this with some other functionality than the standard filtering made available in the list&library column header. With a little help of jQuery and SPServices you can easily achieve this and add some dropdowns onto a page, and you can even easily add a nice design (though I’ll leave this part out of this article and leave it up to you to implement with some CSS).

 


What we want to achieve

The following screenshot shows how this solution allows you to apply filters to a list similar to the way these standard column header filters work. As you can see, filters for the columns SingleLineOfText and Number have been applied already, I could also apply another filter for Currency.

Image(1)

You have the choice which columns you want to be filterable here. If you have 5 columns (Name, Address, ZIP, City, Country), you could supply filters for 2 columns (City, Country) only!

The benefit of this solution here is that it works anywhere. For example, you can use it in combination with a Data View Web Part instead of the standard list/library Web Part (Edit: DVWP work differently than the “normal” list/library web parts; I’m currently testing how to integrate this solution with them). Another option would be to provide users with nicer looking filter dropdowns somewhere else on the page (on top of the library; to the right; embedded within some descriptive text!; etc).
Also, this is probably the easiest way to get a dropdown of all possible unique filter values.

 


Background Information

The filters here do not recreate the standard filter menus, but rather reuse SharePoint’s very own creation mechanism (the same way that these standard menus are created). Basically, the filter menu for a list/library is created through JavaScript. You can find the relevant function addFilterMenuItems in the core.js file . Diving into its functionality, once can see that SharePoint actually calls the file /_layouts/filter.aspx when creating the filter menus. If you open this page manually with the relevant parameters, you get to see that it creates a dropdown just the way we need it:

Image(2)

An example for this URL is:
http://myserver/mysubsite/_layouts/filter.aspx?ListId=%7B8A624345%2DDB60%2D41E6%2D9863%2D3DAF60557DA1%7D&FieldInternalName=Region&ViewId={CDBA0419-769D-4AFB-9152-6D311DE99879}&FilterOnly=1&Filter=1

These relevant parameters are:

  1. the ID of the list/library that you’re using (ListId)
  2. the ID of the view that you’re using (ViewId)
  3. the name of the column that we want to filter (FieldInternalName)

Information about how to find all these parameters is listed further below in this article.

It is also important to note the following things:

  1. If one or more filters are applied, all other filters will take them into account. If I filter by Number in my example above, the dropdown for Currency will only show me the values for those rows which meet the Number filtering as well.
  2. If SharePoint doesn’t allow you to filter a field (e.g. multiple lines of text), you can’t filter it here

The important question is: how do we get the values from this dropdown onto our page?

In the discussion board of SPServices you can find a thread that briefly discusses how to retrieve the dropdown itself as well as it’s values. With some modifications, this code can be used for our solution.

 

The Code

The code below consists of two parts, a JavaScript section (including jQuery and SPServices usage) to retrieve the dropdown and prepare its output as well as a simple HTML section where we present the result of the JavaScript code.

//update the following 2 lines with your own local versions if wanted
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jquery.SPServices/2014.01/jquery.SPServices.min.js"></script>
<script type="text/javascript">
$("document").ready(function() {
//set default vars; replace them with your ownvar
listID = '{B858515E-A827-4444-98DA-E81B4F1AF0AD}';
var viewID = '%7B3C11FBF2%2D9702%2D4B76%2DB280%2D02A783B8E7FA%7D';
//load paramsvar
allVars = $().SPServices.SPGetQueryString();
var filterFieldsParams = "";
$.each(allVars, function( objKey, objValue ){
if(objKey.substr(0,11).toLowerCase()=="filterfield" || objKey.substr(0,11).toLowerCase()=="filtervalue"){
filterFieldsParams+="&"+objKey+"="+objValue;
}
});

function getAjaxFilter(name, internalName){
$.ajax({
url: $().SPServices.SPGetCurrentSite()+'/_layouts/filter.aspx?ListId='+listID+'&FieldInternalName='+internalName+'&ViewId='+viewID+'&FilterOnly=1&Filter=1'+filterFieldsParams,
success: function(data) {
// replace"<b>"+name+": </b>" with your own code if required
$('#filterField'+internalName).html("<b>"+name+": </b>").append($("<div></div>").append(data).find("select, img"));
//clear current onChange event
$("#diidFilter"+internalName).attr("onchange", '');
// add change event
$("#diidFilter"+internalName).change(function() {
FilterField(viewID,internalName,encodeURIComponent(this.options[this.selectedIndex].value), this.selectedIndex);
});
}
});
}
// provide selected filters
getAjaxFilter("Single Line of Text", "SingleLineOfText");
getAjaxFilter("Number", "Number");
getAjaxFilter("Currency", "Currency");
});
</script>
<div id="allFilters">
<div id="filterFieldSingleLineOfText"></div>
<div id="filterFieldNumber"></div>
<div id="filterFieldCurrency"></div>
</div>

 


Explanation

The first two lines load the necessary jQuery and SPServices scripts. In the beginning of the JavaScript code block, we first define the ID of the list/library and the view, and then to fetch any filter parameters that may have been applied already from the URL. In such a case, we want our filters to take into account any existing filters, so that unrealistic filter options are not shown (as mentioned under Background Information).

The function getAjaxFilter is the core of this solution. It calls the above mentioned filter.aspx page and fetches its data, filters it to return only any dropdown and any images (if a filter is applied, an icon is shown), and updates the dropdowns onChange event. The reason for this is that the default behaviour in this case doesn’t work properly when you want to remove a filter (when you select (All) from the dropdown). What we need to do here is to simply call the exact same JavaScript function FilterField (defined in core.js) with the correct parameters.

After the function declaration, we have 3 function calls, which you will later need to r
eplace with your own. Lastly, there are three named DIVs which are used later to “store” the results from the getAjaxFilter calls. They follow the naming convention filterFieldINTERNALFIELDNAME, so you need to update them accordingly with your own column names (see below for how to find them out).

 


Using it on your own page

As mentioned above, there are multiple ways how you can include this solution on your page. The easiest way is to add a Content Editor Web Part (CEWP) and paste the code into its Source Editor.

What you’ll need to apply it to your own list/library is the ID of it as well as the ID of the view that you’re using. Both IDs can be in either of the following two formats:
%7BB858515E%2DA827%2D4444%2D98DA%2DE81B4F1AF0AD%7D
or
{B858515E-A827-4444-98DA-E81B4F1AF0AD}

How do you get both required IDs? When you open the settings page of the list/library, you can find its ID as part of the URL:

Image(3)

An easy way to get the ID of the view that you’re using is to apply a filter through the list/library’s header row. Afterwards you can find the ID as part of the URL:

Image(4)

To get the internal name that is used for a column, go to the list/library’s settings, and click on the column name. The internal name can then be found as part of the URL as the parameter Field:

Image(5)

Please note that if you used certain special characters while creating the column, SharePoint will not use them for the internal name, but replace them with hex codes (http://abstractspaces.wordpress.com/2008/05/07/sharepoint-column-names-internal-name-mappings-for-non-alphabet/):

Image(6)

You will still need to bring these columns into a more readable format. For example, if you copy the name marked here (My%5Fx0020%5F1st%5Fx0020%5FTest%5Fx0020%5FColumn%5Fx0021%5F), and decode it at http://meyerweb.com/eric/tools/dencoder/, you will get the actual proper name My_x0020_1st_x0020_Test_x0020_Column_x0021_ which needs to be used

Once you have all these, replace the IDs in the code with your own, and create your own DIV wrappers and getAjaxFilter calls for your respective columns.

 


Possible Improvements

There are still some improvements that could be done. Depending on your own requirements (for example if you wish to reuse that code in multiple locations), you may want to consider calling getAjaxFilter with filterFieldsParams as parameter to avoid relying on it as a global variable. Also, this implementation is not flexible when it comes to creating output in different layouts. If you want to have different ways of displaying the filters (in a table row / with different style sheets / etc), I’d recommend to not do any output changes (namely the $(‘#filterField’+internalName).html(..) call), but rather return the result from getAjaxFilter and use it in your own function for further changes.