504 lines
15 KiB
HTML
504 lines
15 KiB
HTML
<html>
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<STYLE type="text/css">
|
|
BODY { font-size: 14px; }
|
|
TABLE { width: 100%; }
|
|
HR { height:5px; border: 0px;}
|
|
TD { vertical-align: top; width: 10%; }
|
|
LI {
|
|
text-indent:-1.3em;
|
|
padding-left:1.4em;
|
|
list-style-type:none;
|
|
overflow: hidden;
|
|
margin-bottom: 0.2em;
|
|
}
|
|
LI:before {
|
|
content:"-";
|
|
padding-right: 0.5em;
|
|
}
|
|
TD.narrow LI {
|
|
margin-bottom: 1em;
|
|
}
|
|
LI.nolink:before {
|
|
content:" ";
|
|
padding-right: 1.0em;
|
|
}
|
|
A:link { text-decoration:none; color: #000000; }
|
|
A:visited { text-decoration:none; color: #000000; }
|
|
A.link:hover { text-decoration: underline; }
|
|
A.link:focus { text-decoration: underline; }
|
|
#filter { width: 100%; }
|
|
#search { width: 100%; display: table; }
|
|
.search_span { display: table-cell; text-align: center; vertical-align: middle;
|
|
padding-left: 0.1em; padding-right: 0.1em; }
|
|
.head { font-size: 16px; text-align:left; padding-top: 0.2em; margin-bottom: -0.5em; }
|
|
#menu { font-size: 12px; width: 3em; }
|
|
.tickbox { }
|
|
#reload_span { float: right; }
|
|
#open_blank_span { cursor: pointer; font-size:17px; width: 2em; height: 16px;}
|
|
#open_blank_box { position:relative; left: 0.0em; border: 0px solid black; padding-left: 0em; }
|
|
#open_blank_arrow { position: relative; left: 0em; top: 0em;}
|
|
.hidden { display:none; }
|
|
.fold_plus::after {
|
|
content:" (+)";
|
|
vertical-align: super;
|
|
font-size: 50%;
|
|
}
|
|
</STYLE>
|
|
<script language="javascript">
|
|
function init() {
|
|
var head = document.head;
|
|
if (config.style!=null) {
|
|
var link = document.createElement('link');
|
|
link.type = 'text/css';
|
|
link.rel = 'stylesheet';
|
|
link.href = config.style;
|
|
head.appendChild(link);
|
|
}
|
|
if (config.favicon!=null) {
|
|
var link = document.createElement('link');
|
|
link.type = 'image/x-icon';
|
|
link.rel = 'icon';
|
|
link.href = config.favicon;
|
|
head.appendChild(link);
|
|
}
|
|
var title = document.createElement('title');
|
|
title.innerHTML=config.title;
|
|
head.appendChild(title);
|
|
if (!config.search) {
|
|
document.getElementById('search').style.display='none';
|
|
}
|
|
if (config.columns==1 || narrow_window()) {
|
|
make_menu();
|
|
}
|
|
document.getElementById("open_blank_arrow").innerHTML=config.arrows[0];
|
|
document.getElementById("filter").focus();
|
|
filter_load();
|
|
hitList=search_hits(document.getElementById("filter").value);
|
|
print_results(hitList);
|
|
fold_initial();
|
|
scroll_load();
|
|
parse_request();
|
|
}
|
|
function narrow_window() {
|
|
return window.innerWidth < config.narrow;
|
|
}
|
|
String.prototype.capitalizeFirstLetter = function() {
|
|
return this.charAt(0).toUpperCase() + this.slice(1);
|
|
}
|
|
|
|
function make_link(md) {
|
|
var match=linkReg.exec(md);
|
|
if (match != null) {
|
|
return "<li>"+match[1]+"<a class=\"link\" href=\""+match[3]+"\">"+match[2]+"</a>"+match[4];
|
|
}
|
|
match=linkPlain.exec(md);
|
|
if (match != null) {
|
|
return "<li>"+match[1]+"<a class=\"link\" href=\""+match[2]+"\">"+match[2]+"</a>"+match[3];
|
|
}
|
|
return "<li class=\"nolink\">"+md
|
|
}
|
|
|
|
function make_head(c,index="") {
|
|
var name=c.substring(1).trim();
|
|
var head=c.replace(/ /g," ");
|
|
var id=name.replace(/ /g,"")+"_"+index;
|
|
return '<a name="'+name+'" id="anchor_'+id+'" class="nolink" onclick="fold_toggle(\''+id+'\')">'+
|
|
'<div class=head align=center id="head_'+id+'">'+head+'</div></a>'+
|
|
'<hr WIDTH="100%" SIZE=3 NOSHADE>';
|
|
}
|
|
function make_menu() {
|
|
var doc=document.getElementById("menu_span");
|
|
doc.innerHTML="";
|
|
var sel=document.createElement("select");
|
|
sel.onchange=function(){
|
|
if (this.value=="") { return }
|
|
document.getElementById(this.value).scrollIntoView();
|
|
document.getElementById("menu").value="";
|
|
};
|
|
sel.id="menu";
|
|
doc.appendChild(sel);
|
|
var opt=document.createElement("option");
|
|
opt.value="";
|
|
opt.innerHTML="#";
|
|
sel.appendChild(opt);
|
|
var anchor_index = 0;
|
|
for (c=0; c<linkList.length; c++) {
|
|
if ( linkList[c].substring(0,2) == "# " ) {
|
|
var opt=document.createElement("option");
|
|
var name=linkList[c].substring(1).trim().replace(/ /g,"");
|
|
opt.innerHTML=linkList[c].trim();
|
|
opt.value="anchor_" + name.replace(/^#/,"") + "_" + anchor_index;
|
|
sel.appendChild(opt);
|
|
anchor_index++;
|
|
}
|
|
}
|
|
}
|
|
|
|
function filter(ev) {
|
|
var needle=document.getElementById('filter').value;
|
|
set_cookie("filter", needle);
|
|
hitList=search_hits(needle);
|
|
var c=hitList.length;
|
|
var lastHit=hitList[c-1];
|
|
print_results(hitList);
|
|
if (ev == null) { return }
|
|
var key=ev.keyCode;
|
|
if (key==13){
|
|
/* If search starts with / "cd" to that folder. (also /.. works)*/
|
|
if (needle.startsWith("/")) {
|
|
window.location.href = needle.substring(1);
|
|
}
|
|
if (c==0) { document.getElementById('filter').focus(); }
|
|
if (c==1) { open_link(lastHit); }
|
|
if (c>1) {
|
|
document.getElementById('filter').focus();
|
|
}
|
|
}
|
|
}
|
|
function no_filter(){}
|
|
|
|
function search_hits(needle) {
|
|
needle=needle.trim().toLowerCase();
|
|
if (needle=="") {
|
|
return Array.apply(null, {length: linkList.length}).map(Number.call, Number);
|
|
}
|
|
hitList=[];
|
|
var headName="";
|
|
for (l=0; l<linkList.length; l++) {
|
|
if ( linkList[l].substring(0,2) == "# " ) {
|
|
headName=linkList[l].substring(1).trim().replace(/ /g,"").toLowerCase();
|
|
}
|
|
if (needle.substring(0,1)=="#") {
|
|
/* search for header */
|
|
if (headName.indexOf(needle.substring(1).trim())>-1) {
|
|
/* current header matches */
|
|
hitList.push(l);
|
|
continue
|
|
}
|
|
}
|
|
var match=linkReg.exec(linkList[l].toLowerCase());
|
|
if (match != null ) {
|
|
/* matches to markdown link */
|
|
if ( match[2].indexOf(needle)>-1 ) { hitList.push(l); }
|
|
continue
|
|
}
|
|
match=linkPlain.exec(linkList[l].toLowerCase());
|
|
if (match != null ) {
|
|
/* matches to plain link */
|
|
if ( match[2].indexOf(needle)>-1 ) { hitList.push(l); }
|
|
continue
|
|
}
|
|
if (match===null) {
|
|
/* not a link, match anyway */
|
|
if (linkList[l].toLowerCase().indexOf(needle)>-1) {
|
|
hitList.push(l);
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
return hitList
|
|
}
|
|
|
|
function open_link(c) {
|
|
var match=linkReg.exec(linkList[c]);
|
|
if (match != null ) { location.href=match[3]; return }
|
|
match=linkPlain.exec(linkList[c]);
|
|
if (match != null ) { location.href=match[2]; return }
|
|
return
|
|
}
|
|
var cats=[];
|
|
function print_results(hitList) {
|
|
var str="";
|
|
var cat=0;
|
|
cats=[];
|
|
for (c=0; c<linkList.length; c++) {
|
|
if ( linkList[c].substring(0,2) == "# " ) {
|
|
var name=linkList[c].substring(1).trim().replace(/ /g,"");
|
|
var td=document.createElement("td");
|
|
td.id="td_"+name+"_"+cat;
|
|
var td_content = document.createElement("div");
|
|
td_content.id="content_"+name+"_"+cat;
|
|
if (narrow_window()) { td.className+=" narrow"; }
|
|
td.innerHTML+=make_head(linkList[c],cat);
|
|
td.appendChild(td_content);
|
|
cats.push({name:name, td:td, count:0});
|
|
cat+=1;
|
|
} else {
|
|
if (hitList.indexOf(c)==-1) { continue }
|
|
td_content.innerHTML+=make_link(linkList[c]);
|
|
cats[cat-1].count++;
|
|
}
|
|
}
|
|
var doc=document.getElementById("main");
|
|
doc.innerHTML="";
|
|
var tbl=document.createElement("table");
|
|
var tbody=document.createElement("tbody");
|
|
var tr=document.createElement("tr");
|
|
var print_cat=0;
|
|
for (cat=0; cat<cats.length; cat++) {
|
|
if (cats[cat].count>0) {
|
|
if ((print_cat%config.columns==0 || narrow_window())) {
|
|
var tr=document.createElement("tr");
|
|
tbody.appendChild(tr);
|
|
}
|
|
tr.appendChild(cats[cat].td);
|
|
print_cat++;
|
|
}
|
|
}
|
|
tbody.appendChild(tr);
|
|
tbl.appendChild(tbody);
|
|
doc.appendChild(tbl);
|
|
}
|
|
function reload_source() {
|
|
location.href=config.source
|
|
}
|
|
function get_URL(s) {
|
|
if (window.XMLHttpRequest) { xmlhttp=new XMLHttpRequest(); }
|
|
else { xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); }
|
|
xmlhttp.onreadystatechange=function()
|
|
{ if (xmlhttp.readyState==4 && xmlhttp.status==200)
|
|
{ parse_links(xmlhttp.responseText);
|
|
}}
|
|
xmlhttp.open("GET", s, true);
|
|
xmlhttp.send();
|
|
}
|
|
|
|
function read_links() {
|
|
get_URL(config.source);
|
|
}
|
|
|
|
function parse_links(s) {
|
|
var linkRows=s.split("\n");
|
|
var links=[];
|
|
for (r=0; r<linkRows.length; r++) {
|
|
if (linkRows[r].length>1) {
|
|
links.push(linkRows[r]);
|
|
}
|
|
}
|
|
linkList=links.slice(0);
|
|
init();
|
|
}
|
|
|
|
function parse_request() {
|
|
var request = window.location.search.substring(1);
|
|
var vars = request.split('&');
|
|
for (var i = 0; i < vars.length; i++) {
|
|
var pair = vars[i].split('=');
|
|
if (decodeURIComponent(pair[0]) == "blank") {
|
|
toggle_blank();
|
|
}
|
|
if (decodeURIComponent(pair[0]) == "filter") {
|
|
var value = decodeURIComponent(pair[1]);
|
|
document.getElementById("filter").value = value;
|
|
filter(null);
|
|
}
|
|
}
|
|
}
|
|
|
|
function keyboard_entry(ev) {
|
|
var kC = ev.keyCode;
|
|
var k = String.fromCharCode(ev.keyCode);
|
|
var ctrlDown = ev.ctrlKey || ev.metaKey;
|
|
if (ctrlDown && /C/.test(k)) {
|
|
clear();
|
|
}
|
|
if ( document.activeElement === document.getElementById("filter")) {
|
|
return
|
|
}
|
|
if (/S/.test(k)) {
|
|
document.getElementById("filter").focus();
|
|
}
|
|
if (/N/.test(k)) {
|
|
toggle_blank();
|
|
}
|
|
if (/C/.test(k)) {
|
|
clear();
|
|
}
|
|
}
|
|
|
|
function toggle_blank() {
|
|
var span=document.getElementById('open_blank_span');
|
|
var arrow=document.getElementById('open_blank_arrow');
|
|
if (span.attributes['data']) {
|
|
if ( span.attributes['data'] == "true" ) {
|
|
span.attributes['data'] = "false";
|
|
} else {
|
|
span.attributes['data'] = "true";
|
|
}
|
|
} else {
|
|
span.attributes['data'] = "true";
|
|
}
|
|
var blank=span.attributes['data']=="true";
|
|
var anchors = document.getElementsByTagName('a');
|
|
if (blank) {
|
|
for (var i=0; i<anchors.length; i++){ anchors[i].setAttribute('target', '_blank'); }
|
|
var arrowChar=config.arrows[1];
|
|
} else {
|
|
for (var i=0; i<anchors.length; i++){ anchors[i].removeAttribute('target'); }
|
|
var arrowChar=config.arrows[0];
|
|
}
|
|
arrow.innerHTML=arrowChar;
|
|
}
|
|
function scroll_save() {
|
|
set_cookie("position", window.scrollY);
|
|
}
|
|
function scroll_load() {
|
|
var position=parseInt(get_cookie("position"));
|
|
window.scrollTo(0,position);
|
|
}
|
|
function filter_load() {
|
|
var needle=get_cookie("filter");
|
|
if (needle===null) { return; }
|
|
if (needle.startsWith("/")) { needle=""; }
|
|
document.getElementById("filter").value=needle;
|
|
}
|
|
function get_cookie(name) {
|
|
var nameEQ = name+"=";
|
|
var ca = document.cookie.split(";");
|
|
var cookies = Array();
|
|
for(var i=0;i < ca.length;i++) {
|
|
var c = ca[i];
|
|
while (c.charAt(0)==" ") c = c.substring(1,c.length);
|
|
if (c.indexOf(nameEQ) == 0) { cookies.push(c.substring(nameEQ.length,c.length)); }
|
|
}
|
|
return filter_cookies(cookies,name)
|
|
}
|
|
function filter_cookies(cookies,name) {
|
|
// return only cookies that have the pathname
|
|
for(var i=0;i < cookies.length;i++) {
|
|
var c = cookies[i];
|
|
var split = c.split("&");
|
|
if (split.length == 2) {
|
|
if (split[1] == window.location.pathname) {
|
|
return split[0];
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
function fold_toggle(name,save_state = true) {
|
|
if (!narrow_window()) { return }
|
|
if (!config.foldCategories) { return }
|
|
var title = document.getElementById("head_"+name);
|
|
var el = document.getElementById("content_"+name);
|
|
el.hidden = ! el.hidden;
|
|
title.classList.toggle("fold_plus");
|
|
if (save_state) {
|
|
set_cookie("fold",fold_get_state());
|
|
}
|
|
}
|
|
function fold_set(name,value) {
|
|
if (!narrow_window()) { return }
|
|
if (!config.foldCategories) { return }
|
|
var title = document.getElementById("head_"+name);
|
|
var el = document.getElementById("content_"+name);
|
|
el.hidden = value;
|
|
if (value) {
|
|
title.classList.add("fold_plus");
|
|
} else {
|
|
title.classList.remove("fold_plus");
|
|
}
|
|
}
|
|
function fold_initial() {
|
|
if (!narrow_window()) { return }
|
|
if (!config.foldCategories) { return }
|
|
var state = get_cookie("fold");
|
|
if (state !== null) {
|
|
fold_set_state(state);
|
|
return;
|
|
}
|
|
var slides = document.getElementsByClassName("head");
|
|
for(var i = 0; i < slides.length; i++) {
|
|
var el = slides.item(i);
|
|
var rect = el.getBoundingClientRect();
|
|
if (window.innerHeight*1.5 < rect.top) {
|
|
var name = el.id.replace("head_","");
|
|
fold_toggle(name);
|
|
}
|
|
}
|
|
}
|
|
function fold_get_state() {
|
|
var slides = document.getElementsByClassName("head");
|
|
var state = "";
|
|
for(var i = 0; i < slides.length; i++) {
|
|
var title = slides.item(i);
|
|
var name = title.id.replace("head_","");
|
|
var el = document.getElementById("content_"+name);
|
|
if (el.hidden) {
|
|
state += '-';
|
|
} else {
|
|
state += '+';
|
|
}
|
|
}
|
|
return state;
|
|
}
|
|
function fold_set_state(state) {
|
|
var slides = document.getElementsByClassName("head");
|
|
for(var i = 0; i < slides.length; i++) {
|
|
var title = slides.item(i);
|
|
var name = title.id.replace("head_","");
|
|
if (state[i] == '-') {
|
|
fold_set(name, true);
|
|
}
|
|
if (state[i] == '+') {
|
|
fold_set(name, false);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
function set_cookie(name,value) {
|
|
// Save cookies for 30 minutes
|
|
document.cookie = name + "=" + value.toString() + "&" + window.location.pathname +
|
|
";path=" + window.location.pathname + ";max-age="+ (60 * 30).toString() + ";";
|
|
}
|
|
|
|
function clear() {
|
|
document.getElementById("filter").value = '';
|
|
filter(true);
|
|
}
|
|
function resetTimer() {
|
|
clearTimeout(idleTimer);
|
|
idleTimer = setTimeout(clear, 20 * 60 * 1000); // 20 minutes
|
|
}
|
|
var idleTimer;
|
|
|
|
window.onload = resetTimer;
|
|
document.onmousemove = resetTimer;
|
|
document.onmouseclick = resetTimer;
|
|
document.onkeypress = resetTimer;
|
|
document.onkeyup = keyboard_entry;
|
|
document.onscroll = scroll_save;
|
|
var linkReg=/([^\[]*)\[([^\]]+)\]\(([^\)]+)\)(.*)/;
|
|
var linkPlain=/(.*)(http[^\s]+)(.*)/;
|
|
var linkList=[];
|
|
var hitList=[];
|
|
var config = {
|
|
title:'MDLinks', // title of site
|
|
source:'links.txt', // file for links
|
|
search:true, // include search bar
|
|
columns:4, // number of columns for link table
|
|
style:null, // file to load css from
|
|
favicon:null, // link to favicon file
|
|
narrow:600, // pixel width that is narrow screen = single column table
|
|
arrows:['📙','📚'], // Arrow characters for in/out tab icon
|
|
foldCategories:true // fold categories in single column mode
|
|
};
|
|
|
|
</script>
|
|
<script language="javascript" src="config.js"></script>
|
|
</head>
|
|
<body onload="read_links()">
|
|
<div id="search">
|
|
<span class="search_span"><input type="text" oninput="filter(event)" onkeypress="filter(event)" onblur="no_filter()" id="filter" title="[s] Filter links by name, filter headers by #name. Clear with ctrl-c"></span>
|
|
<span class="search_span" id="menu_span"></span>
|
|
<span class="search_span tickbox" id=open_blank_span onclick="toggle_blank()" title="[n] Toggle open links in new/this window"><span id=open_blank_box></span><span id=open_blank_arrow></span></span>
|
|
</div>
|
|
<div id="main"></div>
|
|
<span class="search_span" id="reload_span"><a href="#" onclick="reload_source()" title="Reload links source">↻</a></span>
|
|
</body>
|
|
</html>
|