Ответ 1
После тщательного изучения этой проблемы, вот мой окончательный отчет:
Во-первых, проблема, отмеченная в вопросе, была на самом деле красной селедкой. Я неправильно отправил форму в iframe
(который arty выделен, но я не подключил точки). Мой подход к этой проблеме был основан на в этом примере, о котором также упоминаются некоторые другие связанные ответы. Правильный подход можно увидеть здесь. В принципе, action
для form
должен быть установлен в src
для iframe
(именно это предложил @arty).
Когда вы это делаете, конкретная проблема, выделенная в вопросе, исчезает, потому что страница вообще не перезагружается (что имеет смысл - почему страница должна перезагружаться при отправке в iframe
?)., который должен был опрокинуть меня). Во всяком случае, поскольку страница не перезагружается, Chrome никогда не просит вас сохранить ваш пароль, независимо от того, как долго вы будете ждать, чтобы отобразить форму после onDomReady
.
Соответственно, отправка в iframe
(правильно) НИКОГДА не приведет к тому, что Chrome попросит вас сохранить ваш пароль. Chrome будет делать это только в том случае, если страница, содержащая форму перезагрузки (обратите внимание: в отличие от старых сообщений здесь Chrome просит вас сохранить пароль, если форма была динамически создана).
Итак, единственное решение - принудительно перезагрузить страницу при отправке формы. Но как мы это сделаем и сохраним нашу структуру AJAX/SPA? Вот мое решение:
(1) Разделите SPA на две части: (1) Для не зарегистрированных пользователей, (2) Для зарегистрированных пользователей. Это может оказаться невыполнимым для тех, у кого больше сайтов. И я не считаю это постоянным решением - пожалуйста, Chrome, пожалуйста... исправьте эту ошибку.
(2) Я фиксирую два события в своих формах: onClickSaveButton
и onFormSubmit
. Для формы входа, в частности, я беру данные пользователя на onClickSaveButton
и делаю вызов AJAX для проверки их информации. Если эта информация проходит, я вручную вызываю formName.submit()
В onFormSubmit
, я гарантирую, что форма не отправлена до вызова onClickSaveButton
.
(3) Форма отправляется в файл PHP, который просто перенаправляет файл index.php
Есть два преимущества для этого подхода:
(1) Он работает в Chrome.
(2) В Firefox пользователю теперь предлагается только сохранить свой пароль, если они успешно вошли в систему (лично мне всегда было досадно, что меня попросили сохранить мой pwd, когда это было неправильно).
Вот соответствующий код (упрощенный):
index.php
<html>
<head>
<title>Chrome: Remember Password</title>
<!-- dependencies -->
<script type="text/javascript" src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<script type="text/javascript" src="http://underscorejs.org/underscore.js"></script>
<script type="text/javascript" src="http://backbonejs.org/backbone.js"></script>
<!-- app code -->
<script type="text/javascript" src="mycode.js"></script>
<script>
$(function(){
createForm();
});
</script>
</head>
<body>
<div id='header'>
<h1>Welcome to my page!</h1>
</div>
<div id='content'>
<div id='form'>
</div>
</div>
</body>
</html>
MYCODE.JS
function createForm() {
VLoginForm = Backbone.View.extend({
allowDefaultSubmit : true,
// UI events from the HTML created by this view
events : {
"click button[name=login]" : "onClickLogin",
"submit form" : "onFormSubmit"
},
initialize : function() {
this.verified = false;
// this would be in a template
this.html = "<form method='post' action='dummy.php'><p><label for='email'>Email</label><input type='text' name='email'></p><p><label for='password'>Password<input type='password' name='password'></p><button name='login'>Login</button></form>";
},
render : function() {
this.$el.html(this.html);
return this;
},
onClickLogin : function(event) {
// verify the data with an AJAX call (not included)
if ( verifiedWithAJAX ) {
this.verified = true;
this.$("form").submit();
}
else {
// not verified, output a message
}
// we may have been called manually, so double check
// that we have an event to stop.
if ( event ) {
event.preventDefault();
event.stopPropagation();
}
},
onFormSubmit : function(event) {
if ( !this.verified ) {
event.preventDefault();
event.stopPropagation();
this.onClickLogin();
}
else if ( this.allowDefaultSubmit ) {
// submits the form as per default
}
else {
// do your own thing...
event.preventDefault();
event.stopPropagation();
}
}
});
var form = new VLoginForm();
$("#form").html(form.render().$el);
}
DUMMY.PHP
<?php
header("Location: index.php");
?>
EDIT: Ответ mkurz выглядит многообещающим. Возможно, ошибки исправлены.