Greasy Fork is available in English.
This is the post test class which is created under the WM version 4.x script
此脚本不应直接安装,它是一个供其他脚本使用的外部库。如果您需要使用该库,请在脚本元属性加入:// @require https://update.greasyfork.org/scripts/6899/27565/WM%20Test%20Object.js
// ==UserScript== // @name WM Test Object // @namespace MerricksdadWMHostObject // @description This is the post test class which is created under the WM version 4.x script // @license http://creativecommons.org/licenses/by-nc-nd/3.0/us/ // @version 4.0.0.0 // @copyright Charlie Ewing except where noted // ==/UserScript== //this script requires some functions in the WM Common Library //this script needs access to a pre-defined JSON object (function(){ //*************************************************************************************************************************************** //***** Test Class //*************************************************************************************************************************************** WM.Test = function(params){try{ this.objType="test"; var self=this; params=params||{}; //defaults this.enabled=!(params.disabled||false); //check for WM2 disabled param this.expanded=true; this.title=""; this.search=[]; //strings array this.find=""; //string this.findArray=[]; //string array this.kids=[]; //test array this.subTests=[]; //strings array this.parent=null; this.appID=""; this.ret="dynamic"; this._findMode="basic"; this.subNumRange={low:0,high:0}; this._isGlobal=false; this.__defineGetter__("saveableData",function(){try{ var dat={}; //dat.id=this.id; dat.label=this.title; dat.enabled=this.enabled; dat.search=this.search; dat.find=(this.findMode=="basic")?this.findArray:this.find; dat.ret=this.ret; dat.expanded=this.expanded; if (this.findMode=="subtests") dat.subTests=this.subTests; if (this.findMode=="subnumrange") { dat.subNumRange=this.subNumRange.low+","+this.subNumRange.high; } if (this.findMode=="regex") dat.regex=this.regex; dat.appID=this.appID; dat.kids=[]; if (isArrayAndNotEmpty(this.kids)) for (var i=0,kid;(kid=this.kids[i]);i++) { dat.kids.push(kid.saveableData); } return dat; }catch(e){log("WM.Test.saveableData: "+e);}}); //set/get wether this test is saved as global or profile this.__defineGetter__("isGlobal",function(){try{ return this._isGlobal; }catch(e){log("WM.Test.isGlobal: "+e);}}); this.__defineSetter__("isGlobal",function(v){try{ //only top level tests can be global if (this.parent) { confirm("Only top level tests can be set to global."); return; } if (!v) { if (!confirm("Disabling profile sharing on this test will prevent other users on this machine from loading it. Are you sure you wish to make this test locally available only?")) return; } this._isGlobal=v; //make sure we have a uniqueID //but don't destroy one that already exists if (v && !exists(this.uniqueID)) this.uniqueID = unique(); //change the color/icon of the isGlobal button if (this.toggleGlobalButton) { var s=WM.opts.littleButtonSize; with (this.toggleGlobalButton) className=className.swapWordB(v,"removeGlobal"+s,"addGlobal"+s); with (this.toggleGlobalButton.parentNode) { className=className.swapWordB(v,"oddOrange","oddGreen"); title=(v)?"Disable Profile Sharing":"Share With Other Profiles"; } } }catch(e){log("WM.Test.isGlobal: "+e);}}); //use passed params for (var p in params) { //omit specific params if (!(["subNumRange","kids","disabled","label","find"].inArray(p)) ) { //copy only params that make it past the checker this[p]=params[p]; } } //calculate subNumRange as an object if (exists(params.subNumRange)) { var p=params.subNumRange.split(","); this.subNumRange={low:p[0]||0, high:p[1]||0}; this._findMode="subnumrange"; } //get the title from the label field if (exists(params.label)) this.title=params.label; //detect which findMode we are using //subNumRange was already inspected above if (this.regex) this._findMode="regex"; else if (exists(params.subTests)) this._findMode="subtests"; //and we default to "basic" already //import the find field now if (isArray(params.find)) this.findArray=params.find; else this.find=params.find; this.enable=function(){try{ this.enabled=true; this.node.className=this.node.className.removeWord("disabled"); WM.grabber.save(); }catch(e){log("WM.Test.enable: "+e);}}; this.disable=function(){try{ this.enabled=false; this.node.className=this.node.className.addWord("disabled"); WM.grabber.save(); }catch(e){log("WM.Test.disable: "+e);}}; this.remove=function(noConfirm){try{ var ask=WM.opts.dynamicConfirmDeleteTest; if (noConfirm || (this.isGlobal && confirm("This test is shared with other profiles. Deleting it here will prevent it from loading for other users. Are you sure you wish to delete this test and its children.")) || !ask || (!this.isGlobal && ask && confirm("Delete test and all of its child nodes?"))){ //remove my data var parentContainer=(this.parent)?this.parent.kids:WM.grabber.tests; parentContainer.removeByValue(this); //remove my node remove(this.node); doAction(WM.grabber.save); } }catch(e){log("WM.Test.remove: "+e);}}; this.moveUp=function(){try{ //where is this var parentContainer=(this.parent)?this.parent.kids:WM.grabber.tests; //only affects items not already the first in the list //and not the only child in the list if ((parentContainer.length>1) && (parentContainer[0]!=this)) { //which index is this? var myIndex=parentContainer.inArrayWhere(this); if (myIndex != -1) { //I have a proper index here //who is my sibling var sibling = parentContainer[myIndex-1]; //swap me with my sibling parentContainer[myIndex-1]=this; parentContainer[myIndex]=sibling; //place my node before my sibling node sibling.node.parentNode.insertBefore(this.node,sibling.node); //save it WM.grabber.save(); } } }catch(e){log("WM.Test.moveUp: "+e);}}; this.moveDown=function(){try{ //where is this var parentContainer=(this.parent)?this.parent.kids:WM.grabber.tests; //only affects items not already the last in the list //and not the only child in the list if ((parentContainer.length>1) && (parentContainer.last()!=this)) { //which index is this? var myIndex=parentContainer.inArrayWhere(this); if (myIndex != -1) { //I have a proper index here //who is my sibling var sibling = parentContainer[myIndex+1]; //swap me with my sibling parentContainer[myIndex+1]=this; parentContainer[myIndex]=sibling; //place my node before my sibling node sibling.node.parentNode.insertBefore(sibling.node,this.node); //save it WM.grabber.save(); } } }catch(e){log("WM.Test.moveDown: "+e);}}; this.moveUpLevel=function(){try{ if (this.parent) { //this is not a top level node, so we can move it var targetContainer=((this.parent.parent)?this.parent.parent.kids:WM.grabber.tests); //remove from parent this.parent.kids.removeByValue(this); //set new parent this.parent=(this.parent.parent||null); //never point to the top level //move the object targetContainer.push(this); //move the node if (this.parent) this.parent.kidsNode.appendChild(this.node); else WM.console.dynamicBuild.appendChild(this.node); //save it WM.grabber.save(); } }catch(e){log("WM.Test.moveUpLevel: "+e);}}; this.moveDownLevel=function(){try{ //where is this var parentContainer=(this.parent)?this.parent.kids:WM.grabber.tests; //create a new rule at my level var newTest = new WM.Test({ parent:this.parent||null, }); parentContainer.push(newTest); //remove me from my current parent parentContainer.removeByValue(this); //attach me to my new parent this.parent=newTest; newTest.kids.push(this); //move my node newTest.kidsNode.appendChild(this.node); //save it WM.grabber.save(); }catch(e){log("WM.Test.moveDownLevel: "+e);}}; this.clone=function(){try{ var cloneTest=this.saveableData; //global clones are not global if (this.parent) this.parent.addChild(cloneTest); else WM.grabber.newTest(cloneTest); }catch(e){log("WM.Test.clone: "+e);}}; this.addChild=function(p){try{ var isNew=!exists(p); p=p||{}; p.parent=this; var test=new WM.Test(p); this.kids.push(test); if (isNew) WM.grabber.save(); }catch(e){log("WM.Test.addChild: "+e);}}; this.toggleContent=function(){try{ this.expanded=!this.expanded; var btnSize=WM.opts.littleButtonSize; with (this.contentNode) className=className.swapWordB(this.expanded,"expanded","collapsed"); with (this.toggleImgNode) className=className.swapWordB(this.expanded,"treeCollapse"+btnSize,"treeExpand"+btnSize); WM.grabber.save(); }catch(e){log("WM.Test.toggleContent: "+e);}}; this.populateBonusList=function(){try{ var node=this.bonusNode; var bonuses={}; //get the list of accept texts for this app if (this.appID!="") { if (this.appID=="*") { //populate list with bonuses from ALL docked sidekicks } else { //make sure the app is ready //if it has not yet docked, it wont be var app=WM.apps[this.appID]; bonuses = (app?(mergeJSON(app.accText,app.userDefinedTypes)||{}):{}); } } //add special return values bonuses["dynamic"]="* Dynamic grab"; bonuses["none"]="* None"; bonuses["wishlist"]="* Flaged as Wishlist"; bonuses["exclude"]="* Excluded types"; bonuses["send"]="* Send Unknown"; bonuses["doUnknown"]="* Get Unknown"; bonuses["{%1}"]="* Subtest Value"; //sort by display text bonuses=sortCollection(bonuses,"value"); //add each element to the dropdown var elem; node.innerHTML=""; //wipe previous list for (var i in bonuses) { var showI=i.removePrefix(this.appID); node.appendChild( elem=createElement("option",{textContent:((bonuses[i].startsWith("*"))?"":((showI.startsWith("send"))?"Send ":"Get "))+bonuses[i], value:i, selected:(this.ret==i)}) ); } }catch(e){log("WM.Test.populateBonusList: "+e);}}; this.populateAppList=function(){try{ var node=this.appListNode; var a={}; for (var i in WM.apps){ a[WM.apps[i].appID]=WM.apps[i].name; } //add special return values a["*"]="* All"; //add each element to the dropdown var elem; node.innerHTML=""; //wipe previous list for (var i in a) { node.appendChild(elem=createElement("option",{textContent:a[i], value:i,selected:(this.appID==i)})); } //sort it elementSortChildren(node,"textContent"); }catch(e){log("WM.Test.populateAppList: "+e);}}; this.calcSearch=function(){try{ //collect the checked search fields in their listed order if (self.searchNode) { self.search=[]; forNodes(".//input[(@type='checkbox')]",{node:self.searchNode},function(e){ if (e && e.checked){ self.search.push(e.value); log(e.value); } }); } WM.grabber.save(); }catch(e){log("WM.Test.calcSearch: "+e);}}; this.convertToRule=function(p){try{ var rule; WM.rulesManager.rules.push( rule=new WM.rulesManager.Rule( WM.rulesManager.ruleFromTest( this.saveableData ) ) ); if (WM.opts.rulesJumpToNewRule){ //jump to rule view WM.console.tabContainer.selectTab(3); //scroll to new rule rule.node.scrollIntoView(); } }catch(e){log("WM.Test.convertToRule: "+e);}}; //set/get find field modes this.__defineGetter__("findMode",function(){try{ return this._findMode; }catch(e){log("WM.Test.findMode: "+e);}}); this.__defineSetter__("findMode",function(v){try{ var lastV = this._findMode; this._findMode=v; if (lastV==v) return; //no change //enable disable regex type this.regex=(v=="regex" || v=="regexp"); //switch to array/string find field type //this.setFindType((v=="basic")?"array":"string"); //show the correct find field if (this.findNode) this.findNode.value=((v=="basic")?this.findArray.join("\n"):this.find); //show/hide the subtests box if (this.subTestsBoxNode) with (this.subTestsBoxNode) className=className.toggleWordB((v!="subtests"),"hidden"); //show/hide the subnumrange picker if (this.subNumRangeBoxNode) with (this.subNumRangeBoxNode) className=className.toggleWordB((v!="subnumrange"),"hidden"); WM.grabber.save(); }catch(e){log("WM.Test.findMode: "+e);}}); //draw it try{(((this.parent)?this.parent.kidsNode:null)||$("wmDynamicBuilder")).appendChild( this.node=createElement("div",{className:"listItem "+((this.enabled)?"enabled":"disabled")},[ createElement("div",{className:"line"},[ createElement("div",{className:"littleButton",title:"Toggle Content",onclick:function(){self.toggleContent();}},[ this.toggleImgNode=createElement("img",{className:"resourceIcon "+(this.expanded?"treeCollapse"+WM.opts.littleButtonSize:"treeExpand"+WM.opts.littleButtonSize)}), ]), this.toggleNode=createElement("input",{type:"checkbox",checked:this.enabled,onchange:function(){ self.enabled=this.checked; with (self.node) className=className.toggleWordB(!this.checked,"disabled"); WM.grabber.save(); }}), createElement("label",{textContent:"Title:"}), this.titleNode=createElement("input",{value:(this.title||""), onchange:function(){self.title=this.value; WM.grabber.save();}}), //toolbox createElement("div",{className:"littleButton oddOrange", title:"Remove Test"},[ createElement("img",{className:"resourceIcon trash"+WM.opts.littleButtonSize,onclick:function(){self.remove();}})]), createElement("div",{className:"littleButton oddBlue", title:"Clone Test"},[ createElement("img",{className:"resourceIcon clone"+WM.opts.littleButtonSize,onclick:function(){self.clone();}})]), createElement("div",{className:"littleButton oddGreen", title:"Move Up"},[ createElement("img",{className:"resourceIcon arrowUp"+WM.opts.littleButtonSize,onclick:function(){self.moveUp();}})]), createElement("div",{className:"littleButton oddOrange", title:"Move Down"},[ createElement("img",{className:"resourceIcon arrowDown"+WM.opts.littleButtonSize,onclick:function(){self.moveDown();}})]), createElement("div",{className:"littleButton oddGreen", title:"Move Up Level"},[ createElement("img",{className:"resourceIcon moveUpLevelLeft"+WM.opts.littleButtonSize,onclick:function(){self.moveUpLevel();}})]), createElement("div",{className:"littleButton oddOrange", title:"Move Down Level"},[ createElement("img",{className:"resourceIcon moveInLevel"+WM.opts.littleButtonSize,onclick:function(){self.moveDownLevel();}})]), createElement("div",{className:"littleButton oddBlue", title:"Show Source"},[ createElement("img",{className:"resourceIcon object"+WM.opts.littleButtonSize,onclick:function(){promptText(JSON.stringify(self.saveableData),true);}})]), createElement("div",{className:"indent littleButton oddBlue", title:"Convert To Rule"},[ createElement("img",{className:"resourceIcon exportGrab"+WM.opts.littleButtonSize,onclick:function(){self.convertToRule();}})]), createElement("div",{className:"indent littleButton "+((this.isGlobal)?"oddOrange":"oddGreen"), title:((this.isGlobal)?"Disable Profile Sharing":"Share With Other Profiles")},[ this.toggleGlobalButton=createElement("img",{className:"resourceIcon "+((this.isGlobal)?"removeGlobal":"addGlobal")+WM.opts.littleButtonSize,onclick:function(){self.isGlobal=!self.isGlobal; WM.grabber.save();}})]), ]), this.contentNode=createElement("div",{className:"subsection "+(this.expanded?"expanded":"collapsed")},[ //appID createElement("div",{className:"line"},[ createElement("label",{textContent:"appID:"}), this.appIDNode=createElement("input",{value:(this.appID||""), onchange:function(){self.appID=this.value;WM.grabber.save();self.populateBonusList();}}), this.appListNode=createElement("select",{onchange:function(){self.appIDNode.value=this.value; self.appID=this.value; WM.grabber.save(); self.populateBonusList();}}), createElement("div",{className:"littleButton oddBlue", title:"Refresh App List"},[ createElement("img",{className:"resourceIcon refresh"+WM.opts.littleButtonSize,onclick:function(){self.populateAppList();}})]), ]), //return type createElement("div",{className:"line"},[ createElement("label",{textContent:"Return Type ('which'):"}), this.retNode=createElement("input",{value:(this.ret||"dynamic"), onchange:function(){self.ret=this.value;WM.grabber.save();}}), this.bonusNode=createElement("select",{onchange:function(){self.retNode.value=this.value; self.ret=this.value; WM.grabber.save();}}), createElement("div",{className:"littleButton oddBlue", title:"Refresh Bonus List"},[ createElement("img",{className:"resourceIcon refresh"+WM.opts.littleButtonSize,onclick:function(){self.populateBonusList();}})]), ]), //search list createElement("div",{className:"line"},[ createElement("label",{textContent:"Search In Field(s):",title:"Specify fields in which to look for data. Adjust order as needed."}), this.searchNode=createElement("div",{className:"subsection optioncontainer"},(function(){ var ret=[]; //draw first the methods we have already selected if (isArrayAndNotEmpty(self.search)) for (var m=0; m<self.search.length; m++) { var s = self.search[m]; ret.push(createElement("div",{className:"line"},[ createElement("div",{className:"littleButton oddGreen", title:"Move Up"},[ createElement("img",{className:"resourceIcon nomargin arrowUp16",onclick:function(){elementMoveUp(this.parentNode.parentNode); self.calcSearch();}}) ]), createElement("div",{className:"littleButton oddOrange", title:"Move Down"},[ createElement("img",{className:"resourceIcon nomargin arrowDown16",onclick:function(){elementMoveDown(this.parentNode.parentNode); self.calcSearch();}}) ]), createElement("div",{className:"littleButton oddGreen", title:"Move To Top"},[ createElement("img",{className:"resourceIcon nomargin moveTopLeft16",onclick:function(){elementMoveTop(this.parentNode.parentNode); self.calcSearch();}}) ]), createElement("div",{className:"littleButton oddOrange", title:"Move To Bottom"},[ createElement("img",{className:"resourceIcon nomargin moveBottomLeft16",onclick:function(){elementMoveBottom(this.parentNode.parentNode); self.calcSearch();}}) ]), createElement("input",{type:"checkbox",value:s,checked:true,onchange:function(){self.calcSearch();}}), createElement("label",{textContent:s,title:WM.rulesManager.postParts[s]}), ])); } //draw the remaining items in their normal order for (var m=0; m<WM.grabber.methods.length; m++){ var s = WM.grabber.methods[m]; //prevent duplicates if (self.search.inArray(s)) continue; ret.push(createElement("div",{className:"line"},[ createElement("div",{className:"littleButton oddGreen", title:"Move Up"},[ createElement("img",{className:"resourceIcon nomargin arrowUp16",onclick:function(){elementMoveUp(this.parentNode.parentNode); self.calcSearch();}}) ]), createElement("div",{className:"littleButton oddOrange", title:"Move Down"},[ createElement("img",{className:"resourceIcon nomargin arrowDown16",onclick:function(){elementMoveDown(this.parentNode.parentNode); self.calcSearch();}}) ]), createElement("div",{className:"littleButton oddGreen", title:"Move To Top"},[ createElement("img",{className:"resourceIcon nomargin moveTopLeft16",onclick:function(){elementMoveTop(this.parentNode.parentNode); self.calcSearch();}}) ]), createElement("div",{className:"littleButton oddOrange", title:"Move To Bottom"},[ createElement("img",{className:"resourceIcon nomargin moveBottomLeft16",onclick:function(){elementMoveBottom(this.parentNode.parentNode); self.calcSearch();}}) ]), createElement("input",{type:"checkbox",value:s,onchange:function(){self.calcSearch();}}), createElement("label",{textContent:s,title:WM.rulesManager.postParts[s]}), ])); } return ret; })()), ]), //find mode createElement("div",{className:"line"},[ createElement("label",{textContent:"Find Mode:",title:"Choose the mode you will use to find text."}), this.findModeNode=createElement("select",{onchange:function(){self.findMode=this.value;}},[ createElement("option",{selected:(this.findMode=="basic"),value:"basic",textContent:"Basic",title:"Search for a list of words or phrases."}), createElement("option",{selected:(this.findMode=="subnumrange"),value:"subnumrange",textContent:"Number Range",title:"Search for a range of numbers using an insertion point '{%1}' in your find parameter."}), createElement("option",{selected:(this.findMode=="subtests"),value:"subtests",textContent:"Sub Tests",title:"Search for a list of words or phrases using an insertion point '{%1}' in your find parameter."}), createElement("option",{selected:(this.findMode=="regex"),value:"regex",textContent:"Registered Expression",title:"Search for complex phrases using a regular expression."}) ]), ]), //find list createElement("div",{className:"line"},[ createElement("label",{textContent:"Find:",title:"One per line (basic mode), or a single regular expression. First match is used, so mind the order."}), createElement("div",{className:"subsection"},[ this.findNode=createElement("textarea",{className:"fit",textContent:((this.findMode=="basic")?this.findArray.join("\n"):this.find), onchange:function(){ if (self.findMode=="basic") self.findArray=this.value.split("\n"); else self.find=this.value; WM.grabber.save(); }}), ]) ]), //subtests list this.subTestsBoxNode=createElement("div",{className:("line").toggleWordB(this.findMode!="subtests","hidden")},[ createElement("label",{textContent:"Subtest Texts:",title:"Provide text replacements for the insertion point. No regular expressions."}), createElement("div",{className:"subsection"},[ this.subTestsNode=createElement("textarea",{className:"fit",textContent:((isArray(this.subTests)?this.subTests.join("\n"):"")||""), onchange:function(){self.subTests=this.value.split("\n"); WM.grabber.save();}}), ]) ]), //subnumrange picker this.subNumRangeBoxNode=createElement("div",{className:("line").toggleWordB(this.findMode!="subnumrange","hidden")},[ createElement("label",{textContent:"Subtest Number Range:",title:"Provide a start and end range for the insertion point."}), this.subNumRangeLowNode=createElement("input",{value:this.subNumRange.low||0, onchange:function(){self.subNumRange.low=this.value; WM.grabber.save();}}), this.subNumRangeHighNode=createElement("input",{value:this.subNumRange.high||0, onchange:function(){self.subNumRange.high=this.value; WM.grabber.save();}}), ]), //kids subbox createElement("div",{className:"line"},[ createElement("label",{textContent:"Child Tests:",title:"Child tests are nested tests which are applied to matching posts at the same time the parent test is applied. Child rules can have different return values that override the parent return value."}), createElement("div",{className:"littleButton oddGreen",onclick:function(){self.addChild();},title:"Add Child"},[ createElement("img",{className:"resourceIcon plus"+WM.opts.littleButtonSize}), ]), this.kidsNode=createElement("div",{className:"subsection"}), ]), ]), ]) );}catch(e){log("WM.Test.init.drawTest: "+e);} //populate my bonus list this.populateAppList(); this.populateBonusList(); //list the kids for this test if (isArrayAndNotEmpty(params.kids)) for (var i=0,kid; (kid=params.kids[i]); i++) { this.addChild(kid); } return self; }catch(e){log("WM.Test.init: ")+e}}; })();