Skip to content

Instantly share code, notes, and snippets.

@eloquence
Last active October 26, 2017 02:01
Show Gist options
  • Save eloquence/d55a8700c79f329abdb0fdb5736c7d98 to your computer and use it in GitHub Desktop.
Save eloquence/d55a8700c79f329abdb0fdb5736c7d98 to your computer and use it in GitHub Desktop.
<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