The remove() on id main is called from clicking another external button. The problem is if the user clicks btn1 and quickly presses that external button, the remove is getting called before the event handler for btn1. As a result of which the popup is loaded after the div has been removed. Is there a way by which the load request can be stopped when event handler for remove is clicked? I tried with jqXHR.abort() when remove method is called,but that doesn't work because the remove is called before the ajax is even sent.
There are many buttons like btn1 which will send ajax requests to load HTML and Few HTMlL files for e.g a.html will load some script files like a.js, which will be executed. And if the script refers to some variable which was deleted in remove(), there will be a TypeError.
<div id="base">
<div id="main">
<!-- some more HTML elements -->
<button id="btn1"></button>
</div>
<div id ="popup">
</div>
</div>
<script>
var xhr;
$("#btn1").on("click", function(){
xhr = $.ajax(
url: "a.html",
success: function(){
//do something
}),
type: "GET"
});
$("#main").on("remove", function(){
// delete all resources,etc.
xhr.abort();
});
</script>
Try using a global variable
var removed = 0;
$('externabutton').click(function(){
$("#main").remove();
removed = 1;
});
$("#btn1").on("click", function(){
xhr = $.ajax(
url: "a.html",
success: function(data){
if (removed == 0 ) {
//append the data
} else {removed ==0;}
}),
type: "GET"
});
As the xhr is async, so we cannot guarantee the xhr is finished before #main.remove method. Maybe you could use a flag to control this.
var isRemoved = false, xhr;
$("#btn1").on("click", function(){
if(isRemoved) return;
xhr = $.ajax({
url: "a.html",
success: function(){
//do something
if(isRemoved) return;
},
type: "GET"
});
});
$("#main").on("remove", function(){
isRemoved = true;
xhr && xhr.abort();
});
Related
I have some JS files included in my page that are simple for displaying blocks on click ant etc..
On another part of page, I have a button. When I click it an ajax call is made that returns some values that I display on the page. To display it, I'm reloading part of page like this:
$(document).ready(function () {
$(document).on('click', '.add', function (e) {
$this = $(this);
$.ajax({
type: 'POST',
url: 'add',
dataType: 'JSON',
data: {product: $this.parent('.input-append').find('input').data('id'),quantity: $this.parent('.input-append').find('input').val()},
success: function (data) {
if(data.success == false){
alert('error')
}else{
$('.test').load(" .test");
$('.sidebar').load(" .sidebar");
$('.top').load(" .top");
}
}
});
});
This reloads part of page, displays values and etc..
However, after the ajax call is made, the JS stops working. When I click my buttons, nothing happens. No errors or anything.
I think it has to do with the ajax when I refresh part of twig and it messes up the previously loaded JS files. But what can I do in that situation? Somehow refresh the loaded JS files? How?
You have to attach event listener on button starting from the container which doesn't get reloaded by Ajax request, like this:
//#mainCont is a container that doesn't get reloaded by Ajax
$("#mainCont").on("click", ".yourBtn", function(){
//do something
});
As said #Nacho M, you need to reinit listener from the loaded element, so you hsould have something like this :
function init() {
$(document).on('click', '.yourclass', function (e) {
//your content
}
// add every button who needs to be reloaded.
}
Init them on loading page first :
$("document").ready(function() {
init();
})
And on success of Ajax call :
$.ajax({
type: 'POST',
url: 'add',
dataType: 'JSON',
data: {product: $this.parent('.input-append').find('input').data('id'),quantity: $this.parent('.input-append').find('input').val()},
success: function (data) {
if(data.success == false){
alert('error')
}else{
$('.test').load(" .test");
$('.sidebar').load(" .sidebar");
$('.top').load(" .top");
init();
}
}
});
I have php page "Home.php", that present user posts(using ajax).
This is how I get the posts:
<script type="text/javascript">
function loadmore()
{
var val = document.getElementById("result_no").value;
var userval = document.getElementById("user_id").value;
$.ajax({
type: 'post',
url: 'fetch.php',
data: {
getresult:val,
getuserid:userval
},
success: function (response) {
var content = document.getElementById("result_para");
content.innerHTML = content.innerHTML+response;
// We increase the value by 2 because we limit the results by 2
document.getElementById("result_no").value = Number(val)+10;
}
});
}
</script>
<div id="content">
<div id="result_para">
</div>
</div>
In every post, there is a like button(which also uses ajax). This is how I save the likes:
<script type="text/javascript">
function likethis(likepostid)
{
$.ajax({
type: 'post',
url: 'fetchlikes.php',
data: {
getpostid:likepostid
},
success: function (response) {
}
});
}
</script>
Before I used ajax to present posts, all worked well. But now when I press the like button, it DOES save the like, BUT the javascript/jquery doesn't work. I tried to make alert when I pressed the LIKE button, but it didn't work.
This is the index.js code(the javascript). It add +1 likes, when the user press the button:
$('.btn-counter_likecount').on('click', function(event, count) {
event.preventDefault();
//alert("hello");
var $this = $(this),
count = $this.attr('data-count'),
active = $this.hasClass('active'),
multiple = $this.hasClass('multiple-count_likecount');
$.fn.noop = $.noop;
$this.attr('data-count', ! active || multiple ? ++count : --count )[multiple ? 'noop' : 'toggleClass']('active');
});
EDIT fetchlikes.php:
<?php
mysql_connect('localhost','root','');
mysql_select_db('blabla');
$postid=$_POST['getpostid'];
mysql_query("UPDATE user_post SET likes_count=likes_count+1 WHERE post_id='$postid'");
?>
Because your posts are being loaded dynamically, the javascript where you bind the event is running before the posts are actually loaded, thus the buttons don't exist when you try to bind the event. You can use delegated events in jQuery to handle this.
Your previous code
$('.btn-counter_likecount').on('click', function(event, count) {
....
});
New Code
$('#result-para').on('click','.btn-counter_likecount',function(event, count) {
....
}
This way the event will actually be bound to a parent element that already exists when jQuery's ready() function runs. This way, the event handler checks for matching elements when the event is fired rather than when the event is bound.
For further reading, look into jQuery's delegated events
I have list of tables,
<table id="<%#DataBinder.Eval(Container.DataItem, "Certificate")%>" class="tbl_evenSearchResultRow" onmouseover="this.className='ResultGridRowSeleted'" onmouseout="this.className='tbl_evenSearchResultRow'" onclick="return SynopsisWindowOpen(this)">
onclick of each i use next function:
function SynopsisWindowOpen(obj) {
var title = $(obj).find("strong[name='title']").html();
var isParentools = 0;
if (window.location.href.indexOf('recent_releases.aspx') > -1)
isParentools = 1;
var url = "/ratings/Synopsis.aspx?logoonly=1&Certificate=" + obj.id + "&Title=" + encodeURIComponent(title) + "&parentools=" + isParentools;
$("#ratingModal").on("show.bs.modal", function (e) {
$.ajax({
url: url,
cache: false,
dataType: "html",
success: function (data) {
$("#ratingModal").find(".modal-body").html(data);
}
});
});
$("#ratingModal").on("hide.bs.modal", function (e) {
$(this).find(".modal-body").html('');
});
$("#ratingModal").modal('show');
return false;
}
By url i render body of modal : i get certificate from request.query and according to it render body
LoadSynopsisContent(Request.QueryString["Certificate"], Request.QueryString["parentools"]);
Problem : when i click at first - everything seems to be good, on second click in modal body firstly rendered body of first click and then of second click. And so on.
I don't know where is problem.
Firstly i use jquery load function, but then i change to simple ajax call with disabled caching.
Move the all event bindings to outside of the function and everything should work fine.
Thus, these parts should not be inside the function:
$("#ratingModal").on("show.bs.modal", ....);
$("#ratingModal").on("hide.bs.modal", ....);
Here is one way you could organize your code:
var url; //a global variable ... not a good idea though
function SynopsisWindowOpen(obj) {
....
url = .....
}
$(function() {
$("#ratingModal").on("show.bs.modal", ....);
$("#ratingModal").on("hide.bs.modal", ....);
});
However, the way would be to not use inline JavaScript but to take advantage of the power of jQuery to separate structure from behavior.
UPDATE
Instead of using a global variable url you can store the new url in a data attribute of the modal. Then you can get it from there when the modal opens.
In the function:
//calculate the url
var url = .....
//store the url in the modal
$('#ratingModal").data('table-url', url);
In the modal event handler:
$("#ratingModal").on("show.bs.modal", function(e) {
//retrieve the url from the modal
var url = $(this).data('table-url');
//use the url
$.ajax({ url: url, .... }):
});
Doing following in jQuery:
$('#signupbox1').on('click', '#signup1', function() {
var str = $('#signupform').serialize();
// make it look like a waiting button
$('#signup1').addClass("btn_wait");
var btn_val = $('#signup1').val();
$('#signup1').val('');
$.ajax({
type: "POST",
url: "signup_step1.php",
data: str,
success: function(msg) {
//doing stuff here
$('#signup1').removeClass("btn_wait");
$('#signup1').val(btn_val);
}
});
});
How could you disable the click event as well till you receive an answer from the ajax call? So, when you click on the button it not only "transforms" to a waiting button because of the added class, but also the click event will be "paused"... is this possible?
Thank you very much in advance!
$('#signupbox1').on('click', '#signup1', function() {
var str = $('#signupform').serialize();
// make it look like a waiting button
var btn_val = $('#signup1').val();
$('#signup1').addClass("btn_wait").val('').unbind('click');
$.ajax({
type: "POST",
url: "signup_step1.php",
data: str,
success: function(msg) {
$('#signup1').removeClass("btn_wait").val(btn_val);
},
complete: function() {
$('#signup1').bind('click'); // will fire either on success or error
}
});
});
You can add a flag to denote "currently loading". You can use anything like a variable, property or attribute. In this example, I use jQuery .data()
Also, it's advisable that you use submit event instead of adding a click handler to the submit button when you submit a form.
$('#signupform').on('submit', function() {
var form = $(this),
loading = form.data('loading'), //check loading status
str, button, val;
//if not loading
if(!loading){
//set loading to true
form.data('loading',true);
str = form.serialize();
button = $('#signup1', form);
val = button.val();
// make it look like a waiting button
button
.addClass("btn_wait");
.val('');
$.ajax({
type: "POST",
url: "signup_step1.php",
data: str,
success: function(msg) {
//remove loading state
form.data('loading',false);
//return button to normal
button
.removeClass("btn_wait");
.val(val);
}
});
}
});
I have some jquery that looks like this,
$('.career_select .selectitems').click(function(){
var selectedCareer = $(this).attr('title');
$.ajax({
type: 'POST',
url: '/roadmap/step_two',
data: 'career_choice='+selectedCareer+"&ajax=true&submit_career=Next",
success: function(html){
$('.hfeed').append(html);
$('#grade_choice').SelectCustomizer();
}
});
});
My problem is that if the user keeps clicking then the .hfeed keeps getting data appended to it. How can I limit it so that it can only be clicked once?
Use the one function:
Attach a handler to an event for the elements. The handler is executed at most once per element
If you wanted the element to only be clicked once and then be re-enabled once the request finishes, you could:
A) Keep a state variable that updates if a request is currently in progress and exits at the top of the event if it is.
B) Use one, put your code inside a function, and rebind upon completion of request.
The second option would look like this:
function myClickEvent() {
var selectedCareer = $(this).attr('title');
var that = this;
$.ajax({
type: 'POST',
url: '/roadmap/step_two',
data: 'career_choice='+selectedCareer+"&ajax=true&submit_career=Next",
success: function(html){
$('.hfeed').append(html);
$('#grade_choice').SelectCustomizer();
},
complete: function() {
$(that).one('click', myClickEvent);
}
});
}
$('.career_select .selectitems').one('click', myClickEvent);
You can either use a global variable like
var added = false;
$('.career_select .selectitems').click(function(){
if(!added) {
// previous code here
added = true;
}
});
or use .one("click", function () { ... }) instead of the previous click function to execute the handler at most once per element. See http://api.jquery.com/one/ for more details.