Hide Available Refiners in SharePoint search refinement panel

Recently one of the customer had a strange request where the customer wanted to Hide “Available Refiners” in SharePoint search refinement panel.

The “Available Refiners” is available in “Drop Down” type refinement panel.

SharePoint Refinement Panel

When the refinement panel is being loaded, SharePoint executes a JavaScript function named AddPostRenderCallback. This would be available in the Refinement Display Template located under MasterPage/Search Gallery. The actual method looks like below code which is taken from O365.

AddPostRenderCallback(ctx, function() {
    if (hasAnyFiltertokens) {
        // Get the hidden block
        var hiddenOptions = document.getElementById(hiddenBlockID).children;
        var unSelGroup = document.getElementById(unselDD);
        var selGroup = document.getElementById(selDD);
        // Clone all the elements from the hidden list to the unselected option group
        for (var i = 0; i < hiddenOptions.length; i++) {
            var selectedElm = GetAllElementsWithAttribute(selGroup, 'value', hiddenOptions[i].getAttribute('value').replace('updateRefinersJSON', 'removeRefinementFiltersJSON'));
            if (selectedElm === null || selectedElm.length <= 0) {
                var cloneElm = hiddenOptions[i].cloneNode(true);
                unSelGroup.appendChild(cloneElm);
            }
        }
    }
});

To the above original code I made a small change so that “Clone all the elements” code executes only when user has selected a refiner.

// Clone all the elements from the hidden list to the unselected option group
if(selectedFilters.length <= 0)
{
	for (var i = 0; i < hiddenOptions.length; i++) {
		var selectedElm = GetAllElementsWithAttribute(selGroup, 'value', hiddenOptions[i].getAttribute('value').replace('updateRefinersJSON', 'removeRefinementFiltersJSON'));
		if (selectedElm === null || selectedElm.length <= 0) {
			var cloneElm = hiddenOptions[i].cloneNode(true);
			unSelGroup.appendChild(cloneElm);
		}
	}
}

To the above orignal code I added the following code to hide the “Available Refiners” option.

if(selectedFilters.length > 0)
{
	if(unSelGroup!=null)
	{
		unSelGroup.style.display = 'none';
	}
}

The above code will hide the “unSelGroup”‘s “Option Group” HTML to hide the Options for “Available Refiners”.

Final code would look like below.

AddPostRenderCallback(ctx, function() {
    if (hasAnyFiltertokens) {
        // Get the hidden block
        var hiddenOptions = document.getElementById(hiddenBlockID).children;
        var unSelGroup = document.getElementById(unselDD);
        var selGroup = document.getElementById(selDD);
        // Clone all the elements from the hidden list to the unselected option group
        if(selectedFilters.length <= 0)
        {
            for (var i = 0; i < hiddenOptions.length; i++) {
                var selectedElm = GetAllElementsWithAttribute(selGroup, 'value', hiddenOptions[i].getAttribute('value').replace('updateRefinersJSON', 'removeRefinementFiltersJSON'));
                if (selectedElm === null || selectedElm.length <= 0) {
                    var cloneElm = hiddenOptions[i].cloneNode(true);
                    unSelGroup.appendChild(cloneElm);
                }
            }
        }
        //Added for Gold Asset requirement where once a refiner is selected the "Avaialble Refiners" item should be made hidden
        if(selectedFilters.length > 0)
        {
            if(unSelGroup!=null)
            {
                unSelGroup.style.display = 'none';
            }
        }
        
        var refinerUpArrow = document.getElementById('refinerExpandCollapseArrow');
        if(refinerUpArrow!=null)
        {
            refinerUpArrow.style.display = 'none';
        }
        
    }
});

End Result is following
Hidden Available Refiners Option Group

Clear SharePoint Search Results

SharePoint Clear SharePoint Search Results

Recently I had a requirement for OOTB search Box + Result where the customer wanted to clear the search results regardless of any refinement selected or not.

Clear SharePoint Search Results

To implement this, in the display template HTML the following was added.

Do note that if refinements are there, the commented single line of code didn’t work and I had to replace the entire # as blank. Do check the original source (mentioned below) for more information.

<!--#_
    clearSearchResults = function()
    {
        var hash = window.location.hash;
        if( hash.indexOf('Default') == 1 ) {
            hash = unescape(hash);
            var kIdx = hash.indexOf('"k":'); 
            var rIdx = hash.indexOf('","'); 
            var query = hash.substring(kIdx+5,rIdx);
            query = query.replace(/\\/g, '');
            //window.location.href = window.location.pathname + window.location.search + '#k=' + escape(query);
            window.location.href = window.location.pathname + window.location.search + '#';
        } else {
            window.location.href = window.location.pathname + window.location.search + "#";
        }                    
    }
_#-->
<div id="ClearSearch" class="ms-alignCenter">
    <h2><a onclick="clearSearchResults();"  style="cursor:pointer">Clear/Reset All</a></h2>
</div>

The source for the above code is Add a “Clear Filters” link to your search page in SharePoint 2013

SharePoint JavaScript Error Script5009 ‘type’ is undefined sp.js

When we add the sp.js link to the SharePoint Webpart Page or simple ASPX Page and when the page loads we get the following error.

script5009 ‘type’ is undefined sp.js

The solution I saw in the web for this is, add Micrsofot Ajax script.

<script type="text/javascript" src="//ajax.aspnetcdn.com/ajax/4.0/1/MicrosoftAjax.js"></script>

Do note that this resolves the similar error which occurs when we add other SharePoint js files as well.

Setting up Provider Hosted App

There are many articles which explain how to setup the Remote Web & SharePoint On-Prem. The following articles explains everything end to end.
http://blogs.msdn.com/b/russmax/archive/2014/06/23/part-1-intro-to-provider-hosted-apps-setup-the-infrastructure.aspx
http://blogs.msdn.com/b/russmax/archive/2014/06/26/part-2-intro-to-provider-hosted-apps-develop-package-and-deploy.aspx

Get People Picker Field Value from SharePoint List – JSOM

Following is the JSOM code which will help in getting single or multiple items from a SharePoint’s People Picker Field.

function GetPeoplePickerFieldValue(currentListItem, internalFieldName) {
    if (currentListItem.get_item(internalFieldName) !== 'undefined' && currentListItem.get_item(internalFieldName) !== null) {
        if (currentListItem.get_item(internalFieldName).length > 0) {
            var _user = "";
            //If field has only one item
            if (currentListItem.get_item(internalFieldName).length == 1) {
                _user = currentListItem.get_item(internalFieldName)[0].get_lookupValue();
                if (_user == null)
                    _user = "";
            }
            //If field has multiple item
            if (currentListItem.get_item(internalFieldName).length > 1) {
                for (var i = 0; i < currentListItem.get_item(internalFieldName).length; i++) {
                    //Append all User names with a semi colon separator
                    _user = _user + currentListItem.get_item(internalFieldName)[i].get_lookupValue() + "; ";
                }
                _user.trim;
                if (_user == null)
                    _user = "";
            }
        }
        return _user;
    }
}

Source: Microsoft TechNet Forum

Windows 10 – Change Task Bar & Start Menu Accent based on current wallpaper automatically

Windows 10 is awesome and currently one of the feature which I like is, changing the task bar & start menu accent colour based on current wallpaper.

To invoke this, do the following.

  1. Right click on empty desktop
  2. Click “Personalize” menu item
  3. Select “Colours” tab
  4. Enable or toggle on “Automatically pick an accent colour from my background”
  5. Enable or toggle “Show colour on Start, taskbar and action centre”
  6. Optionally you can make Start Menu, taskbar & action centre transparent by toggling the last option.

Decoding Query String with Unicode Characters

Recently I came across an issue where the query string had unicode characters and ASP.NET’s “HttpUtility.UrlDecode” was not properly converting the characters. After searching few minutes came across the following solution posted by cjsharp1 at Stackoverflow.

private string GetQueryStringValueFromRawUrl(string queryStringKey)
{
    var currentUri = new Uri(HttpContext.Current.Request.Url.Scheme + "://" + 
        HttpContext.Current.Request.Url.Authority + 
        HttpContext.Current.Request.RawUrl);
    var queryStringCollection = HttpUtility.ParseQueryString((currentUri).Query);
    return queryStringCollection.Get(queryStringKey);
}

Copy current item ID to clipboard using SharePoint custom action

Recently I had a requirement where the user needed to copy an item’s URL to clipboard in SharePoint.

Using the SharePoint designer, I created a Custom Action and in the “Navigate to URL” action type I set the following.

javascript:clipboardData.setData("Text", window.location.protocol+'//'+window.location.hostname+':'+window.location.port +'/sites//Lists//DispForm.aspx?ID='+'{ItemId}');alert('Item URL \"'+window.location.protocol+'//'+window.location.hostname+':'+window.location.port +'/sites//Lists//DispForm.aspx?ID='+'{ItemId}'+'\" copied to clipboard');

 

ASP.NET Persistence

Following is a simple table which I came across a post “Nine Options for Managing Persistent User State in Your ASP.NET Application

Posting it here for easy reference. This lists out various ASP.NET Persistence methods.

Persistence MethodWho Needs the Data?For How Long?How Much Data?
ApplicationAll usersUntil the next application restartCan be almost any size—it will only be stored once
CookieOne userAs short as desired, or for months or even years if the user doesn’t delete their cookiesMinimal, simple data
Form PostOne userFor the next request (can be reused across many requests)Virtually any size—the data is sent back and forth with every page
Query StringOne user or one group of usersFor the next request (can be reused across many requests)Minimal, simple data
SessionOne userAs long as the user is active, plus a timeout period (typically 20 minutes)Can be almost any size, but should be minimized since every user has their own separate session store
CacheAll users or a subset of usersAs long or as short as neededCan be used for large or small, simple or complex data
ContextOne userThis request onlyCan hold large objects, but typically does not since it is often used for every request
View StateOne userOne Web formMinimal; as with Form Post, this data is sent back and forth with every page
Config fileAll usersUntil the configuration file is updatedCan hold a lot of data; usually organized as many small strings or XML structures