Как я могу использовать jQuery в скриптах Greasemonkey в Google Chrome?
как некоторые из вас могут знать, Google Chrome поставил некоторые серьезные ограничения на Скрипты Greasemonkey.
хром не поддерживает
@require
,@resource
,unsafeWindow
,GM_registerMenuCommand
,GM_setValue
илиGM_getValue
.
без require я не могу найти способ включить библиотеку jQuery в скрипт Greasemonkey под Google Chrome.
есть ли у кого-нибудь советы в этом вопросе?
11 ответов:
С "подсказка пользовательского скрипта: использование блога 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);
я написал несколько функций на основании сценарий Эрика Вольда чтобы помочь мне выполнить функции, код и другие скрипты в документе. Вы можете использовать их для загрузки 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"); });
вы можете нажмите здесь чтобы установить его, если вы верите, что я не пытаюсь обмануть вас в установке чего-то вредоносного и что никто не редактировал мой пост, чтобы указать к чему-то еще. Перезагрузите страницу, и вы увидите границу вокруг моего поста.
функции
load(url, onLoad, onError)
загружает скрипт в
url
в документе. По желанию, обратные вызовы могут быть предоставлены дляonLoad
иonError
.
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 не боясь конфликтов, по телефону
jQuery.noConflict(true)
. Вот так: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 userscript и сценарий Greasemonkey, и он использует хороший локальный
@require
копия jQuery, если платформа поддерживает его.// ==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);
простой способ заключается в использовании
required
ключевые слова:// @require http://code.jquery.com/jquery-latest.js
есть очень простой способ обойти, включая полную копию jQuery для сценариев Chrome когда эти скрипты на самом деле не используют никаких привилегированных функций (функции GM_* и т. д.)...
просто вставьте сам скрипт в страницу 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 на мета.stackoverflow с тех пор он не переместил его сюда, и я должен удалить мета-пост..)
кроме того, вы можете упаковать свой скрипт с расширением jQuery to Chrome. Смотрите Скрипты контента Google Chrome.
расширения Chrome, в отличие от скриптов Greasemonkey, могут автоматически обновляться.
более простое решение: вырезать + вставить содержимое jquery.минута.js в верхней части пользовательского скрипта. Сделанный.
Я нашел различные проблемы с рекомендованными ответами. Решение addJQuery () работает на большинстве страниц, но имеет ошибки на многих. Если у вас возникли вопросы, просто скопируйте содержимое в свой скрипт на jQuery.
интересно, если вы не могли бы положиться на
document.defaultView.jQuery
в вашем GM скрипте ala:if (document.defaultView.jQuery) { jQueryLoaded(document.defaultView.jQuery); } else { var jq = document.createElement('script'); jq.src = 'http://jquery.com/src/jquery-latest.js'; 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 = 'http://jquery.com/src/jquery-latest.js'; 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 }
EDIT: DRATS! после тестирования кажется, что этот код не работает, так как Google Chrome запускает userscripts/extensions в отдельной области/процессе от фактической веб-страницы. Вы можете загрузить код jQuery с помощью XmlhttpRequest, а затем оценить его, но вы должны разместить код на сервере, который позволяет Кросс-Происхождения Совместное Использование Ресурсов С помощью
Access-Control-Allow-Origin: *
заголовок. К сожалению ни один из текущих CDNs С поддержкой jQuery это.
идеальное расширение для внедрения jQuery в консоль Chrome так просто, как вы можете себе представить. Это расширение также индокатирует, если jQuery уже был встроен в страницу.
Это расширение используется для встраивания jQuery в любую страницу, которую вы хотите. Он позволяет использовать jQuery в оболочке консоли (вы можете вызвать консоль Chrome с помощью "Ctrl+Shift+j").
чтобы встроить jQuery в выбранную вкладку, нажмите кнопку расширения.
ссылка на расширение: https://chrome.google.com/extensions/detail/gbmifchmngifmadobkcpijhhldeeelkc