mirror of
https://github.com/alexankitty/Myrient-Search-Engine.git
synced 2026-01-15 16:33:15 -03:00
- Add PSP support on web emu - properly doing CORS (blame PPSSPP) - added contributors image on about - proxying emulatorjs to avoid internet blocking - initial seeds for multithreading on webemu - added new searchalikes - Added new error page
288 lines
9.8 KiB
Plaintext
288 lines
9.8 KiB
Plaintext
<meta charset="UTF-8">
|
|
<!-- HTML Meta Tags -->
|
|
<title><%= process.env.INSTANCE_NAME || 'Myrient' %> Search</title>
|
|
|
|
<!-- CSS (load bootstrap from a CDN) -->
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.2/css/bootstrap.min.css" crossorigin="anonymous">
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css" crossorigin="anonymous">
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css" crossorigin="anonymous">
|
|
<style>
|
|
|
|
html, body {
|
|
height: 100%;
|
|
}
|
|
body{
|
|
padding: 0;
|
|
margin: 0;
|
|
background-color: #1c2020;
|
|
color: #fff!important;
|
|
}
|
|
a {
|
|
color: #FFFFFF;
|
|
text-decoration: none;
|
|
}
|
|
tr:hover td {
|
|
color: #FFFFFF;
|
|
background: #3D4351;
|
|
}
|
|
a:hover {
|
|
text-decoration: underline;
|
|
color: #FFFFFF;
|
|
}
|
|
td {
|
|
webkit-transition: background 300ms ease-in;
|
|
transition-behavior: normal;
|
|
transition-duration: 300ms;
|
|
transition-timing-function: ease-in;
|
|
transition-delay: 0s;
|
|
transition-property: background;
|
|
-moz-transition: background 300ms ease-in;
|
|
-ms-transition: background 300ms ease-in;
|
|
-o-transition: background 300ms ease-in;
|
|
transition: background 300ms ease-in;
|
|
transition-behavior: normal;
|
|
transition-duration: 300ms;
|
|
transition-timing-function: ease-in;
|
|
transition-delay: 0s;
|
|
}
|
|
td a {
|
|
display: block;
|
|
}
|
|
|
|
.footer-text{
|
|
margin: 0;
|
|
}
|
|
.selected{
|
|
color: rgb(255, 189, 51)!important;
|
|
}
|
|
.hidden{
|
|
display: none;
|
|
}
|
|
.nav-link:hover, .navbar-brand:hover{
|
|
color: #f0a400!important;
|
|
}
|
|
.nav-link, .navbar-brand{
|
|
transition: all 0.5s;
|
|
}
|
|
.card {
|
|
background-color: #262c2c;
|
|
border: 1px solid rgba(255,255,255,.325)
|
|
}
|
|
.form-control:focus {
|
|
border-color: rgb(255, 189, 51)!important;
|
|
box-shadow: 0 0 0 .2rem rgba(240, 164, 0, .25)!important;
|
|
}
|
|
.form-control {
|
|
background-color: #343a40!important;
|
|
color: #fff!important;
|
|
}
|
|
.page-link {
|
|
background-color: #343a40!important;
|
|
color: rgb(255, 189, 51)!important;
|
|
transition: all 0.5s;
|
|
}
|
|
.page-item.active .page-link {
|
|
border-color: rgb(255, 189, 51)!important;
|
|
}
|
|
.page-link:hover {
|
|
color: #f0a400!important;
|
|
border-color: #f0a400;
|
|
}
|
|
.page-item.disabled .page-link {
|
|
color: #6c757d!important
|
|
}
|
|
.custom-select:focus {
|
|
box-shadow: 0 0 0 .2rem rgba(240, 164, 0, .25)!important;
|
|
}
|
|
.stats {
|
|
display: inline-block;
|
|
color: #6c757d;
|
|
margin-bottom: 5px;
|
|
}
|
|
.SuggestionList {
|
|
text-align: left;
|
|
display: none;
|
|
list-style: none;
|
|
list-style-image: none;
|
|
padding: 0;
|
|
border: 1px solid #ccc;
|
|
margin: 0 0 0.2em 0;
|
|
border-radius: 3px;
|
|
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
|
|
background: #262c2c;
|
|
background-color: #262c2c;
|
|
background-image: none;
|
|
position: absolute;
|
|
z-index: 20;
|
|
|
|
}
|
|
.Suggestion {
|
|
padding: 0.5em 1em;
|
|
border-bottom: 1px solid #eee;
|
|
}
|
|
.Suggestion:last-child {
|
|
border: none;
|
|
}
|
|
.Suggestion:hover {
|
|
background: #484f60;
|
|
}
|
|
.Suggestion.selected {
|
|
background: #576075;
|
|
}
|
|
|
|
</style>
|
|
|
|
<script defer>
|
|
typingTimeout = null
|
|
selectedSuggestion = null
|
|
totalSuggestions = 0
|
|
async function getSuggestions(query){
|
|
await fetch('/suggest',
|
|
{method: 'POST',
|
|
body: JSON.stringify({query: query}),
|
|
headers: {"Content-type": "application/json; charset=UTF-8"}}
|
|
)
|
|
.then((response) => response.json())
|
|
.then((json) => populateSuggestions(json));
|
|
}
|
|
async function populateSuggestions(suggestArr){
|
|
selectedSuggestion = null
|
|
suggestions = suggestArr.suggestions
|
|
let suggestionList = document.getElementById('suggestionList')
|
|
suggestionList.replaceChildren()
|
|
let searchElem = document.getElementById('search')
|
|
let listLength = suggestions.length > 10 ? 10 : suggestions.length
|
|
totalSuggestions = listLength
|
|
for(let x = 0; x < listLength; x++){
|
|
let listElem = document.createElement('li')
|
|
listElem.classList.add('Suggestion')
|
|
listElem.innerText = suggestions[x].suggestion
|
|
listElem.addEventListener('click', (e) => {
|
|
searchElem.value = listElem.innerText
|
|
suggestionList.style.display = 'none'
|
|
selectedSuggestion = null
|
|
totalSuggestions = 0
|
|
})
|
|
listElem.addEventListener('mouseover', (e) => {
|
|
selectedSuggestion = null
|
|
clearSelects()
|
|
})
|
|
listElem.id = `suggestions${x}`
|
|
suggestionList.appendChild(listElem)
|
|
suggestionList.style.display = 'block'
|
|
}
|
|
}
|
|
document.addEventListener('DOMContentLoaded', function(e) {
|
|
searchElem = document.getElementById('search')
|
|
if(!searchElem){
|
|
return
|
|
}
|
|
searchElem/addEventListener('keydown', function(e) {
|
|
if(e.key === 'Enter'){
|
|
if(selectedSuggestion != null){
|
|
e.preventDefault()
|
|
}
|
|
|
|
}
|
|
if(e.key === 'ArrowUp' || e.key === 'ArrowDown'){
|
|
e.preventDefault()
|
|
}
|
|
})
|
|
searchElem.addEventListener('keyup', function (e) {
|
|
if(e.key === 'Escape'){
|
|
return
|
|
}
|
|
if(e.key === 'ArrowUp'){
|
|
if(!totalSuggestions) return
|
|
if(typeof selectedSuggestion != 'number'){
|
|
selectedSuggestion = totalSuggestions - 1
|
|
}
|
|
else{
|
|
selectedSuggestion -= 1
|
|
if(selectedSuggestion < 0){
|
|
selectedSuggestion = totalSuggestions - 1
|
|
}
|
|
}
|
|
selectSuggestion(selectedSuggestion)
|
|
return
|
|
}
|
|
if(e.key === 'ArrowDown'){
|
|
if(!totalSuggestions) return
|
|
if(typeof selectedSuggestion != 'number'){
|
|
selectedSuggestion = 0
|
|
}
|
|
else{
|
|
selectedSuggestion += 1
|
|
if(selectedSuggestion > totalSuggestions -1){
|
|
selectedSuggestion = 0
|
|
}
|
|
}
|
|
selectSuggestion(selectedSuggestion)
|
|
return
|
|
}
|
|
if(e.key === 'Enter'){
|
|
if(selectedSuggestion != null){
|
|
enterSuggestion(selectedSuggestion)
|
|
return
|
|
}
|
|
return
|
|
}
|
|
query = searchElem.value
|
|
if (typingTimeout != null) {
|
|
clearTimeout(typingTimeout);
|
|
}
|
|
typingTimeout = setTimeout(function() {
|
|
typingTimeout = null;
|
|
if(!query){
|
|
let suggestionList = document.getElementById('suggestionList')
|
|
suggestionList.replaceChildren()
|
|
suggestionList.style.display = 'none'
|
|
totalSuggestions = 0
|
|
}else{
|
|
getSuggestions(query)
|
|
}
|
|
}, 500);
|
|
})
|
|
|
|
document.body.addEventListener('click', (e) => {
|
|
let suggestionList = document.getElementById('suggestionList')
|
|
suggestionList.style.display = 'none'
|
|
totalSuggestions = 0
|
|
})
|
|
document.addEventListener('keyup', (e) =>{
|
|
if(e.key === 'Escape' ){
|
|
let suggestionList = document.getElementById('suggestionList')
|
|
suggestionList.style.display = 'none'
|
|
totalSuggestions = 0
|
|
}
|
|
})
|
|
}, false)
|
|
function selectSuggestion(id){
|
|
let suggestId = `suggestions${id}`
|
|
clearSelects()
|
|
document.getElementById(suggestId).classList.add('selected')
|
|
}
|
|
function enterSuggestion(id){
|
|
let suggestId = `suggestions${id}`
|
|
clearSelects()
|
|
document.getElementById('search').value = document.getElementById(suggestId).innerText
|
|
selectedSuggestion = null
|
|
suggestionList.style.display = 'none'
|
|
totalSuggestions = 0
|
|
}
|
|
function clearSelects(){
|
|
let suggestionList = document.getElementById('suggestionList')
|
|
let selectedItems = suggestionList.getElementsByClassName('selected')
|
|
if(!selectedItems.length){
|
|
return
|
|
}
|
|
for(item in selectedItems){
|
|
if(typeof selectedItems[item].classList === 'undefined'){
|
|
//this is jank but the stupid function double fires
|
|
return
|
|
}
|
|
selectedItems[item].classList.remove('selected')
|
|
}
|
|
}
|
|
</script>
|