jquery triggers dont work after dynamically loading new content - javascript

I'm making a vote system thats using images and whenever you click one of the images, it will submit that one, and then it fades out and reloads it using a php page. Problem is, the first submit works, but once it reloads, clicking on the images does nothing. Not even an alert which I've tested.
vote.js
$('.firstDisplay').on("click", function () {
alert("work1");
var win = $(this).attr("title");
var loss = $('.secondDisplay').attr("title");
send_vote(win, loss);
console.log("<-CLIENT-> Click: Sent vote");
});
$('.secondDisplay').on("click", function () {
alert("work2");
var win = $(this).attr("title");
var loss = $('.firstDisplay').attr("title");
send_vote(win, loss);
console.log("<-CLIENT-> Click: Sent vote");
});
function send_vote(win, lose) {
var data = {'win': win, 'lose': lose};
$.ajax({
type: "POST",
url: 'actions/send-vote.php',
data: data,
success: function (html) {
$('#sent-vote').css('display', 'block');
$('#sent-vote').fadeOut(2000);
$('.imageBtn').fadeOut(2000);
$('#imageDisplay').load("source/templates/vote.php");
console.log("<-SYSTEM-> Ajax request sent and processed.");
},
error: function(e) {
$('#fail-vote').css('display', 'block');
$('#fail-vote').fadeOut(2000);
console.log("<-SYSTEM-> Ajax request failed to process.");
}
});
}
vote.php
<?php
$maximumPersons = 95;
$firstDisplay = rand(1, $maximumPersons);
$secondDisplay = rand(1, $maximumPersons);
function getScore($photo_id) {
$query = "SELECT *
FROM photo_scores
WHERE photo_id='".$photo_id."'";
$result = $database->query_select($query);
return $result;
}
?>
<a href="javascript:void(0);" class="imageBtn" id="firstDisplay" title="<?php echo $firstDisplay; ?>">
<img src="<?php echo $baseURL; ?>/images/persons/<?php echo $firstDisplay; ?>.png" />
<?php // $scoreFD = getScore($firstDisplay); echo "Wins: ".$scoreFD["wins"]." Losses: ".$scoreFD["losses"].""; ?>
</a>
<a href="javascript:void(0);" class="imageBtn" id="secondDisplay" title="<?php echo $secondDisplay; ?>">
<img src="<?php echo $baseURL; ?>/images/persons/<?php echo $secondDisplay; ?>.png" />
<?php // $scoreSD = getScore($secondDisplay); echo "Wins: ".$scoreSD["wins"]." Losses: ".$scoreSD["losses"].""; ?>
</a>
it's all loading correctly, just the img/buttons wont submit/work after its reloaded.

You need to use the form $(document).on('event', '.selector', function(){}); to listen for new elements on the DOM and attach your handler to them.

The answer here is event delegation.
Binding an event listener to an object will not bind it to all other dynamically loaded or created objects, or adding the(lets say class as in your example) to another object will not apply its event listeners , since they did not exists when the script was run
$('.firstDisplay').on("click", function () {
you say all current elements with firstDisplay class do something on click. If you then add a new .firstDisplay, it wont know that it needs to listen to the on click. in short the listener is not attached on the class itself, but on the elements that have the class when the script is run.
now to get it to work, we will use event delegation
$(document).on("click",'.firstDisplay', function () {
this time around we bind the event on document. we also tell the event that should it find a firstdisplay class on an element clicked inside the document, the following function must be executed. So if new element are added, the event, bound to document now, will properly fire

Related

During click of load more button, some divs become unclickable

I have undercome a problem when implementing a "Show more button"
The page will initially display 5 rows of data, then on click the button will make a call to a php function through ajax and load more results, ultimately displaying them on the page. It does this very well.
The problem is that each of the divs are clickable in their own right to allow for user interaction. Before clicking the button the first 5 are clickable and work correctly, however after loading the first 10, the first 5 become unclickable and the rest work as expected.
See my code here:
HTML:
<div class="col-sm-12 col-xs-12 text-center pushDown">
<div id="initDisplay">
<?php
// Display all subjects
echo displaySubjects($limit);
?>
</div>
<div id="show_result"></div>
<button id="show_more" class="text-center pushDown btn btn-success">Show More</button>
</div>
On click of the button the following is happening:
JQuery:
<script>
$("#show_more").on("click", function() {
$("#initDisplay").fadeOut();
});
/* This bit is irrelevant for this question
$("#addBtn").on("click", function(){
addSubject();
});
*/
var stag = 5;
$("#show_more").on("click", function(){
stag+=5;
console.log(stag);
$.ajax({
dataType: "HTML",
type: "GET",
url: "../ajax/admin/loadSubjects.php?show="+stag,
success: function(result){
$("#show_result").html(result);
$("#show_result").slideDown();
}
});
var totalUsers = "<?php echo $total; ?>";
if(stag > totalUsers) {
$("#show_more").fadeOut();
}
});
</script>
My PHP page and functions are here:
<?php
include_once '../../functions/linkAll.inc.php';
$limit = filter_input(INPUT_GET, "show");
if (isset($limit)) {
echo displayUsers($limit);
} else {
header("Location: ../../dashboard");
}
function displaySubjects($limit) {
$connect = db();
$stmt = $connect->prepare("SELECT * FROM Courses LIMIT $limit");
$result = "";
if ($stmt->execute()) {
$results = $stmt->get_result();
while($row = $results->fetch_assoc()){
$id = $row['ID'];
$name = $row['Name'];
$image = $row['image'];
if($image === ""){
$image = "subjectPlaceholder.png"; // fail safe for older accounts with no images
}
$result .=
"
<div class='img-container' id='editSubject-$id'>
<img class='miniProfileImage' src='../images/subjects/$image'>
<div class='middle' id='editSubject-$id'><p class='middleText'>$name</p></div>
</div>
";
$result .= "<script>editSubjectRequest($id)</script>";
}
}
$stmt->close();
return $result;
}
The script being called through this is:
function editSubjectRequest(id) {
$("#editSubject-"+id).click(function(e) {
e.preventDefault(); // Prevent HREF
console.log("You clicked on " + id);
$("#spinner").show(); // Show spinner
$(".dashContent").html(""); // Empty content container
setTimeout(function() {
$.ajax({ // Perform Ajax function
url: "../ajax/admin/editSubjects.php?subjectID="+id,
dataType: "HTML",
type: "POST",
success: function (result) {
$("#spinner").hide();
$(".dashContent").html(result);
}
});
}, 1500); // Delay this for 1.5secs
});
}
This will then take the user to a specific page depending on the subject which they clicked on.
Your problem is duplicate ids. First five items are present on the page always. But when you load more, you are loading not new items, but all, including first five. As they are already present on the page, their duplicates are not clickable. The original items are however clickable, but they are hidden.
Here is what you need:
$("#show_more").on("click", function(){
$("#initDisplay").html("");
});
Don't just fadeOut make sure to actually delete that content.
This is the easiest way to solve your issue with minimum changes. But better option would be to rewrite your php, so it would load only new items (using WHERE id > $idOfLastItem condition).
Also you don't need that script to be attached to every div. Use common handler for all divs at once.
$("body").on("click", "div.img-container", function() {
var id = $(this).attr("id").split("-")[1];
});
When you are updating a DOM dynamically you need to bind the click event on dynamically added elements. To achieve this change your script from
$("#editSubject-"+id).click(function(e) {
To
$(document).on("click","#editSubject-"+id,function(e) {
This will bind click event on each and every div including dynamically added div.

Toggle with an IF statement needs two clicks to fire

This is a toggle of a ‘follow-unfollow’ button of a Twitter like following system. When the button has the class unfollow it takes two clicks to trigger to fire. When the button has the class follow it fires in one click. This is related to the if statement. If the script does not need to run through the if statement it fires well on one click which is the part of the else section of the script. It is worth noting, that when two clicks are needed, if there is no refresh in the page, you then can toggle back and forth with just one click as it is supposed to be. Do you know how can I avoid using two clicks when the script needs to go through the if statement?
Thanks in advance.
<button class="followUnfollow" id="boton<?php echo $member->id; ?>" type="button" data-member_id="<?php echo $member->id; ?>" user_id="<?php echo $id;?>"> <?php echo $status; ?> </button>
<script>
$(document).ready(function() {
$("#boton<?php echo $member->id; ?>").on('click', function() {
var memberId = $(this).attr('data-member_id');
var userId = $(this).attr('user_id');
if($("#boton<?php echo $member->id; ?>").hasClass('unfollow')) { // TWO CLICKS TO FIRE
$.get("follow_actions.php", {unfollow_id:memberId, user_id:userId} , function(data) {
});
$(this).html('follow');
$(this).removeClass('unfollow').addClass('follow');
} else { // WORKS WELL, ONE CLICK TO FIRE
$.get("follow_actions.php", {follow_id:memberId, user_id:userId} , function(data) {
});
$(this).html('unfollow');
$(this).removeClass('follow').addClass('unfollow');
}
});
});
</script>

ajax request makes page lag

I have this ajax request code
function hehe2(){
var a = $(".film2numb").val();
return $.ajax({
type : "GET",
url : "php/controller1.php?page=semuafilm",
data : "data="+a,
cache: false,
success: function(data){
$('.semuafilm').load('php/film.php');
},
});
}
and it requests this php code, basically it prints out HTML data from SQL
<?php
$indicator = $_SESSION['p'];
if ($indicator == 'filmbaru') {
# code...
$batas = $_SESSION['a'];
if (!$batas) {
$batas = 1;
}
if ($batas>1) {
$batas = $batas * 8;
}
include('connect.php');
$queryfilm = "select * from tb_film order by film_year desc, film_id desc limit $batas ,8";
$exec = $conn->query($queryfilm);
while ( $f = $exec->fetch_assoc()) {
$tn = str_replace(" ","-",$f['film_name']) ;
?>
<div class='col l3 m3 s6 itemovie'><div><img src="images/dum.jpg" class="lazy" data-original='http://www.bolehnonton.com/images/logo/<?php echo $f["film_logo"]; ?>' width="214" height="317"><div><div><div><p><b><?php echo $f['film_name']; ?></b></p><p>IMDB Rating</p><p><?php echo $f['film_genre']; ?></p><p class='center-align linkmov'><a class='dpinblock browntex' href='?page=movie&filmname=<?php echo $tn; ?>'>PLAY MOVIE</a></p><p class='center-align linkmov'><a class='dpinblock' href=''>SEE TRAILER</a></p></div></div></div></div></div>
<?php
}
?>
and here is the controller
<?php
session_start();
$a = $_GET['data'];
$p = $_GET['page'];
$g = $_GET['genre'];
$_SESSION['a'] = $a;
$_SESSION['p'] = $p;
$_SESSION['g'] = $g;
?>
My question is why every time I click button that binded to the hehe2() function (4-5 times, which requested a lot of images) the page get heavier as I click incrementally(laggy, slow to scroll), is there a way to make it lighter, or is there a way to not store image cache on page or clear every time I click the button that binded to hehe2() function?
I am not sure that my advice will be helpful, I will just share my experience.
First of all you should check your binding. Do you bind click trigger only once?
Sometimes function binds multiple times and it can slow down the page.
You can put code below inside function and check the console
console.log("Function called");
If everything is fine from that point and function fires only once - I would recommend you to change flow a little bit. Is it possible to avoid many clicks in a row? If it is not big deal - you can disable button on click, show loader and enable button when AJAX request is completed. This approach will prevent from making multiple requests at once at page will be faster.

How to make a button reusable after the first click with AJAX/JQUERY and PHP

I have built a follow/unfollow Twitter like system using PHP. With help of this forum I have been successful creating a dynamic button that allows you to “follow” or “unfollow” each user, using AJAX/JQUERY to run the PHP/MySQL code in the back and avoid refreshing the page when the action happens. The thing is that I am able to run this script on the background only once. Let’s say a user unfollows a member by mistake (my AJAX/JQUERY script won’t have any problem with that), but then wants to follow him again, this is where I am stuck. The page will have to be refresh to make this happen. I know this is happening due to the PHP dynamic data that I am using as you will see in my code.
In the PHP code am running an iteration that output all the members in the database. I am outputting here (for simplicity) just the member’s name and a follow/unfollow button to each one. The php variable $what_class is the result of a PHP function that looks into the database to determine if the user is following or not that member. $what_class will output the strings “follow” of “unfollow” so the class can be defined, and then be targeted by either of the two the Jquery scripts.
PHP CODE
<?php foreach($members as $member){ ?>
<p class="member_name"><?php echo $member->name; ?></p>
<button class="<?php echo $what_class; ?>" type="button" data-member_id="<?php echo $member->id; ?>" user_id="<?php echo $id;?>" ><?php echo $what_class; ?></button>
<?php } ?>
Below is the JQUERY scripts, as mentioned before, the button class will be defined by PHP through $what_class. This is the problem when trying to re-use the button after the first time, class won´t change in PHP’s $what_class unless the page is refreshed. I tried to use $(this).removeClass('unfollow').addClass('follow') to change the class using Jquery and have the button to be re-usable but it isn’t working.
JQUERY SCRIPTS TO FOLLOW OF UNFOLLOW
<script type="text/javascript">
$(document).ready(function() {
$("button.unfollow").on('click', function() {
var memberId = $(this).attr('data-member_id');
var userId = $(this).attr('user_id');
$.get("follow_actions.php", {unfollow_id:memberId, user_id:userId} , function(data) {
});
$(this).html('follow');
$(this).removeClass('unfollow').addClass('follow');
});
});
</script>
<script type="text/javascript">
$(document).ready(function() {
$("button.follow").on('click', function() {
var memberId = $(this).attr('data-member_id');
var userId = $(this).attr('user_id');
$.get("follow_actions.php", {follow_id:memberId, user_id:userId} , function(data) {
});
$(this).html('unfollow');
$(this).removeClass('follow').addClass('unfollow');
});
});
</script>
Does anyone knows how I accomplish having a reusable button without reloading the page? I thank you in advance.
Previous Answer:
What I do for that kind of scenario is to have two buttons. One will be shown to the user, and the other one will be hidden.
<button class="follow" data-member_id="<?php echo $member->id; ?>" user_id="<?php echo $id;?>" >Follow</button>
<button class="unfollow" style="display:none" data-member_id="<?php echo $member->id; ?>" user_id="<?php echo $id;?>" >Unfollow</button>
Just tweak your php code what to show and what not.
When a button is click, hide this button and show the other one.
$(document).ready(function(){
$(".follow").on("click", function(){
$(".follow").hide(200);
$(".unfollow").show(200);
/* PUT YOUR OTHER PROCESSES HERE */
});
$(".unfollow").on("click", function(){
$(".follow").show(200);
$(".unfollow").hide(200);
/* PUT YOUR OTHER PROCESSES HERE */
});
});
Check this JSfiddle.
Update:
We can use toggleClass() of jQuery.
<button class="follow" data-member_id="12" user_id="12">Follow</button>
And the script:
$(document).ready(function(){
$(".follow, .unfollow").on("click", function(){
var memberId = $(this).attr('data-member_id');
var userId = $(this).attr('user_id');
$(".follow, .unfollow").toggleClass("follow unfollow");
$(this).text(function(i, text){
return text === "Follow" ? "Following" : "Follow";
});
});
});
Check this JSfiddle.
use <button class="followUnfollow <?php echo $what_class; ?>"
You need to write as less code as possible. Have a common class such as followUnfollow and then check if follow class exists within this element using hasClass function from jQuery.
Have a look at the code below.
<script type="text/javascript">
$(document).ready(function() {
$("button.followUnfollow").on('click', function() {
var memberId = $(this).attr('data-member_id');
var userId = $(this).attr('user_id');
if($(this).hasClass('follow')) { // FOLLOW
$.get("follow_actions.php", {follow_id:memberId, user_id:userId} , function(data) {
});
$(this).html('unfollow');
$(this).removeClass('follow').addClass('unfollow');
} else { // UNFOLLOW
$.get("follow_actions.php", {unfollow_id:memberId, user_id:userId} , function(data) {
});
$(this).html('follow');
$(this).removeClass('unfollow').addClass('follow');
}
});
});
</script>

Javascript function called by itself

I want to display a customized alert when i click a but if im logged in i want to redirect to another page. I have this.
<div id="contentCalendar" class="col-md-3 images_1_of_4 text-center">
<a><img onClick="show_alert();" id="rotateme" class="img-responsive img-circle center-block" src="web/images/calendaricon.png"/></a>
<h4>Check our last events</h4>
</div>
<div id="myalert" class="alert alert-error">
×
<strong>Error!</strong> You must be logged in to see our calendar.
</div>
<script>
$('#myalert').hide();
//What happen if you want to enter the events without loggin.
var logged_in = <?php echo ($logged_in); ?>;
function show_alert()
{
if(logged_in==true)
{
window.location="timeline.php";
}
else
{
$('#myalert').show();
}
}
</script>
For some reason works like a charm when Logged_in is true and i get redirected. But when im logged out it just doesnt show the alert even if i didnt press the button at all.
Any ideas?
Always, again, always, run everything you embed in JS through json_encode:
var logged_in = <?php echo json_encode($logged_in); ?>;
When you simply echo a falsy value in php, it echoes nothing, thus breaking your javascript.
Try this line:
var logged_in = <?php echo $logged_in ? 'true' : 'false'; ?>;
This assumes that the php code outputs the Boolean correctly. Viewing the page source will allow you to see if it is outputted correctly.
Now looking at the JavaScript code.
Move the onclick to the anchor and cancel the click event
<a href="#" onclick="show_alert(); return false"><img ....
A better solution is to dump the inline event handler.
Attach the click unobtrusively and use preventDefault to cancel the click.
HTML:
<a href="timeline.php" class="calendar"><img ....
JavaScript
var logged_in = <?php echo ($logged_in); ?>;
$("a.calendar").on("click", function (e) {
if(!logged_in) {
e.preventDefault();
$('#myalert').show();
}
});
You need to wrap the script in some kind of event. Try :
$(document).ready(function () {
var logged_in = <?php echo ($logged_in); ?>;
function show_alert()
{
if(logged_in==true)
{
window.location="timeline.php";
}
else
{
$('#myalert').show();
}
}
});

Categories

Resources