Skip to content

Commit

Permalink
NEW: Language Filter (#155)
Browse files Browse the repository at this point in the history
closes #155
  • Loading branch information
dwhieb committed Jul 17, 2024
1 parent 780374d commit 919b9f7
Show file tree
Hide file tree
Showing 10 changed files with 142 additions and 93 deletions.
7 changes: 6 additions & 1 deletion data/Database.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,19 @@ export default class Database {
this.components = Array.from(this.index.values())
}

search(query) {
search(query, langQuery) {
// NB: Be careful not to alter the original array here.
return Array.from(this.components).filter(function({
definition,
form,
language,
PA,
tokens,
UR,
}) {

if (langQuery && langQuery !== `all` && langQuery !== language) return false

return definition?.toLowerCase().includes(query)
|| form?.toLowerCase().includes(query)
|| PA?.toLowerCase().includes(query)
Expand All @@ -41,6 +45,7 @@ export default class Database {
|| PA?.toLowerCase().includes(query)
|| UR?.toLowerCase().includes(query)
})

})
}

Expand Down
5 changes: 3 additions & 2 deletions data/Languages.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ export default class Languages extends Map {

}

convertRecord({ key, name }) {
return { key, name }
convertRecord({ autonyms = ``, key, name }) {
autonyms = autonyms.split(/,\s*/gv).filter(Boolean)
return { autonyms, key, name }
}

async load() {
Expand Down
82 changes: 41 additions & 41 deletions data/json/languages.ndjson
Original file line number Diff line number Diff line change
@@ -1,41 +1,41 @@
{"key":"Abenaki","name":"Abenaki"}
{"key":"Abenaki_Eastern","name":"Eastern Abenaki"}
{"key":"Abenaki_Western","name":"Western Abenaki"}
{"key":"Arapaho","name":"Arapaho"}
{"key":"Blackfoot","name":"Blackfoot"}
{"key":"Cheyenne","name":"Cheyenne"}
{"key":"Cree_Atikamekw","name":"Atikamekw"}
{"key":"Cree_East","name":"East Cree"}
{"key":"Cree_Innu","name":"Innu"}
{"key":"Cree_Moose_Swampy","name":"Moose-Swampy Cree"}
{"key":"Cree_Naskapi_Western","name":"Western Naskapi"}
{"key":"Cree_Northern_East","name":"Northern East Cree"}
{"key":"Cree_Plains","name":"Plains Cree"}
{"key":"Cree_Southern_East","name":"Southern East Cree"}
{"key":"Cree_Swampy","name":"Swampy Cree"}
{"key":"Delaware_Common","name":"Common Delaware"}
{"key":"Delaware_Munsee","name":"Munsee"}
{"key":"Delaware_Unami","name":"Unami"}
{"key":"Kickapoo","name":"Kickapoo"}
{"key":"Menominee","name":"Menominee"}
{"key":"Meskwaki","name":"Meskwaki"}
{"key":"Miami_Illinois","name":"Miami-Illinois"}
{"key":"Mikmaq","name":"Mi’kmaq"}
{"key":"Narragansett","name":"Narragansett"}
{"key":"Ojibwe_Algonquin","name":"Algonquin"}
{"key":"Ojibwe_Common","name":"Common Ojibwe"}
{"key":"Ojibwe_Eastern","name":"Eastern Ojibwe"}
{"key":"Ojibwe_Nipissing","name":"Nipissing"}
{"key":"Ojibwe_NW","name":"Northwestern Ojibwe"}
{"key":"Ojibwe_Odawa","name":"Odawa"}
{"key":"Ojibwe_Severn","name":"Severn Ojibwe"}
{"key":"Ojibwe_SW","name":"Southwestern Ojibwe"}
{"key":"Passamaquoddy_Maliseet","name":"Passamaquoddy-Maliseet"}
{"key":"Potawatomi","name":"Potawatomi"}
{"key":"Powhatan","name":"Powhatan"}
{"key":"Proto_Algonquian","name":"Proto-Algonquian"}
{"key":"Proto_Central_Algonquian","name":"Proto-Central Algonquian"}
{"key":"Proto_Central_Eastern_Algonquian","name":"Proto-Central Eastern Algonquian"}
{"key":"Proto_Eastern_Algonquian","name":"Proto-Eastern Algonquian"}
{"key":"Shawnee","name":"Shawnee"}
{"key":"Wampanoag","name":"Wampanoag"}
{"autonyms":[],"key":"Abenaki","name":"Abenaki"}
{"autonyms":["Alənαpαtəwéwαkan"],"key":"Abenaki_Eastern","name":"Eastern Abenaki"}
{"autonyms":["Alnôbaôdwawôgan"],"key":"Abenaki_Western","name":"Western Abenaki"}
{"autonyms":["Hinónoʼeitíít"],"key":"Arapaho","name":"Arapaho"}
{"autonyms":["Niitsi'powahsin"],"key":"Blackfoot","name":"Blackfoot"}
{"autonyms":["Tsėhesenėstsestotse"],"key":"Cheyenne","name":"Cheyenne"}
{"autonyms":["nehirâmowin"],"key":"Cree_Atikamekw","name":"Atikamekw"}
{"autonyms":[],"key":"Cree_East","name":"East Cree"}
{"autonyms":["Innu-Aimun"],"key":"Cree_Innu","name":"Innu"}
{"autonyms":[],"key":"Cree_Moose_Swampy","name":"Moose-Swampy Cree"}
{"autonyms":[],"key":"Cree_Naskapi_Western","name":"Western Naskapi"}
{"autonyms":["iyiyiu-Ayamiwin","ᐄᔨᔫ ᐊᔨᒨᓐ "],"key":"Cree_Northern_East","name":"Northern East Cree"}
{"autonyms":["nêhiyawêwin","ᓀᐦᐃᔭᐍᐏᐣ"],"key":"Cree_Plains","name":"Plains Cree"}
{"autonyms":["iyiniu-Ayamiwin ᐄᓅ ᐊᔨᒨᓐ"],"key":"Cree_Southern_East","name":"Southern East Cree"}
{"autonyms":["Nêhinawêwin","ᓀᐦᐃᓇᐍᐏᐣ "],"key":"Cree_Swampy","name":"Swampy Cree"}
{"autonyms":[],"key":"Delaware_Common","name":"Common Delaware"}
{"autonyms":["monsii"],"key":"Delaware_Munsee","name":"Munsee"}
{"autonyms":["ləná·p·e"],"key":"Delaware_Unami","name":"Unami"}
{"autonyms":[],"key":"Kickapoo","name":"Kickapoo"}
{"autonyms":["Oma͞eqnomenēweqnaesen","Mamāceqtaweqnaesen"],"key":"Menominee","name":"Menominee"}
{"autonyms":["Meshkwahkihaki"],"key":"Meskwaki","name":"Meskwaki"}
{"autonyms":["myaamia"],"key":"Miami_Illinois","name":"Miami-Illinois"}
{"autonyms":["Miꞌkmawiꞌsimk"],"key":"Mikmaq","name":"Mi’kmaq"}
{"autonyms":[],"key":"Narragansett","name":"Narragansett"}
{"autonyms":["Omàmìwininìmowin"],"key":"Ojibwe_Algonquin","name":"Algonquin"}
{"autonyms":["Anishinaabemowin","Ojibwemowin"],"key":"Ojibwe_Common","name":"Common Ojibwe"}
{"autonyms":["Nishnaabemwin"],"key":"Ojibwe_Eastern","name":"Eastern Ojibwe"}
{"autonyms":[],"key":"Ojibwe_Nipissing","name":"Nipissing"}
{"autonyms":[],"key":"Ojibwe_NW","name":"Northwestern Ojibwe"}
{"autonyms":["Nishnaabemwin"],"key":"Ojibwe_Odawa","name":"Odawa"}
{"autonyms":["Anishininiimowin"],"key":"Ojibwe_Severn","name":"Severn Ojibwe"}
{"autonyms":["Anishinaabemowin"],"key":"Ojibwe_SW","name":"Southwestern Ojibwe"}
{"autonyms":["skicinuwatuwewakon"],"key":"Passamaquoddy_Maliseet","name":"Passamaquoddy-Maliseet"}
{"autonyms":["Bodwéwadmimwen"],"key":"Potawatomi","name":"Potawatomi"}
{"autonyms":[],"key":"Powhatan","name":"Powhatan"}
{"autonyms":[],"key":"Proto_Algonquian","name":"Proto-Algonquian"}
{"autonyms":[],"key":"Proto_Central_Algonquian","name":"Proto-Central Algonquian"}
{"autonyms":[],"key":"Proto_Central_Eastern_Algonquian","name":"Proto-Central Eastern Algonquian"}
{"autonyms":[],"key":"Proto_Eastern_Algonquian","name":"Proto-Eastern Algonquian"}
{"autonyms":["Sawanwa","Savannah","Sewanee","Shawano"],"key":"Shawnee","name":"Shawnee"}
{"autonyms":["Wôpanâôt8âôk"],"key":"Wampanoag","name":"Wampanoag"}
13 changes: 13 additions & 0 deletions pages/Search/Search.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
@import './components/pagination/pagination.css';

/* Utility Classes */

:root {
--cell-border: 1px solid #CCC;
}
Expand All @@ -25,6 +26,7 @@
}

/* Cell-Specific Styles */

/* bottom border */
.bb {
border-block-end: var(--cell-border);
Expand All @@ -36,11 +38,13 @@
}

/* Multi-Element Styles */

:is(.form, .PA, .source-forms, .source-PA, .source-URs, .UR) {
white-space: nowrap;
}

/* Element-Specific Styles */

body {
inline-size: fit-content !important;
max-inline-size: none;
Expand Down Expand Up @@ -84,6 +88,14 @@ h2 {
position: sticky;
}

#language-select {
all: revert; /* Use default browser styles. */
font-family: 'Times New Roman', serif; /* This is necessary because the adjustments to ligatures don't apply within the <select> element. */
font-size: 100%;
line-height: 1.5;
padding: 0.25em;
}

#main {
align-items: flex-start;
align-self: stretch;
Expand Down Expand Up @@ -204,6 +216,7 @@ search {
flex-wrap: wrap;
gap: 0.5em;
justify-content: center;
margin: 0.5em;
}

.search-form {
Expand Down
33 changes: 20 additions & 13 deletions pages/Search/Search.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,30 @@
<search class=sticky>
<form class=search-form method=get>
<label for=search-box>Quick Search</label>
<input
autocomplete=on
autocorrect=off
class=text-box
enterkeyhint=search
id=search-box
inputmode=search
name=q
placeholder='e.g. “atimw-” or “dog”'
spellcheck=false
type=search
>
<span class=help-text>Searches forms (in any orthography) and definitions for a match anywhere within the string. Search is not case sensitive. Leave blank to display all components.</span>
<label for=language-select>Language</label>
<select class=text-box name=language id=language-select>
<option selected value=all>All languages</option>
{{#each languages as |lang| }}
<option value='{{ key }}'>{{ name }} {{#if autonyms }}({{#each autonyms }}{{ this }}{{#unless @last }}, {{/unless}}{{/each}}){{/if}}</option>
{{/each}}
</select>
<div class=search-controls>
<input
autocomplete=on
autocorrect=off
class=text-box
enterkeyhint=search
id=search-box
inputmode=search
name=q
placeholder='e.g. “atimw-” or “dog”'
spellcheck=false
type=search
>
<button class='button green' type=submit>Search</button>
<button class='button blue' type=reset>Reset</button>
</div>
<span class=help-text>Searches forms (in any orthography) and definitions for a match anywhere within the string. Search is not case sensitive. Leave blank and press "Search" to display all components.</span>
</form>
</search>

Expand Down
27 changes: 14 additions & 13 deletions pages/Search/Search.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export function Search(req, res) {
const { db } = req.app

const context = {
languages: db.languages.toJSON().sort((a, b) => a.name.localeCompare(b.name)),
numComponents: db.index.size.toLocaleString(),
numLanguages: db.languages.size.toLocaleString(),
pageCSS: res.app.locals.styles.Search,
Expand All @@ -25,7 +26,7 @@ export function Search(req, res) {
url: req.originalUrl,
}

if (!(`q` in req.query)) {
if (!(`q` in req.query || `language` in req.query)) {
return res.render(`Search/Search`, context)
}

Expand All @@ -42,14 +43,15 @@ export function Search(req, res) {

q = q.trim().toLowerCase()

const allResults = req.app.db.search(q)
let results = req.app.db.search(q, req.query.language)
const numTotalResults = results.length

// Sort

sort = new SortDirectives(sort)

if (sort.size) {
allResults.sort((a, b) => {
results.sort((a, b) => {

const comparisons = Array.from(sort.entries())
.map(([field, { direction }]) => {
Expand All @@ -64,14 +66,13 @@ export function Search(req, res) {

// Pagination

limit = Number(limit)
offset = Number(offset)

const results = allResults.slice(offset, offset + limit)
limit = Number(limit)
offset = Number(offset)
results = results.slice(offset, offset + limit)

const numAdjacentPages = 5
const lastPageOffset = Math.floor(allResults.length / limit) * limit
const nextPageOffset = Math.min(offset + limit, allResults.length)
const lastPageOffset = Math.floor(numTotalResults / limit) * limit
const nextPageOffset = Math.min(offset + limit, numTotalResults)
const prevPageOffset = Math.max(offset - limit, 0)
const url = new URL(req.originalUrl, `${ req.protocol }://${ req.host }`)

Expand Down Expand Up @@ -99,7 +100,7 @@ export function Search(req, res) {

let nextOffset = offset + limit

while (nextOffset <= allResults.length && nextPages.length <= numAdjacentPages) {
while (nextOffset <= numTotalResults && nextPages.length <= numAdjacentPages) {

nextPages.push({
link: changeParam(url, `offset`, nextOffset),
Expand All @@ -124,7 +125,7 @@ export function Search(req, res) {
numResults: results.length.toLocaleString(),
pagination: {
currentPage: Math.floor(offset / limit) + 1,
endIndex: Math.min(offset + limit, allResults.length).toLocaleString(),
endIndex: Math.min(offset + limit, numTotalResults).toLocaleString(),
links: {
firstPage: changeParam(url, `offset`, 0),
lastPage: changeParam(url, `offset`, lastPageOffset),
Expand All @@ -133,12 +134,12 @@ export function Search(req, res) {
},
nextPages,
prevPages,
show: allResults.length > limit,
show: numTotalResults > limit,
startIndex: (offset + 1).toLocaleString(),
},
results,
sort: Object.fromEntries(sort),
totalResults: allResults.length.toLocaleString(),
totalResults: numTotalResults.toLocaleString(),
})

res.render(`Search/Search`, context)
Expand Down
19 changes: 19 additions & 0 deletions pages/Search/Search.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,25 @@ describe(`Search`, function() {

})

describe(`Language Filter`, function() {

it(`language filter only`, function() {
cy.visit(`/search`)
cy.get(`#language-select`).select(`Cree_East`)
cy.get(`form`).submit()
cy.get(`#results tbody tr`).should(`have.length`, 6)
})

it(`language filter + search query`, function() {
cy.visit(`/search`)
cy.get(`#search-box`).type(`yi`)
cy.get(`#language-select`).select(`Cree_East`)
cy.get(`form`).submit()
cy.get(`#results tbody tr`).should(`have.length`, 1)
})

})

describe(`Pagination`, function() {

it(`defaults`, function() {
Expand Down
8 changes: 4 additions & 4 deletions pages/Search/client.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/* global document */

import Copier from '../../scripts/Copier.js'
import SearchBox from './scripts/SearchBox.js'
import Table from './scripts/Table.js'
import Copier from '../../scripts/Copier.js'
import SearchForm from './scripts/SearchForm.js'
import Table from './scripts/Table.js'

// Initialize button to copy citation information

Expand All @@ -16,7 +16,7 @@ if (button && el) {

// Initialize search box

const search = new SearchBox
const search = new SearchForm

search.initialize()

Expand Down
19 changes: 0 additions & 19 deletions pages/Search/scripts/SearchBox.js

This file was deleted.

22 changes: 22 additions & 0 deletions pages/Search/scripts/SearchForm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/* global document, window */

export default class SearchForm {

initialize() {

this.search = document.getElementById(`search-box`)
this.language = document.getElementById(`language-select`)

const url = new URL(window.location.href)

const query = url.searchParams.get(`q`)
const language = url.searchParams.get(`language`)

if (query) this.search.value = query
if (language) this.language.value = language

this.search.focus()

}

}

0 comments on commit 919b9f7

Please sign in to comment.