重新加载验证码图片

7
我有一个PHP脚本,它生成一个包含验证码文本的PNG图像。
session_start();   
$captchanumber = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz'; 
$captchanumber = substr(str_shuffle($captchanumber), 0, 8); 
$_SESSION["code"] = $captchanumber; 
$image = imagecreatefromjpeg("cap.jpg");     
$black  = imagecolorallocate($image, 160, 160, 160);   
$font = '../assets/fonts/OpenSans-Regular.ttf';  
imagettftext($image, 20, 0, 35, 27, $black, $font, $captchanumber);   
header('Content-type: image/png');    
imagepng($image);
imagedestroy($image);

我希望能够通过jQuery或JavaScript重新加载图像,因此我正在使用以下内容:
$(document).ready(function(e) {
    $('.captcha').click(function(){
        alert('yolo');
        var id = Math.random();
        $(".captcha").replaceWith('<img class="captcha" src="img/captcha.php?id='+id+'" />');
        id ='';

    });
});

该领域:

<img class="captcha" src="img/captcha.php">

作为第一次尝试,它起作用了,但之后如果我再次点击该字段,它将不会再起作用,我不知道为什么。

7个回答

11

您正在用新元素替换DOM元素,这将销毁所有已附加的事件处理程序。

方法1:您可以通过使用事件委托来监听动态添加元素的事件来解决这个问题。

$(document).ready(function(e) {
    $('body').on('click', '.captcha', function(){
        alert('yolo');
        var id = Math.random();
        $(this).replaceWith('<img class="captcha" src="img/captcha.php?id='+id+'" />');
    });
});

$(document).ready(function(e) {
  $('body').on('click', '.captcha', function() {
    alert('yolo');
    var id = Math.random();
    $(this).replaceWith('<img class="captcha" src="img/captcha.php?id=' + id + '" />');
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<img class="captcha" src="img/captcha.php">


方法2: 不需替换整个元素,只需更新图片的URL。

$(document).ready(function(e) {
    $('.captcha').click(function(){
        alert('yolo');
        var id = Math.random();
        $(this).attr('src', 'img/captcha.php?id='+id);
    });
});

$(document).ready(function(e) {
  $('.captcha').click(function() {
    alert('yolo');
    var id = Math.random();
    $(this).attr('src', 'img/captcha.php?id=' + id);
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<img class="captcha" src="img/captcha.php">


方法3:你也可以使用纯JavaScript来完成,与前面的逻辑相同。

document.querySelector('.captcha').addEventListener('click', function() {
  alert('yolo');
  var id = Math.random();
  this.setAttribute('src', 'img/captcha.php?id=' + id);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<img class="captcha" src="img/captcha.php">

第四种方法:onClick属性设置为元素,并使用纯JavaScript处理点击事件,在这种情况下需要将this作为参数传递以引用该元素。

function captcha(ele) {
  alert('yolo');
  var id = Math.random();
  ele.setAttribute('src', 'img/captcha.php?id=' + id);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<img class="captcha" onclick="captcha(this)" src="img/captcha.php">


5
你的代码仅起一次作用的原因是因为具有验证码类的原始元素已被替换,点击不再被检测

解决方案

一个干净的解决方案是替换图像的src而不是整个元素。

工作示例

Jquery

  $(document).ready(function () {
        $("#changeThis").click(
            function () {
                changeImage();
            }            
        );
    });

function changeImage() {
   //we want whole numbers not numbers with dots here for cleaner urls
   var id = Math.floor((Math.random() * 1000) + 1);
   $('#changeThis').attr("src",'img/captcha.php?id='+id);
   //Not sure why you want to empty id though.
   id ='';
}

或者一行:

$("#changeThis").click($('#changeThis').attr("src",'img/captcha.php?id='+Math.floor((Math.random() * 1000) + 1)));

使用id =“”语法而不是class =“”来表示唯一元素,当多个元素可以具有相同的类时使用class,id是唯一元素的标识符。
<img class="captcha" id="changeThis" src="img/captcha.php">

3

可能只是因为您的代码替换了元素而导致绑定事件出现问题。考虑代理绑定到文档:delegate binding

// Replace
$(document).ready(function(e) {
    $('.captcha').click(function(){
// With
$(document).ready(function(e) {
    $('.captcha').on('click', document, function(){

1
根据这里的文档http://api.jquery.com/on/,您应该编写:$(document).on('click', '.captcha', function() { ... } )。稍后添加到文档中的元素作为第二个参数传递,而不是反过来。 - Muhammad Alvin

0

好的。问题在于您声明了id变量,并且在第二个函数调用中尝试重新声明它,当已经存在一个id变量时,它将被静默忽略并使用空字符串代替。

尝试将var id ='';移出函数,并在函数中使用id = Math.random()


问题是他替换了具有直接绑定的完整元素,通过替换它,该绑定与函数不再有效,委托绑定可以解决这个问题。 - Sven van den Boogaart

0
为了使用新代码加载图像,您可以在captcha.php中使用version参数。请参考以下代码。
<img class="captcha" id="secure_code" src="img/captcha.php"> <a href="#" id="reload_captcha">Reload</a> 

 

$(document).ready(function(e) {
    $('#relaod_captcha').click(function(e) {
        e.preventDefault() ;
        $('#secure_code').attr('src', "img/captcha.php?ver="+Math.random()) ;
    }) ;
}) ;

希望它能有所帮助。


0
这是一个委托问题,因为您插入了一个新元素,所以事件监听器被移除了,有很多解决方案: 解决方案1: 使用内联事件绑定。
function rebindCaptcha()
{
var id = Math.random();
        $(".captcha").replaceWith('<img onclick="rebindCaptcha()" class="captcha" src="img/captcha.php?id='+id+'" />');
}

解决方案2:

保留您的元素在DOM中,只需更改src属性:

$(document).ready(function(e) {
      $('.captcha').click(function(){
          var id = Math.random();
          this.src = 'img/captcha.php?id='+id+';
          id ='';

      });
  });  

仅供参考,jQuery委托可以这样完成:

$(".parent .child").on("event",function(){/*your handler here*/}) 

或者

$(".parent").on("event",".child",function(){/*your handler here*/})

通常选择一个您确定它将始终存在于您的DOM中的父级,并在文档准备就绪事件之后始终附加侦听器。

0

对我来说,它正在按照我的要求工作,你必须在JavaScript中使用ID来更改事物。

// reload is your button reload and captcha must be a div who surrounding the captcha img

document.querySelector('#reload').addEventListener('click', function(e){
  var reload = document.getElementById('captcha')
  reload.innerHTML = "your new logic"
})

//reload.innerHTML 将成为新的验证码 HTML 代码


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接