refactor structure
This commit is contained in:
41
contrib/js/nntpchan/api.js
Normal file
41
contrib/js/nntpchan/api.js
Normal file
@@ -0,0 +1,41 @@
|
||||
// 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;
|
||||
inject_hover_for_element(post);
|
||||
} else {
|
||||
post.setAttribute("class", "notfound post");
|
||||
post.appendChild(document.createTextNode("post not found"));
|
||||
}
|
||||
parent.appendChild(post);
|
||||
}
|
||||
|
||||
13
contrib/js/nntpchan/banner.js
Normal file
13
contrib/js/nntpchan/banner.js
Normal file
@@ -0,0 +1,13 @@
|
||||
var banner_count = 5;
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
||||
20
contrib/js/nntpchan/captcha-reload.js
Normal file
20
contrib/js/nntpchan/captcha-reload.js
Normal file
@@ -0,0 +1,20 @@
|
||||
function setSrcQuery(e, q) {
|
||||
var src = e.src;
|
||||
var p = src.indexOf('?');
|
||||
if (p >= 0) {
|
||||
src = src.substr(0, p);
|
||||
}
|
||||
e.src = src + "?" + q
|
||||
}
|
||||
|
||||
|
||||
function reload(el) {
|
||||
setSrcQuery(el, "reload=" + (new Date()).getTime());
|
||||
return false;
|
||||
}
|
||||
|
||||
onready(function(){
|
||||
document.getElementById("captcha_img").onclick = function() {
|
||||
reload(document.getElementById("captcha_img"));
|
||||
};
|
||||
});
|
||||
70
contrib/js/nntpchan/expand-image.js
Normal file
70
contrib/js/nntpchan/expand-image.js
Normal file
@@ -0,0 +1,70 @@
|
||||
//
|
||||
// expand images inline
|
||||
//
|
||||
// released into the public domain by Jeff on 2016-04-30
|
||||
//
|
||||
|
||||
// is the filename matching an image?
|
||||
function filenameIsImage(fname) {
|
||||
return /\.(gif|jpeg|jpg|png|webp)/.test(fname.toLowerCase());
|
||||
}
|
||||
|
||||
// setup image inlining for 1 element
|
||||
function setupInlineImage(thumb, url) {
|
||||
if(thumb.inlineIsSetUp) return;
|
||||
thumb.inlineIsSetUp = true;
|
||||
var img = thumb.querySelector("img.thumbnail");
|
||||
var expanded = false;
|
||||
var oldurl = img.src;
|
||||
thumb.onclick = function() {
|
||||
if (expanded) {
|
||||
img.setAttribute("class", "thumbnail");
|
||||
img.src = oldurl;
|
||||
expanded = false;
|
||||
} else {
|
||||
img.setAttribute("class", "expanded-thumbnail");
|
||||
img.src = url;
|
||||
expanded = true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// set up image inlining for all applicable children in an element
|
||||
function setupInlineImageIn(element) {
|
||||
var thumbs = element.querySelectorAll("a.file");
|
||||
for ( var i = 0 ; i < thumbs.length ; i++ ) {
|
||||
var url = thumbs[i].href;
|
||||
if (filenameIsImage(url)) {
|
||||
// match
|
||||
console.log("matched url", url);
|
||||
setupInlineImage(thumbs[i], url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
onready(function(){
|
||||
|
||||
// Setup Javascript events for document
|
||||
setupInlineImageIn(document);
|
||||
|
||||
|
||||
// Setup Javascript events via updatoer
|
||||
if (window.MutationObserver) {
|
||||
var observer = new MutationObserver(function(mutations) {
|
||||
for (var i = 0; i < mutations.length; i++) {
|
||||
var additions = mutations[i].addedNodes;
|
||||
if (additions == null) continue;
|
||||
for (var j = 0; j < additions.length; j++) {
|
||||
var node = additions[j];
|
||||
if (node.nodeType == 1) {
|
||||
setupInlineImageIn(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
observer.observe(document.body, {childList: true, subtree: true});
|
||||
}
|
||||
|
||||
});
|
||||
246
contrib/js/nntpchan/expand-video.js
Normal file
246
contrib/js/nntpchan/expand-video.js
Normal file
@@ -0,0 +1,246 @@
|
||||
/* This file is dedicated to the public domain; you may do as you wish with it. */
|
||||
/* Note: This code expects the global variable configRoot to be set. */
|
||||
var configRoot = "";
|
||||
|
||||
|
||||
if (typeof _ == 'undefined') {
|
||||
var _ = function(a) { return a; };
|
||||
}
|
||||
|
||||
function setupVideo(thumb, url) {
|
||||
if (thumb.videoAlreadySetUp) return;
|
||||
thumb.videoAlreadySetUp = true;
|
||||
|
||||
var video = null;
|
||||
var videoContainer, videoHide;
|
||||
var expanded = false;
|
||||
var hovering = false;
|
||||
//var loop = setting("videoloop");
|
||||
var loop = true;
|
||||
var loopControls = [document.createElement("span"), document.createElement("span")];
|
||||
var fileInfo = thumb.parentNode.querySelector(".fileinfo");
|
||||
var mouseDown = false;
|
||||
|
||||
function unexpand() {
|
||||
if (expanded) {
|
||||
expanded = false;
|
||||
if (video.pause) video.pause();
|
||||
videoContainer.style.display = "none";
|
||||
thumb.style.display = "inline";
|
||||
video.style.maxWidth = "inherit";
|
||||
video.style.maxHeight = "inherit";
|
||||
}
|
||||
}
|
||||
|
||||
function unhover() {
|
||||
if (hovering) {
|
||||
hovering = false;
|
||||
if (video.pause) video.pause();
|
||||
videoContainer.style.display = "none";
|
||||
video.style.maxWidth = "inherit";
|
||||
video.style.maxHeight = "inherit";
|
||||
}
|
||||
}
|
||||
|
||||
// Create video element if does not exist yet
|
||||
function getVideo() {
|
||||
if (video == null) {
|
||||
video = document.createElement("video");
|
||||
video.src = url;
|
||||
video.loop = loop;
|
||||
video.innerText = _("Your browser does not support HTML5 video.");
|
||||
|
||||
videoHide = document.createElement("img");
|
||||
videoHide.src = configRoot + "static/collapse.gif";
|
||||
videoHide.alt = "[ - ]";
|
||||
videoHide.title = "Collapse video";
|
||||
videoHide.style.marginLeft = "-15px";
|
||||
videoHide.style.cssFloat = "left";
|
||||
videoHide.addEventListener("click", unexpand, false);
|
||||
|
||||
videoContainer = document.createElement("div");
|
||||
videoContainer.style.paddingLeft = "15px";
|
||||
videoContainer.style.display = "none";
|
||||
videoContainer.appendChild(videoHide);
|
||||
videoContainer.appendChild(video);
|
||||
thumb.parentNode.insertBefore(videoContainer, thumb.nextSibling);
|
||||
|
||||
// Dragging to the left collapses the video
|
||||
video.addEventListener("mousedown", function(e) {
|
||||
if (e.button == 0) mouseDown = true;
|
||||
}, false);
|
||||
video.addEventListener("mouseup", function(e) {
|
||||
if (e.button == 0) mouseDown = false;
|
||||
}, false);
|
||||
video.addEventListener("mouseenter", function(e) {
|
||||
mouseDown = false;
|
||||
}, false);
|
||||
video.addEventListener("mouseout", function(e) {
|
||||
if (mouseDown && e.clientX - video.getBoundingClientRect().left <= 0) {
|
||||
unexpand();
|
||||
}
|
||||
mouseDown = false;
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
|
||||
// Clicking on thumbnail expands video
|
||||
thumb.addEventListener("click", function(e) {
|
||||
if (!e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey) {
|
||||
getVideo();
|
||||
expanded = true;
|
||||
hovering = false;
|
||||
|
||||
video.style.position = "static";
|
||||
video.style.pointerEvents = "inherit";
|
||||
video.style.display = "inline";
|
||||
videoHide.style.display = "inline";
|
||||
videoContainer.style.display = "block";
|
||||
videoContainer.style.position = "static";
|
||||
video.parentNode.parentNode.removeAttribute('style');
|
||||
thumb.style.display = "none";
|
||||
|
||||
//video.muted = (setting("videovolume") == 0);
|
||||
//video.volume = setting("videovolume");
|
||||
video.controls = true;
|
||||
if (video.readyState == 0) {
|
||||
video.addEventListener("loadedmetadata", expand2, false);
|
||||
} else {
|
||||
setTimeout(expand2, 0);
|
||||
}
|
||||
video.play();
|
||||
e.preventDefault();
|
||||
}
|
||||
}, false);
|
||||
|
||||
function expand2() {
|
||||
video.style.maxWidth = "100%";
|
||||
video.style.maxHeight = window.innerHeight + "px";
|
||||
var bottom = video.getBoundingClientRect().bottom;
|
||||
if (bottom > window.innerHeight) {
|
||||
window.scrollBy(0, bottom - window.innerHeight);
|
||||
}
|
||||
// work around Firefox volume control bug
|
||||
//video.volume = Math.max(setting("videovolume") - 0.001, 0);
|
||||
//video.volume = setting("videovolume");
|
||||
}
|
||||
|
||||
// Hovering over thumbnail displays video
|
||||
thumb.addEventListener("mouseover", function(e) {
|
||||
//if (setting("videohover")) {
|
||||
if (false) { // DOESN'T WORK YET
|
||||
getVideo();
|
||||
expanded = false;
|
||||
hovering = true;
|
||||
|
||||
var docRight = document.documentElement.getBoundingClientRect().right;
|
||||
var thumbRight = thumb.querySelector("img, video").getBoundingClientRect().right;
|
||||
var maxWidth = docRight - thumbRight - 20;
|
||||
if (maxWidth < 250) maxWidth = 250;
|
||||
|
||||
video.style.position = "fixed";
|
||||
video.style.right = "0px";
|
||||
video.style.top = "0px";
|
||||
var docRight = document.documentElement.getBoundingClientRect().right;
|
||||
var thumbRight = thumb.querySelector("img, video").getBoundingClientRect().right;
|
||||
video.style.maxWidth = maxWidth + "px";
|
||||
video.style.maxHeight = "100%";
|
||||
video.style.pointerEvents = "none";
|
||||
|
||||
video.style.display = "inline";
|
||||
videoHide.style.display = "none";
|
||||
videoContainer.style.display = "inline";
|
||||
videoContainer.style.position = "fixed";
|
||||
|
||||
//video.muted = (setting("videovolume") == 0);
|
||||
//video.volume = setting("videovolume");
|
||||
video.controls = false;
|
||||
video.play();
|
||||
}
|
||||
}, false);
|
||||
|
||||
thumb.addEventListener("mouseout", unhover, false);
|
||||
|
||||
// Scroll wheel on thumbnail adjusts default volume
|
||||
thumb.addEventListener("wheel", function(e) {
|
||||
//if (setting("videohover")) {
|
||||
if (true) {
|
||||
//var volume = setting("videovolume");
|
||||
if (e.deltaY > 0) volume -= 0.1;
|
||||
if (e.deltaY < 0) volume += 0.1;
|
||||
if (volume < 0) volume = 0;
|
||||
if (volume > 1) volume = 1;
|
||||
if (video != null) {
|
||||
video.muted = (volume == 0);
|
||||
video.volume = volume;
|
||||
}
|
||||
//changeSetting("videovolume", volume);
|
||||
e.preventDefault();
|
||||
}
|
||||
}, false);
|
||||
|
||||
// [play once] vs [loop] controls
|
||||
/*function setupLoopControl(i) {
|
||||
loopControls[i].addEventListener("click", function(e) {
|
||||
loop = (i != 0);
|
||||
thumb.href = thumb.href.replace(/([\?&])loop=\d+/, "$1loop=" + i);
|
||||
if (video != null) {
|
||||
video.loop = loop;
|
||||
if (loop && video.currentTime >= video.duration) {
|
||||
video.currentTime = 0;
|
||||
}
|
||||
}
|
||||
loopControls[i].style.fontWeight = "bold";
|
||||
loopControls[1-i].style.fontWeight = "inherit";
|
||||
}, false);
|
||||
}
|
||||
|
||||
loopControls[0].textContent = _("[play once]");
|
||||
loopControls[1].textContent = _("[loop]");
|
||||
loopControls[(setting("videoloop") ? 1 : 0)].style.fontWeight = "bold";
|
||||
for (var i = 0; i < 2; i++) {
|
||||
setupLoopControl(i);
|
||||
loopControls[i].style.whiteSpace = "nowrap";
|
||||
fileInfo.appendChild(document.createTextNode(" "));
|
||||
fileInfo.appendChild(loopControls[i]);
|
||||
}*/
|
||||
}
|
||||
|
||||
function setupVideosIn(element) {
|
||||
var thumbs = element.querySelectorAll("a.file");
|
||||
for (var i = 0; i < thumbs.length; i++) {
|
||||
if (/(\.webm)|(\.mp4)$/.test(thumbs[i].pathname)) {
|
||||
setupVideo(thumbs[i], thumbs[i].href);
|
||||
} else {
|
||||
var url = thumbs[i].href;
|
||||
if (/(\.webm)|(\.mp4)$/.test(url)) setupVideo(thumbs[i], url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onready(function(){
|
||||
// Insert menu from settings.js
|
||||
if (typeof settingsMenu != "undefined" && typeof Options == "undefined")
|
||||
document.body.insertBefore(settingsMenu, document.getElementsByTagName("hr")[0]);
|
||||
|
||||
// Setup Javascript events for videos in document now
|
||||
setupVideosIn(document);
|
||||
|
||||
// Setup Javascript events for videos added by updater
|
||||
if (window.MutationObserver) {
|
||||
var observer = new MutationObserver(function(mutations) {
|
||||
for (var i = 0; i < mutations.length; i++) {
|
||||
var additions = mutations[i].addedNodes;
|
||||
if (additions == null) continue;
|
||||
for (var j = 0; j < additions.length; j++) {
|
||||
var node = additions[j];
|
||||
if (node.nodeType == 1) {
|
||||
setupVideosIn(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
observer.observe(document.body, {childList: true, subtree: true});
|
||||
}
|
||||
});
|
||||
|
||||
206
contrib/js/nntpchan/hide-post.js
Normal file
206
contrib/js/nntpchan/hide-post.js
Normal file
@@ -0,0 +1,206 @@
|
||||
/** hidepost.js -- hides posts from page given $things */
|
||||
|
||||
|
||||
function get_hidden_posts() {
|
||||
var st = get_storage();
|
||||
var prefix = "nntpchan_hide_post_";
|
||||
return {
|
||||
all : function() {
|
||||
var msgids = [];
|
||||
for ( var k in st) {
|
||||
if (k.indexOf(prefix) == 0) {
|
||||
var m = k.substring(prefix.length);
|
||||
msgids.push(m);
|
||||
}
|
||||
}
|
||||
return msgids;
|
||||
},
|
||||
|
||||
add : function (msg) {
|
||||
st[prefix+msg] = "post";
|
||||
},
|
||||
|
||||
del : function (msg) {
|
||||
st.removeItem(prefix+msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// is a post elem an OP?
|
||||
function postIsOP(elem) {
|
||||
var ds = elem.dataset;
|
||||
return ds && ds.rootmsgid == ds.msgid ;
|
||||
}
|
||||
|
||||
function _hide_elem(elem, fade) {
|
||||
if(!fade) {
|
||||
if (elem.style) {
|
||||
elem.style.display = "none";
|
||||
} else {
|
||||
elem.style = {display: "none" };
|
||||
}
|
||||
elem.dataset.userhide = "yes";
|
||||
} else {
|
||||
$(elem).fadeOut(400, function() {
|
||||
_hide_elem(elem);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function _unhide_elem(elem) {
|
||||
$(elem).fadeIn();
|
||||
elem.dataset.userhide = "no";
|
||||
}
|
||||
|
||||
// return true if element is hidden
|
||||
function _elemIsHidden(elem) {
|
||||
return elem.dataset && elem.dataset.userhide == "yes";
|
||||
}
|
||||
|
||||
// hide a post
|
||||
function hidepost(elem, nofade) {
|
||||
console.log("hidepost("+elem.dataset.msgid+")");
|
||||
var posts = get_hidden_posts();
|
||||
if (posts) {
|
||||
// add to persitant hide
|
||||
posts.add(elem.dataset.msgidhash);
|
||||
}
|
||||
if(postIsOP(elem)) {
|
||||
// hide thread it's an OP
|
||||
var thread = document.getElementById("thread_"+elem.dataset.rootmsgidhash);
|
||||
if (thread) {
|
||||
var e = thread.getElementsByClassName("post");
|
||||
for ( var idx = 0; idx < e.length ; idx ++ ) {
|
||||
if (e[idx].dataset.msgid == elem.dataset.msgid) continue; // don't apply
|
||||
hidepost(e[idx]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// hide attachments and post body
|
||||
var es = elem.getElementsByClassName("attachments");
|
||||
for (var idx = 0; idx < es.length ; idx ++ ) {
|
||||
_hide_elem(es[idx], !nofade);
|
||||
}
|
||||
es = elem.getElementsByClassName("post_body");
|
||||
for (var idx = 0; idx < es.length ; idx ++ ) {
|
||||
_hide_elem(es[idx], !nofade);
|
||||
}
|
||||
es = elem.getElementsByClassName("postheader");
|
||||
for (var idx = 0; idx < es.length ; idx ++ ) {
|
||||
_hide_elem(es[idx], !nofade);
|
||||
}
|
||||
elem.dataset.userhide = "yes";
|
||||
elem.setHideLabel("[show]");
|
||||
}
|
||||
|
||||
// unhide a post
|
||||
function unhidepost(elem) {
|
||||
console.log("unhidepost("+elem.dataset.msgid+")");
|
||||
var posts = get_hidden_posts();
|
||||
if (posts) {
|
||||
// remove from persiting hide
|
||||
posts.del(elem.dataset.msgidhash);
|
||||
}
|
||||
if(postIsOP(elem)) {
|
||||
var thread = document.getElementById("thread_"+elem.dataset.rootmsgidhash);
|
||||
if(thread) {
|
||||
var e = thread.getElementsByClassName("post");
|
||||
for ( var idx = 0; idx < e.length ; idx ++ ) {
|
||||
if(e[idx].dataset.msgid == elem.dataset.msgid) continue;
|
||||
unhidepost(e[idx]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// unhide attachments and post body
|
||||
var es = elem.getElementsByClassName("attachments");
|
||||
for (var idx = 0; idx < es.length ; idx ++ ) {
|
||||
_unhide_elem(es[idx]);
|
||||
}
|
||||
es = elem.getElementsByClassName("post_body");
|
||||
for (var idx = 0; idx < es.length ; idx ++ ) {
|
||||
_unhide_elem(es[idx]);
|
||||
}
|
||||
es = elem.getElementsByClassName("postheader");
|
||||
for (var idx = 0; idx < es.length ; idx ++ ) {
|
||||
_unhide_elem(es[idx]);
|
||||
}
|
||||
|
||||
elem.dataset.userhide = "no";
|
||||
elem.setHideLabel("[hide]");
|
||||
}
|
||||
|
||||
// hide a post given a callback that checks each post
|
||||
function hideposts(check_func) {
|
||||
var es = document.getElementsByClassName("post");
|
||||
for ( var idx = 0; idx < es.length ; idx ++ ) {
|
||||
var elem = es[idx];
|
||||
if(check_func && elem && check_func(elem)) {
|
||||
hidepost(elem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// unhide all posts given callback
|
||||
// if callback is null unhide all
|
||||
function unhideall(check_func) {
|
||||
var es = document.getElementsByClassName("post");
|
||||
for (var idx=0 ; idx < es.length; idx ++ ) {
|
||||
var elem = es[idx];
|
||||
if(!check_func) { unhide(elem); }
|
||||
else if(check_func(elem)) { unhide(elem); }
|
||||
}
|
||||
}
|
||||
|
||||
// inject posthide into page
|
||||
onready(function() {
|
||||
var posts = document.getElementsByClassName("post");
|
||||
for (var idx = 0 ; idx < posts.length; idx++ ) {
|
||||
console.log("inject hide: "+posts[idx].dataset.msgid);
|
||||
var inject = function (elem) {
|
||||
var hider = document.createElement("a");
|
||||
hider.setAttribute("class", "hider");
|
||||
elem.setHideLabel = function (txt) {
|
||||
var e_hider = hider;
|
||||
e_hider.innerHTML = txt;
|
||||
}
|
||||
elem.hidepost = function() {
|
||||
var e_self = elem;
|
||||
var e_hider = hider;
|
||||
hidepost(e_self);
|
||||
}
|
||||
elem.unhidepost = function() {
|
||||
var e_self = elem;
|
||||
var e_hider = hider;
|
||||
unhidepost(e_self);
|
||||
}
|
||||
elem.isHiding = function() {
|
||||
var e_self = elem;
|
||||
return _elemIsHidden(e_self);
|
||||
}
|
||||
hider.appendChild(document.createTextNode("[hide]"));
|
||||
hider.onclick = function() {
|
||||
var e_self = elem;
|
||||
if(e_self.isHiding()) {
|
||||
e_self.unhidepost();
|
||||
} else {
|
||||
e_self.hidepost();
|
||||
}
|
||||
}
|
||||
elem.appendChild(hider);
|
||||
};
|
||||
inject(posts[idx]);
|
||||
}
|
||||
// apply persiting hidden posts
|
||||
var posts = get_hidden_posts();
|
||||
if(posts) {
|
||||
var all = posts.all();
|
||||
for ( var idx = 0 ; idx < all.length; idx ++ ) {
|
||||
var id = all[idx];
|
||||
var elem = document.getElementById(id);
|
||||
if(elem)
|
||||
hidepost(elem, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
1432
contrib/js/nntpchan/livechan.js
Normal file
1432
contrib/js/nntpchan/livechan.js
Normal file
File diff suppressed because it is too large
Load Diff
10
contrib/js/nntpchan/local_storage.js
Normal file
10
contrib/js/nntpchan/local_storage.js
Normal file
@@ -0,0 +1,10 @@
|
||||
function get_storage() {
|
||||
var st = null;
|
||||
if (window.localStorage) {
|
||||
st = window.localStorage;
|
||||
} else if (localStorage) {
|
||||
st = localStorage;
|
||||
}
|
||||
return st;
|
||||
}
|
||||
|
||||
65
contrib/js/nntpchan/old-livechan.js
Normal file
65
contrib/js/nntpchan/old-livechan.js
Normal file
@@ -0,0 +1,65 @@
|
||||
function livechan_got_post(widget, j) {
|
||||
// do scroll
|
||||
while (widget.children.length > 5) {
|
||||
// remove top element
|
||||
widget.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("streaming");
|
||||
}
|
||||
socket.onmessage = function(ev) {
|
||||
var j = null;
|
||||
try {
|
||||
j = JSON.parse(ev.data);
|
||||
} catch(e) {
|
||||
// ignore
|
||||
}
|
||||
if (j) {
|
||||
livechan_got_post(parent, j);
|
||||
}
|
||||
}
|
||||
socket.onclose = function(ev) {
|
||||
progress("connection closed");
|
||||
setTimeout(function() {
|
||||
inject_livechan_widget(prefix, parent);
|
||||
}, 1000);
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
|
||||
1
contrib/js/nntpchan/readme.md
Normal file
1
contrib/js/nntpchan/readme.md
Normal file
@@ -0,0 +1 @@
|
||||
main nntpchan javascript files
|
||||
426
contrib/js/nntpchan/reply.js
Normal file
426
contrib/js/nntpchan/reply.js
Normal file
@@ -0,0 +1,426 @@
|
||||
|
||||
function getReplyTo() {
|
||||
if(!document.dynreply) {
|
||||
var e = document.getElementById("postform_container");
|
||||
if (e) {
|
||||
// use existing postform
|
||||
document.dynreply = new DynReply(e);
|
||||
} else {
|
||||
// build a new postform
|
||||
document.dynreply = new DynReply();
|
||||
}
|
||||
e = document.dynreply.elem;
|
||||
e.style.position = "fixed";
|
||||
e.setAttribute("class", "shadow");
|
||||
}
|
||||
return document.dynreply;
|
||||
}
|
||||
|
||||
function table_insert_row(table, header, items) {
|
||||
var tr = document.createElement("tr");
|
||||
// insert header element
|
||||
var th = document.createElement("th");
|
||||
th.appendChild(header);
|
||||
tr.appendChild(th);
|
||||
// insert the rest of the elements
|
||||
for (var idx = 0; idx < items.length; idx ++ ) {
|
||||
var elem = document.createElement("td");
|
||||
elem.appendChild(items[idx]);
|
||||
tr.appendChild(elem);
|
||||
}
|
||||
table.appendChild(tr);
|
||||
}
|
||||
|
||||
/**
|
||||
build dynamic reply box
|
||||
*/
|
||||
function DynReply(existingElem) {
|
||||
if (existingElem) {
|
||||
// wrap existing post form
|
||||
// XXX: wrap it here
|
||||
this.elem = existingElem;
|
||||
this.form = this.elem.querySelector("form");
|
||||
this._error = document.getElementById("postform_msg");
|
||||
this.url = this.form.action + "?t=json";
|
||||
this.x = 1;
|
||||
this.y = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
// build new post form
|
||||
|
||||
var elem = document.createElement("div");
|
||||
elem.setAttribute("id", "postform_container");
|
||||
this.elem = elem;
|
||||
// build post form
|
||||
this.form = document.createElement("form");
|
||||
this.form.enctype = "multipart/form-data";
|
||||
this.form.name = "post";
|
||||
this.form.method = "post";
|
||||
// reference
|
||||
elem = document.createElement("input");
|
||||
elem.setAttribute("id", "postform_reference");
|
||||
elem.name = "reference";
|
||||
elem.type = "hidden";
|
||||
this.form.appendChild(elem);
|
||||
|
||||
var table = document.createElement("table");
|
||||
table.setAttribute("class", "postform");
|
||||
var tbody = document.createElement("tbody");
|
||||
|
||||
var span = document.createElement("span");
|
||||
// name
|
||||
elem = document.createElement("input");
|
||||
elem.setAttribute("name", "name");
|
||||
elem.setAttribute("value", "Anonymous");
|
||||
elem.setAttribute("id", "postform_name");
|
||||
span.appendChild(elem);
|
||||
// error message
|
||||
var err_elem = document.createElement("span");
|
||||
err_elem.setAttribute("id", "postform_msg");
|
||||
span.appendChild(err_elem);
|
||||
this._error = err_elem;
|
||||
table_insert_row(tbody, document.createTextNode("Name"), [span])
|
||||
|
||||
// subject
|
||||
elem = document.createElement("input");
|
||||
elem.setAttribute("name", "subject");
|
||||
elem.setAttribute("value", "");
|
||||
elem.setAttribute("id", "postform_subject");
|
||||
// submit
|
||||
var submit = document.createElement("input");
|
||||
submit.setAttribute("value", "reply");
|
||||
submit.setAttribute("class", "button");
|
||||
submit.setAttribute("type", "submit");
|
||||
submit.setAttribute("id", "postform_submit");
|
||||
table_insert_row(tbody, document.createTextNode("Subject"), [elem, submit]);
|
||||
|
||||
|
||||
// Comment
|
||||
elem = document.createElement("textarea");
|
||||
elem.setAttribute("id", "postform_message");
|
||||
elem.setAttribute("name", "message");
|
||||
elem.setAttribute("cols", "40");
|
||||
elem.setAttribute("rows", "5");
|
||||
table_insert_row(tbody, document.createTextNode("Comment"), [elem]);
|
||||
|
||||
// file
|
||||
elem = document.createElement("input");
|
||||
elem.setAttribute("class", "postform_attachment");
|
||||
elem.setAttribute("id", "postform_attachments");
|
||||
elem.setAttribute("type", "file");
|
||||
elem.setAttribute("name", "attachment_uploaded");
|
||||
elem.setAttribute("multiple", "multiple");
|
||||
table_insert_row(tbody, document.createTextNode("Files"), [elem]);
|
||||
|
||||
// dubs
|
||||
elem = document.createElement("input");
|
||||
elem.setAttribute("type", "checkbox");
|
||||
elem.setAttribute("name", "dubs");
|
||||
table_insert_row(tbody, document.createTextNode("Get Dubs"), [elem]);
|
||||
|
||||
// captcha
|
||||
elem = document.createElement("img");
|
||||
elem.setAttribute("id", "captcha_img");
|
||||
elem.alt = "captcha";
|
||||
table_insert_row(tbody, document.createTextNode("Captcha"), [elem]);
|
||||
|
||||
// captcha solution
|
||||
elem = document.createElement("input");
|
||||
elem.name = "captcha";
|
||||
elem.autocomplete = "off";
|
||||
elem.setAttribute("id", "captcha_solution");
|
||||
table_insert_row(tbody, document.createTextNode("Solution"), [elem])
|
||||
|
||||
table.appendChild(tbody);
|
||||
this.form.appendChild(table);
|
||||
this.elem.appendChild(this.form);
|
||||
document.body.appendChild(this.elem);
|
||||
this.board = null;
|
||||
this.roothash = null;
|
||||
this.prefix = null;
|
||||
this.url = null;
|
||||
this.x = 1;
|
||||
this.y = 1;
|
||||
|
||||
}
|
||||
|
||||
DynReply.prototype.update = function() {
|
||||
if (this.prefix) {
|
||||
// update captcha
|
||||
this.updateCaptcha();
|
||||
if (this.board) {
|
||||
// update post form
|
||||
var ref = document.getElementById("postform_reference");
|
||||
|
||||
if (this.roothash) {
|
||||
ref.setAttribute("value", this.roothash);
|
||||
} else {
|
||||
ref.setAttribute("value", "");
|
||||
}
|
||||
this.url = this.prefix + "post/" + this.board + "?t=json";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DynReply.prototype.show = function() {
|
||||
console.log("show dynreply");
|
||||
this.update();
|
||||
this.elem.style.display = 'inline';
|
||||
}
|
||||
|
||||
DynReply.prototype.hide = function() {
|
||||
console.log("hide dynreply");
|
||||
this.elem.style.display = "none";
|
||||
}
|
||||
|
||||
// clear all fields
|
||||
DynReply.prototype.clear = function() {
|
||||
this.clearSolution();
|
||||
this.clearPostbox();
|
||||
}
|
||||
|
||||
|
||||
// clear captcha solution
|
||||
DynReply.prototype.clearSolution = function() {
|
||||
var e = document.getElementById("captcha_solution");
|
||||
// reset value
|
||||
e.value = "";
|
||||
}
|
||||
|
||||
// clear postform elements
|
||||
DynReply.prototype.clearPostbox = function() {
|
||||
var e = document.getElementById("postform_subject");
|
||||
e.value = "";
|
||||
e = document.getElementById("postform_message");
|
||||
e.value = "";
|
||||
e = document.getElementById("postform_attachments");
|
||||
e.value = null;
|
||||
}
|
||||
|
||||
DynReply.prototype.post = function(cb, err_cb) {
|
||||
if (this.url && this.form) {
|
||||
var data = new FormData(this.form);
|
||||
var ajax = new XMLHttpRequest();
|
||||
ajax.onreadystatechange = function(ev) {
|
||||
if (ajax.readyState == XMLHttpRequest.DONE) {
|
||||
var j = null;
|
||||
try {
|
||||
j = JSON.parse(ajax.responseText);
|
||||
cb(j);
|
||||
} catch (e) {
|
||||
if(err_cb) {
|
||||
err_cb(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ajax.open("POST", this.url);
|
||||
ajax.send(data);
|
||||
}
|
||||
}
|
||||
|
||||
DynReply.prototype.updateCaptcha = function() {
|
||||
if (this.prefix) {
|
||||
var captcha_img = document.getElementById("captcha_img");
|
||||
captcha_img.src = this.prefix + "captcha/img";
|
||||
}
|
||||
this.clearSolution();
|
||||
}
|
||||
|
||||
DynReply.prototype.setPrefix = function(prefix) {
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
DynReply.prototype.hide = function() {
|
||||
this.elem.style.display = 'none';
|
||||
}
|
||||
|
||||
|
||||
DynReply.prototype.setBoard = function(boardname) {
|
||||
if (boardname) {
|
||||
this.board = boardname;
|
||||
}
|
||||
}
|
||||
|
||||
DynReply.prototype.setRoot = function(roothash) {
|
||||
if (roothash) {
|
||||
this.roothash = roothash;
|
||||
}
|
||||
}
|
||||
|
||||
DynReply.prototype.showError = function(msg) {
|
||||
console.log("error in dynreply: "+msg);
|
||||
this._error.setAttribute("class", "error message");
|
||||
this._error.appendChild(document.createTextNode(msg));
|
||||
this.updateCaptcha();
|
||||
}
|
||||
|
||||
DynReply.prototype.showMessage = function(msg) {
|
||||
this._error.setAttribute("class", "message");
|
||||
this._error.innerHTML = "";
|
||||
this._error.appendChild(document.createTextNode(msg));
|
||||
var e = this._error;
|
||||
setTimeout(function() {
|
||||
// clear it
|
||||
e.innerHTML = "";
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
|
||||
// reply box function
|
||||
function nntpchan_reply(parent, shorthash) {
|
||||
if (parent && document.dynreply) {
|
||||
var boardname = parent.getAttribute("boardname");
|
||||
var roothash = parent.getAttribute("root");
|
||||
var replyto = getReplyTo();
|
||||
// set target
|
||||
replyto.setBoard(boardname);
|
||||
replyto.setRoot(roothash);
|
||||
// show it
|
||||
replyto.show();
|
||||
}
|
||||
var elem = document.getElementById("postform_message");
|
||||
if ( elem )
|
||||
{
|
||||
elem.value += ">>" + shorthash.substr(0,10) + "\n";
|
||||
}
|
||||
}
|
||||
|
||||
// inject post hover behavior
|
||||
function inject_hover(prefix, el, parent) {
|
||||
if (!prefix) { throw "prefix is not defined"; }
|
||||
var linkhash = el.getAttribute("backlinkhash");
|
||||
if (!linkhash) { throw "linkhash undefined"; }
|
||||
console.log("rewrite linkhash "+linkhash);
|
||||
|
||||
var elem = document.createElement("span");
|
||||
elem.setAttribute("class", "backlink_rewritten");
|
||||
elem.appendChild(document.createTextNode(">>"+linkhash.substr(0,10)));
|
||||
if (!parent) {
|
||||
parent = el.parentNode;
|
||||
}
|
||||
parent.removeChild(el);
|
||||
parent.appendChild(elem);
|
||||
|
||||
elem.onclick = function(ev) {
|
||||
if(parent.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.setAttribute("class", "hover notfound-hover "+linkhash);
|
||||
wrapper.appendChild(document.createTextNode("not found"));
|
||||
} else {
|
||||
// wrap backlink
|
||||
nntpchan_buildpost(wrapper, j);
|
||||
}
|
||||
parent.appendChild(wrapper);
|
||||
parent.backlink = false;
|
||||
}, function(msg) {
|
||||
var wrapper = document.createElement("div");
|
||||
wrapper.setAttribute("class", "hover "+linkhash);
|
||||
wrapper.appendChild(document.createTextNode(msg));
|
||||
parent.appendChild(wrapper);
|
||||
parent.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]);
|
||||
}
|
||||
parent.backlink = true;
|
||||
}
|
||||
};
|
||||
parent.backlink = true;
|
||||
}
|
||||
|
||||
// inject post hover for all backlinks in an element
|
||||
function inject_hover_for_element(elem) {
|
||||
var elems = elem.getElementsByClassName("backlink");
|
||||
var ls = [];
|
||||
var l = elems.length;
|
||||
for ( var idx = 0 ; idx < l ; idx ++ ) {
|
||||
var e = elems[idx];
|
||||
ls.push(e);
|
||||
}
|
||||
for( var elem in ls ) {
|
||||
inject_hover(prefix, ls[elem]);
|
||||
}
|
||||
}
|
||||
|
||||
function init(prefix) {
|
||||
// because no one cares about this feature :|
|
||||
return;
|
||||
// inject posthover ...
|
||||
inject_hover_for_element(document);
|
||||
if ( /\.html$/.test(document.location.pathname) && ! (/ukko/.test(document.location.pathname)) ) {
|
||||
// board / thread page
|
||||
console.log("not loading reply widget");
|
||||
} else {
|
||||
// ukko / livechan page
|
||||
var rpl = getReplyTo();
|
||||
rpl.setPrefix(prefix);
|
||||
// set livechan
|
||||
rpl.setBoard("overchan.random");
|
||||
rpl.update();
|
||||
rpl.updateCaptcha();
|
||||
|
||||
// position replyto widget
|
||||
var e = rpl.elem;
|
||||
var mouseDownX, mouseDownY;
|
||||
|
||||
var $dragging = null;
|
||||
|
||||
$(rpl.elem).on("mousemove", function(ev) {
|
||||
if ($dragging) {
|
||||
var x = ev.pageX - $(this).width() / 2,
|
||||
y = ev.pageY - $(this).height() / 2;
|
||||
$dragging.offset({
|
||||
top: y,
|
||||
left: x
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
$(rpl.elem).on("mousedown", e, function (ev) {
|
||||
$dragging = $(rpl.elem);
|
||||
});
|
||||
|
||||
$(rpl.elem).on("mouseup", function (e) {
|
||||
$dragging = null;
|
||||
});
|
||||
|
||||
// add replyto post handlers
|
||||
e = document.getElementById("postform_submit");
|
||||
var postit = function() {
|
||||
var f = document.querySelector("form");
|
||||
// do ajax request to post data
|
||||
var r = getReplyTo();
|
||||
r.showMessage("posting... ");
|
||||
r.post(function(j) {
|
||||
if(j.error) {
|
||||
// an error happened
|
||||
r.showError(j.error);
|
||||
} else {
|
||||
// we're good
|
||||
r.showMessage("posted :^)");
|
||||
r.updateCaptcha();
|
||||
r.clear();
|
||||
}
|
||||
}, function(err) {
|
||||
r.showError(err);
|
||||
r.clearSolution();
|
||||
});
|
||||
}
|
||||
var f = document.querySelector("form");
|
||||
f.onsubmit = function() {
|
||||
postit();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
15
contrib/js/nntpchan/theme.js
Normal file
15
contrib/js/nntpchan/theme.js
Normal file
@@ -0,0 +1,15 @@
|
||||
function enable_theme(prefix, name) {
|
||||
if (prefix && name) {
|
||||
var theme = document.getElementById("current_theme");
|
||||
if (theme) {
|
||||
theme.href = prefix + "static/"+ name + ".css";
|
||||
var st = get_storage();
|
||||
st.nntpchan_prefix = prefix;
|
||||
st.nntpchan_theme = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// apply themes
|
||||
var st = get_storage();
|
||||
enable_theme(st.nntpchan_prefix, st.nntpchan_theme);
|
||||
66
contrib/js/nntpchan/unused/cuckoo_miner.js
Normal file
66
contrib/js/nntpchan/unused/cuckoo_miner.js
Normal file
@@ -0,0 +1,66 @@
|
||||
var easiness = 55.0;
|
||||
var miner_threads = 4;
|
||||
var randoffs = 64;
|
||||
|
||||
/*
|
||||
onready(function(){
|
||||
document.getElementById("start_miner").onclick = function() {
|
||||
var btn = document.getElementById("start_miner");
|
||||
var label = btn.value;
|
||||
btn.value = "..."
|
||||
btn.disabled = true;
|
||||
|
||||
|
||||
var b = new Uint8Array(randoffs);
|
||||
window.crypto.getRandomValues(b);
|
||||
var b_cur = 0;
|
||||
var b_i = 0;
|
||||
var tmp = new Uint8Array(randoffs+b_i+1);
|
||||
tmp.set(b)
|
||||
tmp[b.length]=0
|
||||
b = tmp;
|
||||
|
||||
var workers = new Array(miner_threads);
|
||||
|
||||
var worker_cb = function(e) {
|
||||
if (e.data[0] == "ok") {
|
||||
miner_cb(e.data[1]);
|
||||
btn.value=label;
|
||||
btn.disabled = false;
|
||||
for (i=0; i<miner_threads; i++) {
|
||||
workers[i].terminate();
|
||||
}
|
||||
} else {
|
||||
if (b_cur >= 256) {
|
||||
var tmp = new Uint8Array(randoffs+b_i+1);
|
||||
tmp.set(b)
|
||||
tmp[b.length]=0
|
||||
b = tmp;
|
||||
b_i++;
|
||||
b_cur=0;
|
||||
}
|
||||
b[randoffs+b_i]=b_cur;
|
||||
b_cur++;
|
||||
var params = [b, easiness, e.data[2]];
|
||||
workers[e.data[2]].postMessage(params);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
for (i=0; i<miner_threads; i++) {
|
||||
b[randoffs+b_i]=b_cur;
|
||||
b_cur++;
|
||||
var params = [b, easiness, i];
|
||||
workers[i] = new Worker("./static/mineworker.js");
|
||||
workers[i].onmessage = worker_cb;
|
||||
workers[i].postMessage(params); // Start the worker.
|
||||
}
|
||||
b_cur=4;
|
||||
};
|
||||
});
|
||||
function miner_cb(s) {
|
||||
document.getElementById("miner_result").value = s;
|
||||
}
|
||||
*/
|
||||
|
||||
2
contrib/js/nntpchan/unused/readme.md
Normal file
2
contrib/js/nntpchan/unused/readme.md
Normal file
@@ -0,0 +1,2 @@
|
||||
this directory holds unused javascript files for nntpchan
|
||||
don't delete files move them here
|
||||
Reference in New Issue
Block a user