Google Chrome'daki Greasemonkey komut dosyalarında jQuery'yi nasıl kullanabilirim?


157

Bazılarınızın bildiği gibi Google Chrome, Greasemonkey komut dosyalarında bazı ciddi sınırlamalar getirdi.

Krom desteklemez @require, @resource, unsafeWindow, GM_registerMenuCommand, GM_setValue, veya GM_getValue.

Gerek olmadan, jQuery kitaplığını Google Chrome altında Greasemonkey komut dosyasına dahil etmenin bir yolunu bulamıyorum.

Bu konuda bir tavsiye var mı?


19
Tampermonkey ile Google Chrome'un şimdilik desteğe sahip olduğunu belirtmek gerekir @require, ki bu cevaplardaki yanıtlardan çok daha basit bir yaklaşımdır.
Steen Schütt

2
Tampermonkey ayrıca zaten jQuery olan sayfalar için çok hoş olan güvenli olmayan Windows'u da destekler. var $ = unsafeWindow.jQuery;
Tim Goodman

1
@requireyükleme sırasında $ 'a bağlanan binlerce veya milyonlarca diğer JS kütüphanesinden herhangi biri ile çakışmaktan endişe duymadığınız sitelerde harika çalışıyor. Bununla birlikte, başka bir şey için $ kullanarak bir site için komut dosyası yazıyorsanız veya daha önce her sitede çalışacak bir komut dosyası yazıyorsanız, aşağıdaki tghw tarafından açıklanan nispeten güvenli yükleme mekanizmasını kullanın .
GDorn

Yanıtlar:


192

Gönderen ": - Erik Vold en blog kullanma jQuery Kullanıcı Senaryo İpucu"

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

'Load' için addEventListener içindeki 3 satır yerine "callback ();" sadece iş?
crdx

6
Sayfam zaten jQuery içeriyor, ancak kullanıcı kodunda jQuery kullanmak için yukarıdaki kod hala gerekli görünüyor. Ancak, iki jQuery dahilinde çakışma olabilir, bu nedenle main () işlevinizin ilk satırının jQuery.noConflict () olması gerekebilir;
slolife

2
Çizgiyi değiştirdiniz script.textContent = "(" + callback.toString() + ")();";için script.textContent = "jQuery.noConflict();(" + callback.toString() + ")();";kendi kullanıcı komut dosyası şablonunda yüzden herhangi şaşırtıcı çakışma olmayacaktır. :)
RCE

1
@hippietrail içinde main(), $.loadScript()loadScript jQueryUI yüklemesi tamamlandığında, her şeyi kullanabilir ve sonra çalıştırabilirsiniz.
tghw

1
-1: Bu yöntemle, içindeki kod mainhedef sayfanın bağlamında yürütülür, yani (diğer şeylerin yanı sıra) hedef sayfanın siteler arası istek ilkesi uygulanır - (örneğin GM_xmlhttpRequest, yapıldığını görmeden önce reddetmek zorunda kaldım) yardım etmeyin). Sonunda sadece kopya kodunu yapıştırdı jquery.min.js.
Jean Hominal

43

Erik Vold'un komut dosyasını temel alan birkaç işlev yazdım ve bir belgede işlevleri, kodu ve diğer komut dosyalarını çalıştırmamı sağladım . Bunları, sayfaya jQuery yüklemek ve sonra genel windowkapsam altında kod çalıştırmak için kullanabilirsiniz .

Örnek Kullanım

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

Yüklemek için buraya tıklayabilirsiniz , sizi kötü niyetli bir şey yüklemeye kandırmaya çalışmadığımı ve hiç kimsenin gönderimi başka bir şeye işaret edecek şekilde düzenlemediğini düşünüyorsanız. Sayfayı yeniden yükleyin ve yazımın çevresinde bir kenarlık görmelisiniz.

Fonksiyonlar

load(url, onLoad, onError)

Komut dosyasını urlbelgeye yükler . İsteğe bağlı olarak, geri aramalar için sağlanabilir onLoadve onError.

execute(functionOrCode)

Belgeye bir işlev veya kod dizesi ekler ve yürütür. İşlevler eklenmeden önce kaynak koduna dönüştürülür, böylece geçerli kapsamlarını / kapanışlarını kaybederler ve genel windowkapsamın altında çalıştırılırlar .

loadAndExecute(url, functionOrCode)

Bir kısayol; bu bir komut dosyasını yükler url, ardından functionOrCodebaşarılı olursa ekler ve yürütür .

kod

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

@cyphunk Evet, bu birkaç karakteri kurtarmak benim için çok önemliydi. Aslında, bu gönderiyi bu kadar anlamsız kullanarak bıraktığım için kendimi aptal hissediyorum. Ben kaldıracağım.
Jeremy Banks

18

Çatışma korkusu olmadan arayarak jQuery kullanın jQuery.noConflict(true). Şöyle ki:

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


Ancak, tarayıcılar arası komut dosyaları için, neden mümkün olduğunda güzel, hızlı, yerel bir jQuery kopyasından yararlanmıyorsunuz?

Aşağıdakiler bir Chrome kullanıcı metni ve bir Greasemonkey komut dosyası olarak çalışır @requireve platform destekliyorsa jQuery'nin güzel yerel kopyasını kullanır .

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

3
+1 Etkileyici, tüm bu cevapların arasından @require'ı kullanmanız gerektiğini söyleyen tek yanıt, sayfanın jQuery'si $ = unsafeWindow.jQueryvarsa da kullanabilirsiniz (bunu sadece Tampermonkey'de test ettim).
AMK

Uyarı: dev araçlarını yüklemediğiniz sürece IE'nin bazı sürümlerinde console.log () yoktur, bu nedenle komut dosyası kilitlenir. Genellikle bunu sadece senaryonuzu geliştiricilerin ve KG halkının ötesinde yayınladıktan sonra keşfedersiniz.
Ayrıştırma

1
@Parsingphase, IE burada hemen hemen NA. Son kontrol ettiğimde IE hala kullanıcı metinlerini iyi desteklemiyor (¿hiç?). IE 10 ile bu değişti mi?
Brock Adams

Brock - iyi bir nokta, IE'nin uyumsuzluk matrisini kafamda tutmakta başarısız oluyorum. Yani, doğrudan kullanıcı senaryoları için geçerli değildir (her zaman insanların bir IE çözümü uygulamaya çalıştığı görülmesine rağmen), ancak genel bir gotcha'dan daha fazlasıdır.
Ayrıştırma

15

Sayfada zaten jQuery varsa, şu şablonu izleyin:

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

Ben bunun usercript belge penceresine erişimi olmadığı için işe yaradığını sanmıyorum?
Christoph

@Christoph Çalışıyor, ben var ve ben hala bu yöntemi kullanarak bir usercript kullanıyorum.
Kasım'da Mottie

1
Bu aslında greasemonkey betiğini sayfaya enjekte ediyor. Muhtemelen greasemonkey'in sahip olduğu bazı güvenlik önlemlerini atlıyor.
Timin

1
@Thymine Bu yöntemin usercript'i istenmeyen sayfalara enjekte ettiğini fark ettim. Enjeksiyon bölümünü ifkontrol eden bir ifadede sarmak zorunda kaldım window.location.
Mottie

12

Basit yol requiredanahtar kelimeyi kullanmaktır :

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

Yalnızca uzantı uygulaması tarafından desteklenir.
user2284570

@ user2284570 Herhangi bir tarayıcı için bulabildiğim her kullanıcı metni uzantısı tarafından destekleniyor.
Matt M.

@MattM. Yani kullanıcı metinlerini çalıştırmak için Opera ve Chrome'a ​​bir uzantı yüklemenize gerek yoktur.
user2284570

7

Bu komut dosyaları gerçekten herhangi bir ayrıcalıklı özellik (GM_ * işlevleri vb.) Kullanmıyorsa , Chrome komut dosyalarının tam bir kopyasını dahil etmenin gerçekten kolay bir yolu vardır ...

Betiğin kendisini DOM sayfasına eklemeniz ve çalıştırmanız yeterlidir! En iyi yanı, bu tekniğin Firefox + Greasemonkey'de olduğu gibi çalışmasıdır, böylece her ikisi için de aynı komut dosyasını kullanabilirsiniz:

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

(burada hareket etmediği için meta.stackoverflow'da Shog9'dan unapologetically çalındı ​​ve meta yayını silmek zorundayım ..)


4

Ayrıca, komut dosyanızı jQuery to Chrome uzantısıyla paketleyebilirsiniz. Bkz Google Chrome'un İçerik Scripts .

Chrome uzantıları, Greasemonkey komut dosyalarının aksine kendini otomatik olarak güncelleyebilir.


2
evet, daha kolay olurdu. Ama gerçekten scriptimi şimdilik userscripts.org üzerinden tutmayı ve google uzantıları deposuyla artıklık oluşturmamayı tercih ediyorum.
Alekc

4
Google Web Mağazası'na yükleme 5 ABD dolarıdır.
Camilo Martin

4

Daha kolay çözüm: jquery.min.js içeriğini kesin + kullanıcı komut dosyanızın üstüne yapıştırın. Bitti.

Önerilen cevaplarla ilgili çeşitli sorunlar buldum. AddJQuery () çözümü çoğu sayfada çalışır, ancak birçok sayfada hata vardır. Sorunlarla karşılaşırsanız jquery içeriğini kopyalayın + betiğinize yapıştırın.


Evet, bence bu en mantıklı.
dkinzer

2

document.defaultView.jQueryGM script ala güvenemiyorum merak ediyorum :

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

1

Başka bir yaklaşım, jQuery'yi manuel olarak yüklemek için komut dosyanızı değiştirmek olacaktır. Http://joanpiedra.com/jquery/greasemonkey/ adresinden bir örnek :

// 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
}

DÜZENLEME: DRATS! Testten sonra, Google Chrome kullanıcı metinlerini / uzantılarını gerçek web sayfasından ayrı bir kapsamda / işlemde çalıştırdığından bu kod çalışmaz. JQuery kodunu bir XmlhttpRequest kullanarak indirebilir ve daha sonra Değerlendirebilirsiniz, ancak kodu başlığı kullanarak Çapraz Kaynak Kaynağı Paylaşımına izin veren bir sunucuda barındırmanız gerekir Access-Control-Allow-Origin: *. Ne yazık ki jQuery ile mevcut CDN'lerin YOK bunu destekliyor.


-1

JQuery'yi Chrome Konsoluna tahmin edebileceğiniz kadar basit bir şekilde gömmek için mükemmel uzantı. Bu uzantı, jQuery'nin zaten sayfaya gömülmüş olup olmadığını da gösterir.

Bu uzantı, jQuery'yi istediğiniz herhangi bir sayfaya gömmek için kullanılır. Konsol kabuğunda jQuery kullanılmasına izin verir (Chrome konsolunu "Ctrl + Shift + j" ile başlatabilirsiniz).

JQuery'yi seçili sekmeye gömmek için genişletme düğmesine tıklayın.

Uzantıya LINK: https://chrome.google.com/extensions/detail/gbmifchmngifmadobkcpijhhldeeelkc


Bu gerçekten cevap değil. Gerekmiyorsa neden jQuery yüklemek isteyeyim?
Vik
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.