Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/google-chrome/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何从扩展中检测Google Chrome中的页面标题更改?_Javascript_Google Chrome_Google Chrome Extension - Fatal编程技术网

Javascript 如何从扩展中检测Google Chrome中的页面标题更改?

Javascript 如何从扩展中检测Google Chrome中的页面标题更改?,javascript,google-chrome,google-chrome-extension,Javascript,Google Chrome,Google Chrome Extension,我正在创建一个Google Chrome扩展,我需要检测页面标题何时更改。页面标题的更改与Twitter中的更改类似:(num)Twitter(请参见下面的屏幕截图)-当发布新的tweet时,数量会增加。例如: 我正在尝试检测加载到我的一个选项卡中的URL的标题更改,并在出现差异时播放嘟嘟声。此检查需要重复进行,我认为可以使用setTimeOut()函数来完成 我创建了一个manifest.json,如下所示: { "manifest_version": 2, "name": "De

我正在创建一个Google Chrome扩展,我需要检测页面标题何时更改。页面标题的更改与Twitter中的更改类似:
(num)Twitter
(请参见下面的屏幕截图)-当发布新的tweet时,数量会增加。例如:

我正在尝试检测加载到我的一个选项卡中的URL的标题更改,并在出现差异时播放嘟嘟声。此检查需要重复进行,我认为可以使用
setTimeOut()
函数来完成

我创建了一个
manifest.json
,如下所示:

{
  "manifest_version": 2,

  "name": "Detect Page Title Changes",
  "description": "Blah",
  "version": "1.0",

  "browser_action": {
    "default_icon": "icon.png",
    "default_popup": "background.html"
  },
  "permissions": [
    "tabs"
  ]
}
然而,我对其余的一无所知。我已经搜索了文档,并在类似的堆栈溢出线程(如我)上尝试了解决方案,但没有找到任何适合我的要求的解决方案

你有什么建议吗?如果可能,请附上一个例子

  • 创建一个

  • 创建在网页加载时被注入网页的

  • 在内容脚本中,使用轮询页面以查看
    window.document.title
    是否更改

  • 如果标题已更改,请使用向事件页面发送消息

  • 在事件页面上,使用和收听消息


  • 在研究了Chrome的tabs API之后,它看起来并没有什么可以直接帮助您的。但是,您应该能够将事件侦听器附加到您感兴趣的选项卡的标题节点。DOMSubtreeModified突变事件在Chrome中起作用,在普通html文档中进行快速测试证明对我有效——应该与在扩展中没有什么不同

    var title = document.getElementsByTagName('title')[0];
    
    if (title) {
        title.addEventListener('DOMSubtreeModified', function (e) {
            // title changed
        }, false);
    }
    


    与其在评论中争论某种方法更好,不如让我更具建设性,通过展示我自己写的一篇文章来补充答案,并解释一些你可能遇到的问题代码片段指的是与Twitter不同的服务,但目标是相同的。事实上,此代码的目标是报告未读邮件的确切数量,因此您的代码可能更简单

    我的方法基于此,而不是轮询驱动(按固定时间间隔检查条件),而是事件驱动(通知条件的潜在变化)

    优点包括立即检测到更改(否则在下次轮询之前不会检测到更改),并且在条件不变时不会在轮询上浪费资源。诚然,第二种观点在这里几乎不适用,但第一种观点仍然有效


    架构概览:

  • 将内容脚本插入到相关页面中

  • 分析标题的初始状态,通过
    sendMessage
    向后台页面报告

  • 注册标题更改事件的处理程序

  • 每当触发事件并调用处理程序时,分析标题的新状态,通过
    sendMessage
    向后台页面报告


  • 步骤1已经有了一个解决方案。当在清单中定义内容脚本时,正常的内容脚本注入机制将在导航到与URL匹配的页面时将其注入页面

    "content_scripts": [
      {
        "matches": [
          "*://theoldreader.com/*"
        ],
        "js": ["observer.js"],
        "run_at": "document_idle"
      }
    ]
    
    在重新加载扩展之前,这工作得很好。这可能发生在应用所做更改的开发中,也可能发生在自动更新的已部署实例中。然后,内容脚本不会重新注入现有的打开页面(直到导航发生,就像重新加载一样)。因此,如果依赖于基于清单的注入,当扩展初始化时,还应该考虑包括编程注入已打开的选项卡:

    function startupInject() {
      chrome.tabs.query(
        {url: "*://theoldreader.com/*"},
        function (tabs) {
          for (var i in tabs) {
            chrome.tabs.executeScript(tabs[i].id, {file: "observer.js"});
          }
        }
      );
    }
    
    另一方面,在扩展重新加载时处于活动状态的内容脚本实例不会终止,而是孤立的:任何
    发送消息
    或类似请求都将失败。因此,建议在尝试与父扩展通信时始终检查异常,并在失败时自行终止(通过删除处理程序):

    try {
      chrome.runtime.sendMessage({'count' : count});
    } catch(e) { // Happens when parent extension is no longer available or was reloaded
      console.warn("Could not communicate with parent extension, deregistering observer");
      observer.disconnect();
    }
    

    第二步也有一个解决办法,尽管这取决于你正在观看的服务的具体情况。内容脚本范围内的某些页面不会显示未读项目的数量,但这并不意味着没有新消息

    在观察了web服务的工作方式之后,我得出结论,如果标题更改为没有导航的内容,则可以安全地假设新值(如果正确),但对于初始标题,“无新项目”应被忽略,因为它不可靠

    因此,分析代码说明是初始读取还是处理更新:

    function notify(title, changed) {
      // ...
      var match = /^\((\d+)\)/.exec(title);
      var match_zero = /^The Old Reader$/.exec(title);
    
      if (match && match[1]) {
        count = match[1];
      } else if (match_zero && changed) {
        count = 0;
      }
      // else, consider that we don't know the count
      //...
    }
    
    在第2步中,使用初始标题和
    changed
    =
    false
    调用它


    步骤3和步骤4是“如何观察标题更改”(以事件驱动的方式)的主要答案。

    var target = document.querySelector('head > title');
    
    var observer = new window.MutationObserver(
      function(mutations) {
        mutations.forEach(
          function(mutation){
            notify(mutation.target.textContent, true);
          }
        );
      }
    );
    
    observer.observe(target, { subtree: true, characterData: true, childList: true });
    
    有关设置
    observer.observe
    某些选项的具体原因,请参阅


    请注意,
    notify
    是使用
    changed
    =
    true
    调用的,因此从“(1)旧阅读器”到“旧阅读器”而不进行导航被视为“真”更改为零未读消息。

    在后台脚本中放置
    chrome.tabs.onUpdated.addListener

    chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
       console.log(changeInfo);
    });
    
    changeInfo
    是一个包含标题更改的对象,例如:


    然后可以对对象进行筛选,以便仅当
    changeInfo
    包含标题更改时才会发生操作。对于其他操作,例如使用页面内容/操作响应页面标题的更改,您可以在满足任何条件后从侦听器内部向内容脚本发送消息。

    如果您正在轮询,是否需要事件?你不能只存储最后一个标签标题并将其与当前标签标题进行比较吗?我认为使用事件(如果有)是一个好主意。但是如果没有,你的想法可以是你