Chrome의 Greasemonkey 스크립트에서 jQuery를 사용하려면 어떻게해야하나요?


157

아시다시피, Chrome은 Greasemonkey 스크립트에 심각한 제한을 두었습니다.

크롬은 지원하지 않습니다 @require, @resource, unsafeWindow, GM_registerMenuCommand, GM_setValue, 또는 GM_getValue.

필요하지 않으면 jQuery 라이브러리를 Google Chrome의 Greasemonkey 스크립트에 포함시키는 방법을 찾을 수 없습니다.

이 문제에 대해 조언이 있습니까?


19
Tampermonkey가 포함 된 Chrome에서 @require현재 지원 하는 기능은 답변보다 훨씬 간단합니다.
Steen Schütt

2
Tampermonkey는 또한 unsafeWindow를 지원하는데, 이는 이미 jQuery가있는 페이지에 매우 좋습니다. var $ = unsafeWindow.jQuery;
Tim Goodman

1
@require로드시 $에 바인딩되는 수천 또는 수백만 개의 다른 JS 라이브러리와 충돌 할 염려가없는 사이트에서 훌륭하게 작동합니다. 그러나 다른 것을 위해 $를 사용하여 사이트에 대한 스크립트를 작성하거나 모든 사이트에서 실행할 스크립트를 더 잘못 작성하는 경우 아래 tghw로 설명되는 비교적 안전한 로딩 메커니즘을 사용하십시오 .
GDorn

답변:


192

에서 "- 에릭 Vold 사용자의 블로그 사용 jQuery를 사용자 스크립트 팁"

// ==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'에 대한 addEventListener 내의 3 줄 대신 "callback ();" 그냥 일이야?
crdx

6
내 페이지에는 이미 jQuery가 포함되어 있지만 사용자 스크립트에서 jQuery를 사용하려면 위의 코드가 여전히 필요한 것 같습니다. 그러나 두 개의 jQuery include가 충돌을 일으킬 수 있으므로 main () 함수의 첫 번째 행은 jQuery.noConflict ()이어야합니다.
slolife

2
내 사용자 스크립트 템플릿에서 줄 script.textContent = "(" + callback.toString() + ")();";을 수정하여 script.textContent = "jQuery.noConflict();(" + callback.toString() + ")();";놀라운 충돌이 발생하지 않도록했습니다. :)
RCE

1
@hippietrail에서을 main()사용 $.loadScript()하고 loadScript가 jQueryUI로드를 완료하면 다른 모든 항목을 실행할 수 있습니다.
tghw

1
-1 :이 방법 main을 사용하면 대상 페이지의 컨텍스트에서 코드 가 실행됩니다. 즉, 대상 페이지의 교차 사이트 요청 정책이 적용됩니다 (예 : GM_xmlhttpRequest코드가 제대로 작동하는지 확인하기 전에 다시 주입 해야 함). 도와주세요). 결국 나는 단순히 코드를 복사하여 붙여 넣었다 jquery.min.js.
Jean Hominal

43

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

악의적 인 것을 설치하도록 속이려고하지 않으며 다른 사람을 가리 키도록 내 게시물을 편집 한 사람이 아무도 없다고 믿는 경우 여기클릭 하여 설치할 수 있습니다 . 페이지를 다시로드하면 내 게시물 주위에 테두리가 나타납니다.

기능

load(url, onLoad, onError)

스크립트를 url문서에 로드합니다 . 선택적으로, 콜백이 제공 될 수있다 onLoadonError.

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

@cyphunk 네, 저 문자를 저장하는 것이 중요했습니다. 실제로, 나는이 게시물을 무의미하게 사용하여 남겨둔 것에 대해 꽤 바보 같은 느낌이 들었습니다. 제거하겠습니다.
Jeremy Banks

18

호출 하여 충돌에 대한 두려움없이 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 사용자 스크립트 및 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);
}

3
+1 인상적입니다.이 모든 답변 중에서 @require를 사용한다고 말한 유일한 답변 $ = unsafeWindow.jQuery은 페이지에 jQuery가있는 경우 에도 사용할 수 있습니다 (Tampermonkey 에서만 테스트했습니다).
AMK

주의 사항 : 일부 IE 버전에는 dev 도구를 설치하지 않으면 console.log ()가 없으므로 스크립트가 중단됩니다. 일반적으로 개발자 및 품질 보증 담당자 이외의 스크립트를 출시 한 후에 만이 사실을 발견 할 수 있습니다.
파싱 ​​단계

1
@Parsingphase, IE는 거의 NA입니다. 마지막으로 확인한 IE는 여전히 사용자 스크립트를 제대로 지원하지 않습니다 (¿ 전혀?). IE 10에서 변경 되었습니까?
Brock Adams

브록-좋은 지적, 나는 내 머리 속에 IE의 비 호환성 매트릭스를 유지하는 데 실패했다. 따라서 사용자 스크립트에 직접 적용 할 수는 없지만 사람들이 IE 솔루션을 구현하려고 시도하는 것처럼 보이지만 일반적인 문제는 더 많습니다.
파싱 ​​단계

15

페이지에 이미 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);

사용자 스크립트가 문서 창에 액세스 할 수 없기 때문에 이것이 효과가 없다고 생각합니까?
Christoph

@Christoph 그것은 작동하지만, 나는 이 방법을 사용하여 여전히 사용자 스크립트를 사용하고 있습니다.
Mottie

1
이것은 실제로 페이지에 greasemonkey 스크립트를 주입합니다. 아마도 그리스 몽키가 가지고있는 안전 장치를 우회 할 수 있습니다.
Thymine

1
@Thymine 나는이 방법이 사용자 스크립트를 원하지 않는 페이지에 주입한다는 것을 알았습니다. if을 확인 하는 문장으로 주입 부분을 포장해야 했습니다 window.location.
Mottie

12

간단한 방법은 required키워드를 사용하는 것입니다 .

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

확장 구현에서만 지원됩니다.
user2284570

@ user2284570 모든 브라우저에서 찾을 수있는 모든 사용자 스크립트 확장에서 지원됩니다.
Matt M.

@MattM. 사용자 스크립트를 실행하기 위해 Opera와 Chrome에 확장 프로그램을 설치할 필요가 없습니다.
user2284570

7

해당 스크립트가 실제로 권한 기능 (GM_ * 함수 등)을 사용하지 않는 경우 Chrome 용 jQuery 스크립트의 전체 사본을 포함하는 것이 가장 쉬운 방법입니다 ...

스크립트 자체를 페이지 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();
}

(단지 Meta.stackoverflow에서 Shog9에서 도용되지 않았으므로 메타 포스트를 삭제해야합니다.)


4

또한 jQuery to Chrome 확장 프로그램으로 스크립트를 포장 할 수 있습니다. Chrome의 콘텐츠 스크립트를 참조하십시오 .

Greasemonkey 스크립트와 달리 Chrome 확장 프로그램은 자동 업데이트 될 수 있습니다.


2
네, 더 쉬울 것입니다. 하지만 지금은 userscripts.org를 통해 스크립트를 유지하고 Google 확장 프로그램 저장소로 중복성을 생성하지 않는 것이 좋습니다.
Alekc

4
Google 웹 스토어에 업로드하는 데 5 달러가 소요됩니다.
Camilo Martin

4

더 쉬운 해결책 : jquery.min.js의 내용을 사용자 스크립트 상단에 잘라내어 붙여 넣기하십시오. 끝난.

권장 답변과 관련된 다양한 문제를 발견했습니다. addJQuery () 솔루션은 대부분의 페이지에서 작동하지만 많은 버그가 있습니다. 문제가 발생하면 jquery 내용을 스크립트에 복사하여 붙여 넣으십시오.


네, 여기에 제안한 것을 정확하게 수행하여 크롬 버전을 생성하는 작은 빌드 스크립트를 만들 수도 있기 때문에 이것이 가장 의미가 있다고 생각합니다.
dkinzer

2

document.defaultView.jQueryGM 스크립트 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($);
}

1

또 다른 방법은 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
}

편집 : 드래프트! Chrome에서 실제 웹 페이지와 별도의 범위 / 프로세스에서 사용자 스크립트 / 확장 프로그램을 실행하므로 테스트 후이 코드가 작동하지 않는 것 같습니다. XmlhttpRequest를 사용하여 jQuery 코드를 다운로드 한 다음 평가할 수 있지만 헤더를 사용하여 Cross-Origin Resource Sharing 을 허용하는 서버에서 코드를 호스팅해야합니다 Access-Control-Allow-Origin: *. 슬프게도 jQuery 가있는 현재 CDN 중 아무도 이것을 지원하지 않습니다.


-1

상상할 수있는 한 간단하게 jQuery를 Chrome 콘솔에 내장 할 수있는 완벽한 확장입니다. 이 확장은 jQuery가 이미 페이지에 포함되어 있는지 알려줍니다.

이 확장 프로그램은 jQuery를 원하는 페이지에 포함시키는 데 사용되었습니다. 콘솔 셸에서 jQuery를 사용할 수 있습니다 ( "Ctrl + Shift + j"로 Chrome 콘솔을 호출 할 수 있음).

선택한 탭에 jQuery를 포함하려면 확장 버튼을 클릭하십시오.

LINK to extension : https://chrome.google.com/extensions/detail/gbmifchmngifmadobkcpijhhldeeelkc


그것은 실제로 답이 아닙니다. 왜 필요하지 않은 경우 jQuery를로드하고 싶습니까?
Vik
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.