Browse Source
These files are provided by the Meilisearch project. This commit is larger than usual because of this. The CSS files are copied over from my personal website's repository so they will need modifying going forward. I've added them here as a starting point.stable
Craig Oates
2 years ago
6 changed files with 769 additions and 0 deletions
@ -0,0 +1,418 @@
|
||||
.search-dashboard { |
||||
margin: 0px; |
||||
padding: 0px; |
||||
display: flex; |
||||
flex-direction: column; |
||||
} |
||||
|
||||
.refinements-panel h2, |
||||
.refinements-panel p { |
||||
padding: 0px; |
||||
margin: 0px; |
||||
} |
||||
.refinements-panel p { |
||||
color : silver; |
||||
font-size: 12px; |
||||
} |
||||
|
||||
#clear-refinements { |
||||
margin-bottom: 20px; |
||||
} |
||||
|
||||
.ais-ClearRefinements-button { |
||||
font-size: 16px; |
||||
height: 40px; |
||||
width: 100%; |
||||
margin: 0px; |
||||
font-family: 'main', sans-serif; |
||||
color: white; |
||||
background-color: #0094ff; |
||||
box-shadow: 2px 2px 1px black; |
||||
border-radius: 4px; |
||||
padding: 10px; |
||||
cursor: pointer; |
||||
text-transform: uppercase; |
||||
border: none; |
||||
} |
||||
|
||||
.ais-ClearRefinements-button:hover { |
||||
background: lightblue; |
||||
color: #0094ff; |
||||
text-decoration: none; |
||||
box-shadow: none; |
||||
} |
||||
|
||||
.ais-ClearRefinements-button--disabled { |
||||
text-align: center; |
||||
padding: 10px; |
||||
border: 2px solid silver; |
||||
border-radius: 4px; |
||||
text-transform: uppercase; |
||||
color: silver; |
||||
background: transparent; |
||||
box-shadow: none; |
||||
} |
||||
|
||||
.ais-ClearRefinements-button--disabled:hover { |
||||
background: transparent; |
||||
color: silver; |
||||
} |
||||
|
||||
.search-refinement-list { |
||||
margin: 20px 0px; |
||||
border-bottom: 2px solid black; |
||||
} |
||||
|
||||
#searchbox { |
||||
width: 100%; |
||||
margin-top: 20px; |
||||
margin-bottom: 20px; |
||||
margin-left: auto; |
||||
margin-right: auto; |
||||
} |
||||
|
||||
.ais-SearchBox, |
||||
.ais-ClearRefinements-button { |
||||
max-width: 600px; |
||||
} |
||||
|
||||
.search-results-container { |
||||
display: flex; |
||||
flex-direction: column; |
||||
} |
||||
|
||||
.ais-SearchBox-form { |
||||
display: flex; |
||||
flex-wrap: nowrap; |
||||
justify-content: center; |
||||
align-items: center; |
||||
} |
||||
|
||||
.ais-SearchBox-input { |
||||
width: 100%; |
||||
height: 40px; |
||||
padding: 10px; |
||||
border: 2px solid #0094ff; |
||||
border-radius: 4px; |
||||
font-family: 'main', sans-serif; |
||||
font-size: 16px; |
||||
} |
||||
|
||||
.ais-SearchBox-input::placeholder { |
||||
font-family: 'main', sans-serif; |
||||
font-size: 16px; |
||||
} |
||||
|
||||
.ais-SearchBox-form input:focus-visible { |
||||
outline: none; |
||||
} |
||||
|
||||
.ais-SearchBox-submitIcon, |
||||
.ais-SearchBox-submit, |
||||
.ais-SearchBox-reset { |
||||
display: none; |
||||
} |
||||
|
||||
.ais-RefinementList-list { |
||||
list-style: none; |
||||
padding: 0px; |
||||
margin: 0px 0px 40px 0px; |
||||
display: flex; |
||||
flex-direction: row; |
||||
width: 100%; |
||||
overflow: scroll; |
||||
} |
||||
|
||||
.ais-RefinementList-label { |
||||
display: flex; |
||||
align-items: center ; |
||||
width: max-content; |
||||
margin-right: 6px; |
||||
} |
||||
|
||||
.ais-RefinementList-label > span { |
||||
padding: 0px 2px; |
||||
} |
||||
|
||||
.ais-RefinementList-checkbox { |
||||
width: 30px; |
||||
height: 30px; |
||||
margin: 0px; |
||||
} |
||||
|
||||
.search-hits-panel { |
||||
width: -webkit-fill-available; |
||||
} |
||||
|
||||
#hits { |
||||
width: 100%; |
||||
min-width: 350px; |
||||
display: flex; |
||||
flex-direction: column; |
||||
} |
||||
|
||||
.ais-Hits-list { |
||||
padding: 0px; |
||||
margin: 0px; |
||||
display: flex; |
||||
flex-direction: column; |
||||
list-style: none; |
||||
} |
||||
|
||||
.ais-Hits-item { |
||||
margin: 12px 0px 12px 0px; |
||||
max-height: 400px; |
||||
border: 2px #0094ff solid; |
||||
border-radius: 4px; |
||||
overflow: hidden; |
||||
display: flex; |
||||
flex-direction: column; |
||||
box-shadow: 3px 3px 3px black; |
||||
} |
||||
|
||||
.ais-Hits-item:hover { |
||||
border-color: lightblue; |
||||
box-shadow: none; |
||||
} |
||||
|
||||
#pagination { |
||||
display: block; |
||||
margin: 40px 0px 40px 0px; |
||||
overflow: auto; |
||||
width: 100%; |
||||
} |
||||
|
||||
.ais-Pagination-list { |
||||
list-style: none; |
||||
padding: 0px; |
||||
margin: 0px; |
||||
display: flex; |
||||
justify-content: center; |
||||
align-items: center; |
||||
} |
||||
|
||||
.ais-Pagination-item { |
||||
margin: 0px; |
||||
display: flex; |
||||
justify-content: center; |
||||
align-items: center; |
||||
max-width: 64px; |
||||
height: 50px; |
||||
} |
||||
|
||||
/* Hack to change content of pagination links |
||||
================================================================================ |
||||
https://stackoverflow.com/questions/48907242/how-can-i-remove-and-replace-content-in-a-html-tag-using-css |
||||
|
||||
Because Meilsearch adds the pagination stuff via JavaScript, I can't set the |
||||
contents of the various HTML elements via the djula templates. This means I have |
||||
to update the content after it's loaded. I didn't want to do this via JavaScript |
||||
because I want to keep the JavaScript to a minimum. So, to fix the problem, I |
||||
came across a hack (see Stack Overflow URL above). You need to change the |
||||
visibility (to hidden) of the element(s) you want to change and then use the |
||||
'content' property to set the new text value. When that is done, you adjust the |
||||
element's visibility back to 'visible'. |
||||
|
||||
I ACKNOWLEDGE THIS IS JACKY BUT IT WORKS. |
||||
*/ |
||||
|
||||
.ais-Pagination-item--firstPage a, |
||||
.ais-Pagination-item--previousPage a, |
||||
.ais-Pagination-item--nextPage a { |
||||
visibility: hidden; |
||||
} |
||||
|
||||
/* Meilisearch not designed for extended pagination use (disabled 'Last' link) |
||||
================================================================================ |
||||
https://github.com/meilisearch/documentation/issues/561 |
||||
Meilisearch adds a 'Last Page' link with its built-in pagination features. With |
||||
that said, the people developing the project acknowledge Meilisearch's |
||||
pagination features are limited. They recommend on not using or relying on it |
||||
too much. See the URL above for more information. |
||||
|
||||
Whilst developing this part of the site, I found the 'Last Page' link was |
||||
behaving inconsistently. You would click the link and it would jump ahead |
||||
(I.E. more than one page) but it took several clicks to get to the 'final/last |
||||
page'. Because of that, I've just turned it off by hiding it with the |
||||
style-rule below. Again, see URL above for more info. on this behaviour. |
||||
*/ |
||||
|
||||
.ais-Pagination-item.ais-Pagination-item--lastPage { |
||||
display: none; |
||||
} |
||||
|
||||
.ais-Pagination-item--firstPage.ais-Pagination-item--disabled span, |
||||
.ais-Pagination-item--previousPage.ais-Pagination-item--disabled span, |
||||
.ais-Pagination-item--nextPage.ais-Pagination-item--disabled span { |
||||
visibility: hidden; |
||||
} |
||||
|
||||
/* The new text is set here: See 'Hack to change content of pagination links' |
||||
note above for more information. */ |
||||
.ais-Pagination-item--firstPage.ais-Pagination-item--disabled span:before { |
||||
content: "First"; |
||||
visibility: visible; |
||||
} |
||||
|
||||
.ais-Pagination-item--previousPage.ais-Pagination-item--disabled span:before { |
||||
content: "Prev."; |
||||
visibility: visible; |
||||
} |
||||
.ais-Pagination-item--nextPage.ais-Pagination-item--disabled span:before { |
||||
content: "Next"; |
||||
visibility: visible; |
||||
margin-left: 8px; |
||||
} |
||||
|
||||
.ais-Pagination-item--firstPage.ais-Pagination-item--disabled span:before, |
||||
.ais-Pagination-item--previousPage.ais-Pagination-item--disabled span:before, |
||||
.ais-Pagination-item--nextPage.ais-Pagination-item--disabled span:before { |
||||
width: 70px; |
||||
height: 39px; |
||||
text-transform: uppercase; |
||||
border: 2px solid silver; |
||||
border-radius: 4px; |
||||
text-align: center; |
||||
padding: 8px; |
||||
color: silver; |
||||
} |
||||
|
||||
.ais-Pagination-item--firstPage a:before { |
||||
content: "First"; |
||||
visibility: visible; |
||||
} |
||||
|
||||
.ais-Pagination-item--previousPage a:before { |
||||
content: "Prev."; |
||||
visibility: visible; |
||||
} |
||||
|
||||
.ais-Pagination-item--nextPage a:before { |
||||
content: "Next"; |
||||
visibility: visible; |
||||
margin-left: 8px; |
||||
} |
||||
|
||||
.ais-Pagination-item--firstPage a:link::before, |
||||
.ais-Pagination-item--previousPage a:link::before, |
||||
.ais-Pagination-item--nextPage a:link::before { |
||||
width: 100%; |
||||
height: 39px; |
||||
text-transform: uppercase; |
||||
background: #0094ff; |
||||
color: white; |
||||
border: 2px solid #0094ff; |
||||
border-radius: 4px; |
||||
text-align: center; |
||||
padding: 8px; |
||||
text-decoration: none; |
||||
box-shadow: 2px 2px 3px black; |
||||
} |
||||
|
||||
.ais-Pagination-item--page a:link { |
||||
background: #0094ff; |
||||
color: white; |
||||
padding: 10px; |
||||
border-radius: 4px; |
||||
text-transform: uppercase; |
||||
text-decoration: none; |
||||
margin: 0px 2px; |
||||
box-shadow: 2px 2px 3px black; |
||||
} |
||||
|
||||
.ais-Pagination-item--selected a:link, |
||||
.ais-Pagination-item--selected a:hover { |
||||
background: silver !important; |
||||
color: white; |
||||
box-shadow: none; |
||||
} |
||||
|
||||
.ais-Pagination-item--page a:hover { |
||||
background: lightblue; |
||||
text-decoration: none; |
||||
box-shadow: none; |
||||
} |
||||
|
||||
.ais-Pagination-item--firstPage a:hover::before, |
||||
.ais-Pagination-item--previousPage a:hover::before, |
||||
.ais-Pagination-item--nextPage a:hover::before { |
||||
background: lightblue; |
||||
border: 2px solid lightblue; |
||||
border-radius: 4px; |
||||
text-align: center; |
||||
color: #0094ff; |
||||
box-shadow: none; |
||||
} |
||||
|
||||
.ais-Pagination-item--firstPage a:hover, |
||||
.ais-Pagination-item--previousPage a:hover, |
||||
.ais-Pagination-item--nextPage a:hover { |
||||
text-decoration: none !important; |
||||
} |
||||
|
||||
@media (min-width:600px) { |
||||
.ais-ClearRefinements-button { |
||||
max-width: 200px; |
||||
} |
||||
} |
||||
|
||||
@media (min-width:961px) { |
||||
.search-results-container { |
||||
flex-direction: row; |
||||
} |
||||
|
||||
.refinements-panel { |
||||
max-width: 300px; |
||||
width: 100%; |
||||
margin-right: 20px; |
||||
} |
||||
|
||||
.ais-RefinementList-list { |
||||
font-size: 12px; |
||||
flex-direction: column; |
||||
overflow: auto; |
||||
} |
||||
|
||||
.ais-RefinementList-item { |
||||
margin: 2px 0px; |
||||
} |
||||
|
||||
.ais-RefinementList-checkbox { |
||||
width: 20px; |
||||
margin-right: 4px; |
||||
} |
||||
|
||||
#hits { |
||||
flex-direction: row; |
||||
flex-wrap: wrap; |
||||
} |
||||
|
||||
.ais-Hits-list { |
||||
padding: 0px; |
||||
margin: 0px; |
||||
display: flex; |
||||
flex-direction: row; |
||||
flex-wrap: wrap; |
||||
list-style: none; |
||||
} |
||||
|
||||
.ais-Hits-item { |
||||
width: 200px; |
||||
height: 280px; |
||||
margin: 12px; |
||||
height: 100%; |
||||
display: flex; |
||||
flex-direction: column; |
||||
} |
||||
|
||||
.ais-Hits-item .ui-link-card .ui-card-text { |
||||
height: 75px; |
||||
/* white-space: nowrap; */ |
||||
text-overflow: ellipsis; |
||||
} |
||||
|
||||
.ais-Hits-item .ui-link-card .ui-card-text .ui-card-secondary { |
||||
text-overflow: ellipsis; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,121 @@
|
||||
.ui-search-container { |
||||
margin: 0px; |
||||
display: flex; |
||||
position: abosolute; |
||||
flex-direction: column; |
||||
align-items: center; |
||||
height: 120px; |
||||
border-bottom: 2px solid black; |
||||
} |
||||
|
||||
#searchbox { |
||||
position: relative; |
||||
top: 40px; |
||||
width: 100%; |
||||
max-width: 600px; |
||||
} |
||||
|
||||
.ais-SearchBox-form { |
||||
display: flex; |
||||
flex-wrap: nowrap; |
||||
justify-content: center; |
||||
align-items: center; |
||||
} |
||||
|
||||
.ais-SearchBox-input { |
||||
width: 100%; |
||||
height: 40px; |
||||
padding: 10px; |
||||
border: 2px solid #0094ff; |
||||
border-radius: 4px 4px 0px 0px; |
||||
font-family: 'main', sans-serif; |
||||
font-size: 16px; |
||||
} |
||||
|
||||
.ais-SearchBox-input::placeholder { |
||||
font-family: 'main', sans-serif; |
||||
font-size: 16px; |
||||
} |
||||
|
||||
.ais-SearchBox-form input:focus-visible { |
||||
outline: none; |
||||
} |
||||
|
||||
.ais-SearchBox-submit { |
||||
font-size: 16px; |
||||
height: 40px; |
||||
margin: 0px; |
||||
font-family: 'main', sans-serif; |
||||
color: white; |
||||
background-color: #0094ff; |
||||
border-radius: 4px; |
||||
padding: 10px; |
||||
cursor: pointer; |
||||
text-transform: uppercase; |
||||
border: none; |
||||
} |
||||
|
||||
.ais-SearchBox-submitIcon, |
||||
.ais-SearchBox-submit, |
||||
.ais-SearchBox-reset, |
||||
#hits { |
||||
display: none; |
||||
} |
||||
|
||||
#hits { |
||||
position: relative; |
||||
top:40px; |
||||
background: white; |
||||
width: calc(100% - 4px); |
||||
max-width: calc(600px - 4px); |
||||
border-right: 2px solid #0094ff; |
||||
border-bottom: 2px solid #0094ff; |
||||
border-left: 2px solid #0094ff; |
||||
border-radius: 0px 0px 4px 4px; |
||||
} |
||||
|
||||
.ais-Hits-list { |
||||
list-style: none; |
||||
padding: 0px 2px; |
||||
margin: 0px; |
||||
} |
||||
|
||||
.ais-Hits-list:first-child { |
||||
display: flex; |
||||
flex-wrap: nowrap; |
||||
flex-direction: column; |
||||
justify-content: flex-start; |
||||
} |
||||
|
||||
|
||||
.ais-Hits-item { |
||||
margin: 4px 0px 0px 0px; |
||||
} |
||||
|
||||
.ui-link-search-card { |
||||
overflow: hidden; |
||||
white-space: nowrap; |
||||
text-overflow: ellipsis; |
||||
width: 100%; |
||||
} |
||||
|
||||
.ui-link-search-card:link { |
||||
text-decoration: none; |
||||
float: left; |
||||
border-radius: 0px; |
||||
padding: 4px 0px; |
||||
} |
||||
|
||||
.ui-link-search-card img { |
||||
width: 30px; |
||||
height: 30px; |
||||
display: inline; |
||||
float: left; |
||||
padding: 0px 6px; |
||||
} |
||||
|
||||
.ui-link-search-card span { |
||||
vertical-align: middle; |
||||
} |
||||
|
||||
|
@ -0,0 +1,97 @@
|
||||
/** |
||||
Full Search |
||||
================================================================================ |
||||
This file's main focus in providing the Meilisearch features to the |
||||
search/index.html template. |
||||
|
||||
For more information on Meilisearch, use: |
||||
|
||||
- https://docs.meilisearch.com/
|
||||
- https://github.com/meilisearch/instant-meilisearch
|
||||
|
||||
Meilisearch provides an 'InstantSearch' add-on (plug-in?) which |
||||
links the Meilisearch instance you have running to this website (link above for |
||||
more information). |
||||
*/ |
||||
|
||||
let server = ""; |
||||
let apiKey = ""; |
||||
|
||||
if (location.hostname === "localhost" |
||||
|| location.hostname === "127.0.0.1" |
||||
|| location.hostname === "beta.nera.com") { |
||||
server = "http://localhost:7700"; |
||||
apiKey= "meilisearch-beta-key"; |
||||
} else { |
||||
server = "https://www.nera.net"; |
||||
apiKey = "meilisearch-production-key-nera"; |
||||
} |
||||
|
||||
const search = instantsearch({ |
||||
indexName: "nera", |
||||
searchClient: instantMeiliSearch( |
||||
server, |
||||
apiKey, |
||||
{ |
||||
primaryKey: 'id', |
||||
} |
||||
) |
||||
}); |
||||
|
||||
search.addWidgets([ |
||||
instantsearch.widgets.searchBox({ |
||||
container: "#searchbox", |
||||
placeholder: "Search...", |
||||
}), |
||||
instantsearch.widgets.clearRefinements({ |
||||
container: "#clear-refinements" |
||||
}), |
||||
instantsearch.widgets.refinementList({ |
||||
container: "#year-list", |
||||
attribute: "year" |
||||
}), |
||||
instantsearch.widgets.refinementList({ |
||||
container: "#month-list", |
||||
attribute: "month" |
||||
}), |
||||
instantsearch.widgets.refinementList({ |
||||
container: "#keywords-list", |
||||
attribute: "keywords" |
||||
}), |
||||
instantsearch.widgets.configure({ |
||||
hitsPerPage: 30, |
||||
snippetEllipsisText: "...", |
||||
attributesToSnippet: ["title:100"] |
||||
}), |
||||
instantsearch.widgets.hits({ |
||||
container: "#hits", |
||||
templates: { |
||||
item: ` |
||||
<a class="ui-link-card" href="{{server}}/{{relative-path}}"> |
||||
<div> |
||||
<img src="{{server}}/{{thumbnail-path}}"/> |
||||
<div class="ui-card-text"> |
||||
<span class="ui-card-title"> |
||||
{{#helpers.highlight}}{"attribute": "title"}{{/helpers.highlight}} |
||||
</span> |
||||
<span class="ui-card-secondary"> |
||||
{{#helpers.highlight}}{"attribute": "year"}{{/helpers.highlight}} |
||||
</span> |
||||
<span class="ui-card-secondary"> |
||||
{{#helpers.highlight}}{"attribute": "month"}{{/helpers.highlight}} |
||||
</span> |
||||
<span class="ui-card-keywords"> |
||||
{{keywords}} |
||||
</span> |
||||
</div> |
||||
</div> |
||||
</a> |
||||
` |
||||
} |
||||
}), |
||||
instantsearch.widgets.pagination({ |
||||
container: "#pagination" |
||||
}) |
||||
]); |
||||
|
||||
search.start(); |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,101 @@
|
||||
/** |
||||
Quick Search |
||||
================================================================================ |
||||
This file's main focus is to provide the functionality for the 'quick search' |
||||
bar feature, which is available across the site. The search features are |
||||
provided by Meilisearch. Use the links below for more information. |
||||
|
||||
For more information on Meilisearch, use: |
||||
|
||||
- https://docs.meilisearch.com/
|
||||
- https://github.com/meilisearch/instant-meilisearch
|
||||
|
||||
Meilisearch provides an 'InstantSearch' add-on (plug-in?) which links the |
||||
Meilisearch instance you have running to this website (link above for more |
||||
information). |
||||
*/ |
||||
|
||||
let server = ""; |
||||
let apiKey = ""; |
||||
|
||||
if (location.hostname === "localhost" |
||||
|| location.hostname === "127.0.0.1" |
||||
|| location.hostname === "beta.craigoates.net") { |
||||
server = "http://beta-search.craigoates.net"; |
||||
apiKey= "meilisearch-beta-key"; |
||||
} else { |
||||
server = "https://search.craigoates.net"; |
||||
apiKey = "meilisearch-production-key-26-07-2022"; |
||||
} |
||||
|
||||
const search = instantsearch({ |
||||
indexName: "project", |
||||
searchClient: instantMeiliSearch( |
||||
server, |
||||
apiKey, |
||||
{ |
||||
primaryKey: 'id', |
||||
} |
||||
) |
||||
}); |
||||
|
||||
search.addWidgets([ |
||||
instantsearch.widgets.searchBox({ |
||||
container: "#searchbox", |
||||
autofocus: false, |
||||
placeholder: "Quick Search...", |
||||
}), |
||||
instantsearch.widgets.configure({ hitsPerPage: 8 }), |
||||
instantsearch.widgets.hits({ |
||||
container: "#hits", |
||||
templates: { |
||||
item: ` |
||||
<a class="ui-link-search-card" href="{{server}}/{{relative-path}}"> |
||||
<img src="{{server}}/{{thumbnail-path}}"/>
|
||||
<span>{{#helpers.highlight}}{"attribute": "title"}{{/helpers.highlight}}</span> |
||||
</a> |
||||
` |
||||
} |
||||
}) |
||||
]); |
||||
|
||||
search.start(); |
||||
|
||||
const searchBox = |
||||
document.querySelector(".ais-SearchBox-input"); |
||||
|
||||
const searchResultsBox = |
||||
document.getElementById('hits'); |
||||
|
||||
const searchResultsList = |
||||
document.querySelector(".ais-Hits-list"); |
||||
|
||||
searchBox.addEventListener("keydown", showSearchResults); |
||||
|
||||
document.onmousedown = () => { |
||||
if (document.activeElement !== searchBox) { |
||||
hideSearchResults(); |
||||
} |
||||
}; |
||||
|
||||
function showSearchResults() { |
||||
document.getElementById('hits').style.display = 'block'; |
||||
document.onkeydown = (evt) => { |
||||
if (evt.keyCode === 9) { |
||||
searchResultsBox.focus(); |
||||
} |
||||
if (evt.keyCode === 27) { |
||||
searchBox.blur(); |
||||
hideSearchResults(); |
||||
} |
||||
}; |
||||
document.onkeyup = (evt) => { |
||||
if (searchBox.value.length == 0) { |
||||
hideSearchResults(); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
function hideSearchResults() { |
||||
document.getElementById('hits').style.display = 'none'; |
||||
} |
Loading…
Reference in new issue