2013-10-05 11 views
2

我只想将jQuery注入Safari浏览器扩展的网页中。但仅限于某些页面,因为将jQuery添加为start/endscript会将其注入到所有页面,这会导致浏览速度变慢。 我尝试了通过创建使用其的onload功能的脚本标签:从Safari扩展中注入jQuery到网页

var node = document.createElement('script');  
node.onload = function(){ 
    initjquerycheck(function($) { 
     dosomethingusingjQuery($); 
    }); 
}; 
node.async = "async"; 
node.type = "text/javascript"; 
node.src = "https://code.jquery.com/jquery-2.0.3.min.js"; 
document.getElementsByTagName('head')[0].appendChild(node); 

,以检查是否jQuery是加载使用:

initjquerycheck: function(callback) { 
    if(typeof(jQuery) != 'undefined'){ 
     callback(jQuery); 
    }else { 
     window.setTimeout(function() { initjquerycheck(callback); }, 100); 
    } 
} 

但typeof运算(jQuery的)仍然是不确定的。 (使用console.log()检查)。 只有当我从调试控制台调用console.log(typeof(jQuery))时,它才返回'function'。任何想法如何解决这个问题?提前致谢!

回答

4

扩展插入的脚本无法访问网页的JavaScript名称空间。您的注入脚本创建一个<script>元素并将其添加到页面的DOM中,但该脚本实例化的jQuery对象属于该页面的名称空间,而不是您的注入脚本。

至少有两种可能的解决方案。一,使用扩展API以正常方式将jQuery注入页面。如果您要定位的网页可以使用网址格式进行分类,则此方法才可行。

二,使用Window.postMessage在注入的脚本和网页的名称空间之间进行通信。您需要在页面中添加另一个<script>,并在此脚本中为message事件设置侦听器。监听器将能够使用jQuery,就好像它对页面本身是“本地的”。

这里有一些代码可以让你开始,如果需要的话。

在扩展注入脚本:

var s0 = document.createElement('script'); 
s0.type = 'text/javascript'; 
s0.src = 'https://code.jquery.com/jquery-2.0.3.min.js'; 
document.head.appendChild(s0); 

var s1 = document.createElement('script'); 
s1.type = 'text/javascript'; 
s1.src = safari.extension.baseURI + 'bridge.js'; 
document.head.appendChild(s1); 

window.addEventListener('message', function (e) { 
    if (e.origin != window.location.origin) 
     return; 
    console.log(e.data); 
}, false); 

window.postMessage('What jQuery version?', window.location.origin); 

在bridge.js:

window.addEventListener('message', function (e) { 
    if (e.origin != window.location.origin) 
     return; 
    if (e.data == 'What jQuery version?') { 
     e.source.postMessage('Version ' + $.fn.jquery, window.location.origin); 
    } 
}, false); 
+0

你能在第一个选项扩展( “jQuery注入的页面以正常的方式”),你意思是通过'addContentScriptFromURL'? – meleyal

+0

另外,如果注入的脚本有不同的命名空间,它如何访问'window'对象(即如何访问'window'而不是'$')?它似乎本质上是发布消息。 – meleyal

+1

@meleyal,是的,我的意思是'addContentScript'和'addContentScriptFromURL'。关于注入的脚本如何访问窗口对象,在我看来,注入的脚本和页面自己的脚本就好像它们居住在两个不同的窗口中一样;人们可能会认为它们是碰巧在浏览器中占据相同空间的虚拟窗口。但是这些虚拟窗口共享相同的位置和来源,这就是为什么一个脚本可能将消息发送到另一个虚拟窗口的原因。 (他们也共享相同的DOM,但这与消息传递的目的不相关。) – canisbos