Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reload captcha image

I have a php script which generates a png image with a captcha code as image text.

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);

I want to reload the image via jQuery or JavaScript,so i'm using something like this:

$(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 ='';

    });
});

the field:

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

As the first attempt,it works , but after that if i click on the field again it won't work anymore and i have no idea why .

like image 447
Petru Lebada Avatar asked Jun 01 '16 13:06

Petru Lebada


3 Answers

You are replacing the dom element with new element, it will destroy all attached event handlers.

Method 1: You can resolve this by using event delegation to listen dynamically added elements event.

$(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">

Method 2: Instead of replacing entire element just update the img src attribute with new 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">

Method 3: Also you can get it done with pure JavaScript with same logic as previous.

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">

Method 4: Setting onClick attribute to the element and handling the click event with pure JavaScript, where you need to pass this as argument to refer the element.

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">
like image 160
Pranav C Balan Avatar answered Nov 08 '22 04:11

Pranav C Balan


The reason your code only works once is because the original element with captcha class is replaced and the click is no longer detected.

Solution

A clean solution would be to replace the src of the image instead of the complete element.

Working example

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 ='';
}

Or in oneline:

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

HTML For unique elements use the id="" syntax instead of class="", class is used when multiple elements can have the same class, id is an identifier for a unique element.

<img class="captcha" id="changeThis" src="img/captcha.php">
like image 23
Sven van den Boogaart Avatar answered Nov 08 '22 05:11

Sven van den Boogaart


Might just be a problem with binding events to elements that your code replaces. Consider delegate binding to the document instead:

// Replace
$(document).ready(function(e) {
    $('.captcha').click(function(){
// With
$(document).ready(function(e) {
    $('.captcha').on('click', document, function(){
like image 3
Brian Avatar answered Nov 08 '22 06:11

Brian