How to prevent duplicated AJAX call? - javascript

I'm currently building a simple AJAX call application which will show the result of a textbox after typing some texts inside it:
var delay = (function(){
var timer = 0;
return function(callback, ms){
clearTimeout (timer);
timer = setTimeout(callback, ms);
};
})();
$(document).ready(function(e) {
$("input[name=html]").keyup(function(e) {
if(this.value.length > 1) {
e.preventDefault();
var form = $(this).closest('form');
var form_data = form.serialize();
var form_url = form.attr("action");
var form_method = form.attr("method").toUpperCase();
delay(function(){
$("#loadingimg").show();
$.ajax({
url: form_url,
type: form_method,
data: form_data,
cache: false,
success: function(returnhtml){
$("#result").html(returnhtml);
$("#loadingimg").hide();
}
});
},1000);
}
});
});
Fiddle Demo
As you can see from the demo above, for instance if you type test,test1 or test2 or any word as long as their length is longer than one then it'll make an AJAX call.
My question is that is there any way that allow me to prevent duplicate AJAX call? For example if I type test in the textbox again, it'll immediately show test in the div without making another AJAX call to fetch the result again. Thank you very much in advance.

You just need to cache previous results and, before making the ajax call, check the cache to see if you already have that result in the cache.
In Javascript, one usually uses an object for a cache:
var delay = (function(){
var timer = 0;
return function(callback, ms){
clearTimeout (timer);
timer = setTimeout(callback, ms);
};
})();
// create cache for ajax results
// the key is the form_data
// the value is whatever the ajax call returns
var ajaxCache = {};
$(document).ready(function(e) {
$("input[name=html]").keyup(function(e) {
if(this.value.length > 1) {
e.preventDefault();
var form = $(this).closest('form');
var form_data = form.serialize();
// check the cache for a previously cached result
if (ajaxCache[form_data]) {
// this uses delay, only so that it clears any previous timer
delay(function() {
$("#result").html(ajaxCache[form_data]);
$("#loadingimg").hide();
}, 1);
} else {
var form_url = form.attr("action");
var form_method = form.attr("method").toUpperCase();
delay(function(){
$("#loadingimg").show();
$.ajax({
url: form_url,
type: form_method,
data: form_data,
cache: false,
success: function(returnhtml){
$("#result").html(returnhtml);
// put this result in the cache
ajaxCache[form_data] = returnhtml;
$("#loadingimg").hide();
}
});
},1000);
}
}
});
});
Working demo: http://jsfiddle.net/jfriend00/P2WRk/

Related

if/else with setInterval auto-refreshing and on click refreshing event jquery?

Struggling to get this to work properly...Making an if/else statement with setInterval that if class is clicked, content refreshes, else content auto refreshes after a specific time period. This is what I have for just auto refreshing atm (which works perfectly):
var auto_refreshContentTwo = setInterval (
function() {
$('.page_loading_r_content_two_overlay').fadeIn();
$.ajax({
url: '../../path/to/page.php',
success: function(html) {
var myContentTwoContent = $('#refreshContentTwo').html(html).find('#refreshContentTwo2');
$('#refreshContentTwo').html(myContentTwoContent);
}
});
}, 495000
);
What I've tried to get a "click" function added, but doesn't do anything...:
$('.contentTwoClicked').on('click', function() {
var refreshClicked = true;
if(refreshClicked) {
alert('clicked');
$('.page_loading_r_content_two_overlay').fadeIn();
$.ajax({
url: '../../path/to/page.php',
success: function(html) {
var myContentTwoContent = $('#refreshContentTwo').html(html).find('#refreshContentTwo2');
$('#refreshContentTwo').html(myContentTwoContent);
}
});
} else {
var auto_refreshContentTwo = setInterval (
function() {
$('.page_loading_r_content_two_overlay').fadeIn();
$.ajax({
url: '../../path/to/page.php',
success: function(html) {
var myContentTwoContent = $('#refreshContentTwo').html(html).find('#refreshContentTwo2');
$('#refreshContentTwo').html(myContentTwoContent);
}
});
}, 495000
);
}
});
Where am I going wrong? Or am I way off-base here...? Any guidance/help would be greatly appreciated!
You don't need a conditional statement, but rather a variable to store the set interval in so that it can be cleared and restarted on manual refresh via a calling function:
//variable to store the setInterval
let refreshInterval = '';
//function that calls setInterval
const autoRefresh = () => {
refreshInterval = setInterval(()=> {
refresh();
console.log("auto");
},3000)
}
//run setInterval function on page load;
autoRefresh();
//manual refresh function
const manualRefresh = () => {
//erases the setInterval variable
clearInterval(refreshInterval);
refresh();
//then recalls it to reset the countdown
autoRefresh();
console.log("manual");
}
//for visual purposes
let refreshCount = 0;
//node refresher function
const refresh = () => {
const container = document.getElementById("refresh");
refreshCount ++;
container.textContent= "This div will be refreshed"+ ` Refresh Count: ${refreshCount}`;
}
<button onclick="manualRefresh()">Click to Refresh </button>
<div id="refresh">This div will be refreshed</div>
See it in action: https://codepen.io/PavlosKaralis/pen/rNxzZjj?editors=1111
Edit: Applied to your code I think it would be:
let interval;
var autoRefresh = () => {
interval = setInterval (
function() {
$('.page_loading_r_content_two_overlay').fadeIn();
$.ajax({
url: '../../path/to/page.php',
success: function(html) {
var myContentTwoContent = $('#refreshContentTwo').html(html).find('#refreshContentTwo2');
$('#refreshContentTwo').html(myContentTwoContent);
}
});
}, 495000);
}
$('.contentTwoClicked').on('click', function() {
clearInterval(interval);
alert('clicked');
$('.page_loading_r_content_two_overlay').fadeIn();
$.ajax({
url: '../../path/to/page.php',
success: function(html) {
var myContentTwoContent = $('#refreshContentTwo').html(html).find('#refreshContentTwo2');
$('#refreshContentTwo').html(myContentTwoContent);
}
});
autoRefresh();
});
autoRefresh();

Animation effect before ajax call

I've watched several tutorials on how to load content without having to refresh the browser. I'm also using history pushState and popstate to update the url dynamically depending on what site that is displaying. However even if this code works, I would like to be able to make som page transition animation effects > call the Ajax function > then make some fadeIn animation effects. So far i've had no luck in trying to do so. I tried to read up on Ajax (beforeSend: function(){}), but the success function seems to execute before the (beforeSend) function. Is there anyone that could point me in the right direction, or tell me what i possibly am doing wrong? I'd appriciate it!
$(document).ready(function() {
var content, fetchAndInsert;
content = $('div#content');
// Fetches and inserts content into the container
fetchAndInsert = function(href) {
$.ajax({
url: 'http://localhost:8000/phpexample/content/' + href.split('/').pop(),
method: 'GET',
cache: false,
success: function(data) {
content.html(data);
}
});
};
// User goes back/forward
$(window).on('popstate', function() {
fetchAndInsert(location.pathname);
});
$('.buttonlink').click(function(){
var href = $(this).attr('href');
// Manipulate history
history.pushState(null, null, href);
// Fetch and insert content
fetchAndInsert(href);
return false;
});
});
Questions? Just ask!
Thanks beforehand!
/// E !
You need to use callbacks. The provided solutions will work, but not necessarily sequentially. $.animate() and $.ajax both run asynchronously. If unfamiliar with this term, here's a good intro: http://code.tutsplus.com/tutorials/event-based-programming-what-async-has-over-sync--net-30027
Here's what I might do:
fetchAndInsert = function(href) {
$('#some-element').animate({'opacity':'0.0'}, 1000, function () {
$.ajax({
url: 'http://localhost:8000/phpexample/content/' + href.split('/').pop(),
method: 'GET',
cache: false,
success: function(data) {
content.html(data);
content.animate({'opacity':'1.0'}, 1000);
}
});
});
};
That will fade out whatever is currently in content, fetch the new data, replace what's currently in content, and then fade back in.
I tried to read up on Ajax (beforeSend: function(){}), but the success
function seems to execute before the (beforeSend) function
You can wait for animation to complete before appending new content to html using .queue(), .promise(), .finish()
beforeSend: function() {
element.queue(function() {
$(this).animate({/* do animation stuff */:500}, {duration:5000}).dequeue()
});
},
success: function(content) {
element.finish().promise("fx").then(function() {
container.append(content).fadeIn()
})
}
var element = $("#loading").hide();
var container = $("#content");
var button = $("button");
var ajax = {
// do asynchronous stuff
request: function() {
return new $.Deferred(function(d) {
setTimeout(function() {
d.resolve("complete")
}, Math.random() * 5000)
})
},
beforeSend: function() {
element.fadeIn().queue(function() {
$(this).animate({
fontSize: 100
}, {
duration: 2500
}).dequeue()
});
},
success: function(content) {
element.finish().promise("fx").then(function() {
element.fadeOut("slow", function() {
$(this).css("fontSize", "inherit");
container.append(content + "<br>").fadeIn("slow");
button.removeAttr("disabled")
})
})
}
}
button.click(function() {
$(this).attr("disabled", "disabled");
$.when(ajax.beforeSend()).then(ajax.request).then(ajax.success)
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
<div id="loading">loading...</div>
<div id="content"></div>
<button>load content</button>
jsfiddle https://jsfiddle.net/ajmL5g1a/
Try this:
fetchAndInsert = function(href) {
// Before send ajax. Do some effects here
$.ajax({
url: 'http://localhost:8000/phpexample/content/' + href.split('/').pop(),
method: 'GET',
cache: false,
success: function(data) {
// After loading. Do some effects here
content.html(data);
}
});
};
My solution:
fetchAndInsert = function(href) {
var timeBeforeAnimation = Date.now(), animationDuration = 500;
/* Do some animation, I assume that with jQuery,
so you probably know how much time is takes - store that
time in variable `animationDuration`. */
/* Run your "before" animation here. */
$.ajax({ ...,
success: function(data) {
/* Check, if request processing was longer than
animation time... */
var timeoutDuration = animationDuration -
(Date.now() - timeBeforeAnimation);
/* ...and if so, delay refreshing the content,
and perform the final animation. */
setTimeout(function() {
content.html(data);
/* Perfom final animation. */
}, Math.max(0, timeoutDuration);
}
});
};
I would probably try using some css for this.
#content {
opacity: 0;
transition: all 1s;
}
#content.fade-in {
opacity: 1;
}
...
const content = $('#content');
const btn = $('.buttonlink');
const success = data =>
content.html(data).addClass('fade-in');
const fetchAndInsert = url =>
$.ajax({ url, cache: 'false' }).done(success);
const getData = function(e) {
e.preventDefault();
content.removeClass('fade-in');
fetchAndInsert($(this).attr('href'));
};
btn.on('click', getData)

Firing a function every x seconds

I am currently using a keyup function to initiate my autosave.php file which auto saves information to a table. However, I am starting to find that the keyup seems to be inefficient due to fast typing and submitting long strings.
How can I have the ajax submit every x seconds, instead of each keyup after so many ms?
$(document).ready(function()
{
// Handle Auto Save
$('.autosaveEdit').keyup(function() {
delay(function() {
$.ajax({
type: "post",
url: "autosave.php",
data: $('#ajaxForm').serialize(),
success: function(data) {
console.log('success!');
}
});
}, 500 );
});
});
var delay = (function() {
var timer = 0;
return function(callback, ms) {
clearTimeout (timer);
timer = setTimeout(callback, ms);
};
})();
Solution
Use setInterval It is like setTimeout but repeats itself.
setInterval(function () {
$.ajax({
type: "post",
url: "autosave.php",
data: $('#ajaxForm').serialize(),
success: function(data) {
console.log('success!');
}
});
}, 1000);
Optimization
turn it on when the control has focus and turn it off when focus leaves. Also poll for the form data if it has updated then send the ajax request otherwise ignore it.
var saveToken;
var save = (function () {
var form;
return function () {
var form2 = $('#ajaxForm').serialize();
if (form !== form2) { // the form has updated
form = form2;
$.ajax({
type: "post",
url: "autosave.php",
data: form,
success: function(data) {
console.log('success!');
}
});
}
}
}());
$('.autosaveEdit').focus(function() {
saveToken = setInterval(save, 1000);
});
$('.autosaveEdit').focusout(function() {
clearInterval(saveToken);
save(); // one last time
});
I believe that what you are looking for is the window.setInterval function. It's used like this:
setInterval(function() { console.log('3 seconds later!'); }, 3000);
Use setInterval
function goSaveIt()
{
$.ajax({
type: "post",
url: "autosave.php",
data: $('#ajaxForm').serialize(),
success: function(data) {
console.log('success!');
}
});
}
setInterval(goSaveIt, 5000); // 5000 for every 5 seconds

Disable 2 buttons after click of a button

I have a submit button on page index.php When i click this button another script (call.php) is called through ajax that holds some response. Now i want that time between the click of submit button and response displayed/received under a div through the call of ajax script the buttons option1 and option2 should get disabled. and when succesfully the result is dispalyed the 2 buttons should get enabled, however i am not able to do so. can anyone help me with it
3 buttons and script code on index.php page is
<button class="rightbtn" type="button" id="submitamt" style="display:none; ">Submit</button>
<button class="botleftbtn" type="button" id="walkaway" style="display:none">Option1</button>
<button class="botrightbtn" type="button">Option2</button>
<script>
function myFunction() {
alert("You need to login before negotiating! However you can purchase the product without negotiating");
}
var startClock;
var submitamt;
var walkaway;
var digits;
$(function() {
startClock = $('#startClock').on('click', onStart);
submitamt = $('#submitamt').on('click', onSubmit);
walkaway = $('#walkaway').on('click', onWalkAway);
digits = $('#count span');
beforeStart();
});
var onStart = function(e) {
startClock.fadeOut(function() {
startTimer();
submitamt.fadeIn(function() {
submitamt.trigger('click'); // fire click event on submit
});
walkaway.fadeIn();
});
};
var onSubmit = function(e) {
var txtbox = $('#txt').val();
var hiddenTxt = $('#hidden').val();
$.ajax({
type: 'post',
url: 'call.php',
dataType: 'json',
data: {
txt: txtbox,
hidden: hiddenTxt
},
cache: false,
success: function(returndata) {
$('#proddisplay').html(returndata);
},
error: function() {
console.error('Failed to process ajax !');
}
});
};
var onWalkAway = function(e) {
//console.log('onWalkAway ...');
};
var counter;
var timer;
var startTimer = function() {
counter = 120;
timer = null;
timer = setInterval(ticker, 1000);
};
var beforeStart = function() {
digits.eq(0).text('2');
digits.eq(2).text('0');
digits.eq(3).text('0');
};
var ticker = function() {
counter--;
var t = (counter / 60) | 0; // it is round off
digits.eq(0).text(t);
t = ((counter % 60) / 10) | 0;
digits.eq(2).text(t);
t = (counter % 60) % 10;
digits.eq(3).text(t);
if (!counter) {
clearInterval(timer);
alert('Time out !');
resetView();
}
};
var resetView = function() {
walkaway.fadeOut();
submitamt.fadeOut(function() {
beforeStart();
startClock.fadeIn();
});
};
</script>
You can achieve this by disabling the buttons before you make the AJAX request, and then enabling them again in the complete handler of the request. Try this:
var onSubmit = function(e) {
var txtbox = $('#txt').val();
var hiddenTxt = $('#hidden').val();
$('.botleftbtn, .botrightbtn').prop('disabled', true); // < disable the buttons
$.ajax({
type: 'post',
url: 'call.php',
dataType: 'json',
data: {
txt: txtbox,
hidden: hiddenTxt
},
cache: false,
success: function(returndata) {
$('#proddisplay').html(returndata);
},
error: function() {
console.error('Failed to process ajax !');
},
complete: function() {
$('.botleftbtn, .botrightbtn').prop('disabled', false); // < enable the buttons
}
});
};
Note that its best to enable the buttons in the complete handler and not the success handler. This is because if there is an error the buttons will never be enabled again.
Disable the buttons on click, and enable them on ajax success:
var onSubmit = function(e) {
var txtbox = $('#txt').val();
var hiddenTxt = $('#hidden').val();
//Disable buttons ---------------------- //
//Give an id to the second button
$('#walkaway, #the_other_button').prop('disabled', true);
$.ajax({
type: 'post',
url: 'call.php',
dataType: 'json',
data: {
txt: txtbox,
hidden: hiddenTxt
},
cache: false,
success: function(returndata) {
$('#proddisplay').html(returndata);
//Enable buttons ---------------------- //
$('#walkaway, #the_other_button').prop('disabled', false);
},
error: function() {
console.error('Failed to process ajax !');
}
});
};
In your onsubmit() code, get a var reference to the buttons you wish to deactivate
Var btn1 = document.getElementbyId("btn1");
But you would have to set an Id for the two buttons.
You can disable these in your submit code and then enable them when your timer is done.
Btn1.disabled = true;
When your timer is done, set it as false the same way.

simple ajax request with interval

I recently began learning Ajax and jQuery. So yesterday I started to programm a simple ajax request for a formular, that sends a select list value to a php script and reads something out of a database.
It works so far!
But the problem is, that when I click on the send button, it starts the request, 1 second later. I know that it has something to do with my interval. When I click on the send button, I start the request and every second it requests it also, so that I have the opportunity, to auto-refresh new income entries.
But I'd like to have that interval cycle every second, but the first time I press the button it should load immediately, not just 1 second later.
Here is my code:
http://jsbin.com/qitojawuva/1/edit
$(document).ready(function () {
var interval = 0;
$("#form1").submit(function () {
if (interval === 0) {
interval = setInterval(function () {
var url = "tbladen.php";
var data = $("#form1").serialize();
$.ajax({
type: "POST",
url: url,
data: data,
success: function (data) {
$("#tbladen").html(data);
}
});
}, 1000);
}
return false;
});
});
Thanks!
I might be something like the following you're looking for.
$(document).ready(function () {
var isFirstTime = true;
function sendForm() {
var url = "tbladen.php";
var data = $("#form1").serialize();
$.ajax({
type: "POST",
url: url,
data: data,
success: function (data) {
$("#tbladen").html(data);
}
});
}
$("#form1").submit(function () {
if (isFirstTime) {
sendForm();
isFirstTime = false;
} else {
setTimeout(function () {
sendForm();
}, 1000);
}
return false;
});
});
So, use setTimeout when the callback has finished as setInterval just keeps running whether or not your callback has finished.
$(function () {
$("#form1").submit(postData);
function postData() {
var url = "tbladen.php",
data = $("#form1").serialize();
$.ajax({
type: "POST",
url: url,
data: data,
success: function (data) {
$("#tbladen").html(data);
setTimeout(postData, 1000);
}
});
return false;
}
});
Kind of related demo

Categories