I have a function which calls itself with a pause of 2 seconds until the ajax call returns 0. Now it can go on for a long time, hence i wish to pause it or stop it with an external event like a button click.
function create_abcd()
{
var dataString = 'action=create_abcd&type=' + $('#abcd_type').val() + '&count=100';
$.ajax({
type: "POST",
url: "backend.php",
data: dataString,
success: function(msg){
if(msg != "0")
{
$("#abcd_output").append('<p>' + msg + '</p>')
setTimeout(create_abcd, 2000);
}
else
return false;
}
});
}
any help would be greatly appreciated!
Something like:
var needStop = false;
function create_abcd()
{
var dataString = 'action=create_abcd&type=' + $('#abcd_type').val() + '&count=100';
$.ajax({
type: "POST",
url: "backend.php",
data: dataString,
success: function(msg){
if(needStop) {
needStop = false;
return;
}
if(msg != "0")
{
$("#abcd_output").append('<p>' + msg + '</p>')
setTimeout(create_abcd, 2000);
}
else
return false;
}
});
}
$('#button').click(function() {
needStop = true;
});
=)
I think you're trying to solve your problem in a wrong way. You're obviously want to gen notified when some long-running process finishes on the server, so you poll every 2 secs. This will cause a lot of unnecessary requests.
Instead use push mechanism.
Consider using COMET, since you're PHP:
http://www.zeitoun.net/articles/comet_and_php/start
Create a global variable (or even a hidden input on the page).
Create a 'stop' button on the page.
When you click the 'stop' button you just set that input or variable to a special value.
At the top of your create_abcd just check that variable or input before proceeding. If the special value is set, just exit before setting the timeout again.
Related
In the below code I am making an API call to my backend node.js app using setTimeout() which calls my AJAX at every 5 seconds. Inside my AJAX success I am displaying divContent1 & divContent2 based on certain condition which should execute at least once. After that only divContent2 should be visible at each setTimeout() calls.
index.html
<script type="text/javascript">
$(document).ready(function(){
$.ajax({
url: "http://localhost:8070/api/route1",
type: 'POST',
dataType:'json',
success: function(res) {
//Some Task
}
});
$("#myButton").click(function(){
const route2 = function() {
$.ajax({
url: "http://localhost:8070/api/route2",
type: "POST",
dataType: "json",
data: { var1: val1 },
success: function (res) {
// Various tasks
if(res.flag){
$("#divContent1").hide();
$("#divContent2").show();
}
else{
$("#divContent1").show();
}
//Functions that handle div content data
},
beforeSend: function() {
$("#divContent1").hide();
$("#divContent2").hide();
},
complete: function() {
setTimeout(route2,5000);
},
});
};
$(function(){
route2();
})
});
});
</script>
The setTimeout() calls the entire route2 function which handles all the display and insertion of div content. However, the ask is to only display divContent2 from the second call.
Looking for a solution for this
The setTimeout() calls the entire route2 function which handles all
the display and insertion of div content. However, the ask is to only
display divContent2 from the second call.
You're calling route2 recursively with setTimeout(route2,5000); under complete. So this will run infinitely as complete occur each time an ajax call is completed (wether success or error). So what you can do is to create a timer and clear it after the second execution, something like this:
var ctr = 0, timer =0;
const route2 = function() {
$.ajax({
...
success: function (res) {
//Write you logic based on ctr
}
complete: function() {
if(ctr>0){
clearTimeout(timer)
}else{
timer = setTimeout(route2,5000);
ctr = ctr+ 1;
}
},
});
};
Will an external variable be enough? Just define it in the outer context and set/check it to choose the behavior:
// before declaring button click handler
var requestDoneAtLeastOnce = false;
// ...
// somewhere in success handler
success: function (res) {
if (!requestDoneAtLeastOnce) {
requestDoneAtLeastOnce = true;
// do something that belongs only to handling the first response
}
else {
// this is at least the second request, the other set of commands belongs here
}
}
I want to dynamically change the Ajax URL, this is what I have done so far :
var size=1;
var from = 1;
window.addEventListener('mousewheel', function(e){
if(e.wheelDelta<0 && from<5){
from++;
}
else if(e.wheelDelta>0 && from>1){
from--;
}
console.log(from)
});
$.ajax({
type: 'GET',
url: "/api/v1/users?f="+from+"&s="+size,
data: { get_param: 'value' },
dataType: 'json',
With the mousewheel event I change the value of "from", with this variable I can concatenate the string /api/v1/users?f="+from+"&s="+size, to form a URL.
The variable works fine when I give mousewheel event-listener, but doesn't change the Ajax URL.
Any tips?
Your understanding is not right, your scroll code block change the value of from when scrolling is done. But when page loads the ajax call initiates with the initial value of from.
So to solve this you have to call ajax inside event handler.
If i understand you correctly i think following will help you.
You need to move the ajax call inside the event listner to get the values of from in ajax call
Here is my solution based on the code you provided.
var size = 1;
var from = 1;
window.addEventListener('mousewheel', function(e) {
if (e.wheelDelta < 0 && from < 5) {
from++;
} else if (e.wheelDelta > 0 && from > 1) {
from--;
}
$.ajax({
type: 'GET',
url: "/api/v1/users?f=" + from + "&s=" + size,
data: {
get_param: 'value'
},
dataType: 'json',
success: function() {}
})
});
I am trying to make a facebook style user typing system. But i have one question about keypress.
So my code is working fine but i want to change something else like keypress, keyup, paste ect.
I am using following javascript and ajax codes. In the following my ajax code is working like if ($.trim(updateval).length == 0) { send width notyping.php notyping.php posting 0 and the 0 is don't show typing message.
If if ($.trim(updateval).length > 13) { send with usertyping.php usertyping.php posting 1 and the 1 is show typing message.
The problem is here if user is stoped to wrire some message then it is everytime saying typing. What should I do to fix for it anyone can help me in this regard ?
All ajax and javascript code is here:
;
(function($) {
$.fn.extend({
donetyping: function(callback, timeout) {
timeout = timeout || 1000; // 1 second default timeout
var timeoutReference,
doneTyping = function(el) {
if (!timeoutReference) return;
timeoutReference = null;
callback.call(el);
};
return this.each(function(i, el) {
var $el = $(el);
// Chrome Fix (Use keyup over keypress to detect backspace)
// thank you #palerdot
$el.is(':input') && $el.is(':input') && $el.on('keyup keypress paste', function(e) {
// This catches the backspace button in chrome, but also prevents
// the event from triggering too premptively. Without this line,
// using tab/shift+tab will make the focused element fire the callback.
if (e.type == 'keypress' && e.keyCode != 8) return;
// Check if timeout has been set. If it has, "reset" the clock and
// start over again.
if (timeoutReference) clearTimeout(timeoutReference);
timeoutReference = setTimeout(function() {
// if we made it here, our timeout has elapsed. Fire the
// callback
doneTyping(el);
}, timeout);
}).on('blur', function() {
// If we can, fire the event since we're leaving the field
doneTyping(el);
});
});
}
});
})(jQuery);
Checking text value if is 0 then send data is 0 for user no typing
$('#chattextarea').donetyping(function() {
var typingval = $("#chattextarea").val();
var tpy = $('#tpy').val();
if ($.trim(typingval).length == 0) {
$.ajax({
type: "POST",
url: "/notyping.php",
data: {
tpy: tpy
},
success: function(data) {
}
});
}
Checking text value is >13 then send data is 1 for user typing.(Maybe need to change this if statement)
if ($.trim(typingval).length > 13) {
$.ajax({
type: "POST",
url: "/usertyping.php",
data: {
tpy: tpy
},
success: function(data) {
}
});
}
});
Check and show user typing:
function getTyping(){
setInterval(function(){
var tpy = $('#tpy').val();
$.ajax({
type: "POST",
url: "/getTyping.php",
data: { tpy: tpy },
success: function(data) {
$('#s').html(data);
}
});
},1000);
}
getTyping();
HTML
<textarea id="chattextarea"></textarea>
<div id="s"></div>
I have some remarks about your code and app :
At the first, and as mentioned by #rory-mccrossan, unless you have the infrastructure of facebook, google or microsoft, ..., I think it's really a bad idea to use Ajax instead of Websockets for a real time application like a chat.
Now about your code, I don't know what your PHP scripts are doing behind the scene, but I think that you don't need to send two requests to indicate that the user is typing or not, you can limit that to one request to be sent when the user is typing otherwise, he is surely not typing. Of course you can use some sort of a timeout in your getTyping.php script to limit the life time of a "typing" status (for example 5 seconds), so if a request is sent after that timeout, you can know that your user is not typing.
And about your current problem, I think that's because the "not typing" status is just fired when the textarea is empty, so of course, after stopping writing and the length of the current text is more that 13, so the "not typing" status will never be fired (sent), that's why you need a timeout as I told you in the 2nd point ...
Also, don't forget the cache problem when getting the status using the getTyping.php script which should be not cacheable (or at least for a very limited period) ...
Then, I don't see in your posted code any information(s) to identify the current user and the one which is converting with him ... maybe you haven't included that in the question, I don't know !
...
Hope that can help.
My suggestion here to have external setInterval which will each 3 seconds save current text in oldValue variable and compare currentText with oldValue if they are equal then user stopped writing then send ajax to notyping.php
your updated code is given below
i have created a getTyping function which will be call at every time 1 sec interval if user get start typing.
in get getTyping setinterval function i called a function check_which_function.
in function check_which_funciton i used your code by applying conditions on textarea value length which is in nested if else statement , so now
if user start typing but if content length is =0 than
$.trim(typingval).length == 0 will execute till length is not equal to 12
if length of content is greather equal to 13 than
$.trim(typingval).length > 13 will execute
by default getTyping2() function is executing in this function getTyping.php ajax call is going
<script>
(function ($) {
$.fn.extend({
donetyping: function (callback, timeout) {
timeout = timeout || 1000; // 1 second default timeout
var timeoutReference,
doneTyping = function (el) {
if (!timeoutReference)
return;
timeoutReference = null;
callback.call(el);
};
return this.each(function (i, el) {
var $el = $(el);
// Chrome Fix (Use keyup over keypress to detect backspace)
// thank you #palerdot
$el.is(':input') && $el.is(':input') && $el.on('keyup keypress paste', function (e) {
// This catches the backspace button in chrome, but also prevents
// the event from triggering too premptively. Without this line,
// using tab/shift+tab will make the focused element fire the callback.
if (e.type == 'keypress' && e.keyCode != 8)
return;
// Check if timeout has been set. If it has, "reset" the clock and
// start over again.
if (timeoutReference)
clearTimeout(timeoutReference);
timeoutReference = setTimeout(function () {
// if we made it here, our timeout has elapsed. Fire the
// callback
doneTyping(el);
}, timeout);
}).on('blur', function () {
// If we can, fire the event since we're leaving the field
doneTyping(el);
});
});
}
});
})(jQuery);
function getTyping2() {
var tpy = $('#tpy').val();
$.ajax({
type: "POST",
url: "/getTyping.php",
data: {tpy: tpy},
success: function (data) {
$('#s').html(data);
}
});
}
function check_which_action() {
$('#chattextarea').donetyping(function () {
var typingval = $("#chattextarea").val();
var tpy = $('#tpy').val();
if ($.trim(typingval).length == 0) {
$.ajax({
type: "POST",
url: "/notyping.php",
data: {
tpy: tpy
},
success: function (data) {
}
});
}
else if ($.trim(typingval).length > 13) {
$.ajax({
type: "POST",
url: "/usertyping.php",
data: {
tpy: tpy
},
success: function (data) {
}
});
}
else {
getTyping2() ;
}
});
}
function getTyping() {
setInterval(check_which_action, 1000);
}
getTyping();
</script>
<textarea id="chattextarea"></textarea>
<div id="s"></div>
I'm trying to fetch posts dynamically using AJAX and JQuery by checking if the user is close to the bottom. Serverside is in python on GAE.
Listening for scroll:
this.config.window.on('scroll',this.loadContent);
1.Checking for distance from bottom
2.Sending an ajax request with the number of current posts in order to retrieve the next 10
3.results.check = true means that the server has no further posts to send.
loadContent: function(){
// 1
if($(document).height() - $(window).height() - $(window).scrollTop() < 1000) {
var posts = $('.troll').children('div').length;
data = 'loadmore=True&offset=' + posts; //2
$.ajax({
url: '/',
type: 'POST',
data: data,
dataType: 'json',
success: function(results){
if (results.check === 'true'){ //3
$(window).unbind('scroll');
return;
}
Post.insert10Values(results);
}
});
};
},
insert10Values: function(results){
var update = Handlebars.compile($('#troll10').html()),
troll10update = update(results);
$('div.troll').append( troll10update );
}
The problem here is that when scrolling fast, two or more requests are sent to the server and i get duplicate entries. I want to rate-limit on client-side.
Set a flag loading = false. Before you send a request, check the flag. If it's false, set the flag to true and proceed with request, otherwise ignore the event. When results arrive, show them and set the flag back to false.
Part of your problem is scroll event will trigger many times a second
you can throttle any function calls doing something like this:
var scrollTimer=false;
var delay=500; /* 1/2 second*/
$(window).on('scroll',function(){
if( scrollTimer){
clearTimeout( scrollTimer);
}
scrollTimer=setTimeout(function(){
/* run your code here*/
}, delay);
});
As for the ajax you could store a time for last ajax call and set a miniumum difference based on now vs stored time before making a new ajax call
var lastAJAX=Date.now(), AJAXMin=5000;/* 5 seconds*/
function checkAJAXCalls(){
var now=Date.now(), diff=now-lastAJAX;
if( diff >= AJAXMin){
lastAJAX=now;
return true;
}else{
return false;
}
}
Then run if(checkAJAXCalls()) prior to making request. Concept could be modified to update lastAJAX in success callback of $.ajax also
jQuery.ajax has a method called beforeSend. It is executed right before your ajax call. You can use it to check if any other request is in progress and cancel the call if there is one. If you return false in beforeSend function, the ajax call will not be fired so you won't have any duplicate content.
$.ajax({
url: '/',
type: 'POST',
data: data,
dataType: 'json',
beforeSend: function() {
if (window.nextPageProcess) {
return false;
} else {
window.nextPageProcess = 1;
}
},
success: function(results){
if (results.check === 'true'){ //3
$(window).unbind('scroll');
return;
}
Post.insert10Values(results);
window.nextPageProcess = 1;
}
});
Look at this code please - how could I kill / update or restart an ajax call (not content that Ajax calls) after the content has already been called?
I mean the $('#posting_main') is called onclick and animated - how to stop ajax and make it another $('#posting_main') on another click?
$(document).ready(function() {
$("#img_x_ok").click(function(e){
e.preventDefault();
var post_text = $.trim($("#main_text_area").val());
var data_text = 'post_text='+ post_text;
if (post_text === "") return;
var xhr = $.ajax({
type: "POST",
url: "comm_main_post.php",
data: data_text,
cache: false,
success: function (data){
//content
$("#posting_main").fadeIn();
$("#posting_main").load("pull_comm.php");
$("#main_text_area").attr("value", "");
$("#posting_main").animate({
marginTop: "+=130px",
}, 1000 );
}
}); //ajax close
}); }); //both functions close
You can abort the current request with:
xhr.abort();
After having done that, you can run another $.ajax(...) to make a second request.
You could implement it like the following. Note that indenting code makes it a lot more readable!
$(document).ready(function() {
var xhr; // by placing it outside the click handler, you don't create
// a new xhr each time. Rather, you can access the previous xhr
// and overwrite it this way
$("#img_x_ok").click(function(e){
e.preventDefault();
var post_text = $.trim($("#main_text_area").val());
var data_text = 'post_text='+ post_text;
if (post_text === "") return;
if(xhr) xhr.abort(); // abort current xhr if there is one
xhr = $.ajax({
type: "POST",
url: "comm_main_post.php",
data: data_text,
cache: false,
success: function (data){
//content
$("#posting_main").fadeIn();
$("#posting_main").load("pull_comm.php");
$("#main_text_area").attr("value", "");
$("#posting_main").animate({
marginTop: "+=130px",
}, 1000 );
}
});
});
});
I am not sure I fully understand your question, however:
xhr.abort() will kill the AJAX request. After calling abort(), you could modify and resend the request, if desired.
$("#posting_main").stop() will stop the fadeIn animation. (And I think you might need to follow that with $("#posting_main").hide() to be sure it isn't left partially visible.)