Hits โ
TIP
Prefer the table-based configuration for managing search form fields.
It centralizes settings and uses the same underlying functions as manual methods.
โ ๏ธ The table-based method may not cover all cases. For advanced customizations, override with dedicated functions as needed.
Context โ
Set concordance size (concordanceSize
) โ
To show more or less of the surrounding document when a hit is expanded.
vuexModules.ui.actions.results.shared.concordanceSize(10)
Set Annotation (concordanceAnnotationId
) โ
You can use a different Annotation for searching and displaying, e.g. search for lemmata but show the original text in the results (or even show markup using concordanceAsHtml
).
vuexModules.ui.actions.results.shared.concordanceAnnotationId('word');
Allow users to choose the annotation โ
You can allow users to switch the annotation used for concordances in the hits table. This is useful if you have multiple annotations and want to let users choose which one to display. E.g. one with markup and one without
vuexModules.ui.actions.results.shared.concordanceAnnotationIdOptions(['word', 'lemma']);
HTML and markup in Concordances (concordanceAsHtml
) โ
You can display concordances (the hit and its context) as HTML in the results table. This is useful if you have indexed snippets of raw XML from your documents (for example, using BlackLab's captureXml
mode) and want to render them with custom styling.
vuexModules.ui.actions.results.shared.concordanceAsHtml(true)
Example โ
Combined with BlackLab's captureXml
mode, you can index raw XML from your documents into an annotation (e.g., word_xml
). By enabling concordanceAsHtml
, the frontend will render the annotation as HTML in the hits table, allowing you to style it with custom CSS.
<w>
en<strikethrough>de</strikethrough>
</w>
- name: word_xml
valuePath: //w
captureXml: true
vuexModules.ui.actions.results.shared.concordanceAnnotationId('word_xml')
vuexModules.ui.actions.results.shared.concordanceAsHtml(true)
strikethrough {
text-decoration: line-through;
}
Will result in the following html
en
de
Browser support for non-HTML elements is good, so arbitrary XML should work out of the box, as long as it is well-formed.
WARNING
USE THIS FEATURE WITH CARE! It may break your page if the XML contains unexpected or malformed contents.
Columns and Rows โ
By default, up to 3 extra columns (besides the main annotation) are shown. lemma
and pos
have hardcoded priority, and will show up first if they exist. Remaining spots are filled up in the order you declared your annotations in the .blf.yaml
.
// Replace with the annotation IDs you want to display.
vuexModules.ui.actions.results.hits.shownAnnotationIds(['lemma', 'pos', 'your_annotation']);
Custom column โ
You can also add a column with custom content, the content can be computed from a function.
frontend.customize(corpus => {
// Enable the column
corpus.results.hasCustomHitInfoColumn = (results, isParallelCorpus) => {
return true; // Always show the custom column
};
// Provide content for the column
corpus.results.customHitInfo = (hit, annotatedFieldDisplayName, docInfo) => {
// Example: Show the document title
return `${docInfo.title}`;
};
})
/** Should the custom hit info column be shown for this result set?
*
* If true, uses the customHitInfo function to determine what to show.
*/
hasCustomHitInfoColumn: (results: BLTypes.BLHitResults|BLTypes.BLHitGroupResults, isParallelCorpus: boolean): boolean => {
return isParallelCorpus;
},
/**
* Determine custom hit info for this hit.
*
* Shows some custom text (with doc link) left of the hit.
*
* Default shows versionPrefix if it's set (i.e. if it's a parallel corpus).
* Otherwise, nothing extra is shown.
* @param hit the hit
* @param annotatedFieldDisplayName the name of the field the hit is in. This is already translated to the user's locale.
* In the case of non-parallel corpora, this will always be the main annotated field.
* @param docInfo document metadata
*/
customHitInfo: (
hit: BLTypes.BLHit|BLTypes.BLHitSnippet|BLTypes.BLHitInOtherField,
annotatedFieldDisplayName: string|null,
docInfo: BLTypes.BLDoc): string|null => {
return annotatedFieldDisplayName;
}
Expanded Hit Details โ
Annotations in Expanded View (detailedAnnotationIds
) โ
Control which annotations are shown in the expanded hit details and in CSV exports:
vuexModules.ui.actions.results.shared.detailedAnnotationIds(['word', 'lemma', 'pos_full', 'phonetic']);
Dependency Tree in Expanded View (dependencies
) โ
If your corpus has dependency relations, you can configure which annotations are used in the dependency tree shown in hit details. We will try to show all dependencies in the sentence, or shown the explicitly searched dependencies.
Highlighting Concordances โ
Marking parts of your query will highlight the corresponding parts in the hits table. This is useful to visually distinguish different parts of your query, such as the main search term and any modifiers.
We will highlight marked parts of the query, or alternatively, any matched relations when using a relation query.
TIP
See the BlackLab docs on relations for more information on how to use relations in your data and queries.
a:_ --> b:"koe"
i.e. "anything" as parent of "koe" (cow) in the dependency tree.
You can configure how and what to highlight, if the defauls are not to your liking.
/**
* @param {HighlightSection} matchInfo
* @returns {'hover' | 'static' | 'none' | null}
*/
corpus.results.matchInfoHighlightStyle = function (matchInfo) {
if (matchInfo.isRelation) {
// Show hover highlight for words
if (matchInfo.relType === 'word-alignment')
return 'hover';
// Don't show other relations
return 'none';
}
// Always highlight any named entities captured by our query
// (e.g. <named-entity/> containing "dog")
if (matchInfo.key === 'named-entity')
return 'static';
// Default highlighting behaviour
// ("highlight non-relations if there's explicit captures in the query")
return null;
};
/** Part of a hit/context to highlight, with a label, display and boolean whether it's a relation or a section of the query/result labelled by the user. */
export type HighlightSection = {
/** -1 for root */
sourceStart: number;
/** -1 for root */
sourceEnd: number;
targetStart: number;
targetEnd: number;
targetField?: string;
/** True if this is a relation, false if this is a capture group */
isRelation: boolean;
/** Should this be permanently higlighted? (if not, may still be hoverable if this is a parallel corpus) */
showHighlight: boolean;
/**
* Key of this info as reported by BlackLab.
* E.g. for a query "_ -obj-> _" this would be "obj".
* For an anonymous relation e.g. _ --> _ this would be something like "dep1" or "rel1"
* For a capture group, e.g. "a:[] b:[]" this would be the name of the capture group, "a" or "b".
*
* Can be used for e.g. grouping results (and we do use this, mind when refactoring.)
*/
key: string;
/** Display string, key if !isRelation, relation value + arrow if isRelation == true */
display: string;
}
Addons โ
You can inject custom content (e.g., audio players, buttons, extra info) into the expanded hit details using the addons
array.
Example Addon: Add an audio player to hit details โ
Utils โ
Transform Snippets (transformSnippets
) โ
Use to replace words, add warnings, or correct data after the fact (e.g. escape sequences), or to do markup in combination with concordanceAsHtml
.
/** E.g. {word: ['words', 'in', 'the', 'hit'], lemma: [...], pos: [...]} */
type SnippetPart = Record<string, string[]>;
interface Snippet {
before: SnippetPart;
match: SnippetPart;
after: SnippetPart;
// There might be more properties! beware of that.
}
type TransformFunction = (snippet: Snippet) => void;
Totals Counter Polling โ
Control how long and how often the totals counter (spinner) refreshes while waiting for results: After the timeout, the user will have to manually start the counter again.
vuexModules.ui.actions.results.shared.totalsTimeoutDurationMs(90000); // 90 seconds
vuexModules.ui.actions.results.shared.totalsRefreshIntervalMs(2000); // 2 seconds