3

Safariの新しいタブを特定のURLにリダイレクトしようとしています。つまり、デフォルトの新しいタブページを変更しています。ただし、リンクをたどって開いた新しいタブをリダイレクトしたくありません。

Windows and Tabs APIは、タブの「開く」イベントを記述しますが、これらは、新しいタブが開いたときに発生します(リンクから開かれた新しいタブを含む)。

新しいタブボタンをクリックして作成されたタブのみの新しいタブイベントをキャッチする方法はありますか?

4

1 に答える 1

8

openイベントハンドラーで、最初にイベントターゲットがタブであるかどうかを確認します。beforeNavigateそうである場合は、そのタブでイベントのイベントハンドラーを登録します。beforeNavigateまた、たとえば50ミリ秒以内にイベントが発生しない場合は、ハンドラーの登録を解除するためのタイムアウトを設定します。例えば:

function handleOpen(e) {
    if (e.target instanceof SafariBrowserTab) {
        e.target.addEventListener('beforeNavigate', handleBeforeNavigate, false);
        setTimeout(function () {
            e.target.removeEventListener('beforeNavigate', handleBeforeNavigate, false);
        }, 50);
    }
}

現在、beforeNavigateタブを開いたイベントに続くイベントに関連する3つの可能な結果があります。

ケース1beforeNavigateイベントはタイムアウト内に発生しません。これは通常、タブが空であることを意味します。空のタブはリンククリックの結果ではないので、タイムアウト関数にコードを入れて、好きなことをすることができます。

function handleOpen(e) {
    if (e.target instanceof SafariBrowserTab) {
        e.target.addEventListener('beforeNavigate', handleBeforeNavigate, false);
        setTimeout(function () {
            e.target.removeEventListener('beforeNavigate', handleBeforeNavigate, false);
            takeOverTab();
        }, 50);
    }
}

ケース2beforeNavigateイベントが発生し、そのurlプロパティの値は。になりnullます。これは、タブがトップサイトページまたはブックマークページ(新しいタブのオプションの1つである2つの特別なSafariページ)のいずれかをロードすることを意味します。空のタブのように、そのようなタブはリンククリックの結果ではない可能性があるため、タブを使用して好きなことを行うことができます。例えば:

function handleBeforeNavigate(e) {
    e.target.removeEventListener('beforeNavigate', handleBeforeNavigate, false);
    if (e.url === null) {
        takeOverTab();
    }
}

ケース3beforeNavigateが起動し、そのurl値は空でない文字列、つまり実際のURLになります。これはトリッキーなケースです。タブは、リンクのクリック、new-tabコマンド(ユーザーが自分のホームページに新しいタブを開くようにSafariを構成している場合)、または別のアプリや拡張機能のアクションのいずれかによって発生した可能性があるためです。タブがリンククリックの結果である場合をケース3Aと呼びましょう。new-tabコマンドの結果である場合、ケース3B。その他のアプリのケース、ケース3C。

3Bと3Cを区別する方法が思いつかない。これらの2つのケースを区別する方法が本当にない場合は、他のアプリによって開かれているタブをリダイレクトしたくないと思われるため、アプリにとって非常に悪い可能性があります。

アプリが3Cタブに干渉するかどうかを気にしない場合は、3Aタブと3B/3Cタブを区別する方法が少なくとも1つあります。これは私に起こる方法です:

  • すべてのページに挿入されたスクリプトを使用して、リンクのクリックをリッスンします。リンクがクリックされたら、URLとクリックの時刻をグローバルページに中継します。グローバルページは、後で参照できるようにそれらを記憶しています。例えば:

    function handleMessage(e) {
        if (e.name === 'linkClicked') {
            lastClickedLinkUrl = e.message.url;
            lastLinkClickTime = e.message.clickTime;
        }
    }
    
  • beforeNavigateハンドラーで、イベントのurl値が最後にクリックされたリンクのURLと異なるかどうかをテストします。そうである場合、新しいタブはそのリンククリックの結果ではないため、リンククリックの結果ではない可能性があります。2つのURLが同じである場合は、たとえば、最後のリンククリックから100ミリ秒以上経過していないかどうかを確認します。その場合、URLが同じであるのは偶然の一致である可能性が高いため、新しいタブはリンクのクリックによるものではないと推測できます。例えば:

    function handleBeforeNavigate(e) {
        e.target.removeEventListener('beforeNavigate', handleBeforeNavigate, false);
        if (e.url === null) {
            takeOverTab();
        } else if (e.url !== lastClickedLinkUrl || (new Date) - lastLinkClickTime > 100) {
            takeOverTab();
        }
    }
    

この検出方法は絶対確実ではないことに注意してください。おそらく、うまくいかない可能性のあるいくつかの方法があります。それでも、これがお役に立てば幸いです。

于 2012-04-14T23:57:09.403 に答える