liveui
This commit is contained in:
parent
6797e68ddd
commit
5c66f4684a
@ -4,8 +4,7 @@
|
|||||||
|
|
||||||
|
|
||||||
// insert a backlink for a post given its short hash
|
// insert a backlink for a post given its short hash
|
||||||
function nntpchan_backlink(shorthash)
|
function nntpchan_backlink(shorthash) {
|
||||||
{
|
|
||||||
var elem = document.getElementById("postform_message");
|
var elem = document.getElementById("postform_message");
|
||||||
if ( elem )
|
if ( elem )
|
||||||
{
|
{
|
||||||
@ -13,18 +12,6 @@ function nntpchan_backlink(shorthash)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var banner_count = 3;
|
|
||||||
|
|
||||||
// inject a banner into an element
|
|
||||||
function nntpchan_inject_banners(elem, prefix) {
|
|
||||||
var n = Math.floor(Math.random() * banner_count);
|
|
||||||
var banner = prefix + "static/banner_"+n+".jpg";
|
|
||||||
var e = document.createElement("img");
|
|
||||||
e.src = banner;
|
|
||||||
e.id = "nntpchan_banner";
|
|
||||||
elem.appendChild(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
function get_storage() {
|
function get_storage() {
|
||||||
var st = null;
|
var st = null;
|
||||||
if (window.localStorage) {
|
if (window.localStorage) {
|
||||||
@ -47,10 +34,182 @@ function enable_theme(prefix, name) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function main() {
|
|
||||||
// do other initialization here
|
// call an api method
|
||||||
|
// handler(json_object) on success
|
||||||
|
// handler(null) on fail
|
||||||
|
function nntpchan_apicall(url, handler, err_handler) {
|
||||||
|
var ajax = new XMLHttpRequest();
|
||||||
|
ajax.onreadystatechange = function() {
|
||||||
|
if (ajax.readyState == XMLHttpRequest.DONE ) {
|
||||||
|
var status = ajax.status;
|
||||||
|
var j = null;
|
||||||
|
if (status == 200) {
|
||||||
|
// found
|
||||||
|
try {
|
||||||
|
j = JSON.parse(ajax.responseText);
|
||||||
|
} catch (e) {} // ignore parse error
|
||||||
|
} else if (status == 410) {
|
||||||
|
if (err_handler) {err_handler("cannot fetch post: api disabled");}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
handler(j);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ajax.open("GET", url);
|
||||||
|
ajax.send();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// build post from json
|
||||||
|
// inject into parent
|
||||||
|
// if j is null then inject "not found" post
|
||||||
|
function nntpchan_buildpost(parent, j) {
|
||||||
|
var post = document.createElement("div");
|
||||||
|
if (j) {
|
||||||
|
// huehuehue
|
||||||
|
post.innerHTML = j.PostMarkup;
|
||||||
|
} else {
|
||||||
|
post.setAttribute("class", "notfound post");
|
||||||
|
post.appendChild(document.createTextNode("post not found"));
|
||||||
|
}
|
||||||
|
parent.appendChild(post);
|
||||||
|
}
|
||||||
|
|
||||||
|
// inject post hover behavior
|
||||||
|
function inject_hover(prefix, el, parent) {
|
||||||
|
if (!prefix) { throw "prefix is not defined"; }
|
||||||
|
console.log(el, parent);
|
||||||
|
var timeout;
|
||||||
|
var idx = -2;
|
||||||
|
|
||||||
|
var linkhash = el.backlinkhash;
|
||||||
|
|
||||||
|
var elem = document.createElement("span");
|
||||||
|
elem.setAttribute("class", "backlink_rewritten");
|
||||||
|
elem.appendChild(document.createTextNode(">>"+linkhash.substr(0,10)));
|
||||||
|
|
||||||
|
parent.appendChild(elem);
|
||||||
|
parent.removeChild(el);
|
||||||
|
|
||||||
|
elem.onclick = function(ev) {
|
||||||
|
if(elem.backlink) {
|
||||||
|
nntpchan_apicall(prefix+"api/find?hash="+linkhash, function(j) {
|
||||||
|
var wrapper = document.createElement("div");
|
||||||
|
wrapper.setAttribute("class", "hover "+linkhash);
|
||||||
|
if (j == null) {
|
||||||
|
// not found?
|
||||||
|
wrapper.appendChild(document.createTextNode("not found"));
|
||||||
|
} else {
|
||||||
|
// wrap backlink
|
||||||
|
nntpchan_buildpost(wrapper, j);
|
||||||
|
}
|
||||||
|
elem.appendChild(wrapper);
|
||||||
|
elem.backlink = false;
|
||||||
|
}, function(msg) {
|
||||||
|
var wrapper = document.createElement("div");
|
||||||
|
wrapper.setAttribute("class", "hover "+linkhash);
|
||||||
|
wrapper.appendChild(document.createTextNode(msg));
|
||||||
|
elem.appendChild(wrapper);
|
||||||
|
elem.backlink = false;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
var elems = document.getElementsByClassName(linkhash);
|
||||||
|
if (!elems) throw "bad state, no backlinks open?";
|
||||||
|
for (var idx = 0 ; idx < elems.length; idx ++ ) {
|
||||||
|
elems[idx].parentNode.removeChild(elems[idx]);
|
||||||
|
}
|
||||||
|
elem.backlink = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
elem.backlink = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function livechan_got_post(widget, j) {
|
||||||
|
// do scroll
|
||||||
|
while (widget.children.length > 20) {
|
||||||
|
// remove top element
|
||||||
|
widget.children.removeChild(widget.children[0]);
|
||||||
|
}
|
||||||
|
nntpchan_buildpost(widget, j);
|
||||||
|
// scroll to bottom
|
||||||
|
widget.scrollTop = widget.scrollHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
// inject post form into an element
|
||||||
|
function inject_postform(prefix, parent) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// inject livechan widget into parent
|
||||||
|
function inject_livechan_widget(prefix, parent) {
|
||||||
|
if ( "WebSocket" in window ) {
|
||||||
|
var url = "ws://"+document.location.host+prefix+"live";
|
||||||
|
if ( document.location.protocol == "https:" ) {
|
||||||
|
url = "wss://"+document.location.host+prefix+"live";
|
||||||
|
}
|
||||||
|
var socket = new WebSocket(url);
|
||||||
|
var progress = function(str) {
|
||||||
|
parent.innerHTML = "<pre>livechan: "+str+"</pre>";
|
||||||
|
};
|
||||||
|
progress("initialize");
|
||||||
|
socket.onopen = function () {
|
||||||
|
progress("connected");
|
||||||
|
}
|
||||||
|
socket.onmessage = function(ev) {
|
||||||
|
var j = null;
|
||||||
|
try {
|
||||||
|
j = JSON.parse(ev.data);
|
||||||
|
} catch(e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
if (j) {
|
||||||
|
console.log(j);
|
||||||
|
livechan_got_post(parent, j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
socket.onclose = function(ev) {
|
||||||
|
progress("connection closed");
|
||||||
|
setTimeout(function(){ parent.innerHTML = ""; }, 5000);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
parent.innerHTML = "<pre>livechan mode requires websocket support</pre>";
|
||||||
|
setTimeout(function() {
|
||||||
|
parent.innerHTML = "";
|
||||||
|
}, 5000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function ukko_livechan(prefix) {
|
||||||
|
var ukko = document.getElementById("ukko_threads");
|
||||||
|
if (ukko) {
|
||||||
|
// remove children
|
||||||
|
ukko.innerHTML = "";
|
||||||
|
inject_livechan_widget(prefix, ukko);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var banner_count = 3;
|
||||||
|
|
||||||
|
// inject a banner into an element
|
||||||
|
function nntpchan_inject_banners(elem, prefix) {
|
||||||
|
var n = Math.floor(Math.random() * banner_count);
|
||||||
|
var banner = prefix + "static/banner_"+n+".jpg";
|
||||||
|
var e = document.createElement("img");
|
||||||
|
e.src = banner;
|
||||||
|
e.id = "nntpchan_banner";
|
||||||
|
elem.appendChild(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
function init(prefix) {
|
||||||
|
// inject posthover ...
|
||||||
|
var elems = document.getElementsByClassName("backlink");
|
||||||
|
// ... for backlinks
|
||||||
|
for ( var idx = 0 ; idx < elems.length ; idx ++ ) {
|
||||||
|
// uncomment to do reply hover
|
||||||
|
//inject_hover(prefix, elems[idx], elems[idx].parentNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// apply themes
|
// apply themes
|
||||||
var st = get_storage();
|
var st = get_storage();
|
||||||
enable_theme(st.nntpchan_prefix, st.nntpchan_theme);
|
enable_theme(st.nntpchan_prefix, st.nntpchan_theme);
|
||||||
|
@ -394,7 +394,11 @@ input, textarea {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.backlink, .backlink:hover, .backlink:visited, .backlink:visited:hover {
|
.backlink_rewritten {
|
||||||
|
z-index: 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.backlink, .backlink:hover, .backlink:visited, .backlink:visited:hover, .backlink_rewritten {
|
||||||
margin-left: none;
|
margin-left: none;
|
||||||
color: #D00
|
color: #D00
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
<script type="text/javascript" src="{{board.Prefix}}static/nntpchan.js"></script>
|
<script type="text/javascript" src="{{board.Prefix}}static/nntpchan.js"></script>
|
||||||
<title>{{board.Board}}</title>
|
<title>{{board.Board}}</title>
|
||||||
</head>
|
</head>
|
||||||
<body onload="main()">
|
<body>
|
||||||
<!-- begin navbar -->
|
<!-- begin navbar -->
|
||||||
{{{board.Navbar}}}
|
{{{board.Navbar}}}
|
||||||
<!-- end navbar -->
|
<!-- end navbar -->
|
||||||
@ -55,10 +55,10 @@
|
|||||||
<a href="{{board.Prefix}}catalog-{{board.Name}}.html"> {{#i18n.Translations}}{{catalog_label}}{{/i18n.Translations}} </a>
|
<a href="{{board.Prefix}}catalog-{{board.Name}}.html"> {{#i18n.Translations}}{{catalog_label}}{{/i18n.Translations}} </a>
|
||||||
</div>
|
</div>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
var prefix = "{{board.Prefix}}";
|
||||||
var e = document.getElementById("nntpchan_banner");
|
var e = document.getElementById("nntpchan_banner");
|
||||||
nntpchan_inject_banners(e, "{{board.Prefix}}");
|
nntpchan_inject_banners(e, prefix);
|
||||||
|
init(prefix);
|
||||||
</script>
|
</script>
|
||||||
<hr/>
|
<hr/>
|
||||||
<footer>
|
<footer>
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
<script src="{{thread.Prefix}}static/nntpchan.js" type="text/javascript"></script>
|
<script src="{{thread.Prefix}}static/nntpchan.js" type="text/javascript"></script>
|
||||||
<title> {{thread.OP.Subject}} </title>
|
<title> {{thread.OP.Subject}} </title>
|
||||||
</head>
|
</head>
|
||||||
<body onload="main()">
|
<body>
|
||||||
<!-- begin navbar -->
|
<!-- begin navbar -->
|
||||||
{{{thread.Navbar}}}
|
{{{thread.Navbar}}}
|
||||||
<!-- end navbar -->
|
<!-- end navbar -->
|
||||||
@ -45,9 +45,10 @@
|
|||||||
<hr/>
|
<hr/>
|
||||||
<div class="navLinks">[<a href="{{thread.BoardURL}}" accesskey="a">{{#i18n.Translations}}{{return}}{{/i18n.Translations}}</a>] [<a href="{{thread.Prefix}}catalog-{{thread.Board}}.html" accesskey="r">{{#i18n.Translations}}{{catalog_label}}{{/i18n.Translations}}</a>] [<a href="#thread_{{thread.OP.PostHash}}">{{#i18n.Translations}}{{to_top_label}}{{/i18n.Translations}}</a>] [<a href="#navlinks" accesskey="r" onclick="location.reload();">{{#i18n.Translations}}{{update}}{{/i18n.Translations}}</a>]</div>
|
<div class="navLinks">[<a href="{{thread.BoardURL}}" accesskey="a">{{#i18n.Translations}}{{return}}{{/i18n.Translations}}</a>] [<a href="{{thread.Prefix}}catalog-{{thread.Board}}.html" accesskey="r">{{#i18n.Translations}}{{catalog_label}}{{/i18n.Translations}}</a>] [<a href="#thread_{{thread.OP.PostHash}}">{{#i18n.Translations}}{{to_top_label}}{{/i18n.Translations}}</a>] [<a href="#navlinks" accesskey="r" onclick="location.reload();">{{#i18n.Translations}}{{update}}{{/i18n.Translations}}</a>]</div>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
var prefix = "{{thread.Prefix}}";
|
||||||
var e = document.getElementById("nntpchan_banner");
|
var e = document.getElementById("nntpchan_banner");
|
||||||
nntpchan_inject_banners(e, "{{thread.Prefix}}");
|
nntpchan_inject_banners(e, prefix);
|
||||||
|
init(prefix);
|
||||||
</script>
|
</script>
|
||||||
<hr/>
|
<hr/>
|
||||||
<footer>
|
<footer>
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
<link id="current_theme" rel="stylesheet" href="{{prefix}}static/user.css" />
|
<link id="current_theme" rel="stylesheet" href="{{prefix}}static/user.css" />
|
||||||
<script type="text/javascript" src="{{prefix}}static/nntpchan.js"></script>
|
<script type="text/javascript" src="{{prefix}}static/nntpchan.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body onload="main()">
|
<body>
|
||||||
<center>
|
<center>
|
||||||
<div id="nntpchan_banner">
|
<div id="nntpchan_banner">
|
||||||
</div>
|
</div>
|
||||||
@ -21,10 +21,11 @@
|
|||||||
{{{navbar}}}
|
{{{navbar}}}
|
||||||
<!-- end navbar -->
|
<!-- end navbar -->
|
||||||
<div class="board_header"> {{#i18n.Translations}}{{overboard_title}}{{/i18n.Translations}} </div>
|
<div class="board_header"> {{#i18n.Translations}}{{overboard_title}}{{/i18n.Translations}} </div>
|
||||||
<div id="ukko_threads">
|
<div id="ukko_threads">
|
||||||
|
<pre><a href="#" onclick="ukko_livechan('{{prefix}}')">livechan</a></pre>
|
||||||
{{#threads}}
|
{{#threads}}
|
||||||
<div class="thread" id="thread_{{OP.PostHash}}">
|
<div class="thread" id="thread_{{OP.PostHash}}">
|
||||||
<div class="ukko_thread_header">
|
<div class="ukko_thread_header">
|
||||||
<p>{{#i18n.Translations}}{{posted_on_label}}{{/i18n.Translations}} <a href="{{{BoardURL}}}"><span class="ukko_boardname">{{OP.Board}}</span></a></p>
|
<p>{{#i18n.Translations}}{{posted_on_label}}{{/i18n.Translations}} <a href="{{{BoardURL}}}"><span class="ukko_boardname">{{OP.Board}}</span></a></p>
|
||||||
</div>
|
</div>
|
||||||
{{{OP.Truncate.RenderPost}}}
|
{{{OP.Truncate.RenderPost}}}
|
||||||
@ -36,10 +37,11 @@
|
|||||||
{{/threads}}
|
{{/threads}}
|
||||||
</div>
|
</div>
|
||||||
<script type="text/javascript" >
|
<script type="text/javascript" >
|
||||||
|
var prefix = "{{prefix}}";
|
||||||
var e = document.getElementById("nntpchan_banner");
|
var e = document.getElementById("nntpchan_banner");
|
||||||
nntpchan_inject_banners(e, "{{prefix}}");
|
nntpchan_inject_banners(e, prefix);
|
||||||
|
init(prefix);
|
||||||
</script>
|
</script>
|
||||||
<hr/>
|
<hr/>
|
||||||
<footer>
|
<footer>
|
||||||
<p class="legal">All posts on this site are the responsibility of the individual poster and not the administration, pursuant to 47 U.S.C. § 230.</p>
|
<p class="legal">All posts on this site are the responsibility of the individual poster and not the administration, pursuant to 47 U.S.C. § 230.</p>
|
||||||
|
Reference in New Issue
Block a user