619 lines
16 KiB
JavaScript
619 lines
16 KiB
JavaScript
|
|
var _onreadyfuncs = [];
|
|
|
|
var onready = function(f) {
|
|
_onreadyfuncs.push(function() {f();});
|
|
};
|
|
|
|
var ready = function() {
|
|
for(var idx = 0; idx < _onreadyfuncs.length; idx++) _onreadyfuncs[idx]();
|
|
};
|
|
|
|
var nntpchan_mod_mark_spam = function(longhash) {
|
|
var elem = document.getElementById(longhash);
|
|
if(!elem) return;
|
|
elem.dataset.spam = "yes";
|
|
elem.innerText = "spam";
|
|
};
|
|
|
|
var nntpchan_mod_commit_spam = function(elem) {
|
|
var formdata = new FormData();
|
|
var posts = document.getElementsByClassName("post");
|
|
var spams = [];
|
|
for (var idx = 0; idx < posts.length; idx ++)
|
|
{
|
|
if(posts[idx].dataset.spam == "yes")
|
|
{
|
|
spams.push(posts[idx].dataset.msgid);
|
|
}
|
|
}
|
|
formdata.set("spam", spams.join(","));
|
|
var jax = new XMLHttpRequest();
|
|
jax.onreadystatechange = function() {
|
|
if(jax.readyState == 4)
|
|
{
|
|
if(jax.status == 200)
|
|
{
|
|
|
|
var ajax = new XMLHttpRequest();
|
|
ajax.onreadystatechange = function() {
|
|
if(ajax.readyState == 4)
|
|
{
|
|
if(ajax.status == 200)
|
|
{
|
|
// success (?)
|
|
var j = JSON.parse(ajax.responseText);
|
|
if(j.error)
|
|
{
|
|
elem.innerText = "could not mark as spam: " + j.error;
|
|
}
|
|
else
|
|
{
|
|
elem.innerText = "OK: marked as spam";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
elem.innerText = "post not marked as spam on server: "+ ajax.statusText;
|
|
}
|
|
}
|
|
};
|
|
ajax.open("POST", "/mod/spam")
|
|
ajax.setRequestHeader("X-CSRF-Token", jax.getResponseHeader("X-CSRF-Token"));
|
|
ajax.send(formdata);
|
|
}
|
|
else
|
|
{
|
|
elem.innerText = "failed to moderate, not logged in";
|
|
}
|
|
}
|
|
};
|
|
jax.open("GET", "/mod/");
|
|
jax.send();
|
|
};
|
|
|
|
var nntpchan_mod_delete = function(longhash) {
|
|
var elem = document.getElementById(longhash);
|
|
var ajax = new XMLHttpRequest();
|
|
ajax.onreadystatechange = function() {
|
|
if(ajax.readyState == 4)
|
|
{
|
|
if(ajax.status == 200)
|
|
{
|
|
// success (?)
|
|
var j = JSON.parse(ajax.responseText);
|
|
if(j.deleted.length > 0)
|
|
{
|
|
elem.appendChild(document.createTextNode("deleted: " + j.deleted.join(",")));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
elem.innerHTML = "post not deleted from server: "+ ajax.statusText;
|
|
}
|
|
}
|
|
};
|
|
ajax.open("GET", "/mod/del/"+longhash);
|
|
ajax.send();
|
|
elem.innerHTML = "";
|
|
};
|
|
|
|
var quickreply = function(shorthash, longhash, url) {
|
|
if (!window.location.pathname.startsWith("/t/"))
|
|
{
|
|
window.location.href = url;
|
|
return;
|
|
}
|
|
var elem = document.getElementById("comment");
|
|
if(!elem) return;
|
|
elem.value += ">>" + shorthash + "\n";
|
|
};
|
|
|
|
var get_storage = function() {
|
|
var st = null;
|
|
if (window.localStorage) {
|
|
st = window.localStorage;
|
|
} else if (localStorage) {
|
|
st = localStorage;
|
|
}
|
|
return st;
|
|
};
|
|
|
|
var setSrcQuery = function(e, q) {
|
|
var src = e.src;
|
|
var p = src.indexOf('?');
|
|
if (p >= 0) {
|
|
src = src.substr(0, p);
|
|
}
|
|
e.src = src + "?" + q
|
|
};
|
|
|
|
|
|
var reloadImg = function(el) {
|
|
setSrcQuery(el, "reload=" + (new Date()).getTime());
|
|
return false;
|
|
};
|
|
|
|
var reloadThreadJSON = function(ourPost) {
|
|
var url = window.location.pathname + "/json";
|
|
var ajax = new XMLHttpRequest();
|
|
ajax.onreadystatechange = function() {
|
|
if(ajax.readyState == 4) {
|
|
if(ajax.status == 404) {
|
|
console.log("thread gone");
|
|
} else if (ajax.status == 200) {
|
|
var rootelem = document.getElementById("thread_"+window.location.pathname.split("/")[2]);
|
|
var posts = JSON.parse(ajax.responseText);
|
|
for(var idx = 0; idx < posts.length; idx ++ )
|
|
{
|
|
var id = posts[idx].HashLong;
|
|
var e = document.getElementById(id);
|
|
if(!e) {
|
|
e = document.createElement("div");
|
|
e.innerHTML = posts[idx].PostMarkup;
|
|
rootelem.appendChild(e.childNodes[0]);
|
|
e.remove();
|
|
if(ourPost && posts[idx].Message_id == ourPost) {
|
|
// focus on our post
|
|
window.location.hash = id;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
ajax.open("GET", url);
|
|
ajax.send();
|
|
}
|
|
|
|
// form resubmit
|
|
onready(function() {
|
|
var submitPost = function(form, elem, cb) {
|
|
var ajax = new XMLHttpRequest();
|
|
ajax.onreadystatechange = function() {
|
|
if (ajax.readyState == 4) {
|
|
var err = "unknown error";
|
|
var j = null;
|
|
try {
|
|
j = JSON.parse(ajax.responseText);
|
|
err = j.error || err;
|
|
} catch (ex) {
|
|
err = "error parsing reply: "+ ex;
|
|
}
|
|
if(ajax.status == 201) {
|
|
// success
|
|
form.reset();
|
|
cb(null, j);
|
|
} else if (ajax.status == 200) {
|
|
cb(err, j);
|
|
} else {
|
|
cb("http "+ajax.status, j);
|
|
}
|
|
} else {
|
|
elem.value += ".";
|
|
}
|
|
};
|
|
var data = new FormData();
|
|
data.append("message", document.getElementById("comment").value);
|
|
var inputs = form.getElementsByTagName("input");
|
|
for(var idx = 0; idx < inputs.length; idx++)
|
|
{
|
|
var input = inputs[idx];
|
|
console.log(input);
|
|
if(input.files)
|
|
{
|
|
for (var i =0 ; i < input.files.length; i++)
|
|
{
|
|
var file = input.files[i];
|
|
data.append(input.name, file, file.name);
|
|
}
|
|
}
|
|
else if(input.name)
|
|
data.append(input.name, input.value);
|
|
}
|
|
console.log("posting...");
|
|
ajax.open("POST", form.action+"/json");
|
|
ajax.send(data);
|
|
};
|
|
var elems = document.getElementsByClassName("postbutton");
|
|
if(elems && elems.length > 0 && elems[0]) {
|
|
var e = elems[0];
|
|
var parent = e.parentElement;
|
|
var origText = e.value;
|
|
e.remove();
|
|
e = document.createElement("input");
|
|
e.type = "button";
|
|
parent.appendChild(e);
|
|
e.value = origText;
|
|
e.onclick = function(ev) {
|
|
console.log("clicked post");
|
|
e.disabled = true;
|
|
e.value = "posting ";
|
|
submitPost(document.forms[0], e, function(err, j) {
|
|
if(err) {
|
|
var captcha = document.getElementById("captcha_solution");
|
|
if(captcha) {
|
|
captcha.value = "";
|
|
}
|
|
}
|
|
var msg = err || "posted";
|
|
console.log(msg, j.url);
|
|
e.value = msg;
|
|
if(window.location.pathname === j.url) {
|
|
reloadThreadJSON(j.message_id);
|
|
} else if (j && j.url) {
|
|
// do redirect
|
|
window.location.pathname = j.url;
|
|
return;
|
|
}
|
|
var img = document.getElementById("captcha_img");
|
|
if (img) {
|
|
reloadImg(img);
|
|
}
|
|
setTimeout(function() {
|
|
e.disabled = false;
|
|
e.value = origText;
|
|
}, 1000);
|
|
|
|
});
|
|
}
|
|
}
|
|
|
|
});
|
|
|
|
// captcha reload
|
|
onready(function(){
|
|
|
|
var e = document.getElementById("captcha_img");
|
|
if (e) {
|
|
e.onclick = function() {
|
|
reloadImg(e);
|
|
};
|
|
}
|
|
});
|
|
|
|
// inline reply expand
|
|
onready(function() {
|
|
|
|
var fetchpost = function(url, cb)
|
|
{
|
|
var parts = url.split("#");
|
|
var base = parts[0];
|
|
var h = parts[1];
|
|
var ajax = new XMLHttpRequest();
|
|
ajax.onreadystatechange = function()
|
|
{
|
|
if(ajax.readyState == 4)
|
|
{
|
|
if(ajax.status == 200)
|
|
{
|
|
var j = JSON.parse(ajax.responseText);
|
|
for(var idx =0 ; idx < j.length; idx ++)
|
|
{
|
|
if (j[idx].HashLong == h) {
|
|
cb(j[idx]);
|
|
return;
|
|
}
|
|
}
|
|
cb(null);
|
|
}
|
|
else
|
|
{
|
|
cb(null);
|
|
}
|
|
}
|
|
};
|
|
ajax.open("GET", base +"json");
|
|
ajax.send();
|
|
};
|
|
|
|
var elems = document.getElementsByClassName("backlink");
|
|
var inj = function(elem)
|
|
{
|
|
var showhover = function(parent, url, id)
|
|
{
|
|
fetchpost(url, function(post) {
|
|
var wrapper = document.createElement("div");
|
|
var e = document.createElement("div");
|
|
e.innerHTML = post.PostMarkup || "post not found"
|
|
wrapper.setAttribute('id', id);
|
|
wrapper.setAttribute("class", "hover");
|
|
wrapper.appendChild(e);
|
|
var cl = document.createElement("div");
|
|
cl.innerHTML = "[X]";
|
|
cl.onclick = function() {
|
|
wrapper.remove();
|
|
};
|
|
wrapper.appendChild(cl);
|
|
parent.appendChild(wrapper);
|
|
});
|
|
};
|
|
|
|
var hidehover = function(parent, id)
|
|
{
|
|
var hover = document.getElementById(id);
|
|
if(hover) hover.remove();
|
|
};
|
|
|
|
|
|
var parent = elem.parentNode.parentNode.id;
|
|
var wrapper = document.createElement("div");
|
|
elem.parentNode.insertBefore(wrapper, elem);
|
|
var el = elem.cloneNode(true);
|
|
elem.remove();
|
|
var parts = el.href.split("#");
|
|
wrapper.appendChild(el);
|
|
|
|
var id = "hover_"+parts[1]+"_"+parent;
|
|
console.log(id);
|
|
el.onpointerenter = function() {
|
|
showhover(wrapper, el.href, id);
|
|
};
|
|
|
|
el.onpointerleave = function()
|
|
{
|
|
hidehover(wrapper, id);
|
|
};
|
|
}
|
|
for (var idx = 0 ; idx < elems.length ; idx++) inj(elems[idx]);
|
|
});
|
|
|
|
// rewrite all images to add inline expand
|
|
onready(function() {
|
|
|
|
// is the filename matching an image?
|
|
var filenameIsImage = function(fname) {
|
|
return /\.(gif|jpeg|jpg|png|webp)/.test(fname.toLowerCase());
|
|
};
|
|
|
|
// setup image inlining for 1 element
|
|
var setupInlineImage = function(thumb, url) {
|
|
if(thumb.inlineIsSetUp) return;
|
|
thumb.inlineIsSetUp = true;
|
|
var img = thumb.querySelector("img.image");
|
|
var expanded = false;
|
|
var oldurl = img.src;
|
|
thumb.onclick = function() {
|
|
if (expanded) {
|
|
img.setAttribute("class", "image");
|
|
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
|
|
var setupInlineImageIn = function(element) {
|
|
var thumbs = element.querySelectorAll("a.image_link");
|
|
for ( var i = 0 ; i < thumbs.length ; i++ ) {
|
|
var url = thumbs[i].href;
|
|
if (filenameIsImage(url)) {
|
|
// match
|
|
setupInlineImage(thumbs[i], url);
|
|
}
|
|
}
|
|
};
|
|
// Setup Javascript events for document
|
|
setupInlineImageIn(document);
|
|
|
|
// Setup Javascript events via 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) {
|
|
setupInlineImageIn(node);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
observer.observe(document.body, {childList: true, subtree: true});
|
|
}
|
|
});
|
|
|
|
// set up post hider
|
|
onready(function() {
|
|
|
|
var get_hidden_posts = function() {
|
|
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?
|
|
var postIsOP = function(elem) {
|
|
var ds = elem.dataset;
|
|
return ds && ds.rootmsgid == ds.msgid ;
|
|
};
|
|
|
|
var hide_elem = function(elem, fade) {
|
|
if (elem.style) {
|
|
elem.style.display = "none";
|
|
} else {
|
|
elem.style = {display: "none" };
|
|
}
|
|
elem.dataset.userhide = "yes";
|
|
};
|
|
|
|
var unhide_elem = function(elem) {
|
|
elem.style = "";
|
|
elem.dataset.userhide = "no";
|
|
};
|
|
|
|
// return true if element is hidden
|
|
var elemIsHidden = function(elem) {
|
|
return elem.dataset && elem.dataset.userhide == "yes";
|
|
};
|
|
|
|
// hide a post
|
|
var hidepost = function(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("image");
|
|
for (var idx = 0; idx < es.length ; idx ++ ) {
|
|
hide_elem(es[idx]);
|
|
}
|
|
es = elem.getElementsByClassName("message_span");
|
|
for (var idx = 0; idx < es.length ; idx ++ ) {
|
|
hide_elem(es[idx]);
|
|
}
|
|
es = elem.getElementsByClassName("topicline");
|
|
for (var idx = 0; idx < es.length ; idx ++ ) {
|
|
hide_elem(es[idx]);
|
|
}
|
|
elem.dataset.userhide = "yes";
|
|
elem.setHideLabel("[show]");
|
|
};
|
|
|
|
// unhide a post
|
|
var unhidepost = function(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("image");
|
|
for (var idx = 0; idx < es.length ; idx ++ ) {
|
|
unhide_elem(es[idx]);
|
|
}
|
|
es = elem.getElementsByClassName("message_span");
|
|
for (var idx = 0; idx < es.length ; idx ++ ) {
|
|
unhide_elem(es[idx]);
|
|
}
|
|
es = elem.getElementsByClassName("topicline");
|
|
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
|
|
var hideposts = function(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
|
|
var unhideall = function(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
|
|
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);
|
|
};
|
|
|
|
var posts = document.getElementsByClassName("post");
|
|
for (var idx = 0 ; idx < posts.length; idx++ ) {
|
|
inject(posts[idx]);
|
|
}
|
|
// apply persiting hidden posts
|
|
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);
|
|
}
|
|
}
|
|
});
|