Skip to content

Instantly share code, notes, and snippets.

@hakre
Created May 14, 2019 20:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hakre/10afbfcf1bab4840449e89f10da4ff3a to your computer and use it in GitHub Desktop.
Save hakre/10afbfcf1bab4840449e89f10da4ff3a to your computer and use it in GitHub Desktop.
phpinfo() javascript search
<!-- phpinfo() search -->
<form style="position: sticky; top: 0;">
<input>
</form>
<script defer>//
/*
* phpinfo() search javascript (~ES5/6)
*/
const w = window;
const d = document;
const q = d.querySelector.bind(d);
const query = function* (selector, element) {
yield* (element || d).querySelectorAll(selector);
};
const walk = function* (next, start) {
for (let look = next(start); look !== null; look = next(look))
yield look;
};
const filter = function* (condition, iter) {
for (const item of iter)
if (condition(item)) yield item;
};
const aslong = function* (condition, iter) {
for (const item of iter) {
if (!condition(item)) break;
yield item;
}
};
const on = function(probe, condition, result) {
if (probe !== null && condition(probe) && result)
return result(probe);
return null;
};
const first = function(condition, iter) {
for (item of iter)
if (condition === null || condition(item))
return item;
return null;
};
const has = function (condition, iter) {
for (item of filter(condition, iter))
return true;
return false;
};
const name = e => e.tagName;
const height = e => e.clientHeight;
const visible = e => !e.hidden;
const parent = e => e.parentElement;
const forward = e => e.nextElementSibling;
const backward = e => e.previousElementSibling;
const string = function (e, otherwise) {
return ("string" === typeof e) ? e
: otherwise(e);
};
const isNot = function(func) {
return e => !func(e);
};
const isString = function(str, map) {
str = string(str, map);
return e => map(e) === str;
};
const is = e => !!e;
const isName = e => isString(e, name);
const notName = e => isNot(isName(e));
const reduce = function (aggregate, func, iter) {
for (const item of iter)
aggregate = func(aggregate, item);
return aggregate;
};
const map = function* (func, iter) {
for (const item of iter)
yield func(item);
};
const sum = function(iter) {
return reduce(0, (a, e) => a + e, iter);
};
const look = function (next, start) {
return first(notName(start), walk(next, start));
};
const event = function(e, type, listener, extra) {
e.addEventListener(type, listener, extra);
};
const sections = new Set();
sections.empty = true;
const search_terms = function (terms) {
const regExp = new RegExp(terms.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "i");
const tables = new WeakSet();
tables.has = tables.has.bind(tables);
for (const e of query("table tr td.e, table tr:not(.h) td:not([class])")) {
let row = parent(e);
row.hidden = ! regExp.test(row.innerText);
tables.add(parent(parent(row)));
};
for (const table of query("table")) {
table.hidden = false;
table.hidden = terms.length && (
height(table) < 2
|| (
table.rows[0].className === "h"
&& height(table.tBodies[0]) === sum(map(height, query('tr.h', table)))
)
);
sections.empty && on(look(backward, table), isName('H2'), h2 => sections.add(h2))
}
sections.empty = false;
sections.forEach(h2 => h2.hidden = !has(visible, aslong(isName('TABLE'), walk(forward, h2))));
history.replaceState({}, "search for " + terms, "#" + encodeURIComponent(terms));
};
const input = q("form input");
let c = 0;
const search = function(terms) {
c++;
w.setTimeout(function() {
if (c === 0) {return;}
c = 0;
const untie = ("function" === typeof terms) ? terms() : terms;
input.value = untie;
search_terms(untie);
}, 100);
};
event(input, "input", function() {
search(function() {return this.value;}.bind(this));
}, false);
const hash = function() {
const string = w.location.hash;
search(decodeURIComponent(string).replace(/^#/, ''));
};
event(w, "hashchange", hash, false);
event(d, "DOMContentLoaded", hash, false);
//</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment