41

一連の要素を反復処理する GreaseMonkey スクリプトを作成しています。要素ごとに、後でその要素を参照するために使用できる文字列 ID が必要です。要素自体にはid属性がなく、元のドキュメントを変更して属性を与えることはできません (ただし、スクリプトで DOM を変更することはできます)。参照が必要になったときに、GreaseMonkey スクリプト自体が範囲外になるため、参照をスクリプトに保存できません。たとえば、ブラウザが使用する「内部」IDを取得する方法はありますか? Firefox のみのソリューションで問題ありません。他のシナリオに適用できるクロスブラウザー ソリューションは素晴らしいものです。

編集:

  • GreaseMonkey スクリプトが範囲外の場合、後で要素をどのように参照していますか? 彼らの GreaseMonkey スクリプトは、イベントを DOM オブジェクトに追加しています。参照を配列または他の同様のメカニズムに格納することはできません。イベントが発生すると、GreaseMonkey スクリプトが範囲外になるため、配列がなくなるためです。そのため、イベントは、イベントがアタッチされたときにスクリプトが持っていた要素参照について何らかの方法で知る必要があります。問題の要素は、それが接続されている要素ではありません。

  • 要素にカスタム プロパティを使用することはできませんか? はい、しかし問題はルックアップにあります。そのカスタムプロパティが目的のIDに設定されているものを探して、すべての要素を繰り返し処理する必要があります。それは確かに機能しますが、大きなドキュメントでは非常に時間がかかる可能性があります. 私は、ブラウザが検索の面倒な作業を実行できるものを探しています。

  • ドキュメントを変更できるかできないか? ソース ドキュメントを変更することはできませんが、スクリプトで DOM を変更することはできます。質問で明確にします。

  • クロージャーを使用できませんか?Closuses は機能することが判明しましたが、最初は機能しないと思っていました。私の後の投稿を参照してください。

「使用できる内部ブラウ​​ザ ID はありますか?」という質問に対する答えのように思えます。は「いいえ」です。

4

13 に答える 13

10

閉鎖は行く方法です。このようにして、DOMのシャッフルにも耐えられる要素への正確な参照が得られます。

クロージャを知らない人のための例:

var saved_element = findThatDOMNode();

document.body.onclick = function() 
{
   alert(saved_element); // it's still there!
}

Cookieに保存する必要がある場合は、XPathを計算することをお勧めします(たとえば、IDを持つ要素が見つかるまで、前の兄弟を数えてDOMを上に移動すると、次のようになります[@id=foo]/div[4]/p[2]/a)。

XPointerは、その問題に対するW3Cのソリューションです。

于 2008-10-22T19:26:28.997 に答える
10

答えはノーです。アクセスできる内部IDはありません。OperaとIE(おそらくSafari?)はサポート.sourceIndexしています(DOMがサポートしている場合は変更されます)が、Firefoxにはこの種のものはありません。

特定のノードへのXpathを生成するか、document.getElementsByTagName('*')常にソースの順序で要素を返すノードのインデックスを見つけることにより、ソースインデックスをシミュレートできます。

もちろん、これには完全に静的なファイルが必要です。DOMを変更すると、ルックアップが壊れます。

私が理解していないのは、ノードへの参照を失うことができるが、(理論上の)内部IDへの参照を失うことができない方法です。クロージャと割り当てが機能するか、機能しないかのどちらかです。それとも私は何かが足りないのですか?

于 2008-10-22T17:40:45.200 に答える
7

あなたの質問の言い回しに少し混乱しています-あなたは「[あなた]が後でその要素を参照するために使用できる文字列IDが必要です」と言っていますが、「[あなたの]スクリプトに参照を保存することはできません.それらが必要な場合、GreaseMonkey スクリプト自体は範囲外になります。」

スクリプトが範囲外になる場合、後でそれらをどのように参照していますか?!

私は、あなたが理解していることに混乱しているという事実を無視し、Greasemonkey スクリプトを頻繁に作成し、アクセスする DOM 要素を変更してそれらに ID プロパティを与えることができることを伝えます。これは、一時的に使用する疑似一意の値を取得するために使用できるコードです。

var PseudoGuid = new (function() {
    this.empty = "00000000-0000-0000-0000-000000000000";
    this.GetNew = function() {
        var fourChars = function() {
            return (((1 + Math.random()) * 0x10000)|0).toString(16).substring(1).toUpperCase();
        }
        return (fourChars() + fourChars() + "-" + fourChars() + "-" + fourChars() + "-" + fourChars() + "-" + fourChars() + fourChars() + fourChars());
    };
})();

// usage example:
var tempId = PseudoGuid.GetNew();
someDomElement.id = tempId;

それは私にとってはうまくいきます.Greasemonkeyスクリプトで自分でテストしました.


更新:クロージャーは行くべき道です - 個人的には、筋金入りの JavaScript 開発者として、なぜあなたがすぐにクロージャーを考えなかったのかわかりません。:)

myDomElement; // some DOM element we want later reference to

someOtherDomElement.addEventListener("click", function(e) {
   // because of the closure, here we have a reference to myDomElement
   doSomething(myDomElement);
}, false);

さて、myDomElementあなたの説明から、明らかにあなたがすでに持っている要素の1つです(IDを追加することを考えていたので)。

おそらく、あなたがやろうとしていることの例を投稿すると、これがそうではないと仮定して、あなたを助けるのがより簡単になるでしょう.

于 2008-10-22T17:52:45.317 に答える
5

更新:閉鎖は確かに答えです。それで、もう少しそれをいじった後、私はクロージャが最初に問題であった理由とそれを修正する方法を理解しました。クロージャのトリッキーな点は、要素を反復処理するときに、すべてのクロージャが同じ要素を参照することにならないように注意する必要があることです。たとえば、これは機能しません。

for (var i = 0; i < elements.length; i++) {
    var element = elements[i];
    var button = document.createElement("button");
    button.addEventListener("click", function(ev) {
        // do something with element here
    }, false)
}

しかし、これはします:

var buildListener = function(element) {
    return function(ev) {
        // do something with event here
    };
};

for (var i = 0; i < elements.length; i++) {
    var element = elements[i];
    var button = document.createElement("button");
    button.addEventListener("click", buildListener(element), false)
}

とにかく、質問には2つの回答があったため、1つの回答を選択しないことにしました。1)いいえ、使用できる内部IDはありません。2)これにはクロージャを使用する必要があります。だから私は、内部IDがあるのか​​、IDの生成を勧めたのか、そして閉鎖について言及した人のことを最初に言った人たちに賛成した。助けてくれてありがとう!

于 2008-10-23T15:12:45.967 に答える
4

DOM に書き込むことができる場合(できると確信しています)。私はこれを次のように解決します:

関数に ID を返すか生成させる:

//(function () {

  var idCounter = new Date().getTime();
  function getId( node ) {
    return (node.id) ? node.id : (node.id = 'tempIdPrefix_' + idCounter++ );
  }

//})();

これを使用して、必要に応じて ID を取得します。

var n = document.getElementById('someid');
getId(n);  // returns "someid"

var n = document.getElementsByTagName('div')[1];
getId(n);  // returns "tempIdPrefix_1224697942198"

こうすれば、サーバーから HTML が渡されたときに HTML がどのように見えるかを気にする必要がなくなります。

于 2008-10-22T18:04:57.023 に答える
3

DOMを変更していない場合は、インデックス付きの順序ですべてを取得できます。

プロトタイプ例)

myNodes = document.body.descendants()
alert(document.body.descendants()[1].innerHTML)

すべてのノードをループして、後で簡単に選択できる一意のclassNameをノードに付けることができます。

于 2008-10-22T17:38:43.597 に答える
2

id 属性を計算値に設定できます。プロトタイプ ライブラリには、これを実行できる関数があります。

http://www.prototypejs.org/api/element/identify

私のお気に入りの JavaScript ライブラリは jQuery です。残念ながらjQueryにはidentifyのような機能がありません。ただし、id 属性を独自に生成した値に設定することはできます。

http://docs.jquery.com/Attributes/attr#keyfn

ページ内の位置に基づいて div の id を設定する jQuery ドキュメントの部分的なスニペットを次に示します。

  $(document).ready(function(){

    $("div").attr("id", function (arr) {
          return "div-id" + arr;
        });
  });
于 2008-10-22T17:30:12.633 に答える
1

要素のマウスおよび/または位置プロパティを使用して、一意の ID を生成します。

于 2010-03-26T18:10:42.157 に答える
0

これに似た問題を解決したと「思います」。ただし、ブラウザー DOM 環境で jQuery を使用しています。

var objA = $("いくつかの dom 要素へのセレクター"); var objB = $("selector to some other dom element");

if( objA[0] === objB[0]) { //素晴らしい! 2 つのオブジェクトがまったく同じ dom ノードを指している }

于 2010-03-30T16:18:57.830 に答える
0

一意の識別子の生成に pguid (ページ固有の識別子) を使用することもできます。

 pguid = b9j.pguid.next() // A unique id (suitable for a DOM element)
                          // is generated
                          // Something like "b9j-pguid-20a9ff-0"
 ...
 pguid = b9j.pguid.next() // Another unique one... "b9j-pguid-20a9ff-1"

 // Build a custom generator
 var sequence = new b9j.pguid.Sequence({ namespace: "frobozz" })
 pguid = sequence.next() "frobozz-c861e1-0"

http://appengine.bravo9.com/b9j/documentation/pguid.html

于 2008-10-24T02:44:32.763 に答える
0

JavaScript では、カスタム ID フィールドをノードにアタッチできます。

if(node.id) {
  node.myId = node.id;
} else {
  node.myId = createId();
}

// store myId

ちょっとしたハックですが、すべてのノードに使用できる ID が与えられます。もちろん、document.getElementById()それに注意を払うことはありません。

于 2008-10-22T17:06:42.647 に答える