在一系列已打开的标签

时间:2015-07-14 17:45:59

标签: javascript tabs firefox-addon firefox-addon-sdk onsubmit

我正在制作一个实验插件,可以同时在几个不同的艺术网站上搜索一个单词。

插件的工作原理如下:

  1. 打开一个窗口,询问用户输入(要搜索的术语)
  2. 存储此输入
  3. 启动原始循环过程
  4. 循环打开列表中的第一个标签
  5. 循环附件运行列表中的第一个脚本 (这些脚本几乎都以相同的方式工作)
  6. 此脚本作为工作人员附加到选项卡
  7. 脚本将该术语输入选项卡中的搜索框,然后提交
  8. 提交触发工作人员被销毁
  9. 重复步骤4-8,直到列表用完要打开的列表 注意:这些步骤的数量与代码中的步骤编号
  10. 无关

    Main.js

    var data = require("sdk/self").data;
    var tabs = require("sdk/tabs");
    var journal_entry = require("sdk/panel").Panel({
      contentURL: data.url("DeltaLogPanel.html"),
      contentScriptFile: data.url("get-text.js")
    });
    // Creates the button
    require("sdk/ui/button/action").ActionButton({
      id: "make-post",
      label: "Make post",
      icon: {
        "16": "./icon-16.png",
        "32": "./icon-32.png",
        "64": "./icon-64.png"
      },
      onClick: handleClick
    });
    var count = 0;
    function handleClick(state) {
      journal_entry.show();
    }
    journal_entry.once("show", function() {
      journal_entry.port.emit("show");
    });
    function doit() {
        console.log("Step 1, loop "+ count +" started!");;
        if(count < sites.urls.length)
        {
            TabIt(count);
        }
        else
        {
            console.log("loop ended");
        }
    }
    function TabIt(x) {
        console.log("Step 2, tab "+ count +" is opening!");
       tabs.open(sites.urls[count]);
        handleTab(count);
    }
    //this is our cargo. There's normally more stuff in it
    var Cargo = {
        Title: ""
    };
    var sites = {
    urls: ["https://www.sofurry.com/", "https://inkbunny.net/search.php", "http://www.furaffinity.net/search/", "https://www.weasyl.com/search", "http://www.deviantart.com/"],
    scripts: ["searchSF.js", "searchIB.js", "searchFA.js", "searchWS.js", "searchDA.js"]
    };
    function handleTab(X) 
    {
        console.log("Step 3, tab  "+ count +" is processing!");
    //I tried tabs.on('load'.. and that didn't fix the problem
        tabs.on('ready', function RunPostScript(tab) 
        {
            console.log("The tab is ready");
            worker = tab.attach(
            {
                  contentScriptFile: sites.scripts[X],
                  contentScriptOptions: 
                  {
                    Cargo
                  }
            });
            worker.port.once("myMessage", function handleMyMessage() 
            {
                console.log("Step 4, search "+ count +" is shuttin down!");
                //tab.close();
                worker.destroy();
            });
            tabs.removeListener("ready", RunPostScript);
        console.log("Step 5, search "+ count +" should be finished!");
        count=count+1;
        console.log("Ready to do it again?");
        doit();
        });
    }
    journal_entry.port.once("cargo-shipping", function (cargo) {
        Cargo.Title = cargo.title;
        console.log("title: " + Cargo.Title);
        //All data from panel should be imported. So panel is now hidden
        journal_entry.hide();
        //this starts the tab opening process
        TabIt(count);
    });
    

    DeltaLogPanel.js

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
        <head>
        <!-- <link type="text/css" rel="stylesheet" href="DeltaLogPanel.css"/> -->
            <style>
                #MainPanel 
                {
                width: 180px;
                height:180px;
                background-color: #ACA1A1;
                }
            </style>
        </head>
        <body id="MainPanel">
            <div id="simpleOptions">
                <textarea id="titleBox" placeholder="Title" rows="1"></textarea>
                <button type="button" id="publishButton">Publish</button>
            </div>
        </body>
    </html>
    

    得到-text.js

    var titleArea = document.getElementById("titleBox");
    var finalButton = document.getElementById("publishButton");
    
    //this defines the cargo on the button press then ships it.
    finalButton.addEventListener('click', function() {
        // Remove the newline.
        var cargo = {
            title: ""
        };
        cargo.title = titleArea.value;
        self.port.emit("cargo-shipping", cargo);
        titleArea.value = "";
    }, false);
    
    //focusses on title box when button is pressed
    self.port.on("show", function onShow() {
      titleArea.focus();
    });
    

    searchFA.js

    document.addEventListener("submit", function(event) {
    console.log("Unloading now");
    self.port.emit("myMessage");
    }, false);
    //puts words in the input box
    var titlePort = function(x){
        var FAzA = document.querySelector("form#search-form fieldset input#q");
        FAzA.value = x;
    };
    //hits the submit button
    var ShipIt = function(){
    document.querySelector("form#search-form").submit();
    };
    var Finalize = function(){
    titlePort(self.options.Cargo.Title);
    ShipIt();
    };
    Finalize();
    

    searchIB.js

    document.addEventListener("submit", function(event) {
    console.log("Unloading now");
    self.port.emit("myMessage");
    }, false);
    //puts words in the input box
    var titlePort = function(x){
        var IBzA = document.querySelector("#text");
        IBzA.value = x;
    };
    //hits the submit button
    var ShipIt = function(){
        var x = document.querySelector("body > form:nth-child(12)");
        var y =document.querySelector("body > form:nth-child(9)");
        if (x !==null || y !==null)
        {
            if (x !== null) 
            {
                x.submit();
            }
            else 
            {
                y.submit();
            }
        }
    };
    var Finalize = function(){
    titlePort(self.options.Cargo.Title);
    ShipIt();
    };
    Finalize();
    

    searchSF.js

    document.addEventListener("submit", function(event) {
    console.log("Unloading now");
    self.port.emit("myMessage");
    }, false);
    //puts words in the input box
    var titlePort = function(x){
        var SFzA = document.querySelector("#headersearch");
        SFzA.value = x;
    };
    //hits the submit button
    var ShipIt = function(){
    document.querySelector(".topbar-nav > form:nth-child(3)").submit();
    };
    var Finalize = function(){
    titlePort(self.options.Cargo.Title);
    ShipIt();
    };
    Finalize();
    

    searchWS.js

    document.addEventListener("submit", function(event) {
    console.log("Unloading now");
    self.port.emit("myMessage");
    }, false);
    //puts words in the input box
    var titlePort = function(x){
        var WSzA = document.querySelector("form#search-backup-search input");
        WSzA.value = x;
    };
    //hits the submit button
    var ShipIt = function(){
    document.querySelector("form#search-backup-search").submit();
    };
    var Finalize = function(){
    titlePort(self.options.Cargo.Title);
    ShipIt();
    };
    Finalize();
    

    searchDA.js

    document.addEventListener("submit", function(event) {
    console.log("Unloading now");
    self.port.emit("myMessage");
    }, false);
    //puts words in the input box
    var titlePort = function(x){
        var DAzA = document.querySelector("input.gmbutton2");
        DAzA.value = x;
    };
    //hits the submit button
    var ShipIt = function(){
    document.querySelector("#search7").submit();
    };
    var Finalize = function(){
    titlePort(self.options.Cargo.Title);
    ShipIt();
    };
    Finalize();
    

    什么工作

    存储用户输入。 插件完美地加载了系列中的所有选项卡。 第一个脚本在第一个选项卡上顺利运行。 单独测试时,每个脚本都会运行搜索结果。

    问题

    完成所有操作后,并非所有选项卡都会显示搜索结果。几个搜索框保留为空白,就像脚本从未在这些选项卡上运行一样。 第一个选项卡的脚本始终有效,但其余选项卡上的脚本随机无法运行。 我注意到console.log("Step 4, search "+ count +" is shuttin down!");从未执行过。我认为这意味着工人永远不会被摧毁。 这可能会导致这些问题。 脚本运行以下内容后,应销毁每个脚本的worker:self.port.emit("myMessage"); 这段代码位于每个脚本的顶部。但我认为提交过程发生得太快,无法触发事件监听器。

    错误消息

    我收到以下每个不起作用的脚本的错误消息:

        Object
    - _errorType = TypeError
    - message = FAzA is null
    - fileName = resource://gre/modules/commonjs/toolkit/loader.js -> resource:/
    /gre/modules/commonjs/sdk/loader/sandbox.js -> resource://jid1-tbpzbqttcoeaag-at
    -jetpack/my-addon/data/searchFA.js
    - lineNumber = 8
    - stack = titlePort@resource://gre/modules/commonjs/toolkit/loader.js -> res
    ource://gre/modules/commonjs/sdk/loader/sandbox.js -> resource://jid1-     tbpzbqttco
    eaag-at-jetpack/my-  addon/data/searchFA.js:8:2|Finalize@resource://gre/modules/co
     mmonjs/toolkit/loader.js ->    resource://gre/modules/commonjs/sdk/loader/sandbox.j
    s -> resource://jid1-tbpzbqttcoeaag-at-jetpack/my-  addon/data/searchFA.js:15:1|@r
    esource://gre/modules/commonjs/toolkit/loader.js ->   resource://gre/modules/commo
    njs/sdk/loader/sandbox.js -> resource://jid1-tbpzbqttcoeaag-at-jetpack/my-  addon/
    data/searchFA.js:18:1|
    - name = TypeError
    

    如果只运行一个选项卡/脚本,则不会发生此错误。对于每个选项卡/脚本组合都是如此。所以我知道他们都应该工作。

    我的问题

    如何在脚本运行提交函数后销毁每个脚本的worker?

2 个答案:

答案 0 :(得分:1)

您的错误:

  

FAZA无效

表示使用querySelector()时未在页面中找到该元素。

问题主要在这里:

tabs.on('ready', function RunPostScript(tab) {...});

这会监控所有选项卡,并在提交搜索时创建竞争条件。发生以下情况:

  1. 将ready事件侦听器附加到等待站点A的选项卡
  2. 开放网站A
  3. 页面A触发就绪事件,将脚本A附加到站点A
  4. 删除就绪事件监听器
  5. 增量计数
  6. 循环结束,调用下一个标签
  7. 将ready事件侦听器附加到等待站点B的选项卡
  8. 同时,网站A提交搜索,加载结果页面并触发就绪事件
  9. 将脚本B附加到站点A
  10. 网站A现在作为网站B处理,脚本B找不到搜索输入,输出错误
  11. 删除就绪事件监听器
  12. 增量计数
  13. 循环结束,调用下一个标签
  14. 将ready事件侦听器附加到等待站点C的选项卡
  15. 您应该在选项卡级别监控事件。使用once(),这样您就不必删除侦听器。像这样:

    function TabIt(x) {
        tabs.open({
            url:sites.urls[x],
            onOpen: function(x, tab) {
                // fire once
                // count is available in this scope, no need to setup as arg again
                tab.once('ready', function readyStuff(tab) {
                    tab.attach({
                        contentScriptFile: sites.scripts[x],
                        contentScriptOptions:{Cargo}
                    });
                });
            }
        });
        ++count;
        doit();
    }
    

    您还继续使用count代替x,虽然可以这样做,但由于count存在的范围,需要绑定值。但是因为你有x,所以只需使用它。

    我还在评论中建议在附加脚本中使用DOMContentLoaded。在阅读了有关标签的脚本附件的更多内容之后,这是一个糟糕的建议。

    您的代码可以大大优化,但让我们一次做一件事。

答案 1 :(得分:0)

window.ember

这里是框架脚本,绝对容易: https://github.com/mdn/e10s-example-addons/tree/master/run-script-in-all-pages