¿Cómo puedo usar jQuery en las secuencias de comandos de Greasemonkey en Google Chrome?

Como algunos de ustedes saben, Google Chrome ha puesto una gran limitación en los scripts de Greasemonkey.

Chromium no es compatible con @require , @resource , unsafeWindow , GM_registerMenuCommand , GM_setValue o GM_getValue .

Sin necesidad, no puedo encontrar una manera de incluir la biblioteca jQuery en el script de Greasemonkey bajo Google Chrome.

¿Alguien tiene algún consejo en este asunto?

De “Consejo de usuario: Sugerencia: uso de jQuery – Blog de 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); 

He escrito algunas funciones basadas en el script de Erik Vold para ayudarme a ejecutar funciones, código y otros scripts en un documento. Puede usarlos para cargar jQuery en la página y luego ejecutar el código bajo el scope de la window global.

Ejemplo de uso

 // ==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"); }); 

Puede hacer clic aquí para instalarlo, si confía en que no estoy intentando engañarlo para que instale algo malicioso y que nadie haya editado mi publicación para señalar a otra cosa. Recargue la página y debería ver un borde alrededor de mi publicación.

Funciones

load(url, onLoad, onError)

Carga el script en url en el documento. Opcionalmente, se pueden proporcionar devoluciones de llamada para onLoad y onError .

execute(functionOrCode)

Inserta una función o cadena de código en el documento y lo ejecuta. Las funciones se convierten en código fuente antes de insertarse, por lo que pierden su scope / cierre actual y se ejecutan debajo del scope de la window global.

loadAndExecute(url, functionOrCode)

Un atajo; esto carga un script desde url , luego inserta y ejecuta functionOrCode si tiene éxito.

Código

 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); }); } 

Use jQuery sin miedo a conflictos , llamando a jQuery.noConflict(true) . Al igual que:

 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); } 


Pero, para los scripts de navegador cruzado, ¿por qué no aprovechar una copia local, rápida y agradable de jQuery, cuando puede?

Lo siguiente funciona como un script de usuario de Chrome y un script de Greasemonkey, y usa la bonita copia de @require local de jQuery, si la plataforma lo admite.

 // ==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); } 

Si la página ya tiene jQuery, solo sigue esta plantilla:

 // ==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); 

Hay una manera muy fácil de desplazarse, incluida una copia completa de las secuencias de comandos de jQuery para Chrome, cuando esas secuencias de comandos no utilizan ninguna función privilegiada ( funciones GM_ *, etc.) …

¡Simplemente inserte el script en la página DOM y ejecútelo! La mejor parte es que esta técnica funciona igual de bien en Firefox + Greasemonkey, por lo que puede usar el mismo script para ambos:

 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(); } 

(sin arrepentir robo de Shog9 en meta.stackoverflow ya que no lo movió aquí, y tengo que eliminar la meta publicación ..)

La forma más simple es usar la palabra clave required :

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

Además, podría empaquetar su script con la extensión de jQuery a Chrome. Vea las secuencias de comandos de contenido de Google Chrome .

Las extensiones de Chrome, a diferencia de las secuencias de comandos de Greasemonkey, se pueden actualizar automáticamente.

Solución más fácil: corte y pegue los contenidos de jquery.min.js en la parte superior de su script de usuario. Hecho.

Encontré varios problemas con las respuestas recomendadas. La solución addJQuery () funciona en la mayoría de las páginas pero tiene errores en muchos. Si se encuentra con problemas solo copie y pegue los contenidos de jquery en su secuencia de comandos.

Me pregunto si no podrías confiar en document.defaultView.jQuery en tu script de 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($); } 

Otro enfoque sería modificar su script para cargar jQuery manualmente. Ejemplo de 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! Después de las pruebas, parece que este código no funciona, ya que Google Chrome ejecuta las secuencias de comandos / extensiones de usuario en un ámbito / proceso separado de la página web real. Puede descargar el código de jQuery utilizando una XmlhttpRequest y luego evaluarlo, pero debe alojar el código en un servidor que permita compartir recursos de origen cruzado utilizando el encabezado Access-Control-Allow-Origin: * . Tristemente NINGUNO de los CDN actuales con jQuery lo admiten.

Extensión perfecta para insertar jQuery en Chrome Console tan simple como te puedas imaginar. Esta extensión también indaga si jQuery ya ha sido incluido en la página.

Esta extensión solía incrustar jQuery en cualquier página que desee. Permite utilizar jQuery en el shell de la consola (Puede invocar la consola de Chrome mediante “Ctrl + Shift + j”).

Para insertar jQuery en la pestaña seleccionada, haga clic en el botón de extensión.

ENLACE a la extensión: https://chrome.google.com/extensions/detail/gbmifchmngifmadobkcpijhhldeeelkc