123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933 |
- //表现逻辑层的处理
- if (window.location.href.indexOf("backEndAddressServiceWrapper") >= 0) {
- throw "serviceGrid"; //如果是服务器网页页面,则不执行工具
- }
- //Vueelement
- var app;
- generateToolkit();
- //生成Toolkit
- function generateToolkit() {
- $(".tooltips").html(`
- <div id="realcontent">
- <div class="tooldrag">✍Operation Toolbox (Can drag)</div>
- <div class="realcontent">
- <div v-if="page==0">
- <input type="checkbox" style="width:15px;height:15px;vertical-align:middle;" v-on:mousedown="specialSelect"> </input>
- <p style="margin-bottom:10px;display:inline-block">Special click mode</p>
- <div v-if="list.nl.length==0">
- <p style="color:black">● When your mouse moves to the element, please use your<strong>right mouse button</strong>or<strong>F7</strong> on the keyboard to select it.</p>
- <p style="color:black">● You can click the back button to go back to the page</p>
- {{initial()}}
- </div>
- <div v-if="list.nl.length==1">
- <div v-if="tname()!='null'">
- ● Already selected {{numOfList()}} {{tname()}},<span v-if="numOfReady()>0&&tname()!='Elements in next page'">, meanwhile we find {{numOfReady()}} element with the same type, </span>you can:
- <div class="innercontent">
- <div v-if="numOfReady()>0 && !selectStatus"> <a v-on:mousedown="selectAll">Select All</a> <span title="">☺</span></div>
- <div v-if="existDescendents()&& !selectStatus &&(tname()=='element' || tname()=='link')"> <a v-on:mousedown="selectDescendents">Select child elements</a> <span title="">☺</span></div>
- <div v-if="!selectedDescendents && !selectStatus" id="Single">
- <div v-if="tname()=='selection box'"> <a>---------</a><span title="">☺</span></div>
- <div v-if="tname()=='text box'"> <a v-on:mousedown="setInput">Input Text</a><span title="">☺</span></div>
- <div v-if="tname()!='Image'"> <a v-on:mousedown="getText">Collect {{tname()}}'s text</a><span title="collet text">☺</span></div>
- <div v-if="tname()=='selection box'"> <a>采集选中项的text</a><span title="">☺</span></div>
- <div v-if="tname()=='link'||tname()=='Image'"> <a v-on:mousedown="getLink">采集该{{tname()}}的Address</a><span title="">☺</span></div>
- <div v-if="tname()!='selection box' && tname()!='text box'"> <a v-on:mousedown="clickElement">点击该{{tname()}}</a><span title="">☺</span></div>
- <div v-if="tname()!='selection box' && tname()!='text box'"> <a v-on:mousedown="loopClickSingleElement">循环点击该{{tname()}}</a><span title="">☺</span></div>
- <div v-if="tname()=='link'||tname()=='element'"> <a v-on:mousedown="getInnerHtml">采集该{{tname()}}的Inner Html</a><span title="">☺</span></div>
- <div> <a v-on:mousedown="getOuterHtml">采集该{{tname()}}的Outer Html</a><span title="">☺</span></div>
- <div> <a href="#">----{{tname()}}-</a><span title="">☺</span></div>
- <div v-if="tname()=='text box'"> <a>-----</a><span title="">☺</span></div>
- </div>
- <div v-if="selectedDescendents" id="Single">
- <div><a v-on:mousedown="confirmCollectSingle">Collect Data</a><span title="">☺</span></div>
- </div>
- <div v-if="selectStatus" id="Confirm">
- <div><a v-on:mousedown="confirmCollectSingle">Confirm Collect</a><span title="">☺</span></div>
- </div>
- </div>
- </div>
- </div>
- <div v-if="list.nl.length>1">
- <div v-if="option==100">
- ● 已select了以下element,您可以:
- <div class="innercontent">
- <div> <a v-on:mousedown="confirmCollectMulti">采集数据</a><span title="">☺</span> </div>
- <div> <a v-on:mousedown="revoke">撤销本次selection</a><span title="">☺</span></div>
- </div>
- </div>
- <div v-if="option!=100">
- ● 已select了{{numOfList()}}个同类element,<span v-if="numOfReady()>0">另外发现{{numOfReady()}}个同类element,</span>您可以:
- <div class="innercontent">
- <div v-if="numOfReady()>0"> <a v-on:mousedown="selectAll">选中全部</a><span title="">☺</span></div>
- <div v-if="existDescendents()&&(tname()=='element' || tname()=='link')"> <a v-on:mousedown="selectDescendents">选中子element</a><span title="">☺</span></div>
- <div> <a v-on:mousedown="confirmCollectMultiAndDescendents">采集数据</a><span title="">☺</span></div>
- <div v-if="tname()!='selection box' && tname()!='text box' && !selectedDescendents"> <a v-on:mousedown="loopClickEveryElement">循环点击每个{{tname()}}</a><span title="">☺</span></div>
- <div> <a v-on:mousedown="revoke">撤销本次selection</a><span title="">☺</span></div>
- </div>
- </div>
-
- </div>
- <div v-if="valTable.length>0">
- <div class="toolkitcontain">{{setWidth("290px")}}
- <table class="toolkittb2" cellspacing="0">
- <tbody>
- <th v-for="i in list.opp">{{i["name"]}}</th>
- <th style="width:40px">删除</td>
- </tbody>
- </table>
- <table class="toolkittb4" cellspacing="0">
- <tbody>
- <tr v-for="i in valTable[0].length">
- <td v-for="j in list.opp.length">{{valTable[j-1][i-1]}}</td>
- <td v-on:mousedown="deleteSingleLine" style="font-size: 22px!important;width:40px;cursor:pointer" v-bind:index="i-1">×</td>
- </tr>
- </table>
- </div>
- </div>
-
- <div v-if="valTable.length==0&&tname()!='Elements in next page'">{{setWidth("230px")}}</div>
- <div v-if="list.nl.length>0" style="bottom:12px;position:absolute;color:black!important;left:17px;font-size:13px">
- <div style="margin-bottom:5px">
- <button v-on:mousedown="cancel">取消selection</button>
- <button v-if="!selectStatus" v-on:mousedown="enlarge">扩大选区</button>
- </div>
- <p style="margin-left:16px;margin-bottom:0px">{{lastElementXPath()}}</p>
- </div>
- </div>
- <div v-if="page==1">
- ● 请输入文字:
- <input type="text" v-model="text" autofocus="autofocus" id="WTextBox"></input>
- <button v-on:click="getInput" style="margin-left:0px!important;">确定</button>
- <button v-on:click="cancelInput" style="margin-left:0px!important;">取消</button>
- <div class="innercontent">
- </div>
- </div>
- </div>
- `);
- app = new Vue({
- el: '#realcontent',
- data: {
- option: 0,
- list: { nl: nodeList, opp: outputParameters },
- valTable: [], // 用来存储转换后的para列表
- special: false, //是否为特殊selection模式
- selectedDescendents: false, // 标记是否选中了子element
- selectStatus: false, //标记单个element是否点击了采集
- page: 0, //默认页面,1为输入文字页面
- text: "", // 记录输入的文字
- tNodeName: "", // 记录临时节点列表
- nowPath: "", //现在element的xpath
- },
- watch: {
- nowPath: { //变量发生变化的时候进行一些操作
- handler: function(newVal, oldVal) {
- console.log("xpath:", newVal);
- }
- }
- },
- methods: {
- initial: function() { //每当element是0的时候,执行值的初始化操作
- this.selectedDescendents = false;
- this.selectStatus = false;
- this.nowPath = "";
- },
- confirmCollectSingle: function() { //单element确认采集
- collectSingle();
- clearEl();
- },
- confirmCollectMulti: function() { //无规律多element确认采集
- collectMultiNoPattern();
- clearEl();
- },
- confirmCollectMultiAndDescendents: function() { //有规律多element确认采集
- collectMultiWithPattern();
- clearEl();
- },
- deleteSingleLine: function(event) { //删除单行element
- let at = new Date().getTime()
- //流程图送element的时候,默认的使用不固定循环列表,但是一旦有删除element的操作发生,则按照固定element列表采集element
- index = event.target.getAttribute("index");
- let tnode = nodeList.splice(index, 1)[0]; //删掉当前element
- tnode["node"].style.backgroundColor = tnode["bgColor"];
- tnode["node"].style.boxShadow = tnode["boxShadow"];
- if (nodeList.length > 1) { // 如果删到没有就没有其他的操作了
- handleElement();
- if (this.selectedDescendents) {
- handleDescendents(); //如果之前有选中子element,新加入的节点又则这里也需要重新selection子element
- }
- } else {
- this.valTable = [];
- this.selectStatus = false;
- clearParameters(); //直接撤销重选
- }
- let at2 = parseInt(new Date().getTime());
- console.log("delete:", at2, at, at2 - at);
- },
- clickElement: function() { //点击element操作
- sendSingleClick();
- //先发送数据
- nodeList[0]["node"].focus(); //获得element焦点
- nodeList[0]["node"].click(); //点击element
- clearEl();
- },
- loopClickSingleElement: function() { //循环点击单个element
- sendLoopClickSingle(this.tname()); //识别下一页,循环点击单个element和点击多个element
- if (this.tname() != "Elements in next page") { //Elements in next page不进行点击操作
- nodeList[0]["node"].focus(); //获得element焦点
- nodeList[0]["node"].click(); //点击element
- }
- clearEl();
- },
- loopClickEveryElement: function() { //循环点击每个element
- sendLoopClickEvery(); //识别下一页,循环点击单个element和点击多个element
- nodeList[0]["node"].focus(); //获得element焦点
- nodeList[0]["node"].click(); //点击element
- clearEl();
- },
- setInput: function() { //输入文字
- this.page = 1;
- this.$nextTick(function() { //下一时刻获得焦点
- document.getElementById("WTextBox").focus();
- })
- },
- getInput: function() { //得到输入的文字
- nodeList[0]["node"].focus(); //获得文字焦点
- // nodeList[0]["node"].setAttribute("value", this.text); // 设置输入 box内容
- input(this.text); // 设置输入
- this.text = "";
- clearEl();
- },
- cancelInput: function() {
- this.page = 0;
- },
- setWidth: function(width) { //根据是否出现表格调整最外 box宽度
- $(".tooltips").css("width", width);
- return "";
- },
- getText: function() { //采集文字
- generateParameters(0, true, false);
- this.selectStatus = true;
- clearReady();
- },
- getLink: function() { //采集linkAddress
- generateParameters(0, false, true);
- this.selectStatus = true;
- clearReady();
- },
- getOuterHtml: function() { //采集OuterHtml
- generateParameters(3, true, false);
- this.selectStatus = true;
- clearReady();
- },
- getInnerHtml: function() { //采集InnerHtml
- generateParameters(2, true, false);
- this.selectStatus = true;
- clearReady();
- },
- tname: function() {
- let tag = nodeList.length == 0 ? "" : nodeList[0]["node"].tagName;
- let inputType = nodeList.length == 0 ? "" : nodeList[0]["node"].getAttribute("type");
- if (inputType != null) { //如果没有type属性,则默认为text
- inputType = inputType.toLowerCase();
- } else {
- inputType = "text";
- }
- if (tag == "") {
- return "null";
- } else if ($(nodeList[0]["node"]).contents().filter(function() { return this.nodeType === 3; }).text().indexOf("下一页") >= 0) {
- this.setWidth("250px");
- return "Elements in next page";
- } else if (tag == "A") {
- return "link";
- } else if (tag == "IMG") {
- return "Image";
- } else if (tag == "BUTTON" || (tag == "INPUT" && (inputType == "button" || inputType == "submit"))) {
- return "Button";
- } else if (tag == "TEXTAREA" || (tag == "INPUT" && (inputType != "checkbox" || inputType != "ratio"))) { //普通输入 box
- return "text box";
- } else if (tag == "SELECT") {
- return "selection box";
- } else {
- return "element";
- }
- },
- existDescendents: function() { //检测选中的element是否存在子element,已经选中了子element也不要再出现了
- return nodeList.length > 0 && nodeList[0]["node"].children.length > 0 && !this.selectedDescendents;
- },
- numOfReady: function() {
- return readyList.length;
- },
- numOfList: function() {
- return nodeList.length;
- },
- lastElementXPath: function() { //用来显示element的最大最后5个xpath路劲element
- path = nodeList[nodeList.length - 1]["xpath"];
- path = path.split("/");
- tp = "";
- if (path.length > 5) { //只保留最后五个element
- path = path.splice(path.length - 5, 5);
- tp = ".../"
- }
- for (i = 0; i < path.length; i++) {
- path[i] = path[i].split("[")[0];
- }
- path = path.join("/");
- path = "Path: " + tp + path;
- return path;
- },
- cancel: function() {
- clearEl();
- },
- specialSelect: function() { //特殊selection模式
- if (mousemovebind) {
- tdiv.style.pointerEvents = "none";
- this.special = false;
- } else {
- this.special = true;
- }
- mousemovebind = !mousemovebind;
- },
- enlarge: function() { // 扩大选区功能,总是扩大最后一个选中的element的选区
- if (nodeList[nodeList.length - 1]["node"].tagName != "BODY") {
- nodeList[nodeList.length - 1]["node"].style.backgroundColor = nodeList[nodeList.length - 1]["bgColor"]; //之前element恢复原来的背景颜色
- nodeList[nodeList.length - 1]["node"].style.boxShadow = nodeList[nodeList.length - 1]["boxShadow"]; //之前element恢复原来的背景颜色
- tNode = nodeList[nodeList.length - 1]["node"].parentNode; //向上走一层
- if (tNode != NowNode) { //扩大选区之后背景颜色的判断,当前正好选中的颜色应该是不同的
- sty = tNode.style.backgroundColor;
- } else {
- sty = style;
- }
- nodeList[nodeList.length - 1]["node"] = tNode;
- nodeList[nodeList.length - 1]["bgColor"] = sty;
- nodeList[nodeList.length - 1]["xpath"] = readXPath(tNode, 1);
- //显示 box
- var pos = tNode.getBoundingClientRect();
- div.style.display = "block";
- div.style.height = tNode.offsetHeight + "px";
- div.style.width = tNode.offsetWidth + "px";
- div.style.left = pos.left + "px";
- div.style.top = pos.top + "px";
- div.style.zIndex = 2147483645;
- div.style.pointerEvents = "none";
- handleElement(); //每次数组element有变动,都需要重新处理下
- oe = tNode;
- tNode.style.backgroundColor = "rgba(0,191,255,0.5)";
- this.selectedDescendents = false;
- }
- },
- selectAll: function() { //选中全部element
- step++;
- readyToList(step, false);
- handleElement();
- if (this.selectedDescendents) {
- handleDescendents(); //如果之前有选中子element,新加入的节点又则这里也需要重新selection子element
- }
- },
- revoke: function() { //撤销selection当前节点
- var tstep = step;
- step--; //步数-1
- while (tstep == nodeList[nodeList.length - 1]["step"]) //删掉所有当前步数的element节点
- {
- let node = nodeList.splice(nodeList.length - 1, 1)[0]; //删除数组最后一项
- node["node"].style.backgroundColor = node["bgColor"]; //还原原始属性和边 box
- node["node"].style.boxShadow = node["boxShadow"];
- if (NowNode == node["node"]) {
- style = node["bgColor"];
- }
- //处理已经有选中子element的情况
- // if (this.selectedDescendents) {
- clearParameters(); //直接撤销重选
- // }
- }
- handleElement(); //每次数组element有变动,都需要重新处理下
- },
- selectDescendents: function() { //selection所有子element操作
- handleDescendents();
- }
- },
- });
- h = $(".tooldrag").height();
- difference = 26 - h; //获得高度值差
- if (difference > 0) {
- $(".tooldrag").css("cssText", "height:" + (26 + difference) + "px!important")
- }
- timer = setInterval(function() { //时刻监测相应element是否存在(防止出现如百度一样element消失重写body的情况),如果不存在,添加进来
- if (document.body != null && document.getElementById("wrapperToolkit") == null) {
- this.clearInterval(); //先取消原来的计时器,再设置新的计时器
- document.body.append(div); //默认如果toolkit不存在则div和tdiv也不存在
- document.body.append(tdiv);
- document.body.append(toolkit);
- generateToolkit();
- // var list = document.getElementsByTagName("a");
- // // 对于没有特殊绑定函数的a标签,使他们在新标签页中打开
- // for (var i = 0; i < list.length; i++) {
- // if (list[i].href.indexOf("javascript") == -1 && list[i].href.indexOf("void") == -1 && list[i].href.indexOf("#") == -1 && list[i].href) {
- // list[i].setAttribute("target", "_blank");
- // }
- // };
- // list = document.getElementsByTagName("form");
- // // 对于没有特殊绑定函数的form标签,使他们在新标签页中打开
- // for (var i = 0; i < list.length; i++) {
- // list[i].setAttribute("target", "_blank");
- // };
- }
- }, 3000);
- }
- //每次对element进行增删之后需要执行的操作
- function handleElement() {
- clearReady(); //预备element每次处理都先处理掉
- if (nodeList.length > 1) { //选中了许多element的情况
- app._data.option = relatedTest();
- if (app._data.option == 100) {
- generateMultiParameters();
- } else {
- generateParameters(0);
- }
- } else if (nodeList.length == 1) {
- findRelated(); //寻找和element相关的element
- }
- }
- function clearParameters(deal = true) //清空para列表
- {
- if (deal) //是否取消对选中的子element进行处理
- {
- app._data.selectedDescendents = false;
- }
- for (o of outputParameterNodes) {
- o["node"].style.boxShadow = o["boxShadow"];
- }
- outputParameterNodes.splice(0);
- outputParameters.splice(0); //清空原来的para列表
- app._data.valTable = []; //清空展现数组
- app._data.selectStatus = false;
- }
- //根据nodelist列表内的element生成para列表
- //适合:nodelist中的element为同类型element
- //type:0为全部text 1为节点内直接的文字 2为innerhtml 3为outerhtml
- //nodetype:0,对应全type0123
- //nodetype:1 link,对应type0123
- //nodetype:2 linkAddress 对应type0
- //nodetype:3 按钮和输入text box 对应type
- //nodetype:4 按钮和输入text box 对应type
- function generateParameters(type, linktext = true, linkhref = true) {
- clearParameters(false);
- let n = 1;
- chrome.storage.local.get({ parameterNum: 1 }, function(items) {
- let at = parseInt(new Date().getTime());
- n = items.parameterNum;
- for (let num = 0; num < nodeList.length; num++) {
- let nd = nodeList[num]["node"];
- ndPath = nodeList[num]["xpath"];
- outputParameterNodes.push({ "node": nd, "boxShadow": nd.style.boxShadow == "" || boxShadowColor ? "none" : nd.style.boxShadow });
- nd.style.boxShadow = boxShadowColor;
- let pname = "text";
- let ndText = "";
- if (type == 0) {
- ndText = $(nd).text();
- pname = "text";
- if (nd.tagName == "IMG") {
- ndText = nd.getAttribute("src") == null ? "" : $(nd).prop("src");
- pname = "Address";
- } else if (nd.tagName == "INPUT") {
- ndText = nd.getAttribute("value") == null ? "" : nd.getAttribute("value");
- }
- } else if (type == 1) {
- ndText = $(nd).contents().filter(function() { return this.nodeType === 3; }).text().replace(/\s+/g, '');
- pname = "text";
- if (nd.tagName == "IMG") {
- ndText = nd.getAttribute("src") == null ? "" : $(nd).prop("src");
- pname = "Address";
- } else if (nd.tagName == "INPUT") {
- ndText = nd.getAttribute("value") == null ? "" : nd.getAttribute("value");
- }
- } else if (type == 2) {
- ndText = $(nd).html();
- pname = "Innerhtml";
- } else if (type == 3) {
- ndText = $(nd).prop("outerHTML");
- pname = "outerHTML";
- }
- if (num == 0) { //第一个节点新建,后面的增加即可
- if (nd.tagName == "IMG") { //如果element是Image
- outputParameters.push({
- "nodeType": 4, //节点类型
- "contentType": type, // 内容类型
- "relative": nodeList.length > 1 ? true : false, //是否为相对xpath路径
- "name": "para" + (n++) + "_Image" + pname,
- "desc": "", //para描述
- "relativeXpath": nodeList.length > 1 ? "" : ndPath,
- "exampleValues": [{ "num": num, "value": ndText }]
- });
- } else if (nd.tagName == "A") { //如果element是超link
- if (linktext) {
- outputParameters.push({
- "nodeType": 1,
- "contentType": type, // 内容类型
- "relative": nodeList.length > 1 ? true : false, //是否为相对xpath路径
- "name": "para" + (n++) + "_link" + pname,
- "desc": "", //para描述
- "relativeXpath": nodeList.length > 1 ? "" : ndPath,
- "exampleValues": [{ "num": num, "value": ndText }]
- });
- }
- if (linkhref) {
- outputParameters.push({
- "nodeType": 2,
- "contentType": type, // 内容类型
- "relative": nodeList.length > 1 ? true : false, //是否为相对xpath路径
- "name": "para" + (n++) + "_linkAddress",
- "desc": "", //para描述
- "relativeXpath": nodeList.length > 1 ? "" : ndPath,
- "exampleValues": [{ "num": num, "value": nd.getAttribute("href") == null ? "" : $(nd).prop("href") }]
- });
- }
- } else if (nd.tagName == "INPUT") { //如果element是输入项
- outputParameters.push({
- "nodeType": 3,
- "contentType": type, // 内容类型
- "relative": nodeList.length > 1 ? true : false, //是否为相对xpath路径
- "name": "para" + (n++) + "_" + pname,
- "desc": "", //para描述
- "relativeXpath": nodeList.length > 1 ? "" : ndPath,
- "exampleValues": [{ "num": num, "value": ndText }]
- });
- } else { //其他所有情况
- outputParameters.push({
- "nodeType": 0,
- "contentType": type, // 内容类型
- "relative": nodeList.length > 1 ? true : false, //是否为相对xpath路径
- "name": "para" + (n++) + "_" + pname,
- "desc": "", //para描述
- "relativeXpath": nodeList.length > 1 ? "" : ndPath,
- "exampleValues": [{ "num": num, "value": ndText }]
- });
- }
- } else { //如果element节点已经存在,则只需要插入值就可以了
- if (nd.tagName == "IMG") { //如果element是Image
- outputParameters[0]["exampleValues"].push({ "num": num, "value": ndText });
- } else if (nd.tagName == "A") { //如果element是超link
- outputParameters[0]["exampleValues"].push({ "num": num, "value": ndText });
- outputParameters[1]["exampleValues"].push({ "num": num, "value": nd.getAttribute("href") == null ? "" : $(nd).prop("href") });
- } else if (nd.tagName == "INPUT") { //如果element是输入项
- outputParameters[0]["exampleValues"].push({ "num": num, "value": ndText });
- } else { //其他所有情况
- outputParameters[0]["exampleValues"].push({ "num": num, "value": ndText });
- }
- }
- }
- let at2 = parseInt(new Date().getTime());
- console.log("generateParameters:", at2, at, at2 - at);
- generateValTable();
- console.log(outputParameters);
- });
- }
- //根据nodelist列表内的element生成para列表
- //适合:nodelist中的element为不同类型element
- function generateMultiParameters() {
- clearParameters(false);
- let n = 1;
- chrome.storage.local.get({ parameterNum: 1 }, function(items) {
- let at = parseInt(new Date().getTime());
- n = items.parameterNum;
- for (let num = 0; num < nodeList.length; num++) {
- let nd = nodeList[num]["node"];
- ndPath = nodeList[num]["xpath"];
- outputParameterNodes.push({ "node": nd, "boxShadow": nd.style.boxShadow == "" || boxShadowColor ? "none" : nd.style.boxShadow });
- nd.style.boxShadow = boxShadowColor;
- ndText = $(nd).text();
- if (nd.tagName == "IMG") { //如果element是Image
- outputParameters.push({
- "nodeType": 4, //节点类型
- "contentType": 0, // 内容类型
- "relative": false, //是否为相对xpath路径
- "name": "para" + (n++) + "_imageAddress",
- "desc": "", //para描述
- "relativeXpath": ndPath,
- "exampleValues": [{ "num": 0, "value": nd.getAttribute("src") == null ? "" : $(nd).prop("src") }]
- });
- } else if (nd.tagName == "A") { //如果element是超link
- outputParameters.push({
- "nodeType": 1,
- "contentType": 0, // 内容类型
- "relative": false, //是否为相对xpath路径
- "name": "para" + (n++) + "_linktext",
- "desc": "", //para描述
- "relativeXpath": ndPath,
- "exampleValues": [{ "num": 0, "value": ndText }]
- });
- outputParameters.push({
- "nodeType": 2,
- "contentType": 0, // 内容类型
- "relative": false, //是否为相对xpath路径
- "name": "para" + (n++) + "_linkAddress",
- "desc": "", //para描述
- "relativeXpath": ndPath,
- "exampleValues": [{ "num": 0, "value": nd.getAttribute("href") == null ? "" : $(nd).prop("href") }]
- });
- } else if (nd.tagName == "INPUT") { //如果element是输入项
- outputParameters.push({
- "nodeType": 3,
- "contentType": 0, // 内容类型
- "relative": false, //是否为相对xpath路径
- "name": "para" + (n++) + "_text",
- "desc": "", //para描述
- "relativeXpath": ndPath,
- "exampleValues": [{ "num": 0, "value": nd.getAttribute("value") == null ? "" : nd.getAttribute("value") }]
- });
- } else { //其他所有情况
- outputParameters.push({
- "nodeType": 0,
- "contentType": 0, // 内容类型
- "relative": false, //是否为相对xpath路径
- "name": "para" + (n++) + "_text",
- "desc": "", //para描述
- "relativeXpath": ndPath,
- "exampleValues": [{ "num": 0, "value": ndText }]
- });
- }
- }
- // console.log(outputParameters);
- let at2 = parseInt(new Date().getTime());
- console.log("generateMultiParameters", at2, at, at2 - at);
- generateValTable(false);
- });
- }
- //处理子element,对于每个块中多出的特殊element,需要特殊处理
- function handleDescendents() {
- let n = 1;
- chrome.storage.local.get({ parameterNum: 1 }, function(items) {
- let at = parseInt(new Date().getTime());
- n = items.parameterNum;
- clearParameters(); //清除原来的para列表
- app._data.selectedDescendents = true;
- for (let num = 0; num < nodeList.length; num++) {
- let tnode = nodeList[num]["node"];
- let stack = new Array(); //深度优先搜索遍历element
- stack.push(tnode); //从此节点开始
- while (stack.length > 0) {
- let nd = stack.pop(); // 挨个取出element
- if (nd.parentNode.tagName == "A" && nd.tagName == "SPAN") {
- continue; //对A标签内的SPANelement不进行处理,剪枝,此时子element根本不加入stack,即实现了此功能
- }
- ndPath = readXPath(nd, 1, tnode);
- let index = -1;
- for (let i = 0; i < outputParameters.length; i++) {
- if (outputParameters[i]["relativeXpath"] == ndPath) {
- index = i;
- break;
- }
- }
- outputParameterNodes.push({
- "node": nd,
- "boxShadow": nd.style.boxShadow == "" || boxShadowColor ? "none" : nd.style.boxShadow
- });
- nd.style.boxShadow = boxShadowColor;
- ndText = $(nd).contents().filter(function() {
- return this.nodeType === 3;
- }).text().replace(/\s+/g, '');
- if (index == -1) { //从第二个节点开始,只插入那些不在para列表中的element,根据xpath进行寻址
- //如果当前节点除了子element外仍然有其他文字或者该element是Image/表单项,加入子element节点
- if (ndText != "" || nd.tagName == "IMG" || nd.tagName == "INPUT" || nd.tagName == "A") {
- if (nd.tagName == "IMG") { //如果element是Image
- outputParameters.push({
- "nodeType": 4, //节点类型
- "contentType": 1, // 内容类型
- "relative": nodeList.length > 1 ? true : false, //是否为相对xpath路径,注意当只selection了子element没有选中全部的时候,需要判断
- "name": "para" + (n++) + "_imageAddress",
- "desc": "", //para描述
- "relativeXpath": nodeList.length > 1 ? ndPath : readXPath(nd), //同理需要判断
- "exampleValues": [{
- "num": num,
- "value": nd.getAttribute("src") == null ? "" : $(nd).prop("src")
- }]
- });
- } else if (nd.tagName == "A") { //如果element是超link
- outputParameters.push({
- "nodeType": 1,
- "contentType": 0, // 内容类型
- "relative": nodeList.length > 1 ? true : false, //是否为相对xpath路径
- "name": "para" + (n++) + "_linktext",
- "desc": "", //para描述
- "relativeXpath": nodeList.length > 1 ? ndPath : readXPath(nd),
- "exampleValues": [{ "num": num, "value": $(nd).text() }] //注意这里的ndtext是整个a的文字!!!
- });
- outputParameters.push({
- "nodeType": 2,
- "contentType": 0, // 内容类型
- "relative": nodeList.length > 1 ? true : false, //是否为相对xpath路径
- "name": "para" + (n++) + "_linkAddress",
- "desc": "", //para描述
- "relativeXpath": nodeList.length > 1 ? ndPath : readXPath(nd),
- "exampleValues": [{
- "num": num,
- "value": nd.getAttribute("href") == null ? "" : $(nd).prop("href")
- }]
- });
- } else if (nd.tagName == "INPUT") { //如果element是输入项
- outputParameters.push({
- "nodeType": 3,
- "contentType": 1, // 内容类型
- "relative": nodeList.length > 1 ? true : false, //是否为相对xpath路径
- "name": "para" + (n++) + "_text",
- "desc": "", //para描述
- "relativeXpath": nodeList.length > 1 ? ndPath : readXPath(nd),
- "exampleValues": [{
- "num": num,
- "value": nd.getAttribute("value") == null ? "" : nd.getAttribute("value")
- }]
- });
- } else { //其他所有情况
- outputParameters.push({
- "nodeType": 0,
- "contentType": 1, // 内容类型
- "relative": nodeList.length > 1 ? true : false, //是否为相对xpath路径
- "name": "para" + (n++) + "_text",
- "desc": "", //para描述
- "relativeXpath": nodeList.length > 1 ? ndPath : readXPath(nd),
- "exampleValues": [{ "num": num, "value": ndText }]
- });
- }
- }
- } else //如果element节点已经存在,则只需要插入值就可以了
- {
- if (nd.tagName == "IMG") { //如果element是Image
- outputParameters[index]["exampleValues"].push({
- "num": num,
- "value": nd.getAttribute("src") == null ? "" : $(nd).prop("src")
- });
- } else if (nd.tagName == "A") { //如果element是超link
- outputParameters[index]["exampleValues"].push({ "num": num, "value": $(nd).text() });
- outputParameters[index + 1]["exampleValues"].push({
- "num": num,
- "value": nd.getAttribute("href") == null ? "" : $(nd).prop("href")
- });
- } else if (nd.tagName == "INPUT") { //如果element是输入项
- outputParameters[index]["exampleValues"].push({
- "num": num,
- "value": nd.getAttribute("value") == null ? "" : nd.getAttribute("value")
- });
- } else { //其他所有情况
- outputParameters[index]["exampleValues"].push({ "num": num, "value": ndText });
- }
- }
- for (let i = nd.children.length - 1; i >= 0; i--) {
- stack.push(nd.children[i]);
- }
- }
- }
- let at2 = parseInt(new Date().getTime());
- console.log("选中子element", at2, at, at2 - at);
- generateValTable();
- });
- }
- //根据para列表生成可视化para界面
- function generateValTable(multiline = true) {
- let paravalues = [];
- for (let i = 0; i < outputParameters.length; i++) {
- let tvalues = [];
- let tindex = 0;
- let l = multiline ? nodeList.length : 1;
- for (let j = 0; j < l; j++) {
- //注意第一个循环条件,index超出界限了就不需要再寻找了,其他的全是空
- if (tindex < outputParameters[i]["exampleValues"].length && outputParameters[i]["exampleValues"][tindex]["num"] == j) {
- tvalues.push(outputParameters[i]["exampleValues"][tindex]["value"]);
- tindex++;
- } else {
- tvalues.push(" ");
- }
- }
- paravalues.push(tvalues);
- }
- app._data.valTable = paravalues;
- }
- // 选中第一个节点,自动寻找同类节点
- // 方法:/div[1]/div[2]/div[2]/a[1]
- // 从倒数第一个节点开始找,看去掉方括号之后是否element数目变多,如上面的变成/div[1]/div[2]/div[2]/a
- // 如果没有,则恢复原状,然后试试倒数第二个:/div[1]/div[2]/div/a[1]
- // 直到找到第一个变多的节点或者追溯到根节点为止
- function findRelated() {
- let at = parseInt(new Date().getTime());
- let testPath = nodeList[0]["xpath"].split("/").splice(1); //分离xpath成 ["html","body","div[0]"]这样子
- let nodeNameList = [];
- let nodeIndexList = [];
- for (i = 0; i < testPath.length; i++) {
- nodeNameList.push(testPath[i].split("[")[0]);
- if (testPath[i].indexOf("[") >= 0) { //如果存在索引值
- nodeIndexList.push(parseInt(testPath[i].split("[")[1].replace("]", ""))); //只留下数字
- } else {
- nodeIndexList.push(-1);
- }
- }
- var tempPath = "";
- for (let i = nodeIndexList.length - 1; i >= 0; i--) {
- if (nodeIndexList[i] == -1) { //没有索引值直接跳过
- continue;
- }
- tempIndexList = [...nodeIndexList]; //复刻一个index数组
- tempIndexList[i] = -1; //删除索引值
- tempPath = combineXpath(nodeNameList, tempIndexList); //生成新的xpath
- var result = document.evaluate(tempPath, document, null, XPathResult.ANY_TYPE, null);
- result.iterateNext(); //枚举第一个element
- if (result.iterateNext() != null) { //如果能枚举到第二个element,说明存在同类element,选中同类element,结束循环
- app.$data.nowPath = tempPath; //标记此elementxpath
- pushToReadyList(tempPath);
- break;
- }
- }
- let at2 = parseInt(new Date().getTime());
- console.log("findRelated:", at2, at, at2 - at);
- }
- //根据path将element放入readylist中
- function pushToReadyList(path) {
- result = document.evaluate(path, document, null, XPathResult.ANY_TYPE, null);
- var node = result.iterateNext(); //枚举第一个element
- while (node) { //只添加不在已选中列表内的element
- let exist = false;
- for (o of nodeList) {
- if (o["node"] == node) {
- exist = true;
- break;
- }
- }
- if (!exist) {
- readyList.push({ "node": node, "bgColor": node.style.backgroundColor, "boxShadow": node.style.boxShadow == "" || boxShadowColor ? "none" : node.style.boxShadow });
- }
- node.style.boxShadow = boxShadowColor;
- node = result.iterateNext(); //枚举下一个element
- }
- }
- //将readyList中的element放入选中节点中
- function readyToList(step, dealparameters = true) {
- for (o of readyList) {
- nodeList.push({ node: o["node"], "step": step, bgColor: o["bgColor"], "boxShadow": o["boxShadow"], xpath: readXPath(o["node"], 1) });
- o["node"].style.backgroundColor = selectedColor;
- }
- clearReady();
- if (dealparameters) { //防止出现先选中子element再选中全部失效的问题
- generateParameters(0); //根据nodelist列表内的element生成para列表,0代表纯text
- }
- }
- //根据节点列表和索引列表生成XPATH
- // 如:["html","body","div"],[-1,-1,2],生成/html/body/div[2]
- function combineXpath(nameList, indexList) {
- let finalPath = "";
- for (i = 0; i < nameList.length; i++) {
- finalPath = finalPath + "/" + nameList[i];
- if (indexList[i] != -1) {
- finalPath = finalPath + "[" + indexList[i] + "]";
- }
- }
- return finalPath;
- }
- //专门测试已经选中的这些element之间有没有相关性
- // 举例:
- // /html/body/div[3]/div[1]/div[1]/div[1]/div[3]/div[1]/div[3]/a[22]
- // /html/body/div[3]/div[1]/div[1]/div[1]/div[3]/div[2]/div[3]/a[25]
- // 最终转换为:
- // /html/body/div[3]/div[1]/div[1]/div[1]/div[3]/div/div[3]/a
- function relatedTest() {
- let at = new Date().getTime()
- var testList = [];
- var testpath = "";
- for (i = 0; i < nodeList.length; i++) {
- var testnumList = []; //用于比较节点索引号不同
- var tpath = nodeList[i]["xpath"].split("/").splice(1); //清理第一个空element
- for (j = 0; j < tpath.length; j++) {
- if (tpath[j].indexOf("[") >= 0) { //如果存在索引值
- testnumList.push(parseInt(tpath[j].split("[")[1].replace("]", ""))); //只留下数字
- } else {
- testnumList.push(-1);
- }
- tpath[j] = tpath[j].split("[")[0];
- }
- tp = tpath.join("/");
- if (i > 0 && testpath != tp) { //如果去除括号后element内存在不一致情况,直接返回默认情况代码100
- app.$data.nowPath = ""; //标记此elementxpath
- return 100;
- }
- testpath = tp;
- testList.push(testnumList);
- }
- testpath = testpath.split("/"); //清理第一个空element
- var indexList = []; //记录新生成的xpath
- //如果选中的element属于同样的序列,则计算出序列的最佳xpath表达式
- for (j = 0; j < testList[0].length; j++) {
- indexList.push(testList[0][j]);
- for (i = 1; i < testList.length; i++) {
- if (testList[i][j] != testList[i - 1][j]) {
- indexList[j] = -1; //不一致就记录成-1
- break;
- }
- }
- }
- var finalPath = combineXpath(testpath, indexList);
- app.$data.nowPath = finalPath; //标记此elementxpath
- pushToReadyList(finalPath);
- let at2 = parseInt(new Date().getTime());
- console.log("手动:", at2, at, at2 - at);
- return 50; //先返回给默认码
- }
- //实现提示 box拖拽功能
- $('.tooldrag').mousedown(function(e) {
- // e.pageX
- var positionDiv = $(this).offset();
- var distanceX = e.pageX - positionDiv.left;
- var distanceY = e.pageY - positionDiv.top;
- //alert(distanceX)
- // alert(positionDiv.left);
- $(document).mousemove(function(e) {
- var x = e.clientX - distanceX;
- var y = e.clientY - distanceY;
- if (x < 0) {
- x = 0;
- } else if (x > window.innerWidth - $('.tooldrag').outerWidth(true)) {
- x = window.innerWidth - $('.tooldrag').outerWidth(true);
- }
- if (y < 0) {
- y = 0;
- } else if (y > window.innerHeight - $('.tooldrag').outerHeight(true)) {
- y = window.innerHeight - $('.tooldrag').outerHeight(true);
- }
- $('.tooltips').css({
- 'right': window.innerWidth - x - $('.tooltips').outerWidth(true) + 'px',
- 'bottom': window.innerHeight - y - $('.tooltips').outerHeight(true) + 'px',
- });
- });
- $(document).mouseup(function() {
- $(document).off('mousemove');
- });
- });
|