While we followed the example provided, there are some differences. In the example, coordinate information is returned from the backend, whereas our backend only returns the page number and ambient string. As a result, we disabled the search button and built our own search component/control. With our control, the user clicks search, and we call our backend search engine to retrieve the page number and ambient string. We then loop through each page returned by the search engine, perform a programmatic search, and highlight the results. However, we’ve encountered a couple of issues with the programmatic search, navigation, and highlighting. We’re hoping to receive some assistance in resolving these issues.
- When a user clicks on a search result in our custom component, we call the setCurrentPage() method. However, when we do this, the pages in the viewer become left-aligned for some reason. If the outline panel or any other panel is opened, the pages go back to center alignment. We want to keep the pages centered in the viewer, but we’re not sure why calling this method causes them to snap from center alignment to left alignment. We’ve already tried calling the RefreshAll() and RefreshPage() methods, but they don’t appear to have any effect. Below is the method that gets called on the component result click event.
setActiveSearchResultItem(item: SearchResultModel){
this.activeSearchResult = item;
const { documentViewer } = this.wvInstance.Core;
documentViewer.setCurrentPage(item.pageNumber, true);
}
- When we perform programmatic search and highlighting using documentViewer.textSearchInit(), the results and highlighting are correct on most pages. However, on some pages, the results are correct, but the result coordinates are way off. The strange thing is that sometimes refreshing the browser on the same document solves the problem. We only see this behavior with .xod files; we don’t encounter this issue with PDFs. We’re not sure if there’s a race condition occurring, or if there’s a better way to perform programmatic search and highlighting. Below is the code that gets executed when users click search in our custom component.
async search(): Promise<void> {
const {documentViewer, annotationManager} = this.wvInstance.Core
this.clearHighlights();
await this.getSearchResultsFromBackend();
//Only do searches on pages that backend says that phrase exists on.
let pagesToSearchInViewer = [...new Set(this.results.map((result) => result.pageNumber))];
for (const pageNumber of pagesToSearchInViewer) {
await this.searchForTextInViewer(pageNumber, this.searchFor);
if (pageNumber == documentViewer.getCurrentPage()){
annotationManager.drawAnnotations({pageNumber:pageNumber})
}
}
}
///search for the text for the passed in page and highlights it.
//Based on https://docs.apryse.com/documentation/web/guides/advance-text-search/
//Based on https://community.apryse.com/t/is-it-possible-to-use-textsearchinit-to-search-for-a-list-of-terms/4717/6
searchForTextInViewer = (pageNumber: number, textToSearch: string) => {
return new Promise<void>(resolve => {
console.log('Search for text ' + textToSearch + ' on page ' + pageNumber)
const { documentViewer, Search } = this.wvInstance.Core;
let mode = Search.Mode.PAGE_STOP | Search.Mode.HIGHLIGHT;
let options = {
fullSearch: true,
startPage: pageNumber,
endPage: pageNumber,
onPageEnd: result => {
console.log('Finish searching page.');
console.log(result);
resolve();
},
onError: error => {
console.log('Error occurred while searching.');
console.log(error);
},
onResult: result => {
console.log('Result while searching.');
console.log(result);
if (result.resultCode === Search.ResultCode.FOUND) {
//Seems like there is a bug in that the search results return to many decimal places for the highlight annotation quads.
//Rounding to nearest seems to work.
let quads: Core.Math.Quad[] = result.quads.map((coords: any) => {
let point = coords.getPoints();
//Rounding to get highlights to show. If left as is, no highlights show.
return new this.wvInstance.Core.Math.Quad(
Math.round(point.x1),
Math.round(point.y1),
Math.round(point.x2),
Math.round(point.y2),
Math.round(point.x3),
Math.round(point.y3),
Math.round(point.x4),
Math.round(point.y4))
})
this.highlightText(result.pageNum, quads);
}
}
};
documentViewer.textSearchInit(textToSearch, mode, options);
})
}
highlightText(pageNumber: number, quads: Core.Math.Quad[]) : void {
//Based on https://docs.apryse.com/documentation/web/guides/create-annotation-highlight/
const { Annotations, annotationManager } = this.wvInstance.Core;
const highlight = new Annotations.TextHighlightAnnotation();
highlight.PageNumber = pageNumber;
highlight.Quads = quads;
highlight.StrokeColor = new Annotations.Color(255, 255, 0);
highlight.Listable = false;
annotationManager.addAnnotation(highlight);
this.searchHighlights.push(highlight);
}