Last active
October 26, 2017 02:01
-
-
Save eloquence/d55a8700c79f329abdb0fdb5736c7d98 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<style> | |
.ac-wrap { | |
position: absolute; | |
} | |
.ac-rwrap { | |
background-color: white; | |
box-shadow: 0 2px 4px rgba(0,0,0,0.1); | |
border: 1px solid #e6e6e9; | |
border-bottom-left-radius: 10px; | |
border-bottom-right-radius: 10px; | |
margin-top: 0px; | |
} | |
.ac-row { | |
padding: 7px 10px 5px 10px;; | |
border-bottom: 1px solid #e6e6e9; | |
} | |
.ac-row:hover { | |
background-color: #f2f2f4; | |
cursor: pointer; | |
} | |
.ac-row.selected { | |
background-color: #eee; | |
} | |
.ac-row:last-child { | |
border-bottom: none; | |
} | |
.ac-pr, .ac-sc { | |
vertical-align: baseline; | |
display: block; | |
} | |
.ac-pr { | |
color: #3a3a48; | |
} | |
.ac-sc { | |
font-size: small; | |
padding-top: 5px; | |
} | |
.ac-no-results { | |
padding: 7px 10px 5px 10px; | |
align-items:center; | |
color:red; | |
} | |
.ac-get-more { | |
padding: 7px 10px 5px 10px; | |
display:flex; | |
align-items:center; | |
} | |
.ac-get-more-text { | |
display:inline-block; | |
font-family:sans-serif; | |
color:#999; | |
font-size:small; | |
font-weight:bold; | |
text-transform:uppercase; | |
text-align:center; | |
width:33.33%; | |
} | |
.ac-get-next { | |
text-align:right; | |
} | |
.ac-get-prev { | |
text-align:left; | |
} | |
.ac-get-prev, .ac-get-next { | |
display:inline-block; | |
font-size:xx-large; | |
width:33.33%; | |
} | |
.ac-get-active { | |
color:#4848ca; | |
cursor:pointer; | |
font-size:xx-large; | |
} | |
.search-highlight { | |
color: red; | |
} | |
.search-excerpt { | |
margin:0; | |
padding: 0.5em; | |
margin-bottom:1em; | |
background: #fcfcfc; | |
border-style: dashed; | |
border-width: 1px; | |
border-color: #ccc; | |
border-radius: 10px; | |
display:inline-block; | |
} | |
.hl { | |
background: #eee; | |
} | |
</style> | |
</head> | |
<body> | |
<b>Search:</b> | |
<form autocomplete="off" action="/"> | |
<input size="50" id="search"> | |
</form> | |
<script type="text/javascript"> | |
var module = {}; | |
</script> | |
<script src="https://use.fontawesome.com/638fcd9e3e.js"></script> | |
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script> | |
<script src="https://cdn.rawgit.com/danqing/autocomplete/master/ac.js"></script> | |
<script type="text/javascript"> | |
// Results per query | |
const limit = 7; | |
function triggerFn(row) { | |
if (row.url) | |
window.location = row.url; | |
} | |
function queryFn(query, requestedOffset) { | |
let time = Date.now(); | |
// Keep track of most recently fired query so we can ignore responses | |
// coming in late | |
if (this.latestQuery === undefined || this.latestQuery < time) | |
this.latestQuery = time; | |
this.results = []; | |
query = query.trim(); | |
// Nothing to do - clear out the display & abort | |
if (!query) | |
return this.render(); | |
let q = query.split(' ').map(word => `title:${word}`).join(' AND '); | |
let queryObj = { | |
q, | |
limit, | |
mode: 'everything' | |
}; | |
// Track if this is the first page we're rendering, in which case there's | |
// no "previous" button | |
let isFirstPage; | |
if (requestedOffset) { | |
// Pass along the offset | |
queryObj.offset = requestedOffset; | |
} else { | |
isFirstPage = true; | |
} | |
let getQuery = queryObj => { | |
return new Promise((resolve, reject) => { | |
$.ajax({ | |
url: 'https://openlibrary.org/search.json', | |
dataType: 'json', | |
data: queryObj | |
}) | |
.done(resolve) | |
.fail(reject); | |
}); | |
}; | |
let queries = [getQuery(queryObj)]; | |
// Add a second wildcard query for longer searches. This may produce 0 | |
// results due to stemming conflicts, so we still have to fire off the | |
// other query, as well. | |
if (query.length >= 3) { | |
let queryObj2 = Object.assign({}, queryObj); | |
queryObj2.q += '*' | |
queries.push(getQuery(queryObj2)); | |
} | |
Promise | |
.all(queries) | |
.then(results => { | |
// Eliminate duplicate keys and merge results into a single array | |
let data = mergeResults(results); | |
// Don't update if a more recent query has superseded this one | |
if (time < this.latestQuery) | |
return; | |
this.results = []; | |
if (typeof data === 'object' && data.docs && data.docs.length) { | |
this.results = data.docs.map(item => { | |
return { | |
url: `https://openlibrary.org${item.key}`, | |
title: item.title_suggest, | |
description: item.author_name | |
}; | |
}); | |
this.render(); | |
} | |
else { | |
this.render(); | |
let $wrapper = $(this.rowWrapperEl); | |
// No results, render empty list | |
console.log($wrapper); | |
$('<div class="ac-no-results">No results for this search</div>').appendTo($wrapper); | |
$wrapper.show(); | |
} | |
}); | |
} | |
let ac = new AC($('#search')[0], null, queryFn, null, null, triggerFn); | |
ac.secondaryTextKey = 'description'; | |
ac.delay = 300; | |
// Merge response from two queries into a single array. Overall size of | |
// result will not exceed limit | |
function mergeResults(results) { | |
let data = { docs: []}; | |
let knownKeys = []; | |
for (let result of results) { | |
if (typeof result == 'object' && result.docs && result.docs.length) { | |
for (let doc of result.docs) { | |
if (!knownKeys.includes(doc.key) && data.docs.length < limit) { | |
data.docs.push(doc); | |
knownKeys.push(doc.key); | |
} | |
} | |
} | |
} | |
return data; | |
} | |
function hasURI(data, uri) { | |
for (let dataItem of data.results.bindings) { | |
if (dataItem.item.value === uri) | |
return true; | |
} | |
console.log(uri); | |
return false; | |
} | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment