Have you ever wanted to allow a Web user to perform a custom search, then return a partial result set and allow the user to step through the results with a next and previous button? Many times the standard query feature provided by Domino is too limited. The problem with providing a previous and next button for web searches is that you have no context that maintains the results set. So, you really don't know where you were in the result set when the user hits previous or next. Here's an R5 solution for providing this feature on your web sites.
1) Allow the user to specify search criteria on a search form. This might include various fields the user can search or dialog lists to search keyword fields, for example a State pull down list. Provide a search button to execute the search results. The Search button will execute an agent that performs the search and writes the results back to a variable on the search form. When you execute an agent in R5 (toolsrunmacro), the Domino server runs the agent and redisplays the current form again.
2) Use a field on the result form to keep track of the "current page" of results the user is viewing. My example uses "SearchCurPage". Set its default value to 1.
3) On the results page, your next and previous buttons will increment or decrement the page counter variable.
4) When the user hits the next or previous buttons, you increment or decrement the current page counter and execute your search agent again. For example, the next button would add one to the page counter and re-execute the search agent.
Here's the code for the next button:
FIELD SearchCurPage := @If(SearchCurPage<SearchNumPages;SearchCurPage + 1;SearchCurPage); @Command([ToolsRunMacro]; "(WebSearch)")
Here's the code for the previous button:
FIELD SearchCurPage := @If(SearchCurPage>1;SearchCurPage - 1;SearchCurPage); @Command([ToolsRunMacro]; "(WebSearch)")
5) The agent brings back the same (entire) results each time. You just need to put a counter in the result processing portion that will skip the results that are not on the page the user is requesting. This is of course dependent on the number of results you want to display per page. Here's the script code:
"itemcount" is the total number of results returned. "Find_Results" is the form field (Rich Text) that will show the results. "ResultsPerPage" is a script variable that determines the number of results to show per page. "RowHTML" is an array that contains the search results data to display. Set doc = Session.DocumentContext If itemcount > 0 Then Set rtitem = New NotesRichTextItem(doc ,"Find_Results") For z = 1 To itemcount If Fix((z - 1)/ResultsPerPage) + 1 = Doc.SearchCurPage(0) Then Call rtitem.AppendText("["+RowHTML(z)+"]") End If Next Else doc.Find_Results="Sorry No Items Found" End If
6) I also keep track of the total number of pages within the agent and write this back to another field on the form. This allows me to hide the next button if the current page equals the number of pages. You can also hide the previous button if the current page equals 1.
'Compute number of total pages - ALWAYS remainder = itemcount Mod ResultsPerPage doc.SearchNumpages =Fix(itemcount / ResultsPerPage) If remainder > 0 Then doc.SearchNumPages = doc.SearchNumPages(0) + 1 End If
7) Some additional tips:
- The Search button should always set the current page counter back to 1, before executing the WebSearch agent. This is needed in case the user changes the search criteria and hits the search button again.
- You can build an HTML table in the result set variable on the form to display your results in a nice and neat layout.
- Use a variable in the search agent to specify the number of results to display per page. This allows you to easily change this setting without having to change several lines of code. (ResultsPerPage in the examples)
- You can bring back results into an array and sort the results before you process them for display.
- Here's some script to compute a text string that shows the user the total number of results and the current result subset being displayed.
If itemcount > 1 Then If itemcount > ResultsPerPage Then Mindsp = ((doc.SearchCurPage(0) - 1) * ResultsPerPage) + 1 maxdsp = doc.SearchCurPage(0) * ResultsPerPage If MaxDsp > itemcount Then MaxDsp = itemcount End If Header ="[<b><br>"+Cstr(itemcount) + " Items Found, Showing Results " + Cstr(MinDsp) + " - " + Cstr(MaxDsp)+"<br>]" Else Header = "[<b><br>"+Cstr(itemcount) + " Items Found<br>]" End If Else If itemcount = 1 Then Header = "[<b><br>1 Item Found<br>]" End If End If
- Advanced Tip! Create a table header on your search form that allows the user to click on column headings to sort the results by different columns. Just like the Notes client!
Simply create an action hotspot that sets a variable to keep track of the current sort order chosen by the user.
Here's an example hotspot action:
FIELD CurSearchSort := "CODE"; FIELD SearchCurPage := 1; @Command([ToolsRunMacro]; "(WebSearch)")
Here's the section of script that builds a set of arrays based on the sort order chosen by the user:
Select Case doc.CurSearchSort(0) Case "PO" TextSort(itemcount) = founddoc.OrderNo(0) Case "CODE" TextSort(itemcount) = founddoc.Code(0) Case "DATE" If Isdate(founddoc.SHIPDATE(0)) Then TextSort(itemcount) = Format(founddoc.SHIPDATE(0),"yyyy-mm-dd") End If End Select 'temp contains a previous built HTML string to display the search result row RowHTML(itemcount)= temp
This example uses a simple bubble sort to sort the array of search items in ascending order. This is accomplished by using two arrays. One array contains the text data to be sorted, the second array is used to hold the HTML data that will be used to build the search results table.
If Itemcount > 1 Then For w = 1 To itemcount-1 For x = w+1 To itemcount If (TextSort(w) > TextSort(x))Then 'swap swapstr = TextSort(w) TextSort(w) = TextSort(x) TextSort(x) = swapstr swapstr = RowHTML(w) RowHTML(w) = RowHTML(x) RowHTML(x) = swapstr End If Next Next End If