繁体   English   中英

通过Chrome Extension内容脚本在iFrame中激活Zurb Foundation的Joyride

[英]Activating Zurb Foundation's Joyride in an iFrame, from Chrome Extension content script

我正在构建一个Chrome扩展程序,该扩展程序可以在任何HTML页面(即在浏览器窗口中查看的任何页面)内创建iFrame。

Chrome扩展程序的内容脚本将iFrame“注入”到HTML页面中。 生成的HTML如下所示:

<html>
  <head>..</head>
  <body>..</body>
  <iframe id="myIframe">...</iframe>
</html>

在内容脚本将iFrame添加到主页的DOM之后,它继续通过操作其自己的DOM在iframe中填充内容。 我使用Zurb CSS设置iframe内容的样式。

而且一切正常。

我现在正在尝试将Zurb Joyride添加到iframe的内容中,而这正是我无法开始的工作。

我的清单的content_scripts声明如下所示:

"content_scripts": [{
    "matches":    ["*://*/*"],
    "js":         ["js/externalJS/jquery-2.1.4.min.js",
                   "js/externalJS/foundation.min.js",
                   "js/content_script.js"],
    "run_at":     "document_end"
}],

我怀疑iframe本身需要访问Zurb脚本,因此,清单是作为扩展的一部分由manifest加载的foundation.min.js,我的内容脚本也在iframe中添加了相关标签(通过操作DOM) )。 我的理解是iframe中的关键元素是:

  • Zurb JS文件的标签
  • 将操纵杆附加到(id =“ testjoyride”)的对象
  • 喜乐内容本身
  • 对Foundation()的初始化调用

因此,考虑到这一点,我使清单的web_accessible_resources声明看起来像这样:

"web_accessible_resources": [

    "js/externalJS/jquery-2.1.4.min.js",
    "js/externalJS/vendor/modernizr.js",
    "js/externalJS/vendor/fastclick.js",
    "js/externalJS/foundation.min.js",
    "css/foundation.css",
    "css/app.css"
],

然后使用内容脚本在iframe中构建以下HTML:

<iframe id="myIframe">
  <html>
    <head>

      <!-- the foundation style sheet (which works fine already) -->
      <link type="text/css" rel="stylesheet" href="chrome-extension://extension_id/css/foundation.css">

      <!-- the first two scripts -->
      <script src="chrome-extension://extension_id/js/externalJS/vendor/modernizr.js"></script>
      <script src="chrome-extension://extension_id/js/externalJS/jquery-2.1.4.min.js"></script>

    </head>

    <body>

      <!-- a test object to attach the joyride too -->
      <input type="submit" id="testjoyride">

      <!-- now the rest of the iframe content -->
      ... content ...

      <!-- the other two scripts -->
      <script src="chrome-extension://extension_id/js/externalJS/vendor/fastclick.js"></script>
      <script src="chrome-extension://extension_id/js/externalJS/foundation.min.js"></script>

      <!-- default joyride code from foundation.zurb.com -->
      <ol class="joyride-list" data-joyride="">  
        <li data-id="testjoyride" data-class="custom so-awesome" data-text="Next" data-prev-text="Prev">    
         <h4>Stop #1</h4>    
        </li>
        <li data-button="end" data-prev-text="Prev">
          <h4>Stop #3</h4>
        </li>
      </ol>

    </body>
  </html>
</iframe>

然后,最后,当上述所有内容都附加到iframe(并且iframe当然也附加到父页面的DOM)时,我从content_script调用foundation()。

我想我需要这样称呼它:$(window.frames.myIframe.contentWindow.document).foundation('joyride','start');

即传入iframe的文档对象,而不是父页面**

所以我做了所有这些,没有任何反应。 该兜风没有出现,也没有在HTML得到转化为自动生成的输出(如描述在这里 )。

我已经在一个简单的HTML页面中创建了一个测试用例,并且工作正常,我试图将测试页面移至iframe中,并且Joyride停止工作。 因此,尽管没有足够的信心,但我怀疑问题出在iframe,而不是Chrome扩展。

**注意,我将此调用放在所有DOM操作的结尾。 在将新创建的HTML添加到iframe的DOM之后,以及在创建所有侦听器等之后,因此,我确信脚本和操纵杆应该在那时就“存在”了。 但是,如果我刚好在调用Foundation('joyride','start')之前粘贴了alert(),则该警告显示后会带有一个空的iframe,并且只有在我关闭该警告后,iframe才会填充。 这是重要的还是警报的奇怪效​​果,我不知道。

多亏了一些有用的评论,我设法使这项工作奏效。 完全相同的解决方案也使QTip2正常工作。 因此,这是以下解决方案:

  • 第三方javascript程序包(特别是JQuery,Foundation Zurb Joyride和QTip2)...
  • ...由Chrome扩展程序以编程方式注入...
  • ...放入iFrame-Chrome扩展程序本身已将其注入用户的当前网页

我将尽力在下面对其进行描述。 我是自学成才的人,仍然是新手,因此对任何令人困惑的术语或与最佳实践的差异表示歉意。

解决方案概述

我最终将Chrome扩展程序分为三个级别:

  1. 一个控制扩展的后台脚本(与该特定问题无关紧要,但出于完整性考虑,值得一提)。
  2. 内容脚本从后台脚本接收命令,并以编程方式将iframe,iframe HTML内容和第3部分JS程序包注入用户的网页。
  3. “ iframe脚本”,这是一个自定义JS脚本,与第3方程序包一起注入了iframe。 该iframe脚本可以向内容脚本发送消息/从内容脚本接收消息,同时可以访问第三方JS程序包-Zurb Joyride和QTips

清单

尽管内容脚本(content_script.js)控制着所有注入,但是它实际上从未真正运行任何第三方JS包。 它们由用户的网页运行。 因此,清单的content_scripts声明如下所示:

"content_scripts": [{
        "matches":    ["*://*/*"],
        "js":         ["js/content_script.js"],
        "run_at":     "document_end"
    }],

由于网页需要访问第三方脚本,因此必须获得权限。 它还需要访问我们的自定义iframe脚本:

"web_accessible_resources": [
        "js/iframe_script.js",

        "js/externalJS/jquery-2.1.4.min.js",
        "js/externalJS/jquery.qtip.min.js",
        "js/externalJS/vendor/modernizr.js",
        "js/externalJS/vendor/fastclick.js",
        "js/externalJS/foundation.min.js",
        "css/foundation.css",
        "css/jquery.qtip.min.css"
    ],

内容脚本:将Joyride HTML注入iframe

内容脚本创建一个iframe元素(id =“ myIframe”)并将其附加到用户的网页上。 然后继续以编程方式将其填充内容。

其中一些内容将成为joyride的基础:ID设置为joyrideStop1,joyrideStop2等的HTML元素:

iframeContentHTML += <i class="fi-info brandSpielIcon" id="joyrideStop1"></i>

根据Zurb文档 ,内容脚本还在iframe主体的底部建立了Joyride HTML。

joyrideHTML += '<ol class="joyride-list" data-joyride>';
joyrideHTML += '  <li data-id="joyrideStop1" data-text="Next (1 of 5)" data-prev-text="Prev" class="customJoyride">';
joyrideHTML += '    <h4>Title</h4>';
joyrideHTML += '    <p>Content</p>';
joyrideHTML += '  </li>';
... 

我的自定义CSS类很简单:

.customJoyRide .joyride-nub {
    visibility: hidden;
}

这使Joyride工具提示上的小尖箭头消失了。 尝试使操纵杆在小型iframe中很好地显示时,我遇到了很多问题。 理想情况下,我希望它们锚定到iframe中的元素,但要显示为好像它们是主页的一部分。 最后,这似乎太难了或不可能,所以我只是删除了小块并回避了问题。 这是一个显示问题,仅是小型iframe的问题,因此不是此解决方案的核心部分。

内容脚本:将JS注入iframe

为了使Joyride正常工作,我们需要将第3方脚本和自定义iframe_script.js注入到iframe中。 这是来自content_script.js的第三方脚本之一的代码示例:

// Inject foundation script into iframe body
var foundationScript = document.createElement('script');
foundationScript.src = chrome.extension.getURL('js/externalJS/foundation.min.js');
window.frames.myIframe.contentWindow.document.body.appendChild(foundationScript);

NB。 解决方案的这一部分纠正了我的原始错误之一。 如果仅将文本附加到innerHTML上,则脚本似乎没有初始化: body.innerHTML += '<script src=".."></script>;'

因此,我对所有脚本重复以上代码。 在iframe头中,我输入了:

  • jquery.qtipmin.css
  • modernizr.js
  • jQuery的2.1.4.min.js

然后在iframe主体的底部放置:

  • fastclick.js
  • foundation.min.js
  • jquery.qtip.min.js
  • iframe_script.js。

以该顺序。

iframe脚本:初始化

当iframe_script.js初始化时,我立即获得它以添加消息侦听器(以便内容脚本可以与之通信),然后将消息发送到内容脚本以告知其已准备好(内容脚本已经设置了自己的消息侦听器) ,此处未详细说明其代码):

(function initialise(){

    // Listen for messages from the content script
    window.addEventListener("message", contentScriptMessage_listener, false);

    // Tell the content script we're ready to go
    window.parent.postMessage({sender:  'iframe_script',
                               subject: 'iframeScriptHasInitialised'}, '*');
})();

NB。 在我的content_script将其第一条消息发送到iframe之前,我难以确保已设置iframe的侦听器。 最后,该解决方案(等待从iframe返回消息)似乎效果最好,尽管我怀疑可能会有更好的方法

内容脚本:告诉iframe激活操纵杆

现在,内容脚本知道iframe侦听器已准备就绪,可以告诉它激活Zurb joyride(和/或QTips)。 我是通过将消息发送回iframe来实现的。

window.frames.myIframe.contentWindow.postMessage({
    sender:  'content_script', 
    subject: 'pleaseActivateJoyride'}, '*');

显然,直接从iframe脚本激活Joyride会更简单,而不会使所有这些消息来回跳动。 但这就是重点:内容脚本知道是否应显示操纵杆,更不用说所有其他配置详细信息了。 使用内容脚本(最终使用后台脚本)进行控制,可以使整体实现更为整洁。

iframe脚本:激活Joyride

我的iframe脚本的消息处理程序从内容脚本接收消息并调用此函数:

function activateJoyride(){

    $(document).foundation({
        joyride: {
            ... configuration ...
        }
    });

    $(document).foundation('joyride', 'start');
}

NB。 我这里有一个悬而未决的问题。 这有时可以在加载JQuery之前运行,从而导致错误(“未声明$”)。 为了解决这个问题,我玩过window.setTimeout,它几乎一直都在工作...但不是100%

就是这样!

QTips有一个匹配的激活功能,相应的内容可以早些时候注入到iframe中。 就像操纵杆一样,我在小型iframe中尝试渲染Qtips时也遇到了麻烦。 QTip2功能更强大,文档建议有解决方案

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM