API search now works
This commit is contained in:
parent
976f535aec
commit
68a1e27881
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
246
public/scripts/plugins/jets.js
Normal file
246
public/scripts/plugins/jets.js
Normal file
|
@ -0,0 +1,246 @@
|
|||
/* global define */
|
||||
|
||||
/*! Jets.js - v0.14.1 - 2018-06-22
|
||||
* http://NeXTs.github.com/Jets.js/
|
||||
* Copyright (c) 2015 Denis Lukov; Refactored 2018 Paul Anthony Webb; Licensed MIT */
|
||||
|
||||
(function (root, definition) {
|
||||
if (typeof module !== "undefined") module.exports = definition();
|
||||
else if (typeof define === "function" && typeof define.amd === "object") define(definition);
|
||||
else root["Jets"] = definition();
|
||||
}(this, function () {
|
||||
"use strict";
|
||||
|
||||
function Jets(opts) {
|
||||
if (!(this instanceof Jets)) return new Jets(opts);
|
||||
|
||||
const defaults = {
|
||||
diacriticsMap: {},
|
||||
hideBy: "display: none",
|
||||
searchSelector: "*AND"
|
||||
};
|
||||
|
||||
const self = this;
|
||||
self.options = {};
|
||||
|
||||
[
|
||||
"addImportant",
|
||||
"callSearchManually",
|
||||
"columns",
|
||||
"diacriticsMap",
|
||||
"didSearch",
|
||||
"hideBy",
|
||||
"invert",
|
||||
"manualContentHandling",
|
||||
"searchInSpecificColumn",
|
||||
"searchSelector"
|
||||
].forEach(name => self.options[name] = opts[name] || defaults[name]);
|
||||
|
||||
if (this.options.searchSelector.length > 1) {
|
||||
const searchSelector = self.options["searchSelector"].trim();
|
||||
|
||||
self.options.searchSelector = searchSelector.substr(0, 1);
|
||||
self.options.searchSelectorMode = searchSelector.substr(1).toUpperCase();
|
||||
}
|
||||
|
||||
self.content_tag = document.querySelectorAll(opts.contentTag);
|
||||
if (!self.content_tag) throw new Error("Error! Could not find contentTag element");
|
||||
self.content_param = opts.contentTag;
|
||||
self.search_tag = document.querySelector(opts.searchTag);
|
||||
|
||||
if (
|
||||
!self.search_tag &&
|
||||
!self.options.callSearchManually
|
||||
) throw new Error("Error! Provide one of search methods: searchTag or callSearchManually and call .search(\"phrase\") manually");
|
||||
|
||||
let last_search_query = self.search_tag && self.search_tag.value || "";
|
||||
|
||||
self.search = (search_query, optional_column) => {
|
||||
const new_search_query =
|
||||
self.options.callSearchManually &&
|
||||
typeof search_query !== "undefined"
|
||||
? search_query
|
||||
: self.search_tag
|
||||
? self.search_tag.value
|
||||
: "";
|
||||
|
||||
if (last_search_query === (last_search_query = new_search_query)) return;
|
||||
(0, self._applyCSS(last_search_query, optional_column));
|
||||
self.options.didSearch && self.options.didSearch(last_search_query);
|
||||
};
|
||||
|
||||
self._onSearch = function (event) {
|
||||
if (event.type === "keydown") return setTimeout(self.search, 0);
|
||||
self.search();
|
||||
};
|
||||
|
||||
self.destroy = function () {
|
||||
if (!self.options.callSearchManually) self._processEventListeners("remove");
|
||||
self._destroy();
|
||||
};
|
||||
|
||||
if (!self.options.callSearchManually) self._processEventListeners("add");
|
||||
|
||||
self._addStyleTag();
|
||||
self._setJets();
|
||||
self._applyCSS(last_search_query);
|
||||
}
|
||||
|
||||
Jets.prototype = {
|
||||
constructor: Jets,
|
||||
_processEventListeners: function (action) {
|
||||
[
|
||||
"change",
|
||||
"input",
|
||||
"keydown"
|
||||
].forEach(function (event_type) {
|
||||
this.search_tag[action + "EventListener"](event_type, this._onSearch);
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
_applyCSS: function (search_query, optional_column) {
|
||||
const options = this.options;
|
||||
|
||||
const search_phrase = this.replaceDiacritics(
|
||||
search_query
|
||||
.trim()
|
||||
.toLowerCase()
|
||||
.replace(/\s\s+/g, " ")
|
||||
).replace(/\\/g, "\\\\");
|
||||
|
||||
const words = options.searchSelectorMode
|
||||
? search_phrase.split(" ").filter((item, pos, arr) => arr.indexOf(item) === pos)
|
||||
: [search_phrase];
|
||||
|
||||
const is_strict_selector = options.searchSelectorMode === "AND";
|
||||
const selectors = new Array(words.length);
|
||||
|
||||
for (let i = 0, ii = words.length; i < ii; i++) {
|
||||
selectors[i] =
|
||||
(is_strict_selector ? this.content_param + ">" : "") +
|
||||
(options.invert ? "" : ":not(") +
|
||||
"[data-jets" + (typeof optional_column !== "undefined" ? "-col-" + optional_column : "") + options.searchSelector + `="${words[i]}"]` +
|
||||
(options.invert ? "" : ")");
|
||||
}
|
||||
|
||||
const hide_rules =
|
||||
options.hideBy
|
||||
.split(";")
|
||||
.filter(Boolean)
|
||||
.map(rule => rule + (options.addImportant ? "!important" : ""));
|
||||
|
||||
const css_rule = (is_strict_selector ? "" : this.content_param + ">") + selectors.join(is_strict_selector ? "," : "") + "{" + hide_rules.join(";") + "}";
|
||||
|
||||
this.styleTag.innerHTML = search_phrase.length ? css_rule : "";
|
||||
},
|
||||
|
||||
_addStyleTag: function () {
|
||||
this.styleTag = document.createElement("style");
|
||||
document.head.appendChild(this.styleTag);
|
||||
},
|
||||
|
||||
_getText: function (tag) {
|
||||
return tag && (tag.textContent || tag.innerText) || "";
|
||||
},
|
||||
|
||||
_sanitize: function (text) {
|
||||
return this.replaceDiacritics(text).trim().replace(/\s+/g, " ").toLowerCase();
|
||||
},
|
||||
|
||||
_getContentTags: function (query) {
|
||||
return Array.prototype.slice.call(this.content_tag).reduce((all, elem) => {
|
||||
return all.concat(Array.prototype.slice.call(elem.querySelectorAll(query || ":scope > *")));
|
||||
}, []);
|
||||
},
|
||||
|
||||
_handleSpecificColumns: function (tag, set) {
|
||||
const self = this;
|
||||
if (!self.options.searchInSpecificColumn) return;
|
||||
|
||||
Array.prototype.slice.call(tag.children).map((children, i) => {
|
||||
if (
|
||||
self.options.columns &&
|
||||
self.options.columns.length &&
|
||||
self.options.columns.indexOf(i) === -1
|
||||
) return;
|
||||
|
||||
tag[(set || "remove") + "Attribute"]("data-jets-col-" + i, set && self._sanitize(self._getText(children)));
|
||||
});
|
||||
},
|
||||
|
||||
_setJets: function (query, force) {
|
||||
const self = this;
|
||||
const tags = self._getContentTags(force ? "" : query);
|
||||
let text;
|
||||
|
||||
for (const tag of tags) {
|
||||
if (tag.hasAttribute("data-jets") && !force) continue;
|
||||
|
||||
text = this.options.manualContentHandling
|
||||
? this.options.manualContentHandling(tag)
|
||||
: self.options.columns &&
|
||||
self.options.columns.length
|
||||
? self.options.columns.map(column => self._getText(tag.children[column])).join(" ")
|
||||
: self._getText(tag);
|
||||
|
||||
tag.setAttribute("data-jets", self._sanitize(text));
|
||||
self._handleSpecificColumns(tag, "set");
|
||||
}
|
||||
},
|
||||
|
||||
replaceDiacritics: function (text) {
|
||||
const diacritics = this.options.diacriticsMap;
|
||||
|
||||
for (const letter in diacritics) if (diacritics.hasOwnProperty(letter)) {
|
||||
for (let i = 0, ii = diacritics[letter].length; i < ii; i++) {
|
||||
text = text.replace(new RegExp(diacritics[letter][i], "g"), letter);
|
||||
}
|
||||
}
|
||||
|
||||
return text;
|
||||
},
|
||||
|
||||
update: function (force) {
|
||||
this._setJets(":scope > :not([data-jets])", force);
|
||||
},
|
||||
|
||||
_destroy: function () {
|
||||
this.styleTag.parentNode && document.head.removeChild(this.styleTag);
|
||||
const tags = this._getContentTags();
|
||||
|
||||
for (const tag of tags) {
|
||||
tag.removeAttribute("data-jets");
|
||||
this._handleSpecificColumns(tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// :scope polyfill
|
||||
// https://stackoverflow.com/a/17989803/1221082
|
||||
;(function (doc, proto) {
|
||||
try {
|
||||
doc.querySelector(":scope body");
|
||||
} catch (err) {
|
||||
["querySelector", "querySelectorAll"].forEach(method => {
|
||||
const nativ = proto[method];
|
||||
|
||||
proto[method] = function (selectors) {
|
||||
if (/(^|,)\s*:scope/.test(selectors)) {
|
||||
const id = this.getAttribute("id");
|
||||
this.id = "ID_" + Date.now();
|
||||
selectors = selectors.replace(/((^|,)\s*):scope/g, "$1#" + this.getAttribute("id"));
|
||||
|
||||
const result = doc[method](selectors);
|
||||
this.id = id;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return nativ.call(this, selectors);
|
||||
};
|
||||
});
|
||||
}
|
||||
})(window.document, Element.prototype);
|
||||
|
||||
return Jets;
|
||||
}));
|
|
@ -28,9 +28,9 @@
|
|||
|
||||
.api__toc__search__field {
|
||||
border-bottom: 1px solid rgba($gray, 0.3);
|
||||
font-size: 1rem;
|
||||
font-size: 0.8rem;
|
||||
line-height: 2rem;
|
||||
padding: 0.25rem calc(2rem + 4px) 0.25rem 0.5rem;
|
||||
padding: 0.25rem calc(2rem + 4px) 0.25rem 0.75rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@
|
|||
color: $white;
|
||||
cursor: pointer;
|
||||
font-size: 1rem;
|
||||
line-height: 1.3;
|
||||
line-height: 1.15;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
transition: opacity 0.2s;
|
||||
|
@ -59,39 +59,9 @@
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.api__toc__search__results,
|
||||
.api__toc__items {
|
||||
font-size: 0.8rem;
|
||||
line-height: 1.33;
|
||||
}
|
||||
|
||||
.api__toc__search__results {
|
||||
list-style-type: none;
|
||||
|
||||
&:not(.active) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background-color: rgba($gray, 0.3);
|
||||
border-bottom: 1px solid rgba($gray, 0.3);
|
||||
padding-top: 0.25rem;
|
||||
padding-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
a {
|
||||
display: block;
|
||||
padding: 0.25rem 0.5rem 0.25rem 0.75rem;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba($gray, 0.3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.api__toc__items {
|
||||
list-style-type: none;
|
||||
padding-top: 0.25rem;
|
||||
padding-bottom: 0.25rem;
|
||||
|
@ -127,7 +97,6 @@
|
|||
}
|
||||
|
||||
h3 {
|
||||
// border-bottom: 1px solid rgba($gray, 0.3);
|
||||
font-size: 0.8rem;
|
||||
letter-spacing: 0.1rem;
|
||||
margin-bottom: 0.25rem;
|
||||
|
@ -140,10 +109,6 @@
|
|||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
ol, ul {
|
||||
// padding-left: 1rem;
|
||||
}
|
||||
|
||||
table {
|
||||
border: 1px solid rgba($white, 0.1);
|
||||
border-radius: 0.3rem;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
const dedent = require("dedent");
|
||||
const fetch = require("make-fetch-happen").defaults({ cacheManager: "./cache" });
|
||||
const fs = require("graceful-fs");
|
||||
const html = require("choo-async/html");
|
||||
const raw = require("nanohtml/raw");
|
||||
|
||||
|
@ -16,6 +17,8 @@ const apiFileLink = process.env.NODE_ENV === "development" ?
|
|||
"https://cdn.rawgit.com/lbryio/lbry/5b3103e4/docs/api.json"
|
||||
;
|
||||
|
||||
const apiScripts = "<script>" + fs.readFileSync("./views/partials/api-scripts.js", "utf-8") + "</script>";
|
||||
|
||||
|
||||
|
||||
// E X P O R T
|
||||
|
@ -34,6 +37,8 @@ module.exports = exports = () => async () => parseApiFile().then(response => htm
|
|||
|
||||
<section class="api__content" id="toc-content">${raw(createApiContent(response).join(""))}</section>
|
||||
</div>
|
||||
|
||||
${raw(apiScripts)}
|
||||
`);
|
||||
|
||||
|
||||
|
@ -46,9 +51,9 @@ function createApiContent(apiDetails) {
|
|||
for (const apiDetail of apiDetails) {
|
||||
const apiDetailsReturns = JSON.parse(JSON.stringify(apiDetail.returns));
|
||||
|
||||
/* if (apiDetail.name !== "settings_set") */ apiContent.push(`
|
||||
apiContent.push(`
|
||||
<div class="api__content__body">
|
||||
<h2 id="#${apiDetail.name}">${apiDetail.name}</h2>
|
||||
<h2 id="${apiDetail.name}">${apiDetail.name}</h2>
|
||||
<p>${apiDetail.description}</p>
|
||||
|
||||
<h3>Returns</h3>
|
||||
|
|
37
views/partials/api-scripts.js
Normal file
37
views/partials/api-scripts.js
Normal file
|
@ -0,0 +1,37 @@
|
|||
/* global $, Jets */ "use strict";
|
||||
|
||||
|
||||
|
||||
let jets = new Jets({
|
||||
searchTag: "#input-search",
|
||||
contentTag: "#toc"
|
||||
});
|
||||
|
||||
|
||||
|
||||
$("#input-search")[0].value = ""; // reset on page load
|
||||
|
||||
$("#input-search").on("keyup", () => {
|
||||
if ($("#input-search").val()) $(".api__toc__search__clear").addClass("active");
|
||||
else $(".api__toc__search__clear").removeClass("active");
|
||||
});
|
||||
|
||||
$(".api__toc__search__clear").on("click", () => {
|
||||
$("#input-search")[0].value = "";
|
||||
$(".api__toc__search__clear").removeClass("active");
|
||||
jets.destroy();
|
||||
reinitJets();
|
||||
});
|
||||
|
||||
|
||||
|
||||
// H E L P E R
|
||||
|
||||
function reinitJets() {
|
||||
jets = new Jets({
|
||||
searchTag: "#input-search",
|
||||
contentTag: "#toc"
|
||||
});
|
||||
|
||||
$("#input-search").focus();
|
||||
}
|
|
@ -55,6 +55,7 @@ module.exports = exports = () => async (state) => {
|
|||
html`<link rel="stylesheet" href="/assets/css/style.css"/>`,
|
||||
|
||||
html`<script src="/assets/scripts/vendor/zepto.js"></script>`,
|
||||
pageTitle === "API" ? html`<script src="/assets/scripts/plugins/jets.js"></script>` : "",
|
||||
html`<script>const ws = new WebSocket(location.origin.replace(/^http/, "ws"));</script>`,
|
||||
html`<script src="/assets/scripts/sockets.js"></script>`
|
||||
]}`;
|
||||
|
|
Loading…
Reference in a new issue