Reputation: 1682
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 .
Upvotes: 7
Views: 11208
Reputation: 115222
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">
Upvotes: 11
Reputation: 51
In order to load the image with new code, you can use version paramter for captcha.php. See the following code.
<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()) ;
}) ;
}) ;
I wish it will help.
Upvotes: 0
Reputation: 225
For me its working as i say you have to use id in javascript for changing things
// 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 gonna be the new captcha html code
Upvotes: 0
Reputation: 12317
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.
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">
Upvotes: 5
Reputation: 15836
This is a delegation issue, as you have inserted a new element, so the event listener is removed, there are many solutions:
Solution 1:
Use inline event binding
function rebindCaptcha()
{
var id = Math.random();
$(".captcha").replaceWith('<img onclick="rebindCaptcha()" class="captcha" src="img/captcha.php?id='+id+'" />');
}
Solution 2:
Keep your element in dom, and just change the src attribute:
$(document).ready(function(e) {
$('.captcha').click(function(){
var id = Math.random();
this.src = 'img/captcha.php?id='+id+';
id ='';
});
});
Just for your reference, jQuery delegation can be done with like:
$(".parent .child").on("event",function(){/*your handler here*/})
or
$(".parent").on("event",".child",function(){/*your handler here*/})
Usually pick a parent that you are sure it will always exist in your dom, and always attach listener after document ready event.
Upvotes: 0
Reputation: 3923
Okay. The problem is that you declare the id
variable, and you try to redeclare it in the second function call, when there already is an id
variable, so it will silently be ignored and the empty string used instead.
Try moving var id ='';
out of the function, and use id = Math.random()
in the function.
Upvotes: 0
Reputation: 7654
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(){
Upvotes: 3