<style type="text/css">
/* Hide the search scope fields as we don't take their input */
.ms-sbscopes {display:none} /* MOSS */
#idSearchScope {display:none} /* WSS */
.quickSearchResultDivUnselected
{
background: white;
border: 1px solid white;
margin-left: 2px;
overflow: hidden;
text-overflow: ellipsis;
}
.quickSearchResultDivSelected
{
background: #EEEEEE;
border: 1px solid Gray;
margin-left: 2px;
overflow: hidden;
text-overflow: ellipsis;
}
</style>
<!-- Load the JQuery Libraries that ship with Infuser -->
<script type="text/javascript" src="/_layouts/Muhimbi.Infuser/JQuery/jquery-1.3.2.min.js"></script>
<script type="text/javascript">
// QuickSearch v0.2
// Created by Jan Tielens, http://weblogs.asp.net/jan
// Modified to integrate with standard Seachbox by www.muhimbi.com
// This sample code is provided on an “as is” basis and without warranty of any kind.
// *** Customizable parameters ***
var quickSearchConfig = {
delay: 500, // time to wait before executing the query (in ms)
minCharacters: 3, // minimum nr of characters to enter before search
scope: "All Sites", // search scope to use 'All Sites'
numberOfResults: 15, // number of results to show
resultsAnimation: 200, // animation time (in ms) of the search results
resultAnimation: 0 // animation time (in ms) of individual result (when selected)
};
var quickSearchTimer;
var quickSearchSelectedDivIndex = -1;
var searchBox = null;
// ** Hook up the various events
jQuery.event.add(window, "resize", resizeWindow);
jQuery.event.add(document, "click", hideResultsDiv);
$(document).ready(function() {
// ** The searchbox uses a dynamic ID so select it by class
searchBox = $('.ms-sbplain');
// Muhimbi, insert the results box after te search area
searchBox.after("<div id=\"quickSearchResults\" style=\"display: none; z-index:1000\"></div>");
searchBox.keyup(function(event) {
var previousSelected = quickSearchSelectedDivIndex;
// catch some keys
switch(event.keyCode) {
case 13: // enter
var selectedDiv = $("#quickSearchResults>div:eq(" + quickSearchSelectedDivIndex + ") a");
if(selectedDiv.length == 1)
window.location = selectedDiv.attr("href");
break;
case 38: // key up
quickSearchSelectedDivIndex--;
break;
case 40: // key down
quickSearchSelectedDivIndex ++;
break;
}
// check bounds
if(quickSearchSelectedDivIndex != previousSelected) {
if(quickSearchSelectedDivIndex < 0)
quickSearchSelectedDivIndex = 0;
if(quickSearchSelectedDivIndex >= $("#quickSearchResults>div").length -1)
quickSearchSelectedDivIndex = $("#quickSearchResults>div").length - 2;
}
// select new div, unselect the previous selected
if(quickSearchSelectedDivIndex > -1) {
if(quickSearchSelectedDivIndex != previousSelected) {
unSelectDiv( $("#quickSearchResults>div:eq(" + previousSelected + ")"));
selectDiv($("#quickSearchResults>div:eq(" + quickSearchSelectedDivIndex + ")"));
}
}
// if the query is different from the previous one, search again
if($(searchBox).data("query") != $(searchBox).val()) {
if (quickSearchTimer != null) // cancel the delayed event
clearTimeout(quickSearchTimer);
quickSearchTimer = setTimeout(function() { // delay the searching
$("#quickSearchResults").fadeOut(200, initSearch);
} , quickSearchConfig.delay);
}
});
});
function showResultsDiv(text) {
var div = $("#quickSearchResults");
resizeWindow();
div.append(text).slideDown(quickSearchConfig.resultsAnimation);
}
function hideResultsDiv() {
var div = $("#quickSearchResults");
div.slideUp(quickSearchConfig.resultsAnimation);
div.empty()
}
function resizeWindow()
{
var div = $("#quickSearchResults");
var searchParent = $(searchBox).parent();
var divCss = {
"left": searchParent.offset().left,
"padding": 0,
"position": "absolute",
"top": searchParent.offset().top + searchParent.height() + 1,
"border": "1px solid #7f9db9",
"width": searchParent.width(),
"background": "white",
"max-width": searchParent.width()
};
div.css(divCss);
}
function unSelectDiv(div) {
// first stop all animations still in progress
$("#quickSearchResults>div>div").stop(true,true);
div.removeClass("quickSearchResultDivSelected").addClass("quickSearchResultDivUnselected");
$("#details", div).hide();
}
function selectDiv(div) {
div.addClass("quickSearchResultDivSelected");
$("#details", div).slideDown(quickSearchConfig.resultAnimation);
}
function initSearch() {
// first store query in data
$(searchBox).data("query", $(searchBox).val());
// clear the results
$("#quickSearchResults").empty();
// start the search
var query = $(searchBox).val();
if(query.length >= quickSearchConfig.minCharacters) {
showResultsDiv("Searching ..."); // display status
search(query);
}
}
function search(query) {
quickSearchSelectedDivIndex = -1;
var queryXML =
"<QueryPacket xmlns='urn:Microsoft.Search.Query' Revision='1000'> \
<Query domain='QDomain'> \
<SupportedFormats> \
<Format>urn:Microsoft.Search.Response.Document.Document</Format> \
</SupportedFormats> \
<Context> \
<QueryText language='en-US' type='STRING' >SCOPE:\"" +
quickSearchConfig.scope + "\"" + query + "</QueryText> \
</Context> \
<SortByProperties> \
<SortByProperty name='Rank' direction='Descending' order='1'/> \
</SortByProperties> \
<Range><StartAt>1</StartAt><Count>" + quickSearchConfig.numberOfResults + "</Count></Range> \
<EnableStemming>false</EnableStemming> \
<TrimDuplicates>true</TrimDuplicates> \
<IgnoreAllNoiseQuery>true</IgnoreAllNoiseQuery> \
<ImplicitAndBehavior>true</ImplicitAndBehavior> \
<IncludeRelevanceResults>true</IncludeRelevanceResults> \
<IncludeSpecialTermResults>true</IncludeSpecialTermResults> \
<IncludeHighConfidenceResults>true</IncludeHighConfidenceResults> \
</Query></QueryPacket>";
var soapEnv =
"<soap:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'" +
" xmlns:xsd='http://www.w3.org/2001/XMLSchema' \
xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'> \
<soap:Body> \
<Query xmlns='urn:Microsoft.Search'> \
<queryXml>" + escapeHTML(queryXML) + "</queryXml> \
</Query> \
</soap:Body> \
</soap:Envelope>";
$.ajax({
url: L_Menu_BaseUrl + "/_vti_bin/search.asmx",
type: "POST",
dataType: "xml",
data: soapEnv,
complete: processResult,
contentType: "text/xml; charset=\"utf-8\""
});
function processResult(xData, status) {
var html = "";
$(xData.responseXML).find("QueryResult").each(function() {
var divWidth = $(searchBox).parent().width() + 20;
var x = $("<xml>" + $(this).text() + "</xml>");
x.find("Document").each(function() {
var title = $("Title", $(this)).text();
var url = $("Action>LinkUrl", $(this)).text();
var description = $("Description", $(this)).text()
html +=
"<div class='quickSearchResultDivUnselected' style='width:" + divWidth +
"px;max-width:" + divWidth +"px'> \
<a href=\"" + url + "\">" + $("Title", $(this)).text() + "</a> \
<div style='display:none' id='details' style='margin-left:10px'>"
+ description +
"<br/>" + url + " \
</div> \
</div>";
});
if(x.find("TotalAvailable").text() != "")
html += "<div style='text-align:center; width:" + divWidth +
"px'>Total results: " + x.find("TotalAvailable").text() + "</div>";
else
html += "<div style='text-align:center; width:" + divWidth +
"px'>Total results: 0</div>";
});
$("#quickSearchResults").empty().append(html);
$("#quickSearchResults>div>a").hover(
function() { selectDiv($(this).parent()); },
function() { unSelectDiv($(this).parent()); }
);
showResultsDiv();
}
}
function escapeHTML (str) {
return str.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
}
</script>
7 Comments:
Perfecto! Found just one bug for now: it doesn't recognize (') apostrophes. Returns a page with whatever text is better the apostrophe.
By
Anonymous, At
01 October, 2009 19:10
Can this be used in a list-limited or site limited manner rather than searching across "All Sites". I've tried and it hasnt worked.
By
Anonymous, At
01 October, 2009 21:44
Sure it can, but it requires a little bit of programming, which is really beyond the scope of this example.
You will need to update the query that is send to the Search Web Service. A quick Google should give you some examples.
By
Muhimbi, At
01 October, 2009 22:26
Regarding the issue with the apostrophe, I have never seen one in a SharePoint URL, but I have updated the code.
Changed line 221 from
<a href='" + url + "'>" + $("Title", $(this)).text() + "</a> \
to
<a href=\"" + url + "\">" + $("Title", $(this)).text() + "</a> \
By
Muhimbi, At
02 October, 2009 10:59
Any luck with WSS compatibility?
By
Gee Why, At
25 November, 2009 21:16
Hi Gee,
This is just a proof of concept, we are not actively developing this script. However, I believe if you look on endusersharepoint.com in the comments then you'll find someone who has made it compatible with WSS.
Jeroen
By
Muhimbi, At
26 November, 2009 09:06
Great post. That inspired me to offer another version with a few more enhancements: http://herve20.blogspot.com/2009/12/sharepoint-people-search-autocomplete.html
By
Unknown, At
27 December, 2009 17:25
Post a Comment
Subscribe to Post Comments [Atom]