diff --git a/resource/js/vocab-search.js b/resource/js/vocab-search.js
index 1678cef7..9c46f21c 100644
--- a/resource/js/vocab-search.js
+++ b/resource/js/vocab-search.js
@@ -16,7 +16,7 @@ const vocabSearch = Vue.createApp({
},
mounted () {
this.languages = window.SKOSMOS.languageOrder
- this.selectedLanguage = window.SKOSMOS.content_lang
+ this.selectedLanguage = this.parseSearchLang()
this.searchCounter = 0
this.languageStrings = window.SKOSMOS.language_strings[window.SKOSMOS.lang] ?? window.SKOSMOS.language_strings.en
this.msgs = window.SKOSMOS.msgs[window.SKOSMOS.lang] ?? window.SKOSMOS.msgs.en
@@ -45,7 +45,8 @@ const vocabSearch = Vue.createApp({
const mySearchCounter = this.searchCounter + 1 // make sure we can identify this search later in case of several ongoing searches
this.searchCounter = mySearchCounter
let skosmosSearchUrl = 'rest/v1/' + window.SKOSMOS.vocab + '/search?'
- const skosmosSearchUrlParams = new URLSearchParams({ query: this.formatSearchTerm(), lang: window.SKOSMOS.lang, unique: true })
+ const skosmosSearchUrlParams = new URLSearchParams({ query: this.formatSearchTerm(), unique: true })
+ if (this.selectedLanguage !== 'all') skosmosSearchUrlParams.set('lang', this.selectedLanguage)
skosmosSearchUrl += skosmosSearchUrlParams.toString()
fetch(skosmosSearchUrl)
@@ -67,8 +68,39 @@ const vocabSearch = Vue.createApp({
}
return false
},
- renderMatchingPart (searchTerm, label) {
+ parseSearchLang () {
+ // if content language can be found from uri params, use that and update it to SKOSMOS object and to search lang cookie
+ const urlParams = new URLSearchParams(window.location.search)
+ const paramLang = urlParams.get('clang')
+ const anyLang = urlParams.get('anylang')
+ if (anyLang) {
+ this.changeLang('all')
+ return 'all'
+ }
+ if (paramLang) {
+ this.changeLang(paramLang)
+ return paramLang
+ }
+ // use searchLangCookie if it can be found, otherwise pick content lang from SKOSMOS object
+ const cookies = document.cookie.split('; ')
+ const searchLangCookie = cookies.find(cookie =>
+ cookie.startsWith('SKOSMOS_SEARCH_LANG='))
+ if (searchLangCookie) {
+ const selectedLanguage = searchLangCookie.split('=')[1]
+ if (selectedLanguage !== 'all') {
+ window.SKOSMOS.content_lang = selectedLanguage
+ }
+ return selectedLanguage
+ } else {
+ return window.SKOSMOS.content_lang
+ }
+ },
+ renderMatchingPart (searchTerm, label, lang = null) {
if (label) {
+ let langSpec = ''
+ if (lang && this.selectedLanguage === 'all') {
+ langSpec = ' (' + lang + ')'
+ }
const searchTermLowerCase = searchTerm.toLowerCase()
const labelLowerCase = label.toLowerCase()
if (labelLowerCase.includes(searchTermLowerCase)) {
@@ -77,10 +109,10 @@ const vocabSearch = Vue.createApp({
return {
before: label.substring(0, startIndex),
match: label.substring(startIndex, endIndex),
- after: label.substring(endIndex)
+ after: label.substring(endIndex) + langSpec
}
}
- return label
+ return label + langSpec
}
return null
},
@@ -95,21 +127,25 @@ const vocabSearch = Vue.createApp({
renderResults () {
// TODO: get the results list form cache if it is implemented
const renderedSearchTerm = this.searchTerm // save the search term in case it changes while rendering
+
this.renderedResultsList.forEach(result => {
if ('hiddenLabel' in result) {
result.hitType = 'hidden'
- result.hit = this.renderMatchingPart(renderedSearchTerm, result.prefLabel)
+ result.hit = this.renderMatchingPart(renderedSearchTerm, result.prefLabel, result.lang)
} else if ('altLabel' in result) {
result.hitType = 'alt'
- result.hit = this.renderMatchingPart(renderedSearchTerm, result.altLabel)
+ result.hit = this.renderMatchingPart(renderedSearchTerm, result.altLabel, result.lang)
result.hitPref = this.renderMatchingPart(renderedSearchTerm, result.prefLabel)
} else {
if (this.notationMatches(renderedSearchTerm, result.notation)) {
result.hitType = 'notation'
- result.hit = this.renderMatchingPart(renderedSearchTerm, result.notation)
+ result.hit = this.renderMatchingPart(renderedSearchTerm, result.notation, result.lang)
+ } else if ('matchedPrefLabel' in result) {
+ result.hitType = 'pref'
+ result.hit = this.renderMatchingPart(renderedSearchTerm, result.matchedPrefLabel, result.lang)
} else if ('prefLabel' in result) {
result.hitType = 'pref'
- result.hit = this.renderMatchingPart(renderedSearchTerm, result.prefLabel)
+ result.hit = this.renderMatchingPart(renderedSearchTerm, result.prefLabel, result.lang)
}
}
if ('uri' in result) { // create relative Skosmos page URL from the search result URI
@@ -144,13 +180,26 @@ const vocabSearch = Vue.createApp({
const currentVocab = window.SKOSMOS.vocab + '/' + window.SKOSMOS.lang + '/'
const vocabHref = window.location.href.substring(0, window.location.href.lastIndexOf(window.SKOSMOS.vocab)) + currentVocab
const searchUrlParams = new URLSearchParams({ clang: window.SKOSMOS.content_lang, q: this.searchTerm })
- if (this.selectedLanguage === 'all') searchUrlParams.set('anylang', 'on')
+ if (this.selectedLanguage === 'all') searchUrlParams.set('anylang', 'true')
const searchUrl = vocabHref + 'search?' + searchUrlParams.toString()
window.location.href = searchUrl
},
- changeLang () {
- window.SKOSMOS.content_lang = this.selectedLanguage
- // TODO: Implement (a normal) page load to change content according to the new content language
+ changeLang (lang) {
+ this.selectedLanguage = lang
+ this.setSearchLangCookie(lang)
+ this.resetSearchTermAndHideDropdown()
+ },
+ changeContentLangAndReload (lang) {
+ this.changeLang(lang)
+ const params = new URLSearchParams(window.location.search)
+ if (lang === 'all') {
+ params.set('anylang', 'true')
+ } else {
+ params.delete('anylang')
+ params.set('clang', lang)
+ }
+ this.$forceUpdate()
+ window.location.search = params.toString()
},
resetSearchTermAndHideDropdown () {
this.searchTerm = ''
@@ -163,6 +212,14 @@ const vocabSearch = Vue.createApp({
showAutoComplete () {
this.showDropdown = true
this.$forceUpdate()
+ },
+ setSearchLangCookie (lang) {
+ // The cookie path should be relative if the baseHref is known
+ let cookiePath = '/'
+ if (window.SKOSMOS.baseHref && window.SKOSMOS.baseHref.replace(window.origin, '')) {
+ cookiePath = window.SKOSMOS.baseHref.replace(window.origin, '')
+ }
+ document.cookie = `SKOSMOS_SEARCH_LANG=${this.selectedLanguage};path=${cookiePath}`
}
},
template: `
@@ -170,7 +227,7 @@ const vocabSearch = Vue.createApp({
diff --git a/src/view/scripts.inc b/src/view/scripts.inc
index 87a4d99d..be8641c9 100644
--- a/src/view/scripts.inc
+++ b/src/view/scripts.inc
@@ -24,6 +24,7 @@ window.SKOSMOS = {
{%- if request.plugins.callbacks ~%}
"pluginCallbacks": [{% for function in request.plugins.callbacks %}{% if not loop.first %}, {% endif %}"{{ function }}"{% endfor %}],
{%- endif ~%}
+ "baseHref": "{{ BaseHref }}",
"language_strings": { "fi": { "fi": "suomi",
"en": "englanti",
"se": "pohjoissaame",
diff --git a/tests/cypress/template/vocab-search-bar.cy.js b/tests/cypress/template/vocab-search-bar.cy.js
index b5f1ce81..9753465f 100644
--- a/tests/cypress/template/vocab-search-bar.cy.js
+++ b/tests/cypress/template/vocab-search-bar.cy.js
@@ -1,157 +1,199 @@
describe('Vocab search bar', () => {
- it('search can be done with a chosen content language', () => {
- // go to YSO vocab front page
- cy.visit('/yso/fi/')
- // Select an option from the dropdown
- cy.get('#search-wrapper select').select('sv');
+ describe('Search Language', () => {
+ it('search can be done with a chosen content language', () => {
+ // go to YSO vocab front page
+ cy.visit('/yso/fi/')
- // Enter a search term
- cy.get('#search-wrapper input').type('Katt');
+ // Select an option from the dropdown
+ cy.get('#search-wrapper select').select('sv');
- // Click the search button
- cy.get('#search-button').click();
+ // Enter a search term
+ cy.get('#search-wrapper input').type('Katt');
- //Verify the search page url (search result page tests are elsewhere)
- cy.url().should('include', 'q=Katt').and('include', 'clang=sv');
+ // Click the search button
+ cy.get('#search-button').click();
- })
+ // Verify the search page url (search result page tests are elsewhere)
+ cy.url().should('include', 'q=Katt').and('include', 'clang=sv');
+ })
- it('search can be done with all languages', () => {
- // go to YSO vocab front page
- cy.visit('/yso/fi/')
+ it('search can be done with all languages', () => {
+ // go to YSO vocab front page
+ cy.visit('/yso/fi/')
- // Choose 'all' languages
- cy.get('#search-wrapper select').select('all');
+ // Choose 'all' languages
+ cy.get('#search-wrapper select').select('all');
- // Enter a search term
- cy.get('#search-wrapper input').type('Katt');
+ // Enter a search term
+ cy.get('#search-wrapper input').type('Katt');
- // Click the search button
- cy.get('#search-button').click();
+ // Click the search button
+ cy.get('#search-button').click();
- //Verify the search page url (search result page tests are elsewhere)
- cy.url().should('include', 'q=Katt').and('include', 'anylang=on');
- })
+ // Verify the search page url (search result page tests are elsewhere)
+ cy.url().should('include', 'q=Katt').and('include', 'anylang=true');
+ })
- it('Writing in the text field triggers the autocomplete results list', () => {
- // go to YSO vocab front page
- cy.visit('/yso/fi/')
+ it('search with all languages retains the previously chosen content language', () => {
+ // go to YSO vocab front page
+ cy.visit('/yso/fi/')
- cy.get('#search-field').type('kas'); // perform autocomplete search
- cy.get('#search-autocomplete-results', { timeout: 20000 }).should('be.visible').children().should('have.length.greaterThan', 2);
- })
+ // Choose 'sv' for search & content language
+ cy.get('#search-wrapper select').select('sv');
- it('No results message is displayed if no results are found', () => {
- // go to YSO vocab front page
- cy.visit('/yso/en/')
+ // Choose 'all' for search language
+ cy.get('#search-wrapper select').select('all');
- cy.get('#search-field').type('kissa'); // even if the search yields no results, there shoulde a single line in the result list
- cy.get('#search-autocomplete-results', { timeout: 20000 }).should('be.visible').children().should('have.length.greaterThan', 0);
- cy.get('#search-autocomplete-results').within(() => {
- cy.get('li').eq(0).invoke('text').should('contain', 'No results') // the single result should display a no results message
- })
- })
+ // Verify the search page url has the previously chosen language as the content language
+ cy.url().should('include', 'clang=sv');
+ })
- it('No results are displayed for autocomplete if there is not at leas two charecters in the search term', () => {
- // go to YSO vocab front page
- cy.visit('/yso/en/')
+ });
- cy.get('#search-field').type('k'); // even if the search yields no results, there shoulde a single line in the result list
- cy.get('#search-autocomplete-results', { timeout: 20000 }).should('not.be.visible');
- })
+ describe('Autocomplete', () => {
+ it('Writing in the text field triggers the autocomplete results list', () => {
+ // go to YSO vocab front page
+ cy.visit('/yso/fi/')
- it('The autocomplete list should not change due to previous searches completing', () => {
- // go to YSO vocab front page
- cy.visit('/yso/fi/')
+ cy.get('#search-field').type('kas'); // perform autocomplete search
+ cy.get('#search-autocomplete-results', { timeout: 20000 }).should('be.visible').children().should('have.length.greaterThan', 2);
+ })
- cy.get('#search-field').type('ka');
- cy.wait(300);
- cy.get('#search-field').type('i');
- cy.get('#search-autocomplete-results', { timeout: 20000 }).should('be.visible'); // the autocomplete should appear
- cy.get('#search-autocomplete-results').children().should('have.length', 1)
- cy.wait(10000); // wait extra 10 seconds to see if the 'ka' search adds results to the list
- cy.get('#search-autocomplete-results').children().should('have.length', 1)
- })
+ it('Special characters can be used in the search', () => {
+ // go to YSO vocab front page
+ cy.visit('/yso/fi/')
- it('Clear button should hide the autocomplete list', () => {
- // go to YSO vocab front page
- cy.visit('/yso/en/')
+ cy.get('#search-field').type('*tus (*');
+ cy.get('#search-autocomplete-results', { timeout: 20000 }).should('be.visible'); // the autocomplete should appear
- cy.get('#search-field').type('kas');
- cy.get('#search-autocomplete-results', { timeout: 20000 }).should('be.visible'); // the autocomplete should appear
+ cy.get('#search-autocomplete-results').within(() => { // the first result should have text ajoitus (historia)
+ cy.get('li').first().should('contain', 'ajoitus (historia)')
+ })
+ })
- cy.get('#clear-button').click()
- cy.get('#search-autocomplete-results').should('not.be.visible'); // the autocomplete should disappear
- })
+ it('No results message is displayed if no results are found', () => {
+ // go to YSO vocab front page
+ cy.visit('/yso/en/')
- it('Emptying the text search field hides the autocomplete list', () => {
- // go to YSO vocab front page
- cy.visit('/yso/en/')
+ cy.get('#search-field').type('kissa'); // even if the search yields no results, there shoulde a single line in the result list
+ cy.get('#search-autocomplete-results', { timeout: 20000 }).should('be.visible').children().should('have.length.greaterThan', 0);
+ cy.get('#search-autocomplete-results').within(() => {
+ cy.get('li').eq(0).invoke('text').should('contain', 'No results') // the single result should display a no results message
+ })
+ })
- cy.get('#search-field').type('kis');
- cy.get('#search-autocomplete-results', { timeout: 20000 }).should('be.visible'); // the autocomplete should appear
+ it('No results are displayed for autocomplete if there is not at leas two charecters in the search term', () => {
+ // go to YSO vocab front page
+ cy.visit('/yso/en/')
- cy.get('#search-field').clear();
- cy.get('#search-autocomplete-results').should('not.be.visible'); // the autocomplete should disappear
- })
+ cy.get('#search-field').type('k'); // even if the search yields no results, there shoulde a single line in the result list
+ cy.get('#search-autocomplete-results', { timeout: 20000 }).should('not.be.visible');
+ })
- it('Clicking outside of the autocomplete list hides the autocomplete list', () => {
- // go to YSO vocab front page
- cy.visit('/yso/en/')
+ it('The autocomplete list should not change due to previous searches completing', () => {
+ // go to YSO vocab front page
+ cy.visit('/yso/fi/')
+
+ cy.get('#search-field').type('ka');
+ cy.wait(300);
+ cy.get('#search-field').type('i');
+ cy.get('#search-autocomplete-results', { timeout: 20000 }).should('be.visible'); // the autocomplete should appear
+ cy.get('#search-autocomplete-results').children().should('have.length', 1)
+ cy.wait(5000); // wait extra 5 seconds to see if the 'ka' search adds results to the list
+ cy.get('#search-autocomplete-results').children().should('have.length', 1)
+ })
- cy.get('#search-field').type('kas');
- cy.get('#search-autocomplete-results', { timeout: 20000 }).should('be.visible'); // the autocomplete should appear
+ it('Clear button should hide the autocomplete list', () => {
+ // go to YSO vocab front page
+ cy.visit('/yso/en/')
- cy.get('#main-container').click({ force: true }); // using force true to click on elements not considered actionable
- cy.get('#search-autocomplete-results').should('not.be.visible'); // the autocomplete should disappear
- })
+ cy.get('#search-field').type('kas');
+ cy.get('#search-autocomplete-results', { timeout: 20000 }).should('be.visible'); // the autocomplete should appear
- it('AltLabel search results should bold the matching parts of altLabel', () => {
- // go to YSO vocab front page
- cy.visit('/yso/fi/')
+ cy.get('#clear-button').click()
+ cy.get('#search-autocomplete-results').should('not.be.visible'); // the autocomplete should disappear
+ })
- cy.get('#search-field').type('assyro');
- cy.get('#search-autocomplete-results', { timeout: 20000 }).should('be.visible'); // the autocomplete should appear
+ it('Emptying the text search field hides the autocomplete list', () => {
+ // go to YSO vocab front page
+ cy.visit('/yso/en/')
- cy.get('#search-autocomplete-results').within(() => { // the first result should have matching part of text 'assyrologia' appearing in bold
- cy.get('li').last().find('b').eq(0).should('have.text', 'assyro')
+ cy.get('#search-field').type('kis');
+ cy.get('#search-autocomplete-results', { timeout: 20000 }).should('be.visible'); // the autocomplete should appear
+
+ cy.get('#search-field').clear();
+ cy.get('#search-autocomplete-results').should('not.be.visible'); // the autocomplete should disappear
})
- })
- it('AltLabel search results should be displayed in italics', () => {
- // go to YSO vocab front page
- cy.visit('/yso/fi/')
+ it('Clicking outside of the autocomplete list hides the autocomplete list', () => {
+ // go to YSO vocab front page
+ cy.visit('/yso/en/')
- cy.get('#search-field').type('assyro');
- cy.get('#search-autocomplete-results', { timeout: 20000 }).should('be.visible'); // the autocomplete should appear
+ cy.get('#search-field').type('kas');
+ cy.get('#search-autocomplete-results', { timeout: 20000 }).should('be.visible'); // the autocomplete should appear
- cy.get('#search-autocomplete-results').within(() => { // the first result should have text 'assyrologia' appearing in italics
- cy.get('li').last().find('i').eq(0).should('contain.text', 'assyrologia')
+ cy.get('#main-container').click({ force: true }); // using force true to click on elements not considered actionable
+ cy.get('#search-autocomplete-results').should('not.be.visible'); // the autocomplete should disappear
})
- })
+ });
- it('Notation search results should bold the matching parts of the notation', () => {
- // go to YSO vocab front page
- cy.visit('/yso/fi/')
+ describe('Search Result Rendering', () => {
+ it('AltLabel search results should bold the matching parts of altLabel', () => {
+ // go to YSO vocab front page
+ cy.visit('/yso/fi/')
- cy.get('#search-field').type('51');
- cy.get('#search-autocomplete-results', { timeout: 20000 }).should('be.visible'); // the autocomplete should appear
+ cy.get('#search-field').type('assyro');
+ cy.get('#search-autocomplete-results', { timeout: 20000 }).should('be.visible'); // the autocomplete should appear
- cy.get('#search-autocomplete-results').within(() => { // the first result should have text '51' appearing in bold
- cy.get('li').last().find('b').eq(0).should('have.text', '51')
+ cy.get('#search-autocomplete-results').within(() => { // the first result should have matching part of text 'assyrologia' appearing in bold
+ cy.get('li').last().find('b').eq(0).should('have.text', 'assyro')
+ })
})
- })
- it('Special characters can be used in the search', () => {
- // go to YSO vocab front page
- cy.visit('/yso/fi/')
+ it('AltLabel search results should be displayed in italics', () => {
+ // go to YSO vocab front page
+ cy.visit('/yso/fi/')
- cy.get('#search-field').type('*tus (*');
- cy.get('#search-autocomplete-results', { timeout: 20000 }).should('be.visible'); // the autocomplete should appear
+ cy.get('#search-field').type('assyro');
+ cy.get('#search-autocomplete-results', { timeout: 20000 }).should('be.visible'); // the autocomplete should appear
- cy.get('#search-autocomplete-results').within(() => { // the first result should have text ajoitus (historia)
- cy.get('li').first().should('contain', 'ajoitus (historia)')
+ cy.get('#search-autocomplete-results').within(() => { // the first result should have text 'assyrologia' appearing in italics
+ cy.get('li').last().find('i').eq(0).should('contain.text', 'assyrologia')
+ })
})
- })
+
+ it('Notation search results should bold the matching parts of the notation', () => {
+ // go to YSO vocab front page
+ cy.visit('/yso/fi/')
+
+ cy.get('#search-field').type('51');
+ cy.get('#search-autocomplete-results', { timeout: 20000 }).should('be.visible'); // the autocomplete should appear
+
+ cy.get('#search-autocomplete-results').within(() => { // the first result should have text '51' appearing in bold
+ cy.get('li').last().find('b').eq(0).should('have.text', '51')
+ })
+ })
+ });
+
+ describe('Cookie Management', () => {
+ it('The search language cookie is set', () => {
+ cy.visit('/yso/fi/');
+
+ // Select an option from the dropdown to set the search language
+ cy.get('#search-wrapper select').select('sv');
+
+ // Test that the cookie has been set correctly
+ cy.getCookie('SKOSMOS_SEARCH_LANG').should('have.property', 'value', 'sv');
+ });
+
+ it('The search language cookie is read', () => {
+ cy.visit('/'); // setting the cookie at the front page to make sure the cookies are set globally
+ cy.setCookie('SKOSMOS_SEARCH_LANG', 'en');
+ cy.visit('/yso/fi/');
+
+ // Test that the cookie value has been read and used to initialize the language selector
+ cy.get('#search-wrapper select').should('have.value', 'en');
+ });
+ });
})