Skip to content

Instantly share code, notes, and snippets.

@Klaster1
Last active December 16, 2018 06:14
Show Gist options
  • Save Klaster1/320ef4110b3ea34766710301c66882af to your computer and use it in GitHub Desktop.
Save Klaster1/320ef4110b3ea34766710301c66882af to your computer and use it in GitHub Desktop.
MobyGames Credits Tool userscript
// ==UserScript==
// @name MobyGames Credits Tool
// @author Klaster_1
// @version 0.5
// @include http://www.mobygames.com/game/sheet/contribute/credits
// @include https://www.mobygames.com/game/sheet/contribute/credits
// @include http://www.mobygames.com/approval/game/edit_developer
// @include https://www.mobygames.com/approval/game/edit_developer
// @match http://www.mobygames.com/game/sheet/contribute/credits
// @match https://www.mobygames.com/game/sheet/contribute/credits
// @match http://www.mobygames.com/approval/game/edit_developer
// @match https://www.mobygames.com/approval/game/edit_developer
// @icon https://raw.github.com/klaster1/mobytools/master/images/icon.png
// @downloadURL https://gist.github.com/Klaster1/320ef4110b3ea34766710301c66882af/raw/MobyGames%2520Credits%2520Tool.user.js
// @updateURL https://gist.github.com/Klaster1/320ef4110b3ea34766710301c66882af/raw/MobyGames%2520Credits%2520Tool.user.js
// @run-at document-end
// ==/UserScript==
/*jslint browser:true,devel:true,es5:true*/
(function(){
"use strict";
console.log("Loading Credits Tool");
// Prototype.js is evil
delete Array.prototype.toJSON;
// Important objects
var credits={
get value(){
return JSON.parse(sessionStorage.getItem("credits"));
},
set value(data){
sessionStorage.setItem("credits",JSON.stringify(data));
}
};
var step=parseInt(document.querySelector("input[name='step']").value,10);
// Input and output of data
var exportJSON=function(data){
window.open("data:text/json;charset=utf-8,"+
encodeURIComponent(JSON.stringify(data,null,"\t")),"credits","width=600,height=600");
};
var importJSON=function(){
var fr=new FileReader(),
u=document.querySelector("#upload");
if(typeof fr.onload!=="function" && typeof u.onchange!=="function"){
u.onchange=function(e){
fr.readAsText(e.target.files[0]);
};
fr.onload=function(){
credits.value=JSON.parse(this.result);
u.value="";
};
}
u.click();
};
var removeCredits=function(){
sessionStorage.removeItem("credits");
};
// Step 2
var fillGroups=function(){
var names=credits.value.map(function(e){return e.name;}),
fields=document.querySelectorAll("#addgroup .FormLt1"),
i=0,nl=names.length,fl=fields.length;
for(;i<nl&&i<fl;i++){
fields[i].value=names[i];
}
document.querySelector("input[type=submit][name=update]").focus();
};
var padGroups=function(){
var g=document.querySelectorAll("input.FormLt1");
for(var i=0;i<g.length-5;i++){
g[0].value+=new Array(i+1).join(" ");
}
};
// Step 3
var createRoleLine=function(groupId,index,role,devIndex){
var tr=document.createElement("tr");
tr.setAttribute("class","cEntry");
tr.setAttribute("id","entryLine"+index);
tr.setAttribute("valign","top");
tr.innerHTML=
"<tr class=cEntry id=entryLine"+index+" valign=top>"+
" <td width=33%>"+
" <input type=hidden name=groupId-"+index+" value="+groupId+">"+
" <input type=hidden name=chkl-"+index+" value=1>"+
" <input type=text class=FormLtCredit id=titleEntry"+index+
" name=newCreditTitle_"+index+" value size=25"+
" onkeypress=showAddCreditsEntry("+(1+index)+")>"+
" </td>"+
" <td width=67%>"+
" <textarea class=FormLtCredit id=creditEntry"+index+".inp"+
" name=developerName_"+index+" cols=60 rows=1 onchange=parseNames("+index+",1)"+
" onkeyup=expandCreditsEntry(creditEntry"+index+".inp)></textarea>"+
" <div id=creditEntry"+index+".dsp></div>"+
" </td>"+
"</tr>";
tr.querySelector("input.FormLtCredit").value=role.name;
tr.querySelector("div").innerHTML=(function(){
var out="";
role.devs.forEach(function(dev,devIndexAtRole){
out+=createDev(index,dev,devIndexAtRole,devIndex);
devIndex+1;
});
return out;
}());
return tr;
};
var createDev=function(roleIndex,dev,devIndexAtRole,devIndexTotal){
var content=(function(){
var print;
if(dev.type==="person"){
if(dev.id===0||dev.id==="0"){
print= dev.name+
"<input type=hidden name='newPerson-"+roleIndex+"~"+devIndexAtRole+"' value=\""+dev.name+"\">";
}else{
print="<input type=hidden name=developerId-"+roleIndex+"~"+devIndexAtRole+" value="+dev.id+">"+
"<a href=/developer/sheet/view/developerId,"+dev.id+" target=_blank>"+dev.name+"</a>";
}
if(typeof dev.alt!=="undefined"&&dev.alt!==""){
print+=" ("+dev.alt+")<input type=hidden name=rn-"+roleIndex+"-"+dev.id+" value='"+dev.alt.replace(/^\(|\)$/gi,"")+"'/>";
}
return print;
}else if(dev.type==="text"){
return dev.name+
"<input type=hidden name=newEntity-"+roleIndex+"~"+devIndexAtRole+" value=\""+dev.name+"\">";
}else{
throw{
name:"Error",
message:"Unknown entity type "+dev.type
};
}
}())+
"--"+
"<a href=javascript:removeName("+devIndexTotal+")>remove</a>"+
"<br>";
return content;
};
var fillRoles=function(){
var groupRows=document.querySelectorAll("#addt .cEntry:not([id])"),
start,end,
i=0,j=1,k=0;
if(credits.value.length===groupRows.length){
start=groupRows;
end=document.querySelectorAll("#addt .cEntry:not([id])~tr:not([class])");
(function(){
var range,rolesLength,groupId;
for(;i<credits.value.length;i++){
range=document.createRange();
rolesLength=credits.value[i].roles.length;
groupId=start[i].nextElementSibling.querySelector("input[name^='groupId']").value;
range.setStartAfter(start[i]);
range.setEndBefore(end[i]);
range.deleteContents();
credits.value[i].roles.forEach(function(role){
range.collapse(false);
range.insertNode(createRoleLine(groupId,j,role,k));
j+=1;
});
}
})();
}else{
throw{
name:"Error",
message:"Groups quantity mismatch. Data: "+credits.value.length+"; page: "+groupRows.length
};
}
};
var grabDevs=function(){
if(document.querySelectorAll("a[href^='javascript:remove']").length){
console.log("Remove links found, aborting.");
alert("Finish adding new developers first and press 'Update' button. Then try again.");
return;
}
var entries=document.querySelectorAll("#addt tr:not(:first-of-type):not(:last-of-type):not([class]),"+
"#addt tr.cEntry[valign]:not([id])"),
isApproved=document.querySelectorAll(".mb1").length,
creditsOut=[],
hasClass,
addGroup,
addRole;
hasClass=function(el){
return el.hasAttribute("class");
};
addGroup=function(el){
creditsOut.push({
name:el.querySelector("td").textContent,
roles:[]
});
};
if(isApproved){
addRole=function(el){
var name=el.querySelector(".FormLtCredit").value,
devs=el.querySelectorAll(".mb1"),
role={
name:name,
devs:[]
};
Array.prototype.forEach.call(devs,function(dev){
var out={};
switch(dev.childNodes.length){
case 1:
var node=dev.childNodes[0];
out.name=node.textContent;
if(node.nodeType===1&&node.nodeName==="A"){
out.id=+node.getAttribute("href").match(/\d+/)[0];
out.type="person";
}else if(node.nodeType===3){
out.type="text";
}
break;
case 2:
out.name=dev.childNodes[0].textContent;
out.id=+dev.childNodes[0].getAttribute("href").match(/\d+/)[0];
out.alt=dev.childNodes[1].textContent.trim().replace(/^\(|\)$/g,"");
out.type="person";
break;
}
role.devs.push(out);
});
creditsOut[creditsOut.length-1].roles.push(role);
};
}else{
addRole=function(el){
var name=el.querySelector(".FormLtCredit").value,
nodes=el.children[1].childNodes,
role={
name:name,
devs:[]
};
(function(length){
var i;
for(i=0;i<length;i++){
var node=nodes[i],
out={};
if(node.nodeName!=="BR"){
if(node.nodeType===1 && node.nodeName==="A"){
out.type="person";
out.name=node.textContent;
out.id=+node.getAttribute("href").match(/\d+/)[0];
if(nodes[i+1].nodeType===3 && nodes[i+1].textContent===" ("){
out.alt=nodes[i+2].value;
i+=4;
}else{
i+=1;
}
}else if(node.nodeType===3){
out.type="text";
out.name=node.textContent;
i+=1;
}
role.devs.push(out);
}
}
})(nodes.length);
creditsOut[creditsOut.length-1].roles.push(role);
};
}
Array.prototype.forEach.call(entries,function(entry,index){
switch(hasClass(entry)){
case false:
addGroup(entry);
break;
case true:
addRole(entry);
break;
default:
console.log("Something went wrong");
break;
}
});
credits.value=creditsOut;
};
var handleCheckboxes=function(){
var prev={
index:-1,
checked:false
},
parent=document.querySelector("#delt"),
cboxes=parent.querySelectorAll("input[type='checkbox']"),
handle;
handle=function(e){
var el=e.target,
index=Array.prototype.indexOf.call(cboxes,el),
reverse=(function(){
if((index+1)<prev.index) return true;
if(index>(prev.index+1)) return false;
}()),
i;
if(el.nodeName==="INPUT"&&el.type==="checkbox"&&index!==-1){
if(e.shiftKey&&prev.index!==-1&&reverse!==undefined){
for(i=reverse?index:prev.index;i<(reverse?prev.index:index);i++){
cboxes[i].checked=prev.checked;
}
}
}
prev={
index:index,
checked:el.checked
};
};
parent.addEventListener("click",function(e){
handle(e);
},false);
};
// Step 5
var setClassification=function(){
var selects=document.querySelectorAll("select.FormLt2"),
i=0;
credits.value.forEach(function(group){
group.roles.forEach(function(role){
selects[i].value=role.clas;
i+=1;
});
});
};
var grabClassification=function(){
var selects=document.querySelectorAll("select"),
c=credits.value,
i=0;
credits.value=credits.value.map(function(group){
group.roles.forEach(function(role){
role.clas=+selects[i].value;
i+=1;
});
return group;
});
};
// Interface initialization
(function(){
var u=document.createElement("input");
u.setAttribute("type","file");
u.setAttribute("id","upload");
u.style.visibility="hidden";
document.body.appendChild(u);
})();
(function(){
var addButton=function(text,binding){
var out=document.createElement("button");
out.innerHTML=text;
out.addEventListener("click",binding);
return out;
};
var panel=document.createElement("span");
panel.id="CT";
panel.setAttribute("style","position:fixed;right:0;bottom:0;");
panel.appendChild(document.createTextNode(credits.value?"Credits are loaded":"Credits aren't loaded"));
if(credits.value){
panel.appendChild(addButton("Remove credits",removeCredits));
panel.appendChild(addButton("Export JSON",function(){exportJSON(credits.value);}));
}
panel.appendChild(addButton("Import JSON",importJSON));
switch(step){
case 2:
panel.appendChild(addButton("Insert groups",fillGroups));
panel.appendChild(addButton("Add spaces",padGroups));
break;
case 3:
handleCheckboxes();
if(credits.value)panel.appendChild(addButton("Insert developers",fillRoles));
panel.appendChild(addButton("Grab developers",grabDevs));
break;
case 5:
if(credits.value)panel.appendChild(addButton("Classify roles",setClassification));
panel.appendChild(addButton("Grab roles",grabClassification));
break;
}
document.querySelector("body").appendChild(panel);
}());
console.log("Credits Tool loaded");
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment