Search

Native text search in the Viewer composition

The Doconut Viewer provides normal Search using text extracted by the format viewer or a text-based PDF redirect. It requires the Search license capability.

Enable the search UI

Search is a Viewer module, not a standalone toolbar. The complete page must include the Viewer resources, Viewer toolbar, Viewer mount, and initialized objViewer; the Search Ribbon is then mounted and attached to that same instance.

Search and annotation are built-in licensed features, not AddPlugin<T>() packages. Request the search resources from Viewer; their tags are emitted only when the license grants Search. MVC 5 views have no @inject, so build the tags in the controller and pass them on ViewBag, together with the license flag the page needs:

csharp
var viewer = Doconut.DoconutHost.Services.GetRequiredService<Viewer>();
ViewBag.ViewerCss = viewer.ReferenceCss(new CssConfig
{
    IncludeViewerCss = true,
    IncludeSearchCss = true
});
ViewBag.ViewerScripts = viewer.ReferenceScripts(new ScriptConfig
{
    IncludeJQuery        = true,
    IncludeViewerScripts = true,
    IncludeSearchScripts = true,
    IncludeSearchBar     = true
});
ViewBag.IsSearchEnabled = viewer.IsSearchEnabled;

Write them in the view with @Html.Raw(ViewBag.ViewerCss) and @Html.Raw(ViewBag.ViewerScripts). In Web Forms, expose the same values from the code-behind and write them with <%= %>.

The embedded ribbon calls the same JavaScript methods available to a custom UI.

Keep the complete Viewer composition visible in the markup, initialize docViewer first, and then attach the licensed Ribbon:

html
<nav id="toolbar" aria-label="Document viewer controls">
    <!-- Viewer controls, including the button that opens Search -->
</nav>
<div id="searchBarMount"></div>
<div id="divDocViewer"><div id="div_ctlDoc"></div></div>

<script>
    let searchBar = null;
    let currentToken = '';

    const objViewer = $('#div_ctlDoc').docViewer({
        BasePath: '/',
        ResPath: 'doconut-res/images'
    });

    @if ((bool)ViewBag.IsSearchEnabled)
    {
        <text>
    searchBar = $('#searchBarMount').doconutSearchBar({
        docId: 'ctlDoc',
        getRequestParams: () => ({ token: currentToken }),
        onStatus: (message) => console.log(message),
        onToast: (message, type) => console.log(type, message),
        onLayout: () => requestAnimationFrame(() => objViewer.Refit())
    });
    searchBar.attach(objViewer);
        </text>
    }
</script>

The server-side if matters: without the Search capability, ReferenceScripts leaves out the Ribbon's script, so an unguarded doconutSearchBar(...) call would throw and stop the viewer page from starting. In Web Forms, write the same guard as <% if (IsSearchEnabled) { %> … <% } %>.

The component injects Find, Options, and Results groups and handles searching, clearing, match counts, and previous/next match navigation. A host-owned Viewer toolbar only needs to toggle it:

javascript
searchBar.isOpen() ? searchBar.close() : searchBar.open();

Its public API is intentionally small:

MethodPurpose
attach(objViewer)Connect the Ribbon to the initialized viewer; required once
open() / close()Show or hide the Ribbon; closing also clears highlights
reset()Clear the current term, result count, and highlights
isOpen()Report whether the Ribbon is visible
setStatus(message)Forward a status message through the configured callback

The optional onToggle(isOpen) callback lets the host synchronize its Search button, and onLayout lets it resize/refit the viewer when the Ribbon changes height. For the combined Viewer, Search, and Annotation startup sequence, see Quick Start.

Search from JavaScript

javascript
objViewer.Search(keyword, false, function (resultCount) {
    console.log('Matches:', resultCount);
});

The second argument is whole-word/exact matching. The match count arrives in the callback: Search itself goes to the server and returns nothing useful, so var n = objViewer.Search(keyword, false) always reads undefined — and a page built that way reports "nothing found" while the viewer highlights the matches. After the callback:

MethodResult
SearchMatchCount()Total individual matches in the document.
SearchSummary(false)[pageNumber, matchCount] entries without repainting.
SearchSummary(true)Same summary and paints page/thumbnail highlights.
GotoSearchMatch(index)Navigates to a zero-based match index.

DocImage.axd answers search=<term> and exact=true|false with XML. Use the widget API rather than parsing that internal response yourself.

Check search capability

The initialization response reports:

text
X-Doconut-Can-Search: 1

After initialization, objViewer.CanSearch() exposes the same format/session verdict. It returns false when the server sends 0; before the response, or with an older server that omits the header, it defaults to true.

Three independent gates must not be confused:

GateQuestion
CanSearch() / response headerDoes the resolved viewer have a native index/search path?
AllowSearchDid this format config request text extraction where the switch exists?
LicenseCapability.SearchIs the application authorized to execute search and receive the UI bundles?

A format can be technically searchable while the current license denies the operation.

Enable extraction per format

csharp
var token = await viewer.OpenDocumentAsync(path, new PdfConfig
{
    AllowSearch = true,
    AllowCopy   = true   // optional: lets the user drag a region and copy its text
});

AllowSearch and AllowCopy exist on PdfConfig, WordConfig, ExcelConfig, and PptConfig. The Office properties delegate to their nested PdfConfig. Both default to false.

Normal native-search adapters exist for PDF, Word, Excel, PowerPoint, TXT, Visio, email, EPUB, and MHT. XPS uses its PDF path by default. HTML and Microsoft Project benefit from a text-based PDF redirect:

csharp
// DefaultRender = false → converted to a text-based PDF → searchable
var token = await viewer.OpenDocumentAsync(path, new HtmlConfig { DefaultRender = false });

For native renderers, CanSearch() describes the viewer capability; it does not guarantee that a particular document contains usable text. A PDF whose pages are only scanned images can still produce zero native results.

Normal Search behavior

The server tries search sources in this order:

  1. Native ISearchableViewer results.
  2. A prebuilt .srh search index.
  3. An error/empty result when no search source exists.

CanSearch() can be true for a searchable viewer even when a particular document has no text layer and therefore returns no matches.

Licensing and UI behavior

An active Temporary/Demo license grants Search during its active period. A missing license and legacy TRIAL file grant no Search capability. Without Search:

  • ReferenceCss and ReferenceScripts omit the search bundles.
  • DocImage.axd refuses search requests instead of returning results.

Drive custom UI visibility from IDoconutLicenseService.IsCapabilityGranted(LicenseCapability.Search) and use CanSearch() for the separate format/session verdict.

Troubleshooting

SymptomCheck
Search bar is missingSearch capability and IncludeSearchCss/IncludeSearchScripts/IncludeSearchBar
CanSearch() is falseFormat viewer, selected DefaultRender path, and initialization response header
Search returns zero for a scanned PDFThe document has no text layer; use a text-bearing source or a PDF projection that preserves text
Search works but highlights are offsetRendering path, resolution, document transforms, and extracted word boxes

War diese Seite hilfreich?