[英]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中的关键元素是:
因此,考虑到这一点,我使清单的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正常工作。 因此,这是以下解决方案:
我将尽力在下面对其进行描述。 我是自学成才的人,仍然是新手,因此对任何令人困惑的术语或与最佳实践的差异表示歉意。
解决方案概述
我最终将Chrome扩展程序分为三个级别:
清单
尽管内容脚本(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头中,我输入了:
然后在iframe主体的底部放置:
以该顺序。
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.