重新加载验证码图像

时间:2016-06-01 13:39:37

标签: javascript php jquery image

我有一个php脚本,它生成一个带有验证码的png图像作为图像文本。

var maxmind = require('maxmind');
var lookup = maxmind.open('./GeoLite2-City.mmdb');

/**/
var peers = [
    '31.193.128.0', // UK
    '23.112.0.0', // USA
    '5.24.0.0', // Turkey
    '196.203.0.0', // Tunisia
    '77.243.64.0' // Malta
];

var peerLocations = {};

peers.forEach(function(peer) {

    var tmp = lookup.get(peer);

    if (!tmp || !tmp.location) {
        throw new Error('Unable to get initial peer location: ' + peer);
    }
    peerLocations[peer] = tmp.location;
});


/**/

var testIp = '84.17.64.0'; // Turkey
// 84.17.64.0   // Turkey
// 37.219.0.0   // Finland
// 5.39.0.0     // France
// 37.75.32.0   // Malta
// 5.2.96.0     // UK
// 15.0.0.0     // USA
// 41.224.0.0   // Tunisia

console.log( findClosestPeer(testIp, 3) );

function findClosestPeer(ip, len) {

    var ipData = lookup.get(ip);
    var distances = [];

    if (ipData && ipData.location) {

        Object.keys(peerLocations).forEach(function(key) {

            var peer = peerLocations[key];
            var distance = getDistanceFromLatLonInKM(ipData.location.latitude, ipData.location.longitude, 
                peer.latitude, peer.longitude);

            distances.push({ip: key, distance: distance});
        });
    }

    // 0 ... 9
    distances.sort(function(a, b) {
        return a.distance - b.distance;
    });

    return len > 1 ? distances.slice(0, len)
        : distances.shift();
}



/* http://stackoverflow.com/a/21279990/605399 */
function getDistanceFromLatLonInKM(lat1, lon1, lat2, lon2) {

    var R = 6371; // Radius of the earth in km

    var dLat = deg2rad(lat2 - lat1);  // deg2rad below
    var dLon = deg2rad(lon2 - lon1); 
    var a = 
        Math.sin(dLat/2) * Math.sin(dLat/2) +
        Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * 
        Math.sin(dLon/2) * Math.sin(dLon/2)
    ;

    var c = 2 * Math.atan2( Math.sqrt(a), Math.sqrt(1 - a) ); 
    var d = R * c; // Distance in km

    return d;
}

function deg2rad(deg) {
    return deg * ( Math.PI / 180 );
}

我想通过jQuery或JavaScript重新加载图片,所以我使用的是这样的东西:

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

字段:

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

    });
});

作为第一次尝试,它有效,但在那之后,如果我再次点击该字段,它将不再工作,我不知道为什么。

7 个答案:

答案 0 :(得分:11)

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

方法1:您可以使用event delegation来监听动态添加的元素事件来解决此问题。

$(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+'" />');
    });
});

&#13;
&#13;
$(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 + '" />');
  });
});
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<img class="captcha" src="img/captcha.php">
&#13;
&#13;
&#13;

方法2:只需使用新网址更新img src属性,而不是替换整个元素。

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

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

方法3:此外,您可以使用与之前相同逻辑的纯JavaScript完成此操作。

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

方法4 :为元素设置 onClick 属性,并使用纯JavaScript处理click事件,您需要将this作为function captcha(ele) { alert('yolo'); var id = Math.random(); ele.setAttribute('src', 'img/captcha.php?id=' + id); }传递给引用元素的参数。

&#13;
&#13;
<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">
&#13;
function() { for (var idx = 0; idx < this.cars.length; idx++) {
                           var key = this.cars[idx].carName;
                           var value = {
                               count : 1, 
                               certifiedCheck : this.cars[idx].certified
                           };
                           emit(key, value);
                       } }
&#13;
&#13;
&#13;

答案 1 :(得分:4)

你的代码只运行一次的原因是因为带有验证码类的原始元素是replaced and the click is no longer detected

解决方案

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

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

或在线上:

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

HTML 对于唯一元素,使用id =“”语法而不是class =“”,当多个元素可以具有相同的类时使用class,id是唯一元素的标识符。 / p>

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

答案 2 :(得分:3)

可能只是将事件绑定到代码替换的元素的问题。请改为考虑文档delegate binding

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

答案 3 :(得分:0)

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

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

答案 4 :(得分: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中的父级,并且在文档就绪事件之后始终附加侦听器。

答案 5 :(得分: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代码

答案 6 :(得分:0)

为了使用新代码加载图像,您可以对captcha.php使用版本参数。请参阅以下代码。

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

我希望它会有所帮助。