我制作了一个Chrome扩展程序,可以将键盘控件添加到Earbits radio
我正在尝试让鼠标滚轮改变音量。我已成功绑定鼠标滚轮事件,但我无法访问音量滑块选择器中的.slider()
属性(我得到undefined is not a function
)。奇怪的是,我可以从网页上的开发者控制台访问它。
这是我的manifest.json:
{
"name": "Earbits Keyboard Controls",
"version": "0.1",
"description": "Adds basic keyboard controls to Earbits radio",
"permissions": [
"http://www.earbits.com/*"
],
"content_scripts": [{
"matches": ["http://www.earbits.com/*"],
"js": ["jquery.js", "jquery.mousewheel.js", "jquery-ui-1.10.4.custom.min.js", "controls.js"]
}],
"manifest_version": 2
}
我的主脚本的相关位(我在一个区间中放置绑定的原因是我认为我无法访问该属性,因为它懒得加载):
var options = {
keys: {
SPACE: 32,
LEFT: 37,
RIGHT: 39,
F: 70
},
volumeIncrement: 5
}
function setVolume(value) {
var volSlider = $('.volume-slider');
volSlider.slider('value', value);
volSlider.slider('option', 'slide')(null, {value: volSlider.slider('value')});
}
function adjustVolume(delta) {
var volSlider = $('.volume-slider');
console.log(volSlider.slider('value'));
var value = Math.min(Math.max(volSlider.slider('value') + delta, 0), 100);;
setVolume(value);
}
$(window).load(function() {
var bindVolumeInterval = setInterval(function() {
if(typeof $('.volume-slider').slider != 'undefined') {
$('#menu, #audio-controls').on('mousewheel', function(e) {
e.preventDefault();
// console.log(e);
if(parseInt(e.deltaY) > 0) {
adjustVolume(options.volumeIncrement);
} else {
adjustVolume(-options.volumeIncrement);
}
});
clearInterval(bindVolumeInterval);
console.log('volume-bind ok');
} else {
console.log('volume-bind fail');
}
}, 1000);
});
答案 0 :(得分:3)
内容脚本在称为隔离的特殊环境中执行 世界。他们可以访问他们注入的页面的DOM, 但不是页面创建的任何JavaScript变量或函数。 它将每个内容脚本视为没有其他JavaScript 在正在运行的页面上执行。反过来也是如此: 页面上运行的JavaScript无法调用任何函数或访问任何函数 由内容脚本定义的变量。
这实际上是一种安全功能,这样网页的JavaScript代码就不会破坏您的扩展程序的功能,例如通过重新定义标准DOM方法。您的内容脚本根本看不到网页中运行的JavaScript添加/覆盖的任何属性。
当然,这使得调用页面JavaScript代码中的函数变得更加复杂。您的内容脚本实际上加载了自己的jQuery副本 - 但该副本对网页的功能一无所知,因此它也不知道所讨论的元素是滑块。 Communicating with the embedding page无法提供帮助,因为在这种情况下您无法控制网页。
运行可与该网页的JavaScript对话的JavaScript代码的最强大方法似乎是添加了<script>
代码:
function setVolume(value)
{
// Sanitize parameter, to make sure it doesn't need any escaping
value = parseInt(value, 10);
var script = document.createElement("script");
script.async = false;
script.textContent = "(function() {" +
"var value = " + value + ";" +
"var volSlider = $('.volume-slider');" +
"volSlider.slider('value', value);" +
"volSlider.slider('option', 'slide')(null, {value: volSlider.slider('value')});" +
"})()";
document.documentElement.appendChild(script);
document.documentElement.removeChild(script);
}
这是一种相当丑陋的方法,特别是对于冗长的脚本 - 您必须将整个脚本放入字符串中。因此,如果您注入网页的逻辑变得更复杂,您可能需要考虑为扩展添加脚本文件。您必须将此文件添加到web_accessible_resources并将其URL用作脚本源。您将无法再通过更改来源传递参数,但您可以按照Communication with the embedding page下的概述发布消息(无论如何,这是一种更好的方法)。
请注意,可以将异步脚本添加到页面中并立即删除,然后它就已经执行了。另请注意,您不需要在内容脚本中使用jQuery - 所有jQuery调用都发生在网页中,并且已经加载了jQuery。