Ele*_*One 33 javascript jquery google-chrome backbone.js
注意:此问题是从其原始版本进行了大量编辑.这个问题已经大大简化了.
以前曾多次提出类似的问题,不同的形式 - 例如,
但是,这个问题涉及Chrome功能的一个非常具体的方面,所以在这方面它是完全不同的.
从过去的答案来看,似乎让Chrome提示密码保存的最佳方法是将表单提交给虚拟iframe,同时实际通过AJAX登录:示例.这对我来说很有意义,所以我现在已经花了几天的时间来摆弄一些示例代码.但是,Chrome在这方面的行为对我来说没有意义.完全没有.因此问题.
出于某种原因,如果在onDomReady之后/之后存在提交到虚拟iframe的表单,则Chrome不会提示您保存密码.
可以在这里找到一个jsfiddle ,但它没什么用处,因为你必须dummy.html在本地创建才能看到所描述的行为.因此,最好的方法是将完整的html复制到您自己的html中index.html,然后创建一个dummy.html文件.
这是完整的代码index.html.这三种方法都突出显示为(1),(2),(3).仅(2)确保提示用户保存其密码,并且(3)不起作用的事实对我来说特别困惑.
<html>
<head>
<title>Chrome: Remember Password</title>
<script type="text/javascript" src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<script type="text/javascript">
$(function(){
function create_login_form()
{
$('#login_form').html(
"<input type='text' name='email'>" +
"<input type='password' name='password'>" +
"<input id='login-button' type='submit' value='Login'/>");
}
// (1) this does not work. chrome seems to require time after "onDomReady" to process
// the forms that are present on the page. if the form fields exist while that processing
// is going on, they will not generate the "Save Password?" prompt.
//create_login_form();
// (2) This works. chrome has obviously finished its "work" on the form fields by now so
// we can add our content to the form and, upon submit, it will prompt "Save Password?"
setTimeout(create_login_form,500);
});
</script>
</head>
<body>
<!-- Our dummy iframe where the form submits to -->
<iframe src="dummy.html" name="dummy" style="display: none"></iframe>
<form action="" method="post" target="dummy" id="login_form">
<!-- (3) fails. form content cannot be present on pageload -->
<!--
<input type='text' name='email'>
<input type='password' name='password'>
<input id='login-button' type='submit' value='Login'/>
-->
</form>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
如果有人能够解释这里发生了什么,我将非常感激.
编辑:请注意,Chrome的"保存密码问题"已扩展到使用由Google开发的AngularJS的用户:Github
mku*_*urz 23
从Chrome 46开始,您不再需要iframe黑客了!
在推送状态或ajax请求之后,通过删除(或隐藏)表单或更改其动作URL(不测试但也应该工作),确保原始登录表单不再"存在".还要确保同一页面中的所有其他表单指向不同的操作URL,否则它们也被视为登录表单.
看看这个例子:
<!doctype html>
<title>dynamic</title>
<button onclick="addGeneratedForms()">addGeneratedForms</button>
<script>
function addGeneratedForms(){
var div = document.createElement('div');
div.innerHTML = '<form class="login" method="post" action="login">\
<input type="text" name="username">\
<input type="password" name="password">\
<button type="submit">login</button> stay on this page but update the url with pushState\
</form>';
document.body.appendChild(div);
}
document.body.addEventListener('submit', function ajax(e){
e.preventDefault();
setTimeout(function(){
e.target.parentNode.removeChild(e.target); // Or alternatively just hide the form: e.target.style.display = 'none';
history.replaceState({success:true}, 'title', "/success.html");
// This is working too!!! (uncomment the history.xxxState(..) line above) (it works when the http response is a redirect or a 200 status)
//var request = new XMLHttpRequest();
//request.open('POST', '/success.html', true); // use a real url you have instead of '/success.html'
//request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
//request.send();
}, 1);
}, false);
</script>
Run Code Online (Sandbox Code Playgroud)
如果您有兴趣,可以在此回购中找到更多示例.您可以使用node运行它:node server.js.也许还看到这个提交的评论:https://github.com/mkurz/ajax-login/commit/c0d9503c1d2a6a3a052f337b8cad2259033b1a58
如果您需要帮助,请告诉我.
在彻底研究了这个问题之后,这是我的最终报告:
首先,问题中突出显示的问题实际上是红鲱鱼.我被错误地提交表单到iframe(这附庸风雅突出-但我没有连接点).我对这个问题的处理方法是基于这个例子,其中一些其他相关答案也被引用.这里可以看到正确的方法.基本上,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()In onFormSubmit,我确保在onClickSaveButton调用之前不提交表单.
(3)表单提交到一个简单重定向到该index.php文件的PHP 文件
这种方法有两个优点:
(1)适用于Chrome.
(2)在Firefox上,用户现在只有在成功登录时才被要求保存密码(我个人总是觉得在出错时要求保存我的密码非常烦人).
这是相关代码(简化):
的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>
Run Code Online (Sandbox Code Playgroud)
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);
}
Run Code Online (Sandbox Code Playgroud)
DUMMY.PHP
<?php
header("Location: index.php");
?>
Run Code Online (Sandbox Code Playgroud)
编辑: mkurz的答案看起来很有希望.也许错误是固定的.