Showing posts with label Search Box Webpart. Show all posts
Showing posts with label Search Box Webpart. Show all posts

Wednesday, 9 October 2013

Customising the SharePoint Advanced Search Page

The SharePoint Enterprise Search site contains a number of pages when it's created. One of those pages is an Advanced Search page that can be used to create advanced search queries.




I answered a question in a forum recently about a specific problem customising this page. The forum user wanted to set the Result Type to "All Results", hide the Result Type label and drop-down box, but keep the property selector in the "Add property restrictions..." section. You can use the Advanced Search Box webparts toolpane properties to remove the Results Type selector, however, it also removes the "Add property restrictions..." section.

There are two solutions to achieve this; use JavaScript, or use CSS. The answer I posed was using CSS with specific selectors to hide the elements used to display the "Result Type" label and drop-down box.

Solution

1. Edit the Advanced Search page
2. Edit the Advanced Search Box webpart
3. In the webparts toolbox, expand the Scopes section
4. Un-check Show the languages picker
5. In the webparts toolbox, expand the Properties section


6. Copy the text in the Properties textbox to a notepad editor
7. Search for the string "<ResultTypes>"
8. Remove all the <ResultType> elements, except for the "All Results" element.


9. Copy the XML back into the Properties textbox in the webparts toolbox pane
10. Apply the changes to the Advanced Search Box webpart.
11. Add an HTML Form webpart to the page.
12. Add the following markup to the HTML form webpart

<style type="text/css">
td.ms-advsrchText-v2 > select[title='Result Type']{display:none}
td.ms-advsrchText-v1 > label[for*='_ASB_SS_rtlb']{display:none}
</style>


13. Save the HTML Form webparts properties
14. Save the page page.

The Advanced Search page now includes the property restrictions for the All Results result type, without displaying the Result Type picker.



CSS Explanation

To remove the Result Type label and drop-down box, we need two CSS rules to hide those elements.

The first CSS rule, "td.ms-advsrchText-v2 > select[title='Result Type']{display:none}", applies display:none to all select elements that have a title equal to "Result Type", appearing directly after a <td> element that contains the ms-advsrchText-v2 class (<td class="ms-advsrchText-v2>)

The second rule is slightly trickier. It looks as though there isn't something specific enough to hide the "Result Type" label with a CSS rule (without hiding other rows). However, the "for" attribute of the label contains a randomly generated unique string. This string, is only partially random. The last part of the string is constant, and we can use an attribute selector to select all labels that have a "for" element that ends in "_ABS_SS_rtlb". This does the job perfectly, selecting only the "Results Type" label.

This can be seen using the Internet Explorer Developer Tools (F12 in your Internet Explorer browser).




References

Forum content (advanced-search-web-part)


Tuesday, 6 March 2012

Extending the SharePoint Search Box (SearchBoxEx) webpart

I've just finished extending SharePoints Search Box (SearchBoxEx) webpart. I had requirements for three different search boxes (wildcarding the people search, adding a custom properties drop down box for advanced searching and adding an extra button for an optional people search).

The process for all three was largely the same. The method below outlines how I created the multi-button search box, embedded in our master page and looks like this:




The basic steps are;
1. Create a new webpart project and inherit from the SearchBoxEx class
2. Add an ImageButton that calls a (client side) javascript function
3. Copy, rename and modify the javascipt function that the oob webpart calls
4. Create the webpart.dwp file
5. Deploy the solution

This is what I did;
1. Create a new Empty SharePoint project
2. Add a reference to Microsoft.SharePoint.Portal
3. Add a new webpart to the project
4. In the webparts class file, adding the using statement and inherit the SearchBoxEx (Search Box webpart) class (See MSDN for more information)

using ...
using Microsoft.SharePoint.WebControls;

namespace Ince.SearchParts.MultiMiniSearchBox{
[ToolboxItemAttribute(false)]
public class MultiMiniSearchBox : Microsoft.SharePoint.Portal.WebControls.SearchBoxEx
{
...
} 

5. Add the ImageButton and initialise it.

private ImageButton _peopleSearch;
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
_peopleSearch = new ImageButton();
_peopleSearch.ID = "peopleMiniSearch";
_peopleSearch.EnableViewState = false;
_peopleSearch.CausesValidation = false;
_peopleSearch.ImageUrl = "/_layouts/images/ince/isqdepartment.png";
_peopleSearch.Height = new Unit(19, UnitType.Pixel);
_peopleSearch.CssClass = "isqPeopleSearchImg";
} 

6. Add two properties for the results pages (the search results page and the people search results page).

private string _peopleResultsUri = String.Empty;
[WebBrowsable(true), WebDisplayName("People Results Url"), Personalizable(PersonalizationScope.Shared), Category("Webpart Settings")]
public String PeopleResultsUri
{
get { return _peopleResultsUri; }
set { _peopleResultsUri = value; }
}

private string _searchResultsUri = String.Empty;
[WebBrowsable(true), WebDisplayName("Search Results Url"), Personalizable(PersonalizationScope.Shared), Category("Webpart Settings")]
public String SearchResultsUri
{
get { return _searchResultsUri; }
set { _searchResultsUri = value; }
} 

7. Add code to the CreateChildControls method to set the search results url properties.

Because I'm primarly using this webpart in the master page (and unable to set the properties from the toolpart pane), I'm looking for the results page URL in two locations. The first is the webparts properties (settable via the toolpart pane). If this is empty, then I'm checking the root webs property bag for the URL.

I'm also configuring the other settings for the webpart, like the scope, CSS, chrome, etc.

protected override void CreateChildControls()
{
base.CreateChildControls();
EnsureChildControls();
String peopleResultsUrl = this.SearchResultPageURL;
String searchResultsUrl = this.SearchResultPageURL;
try
{
var rootWeb = SPContext.Current.Site.RootWeb;
if (PeopleResultsUri != String.Empty)
{
peopleResultsUrl = PeopleResultsUri;
}
else
{
if (rootWeb.Properties.ContainsKey("inceIsqPeopleResultsUri"))
{
peopleResultsUrl = rootWeb.Properties["inceIsqPeopleResultsUri"];
}
}
if (SearchResultsUri != String.Empty)
{
searchResultsUrl = SearchResultsUri;
}
else
{
if (rootWeb.Properties.ContainsKey("inceIsqSearchResultsUri"))
{
searchResultsUrl = rootWeb.Properties["inceIsqSearchResultsUri"];
}
}
}
catch (Exception exception)
{
SPDiagnosticsService.Local.WriteTrace(0, HighCategory(), TraceSeverity.High, 
String.Format("[CreateChildControls] Unhandled Exception getting results page urls. Error: {0}", 
    exception.Message), "");
}
_peopleSearch.Style.Clear();
_peopleSearch.OnClientClick = String.Format("javascript:isqPeopleSearch('{0}', '{1}');return;", 
    m_searchKeyWordTextBox.ClientID, peopleResultsUrl);
Controls.Add(_peopleSearch);
this.UseSiteDropDownMode = false;
this.SearchResultPageURL = searchResultsUrl;
this.AdvancedSearchPageURL = searchResultsUrl;
this.ChromeType = PartChromeType.None;
this.GoImageActiveUrl = this.GoImageUrl;
this.CssClass = "isqSearchBoxExOveride";
this.DropDownMode = DropDownModes.HideScopeDD;
this.DropDownModeEx = DropDownModesEx.HideScopeDD;
this.QueryPromptString = String.Empty;
} 

8. Attach the CSS and JavaScript

protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
CssRegistration.Register("/_layouts/styles/ince/ince-searchparts.css?v2");
ClientScriptManager cs = Page.ClientScript;
if (!cs.IsStartupScriptRegistered("incesearchparts"))
{
cs.RegisterStartupScript(this.GetType(), "incesearchparts", 
    "<script type='text/javascript\' src='/_layouts/incejs/ince-searchparts.js?v2'></Script>");
cs.RegisterClientScriptInclude(this.GetType(), 
    "incesearchparts", "/_layouts/incejs/ince-searchparts.js?v2");
}
} 

9. Add the JavaScript function

The OOB search button calls a JavaScript function, which in turn calls the GoSearch(...) found in search.js

I pulled this function apart and copied out the bits I needed, then modified it to do what I needed (which was simply to wildcard the keyword if the people search button was clicked). This is what I ended up with:

function isqPeopleSearch(keywordElement, resultsPage)
{
var i = document.forms[0].elements[keywordElement].value;
i = i.replace(/\s*$/, "");
var b = "?s=People";
if (i == "")
{
alert("Please enter one or more search words.");
if (null != event) {
event.returnValue = false; return false
}
else
return;
}
b += "&k="+i+"*";
window.location = resultsPage + b;
try {
if (null != event)
event.returnValue = false
}
catch (s) {
}
return
} 

10. Create the dwp file.

Before deploying the solution and adding the webpart, you'll need to create a .dwp webpart description file, and modify the elements.xml file.

10.1 Elements XML

Open the elements.xml file, and change the extension of the webpart file from .webpart to .dwp. My elements.xml file now looks like this:

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/" >
<Module Name="MultiMiniSearchBox" List="113" Url="_catalogs/wp">
<File Path="MultiMiniSearchBox\MultiMiniSearchBox.dwp" 
    Url="MultiMiniSearchBox.dwp" Type="GhostableInLibrary">
<Property Name="Group" Value="Ince Search" />
</File>
</Module>
</Elements> 

10.2 Create the dwp file

Right click the webpart and select Add. Add new XML file, giving it the same file name used in the elements.xml file (i.e. MultiMiniSearchBox.dwp)

Now add all the webpart properties to the xml file (make sure you get the Assembly and TypeName correct). There's other documentation and blogs on how to do this, but my slimmed down version was:

<?xml version="1.0" encoding="utf-8"?>
<WebPart xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns="http://schemas.microsoft.com/WebPart/v2">
<Title>Multi Min Search Box</Title>
<FrameType>None</FrameType>
<Description>Displays a search box that allows users to search for information or people.</Description>
<IsIncluded>true</IsIncluded>
<IsVisible>true</IsVisible>
<HelpMode>Modeless</HelpMode>
<Dir>Default</Dir>
<MissingAssembly>Cannot import this Web Part.</MissingAssembly>
<Assembly>Ince.SearchParts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=e69a99a27d408090</Assembly>
<TypeName>Ince.SearchParts.MultiMiniSearchBox.MultiMiniSearchBox</TypeName>
<ShouldTakeFocusIfEmpty xmlns="urn:schemas-microsoft-com:SearchBoxEx">true</ShouldTakeFocusIfEmpty>
</WebPart> 

10.3 Change the Deployment Type for the new .dwp file

Click the new .dwp file in Solution Explorer, and view the properties. Change the Deployment Type to ElementFile.

10.4 Delete the old .webpart file

11. Deploy the solution