12

addon-sdk を使用して Firefox アドオンを開発しています。このアドオンはコンテキスト メニューにメニュー項目を追加し、ユーザーは任意の編集コントロールを右クリックしてこのメ​​ニュー項目をアクティブにできます。有効にすると、ユーザーが何かを入力すると、提案を含む小さなポップアップが表示されます。

Gmail 以外はすべて問題なく動作します。

Gmail では、以下のコードは失敗します。

self.port.on('showPopup', function(data) {
    var active = document.activeElement;
    console.log(active.type);
    if (active && getWordUnderCaret(active).word == data.input) {
        populateSuggestions(data);
        positionPopup(active);
        stylePopup();
    }
});

失敗の理由は、入力/テキスト領域コントロールを期待しているため、失敗したことを示していdocument.activeElementます。これは、他のすべての場所でうまく機能します。フォーカスが入力コントロールにあることがわかるので、なぜそれが指しているのかわかりません。Firebug コンソールに入力すると、適切なオブジェクトが表示されます。document.bodygetWordUnderCaretdocument.bodydocument.activeElement

または、を使用するのではなく、アクティブな要素を自分で追跡しようとしましたdocument.activeElement。しかし、これをどこかに永続化するなどの問題に遭遇しました。プロキシであるため、windowこれを永続化するために使用することはできません。windowで試しましunsafeWindowたが、動作させることができませんでした。

Gmailでこれが失敗するのはなぜですか? これを修正するための助けは素晴らしいでしょう!

私のコードはGithubで入手できます

編集

これは addon-sdk の問題のようです。問題を再現するために使用できる Gist を作成しました。ここで入手できます

4

2 に答える 2

12

メールを作成するときにメッセージ本文を入力する、Gmail の大きなボックスについて言及していると思います。

" そうだとすれば;

理由:

Gmail のその編集コントロールは、テキスト コントロール (input または textarea) ではありません。これは、設定によって(または ブラウザーのサポートに応じて)編集可能になる で実装されたWYSIWYGエディターです。<iframe>document.designMode = "on"document.body.contentEditable = true

したがって、クリックすると; この場合、クエリの方法で常に正しい要素を取得できるとは限りませんdocument.activeElement。ラッピング (メイン) ドキュメントの, body( でさえありません) を取得します。iframebody

例えば; あなたのコードのこの行で、私は信じています。clickイベント リスナーをメイン ドキュメントに追加します。ただし、ページ内の編集可能な iframeにも追加する必要があります。ページと iframe は異なるdocumentオブジェクトを持っているためです (そして、iframe はそれ自体をアクティブとして設定しません)。だから、あなたは間違っているでしょうdocument.activeElement

回避策:

必要なイベント リスナーも iframe に追加します。それらについての通知を受け取りたいので。

// Add mouseup event listener to the main document
document.addEventListener('mouseup', logActiveElement, false);
// Get all the iframes on the main document.
var iframeElems = document.getElementsByTagName('iframe');
// Add mouseup event listener to the document of the iframe elements
for (var i = 0; i < iframeElems.length; ++i) {
    addIframeEvent(iframeElems[i], true, 'mouseup', logActiveElement);
}

ヘルパー関数は次のとおりです
(メイン ドキュメントから iframe (ドキュメント) にイベント リスナーを追加する方法と、iframe が現在編集可能かどうかを確認する方法に注目してください)。

// Adds the specified event listener to the iframe element. 
function addIframeEvent(iframeElem, editableOnly, eventName, callback) {
    // Get the document of the iframe element.
    var iframeDocument = iframeElem.contentDocument || 
                            iframeElem.contentWindow.document;
    // Watch for editableOnly argument. 
    if ( (editableOnly && isDocEditable(iframeDocument)) || !editableOnly) {
        // Add the event listener to the document of the iframe element.
        iframeDocument.addEventListener(eventName, callback, false);
    }
}

// Checks whether the specified document is content-editable or in design mode.
function isDocEditable(doc) {
    return ( ('contentEditable' in doc.body) && (doc.body.contentEditable === true) ) || 
        ('designMode' in doc) && (doc.designMode == "on") );
}

// Handler function
function logActiveElement() {
    console.log("Active Element:", document.activeElement);
}

これで、イベント ハンドラーは正しいログactiveElementをコンソールに記録します。

合併症:

結果として; 既存のコードでのテキストの選択やインスペクションなどは、通常の編集コントロール (input、textarea など) と同じようには機能しません。

例えば; getWordUnderCaret(editor)関数は(ターゲットの) に存在しない を取得insertionPointします。このような選別・検査に。DOM SelectionsDOM Rangesを切り替える必要があります。テキスト編集コントロールのテキスト選択と範囲の代わりに。editor.selectionStartdocument.bodyiframe

注: 使用するテキスト選択/範囲 jQuery ライブラリ ( Rangy ) は、ブラウザー内でこの種の編集可能なコンテンツ (iframe、div など) を処理することを約束します。iframe で (Gmail などで) 試しましたか?

さらに詳しい情報:

  • Mozilla Developer Network でactiveElement のドキュメントを参照してください。さらに、「ドキュメント上の選択とフォーカスを混同しないでください。選択がない場合、 activeElementはページの<body>です。」

アップデート:

Gmail のテキスト コントロールを確認するには; 私もあなたのサンプルコードで遊んだ。

  • attachTo: ["existing", "top", "frame"]PageMod オプションに追加されました。
  • PageMod オプションでの値contentScriptWhen'end'( ではなく ) に変更しました。'ready'DOM、CSS、JS を含むすべてがロードされていることを確認します。一部のコンテンツは、ページの準備/読み込み時に JS を介して変更される可能性があるため、'end' はその後に実行されます。
  • メニュー項目にもセレクター コンテキストを適用しました。アイテムがセレクターコンテキスト中にのみ表示されるようにするため。

Gmail (検索ボックス、チャット ボックスなど) およびその他のサイトでテスト済み。これは機能しているようです。addon builderで実際の
を参照/テストしてください

Gmail 検索ボックスのテキスト入力

Gmail チャットボックスのテキストエリア

于 2013-01-24T04:16:57.893 に答える
3

アドオン SDK の最新の git バージョンを使用してみましたか? そこのコンテキスト メニューはゼロから書き直されており、かなりの数のバグが修正されていると聞きました。

于 2013-01-11T14:57:01.703 に答える