2

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

警告:前面是丑陋的 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>"';
?>

丑陋。快速闪现新标签,然后它就消失了。有更好的方法吗?“成功”消息会很好,但我不知道如何合并它。

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 回答