Chrome扩展程序:当发生Ajax请求时运行代码

12

因此,对于我的问题的基本描述如下。

我有一个扩展程序,目前正在工作(终于),它将电话号码包装在类型的标签中。

它现在正在工作,但我遇到了任何基于用户操作或基于ajax请求动态加载的内容的问题

例如,如果我单击热邮件电子邮件并打开它,脚本就会工作,但仅当我刷新页面以使电子邮件加载并调用我的内容脚本时才能工作

我想过通过让用户点击扩展名图标来解决这个问题,但这并不是所请求的功能。

如果在Chrome中有一种方法可以监听ajax请求(似乎有) http://code.google.com/chrome/extensions/webRequest.html 那就是我想做的,但我不知道如何实现。我该把它当作监听器吗?

我想出了另一种方法,基于DOM何时发生更改,但这使得负载需要很长时间,DOM中有太多的事情要做。我需要监听AJAX请求,并在完成时再次运行我的代码。

任何帮助或指向正确方向的指针都将是巨大的 =)

如果这是一个愚蠢的问题,请友善点,我保证我已经在谷歌上和论坛上搜索了答案,但似乎找不到任何信息。可能我甚至不知道足够提出正确的问题。 我现在使用JavaScript已有两周了...所以我的学习曲线一直很陡峭。


chrome.webRequest.onCompleted.addListener(function(){/*your code here*/}); 放到后台页面怎么样? - Derek 朕會功夫
这是我的初步答案:http://pastebin.com/8ZB8ucAM。 - Rob W
对Derek和Rob W,我尝试按照你们描述的方式实现它。我首先在我的background.js中尝试了这个: 'chrome.webRequest.onCompleted.addListener(function(){ chrome.tabs.executeScript(null, {file: "typenex_contentscript.js"}); });'但似乎没有任何改变,然后我实施了Rob的方法,但也没有结果。我需要发送消息到我的内容脚本,而不是执行它吗?我仍然不确定这个规则。此外,类似hotmail.com这样的网站更新其网站的唯一方法是使用XHR,对吧?没有其他方法了吗? - njfife
我确实为我的扩展程序授予了选项卡权限。 - njfife
@njfife 如果你希望在评论中提到某人时,他们能够收到通知,你需要在他们的名字前面加上 @ 符号。 - PAEz
2个回答

12

当你说...

我发现另一种方法是基于DOM变化时的情况,但这使得加载时间变得很长,DOM中的操作太多了,无法采用这种方法。我需要监听AJAX请求,并在它们完成后重新运行我的代码。

...你使用的是Mutation Events还是Mutation Observers?因为我认为Observers被设计来解决这个问题。我以前从未使用过Observers,使用了Mutation Summary。它似乎能够实现你想要的,只是它直到文档就绪/空闲(不确定哪个)才开始观察,所以你可能需要在文档就绪时进行扫描,然后启动Observer。
以下是我的测试代码(在内容脚本中)...

handleChanges = function(summaries) {
    // There may be more things to ignore
    var ignore = {
        SCRIPT: true,
        NOSCRIPT: true, 
        CDATA: true,
        '#comment': true
    }
    summaries.forEach(function(summary) {
        summary.added.forEach(function(node) {
            if (!ignore[node.nodeName] || (node.parentNode && !ignore[node.parentNode.nodeName]) && node.nodeValue.trim()) {
                node.nodeValue='PAEz woz ere - '+node.nodeValue;
            }
        })
    })

}

var observer = new MutationSummary({
    callback: handleChanges,
    // required
    rootNode: document,
    // optional, defaults to window.document
    observeOwnChanges: false,
    // optional, defaults to false
    queries: [{
        characterData: true
    }]
});

另一种检查XMLHttpRequest的方法是劫持它,只需在内容脚本中编写以下代码即可(在文档开始时).....

function injectScript(source) {

    var elem = document.createElement("script"); //Create a new script element
    elem.type = "text/javascript"; //It's javascript
    elem.innerHTML = source; //Assign the source
    document.documentElement.appendChild(elem); //Inject it into the DOM
}

injectScript("("+(function() {

    function bindResponse(request, response) {
        request.__defineGetter__("responseText", function() {
            console.warn('Something tried to get the responseText');
            console.debug(response);
            return response;
        })
    }

    function processResponse(request,caller,method,path) {
        bindResponse(request, request.responseText);
    }

    var proxied = window.XMLHttpRequest.prototype.open;
    window.XMLHttpRequest.prototype.open = function(method, path, async) {
            var caller = arguments.callee.caller;
            this.addEventListener('readystatechange', function() {
                if (this.readyState === 4)
                    processResponse(this,caller,method,path);
            }, true);
        return proxied.apply(this, [].slice.call(arguments));
    };
}).toString()+")()");

我从超级有趣的Supper Happy Fun Blog学到了这个技巧,但你可能已经知道,这对于使用ajax技术的网站来说不够。通常你需要为该网站编写特定的代码,或者也可以使用Mutation Observer。


很抱歉花了这么久时间才接受答案,我刚刚意识到在另一个问题上该如何操作!所以我回来并为您接受了它。非常感谢! - njfife

0

这是一个使用 MutationObserver 更新的答案,因为 MutationSummary 不再起作用:

var observer = new MutationObserver(function(mutationsList) {
  console.log(`Something has changed`);
});

observer.observe(document.querySelector('.whatever'), {
  attributes: true,
  characterData: true,
  childList: true,
  subtree: true
});
  • 请确保将 .whatever 选择器更改为您感兴趣的任何类/ID。
  • 请确保在 subtree 选项中指定 true/false,以确定您是否对选择器的子元素进行修改。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接