2

I'm using a bookmarklet to send the current page source to a server function which then processes it (stores it, no information needs to be returned to the user).

Warning: ugly Javascript ahead, it's not a language I normally need to use.

Here's the bookmarklet, pretty-printed for ease of reading:

javascript: (function () {
var h = document.documentElement.innerHTML;

function c(a, b) {
    var c = document.createElement("textarea");
    c.name = a;
    c.value = b;
    d.appendChild(c)
}(document), d = document.createElement("form");
d.method = "POST";
d.action = "http://example.com/do.php";
d.enctype = "multipart/form-data";
d.target = "_blank";
c("h", h);
c("u", "1234");
document.body.appendChild(d);
d.submit();
})();

This basically works, "do.php" receives the head and body sections in form variable h.

ただし、各ページで 1 回しか機能しないようです。同じページに対してブックマークレットを 2 回押しても、何も起こりません。ページがリロードされると、再び機能します。リセットしなければならないものはありますか?(もちろん 1 回実行するだけで十分ですが、2 回目に実行したときにユーザーにフィードバックを提供するとよいでしょう)。

次に、これにより新しいタブ/ウィンドウがポップアップします。do.php に javascript を返してウィンドウを閉じさせることで、これを回避できます (注: これはテスト目的であり、実際のコードではありません)。

<?php
$page = $_REQUEST['h'];
file_put_contents('/tmp/work.txt', $page);
echo '<script type="text/javascript">window.close();</script>"';
?>

醜い。新しいタブをすばやくフラッシュすると、それはなくなります。より良いアプローチはありますか?「成功」メッセージはいいのですが、それを組み込む方法がわかりません。

4

1 に答える 1

2

まず第一に、フォームの HTML が後続の POST リクエストに含まれてしまうため、ドキュメントの本文にフォームを追加したくありません。おそらくそれは望ましくないので、次の行を削除します。

document.body.appendChild(d);

次に、ブックマークレットを介した同じ URL への複数の送信がブラウザーによってブロックされているようです (Google Chrome の場合)。ボタンのハンドラーを介して実行されるまったく同じコードがonclick毎回機能します。解決策は、次のように、各リクエストに追加のランダム パラメータを追加することです。

d.action = "http://example.com/do.php?nocache=" + Math.random();

これがセキュリティの問題なのかキャッシュの問題なのかはわかりませんが、この修正は機能します。

では、新しいウィンドウに進みます。これは、target = "_blank"属性をフォームに追加したためです。もちろん、そうしないと、フォームは現在のウィンドウ/タブで送信され、おそらくユーザーがページを離れたくないでしょう。最初に試してみるのは、iframe を使用し、それにフォームを追加し、iframe をドキュメントに追加し、フォームを送信してから、iframe を削除することです。もちろん、フォームの送信がいつ完了したかを知るメカニズムが必要です。これにより、おそらく「クロスドメイン」制限の土地に着陸することになりますが、試してみる価値はあります. クロスドメイン AJAX リクエストと JSONP を調べることもできます。

アップデート

私はそれを持っていると思います!送信が完了したときに通知するために宛先ページは必要ないと思いました.iframeのloadイベントに頼ることができます。Chrome でこれをテストしましたが、完全に動作します。他のブラウザもテストしてください。コードのコメントを参照してください。

(function () {
    var html = document.documentElement.innerHTML;

    /** 
     * the iframe's onload event is triggered twice: once when appending it to the document, 
     * and once when the form finishes submitting and the new URL is loaded 
     */
    var loaded = 0;

    var iframe = document.createElement('iframe');

        // unique name, to make sure we don't create any conflicts with other elements on the page
        iframe.name = 'bookmarklet-' + Math.floor((Math.random() * 10000) + 1);
        iframe.style.display = 'none';

        iframe.onload = function () {
            // remove the iframe from the document on the second firing of the onload event
            if (++loaded == 1) {
                return;
            }

            // you can also alert('Done!') here :)
            document.body.removeChild(iframe);
        };

    var form = document.createElement('form');
        form.method = "POST";
        form.action = "http://requestb.in/sbnc0lsb?nocache=" + Math.random();
        form.target = iframe.name;

    var textarea = document.createElement('textarea');
        textarea.name = 'source';
        textarea.value = html;

    form.appendChild(textarea);
    iframe.appendChild(form);

    document.body.appendChild(iframe);

    form.submit();
})();
于 2012-10-27T10:34:46.873 に答える