2

FireFox で unsafeWindow を使用するスクリプトを使用していますが、それが機能しなかったため、別のオプションを検索して見つけました。

私のコードは次のとおりです。

// ==UserScript==
// @name   Test
// @description  Test
// @include   http://www.google*
// ==/UserScript==

var toAlert = "This is what I want to alert...";
alert("Before implementation...");
contentEval( function(){ alert(toAlert);});
alert("And after...");
function contentEval(source) {
  // Check for function input.
  if ('function' == typeof source) {
    // Execute this function with no arguments, by adding parentheses.
    // One set around the function, required for valid syntax, and a
    // second empty set calls the surrounded function.
    source = '(' + source + ')();'
  }

  // Create a script node holding this  source code.
  var script = document.createElement('script');
  script.setAttribute("type", "application/javascript");
  script.textContent = source;

  // Insert the script node into the page, so it will run, and immediately
  // remove it to clean up.
  document.body.appendChild(script);
  document.body.removeChild(script);
}

そして、それは機能しません...何が間違っていますか?

4

1 に答える 1

4

toAlertたまたまページのグローバルスコープで定義されていれば、スクリプトは機能します。

Chrome では、拡張機能/Greasemonkey JavaScript は変数やクロージャをページ JavaScript と共有できません。
そのため、その関数を拡張スコープからページ スコープに直接注入することはできず、ソース文字列から再作成する必要があります。

これは、ページ スコープで関数を作成する場合、関数に必要な変数または関数は次のいずれかでなければならないことを意味します。

  1. ソースページにすでにグローバルに存在している。
    または
  2. ソースページにもスクリプト化されます。

たとえば、コードを次のように変更すると...

//-- Must recreate the variable that the function requires.
scriptStr  = 'var toAlert="' + toAlert +'";';

//-- Now the function.
scriptStr += '(' + source.toString() + ')();'

var script = document.createElement('script');
script.textContent = scriptStr;

...うまくいきますが、このアプローチは明らかに面倒です。

(A) すべてのJavaScript
を拡張機能に保持する。ページの JavaScript を操作しないでください。

または (B) ページの JS とやり取りする必要がある場合、または jQuery などのライブラリをロードする必要がある場合は、すべてのコードを 1 つの main() 関数に入れ、それをソース ページにスクリプト化します。

そのようです:

function localMain ()
{
    /*--- Put EVERYTHING inside this wrapper, functions and variables.
        Call or use nothing else that's defined in the GM script here.
        Can use objects in the source page's scope, though.
    */
}

//--- Now create the function in the page's scope and run it.
var scriptNode          = document.createElement ("script");
scriptNode.textContent  = localMain.toString() + "\n localMain ();";
document.head.appendChild (scriptNode);

ページのスコープにライブラリもロードしている場合localMain()は、タイマーとそのライブラリのチェックを使用して実行を遅らせる必要がある場合があることに注意してください。

于 2010-09-09T18:40:56.167 に答える