mb. POWER VOTE

musicbrainz.org: Adds some buttons to check all unvoted edits (Yes/No/Abs/None) at once in the edit search page. You can also collapse/expand (all) edits for clarity. A handy reset votes button is also available + Double click radio to vote single edit + range click with shift to vote a series of edits. , Hidden (collapsed) edits will never be voted (even if range click or shift+click force vote).

2015/04/30時点のページです。最新版はこちら。

作者のサイトでサポートを受ける。または、このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください。
(function(){"use strict";var meta={rawmdb:function(){
// ==UserScript==
// @name         mb. POWER VOTE
// @version      2015.4.30.1619
// @description  musicbrainz.org: Adds some buttons to check all unvoted edits (Yes/No/Abs/None) at once in the edit search page. You can also collapse/expand (all) edits for clarity. A handy reset votes button is also available + Double click radio to vote single edit + range click with shift to vote a series of edits. , Hidden (collapsed) edits will never be voted (even if range click or shift+click force vote).
// @homepage     http://userscripts-mirror.org/scripts/show/57765
// @supportURL   https://github.com/jesus2099/konami-command/issues
// @namespace    https://github.com/jesus2099/konami-command
// @author       PATATE12
// @licence      CC BY-NC-SA 3.0 (https://creativecommons.org/licenses/by-nc-sa/3.0/)
// @since        2009-09-14
// @icon         data:image/gif;base64,R0lGODlhEAAQAKEDAP+/3/9/vwAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh/glqZXN1czIwOTkAIfkEAQACAwAsAAAAABAAEAAAAkCcL5nHlgFiWE3AiMFkNnvBed42CCJgmlsnplhyonIEZ8ElQY8U66X+oZF2ogkIYcFpKI6b4uls3pyKqfGJzRYAACH5BAEIAAMALAgABQAFAAMAAAIFhI8ioAUAIfkEAQgAAwAsCAAGAAUAAgAAAgSEDHgFADs=
// @grant        none
// @include      http*://*musicbrainz.org/*
// @include      http://*.mbsandbox.org/*
// @exclude      *//*/*mbsandbox.org/*
// @exclude      *//*/*musicbrainz.org/*
// @run-at       document-end
// ==/UserScript==
	}};
	if (meta.rawmdb && meta.rawmdb.toString && (meta.rawmdb = meta.rawmdb.toString())) {
		var kv/*key,val*/, row = /\/\/\s+@(\S+)\s+(.+)/g;
		while ((kv = row.exec(meta.rawmdb)) !== null) {
			if (meta[kv[1]]) {
				if (typeof meta[kv[1]] == "string") meta[kv[1]] = [meta[kv[1]]];
				meta[kv[1]].push(kv[2]);
			} else meta[kv[1]] = kv[2];
		}
	}
	var chrome = "Please run “"+meta.name+"” with Tampermonkey instead of plain Chrome.";
	var editform = document.querySelector("div#edits > form");
	if (editform) {
		/* - --- - --- - --- - START OF CONFIGURATION - --- - --- - --- - */
		var showtop = true;
		var showbottom = true;
		var border = "thin dashed red"; /*leave "" for defaults*/
		var submitButtonOnTopToo = true;
		var onlySubmitTabIndexed = true; /*hit tab after typed text or voted directly goes to a submit button*/
		var text = " // Check all unvoted edits (shift+click to force all votes) → ";
		var canceltext = "Reset votes";
		var scrollToEdits = false; /*will never get in the way if you have scrolled down yourself*/
		var rangeclick = true; /*multiple votes by clicking first vote then shift-clicking last radio in a range*/
		var collapseEdits = true;
		var voteColours = true;
		/* - --- - --- - --- - END  OF  CONFIGURATION - --- - --- - --- - */
		var userjs = "jesus2099userjs57765";
		var FF = /firefox/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent);/*FF has bugs*/
		if (FF) { FF = {"1":"#b1ebb0", "0":"#ebb1ba", "-1":"#f2f0a5"}; }
		document.head.appendChild(document.createElement("style")).setAttribute("type", "text/css");
		var j2css = document.styleSheets[document.styleSheets.length-1];
		j2css.insertRule("div.edit-list."+userjs+"force, div.edit-list."+userjs+"ninja > div.edit-actions, div.edit-list."+userjs+"ninja > div.edit-details, div.edit-list."+userjs+"ninja > div.edit-notes { overflow: hidden !important; height: 0 !important; !important; padding: 0 !important; margin: 0 !important; }", j2css.cssRules.length);
		j2css.insertRule("div#"+userjs+"xhrstat { position: fixed; top: 0; left: 0; border: 2px solid black; border-width: 0 2px 2px 0; background-color: #ff6; }", j2css.cssRules.length);
		j2css.insertRule("tr.rename-artist-credits."+userjs+"yes > th { vertical-align: middle; }", j2css.cssRules.length);
		j2css.insertRule("tr.rename-artist-credits."+userjs+"yes > td { color: #f00; font-weight: bolder; font-size: 2em; text-shadow: 1px 1px 0 #663; text-transform: uppercase; }", j2css.cssRules.length);
		var radios = [];
		var radiosafe = [];
		var lastradio;
		var submitButton, submitClone, submitShift, inputs;
		var collapse = ["▼", "◀"];
		var pendingXHRvote = 0;
		editform.addEventListener("submit", function(e) {
			e.preventDefault();
			if (pendingXHRvote > 0) {
				if (submitShift || confirm("GOING BACKGROUND (AJAX)? (or not)\n\n"+pendingXHRvote+" background vote"+(pendingXHRvote==1?" is":"s are")+" pending,\ndo you want to add more votes to this queue?\n\nSHIFT+CLICK on submit to bypass this confirmation next time.")) {
					var pendingvotes = editform.querySelectorAll("div.voteopts input[type='radio']:not([value='-2']):not([disabled])");
					for (var pv=0; pv<pendingvotes.length; pv++) {
						if (pendingvotes[pv].checked) {
							click(getParent(pendingvotes[pv], "label") || pendingvotes[pv], "dbl");
						}
					}
				}
			}
			else {
				lockform();
				this.submit();
			}
		}, false);
		if (inputs = document.querySelector("div#content div.overall-vote")) {
			del(inputs);
		}
		for (var rac = editform.querySelectorAll("tr.rename-artist-credits > td"), r=0; r<rac.length; r++) {
			if (rac[r].textContent.match(/jah?|yes|s[íì]|oui|voor|kyllä|ναι|はい/i)) {
				rac[r].parentNode.className += " "+userjs+"yes";
			}
		}
		inputs = editform.querySelectorAll("div.voteopts input[type='radio']");
		for (var i = 0; i < inputs.length; i++) {
			if (onlySubmitTabIndexed) { inputs[i].setAttribute("tabindex", "-1"); }
			radios.push(inputs[i]);
			if (voteColours) {/*FF is LIFO*/
				inputs[i].addEventListener("change", function(e) {
					var actions = getParent(this, "div", "edit-actions");
					if (this.value != -2) { actions.style.setProperty("background-color", FF?FF[this.value]:self.getComputedStyle(getParent(this, "div", "vote")).getPropertyValue("background-color")); }
					else { actions.style.removeProperty("background-color"); }
				}, false);
				if (inputs[i].checked) { sendEvent(inputs[i], "change"); }
			}
			var labinput = getParent(inputs[i], "label") || inputs[i];
			pd(labinput, "mousedown");
			labinput.setAttribute("title", "double-click to vote this single edit");
			labinput.addEventListener("dblclick", function(e) {
				var ed = getParent(this, "div", "edit-list");
				var vote = (this.querySelector("input[type='radio']") || this).value;
				var id = ed.querySelector("input[type='hidden'][name$='edit_id']");
				if (ed && vote && id) {
					var ta = ed.querySelector("textarea");
					var params = "enter-vote.vote.0.edit_id="+id.value+"&enter-vote.vote.0.vote="+vote+"&url="+encodeURIComponent("/edit/"+id.value);
					if (ta) { params += "&enter-vote.vote.0.edit_note="+encodeURIComponent(ta.value); }
					var xhr = new XMLHttpRequest();
					xhr.onreadystatechange = function(e) {
						if (xhr.readyState == 4) {
							var xhredito, xhredit = this.responseText.match(/<title>Edit #([0-9]+)/);
							var errmsg = "Error while edit voting in the background.";
							if (xhr.status != 200) { errmsg += "\n"+xhr.status+": "+xhr.statusText; }
							if (xhredit) {
								xhredit = xhredit[1];
								errmsg = "Edit #"+xhredit+"\n"+errmsg;
								xhredito = document.querySelector("input[type='hidden'][name$='edit_id'][value='"+xhredit+"']");
								if (xhredito) {
									xhredito = getParent(xhredito, "div", "edit-list");
								}
							}
							else { errmsg = "Unknown edit\n"+errmsg; }
							if (xhr.status == 200 && pendingXHRvote > 0 && xhredito) {
								del(xhredito);
							}
							else {
								if (xhredito) {
									ninja(e, xhredito, false, "force");
									xhredito.style.setProperty("background-color", "pink");
									xhredito.style.setProperty("display", "block");
								}
								alert(errmsg);
								if (xhredit && !xhredito) {
									self.open("/edit/"+xhredit);
								}
							}
							if (pendingXHRvote > 0) { updateXHRstat(--pendingXHRvote); }
						}
					};
					xhr.open("POST", "/edit/enter_votes", true);
					xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
					xhr.setRequestHeader("Content-length", params.length);
					xhr.setRequestHeader("Connection", "close");
					updateXHRstat(++pendingXHRvote);
					xhr.send(params);
					ninja(e, ed, true, "force");
				}
			}, false);
			labinput.addEventListener("click", function(e) {
				var rad = this.querySelector("input[type='radio']");
				if (rangeclick && (rad || this)) {
					if (e.shiftKey && lastradio && rad != lastradio && rad.value == lastradio.value) {
						rangeclick = false;
						doitdoit(e, rad.value, Math.min(radios.indexOf(rad), radios.indexOf(lastradio)), Math.max(radios.indexOf(rad), radios.indexOf(lastradio)));
						rangeclick = true;
						lastradio = null;
					}
					else {
						lastradio = rad;
					}
				}
			}, false);
			if (inputs[i].checked) { radiosafe.push(inputs[i]); }
		}
		if (radios.length > 4) {
			if (showtop) { showtop = editform.insertBefore( shortcutsRow(), editform.firstChild ); }
			if (showbottom) { showbottom = editform.insertBefore( shortcutsRow(), editform.lastChild.previousSibling ); }
		}
		submitButton = editform.querySelector("div.row > span.buttons > button");
		submitButton.addEventListener("click", submitShiftKey, false);
		submitButton.setAttribute("title", "SHIFT+CLICK for background voting of selected edits");
		if (submitButtonOnTopToo) {
			submitClone = editform.insertBefore(getParent(submitButton, "div", "row").cloneNode(true), editform.firstChild).querySelector("button[type='submit']");
			submitClone.addEventListener("click", submitShiftKey, false);
		}
		if (collapseEdits) {
			var edits = editform.querySelectorAll("div.edit-list");
			for (var ed = 0; ed < edits.length; ed++) {
				if (edits[ed].querySelector("div.edit-description")) {
					var eheader = edits[ed].querySelector("div.edit-header");
					var collexp = document.createElement("div");
					var collexpa = collexp.appendChild(document.createElement("a").appendChild(document.createTextNode(collapse[0])).parentNode);
					collexp.style.setProperty("float", "right");
					collexpa.className = userjs;
					if (eheader.querySelectorAll("td.vote-count > div > strong").length == 1) collexpa.className += " autoedit";
					collexpa.style.setProperty("cursor", "pointer");
					collexpa.style.setProperty("font-size", "2em");
					pd(collexpa, "mousedown");
					collexpa.setAttribute("title", "collapse same EDITOR edits: CTRL+click\n\ncollapse same TYPE edits: ALT+click\n\ncollapse "+(collexpa.className.match(/autoedit/)?"auto":"same VOTED ")+"edits: CTRL+ALT+click\n\ncollapse ALL edits: SHIFT+click");
					collexpa.setAttribute("rel", "collapse");
					collexpa.addEventListener("click", function(e) {
						var expand = (this.getAttribute("rel") == "expand");
						this.replaceChild(document.createTextNode(collapse[expand?0:1]), this.firstChild);
						this.setAttribute("title", this.getAttribute("title").replace(new RegExp(expand?"expand":"collapse", "g"), expand?"collapse":"expand"));
						this.setAttribute("rel", expand?"collapse":"expand");
						ninja(e, getParent(this, "div", "edit-list"), !expand);
						var editheader = getParent(this, "div", "edit-header");
						var editheadersel = "div.edit-header", editor, vote;
						var userCSS = "div.edit-header > p.subheader > a[href*='/user/']";
						var voteCSS = "div.edit-list > div.edit-actions > div.voteopts input[type='radio']:checked";
						var autoedit = false;
						if (!e.shiftKey) {
							if (e.altKey && e.ctrlKey) {
								if (this.className.match(/autoedit/)) autoedit = true;
								else {
									vote = editheader.parentNode.querySelector(voteCSS);
									if (vote) vote = vote.getAttribute("value");
								}
							}
							else if (e.altKey) {
								var edittype = editheader.getAttribute("class").match(/\W([a-z-]+)$/);
								if (edittype) {
									editheadersel += "."+edittype[1];
								}
							}
							else if (e.ctrlKey) {
								if (editor = editheader.querySelector(userCSS).getAttribute("href").match(/\/user\/(.+)$/)) {
									editor = editor[1];
								}
							}
						}
						if (e.altKey || e.ctrlKey || e.shiftKey) {
							var others = editform.querySelectorAll(editheadersel+" a."+userjs+(autoedit?".autoedit":"")+"[rel='"+(expand?"expand":"collapse")+"']");
							for (var other = 0; other < others.length; other++) {
								var ovote = getParent(others[other], "div", "edit-list").querySelector(voteCSS);
								if (ovote) ovote = ovote.getAttribute("value");
								if (
									(!editor || editor == getParent(others[other], "div", "edit-header").querySelector(userCSS).getAttribute("href").match(/\/user\/(.+)$/)[1])
									&& (!vote || vote == ovote)
								) {
									click(others[other]);
								}
							}
						}
					}, false);
					eheader.insertBefore(collexp, eheader.firstChild);
				}
			}
		}
		if (self.pageYOffset > 0) {
			var cs, offset = 0;
			if (submitClone && (cs = self.getComputedStyle(getParent(submitClone, "div", "row")))) {
				offset += parseInt(cs.getPropertyValue("height").match(/\d+/), 10);
				offset += parseInt(cs.getPropertyValue("margin").match(/\d+/), 10);
			}
			if (showtop.tagName && (cs = self.getComputedStyle(showtop))) {
				offset += parseInt(cs.getPropertyValue("height").match(/\d+/), 10);
				offset += parseInt(cs.getPropertyValue("margin").match(/\d+/), 10);
			}
			if (offset != 0) {
				self.scrollTo(0, self.pageYOffset + offset);
			}
		}
		else if (scrollToEdits) {
			var foundcount = document.querySelector("div#page div.search-toggle > p > strong");
			var navpages = document.querySelector("div#edits > p.pageselector > em");
			var addedStuff;
			if (navpages) {
				navpages.appendChild(document.createTextNode(" — "));
				addedStuff = navpages.appendChild(foundcount.cloneNode(true));
			} else if (submitClone) {
				addedStuff = getParent(submitClone, "div", "row").appendChild(foundcount.cloneNode(true));
				addedStuff.style.setProperty("float", "left");
			} else {
				addedStuff = editform.insertBefore(getParent(foundcount, "div", "search-toggle").cloneNode(true), editform.firstChild);
			}
			del(getParent(foundcount, "div", "search-toggle"));
			var artistlnk = document.getElementsByClassName("artistheader");
			if (addedStuff && artistlnk && artistlnk[0] && artistlnk[0].getElementsByTagName("a") && artistlnk[0].getElementsByTagName("a")[0]) {
				addedStuff.appendChild(document.createTextNode(" for "));
				artistlnk = artistlnk[0].getElementsByTagName("a")[0].cloneNode(true);
				addedStuff.appendChild(artistlnk);
				artistlnk.style.setProperty("border", "0");
				artistlnk.style.setProperty("padding", "0");
				artistlnk.style.setProperty("margin", "0");
				artistlnk.style.setProperty("font-size", "1.2em");
				artistlnk.style.setProperty("font-weight", "normal");
				artistlnk.style.setProperty("color", "black");
			}
			self.scrollTo(0, findPos(document.getElementById("edits")).y - self.getComputedStyle(document.getElementById("header-menu")).getPropertyValue("height").match(/\d+/));
		}
	}
	function shortcutsRow() {
		var editlist, editactions, voteopts, editdetails;
		editlist = mkElt("div", "edit-list");
		editlist.style.setProperty("border", border);
		editactions = mkElt("div", "edit-actions c applied");
		voteopts = mkElt("div", "voteopts buttons");
		voteopts.style.setProperty("width", "175px");
		voteopts.style.setProperty("margin", "0");
		voteopts.appendChild(shortcut("1", "Yes"));
		voteopts.appendChild(shortcut("0", "No"));
		voteopts.appendChild(shortcut("-1", "Abstain"));
		voteopts.appendChild(shortcut("-2", "None"));
		editactions.appendChild(voteopts);
		editlist.appendChild(editactions);
		editdetails = mkElt("div", "edit-details");
		editdetails.style.setProperty("text-align", "right");
		editdetails.style.setProperty("margin", "0");
		editdetails.appendChild(mkElt("span", "buttons").appendChild(shortcut("omgcancel", canceltext)).parentNode);
		editdetails.appendChild(document.createTextNode(text));
		editlist.appendChild(editdetails);
		return editlist;
	}
	function mkElt(typ, cls) {
		var obj = document.createElement(typ);
		obj.className = cls;
		return obj;
	}
	function shortcut(vote, txt) {
		var button = document.createElement("button");
		if (onlySubmitTabIndexed) { button.setAttribute("tabindex", "-1"); }
		button.style.setProperty("padding", FF?"0 2px":"0 3px");
		button.style.setProperty("margin", FF?"0 3px 0 0":"0 3px");
		button.style.setProperty("float", "none");
		button.appendChild(document.createTextNode(txt));
		button.addEventListener("click", function(e) { doitdoit(e, vote); }, false);
		return button;
	}
	function doitdoit(e, vote, min, max) {
		if (vote != "omgcancel") {
			for (i = (min?min+(FF?0:1):0); i < (max?max+1:radios.length); i++) {/*FF shift+click label NG*/
				if (radios[i].getAttribute("value") == vote && !radios[i].checked && !ninja(e, getParent(radios[i], "div", "edit-list")) && (e.shiftKey || isOkToVote(radios[i]))) {
					click(radios[i]);
				}
			}
		}
		else { for (i = 0; i < radiosafe.length; i++) { click(radiosafe[i]); } }
	}
	function isOkToVote(radiox) {
		return getParent(radiox, "div", "voteopts").querySelector("input[type='radio'][value='-2']").checked;
	}
	function getParent(obj, tag, cls) {
		var cur = obj;
		if (cur.parentNode) {
			cur = cur.parentNode;
			if (cur.tagName == tag.toUpperCase() && (!cls || cls && cur.className.match(new RegExp("\\W*"+cls+"\\W*")))) {
				return cur;
			} else {
				return getParent(cur, tag, cls);
			}
		} else {
			return null;
		}
	}
	function findPos(obj) { /* http://www.quirksmode.org/js/findpos.html */
		var curleft = 0, curtop = 0;
		if (obj.offsetParent) {
			do {
				curleft += obj.offsetLeft;
				curtop += obj.offsetTop;
			} while (obj = obj.offsetParent);
		}
		return {"x":curleft, "y":curtop};
	}
	function click(n, mod){
		var clicke = document.createEvent("MouseEvents");
		clicke.initMouseEvent((mod?mod:"")+"click", true, true, self, mod?2:0, 0, 0, 0, 0, false, false, false, false, 0, null);
		n.dispatchEvent(clicke);
	}
	function sendEvent(n, e){
		var ev = document.createEvent("HTMLEvents");
		ev.initEvent(e, true, true);
		n.dispatchEvent(ev);
	}
	function disable(cont, dis) {
		var inputs = cont.querySelectorAll("input, select, textarea, button");
		if (inputs.length > 0) {
			for (var i=0; i < inputs.length; i++) {
				if (dis) { inputs[i].setAttribute("disabled", "disabled"); }
				else { inputs[i].removeAttribute("disabled"); }
			}
			return true;
		} else { return false; }
	}
	function ninja(e, o, n, spec) {
		disable(o, n);
		var cls = spec?spec:"ninja";
		if (n != null) {
			var jQwtf;
			var allbutheader = "div.edit-actions, div.edit-notes, div.edit-details";
			try {
				jQwtf = spec?jQuery(o):jQuery(o).children(allbutheader);
			} catch(e) {
				jQwtf = spec?[o]:o.querySelectorAll(allbutheader);
				console.log(e.message+"!\n"+chrome);
			}
			if (e.detail > 0 && !e.altKey && !e.ctrlKey && !e.shiftKey) {
				if (n) {
					try { jQwtf.hide(100); } catch(e) { for(var j=0; j<jQwtf.length; j++) jQwtf[j].style.setProperty("display", "none"); }
				}
				else {
					try {
						jQuery(o).removeClass(userjs+"ninja");
						jQwtf.show(100);
					} catch(e) {
						for(var j=0; j<jQwtf.length; j++) {
							cssClass(jQwtf[j], "-"+userjs+"ninja");
							jQwtf[j].style.setProperty("display", "block");
						}
					}
				}
			}
			else {
				try { jQwtf.css("display", n?"none":""); } catch(e) { for(var j=0; j<jQwtf.length; j++) jQwtf[j].style.setProperty("display", n?"none":""); }
				cssClass(o, (n?"+":"-")+userjs+cls);
			}
		}
		else return cssClass(o, "?"+userjs+cls);
	}
	function cssClass(o, a) {
		var cls_str = a.substr(1);
		var cls_reg = new RegExp("(\\s|^)"+cls_str+"(\\s|$)");
		switch (a.substr(0,1)) {
			case "?": return o.className.match(cls_reg);
			case "+": if (!cssClass(o, "?"+cls_str)) o.className += " "+cls_str; return o.className;
			case "-": if (cssClass(o, "?"+cls_str)) o.className = o.className.replace(cls_reg, " "); return o.className;
			default: return null;
		}
	}
	function lockform(lo) {
		if (typeof lo != "boolean" || lo == true) {
			submitButton.setAttribute("disabled", "disabled");
			if (submitClone) submitClone.setAttribute("disabled", "disabled");
		}
		else {
			submitButton.removeAttribute("disabled");
			if (submitClone) submitClone.removeAttribute("disabled");
		}
	}
	function updateXHRstat(nbr) {
		var stat = document.getElementById(userjs+"xhrstat");
		if (!stat) {
			stat = document.body.appendChild(document.createElement("div"));
			stat.setAttribute("id", userjs+"xhrstat");
			stat.appendChild(document.createTextNode(" "));
			stat.style.setProperty("z-index", "2099");
		}
		stat.replaceChild(document.createTextNode(nbr+" background vote"+(nbr==1?"":"s")+" pending…"), stat.firstChild);
		lockform(editform.querySelector("div.edit-list:not(."+userjs+"force) div.edit-description")?false:true);
		if (!editform.querySelector("div.edit-list div.edit-description")) {
			location.reload();
		}
		stat.style.setProperty("display", nbr>0?"block":"none");
	}
	function del(o) {
		return o.parentNode.removeChild(o);
	}
	function submitShiftKey(e) { submitShift = e.shiftKey; }
	function pd(ob, en) { ob.addEventListener(en, function(e) { e.preventDefault(); }, false); }
})();