我如何在Google Chrome的Greasemonkey脚本中使用jQuery?

正如您可能知道的一样,Google Chrome已经对Greasemonkey脚本进行了一些严格的限制。

Chromium不支持@require@resourceunsafeWindowGM_registerMenuCommandGM_setValueGM_getValue

没有要求,我找不到一种方法来在Google Chrome中的Greasemonkey脚本中包含jQuery库。

有没有人在这个问题上有一些build议?

从“用户脚本提示:使用jQuery – Erik Vold的博客”

 // ==UserScript== // @name jQuery For Chrome (A Cross Browser Example) // @namespace jQueryForChromeExample // @include * // @author Erik Vergobbi Vold & Tyler G. Hicks-Wright // @description This userscript is meant to be an example on how to use jQuery in a userscript on Google Chrome. // ==/UserScript== // a function that loads jQuery and calls a callback function when jQuery has finished loading function addJQuery(callback) { var script = document.createElement("script"); script.setAttribute("src", "//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"); script.addEventListener('load', function() { var script = document.createElement("script"); script.textContent = "window.jQ=jQuery.noConflict(true);(" + callback.toString() + ")();"; document.body.appendChild(script); }, false); document.body.appendChild(script); } // the guts of this userscript function main() { // Note, jQ replaces $ to avoid conflicts. alert("There are " + jQ('a').length + " links on this page."); } // load jQuery and execute the main function addJQuery(main); 

我已经写了几个基于Erik Vold脚本的函数来帮助我在文档中运行函数,代码和其他脚本。 您可以使用它们将jQuery加载到页面中,然后在全局window范围下运行代码。

用法示例

 // ==UserScript== // @name Example from http://stackoverflow.com/q/6834930 // @version 1.3 // @namespace http://stackoverflow.com/q/6834930 // @description An example, adding a border to a post on Stack Overflow. // @include http://stackoverflow.com/questions/2246901/* // ==/UserScript== var load,execute,loadAndExecute;load=function(a,b,c){var d;d=document.createElement("script"),d.setAttribute("src",a),b!=null&&d.addEventListener("load",b),c!=null&&d.addEventListener("error",c),document.body.appendChild(d);return d},execute=function(a){var b,c;typeof a=="function"?b="("+a+")();":b=a,c=document.createElement("script"),c.textContent=b,document.body.appendChild(c);return c},loadAndExecute=function(a,b){return load(a,function(){return execute(b)})}; loadAndExecute("//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js", function() { $("#answer-6834930").css("border", ".5em solid black"); }); 

你可以点击这里来安装它,如果你相信我没有试图欺骗你安装恶意的东西,没有人编辑我的post指向别的东西。 重新加载页面,你应该看到我的文章边框。

function

load(url, onLoad, onError)

url的脚本加载到文档中。 或者,可以为onLoadonError提供callback。

execute(functionOrCode)

将一个函数或一串代码插入到文档中并执行它。 在被插入之前,函数被转换为源代码,所以它们失去了当前的范围/闭包,并在全局window范围下运行。

loadAndExecute(url, functionOrCode)

捷径; 这从url加载脚本,然后插入并执行functionOrCode如果成功。

 function load(url, onLoad, onError) { e = document.createElement("script"); e.setAttribute("src", url); if (onLoad != null) { e.addEventListener("load", onLoad); } if (onError != null) { e.addEventListener("error", onError); } document.body.appendChild(e); return e; } function execute(functionOrCode) { if (typeof functionOrCode === "function") { code = "(" + functionOrCode + ")();"; } else { code = functionOrCode; } e = document.createElement("script"); e.textContent = code; document.body.appendChild(e); return e; } function loadAndExecute(url, functionOrCode) { load(url, function() { execute(functionOrCode); }); } 

通过调用jQuery.noConflict(true)使用jQuery 而不用担心冲突 。 像这样:

 function GM_main ($) { alert ('jQuery is installed with no conflicts! The version is: ' + $.fn.jquery); } add_jQuery (GM_main, "1.7.2"); function add_jQuery (callbackFn, jqVersion) { jqVersion = jqVersion || "1.7.2"; var D = document; var targ = D.getElementsByTagName ('head')[0] || D.body || D.documentElement; var scriptNode = D.createElement ('script'); scriptNode.src = 'http://ajax.googleapis.com/ajax/libs/jquery/' + jqVersion + '/jquery.min.js' ; scriptNode.addEventListener ("load", function () { var scriptNode = D.createElement ("script"); scriptNode.textContent = 'var gm_jQuery = jQuery.noConflict (true);\n' + '(' + callbackFn.toString () + ')(gm_jQuery);' ; targ.appendChild (scriptNode); }, false); targ.appendChild (scriptNode); } 


但是, 对于跨浏览器脚本,为什么不尽快利用jQuery的本地副本呢?

以下内容可以作为Chrome用户脚本和Greasemonkey脚本使用,如果平台支持,它使用jQuery的本地@require副本。

 // ==UserScript== // @name _Smart, cross-browser jquery-using script // @include http://YOUR_SERVER.COM/YOUR_PATH/* // @require http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js // @grant GM_info // ==/UserScript== function GM_main ($) { alert ('jQuery is installed with no conflicts! The version is: ' + $.fn.jquery); } if (typeof jQuery === "function") { console.log ("Running with local copy of jQuery!"); GM_main (jQuery); } else { console.log ("fetching jQuery from some 3rd-party server."); add_jQuery (GM_main, "1.7.2"); } function add_jQuery (callbackFn, jqVersion) { var jqVersion = jqVersion || "1.7.2"; var D = document; var targ = D.getElementsByTagName ('head')[0] || D.body || D.documentElement; var scriptNode = D.createElement ('script'); scriptNode.src = 'http://ajax.googleapis.com/ajax/libs/jquery/' + jqVersion + '/jquery.min.js' ; scriptNode.addEventListener ("load", function () { var scriptNode = D.createElement ("script"); scriptNode.textContent = 'var gm_jQuery = jQuery.noConflict (true);\n' + '(' + callbackFn.toString () + ')(gm_jQuery);' ; targ.appendChild (scriptNode); }, false); targ.appendChild (scriptNode); } 

如果页面已经有jQuery,那么只需按照下面的模板:

 // ==UserScript== // @name My Script // @namespace my-script // @description Blah // @version 1.0 // @include http://site.com/* // @author Me // ==/UserScript== var main = function () { // use $ or jQuery here, however the page is using it }; // Inject our main script var script = document.createElement('script'); script.type = "text/javascript"; script.textContent = '(' + main.toString() + ')();'; document.body.appendChild(script); 

当这些脚本实际上不使用任何特权function (GM_ *函数等)时,有一种非常简单的方法可以解决,包括jQuery for Chrome脚本的完整副本。

只需将脚本本身插入到页面DOM中即可执行! 最好的部分是,这种技术同样适用于Firefox + Greasemonkey,所以你可以使用相同的脚本:

 var script = document.createElement("script"); script.type = "text/javascript"; script.textContent = "(" + threadComments.toString() + ")(jQuery)"; document.body.appendChild(script); function threadComments($) { // taken from kip's http://userscripts-mirror.org/scripts/review/62163 var goodletters = Array('\u00c0','\u00c1','\u00c2','\u00c3','\u00c4','\u00c5','\u00c6','\u00c7' ,'\u00c8','\u00c9','\u00ca','\u00cb','\u00cc','\u00cd','\u00ce','\u00cf' ,'\u00d1','\u00d2','\u00d3','\u00d4','\u00d5','\u00d6' ,'\u00d8','\u00d9','\u00da','\u00db','\u00dc','\u00dd' ,'\u00e0','\u00e1','\u00e2','\u00e3','\u00e4','\u00e5','\u00e6','\u00e7' ,'\u00e8','\u00e9','\u00ea','\u00eb','\u00ec','\u00ed','\u00ee','\u00ef' ,'\u00f1','\u00f2','\u00f3','\u00f4','\u00f5','\u00f6' ,'\u00f8','\u00f9','\u00fa','\u00fb','\u00fc','\u00fd' ,'\u00ff').join(''); // from Benjamin Dumke's http://userscripts-mirror.org/scripts/review/68252 function goodify(s) { good = new RegExp("^[" + goodletters + "\\w]{3}"); bad = new RegExp("[^" + goodletters + "\\w]"); original = s; while (s.length >3 && !s.match(good)) { s = s.replace(bad, ""); } if (!s.match(good)) { // failed, so we might as well use the original s = original; } return s; } in_reply_to = {}; function who(c, other_way) { if (other_way) { // this is closer to the real @-reply heuristics m = /@(\S+)/.exec(c); } else { m = /@([^ .:!?,()[\]{}]+)/.exec(c); } if (!m) {return} if (other_way) {return goodify(m[1]).toLowerCase().slice(0,3);} else {return m[1].toLowerCase().slice(0,3);} } function matcher(user, other_way) { if (other_way) { return function () { return goodify($(this).find(".comment-user").text()).toLowerCase().slice(0,3) == user } } else { return function () { return $(this).find(".comment-user").text().toLowerCase().slice(0,3) == user } } } function replyfilter(id) { return function() { return in_reply_to[$(this).attr("id")] == id; } } function find_reference() { comment_text = $(this).find(".comment-text").text(); if (who(comment_text)) { fil = matcher(who(comment_text)); all = $(this).prevAll("tr.comment").filter(fil); if (all.length == 0) { // no name matched, let's try harder fil = matcher(who(comment_text, true), true); all = $(this).prevAll("tr.comment").filter(fil); if (all.length == 0) {return} } reference_id = all.eq(0).attr("id"); in_reply_to[$(this).attr("id")] = reference_id; } } // How far may comments be indented? // Note that MAX_NESTING = 3 means there are // up to *four* levels (including top-level) MAX_NESTING = 3 // How many pixels of indentation per level? INDENT = 30 function indenter(parent) { for (var i = MAX_NESTING; i > 0; i--) { if (parent.hasClass("threading-" + (i-1)) || (i == MAX_NESTING && parent.hasClass("threading-" + i))) { return function() { $(this).addClass("threading-" + i).find(".comment-text").css({"padding-left": INDENT*i}); } } } return function() { $(this).addClass("threading-1").find(".comment-text").css({"padding-left": INDENT}); } } function do_threading(){ id = $(this).attr("id"); replies = $(this).nextAll("tr.comment").filter(replyfilter(id)); ind = indenter($(this)); replies.each(ind); replies.insertAfter(this); } function go() { $("tr.comment").each(find_reference); $("tr.comment").each(do_threading); } $.ajaxSetup({complete: go}); go(); } 

(没有歉意从Shog9在meta.stackoverflow被盗,因为他没有在这里移动它,我不得不删除meta post ..)

此外,你可以打包你的脚本与jQuery到Chrome扩展。 查看Google Chrome的内容脚本 。

与Greasemonkey脚本不同,Chrome扩展程序可以自动更新自己。

更简单的解决scheme:剪切+粘贴jquery.min.js的内容到您的用户脚本的顶部。 完成。

我find了推荐的答案的各种问题。 addJQuery()解决scheme在大多数页面上工作,但在许多页面上都有错误。 如果遇到问题,只需将jquery内容复制粘贴到您的脚本中即可。

简单的方法是使用required关键字:

 // @require http://code.jquery.com/jquery-latest.js 

我不知道你是否不能依赖你的GM脚本中的document.defaultView.jQuery ala:

 if (document.defaultView.jQuery) { jQueryLoaded(document.defaultView.jQuery); } else { var jq = document.createElement('script'); jq.src = 'src/jquery-latest.html'; jq.type = 'text/javascript'; document.getElementsByTagName('head')[0].appendChild(jq); (function() { if (document.defaultView.jQuery) jQueryLoaded(document.defaultView.jQuery); else setTimeout(arguments.callee, 100); })(); } function jQueryLoaded($) { console.dir($); } 

另一种方法是修改脚本以手动加载jQuery。 来自http://joanpiedra.com/jquery/greasemonkey/的示例:;

 // Add jQuery var GM_JQ = document.createElement('script'); GM_JQ.src = 'src/jquery-latest.html'; GM_JQ.type = 'text/javascript'; document.getElementsByTagName('head')[0].appendChild(GM_JQ); // Check if jQuery's loaded function GM_wait() { if(typeof unsafeWindow.jQuery == 'undefined') { window.setTimeout(GM_wait,100); } else { $ = unsafeWindow.jQuery; letsJQuery(); } } GM_wait(); // All your GM code must be inside this function function letsJQuery() { alert($); // check if the dollar (jquery) function works } 

编辑:DRATS! 经过testing,出现此代码不起作用,因为Google Chrome在实际网页的独立范围/stream程中运行了用户脚本/扩展程序。 您可以使用XmlhttpRequest下载jQuery代码,然后评估它,但是您必须将代码托pipe在允许使用Access-Control-Allow-Origin: *标头的跨源资源共享的服务器上。 可悲的是没有任何 jQuery支持这个CDN 。

将jQueryembeddedChrome控制台的完美扩展就像你想象的那样简单。 如果jQuery已经被embedded页面,这个扩展也是indocates。

这个扩展用来将jQueryembedded到你想要的任何页面中。 它允许在控制台shell中使用jQuery(您可以通过“Ctrl + Shift + j”调用Chrome控制台)。

要将jQueryembedded到选定的选项卡中,请单击扩展button。

链接到扩展程序: https : //chrome.google.com/extensions/detail/gbmifchmngifmadobkcpijhhldeeelkc