Bookmarklet将页面源提交到表单

时间:2012-10-27 05:04:34

标签: javascript forms bookmarklet

我正在使用书签将当前页面源发送到服务器函数,然后处理它(存储它,不需要将信息返回给用户)。

警告:丑陋的Javascript未来,它不是我通常需要使用的语言。

这是小书签,非常易于阅读:

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();
})();

这基本上有效,“do.php”以形式变量h接收头部和身体部分。

但是,它似乎只为每个页面工作一次。如果为同一页面按两次书签,则不会发生任何事情。重新加载页面时,它会再次运行。有什么我应该重置的吗? (运行一次就足够了,但是第二次按下时给用户提供一些反馈会很好。)

其次,这会弹出一个新的标签/窗口。我可以通过让do.php返回一些javascript关闭窗口来解决这个问题(注意:这仅用于测试目的,而不是真正的代码):

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

难看。快速刷新新标签,然后它就消失了。有更好的方法吗?一个“成功”的消息会很好,但我看不出如何融入它。

1 个答案:

答案 0 :(得分:2)

首先,您不希望将表单附加到文档的正文中,因为表单的HTML随后将包含在后续的POST请求中,您可能不希望这样,所以删除此行:

document.body.appendChild(d);

其次,浏览器会阻止通过bookmarklet对同一网址进行多次提交(无论如何都是谷歌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();
})();