我正在构建一个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脚本,因此作为清单的一部分由清单清单加载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转换为自动生成的输出(如here所述)。
我已经在一个简单的HTML页面中创建了一个测试用例,并且工作正常,我试图将测试页面移至iframe中,并且Joyride停止工作。因此,尽管没有太多信心,但我怀疑问题出在iframe,而不是Chrome扩展。
**注意,我将此调用直接放在所有DOM操作的末尾。在将新创建的HTML添加到iframe的DOM之后,以及在创建所有侦听器之后,等等。因此,我有信心在那时脚本和操纵杆应位于“那里”。但是,如果我刚好在调用Foundation('joyride','start')之前粘贴了alert(),则该警告显示后会带有一个空的iframe,并且只有在我关闭该警告之后,iframe才会填充。这是重要的还是警报的奇怪效果,我不知道。
最佳答案
多亏了一些有用的评论,我设法使这项工作奏效。完全相同的解决方案也可以正常工作。因此,这是以下解决方案:
第三方javascript程序包(特别是JQuery,Foundation Zurb Joyride和QTip2)...
...由Chrome扩展程序以编程方式注入...
...放入iFrame-Chrome扩展程序本身已将其注入用户的当前网页
我将尽力在下面进行描述。我是自学成才的人,仍然是新手,因此对任何令人困惑的术语或与最佳实践的差异表示歉意。
解决方案概述
我最终将Chrome扩展程序分为三个级别:
一个控制扩展的后台脚本(与该特定问题无关紧要,但出于完整性考虑,值得一提)。
内容脚本从后台脚本接收命令,并以编程方式将iframe,iframe HTML内容和第3部分JS程序包注入用户的网页。
“ 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>
内容脚本还根据iaa主体底部的QTip2建立了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);
注意解决方案的这一部分纠正了我的原始错误之一。如果仅将文本附加到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'}, '*');
})();
注意在我的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');
}
注意我这里有一个悬而未决的问题。这有时可以在加载JQuery之前运行,从而导致错误(“未声明$”)。为了解决这个问题,我玩过window.setTimeout,它几乎一直都在工作...但是不是100%
就是这样!
QTips有一个匹配的激活功能,之前已将适当的内容注入到iframe中。就像使用Joyride一样,我在小型iframe中尝试渲染Qtips时也很费劲。 QTip2功能更强大,文档建议其中有Zurb docs。
关于javascript - 通过Chrome Extension内容脚本在iFrame中激活Zurb Foundation的Joyride,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32439431/