Files
mdlinks/index.html
2017-07-13 09:05:43 +03:00

352 lines
11 KiB
HTML

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=320" />
<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:hover { text-decoration: underline; }
A: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; }
</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);
scroll_load();
}
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 href=\""+match[3]+"\">"+match[2]+"</a>"+match[4];
}
match=linkPlain.exec(md);
if (match != null) {
return "<li>"+match[1]+"<a href=\""+match[2]+"\">"+match[2]+"</a>"+match[3];
}
return "<li class=nolink>"+md
}
function make_head(c) {
var name=c.substring(1).trim();
var head=c.replace(/ /g,"&nbsp;");
var id=name.replace(/ /g,"");
return '<a name="'+name+'" id="anchor_'+id+'"><div class=head align=center>'+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("anchor_"+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);
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=name.replace(/^#/,"");
sel.appendChild(opt);
}
}
}
function filter(ev) {
var needle=document.getElementById('filter').value;
document.cookie="filter="+needle;
hitList=search_hits(needle);
var c=hitList.length;
var lastHit=hitList[c-1];
print_results(hitList);
var key=ev.keyCode;
if (key==13){
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;
if (narrow_window()) { td.className+=" narrow"; }
td.innerHTML+=make_head(linkList[c]);
cats.push({name:name, td:td, count:0});
cat+=1;
} else {
if (hitList.indexOf(c)==-1) { continue }
td.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 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 keyboard_entry(ev) {
var kC=ev.keyCode;
var k=String.fromCharCode(ev.keyCode);
if ( document.activeElement === document.getElementById("filter")) {
return
}
if (/S/.test(k)) {
document.getElementById("filter").focus();
}
if (/N/.test(k)) {
toggle_blank();
}
}
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() {
document.cookie = "position=" + window.scrollY + "; path=" + window.location.pathname;
}
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 }
document.getElementById("filter").value=needle;
}
function get_cookie(name) {
var nameEQ = name+"=";
var ca = document.cookie.split(';');
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) { return c.substring(nameEQ.length,c.length); }
}
return null
}
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:['&#x1F4D9;','&#x1F4dA;'] // Arrow characters for in/out tab icon
};
</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"></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">&#8635;</a></span>
</body>
</html>