How to create a FAQ in SharePoint with OOB features
There are lots of stuff in the web around how to create a FAQ in SharePoint.
To understand this post you should have some basic know-how about:
The following image shows us the final page.
Our FAQ page has a FAQ list and a document library. This is useful if you want to link on some documents in your FAQ. The page has a list WebPart with a special grouped view and also2 quick searches for documents and for the FAQ list.
I also use a category for my FAQ. To manage the category I've an own list "Basic themes", where the FAQ owner can manage his categories.
will be referenced by the FAQ list for categorize the FAQ. This list does need nothing but a title. This titles will categorize our FAQ.
Our FAQ needs now some fields. You can easily add more fields if you want but for my FAQ I took the following fields:
Script to search the document library
The second script is to set a search. The search results appear in a dialog box. I find this very handy. Copy now the following script into a .txt file and upload it also to your site assets library. Adapt the list and site parameters in the script to search the correct site and library .
Go to your home site and click on edit.Click on "Add WebPart" on the right section and choose the "HtmlFormsWebPart" from "Forms" category.
The cool thing about the html forms WebPart is that you can connect to other WebParts with it.
Open the settings of this WebPart and click on "Sourcecode editor". Put the following source code in it. Check if the list name in the code "Basicthemes" matches your list name, else change it to your list name.
This code loads the entries from the "Basicthemes" list into a dropdown menu, which can be used for filtering.
In the upcoming Window choose :
Click on "Save" and save your WebPart Settings. The connection should be etablished now.
Other problems can be that the list or site names are wrong in the scripts. Pay attention that you change every setting. Search & replace is a good tactic in such a case. You can also edit the .txt file in the site assets library in Explorer View directly in NotePad++. So don't have to down- and upload everytime.
In this post I'll show you some tricks what you can do with additional OOB SharePoint tools to have also some search and some style within your FAQ to impress your customer. It also shows you the power of SharePoint as a developer platform.
The requirements for our FAQ are:
- Easy to maintain
- Easy to search content
- Add documents as links in FAQ
- Grouped FAQ content
- Export FAQ when needed into a report
To understand this post you should have some basic know-how about:
- SharePoint Lists
- SharePoint List Views
- HTML, CSS
- JavaScript (SharePoint Client API)
- SharePoint WebParts
- CAML
The following image shows us the final page.
Final FAQ Pag |
Our FAQ page has a FAQ list and a document library. This is useful if you want to link on some documents in your FAQ. The page has a list WebPart with a special grouped view and also2 quick searches for documents and for the FAQ list.
I also use a category for my FAQ. To manage the category I've an own list "Basic themes", where the FAQ owner can manage his categories.
Steps to create the FAQ
1. STEP : Create a site
Create a own site collection for your FAQ. Use the blank site template.2. STEP : Create the Basic Themes List
Use the "Custom List Template" to create the Basic themes List. Name the list "Basicthemes". This listwill be referenced by the FAQ list for categorize the FAQ. This list does need nothing but a title. This titles will categorize our FAQ.
3. STEP : Create a document library
Create a standard document library and call it "Documents". This library will contain documents referenced by the FAQ.4. STEP : Create the FAQ List
Use the "Custom List Template" to create the FAQ List. Name the list "FAQ".Our FAQ needs now some fields. You can easily add more fields if you want but for my FAQ I took the following fields:
Field name | Field type |
Title | Single line of text |
Theme | Lookup to Basic Themes List on Title |
Question | Multiple line of text |
Answer | Multiple line of text |
5. STEP: Create a group view
Go to the FAQ list and create a new view. Call it "WebPart View". Use following settings
Search FAQ Script
Script to search FAQ content. Copy the code into a .txt file and upload it to the "Site Assets" library.
Adapt the list url and site url settings in the code. Check in the "BAR.CreateXML" function that the field names are set correct like in your library.
This script contains also some css to make the list view more readable.
View option | Option values |
Fields : | Question, Answer |
Group by : | Theme than title |
Format: | Magazine |
6. STEP: Create an asset library
Create a document or asset library and name it "Site Assets". This library will contain some scripts we need for the site.7. STEP Upload Quick Search Scripts
Upload the following scripts to the "Site Assets" library. Adapt the list/site names in the scripts with the names of your list/site.Search FAQ Script
Script to search FAQ content. Copy the code into a .txt file and upload it to the "Site Assets" library.
Adapt the list url and site url settings in the code. Check in the "BAR.CreateXML" function that the field names are set correct like in your library.
This script contains also some css to make the list view more readable.
<style type="text/css">
#SearchResults ul { padding-left:10px }
#SearchResults li { margin-bottom:5px }
#SearchResults span { color:#666 }
.biggySearcher div.s4-search { width:100%; height:30px }
.biggySearcher .ms-sbplain { width:150px }
.ms-listviewtable tbody tr+tr+tr .ms-rtestate-field {
font-weight:bold;
font-size: 14px;
background-color:#eee;
padding:2px 0;
border-bottom:1px solid #de3400
}
.ms-listviewtable tbody tr+tr+tr+tr .ms-rtestate-field {
font-weight:normal;
font-size: inherit;
background-color:#fff
}
</style>
<script type="text/javascript">
if (typeof BAR == "undefined") {
BAR = {};
}
BAR.siteUrl = "/sites/claims";
BAR.listName = "FAQ"; // Displayname
BAR.listUrl = BAR.siteUrl + '/Lists/faq'
BAR.resultItems = null;
BAR.StartQuery = function() {
var text = document.getElementById("QueryText").value;
text = text.replace(/^\s+|\s+$/g, ""); // Trim
var result = BAR.CreateQuery(text);
BAR.QueryList(result);
}
BAR.CreateQuery = function( pSearchText )
{
var result = "";
var searchWords = pSearchText.split(" ");
for (var i=0;i<searchWords.length;i++){
if (searchWords[i] != "") {
if (i>0) result = "<And>" +result;
result += BAR.CreateXML(searchWords[i]);
if (i>0) result += "</And>";
}
}
return result;
}
BAR.CreateXML = function(pSearchText) {
return ' <Or>'
+ ' <Or>'
+ ' <Contains>'
+ ' <FieldRef Name="Title" />'
+ ' <Value Type="Text">'+ pSearchText +'</Value>'
+ ' </Contains>'
+ ' <Contains>'
+ ' <FieldRef Name="Question" />'
+ ' <Value Type="Note">'+ pSearchText +'</Value>'
+ ' </Contains>'
+ ' </Or>'
+ ' <Contains>'
+ ' <FieldRef Name="Answer" />'
+ ' <Value Type="Note">'+ pSearchText +'</Value>'
+ ' </Contains>'
+ ' </Or>'
}
BAR.QueryList = function(pSearchXML){
var context = new SP.ClientContext(BAR.siteUrl);
var oList = context.get_web().get_lists().getByTitle(BAR.listName);
var camlQuery = new SP.CamlQuery();
camlQuery.set_viewXml("<View><Query>"
+ '<Where>'
+ pSearchXML
+ '</Where>'
+ '</Query><RowLimit>10</RowLimit></View>');
BAR.resultItems = oList.getItems(camlQuery);
context.load(BAR.resultItems, 'Include(Id, Title, Frage, Basisthema)');
context.executeQueryAsync(
Function.createDelegate(this, BAR.onQuerySucceeded),
Function.createDelegate(this, BAR.onQueryFailed)
);
}
BAR.onQuerySucceeded = function(sender, args) {
var resultHTML = [];
var listItemEnumerator = BAR.resultItems.getEnumerator();
var i = 0;
while (listItemEnumerator.moveNext()) {
i++;
var oListItem = listItemEnumerator.get_current();
var id = oListItem.get_id();
var theme = oListItem.get_item('Basisthema').get_lookupValue();
var title = oListItem.get_item('Title');
var quest = oListItem.get_item('Frage').substr(0,120);
resultHTML.push('<li>');
resultHTML.push('<a href="javascript:EditItem2(null,\''+ BAR.listUrl +'/DispForm.aspx?ID='+ id +'\')">' + title + '</a>');
resultHTML.push('<br/>('+ theme +')');
resultHTML.push('<br/><span>'+ quest +' ...</span>');
resultHTML.push('</li>');
}
if (i == 0)
resultHTML.push('<li><span>No FAQ entry found.</span></li>');
document.getElementById("SearchResults").innerHTML = resultHTML.join("");
}
BAR.onQueryFailed = function(sender, args) {
alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
}
</script>
<div class="biggySearcher">
<div class="s4-search">
<table class="ms-sbtable s4-search"><tr>
<td class="ms-sbcell">
<input type="text" class="ms-sbplain" id="QueryText" />
</td>
<td class="ms-sbgo ms-sbcell">
<img src="/_layouts/images/gosearch15.png" alt="Search" class="srch-gosearchimg"
onmouseout="this.src='\u002f_layouts\u002fimages\u002fgosearch15.png'"
onmouseover="this.src='\u002f_layouts\u002fimages\u002fgosearchhover15.png'" title="Search"
onclick="BAR.StartQuery()" />
</td>
</tr></table>
</div>
<ul id="SearchResults"></ul>
</div>
Script to search the document library
The second script is to set a search. The search results appear in a dialog box. I find this very handy. Copy now the following script into a .txt file and upload it also to your site assets library. Adapt the list and site parameters in the script to search the correct site and library .
<script type="text/javascript">
if (typeof BAR == "undefined") {
BAR = {};
}
BAR.siteUrl = '/sites/myfaq';
BAR.documentLibUrl = 'http://sharepoint/sites/myfaq/documents'
BAR.QueryDocs = function() {
var text = document.getElementById("QueryTextDocs").value;
text = text.replace(/^\s+|\s+$/g, ""); // Trim
text = "*" + text + "*"
EditItem2(null, BAR.siteUrl + '/_layouts/OSSSearchResults.aspx?k=' + text + '&cs=This%20List&u=' + encodeURIComponent(BAR.documentLibUrl) );
}
</script>
<div class="biggySearcher">
<div class="s4-search">
<table class="ms-sbtable s4-search"><tr>
<td class="ms-sbcell">
<input type="text" class="ms-sbplain" id="QueryTextDocs" />
</td>
<td class="ms-sbgo ms-sbcell">
<img src="/_layouts/images/gosearch15.png" alt="Search" class="srch-gosearchimg"
onmouseout="this.src='\u002f_layouts\u002fimages\u002fgosearch15.png'"
onmouseover="this.src='\u002f_layouts\u002fimages\u002fgosearchhover15.png'" title="Search"
onclick="BAR.QueryDocs()" />
</td>
</tr></table>
</div>
</div>
8. STEP: Insert the FAQ List into your page
Goto your home site and click on edit. Add your FAQ list to the middle WebPart section. Click on "Add WebPart" and choose the FAQ list. Choose the WebPart View from the WebPart settings.9. STEP: Insert FAQ Document Search
Goto your home site and click on edit. Add a "Content Viewer WebPart" to the right WebPart section. Go to the WebPart settings and put into the top text box the path to the uploaded txt file, which contains the documents query.10. STEP: Insert FAQ Quick Search
Do the same for the FAQ query file.11. STEP: Adding category filter WebPart
In this step we want to add the category filter:Go to your home site and click on edit.Click on "Add WebPart" on the right section and choose the "HtmlFormsWebPart" from "Forms" category.
The cool thing about the html forms WebPart is that you can connect to other WebParts with it.
Open the settings of this WebPart and click on "Sourcecode editor". Put the following source code in it. Check if the list name in the code "Basicthemes" matches your list name, else change it to your list name.
This code loads the entries from the "Basicthemes" list into a dropdown menu, which can be used for filtering.
<div onkeydown="javascript:if (event.keyCode == 13) _SFSUBMIT_" style="margin-bottom:5px">
<select id="selThemes" name="T1"></select>
<input type="button" value="Filter" onclick="javascript:_SFSUBMIT_"/>
</div>
<span style="height:11px;width:11px;position:relative;display:inline-block;overflow:hidden;">
<img style="position:absolute;border:0;left:0;top:-584px" src="/_layouts/images/fgimg.png" />
</span>
<a href="javascript:location.href=location.href">Reset Filter</a>
<script type="text/javascript">
function LoadSelectThemes() {
var context = SP.ClientContext.get_current();
var list = context.get_web().get_lists().getByTitle('Basicthemes');
var camlQuery = SP.CamlQuery.createAllItemsQuery();
var items = list.getItems(camlQuery);
context.load(items, 'Include(Title, Id)');
context.executeQueryAsync(
function(){
var listItemEnumerator = items.getEnumerator();
var oSelect = document.getElementById("selThemes");
while (listItemEnumerator.moveNext()) {
var oListItem = listItemEnumerator.get_current();
var title = oListItem.get_item('Title');
var option = document.createElement("option");
option.innerHTML = title;
option.value = title;
if (oSelect != null){
oSelect.appendChild(option);
}
}
},
function(sender, args) {
alert('List Data fetch failed. ' + args.get_message() + 'n' + args.get_stackTrace());
}
);
}
window.onload = function(){ ExecuteOrDelayUntilScriptLoaded(ViewItem, "sp.js"); };
</script>
12. STEP: Connecting the filter
In this step we connect the Form WebPart with the list view WebPart on the site. Edit you home site. Go to your WebPart Menu of your HTML Form WebPart and click on connections and choose FAQ.In the upcoming Window choose :
- Source field = T1
- Consumer field = Themes (The Lookup field)
Click on "Save" and save your WebPart Settings. The connection should be etablished now.
13. STEP: Testing
Most things should be straight forward. The HTMLFormWebPart caused me sometimes that the whole site stopped working because of wrong JavaScript code. In this case remove the WebPart by adding ?contents=1 to the URL. You will be redirected to the WebPart maintanance page.Other problems can be that the list or site names are wrong in the scripts. Pay attention that you change every setting. Search & replace is a good tactic in such a case. You can also edit the .txt file in the site assets library in Explorer View directly in NotePad++. So don't have to down- and upload everytime.
Comments
I got it fully working in 30 minutes. Awsome!