How can I use jQuery in Greasemonkey scripts in Google Chrome?

后端 未结 11 1163

As some of you may know, Google Chrome has put some severe limitation on Greasemonkey scripts.

Chromium does not support @require,

相关标签:
11条回答
  • 2020-11-22 10:14

    The simple way is using required keyword:

    // @require     http://code.jquery.com/jquery-latest.js
    
    0 讨论(0)
  • 2020-11-22 10:16

    I have written a few functions based on the Erik Vold's script to help run me run functions, code and other scripts in a document. You can use them to load jQuery into the page and then run code under the global window scope.

    Example Usage

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

    You can click here to install it, if you trust that I'm not trying to trick you into installing something malicious and that nobody has edited my post to point to something else. Reload the page and you should see a border around my post.

    Functions

    load(url, onLoad, onError)

    Loads the script at url into the document. Optionally, callbacks may be provided for onLoad and onError.

    execute(functionOrCode)

    Inserts a function or string of code into the document and executes it. The functions are converted to source code before being inserted, so they lose their current scope/closures and are run underneath the global window scope.

    loadAndExecute(url, functionOrCode)

    A shortcut; this loads a script from url, then inserts and executes functionOrCode if successful.

    Code

    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); });
    }
    
    0 讨论(0)
  • 2020-11-22 10:21

    Easier solution: cut+paste the contents of jquery.min.js into the top of your user script. Done.

    I found various problems with the recommended answers. The addJQuery() solution works on most pages but has bugs on many. If you run into issues just copy+paste the jquery contents into your script.

    0 讨论(0)
  • 2020-11-22 10:22

    Use jQuery without fear of conflicts, by calling jQuery.noConflict(true). Like so:

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


    But, For cross-browser scripts, why not take advantage of a nice, fast, local copy of jQuery, when you can?

    The following works as a Chrome userscript and a Greasemonkey script, and it uses the nice local @require copy of jQuery, if the platform supports it.

    // ==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);
    }
    
    0 讨论(0)
  • 2020-11-22 10:27

    Another approach would be to modify your script to load jQuery manually. Example from 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! After testing it appears this code does not work since Google Chrome runs userscripts/extensions in a separate scope/process from the actual webpage. You can download the jQuery code using an XmlhttpRequest and then Eval it, but you have to host the code on a server that allows Cross-Origin Resource Sharing using the Access-Control-Allow-Origin: * header. Sadly NONE of the current CDNs with jQuery support this.

    0 讨论(0)
提交回复
热议问题