javascript 如何在页面刷新/加载时刷新验证码图像?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6168451/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to refresh captcha image on page refresh/load?
提问by Soph
I want to force my site to refresh the captcha image everytime it loads, so I have a javascript method triggered with the onload() event. Here I have the following line:
我想强制我的网站在每次加载时刷新验证码图像,所以我有一个由 onload() 事件触发的 javascript 方法。在这里,我有以下几行:
document.getElementById('yw0_button').click;
Firebug doesn't detect any errors, and for testing purposes I have added an alert right after the displayed line, and the alert pops up each time the page is loaded. However, the image doesn't refresh!
Firebug 没有检测到任何错误,出于测试目的,我在显示的行之后添加了一个警报,并且每次加载页面时都会弹出警报。但是,图像不会刷新!
This is what I believe is relevant about the view file:
这是我认为与视图文件相关的内容:
<?php if(extension_loaded('gd')): ?>
<div class="row">
<?php echo $form->labelEx($model,'verifyCode'); ?>
<div>
<?php
$this->widget('CCaptcha',
array('showRefreshButton'=>true,
'buttonType'=>'button',
'buttonOptions'=>
array('type'=>'image',
'src'=>"/path/images/refresh-icon.png",
'width'=>30,
),
'buttonLabel'=>'Refrescar imagen'),
false);
?>
<br>
<?php echo $form->textField($model,'verifyCode'); ?>
</div>
<div class="hint">
Porfavor ingrese las letras como las ve en la imagen superior.
<br/>No hay distincion entre minúsculas y mayúsculas.</div>
</div>
<?php endif; ?>
Any ideas?
有任何想法吗?
@k to the zjust saw this! Yes sure, if you could help me find a more proper solution it would be awesome! This is what i believe is relevant about the view file:
@k to the z刚看到这个!是的,当然,如果您能帮我找到更合适的解决方案,那就太棒了!这是我认为与视图文件相关的内容:
<?php if(extension_loaded('gd')): ?>
<div class="row">
<?php echo $form->labelEx($model,'verifyCode'); ?>
<div>
<?php
$this->widget('CCaptcha',
array('showRefreshButton'=>true,
'buttonType'=>'button',
'buttonOptions'=>
array('type'=>'image',
'src'=>"/path/images/refresh-icon.png",
'width'=>30,
),
'buttonLabel'=>'Refrescar imagen'),
false);
?>
<br>
<?php echo $form->textField($model,'verifyCode'); ?>
</div>
<div class="hint">
Porfavor ingrese las letras como las ve en la imagen superior.
<br/>No hay distincion entre minúsculas y mayúsculas.</div>
</div>
<?php endif; ?>
In the controller I grant authorized users permission in the accessRules() method to the captcha action, and thats about all. Is there something else I could post?
在控制器中,我将 accessRules() 方法中的授权用户权限授予验证码操作,仅此而已。还有什么我可以发布的吗?
回答by Soph
In case anyone goes through a similar problem whilst getting started with Yii.. This is how I resolved the CAPTCHA issue triggering a click: I have an event triggered the the onload event, which has the following code:
如果有人在开始使用 Yii 时遇到类似问题.. 这就是我解决触发点击的 CAPTCHA 问题的方法:我有一个事件触发了 onload 事件,它具有以下代码:
$('#yw0_button').click();
$('#yw0_button').click();
There surely must be a better way, im open to suggestions! However as a temporary solution this works just fine, refreshing the captcha image each time the page is loaded. Good luck!
肯定有更好的方法,我愿意接受建议!但是,作为临时解决方案,这很好用,每次加载页面时刷新验证码图像。祝你好运!
EDIT:What I did was handle the onload event for my html page like this
编辑:我所做的是像这样处理我的 html 页面的 onload 事件
<body onload="initialize()">
..
</body>
Then in my js file:
然后在我的 js 文件中:
function initialize()
{
$('#yw0_button').click();
}
回答by ezze
I hope I can propose a better way to solve the problem mentioned by Soph. I know this is not JavaScript-related solution this question is addicted to but as I can see this one is the most right way to go.
我希望我能提出一个更好的方法来解决Soph提到的问题。我知道这不是与 JavaScript 相关的解决方案,这个问题让人上瘾,但正如我所见,这是最正确的方法。
I faced the same requirement - to refresh the caption on page refresh but preserve this one when user's input is invalid on other fields because repeating a new verification code on each validation's fail is annoying. So this task looks like to not refresh the caption on POST
request and refresh it otherwise (GET
request). A solution proposed by Sophby himself can't achieve this - as one could know POST
requests are sent to server and their data cannot be analyzed by client-side JavaScript.
我遇到了同样的要求 - 在页面刷新时刷新标题,但在用户输入在其他字段上无效时保留这个标题,因为在每次验证失败时重复新的验证码很烦人。所以这个任务看起来不会根据POST
请求刷新标题,否则刷新它(GET
请求)。Soph自己提出的解决方案无法实现这一点 - 因为人们知道POST
请求被发送到服务器并且它们的数据不能被客户端 JavaScript 分析。
Therefore I decided to look at Yii's captcha implementation. It consists of two classes located in system.web.widgets.captcha
package. The former is CCaptcha
extended from CWidget
and that we use in our view to add a captcha to web form in the manner like this:
因此我决定看看 Yii 的验证码实现。它由位于system.web.widgets.captcha
包中的两个类组成。前者是CCaptcha
从CWidget
我们的观点中扩展而来的,我们使用它以如下方式向 Web 表单添加验证码:
<?php
$this->widget("CCaptcha", array(
'buttonLabel' => "Generate another code",
'showRefreshButton' => false,
'clickableImage' => true
));
?>
The latter is CCaptchaAction
that does the most significant work to provide a captcha by generating a verification code and creating an image. Taking into account that Yii is designed to be object-oriented we can create a couple of our own classes Captcha
and CaptchaAction
extended from CCaptcha
and CCaptchaAction
relatively and place them in components
subdirectory of our web application's directory.
后者是CCaptchaAction
通过生成验证码和创建图像来提供验证码的最重要的工作。考虑到 Yii 被设计为面向对象,我们可以创建几个我们自己的类Captcha
,并相对地CaptchaAction
扩展它们并将它们放置在我们的 Web 应用程序目录的子目录中。CCaptcha
CCaptchaAction
components
My implementation of both these classes is below.
我对这两个类的实现如下。
run()
method of CCaptchaAction
is overriden and is quite similar to original one excepting that there is one additional if
-branch executing when render_refreshed
GET-parameter is set and where new verification code is being generated on the fly and corresponding new image is being rendered and returned as action's result.
run()
的方法CCaptchaAction
被覆盖并且与原始方法非常相似,除了if
在render_refreshed
设置 GET 参数时执行一个额外的分支,并且正在动态生成新的验证码,并且正在呈现相应的新图像并将其作为操作的结果返回。
A public refresh
variable has been introduced in Captcha
class and defaults to false
meaning widget's behavior is similar to CCaptcha
's one. Overriding renderImage
method we alter a code responsible for preparing widget's output HTML code. To be more precisive it's where a link to captcha action is prepared used as src
attribute of an img
tag. In the case of refresh
member is set to true
an additional render_refreshed
parameter is appended to this link.
类中refresh
引入了一个公共变量Captcha
,默认为false
意味着小部件的行为类似于 的行为CCaptcha
。覆盖renderImage
方法我们更改负责准备小部件输出 HTML 代码的代码。更准确地说,它准备了一个到验证码操作的链接,用作标签的src
属性img
。在refresh
成员设置为true
附加render_refreshed
参数的情况下附加到此链接。
Here is CaptchaAction.php
:
这是CaptchaAction.php
:
<?php
Yii::import("system.web.widgets.captcha.CCaptchaAction");
class CaptchaAction extends CCaptchaAction
{
const RENDER_REFRESHED_GET_VAR = "render_refreshed";
public function run()
{
if (isset($_GET[self::REFRESH_GET_VAR])) // AJAX request for regenerating code
{
$code = $this->getVerifyCode(true);
echo CJSON::encode(array(
'hash1' => $this->generateValidationHash($code),
'hash2' => $this->generateValidationHash(strtolower($code)),
// we add a random 'v' parameter so that FireFox can refresh the image
// when src attribute of image tag is changed
'url'=> $this->getController()->createUrl($this->getId(), array(
'v' => uniqid()
)),
));
}
else if (isset($_GET[self::RENDER_REFRESHED_GET_VAR]))
{
$this->renderImage($this->getVerifyCode(true));
}
else
$this->renderImage($this->getVerifyCode());
Yii::app()->end();
}
}
And this is Captcha.php
:
这是Captcha.php
:
<?php
Yii::import("web.system.widgets.CCaptcha");
class Captcha extends CCaptcha
{
public $refresh = false;
protected function renderImage()
{
if (!isset($this->imageOptions['id']))
$this->imageOptions['id'] = $this->getId();
if ($this->refresh)
{
$url = $this->getController()->createUrl($this->captchaAction, array(
'v' => uniqid(),
CaptchaAction::RENDER_REFRESHED_GET_VAR => 1
));
}
else
{
$url = $this->getController()->createUrl($this->captchaAction, array(
'v' => uniqid()
));
}
$alt = isset($this->imageOptions['alt']) ? $this->imageOptions['alt'] : '';
echo CHtml::image($url, $alt, $this->imageOptions);
}
}
So the usage is quite simple. In action preparing model's data for site's page do the following:
所以用法很简单。在为站点页面准备模型数据时,请执行以下操作:
...
// Creating order model's instance
$model = new MyModel();
$refreshCaptcha = true;
if (isset($_POST['MyModel']))
{
$refreshCaptcha = false;
...
}
...
$this->render("myView", array(
'model' => $model,
'refreshCaptcha' => $refreshCaptcha
));
After that modify captcha's widget call in myView
template of this page's action:
之后在myView
此页面操作的模板中修改验证码的小部件调用:
<?php
$this->widget("Captcha", array(
'buttonLabel' => "Generate another code",
'showRefreshButton' => false,
'clickableImage' => true,
'refresh' => $refreshCaptcha
));
and don't forget to modify actions
method of page's controller by replacing CCaptchaAction
class by CaptchaAction
:
并且不要忘记actions
通过将CCaptchaAction
类替换为以下内容来修改页面控制器的方法CaptchaAction
:
public function actions()
{
return array(
'captcha'=>array(
'class'=>'CaptchaAction',
'backColor'=>0xFFFFFF
)
);
}
Seems to me that it works as expected. Hope this will help somebody.
在我看来,它按预期工作。希望这会帮助某人。
回答by Bulki S Maslom
I'd like to add something to the Ezze's answer:
我想在 Ezze 的回答中添加一些内容:
To make clientValidation working, you can use custom captcha validation:
要使 clientValidation 工作,您可以使用自定义验证码验证:
class CaptchaValidatorRefresh extends CCaptchaValidator
{
public function clientValidateAttribute($object,$attribute)
{
$js="";
if(!$this->allowEmpty)
{
$message=$this->message!==null ? $this->message : Yii::t('yii','The verification code is incorrect.');
$js="
if($.trim(value)=='') {
messages.push(".CJSON::encode($message).");
}
";
}
return $js;
}
}
and then
接着
public function rules()
{
return array(
array('verifyCode', 'CaptchaValidatorRefresh', 'on'=>'request', 'allowEmpty'=>!CCaptcha::checkRequirements()),
);
}
回答by Nanhe Kumar
Add this javascript:
添加这个javascript:
jQuery(document).ready(function() {
jQuery.ajax({
'success':function(html){jQuery("#yw0").attr("src",html)},
'url':'/checkout/finish/captcha?refresh=1',
'cache':false
});
return false;
});
回答by Kailas
You can write the script before form beginWedget.
您可以在表单 beginWedget 之前编写脚本。
on every page load generate the new captcha code.
在每个页面加载时生成新的验证码。
$script=' $(document).ready(function() {
document.getElementById("yw0_button").click();
});';
Yii::app()->clientScript->registerScript('yw0_button', $script);
$form=$this->beginWidget('CActiveForm', array(
'id'=>'test-form',
'action'=>Yii::app()->createUrl('controllerName/actionName'),
'enableClientValidation'=>true,
'clientOptions'=>array(
'validateOnSubmit'=>true,
),
));
it's work for me.
这对我有用。
I hope it's also work for you
我希望它也适合你
回答by Ben
Here's another (correct?) way to do it (discussion):
这是另一种(正确的?)方法(讨论):
Yii::app()->getController()->createAction('captcha')->getVerifyCode(true);
回答by saeedeh
I have used : http://www.yiiframework.com/extension/captcha-extended/
我用过:http: //www.yiiframework.com/extension/captcha-extended/
and change CaptchaExtendedAction.php (path: extensions/captchaExtended)
并更改 CaptchaExtendedAction.php(路径:extensions/captchaExtended)
in line 154
在第 154 行
$this->renderImage($this->getVerifyCode());
to
到
$this->renderImage($this->getVerifyCode(true));
回答by ThinkAlone
I have a better solution for you guys:
我有一个更好的解决方案给你们:
public function beforeAction($action)
{
if($action->id == 'captcha'){
$action->getVerifyCode(true);
}
return parent::beforeAction($action);
}
Put these codes into the controller which you include captcha action!
将这些代码放入包含验证码操作的控制器中!