Skip to content

Commit

Permalink
Search for parshiyot by their English names
Browse files Browse the repository at this point in the history
  • Loading branch information
akivajgordon committed Oct 19, 2018
1 parent d6e34bd commit 6f083d8
Show file tree
Hide file tree
Showing 6 changed files with 177 additions and 33 deletions.
96 changes: 92 additions & 4 deletions components/ParshaPicker.js
@@ -1,4 +1,5 @@
import parshiyot from '../build/parshiyot.json'
import fuzzy from '../src/fuzzy'

const Parsha = ({ ref, he }) => `<li
class="parsha"
Expand All @@ -19,12 +20,64 @@ const Book = (book) => `
</li>
`

/*
<li class="search-result">
<p class="search-result-tag">שלח</p>
<p class="search-result-tag"><strong>Sh</strong>e<strong>l</strong>a<strong>ch</strong></p>
</li>
<li class="search-result">
<p class="search-result-tag">בשלח</p>
<p class="search-result-tag">Be<strong>sh</strong>a<strong>l</strong>a<strong>ch</strong></p>
</li>
<li class="search-result">
<p class="search-result-tag">וישלח</p>
<p class="search-result-tag">Vayi<strong>shl</strong>a<strong>ch</strong></p>
</li>
*/

/*
<li class="search-result">
<p class="" style="text-align: center; color: hsla(0, 0%, 0%, 0.5);">No results</p>
</li>
*/
const Search = () => `
<div class="search">
<div class="search-bar">
<span class="search-icon">⚲</span>
<input class="search-input" placeholder="Search..." autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" autofocus />
</div>
<ol class="search-results u-hidden">
</ol>
</div>
`

const decorateString = ({ string, atIndexes, withDecoration }) => {
let indexesIndex = 0
return string
.split('')
.map((char, i) => {
if (atIndexes[indexesIndex] !== i) return char

++indexesIndex
return withDecoration(char)
}, '')
.join('')
}

const SearchResult = ({ string, indexes }) => `
<li class="search-result">
<p class="search-result-tag">${decorateString({
string,
atIndexes: indexes,
withDecoration: (c) => (`<strong>${c}</strong>`)
})}
</p>
</li>
`

const ParshaPicker = () => `
<div class="parsha-picker">
<div class="parsha-search">
<input class="parsha-search-input" placeholder="Search..." autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
<span class="parsha-search-icon">⚲</span>
</div>
${Search()}
<ol class="parsha-books">
${parshiyot
.reduce((books, parsha) => {
Expand All @@ -40,4 +93,39 @@ const ParshaPicker = () => `
</div>
`

const searchResults = (query) => fuzzy(parshiyot.map(parsha => parsha.en), query)

const htmlToElement = (html) => {
const template = document.createElement('template')
html = html.trim() // Never return a text node of whitespace as the result
template.innerHTML = html
return template.content.firstChild
}

const top = (n) => (_, i) => i < n

const search = ({ jumper, query }) => {
const searchResultsElement = jumper.querySelector('.search-results')

if (query) {
searchResultsElement.classList.remove('u-hidden')
jumper.querySelector('.parsha-books').classList.add('u-hidden')

searchResultsElement.innerHTML = ''

searchResults(query)
.filter(top(5))
.map(SearchResult)
.map(htmlToElement)
.forEach(result => {
searchResultsElement.appendChild(result)
})
} else {
searchResultsElement.classList.add('u-hidden')
jumper.querySelector('.parsha-books').classList.remove('u-hidden')
}
}

export { search }

export default ParshaPicker
3 changes: 3 additions & 0 deletions css/master.css
Expand Up @@ -15,10 +15,13 @@

* {
box-sizing: border-box;
margin: 0;
padding: 0;
}

body {
height: 100vh;
font-family: sans-serif;
}

ol {
Expand Down
68 changes: 51 additions & 17 deletions css/parsha-picker.css
Expand Up @@ -26,31 +26,65 @@
padding: 2em 1em;
}

.parsha-search {
position: relative;
font-family: sans-serif;
border-bottom: 2px solid hsla(0, 0%, 0%, 0.25);
.search {
direction: ltr;
}

.parsha-search-input {
border: none;
direction: ltr;
padding: 0.1em 2em 0.1em 0.5em;
width: 30ch;
.search {
background-color: hsla(0, 0%, 0%, 0.05);
display: inline-block;
border-radius: 4px;
color: hsla(0, 0%, 0%, 0.7);
border: 1px solid hsla(0, 0%, 0%, 0);
width: 30ch;
}

.parsha-search-input:focus {
outline: none;
border-color: hsla(0, 0%, 0%, 0.5);
.search:focus-within {
border: 1px solid hsla(0, 0%, 0%, 0.1);
}

.parsha-search-icon {
position: absolute;
right: 10px;
.search-bar {
display: flex;
padding: 0.5em 1em;
}

.search-bar > *:not(:first-child) {
margin-left: 1em;
}

.search-icon {
transform: rotate(-45deg);
font-size: 1.25em;
color: hsla(0, 0%, 0%, 0.7);
display: block;
font-size: 1.5em;
}

.search-input {
border: none;
background-color: transparent;
outline: none;
color: inherit;
}

.search-results {
border-top: 1px solid hsla(0, 0%, 0%, 0.2);
}

.search-result {
list-style: none;
padding: 1em 1em;
cursor: pointer;
}

.search-result:hover {
background-color: hsla(0, 0%, 0%, 0.05);
}

.search-result:not(:last-child) {
border-bottom: 1px solid hsla(0, 0%, 0%, 0.1);
}

.search-result-tag:not(:last-child) {
margin-bottom: 1em;
}

.parsha-books {
Expand Down
14 changes: 10 additions & 4 deletions cypress/integration/jumper.cypress.test.js
Expand Up @@ -76,13 +76,19 @@ describe('app', () => {
cy.contains('וירא')
})

it.only('filters parshiyot', () => {
it('filters parshiyot', () => {
cy.get('body').type('/')

cy
.get('[placeholder*="search" i]')
cy.contains(/vayishlach/i).should('not.be.visible') // shouldn't start by showing search results

cy.focused()
.should('match', '[placeholder*="search" i]')
.type('shlch') // vayishlach, b'shalach, sh'lach

cy.contains('נח').should('not.exist')
cy.contains('נח').should('not.be.visible') // hides parsha list

cy.contains('Vayishlach')
cy.contains(`Beshalach`)
cy.contains(`Sh'lach`)
})
})

0 comments on commit 6f083d8

Please sign in to comment.