SharePoint 2013: Basic Search box Customization


Requirement:

Customize the small search box to support both portal and google searching capabilities

This is the OOB small search control

2013-11-18 12_46_20-Advent_QA - 54.236.214.160 - Remote Desktop Connection

This should be customized such that when the user is on “search Google” tab and click search button it should open google results in new tab and OOB search should work as usual.

2013-11-18 12_37_10-Advent_QA - 54.236.214.160 - Remote Desktop Connection

Design:

Small search box is one of the delegate control in the master page.

<div id="searchInputBox">
 <SharePoint:DelegateControl runat="server" ControlId="SmallSearchInputBox" />
</div>

Definition of this delegate control is available at  \15\TEMPLATE\FEATURES\OSearchBasicFeature\SearchArea.xml

<?xml version="1.0" encoding="utf-8" ?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
 <Control
 Id="SmallSearchInputBox"
 Sequence="50"
 ControlClass=" Microsoft.Office.Server.Search.WebControls.SearchBoxScriptWebPart" ControlAssembly="Microsoft.Office.Server.Search, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c">
 <Property Name="UseSharedSettings">true</Property>
 <Property Name="RenderTemplateId">~sitecollection/_catalogs/masterpage/Display Templates/Search/Control_SearchBox_Compact.js</Property>
 <Property Name="EmitStyleReference">false</Property>
 <Property Name="ServerInitialRender">true</Property>
 <Property Name="TryInplaceQuery">false</Property>
 <Property Name="QueryGroupNamesJson">[&"MasterPage&"]</Property>
 <Property Name="ChromeType">None</Property>
 <Property Name="ID">SmallSearchInputBox1</Property>
 </Control>
</Elements>

<Property Name=”RenderTemplateId”> holds the display template value which is rendered for small search box. OOB searchbox can be override by creating a new delegate control with custom display template.

Implementation:

Step 1:

Make a copy of ~sitecollection/_catalogs/masterpage/Display Templates/Search/Control_SearchBox_Compact.html and rename to Custom_Control_SearchBox_Compact.html and upload to same location. This will create a new JS file Custom_Control_SearchBox_Compact.js.

Step 2:

Now create a new project in Visual studio with empty feature and add a element.xml file with new delegate definition

<?xml version="1.0" encoding="utf-8" ?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
 <Control
 Id="SmallSearchInputBoxAdv"
 Sequence="23"
 ControlClass="Microsoft.Office.Server.Search.WebControls.SearchBoxScriptWebPart" ControlAssembly="Microsoft.Office.Server.Search, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c">
 <Property Name="UseSharedSettings">false</Property>
 <Property Name="RenderTemplateId">~sitecollection/_catalogs/masterpage/Display Templates/Search/Custom_Control_SearchBox_Compact.js</Property>
 <Property Name="EmitStyleReference">false</Property>
 <Property Name="TryInplaceQuery">false</Property>
 <Property Name="QueryGroupNamesJson">[&"MasterPage&"]</Property>
 <Property Name="ChromeType">None</Property>
 <Property Name="ID"><strong>SmallSearchInputBoxCustom</strong></Property>
 </Control>
</Elements>

Now deploy the solution and make the change in masterpage to refer the new delegate function

<div id="searchInputBox">
 <SharePoint:DelegateControl runat="server" ControlId="<strong>SmallSearchInputBoxCustom</strong>" />
</div>

Step 4:

Now make changes to the display template Custom_Control_SearchBox_Compact.html to achieve the required functionality.

<html xmlns:mso="urn:schemas-microsoft-com:office:office" xmlns:msdt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882">
<head>
<title>Site Search Box</title>

<!--[if gte mso 9]><xml>
<mso:CustomDocumentProperties>
<mso:TemplateHidden msdt:dt="string">0</mso:TemplateHidden>
<mso:MasterPageDescription msdt:dt="string">Displays the Search Box control in a compact form.</mso:MasterPageDescription>
<mso:ContentTypeId msdt:dt="string">0x0101002039C03B61C64EC4A04F5361F385106601</mso:ContentTypeId>
<mso:TargetControlType msdt:dt="string">;#SearchBox;#</mso:TargetControlType>
<mso:HtmlDesignAssociated msdt:dt="string">1</mso:HtmlDesignAssociated>
<mso:HtmlDesignConversionSucceeded msdt:dt="string">True</mso:HtmlDesignConversionSucceeded>
<mso:HtmlDesignStatusAndPreview msdt:dt="string">http://sp2012/_catalogs/masterpage/Display Templates/Search/Adv_Control_SearchBox_Compact.html, Conversion successful.</mso:HtmlDesignStatusAndPreview>
<mso:CrawlerXSLFile msdt:dt="string"></mso:CrawlerXSLFile>
<mso:HtmlDesignPreviewUrl msdt:dt="string"></mso:HtmlDesignPreviewUrl>
</mso:CustomDocumentProperties>
</xml><![endif]-->
</head>
<body>
 <script >

$includeCSS(this.url,"~sitecollection/_catalogs/masterpage/Display Templates/Search/SearchBox.css");
 $includeLanguageScript(this.url,"~sitecollection/_catalogs/masterpage/Display Templates/Search/jquery-1.9.1.js");
 $includeLanguageScript(this.url,"~sitecollection/_catalogs/masterpage/Display Templates/Search/SearchBox.js");
 </script>

<div id="Control_SearchBox_Compact">
<!--#_
 var showQuerySuggestions = ctx.ClientControl.get_showQuerySuggestions();
 var showNavigation = ctx.ClientControl.get_showNavigation();

var prompt = ctx.ClientControl.get_initialPrompt();
 if ($isNull(prompt))
 {
 prompt = "E.g., TFS";
 }

var searchBoxDivId = ctx.ClientControl.get_id() + "_sboxdiv";
 var searchBoxId = ctx.ClientControl.get_id() + "_sbox";
 var navButtonId = ctx.ClientControl.get_id() + "_NavButton";
 var suggestionsListId = ctx.ClientControl.get_id() + "_AutoCompList";
 var navListId = ctx.ClientControl.get_id() + "_NavDropdownList";
 var searchBoxLinkId = ctx.ClientControl.get_id() + "_SearchLink";
 var searchBoxProgressClass = "ms-srch-sbprogress";
 var searchBoxPromptClass = "ms-srch-sb-prompt ms-helperText";

ctx.OnPostRender = function(rCtx) {
 ctx.ClientControl.activate(
 prompt,
 searchBoxId,
 searchBoxDivId,
 navButtonId,
 suggestionsListId,
 navListId,
 searchBoxLinkId,
 searchBoxProgressClass,
 searchBoxPromptClass);

$("#Googleli").click(function(){
 if (!$('#Googleli').hasClass('searchSelect'))
 {
 $("#Googleli").toggleClass("searchSelect");
 $("#portalli").toggleClass("searchSelect");
 var sb = $('#' + searchBoxId);
 sb.val("e.g., Wall Street Journal");
}

});
 $("#portalli").click(function(){
 if (!$('#portalli').hasClass('searchSelect'))
 {
 $("#portalli").toggleClass("searchSelect")
 $("#Googleli").toggleClass("searchSelect");
 var sb = $('#' + searchBoxId);
 sb.val("E.g., DFS DQM");

}

});
 $("#portalli").toggleClass("searchSelect");
 }

_#-->

<div id="SearchBoxAdv" name="Control" >
 <div class="ms-srch-sbAdv">
 <ul id ="AdvSearchBox">
 <li id="portalli">Search portal</li>
 <li id="Openli"></li>
 <li id="Googleli">Search Google</li>
 </ul>

<input type="text" value="_#= $htmlEncode(ctx.ClientControl.get_currentTerm()) =#_" maxlength="2048" class="ms-textSmall"
 accessKey="_#= $htmlEncode(Srch.Res.sb_AccessKey) =#_"
 title="_#= $htmlEncode(prompt) =#_"
 id="_#= $htmlEncode(searchBoxId) =#_" autocomplete="off" autocorrect="off"

onkeypress="if (Srch.U.isEnterKey(String.fromCharCode(event.keyCode))) {
 getResults($getClientControl(this),this.value);
}"

onkeydown="var ctl = $getClientControl(this);ctl.activateDefaultQuerySuggestionBehavior();"
 onfocus="var ctl = $getClientControl(this);ctl.hidePrompt();this.value=' ';"
 onblur="var ctl = $getClientControl(this);ctl.showPrompt();" />
<!--#_

var imagesUrl = "/PublishingImages/searchicon.png";
 if (showNavigation) {
_#-->
 <a class="ms-srch-sb-navLink" title="_#= $htmlEncode(Srch.Res.sb_GoNav) =#_" id="_#= $htmlEncode(navButtonId) =#_"
 onclick="$getClientControl(this).activateDefaultNavigationBehavior();return Srch.U.cancelEvent(event);"
 href="javascript: {}" >
 <img src="_#= $urlHtmlEncode(imagesUrl) =#_" class="ms-srch-sb-navImg" id="navImg" alt="_#= $htmlEncode(Srch.Res.sb_GoNav) =#_" />
 </a>
<!--#_
 }
_#-->
 <a title="_#= $htmlEncode(Srch.Res.sb_GoSearch) =#_" class="ms-srch-sb-searchLink" id="_#= $htmlEncode(searchBoxLinkId) =#_"
 onclick="getResults($getClientControl(this),$get('_#= $scriptEncode(searchBoxId) =#_').value);" href="javascript: {}">
 <img src="_#= $urlHtmlEncode(imagesUrl) =#_" id="searchImg" alt="_#= $htmlEncode(Srch.Res.sb_GoSearch) =#_" />
 </a>
<!--#_
 if (showQuerySuggestions) {
_#-->
 <div class="ms-qSuggest-container ms-shadow" id="AutoCompContainer">
 <div id="_#= $htmlEncode(suggestionsListId) =#_"></div>
 </div>
<!--#_
 }

if (showNavigation) {
_#-->
 <div class="ms-qSuggest-container ms-shadow" id="NavDropdownListContainer">
 <div id="_#= $htmlEncode(navListId) =#_"></div>
 </div>
<!--#_
 }
_#-->
 </div>
<!--#_
 if (ctx.ClientControl.get_showAdvancedLink()) {
 var advancedUrl = ctx.ClientControl.get_advancedSearchPageAddress();
 if(!$isEmptyString(advancedUrl)){
_#-->
 <div class="ms-srch-sb-link"><a id="AdvancedLink" href="_#= $urlHtmlEncode(advancedUrl) =#_">_#= $htmlEncode(Srch.Res.sb_AdvancedLink) =#_</a></div>
<!--#_
 }
 }
 if (ctx.ClientControl.get_showPreferencesLink()) {
 var preferencesUrl = ctx.ScriptApplicationManager.get_preferencesUrl();
 if(!$isEmptyString(preferencesUrl)){
_#-->
 <div class="ms-srch-sb-link"><a id="PreferencesLink" href="_#= $urlHtmlEncode(preferencesUrl) =#_">_#= $htmlEncode(Srch.Res.sb_PreferencesLink) =#_</a></div>
<!--#_
 }
 }
_#-->
 </div>
 </div>
</body>
</html>

ctx.ClientControl.activate() renders the OOB small search control. Add custom html elements around this to customize the search control.

onkeypress” event passes Search control and search query to a custom javascript function SearchBox.js which opens google search results in a new tab if google tab is selected.

function getResults(cliSrchobj,query) {

if($('#Googleli').hasClass('searchSelect'))
{
 var totalUrl = &quot;https://www.google.com/search?q=&quot;;
 totalUrl+= query;
 window.open(totalUrl,'_blank');

}
else
{
 cliSrchobj.search(query);
 return Srch.U.cancelEvent(event);
}

}

2013-11-18 12_37_10-Advent_QA - 54.236.214.160 - Remote Desktop Connection

Advertisements

15 thoughts on “SharePoint 2013: Basic Search box Customization

  1. Hi,

    Here are the steps I am doing.

    1. Copy and rename the Control_SearchBox_Compact.html
    2. Create the Visual studio project with element file and empty feature
    3. Copy and paste the text from Step 2 in the element file
    4. Deploy the solution
    5. Update the masterpage search control with the ControlId=”SmallSearchInputBoxCustom
    6. Paste text from Step 4 into Custom_Control_SearchBox_Compact.html file
    7. Reset iis
    8. When I reload my homepage there is no longer a search box.

    Also tried copied getResusts function script you have above and saved it as a SearcBox.js file

    You also reference SearchBox.css and SearchBox.js but I do not see that in your steps.

    Is it possible to get the files you are deploying?

    Thanks,

  2. In the step 2: make sure ypur custom JS display template is referenced
    ~sitecollection/_catalogs/masterpage/Display Templates/Search/Control_SearchBox_Compact.js

    Your custom JS , CSS can be referenced in display template like this

    $includeCSS(this.url,”~sitecollection/_catalogs/masterpage/Display Templates/Search/SearchBox.css”);
    $includeLanguageScript(this.url,”~sitecollection/_catalogs/masterpage/Display Templates/Search/jquery-1.9.1.js”);
    $includeLanguageScript(this.url,”~sitecollection/_catalogs/masterpage/Display Templates/Search/SearchBox.js”);

  3. Hi,

    I am following all of the steps just as you have listed them and this is not working for me.

    In Step 2 I am referencing the js template
    ~sitecollection/_catalogs/masterpage/Display Templates/Search/Custom_Control_SearchBox_Compact.js

    I am using the text you provided in Step 4 which references the SearchBox.css and SearcBox.js but what are those files supposed to be? What is the Searchbox.js? Where is the Css that you are using in your example?

    Thanks,
    Karen

  4. Hi,

    Could you please refer how to display the Google search result in search web parts with default refiners.

    your response will really appreciate.

    Thanks
    Kumar

    • You cannot use the default refiners for Google search results. You should write your own refiner templates and results display template to acheive the results you expect.

  5. Hi,

    Thx for your response, I have search api which is based on Lucien. i like to hook my search api and like to display the result in search result web part and want to use search refiner web parts.

    could you please suggest how to achieve the same.

    Thanks
    Kumar

  6. Hi there,
    I am getting a few errors when deploying the solution…
    They are on the following lines:
    [&”MasterPage&”]
    SmallSearchInputBoxCustom

    Any ideas?

    • Before deploying the solution “&” in the elements.xml should be encoded. Change [&”MasterPage&”] to

        <Property Name="QueryGroupNamesJson">[&quot;MasterPage&quot;]</Property>
      
  7. Hi

    I followed your steps and Copied “Control_SearchBox_Compact.html” from 15 hives and I renamed it “Custom_Control_SearchBox_Compact.html” and pasted back in 15 hives same location but still not able to find the “Custom_Control_SearchBox_Compact.js” file. Could you please let me know how to follow this step.

    Thanks in Advance,
    Pradeep

  8. Hi,

    We need to open search documents in new window. How can we achieve this. Please let me know if you have any solution for this.

    Thanks,
    Saran

  9. Thanks for the article, it was helpful. But I think there’s a mistake in step 2. Here is the delegate control I used to get this to work:

    In step 2, you set ControlId to SmallSearchInputBoxCustom, but it should be set to match the first ID field (not the property) in elements.xml. This is also consistent with the OOB configuration where ControlId=”SmallSearchInputBox” as opposed to SmallSearchInputBox1 which is given in SearchArea.xml.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s