We have built a small JavaScript library that offers a Vuetify web component to integrate the Federated Content Search into you own website. It uses the FCS Aggregator REST API (e.g., from the CLARIN Content Search or any other public FCS Aggregator) to execute searches and then display results in a popup window.
This library is primarily intended for data centres or institutes that already have their resources integrated in the FCS but want to offer the same search capabilities on their own website for visitors instead of having to redirect them to the Aggregator.
Code, examples and instructions can be found at: text-plus / Federated Content Search / Text+ FCS Vuetify · GitLab. Take a look at the How to run as standalone demo webapp (FCS only!) section.
If you are interested in just a JavaScript library for integrating the FCS Aggregator REST API, see the text-plus / Federated Content Search / Text+ FCS Vue Store · GitLab library. It is used in the Vuetify Search Dialog to communicate with the FCS Aggregator but doesn’t provide any visual components.
Examples
Screenshot: Open search dialog with resources cards and random search suggestions
Screenshot: Search for “Leipzig” for active search with restriction using language facets, resource cards in different colors based on result status
Screenshot: List of resources with hits for advanced search “[ word = “shark” ]” with both KWIC and expanded result views
The Text+ website has this search web component integrated. Visiting Home - Text+ opens the search dialog with all the German FCS resources. Or choose the red Search/Suche buttons on the page.
The SAW Repository uses the optional resource filtering configuration to integrate the content search with only the resources hosted by the SAW Repository. It still uses the same FCS Aggregator as the Text+ website. If the URL has not automatically opened the search dialog, you can also use one of the following options to do so:
- Choose Resources > Content Search in the main menu to open the search dialog with all the resources from the SAW Repository only. (Filtering using FCS Endpoint URLs.)
- Visit any resource page, e.g. Dictionary Digital edition of J. G. Zwahr’s Lower Sorbian-German Dictionary 1847 and click the button TODO: XYZ to open the search dialog with this one resource only. (Filtering using the Resource’s PID.)
How to integrate the search dialog
Building static JS/CSS assets
You first have to build the web component to get the static JS/CSS files that you later include into your website:
# first clone the repo
git clone https://git.saw-leipzig.de/text-plus/FCS/textplus-fcs-vuetify.git
cd textplus-fcs-vuetify/
# optionally check out a specific version but using the latest `main` branch release is recommended
git checkout main
# build the library
yarn build:fcs
You will find the built JS/CSS files in the dist/
folder.
You can try out the demo using the following command and then visiting http://localhost:8000/fcs-standalone.html.
# Start a webserver, here using Python3 in the root directory
python3 -m http.server 8000
Asset integration and configuration
Integrate the static JS/CSS files into your page:
<!-- add this to you <head> section -->
<link rel="stylesheet" href="/dist/fcs-vuetify.css">
<!-- add this to you <body> section -->
<script src="/dist/fcs-vuetify.js"></script>
You need to then specify a mounting point for the search dialog, e.g. add a div with an unique id
to you <body>
. (Note that we chose advanced-search-app
as ID. This ID is different to the one used for the optional PostCSS style prefixes we will describe later.)
<div id="advanced-search-app"></div>
Then configure the search to use the correct endpoint using a bit of JavaScript (e.g., simply add the code into a <script>
tag at the end of your <body>
.
You can optionally filter to you own resources (recommended) using the PIDs that are used in the FCS EndpointDescription
.
// we need to wait for the script to finish loading
const waitForLoad = window.setInterval(() => {
console.debug("Check if 'advancedsearch' has been loaded...", window.advancedsearch);
if (window.advancedsearch === undefined) {
return;
}
// stop check as script has been loaded
window.clearInterval(waitForLoad);
// mount app and setup all those vue stuff ...
console.debug("Library 'advancedsearch' is ready. Mount app.");
advancedsearch.mountApp({
// the mounting point with the unique ID chosen above
selector: "#advanced-search-app",
// the FCS Aggregator URLs (REST API), here the CLARIN Content Search FCS Aggregator
rest_base_uri: "https://contentsearch.clarin.eu/rest/",
// optinal url to link to the aggregator to view finished searches there
ui_base_uri: "https://contentsearch.clarin.eu/",
// optionally restrict to set of resources using ids, endpoint urls or institution names
// all filters will be combined, so additive resource id set
// resource_ids: [ "https://fcs-endpoint.de/#res1", "https://fcs-endpoint.de/#http://example.com/res2", ... ],
// endpoint_urls: [ "https://fcs.endpoint.com/sru", ... ],
// institution_names: [ "Example Institution", ... ],
// optionally overwrite the search dialog title (for multiple languages)
appLabel: {en: 'CLARIN Federated Content Search'},
appLabelShort: {en: 'FCS'},
});
// switch to language for dialog based on e.g. <html lang="de">
// (only possible after the app has been mounted!)
const language = document.documentElement.lang;
if (!!language) {
console.debug("Switch locale to:", language);
advancedsearch.switchLocale(language);
}
// NOTE: you can set some input filter fields, there is however no validation if values are correct!
// set query type / search capability of resources: BASIC_SEARCH|ADVANCED_SEARCH
//advancedsearch.setSearchCapability("ADVANCED_SEARCH");
// set resource language selection, always an array with ISO 639-3 codes
//advancedsearch.setSelectedLanguages(["eng", "deu"]);
// preselect resources using their IDs, always an array of strings
//advancedsearch.setSelectedResources(["http://example.org/fcs#hdl:resource1"]);
// optionally dis-/enable search history
advancedsearch.setEnableSearchHistory(true);
// optionally enable perma urls (using hash-fragments)
advancedsearch.setEnablePermaURLs(true, { useHash: true, hashAction: 'open-search' });
// for perma URLs: do initial evaluation when script has loaded
dialog.openFromPermaUrl();
// do evaluation when URL hash has changed
window.addEventListener('hashchange', (event) => dialog.openFromPermaUrl())
}, 250);
Now you are almost done. You just need to provide a way to open the search dialog. This can be achieved with the following snippet: (important is the advancedsearch.openDialog()
function call)
<button onclick="advancedsearch.openDialog()">Open Dialog</button>
See this demo HTML file for a complete example.
Note about CSS style conflicts
This web component uses Vuetify which is based on Material Design. This can lead to conflicts with existing CSS frameworks like bootstrap. If that is the case, there is a way to prefix all the Vuetify CSS rules so that there is no conflict. For this to work, the app needs to be mounted with the mount point or a parent having the ID advanced-search
!
A working configuration can be found in postcss.config.js.disabled
. The (re)build with PostCSS should automatically drop some CSS reset rules and prefix generic CSS rule names that are used in Vuetify. So, only the fcs-vuetify.css
should have changed (it will now contain some selectors with the prefix #advanced-search-dialog
).
# enable the PostCSS prefixer configuration
# (this file needs to stay in the root of the `textplus-fcs-vuetify` folder)
cp postcss.config.js.disabled postcss.config.js
# add the prefixer dependency
yarn add postcss-prefix-selector
# (re)build the library
yarn build:fcs
You will find the built JS/CSS files in the dist/
folder.
Another working configuration (using Hugo and Bootstrap) is used in the Text+ Webportal.
If you still experience issues, contact me and we can try to find a solution.