718 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			718 lines
		
	
	
		
			19 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_decode_ipban = function(longhash) {
 | |
|   var elem = document.getElementById("post_body_" + longhash);
 | |
|   if(!elem) return;
 | |
|   var lines = elem.innerText.split("\n");
 | |
|   console.log(lines);
 | |
|   for(var i = 0; i < lines.length; ++i)
 | |
|   {
 | |
|     if(!lines[i])
 | |
|       continue;
 | |
|     if (!lines[i].startsWith("overchan-inet-ban"))
 | |
|       continue;
 | |
|     console.log(lines[i]);
 | |
|     var parts = lines[i].split(" ");
 | |
|     if(parts.length < 2) continue;
 | |
|     parts = parts[1].split(":");
 | |
|     if(parts.legngth < 2) continue;
 | |
|     var a1 = atob(parts[0]);
 | |
|     var a2 = atob(parts[1]);
 | |
|     var txt = "";
 | |
|     for(var idx = 0; idx < a1.length; ++idx)
 | |
|     {
 | |
|       txt += String.fromCharCode(a1.charCodeAt(idx) ^ a2.charCodeAt(idx));
 | |
|     }
 | |
|     elem.appendChild(document.createTextNode(txt + "\n"));
 | |
|   }
 | |
| };
 | |
| 
 | |
| var nntpchan_mod_action = function(mod_action, elem) {
 | |
| 
 | |
|   var csrf_ajax = new XMLHttpRequest();
 | |
|   csrf_ajax.onreadystatechange = function() {
 | |
|     if (csrf_ajax.readyState == XMLHttpRequest.DONE) {
 | |
|       // get csrf token
 | |
|       var csrf = csrf_ajax.getResponseHeader("X-CSRF-Token");
 | |
|       // fire off ajax
 | |
|       var ajax = new XMLHttpRequest();
 | |
|       ajax.onreadystatechange = function() {
 | |
|         if (ajax.readyState == XMLHttpRequest.DONE) {
 | |
|           var status = ajax.status;
 | |
|           // we gud?
 | |
|           if (status == 200) {
 | |
|             // yah
 | |
|             var txt = ajax.responseText;
 | |
|             var j = JSON.parse(txt);
 | |
|             if (j.error) {
 | |
|               var e = document.createTextNode(j.error);
 | |
|               elem.appendChild(e);
 | |
|             } else {
 | |
|               if (mod_action.handle) {
 | |
|                 var result = mod_action.handle(j);
 | |
|                 if (result) {
 | |
|                   elem.appendChild(result);
 | |
|                 }
 | |
|               }
 | |
|             }
 | |
|           } else if (status) {
 | |
|             // nah
 | |
|             // http error
 | |
|             elem.innerHTML = "error: HTTP "+status;
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|       if (mod_action.name) {
 | |
|         var url = "/mod/" + mod_action.name;
 | |
|         ajax.open(mod_action.method || "GET", url);
 | |
|         ajax.setRequestHeader("X-CSRF-Token", csrf);
 | |
|         var data = mod_action.data;
 | |
|         if (data) {
 | |
|           ajax.setRequestHeader("Content-type","text/json");
 | |
|           ajax.send(JSON.stringify(data));
 | |
|         } else {
 | |
|           ajax.send();
 | |
|         }
 | |
|       } else {
 | |
|         alert("mod action has no name");
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   csrf_ajax.open("GET", "/mod/");
 | |
|   csrf_ajax.send();
 | |
| };
 | |
| 
 | |
| 
 | |
| var nntpchan_do_admin = function(method, param, result_elem) {
 | |
|   nntpchan_mod_action({
 | |
|     name:"admin/"+method,
 | |
|     method: ( param && "POST" ) || "GET",
 | |
|     data: param
 | |
|   }, result_elem);
 | |
| };
 | |
| 
 | |
| var nntpchan_mod_trust_mod = function(pubkey, elem) {
 | |
|   nntpchan_do_admin("pubkey.add", {pubkey: pubkey}, elem);
 | |
| };
 | |
| 
 | |
| var nntpchan_mod_untrust_mod = function(pubkey, elem) {
 | |
|   nntpchan_do_admin("pubkey.del", {pubkey: pubkey}, elem);
 | |
| };
 | |
| 
 | |
| 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() {
 | |
|   return;
 | |
|   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);
 | |
|     }
 | |
|   }
 | |
| });
 |