// ==UserScript==
// @name wikiru.jp コメントあぼーん
// @version 0.0.3.3
// @description wikiru.jp のコメント欄にNGID機能を追加します。
// @author Shikikan
// @match *://*.wikiru.jp/index.php*
// @grant GM_getValue
// @grant GM_setValue
// @run-at document-end
// @namespace https://greasyfork.org/users/159960
// ==/UserScript==
(function() {
'use strict';
var NGIDs;
var AboneMode;
load();
function initComments() {
var comments = document.querySelectorAll("ul.list1 li");
var regexId = new RegExp('[\\[{]' + '([0-9a-zA-Z\\.\\/]{11})' + '[\\]}]', 'gm');
var regexBrac = new RegExp('[\\[\\]{}]', 'gm');
var i=0, len;
var elem, match, userId, tmpHtml;
for(i=0,len=comments.length; i<len; i++) {
tmpHtml = "";
for(var elem=comments[i].firstChild; elem!==null; elem=elem.nextSibling) {
if(elem.nodeName == "#text") {
tmpHtml += elem.nodeValue;
elem.nodeValue = "";
}else if(elem.nodeName == "INPUT" || elem.nodeName == "BR") {
tmpHtml += elem.outerHTML;
elem.classList.add("js-remove");
}else if(elem.nodeName == "SPAN" || elem.nodeName == "A" || elem.nodeName == "STRONG") {
tmpHtml += elem.outerHTML;
elem.classList.add("js-remove");
}
}
match = tmpHtml.match(regexId);
if(match !== null) {
userId = match[match.length-1].replace(regexBrac,"");
tmpHtml = tmpHtml.replace(regexId, "[<span class='js-abonelinkwrap'><a href='javascript:void(0);' class='js-abonelink' data-userid='$1'>$1</a></span>]");
}
comments[i].insertAdjacentHTML("afterbegin", "<span class='js-comment' data-userid='"+ userId +"'>"+ tmpHtml +"</span>");
}
var aboneLinks = document.querySelectorAll("a.js-abonelink");
for(i=0,len=aboneLinks.length; i<len; i++) {
aboneLinks[i].addEventListener("click", showAboneLinkMenu, false);
}
var oldNodes = document.querySelectorAll(".js-remove");
for(i=0,len=oldNodes.length; i<len; i++) {
oldNodes[i].parentNode.removeChild(oldNodes[i]);
}
abone();
}
function initStyle() {
var str = ""+
" .js-aboned > span { display:none; }"+
" .js-aboned:before { content:'あぼーん'; display:block; color:#ccc; }"+
".js-sabori .js-aboned > span { display:block; }"+
".js-sabori .js-aboned:before { content:none; }"+
".js-sabori.js-gray .js-aboned > span { color:#eee !important; }"+
".js-sabori.js-white .js-aboned > span { color:#fff !important; }"+
".js-hide .js-aboned > span { display:none; }"+
".js-hide .js-aboned:before { content:none; }"+
".js-hide .js-aboned.js-notree { display:none; }"+
".js-rensa .js-aboned > span { display:none; }"+
".js-rensa .js-aboned > ul li > span { display:none; }"+
".js-rensa .js-aboned > ul li:before { content:'あぼーん'; display:block; color:#ccc; }"+
".js-hide.js-rensa .js-aboned { display:none; }"+
".js-listcontainer { position:fixed; top:0; right:-300px; width:300px; height:100%; box-sizing:border-box; padding:36px 28px; color:#fff; font-size:14px; background-color:rgba(0,0,0,0.8); transform:translateX(0); transition:all 0.2s 0.3s ease-out; }"+
".js-drawer { position:fixed; top:50%; left:-20px; width:20px; height:220px; background-color:rgba(0,0,0,0.2); transform:translateY(-50%); border-radius:12px 0 0 12px; }"+
".js-listcontainer:hover { transform:translateX(-300px); transition:all 0.2s 0s ease-out; }"+
".js-listcontainer h1 { background-color:transparent; color:#fff; font-size:23px; line-height:34px; font-weight:inherit; padding:0; margin:0 0 6px 0; }"+
".js-listpulldown select { margin:0 0 31px 0; }"+
".js-listcontainer a { color:#fff; }"+
".js-listcontainer ::-webkit-scrollbar { width:4px; }"+
".js-listcontainer ::-webkit-scrollbar-track { background-color:rgba(0,0,0,0); }"+
".js-listcontainer ::-webkit-scrollbar-thumb { background-color:rgba(255,255,255,0.2); }"+
".js-listcontainer a:hover { background-color:transparent; color:#f30; text-decoration:none; }"+
".js-listvflex { display:flex; flex-flow:column nowrap; width:100%; height:100%; }"+
".js-listtablewrap { overflow-x:hidden; overflow-y:auto; width:100%; height:100%; padding-right:6px; }"+
".js-listtable { display:table; width:100%; }"+
".js-listrow { display:table-row; }"+
".js-listrow:hover { background-color:rgba(255,255,255,0.1); }"+
".js-listcell { display:table-cell; line-height:28px; }"+
".js-listcell:last-of-type { text-align:right; width:1em; }"+
".js-listbtn { }"+
".js-abonelinkwrap { display:inline-block; position:relative; }"+
".js-abonelinkmenu { display:inline-block; position:absolute; top:1.5em; left:0; z-index:100; width:10em; margin:0; padding:0.4em 0; list-style:none; background-color:rgba(255,255,255,0.9); border:1px solid #ccc; box-shadow:0 2px 2px rgba(0,0,0,0.2); }"+
".js-abonelinkmenu li { background-color:rgba(0,0,0,0); }"+
".js-abonelinkmenu li a { display:block; line-height:2em; padding:0 0 0 1em; background-color:rgba(0,0,0,0); color:#333; }"+
".js-abonelinkmenu li a:hover { background-color:rgba(0,0,0,0.1); text-decoration:none; }"+
"";
var tag = document.createElement('style');
var textnode = document.createTextNode(str);
if(tag.styleSheet) {
tag.styleSheet.cssText = textnode.nodeValue;
}else{
tag.appendChild(textnode);
}
document.getElementsByTagName('head')[0].appendChild(tag);
}
function initList() {
var str = ""+
"<div class='js-listcontainer'>"+
"<div class='js-listvflex'>"+
"<h1>あぼーんリスト</h1>"+
"<div class='js-listpulldown'><select name='abonemode'>"+
"<option value='normal'>ふつう</option>"+
"<option value='sabori'>さぼり</option>"+
"<option value='hide'>かくす</option>"+
"<option value='gray'>うすく</option>"+
"<option value='white'>しろく</option>"+
"<option value='rensa'>れんさふつう</option>"+
"<option value='rensahide'>れんさかくす</option>"+
"</select></div>"+
"<div class='js-listtablewrap'>"+
"<div class='js-listtable'></div>"+
"</div>"+
"</div>"+
"<div class='js-drawer'></div>"+
"</div>";
document.body.insertAdjacentHTML("afterend", str);
printList();
var menu = document.querySelector(".js-listpulldown select");
var options = menu.getElementsByTagName("OPTION");
for(var i=0,len=options.length; i<len; i++) {
menu.options[i].selected = (menu.options[i].value == AboneMode);
}
setAboneMode(AboneMode);
menu.addEventListener("change", function() {
var i = this.selectedIndex;
var options = this.getElementsByTagName("OPTION");
setAboneMode(options[i].value);
});
}
function setAboneMode(mode) {
document.body.classList.remove("js-sabori","js-hide","js-rensa","js-gray","js-white");
switch(mode) {
case "normal":
break;
case "sabori":
document.body.classList.add("js-sabori");
break;
case "gray":
document.body.classList.add("js-sabori","js-gray");
break;
case "white":
document.body.classList.add("js-sabori","js-white");
break;
case "hide":
document.body.classList.add("js-hide");
break;
case "rensa":
document.body.classList.add("js-rensa");
break;
case "rensahide":
document.body.classList.add("js-rensa","js-hide");
break;
default:
break;
}
AboneMode = mode;
save();
}
function printList() {
var table = document.querySelector(".js-listtable");
var tmpHtml = "";
var i=0, len;
for(i=0,len=NGIDs.length; i<len; i++) {
tmpHtml += ""+
"<div class='js-listrow'>"+
"<div class='js-listcell'>"+
NGIDs[i]+
"</div>"+
"<div class='js-listcell'>"+
"<a href='javascript:void(0);' class='js-listbtn' data-userid='"+ NGIDs[i] +"'>×</a>"+
"</div>"+
"</div>";
}
table.innerHTML = tmpHtml;
var removeLinks = document.querySelectorAll("a.js-listbtn");
for(i=0,len=removeLinks.length; i<len; i++) {
removeLinks[i].addEventListener("click", clickRemoveLinkEvent, false);
}
}
function clickAddLinkEvent(ev) {
var userid = ev.target.dataset.userid;
var ans = window.confirm(userid +" をNGIDに追加します。よろしいですか?");
if(ans){
addNgid(userid);
}
}
function clickRemoveLinkEvent(ev) {
var userid = ev.target.dataset.userid;
var ans = window.confirm(userid +" をNGIDから削除します。よろしいですか?");
if(ans){
removeNgid(userid);
}
}
function clickSearchLinkEvent(ev) {
var userId = ev.target.dataset.userid;
var copyResult = clipboard(userId);
console.log("copy: "+copyResult);
var form = document.createElement("form");
form.setAttribute("action", "https://" + window.location.hostname + "/index.php?cmd=search");
form.setAttribute("method","post");
form.setAttribute("target","_blank");
form.style.position = "fixed";
form.style.left = "-100%";
var encode_hint = document.createElement("input");
encode_hint.setAttribute("type","hidden");
encode_hint.setAttribute("name","encode_hint");
encode_hint.setAttribute("value","ぷ");
form.appendChild(encode_hint);
var word = document.createElement("input");
word.setAttribute("type","hidden");
word.setAttribute("name","word");
word.setAttribute("value",userId);
form.appendChild(word);
var type = document.createElement("input");
type.setAttribute("type","hidden");
type.setAttribute("name","type");
type.setAttribute("value","AND");
form.appendChild(type);
document.body.appendChild(form);
form.submit();
document.body.removeChild(form);
}
function clipboard(str) {
var div = document.createElement("div");
div.appendChild(document.createElement("pre")).textContent = str;
div.style.position = "fixed";
div.style.left = "-100%";
document.body.appendChild(div);
document.getSelection().selectAllChildren(div);
var result = document.execCommand('copy');
document.body.removeChild(div);
return result;
}
function showAboneLinkMenu(ev) {
if(!ev.target.parentNode.querySelector(".js-abonelinkmenu")) {
var idLink = ev.target;
var idLinkWrap = ev.target.parentNode;
var userId = ev.target.dataset.userid;
var str = ""+
"<ul class='js-abonelinkmenu'>"+
"<li><a href='javascript:void(0);' class='js-itemabone' data-userid='"+userId+"'>NGIDに登録</a></li>"+
"<li><a href='javascript:void(0);' class='js-itemsearch' data-userid='"+userId+"'>コピーして検索</a></li>"+
"</ul>";
idLink.insertAdjacentHTML("afterend",str);
var itemAbone = idLinkWrap.querySelector(".js-itemabone");
var itemSearch = idLinkWrap.querySelector(".js-itemsearch");
itemAbone.addEventListener("click",clickAddLinkEvent,false);
itemSearch.addEventListener("click",clickSearchLinkEvent,false);
}
}
function hideAboneLinkMenu(ev) {
if( ev.target.parentNode.classList.contains(".js-abonelinkmenu") ||
ev.target.classList.contains(".js-itemabone") ||
ev.target.classList.contains(".js-itemsearch") ) return false;
var menus = document.querySelectorAll(".js-abonelinkmenu");
for(var i=0,len=menus.length; i<len; i++) {
menus[i].parentNode.removeChild(menus[i]);
}
}
function initBodyClick(){
document.body.addEventListener("click",hideAboneLinkMenu,true);
}
function addNgid(userid) {
NGIDs.unshift(userid);
NGIDs = NGIDs.filter(function (x, i, self) {
return self.indexOf(x) === i;
});
save();
printList();
abone();
}
function removeNgid(userid) {
NGIDs = NGIDs.filter(function(v){
return v != userid;
});
save();
printList();
abone();
}
function save() {
var str = NGIDs.join(',');
if(typeof GM_setValue == 'function'){
GM_setValue("NGIDs", str);
GM_setValue("AboneMode", AboneMode);
}else{
localStorage.setItem("NGIDs", str);
localStorage.setItem("AboneMode", AboneMode);
}
}
function load() {
var str;
if(typeof GM_getValue == 'function'){
str = GM_getValue("NGIDs","");
if(str == "" || str == null || typeof str == 'undefined') {
NGIDs = [];
return;
}
NGIDs = str.split(',');
AboneMode = GM_getValue("AboneMode","normal");
}else{
str = localStorage.getItem("NGIDs","");
if(str == "" || str == null || typeof str == 'undefined') {
NGIDs = [];
return;
}
NGIDs = str.split(',');
AboneMode = localStorage.getItem("AboneMode","normal");
}
}
function abone() {
var i=0, j=0, clen, ilen, alen;
var comments = document.querySelectorAll("span.js-comment");
var aboned = document.querySelectorAll(".js-aboned");
for(i=0,alen=aboned.length; i<alen; i++) {
aboned[i].classList.remove("js-aboned");
}
for(i=0,clen=comments.length; i<clen; i++) {
for(j=0,ilen=NGIDs.length; j<ilen; j++) {
if(comments[i].dataset.userid == NGIDs[j]) {
if( ! comments[i].nextElementSibling ) {
comments[i].parentNode.classList.add("js-aboned","js-notree");
}else{
comments[i].parentNode.classList.add("js-aboned");
}
}
}
}
}
initStyle();
initComments();
initList();
initBodyClick();
})();