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)
Related
I have two very similar jquery AJAX codes. Both work correctly when I use them separately. However, if I load the first code, if I want to load the second it probably works (because I tested different places "console.log(''test'')"), but it doesn't change the DOM. Please help.
I have tried many different solutions and none have provided a solution. I have searched on many forums but have not found an answer.
1st
var basketAddTimeout;
var ajaxSubmitForm;
app_shop.run(function() {
ajaxSubmitForm = function() {
$this = $('#projector_button_basket');
var url = $('#projector_form').attr('action');
var txt = $this.text().trim();
clearTimeout(basketAddTimeout);
$.ajax({
type: 'POST',
url: url,
data: $('#projector_form').serializeArray(),
success: function(data) {
basketAddTimeout = setTimeout(function() {
$('#Basket').load(' #projector-basket-form');
}, 1000)
fetch('/ajax/basket.php').then(res => res.json()).then(({
basket
}) => {
const number = basket.productsNumber;
const number12 = basket.worth_formatted;
$('#kwota-basket').text(number12);
document.getElementById('badgekoszyka').style.display = 'block';
$( "#badgekoszyka" ).fadeOut( "slow");
$( "#badgekoszyka" ).fadeIn( "slow");
$('#menu_basket .badge').text(number);
$('#badgekoszyka').text(number);
})
},
error: function() {
classObj.alert(classObj.txt.dodano_produkt_blad);
$('#projector_button_basket').html(txt);
$('#projector_button_basket').removeClass('loader');
}
});
}
}, 'all');
second
var basketAddTimeout2;
var ajaxSubmitForm2;
app_shop.run(function() {
ajaxSubmitForm2 = function() {
var url = $('#projector-basket-form').attr('action');
$('#loaders').addClass('loader-koszyk');
$('#blok-koszyk').css('filter','blur(3px)');
clearTimeout(basketAddTimeout2);
$.ajax({
type: 'POST',
url: url,
data: $('#projector-basket-form').serializeArray(),
success: function(data) {
basketAddTimeout2 = setTimeout(function() {
}, 1000)
fetch('/ajax/basket.php').then(res => res.json()).then(({
basket
}) => {
const number = basket.productsNumber;
const number12 = basket.worth_formatted;
$('#kwota-basket').text(number12);
$('#menu_basket .badge').text(number);
$('#badgekoszyka').text(number);
$('.topBasket').load('/basketchange.php?type=multiproduct&mode=2 .topBasket>*', function() {});
$('#loaders').removeClass('loader-koszyk');
$('#blok-koszyk').css('filter','blur(0px)');
document.getElementById("Basket").innerHTML = contentt;
})
},
error: function() {
classObj.alert(classObj.txt.dodano_produkt_blad);
}
});
}
}, 'all')
$(document).on('click', '#usuwanie-koszyk, #dodawanie-koszyk, #usuwanie-calkowite ', function(e) {
ajaxSubmitForm2();
e.preventDefault();
});
You Should call e.preventDefault() at the priority to defend the default action on the element in the second request.
$(document).on('click', '#usuwanie-koszyk, #dodawanie-koszyk, #usuwanie-calkowite ', function(e) {
e.preventDefault()
ajaxSubmitForm2()
});
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
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
I've done a web page that has to make the use wait a loooong time before getting the answer.
When the user clicks on "Generate" (complex stuff), i do a slow slideUp() of the main div and immediately after that, I launch my "background" AJAX call:
$('#div-lol-generate-result').slideUp(4000);
$('#div-lol-generate-form').slideUp(3000);
$.ajax({
url: '/long/api/call/that/takes/between/1/and/10/seconds',
data: data,
dataType: 'json',
method: 'POST'
})
.done(function(result) {
console.log('ok :');
console.log(result);
var monp=$('<p />');
if (typeof(result.error)!='undefined') {
for (var i in result.error) {
monp.append(result.error[i]);
monp.append('<br />');
}
} else if (typeof(result.story)!='undefined') {
console.log(result.story.length);
for (var i in result.story) {
monp.append(result.story[i]);
monp.append('<br />');
}
}
monp.last().remove();
$('#div-lol-generate-result').empty().append(monp).slideDown();
});
})
.error(function(result) {
console.log('Erreur :');
console.log(result);
})".
Everything works fine... only when the answer takes longer than the "hide" animation. If the answer is fast, the we can see the content of the maindiv being replaced.
How do you deal with that?
You make sure both the animation and the ajax call has completed before you replace the content
var promise1 = $('#maindiv').slideUp(4000).promise();
var promise2 = $.ajax({
url : '/complexstuff',
data : data,
dataType : 'json',
method : 'POST'
});
$.when.apply($, [promise1, promise2]).done(function(elem, data) {
$('#maindiv').html(data.result).slideDown();
});
This way the ajax call starts right away without having to wait for a callback, and the promises makes sure both have completed before the callback for $.when is called.
Here's my final working code, thanks to adeneo
$(document).ready(function() {
$('#div-lol-generate-result').hide();
var sub=function() { return lol_submit(); };
var lol_submit = function() {
var data=$('#lol-generate-form').serialize();
$('#lol-generate-form :input')
.prop('disabled', 'disabled');
$('#lol-generate')
.unbind('click')
.click(function(e) {
e.preventDefault();
});
$.when(
$('#div-lol-generate-result').slideUp(4000),
$('#div-lol-generate-form').slideUp(3000),
$.ajax({
url: '/lol/json/story',
data: data,
dataType: 'json',
method: 'POST'
})
)
.then(function(a, b, c) {
result=c[0];
var monp=$('<p />');
if (typeof(result.error)!='undefined') {
for (var i in result.error) {
monp.append(result.error[i]);
monp.append('<br />');
}
}
else if (typeof(result.story)!='undefined') {
console.log(result.story.length);
for (var i in result.story) {
monp.append(result.story[i]);
monp.append('<br />');
}
}
monp.last().remove();
$('#div-lol-generate-result')
.empty()
.append(monp)
.slideDown();
}, function(a, b, c) {
/* should never happen
* TODO: hide and all ask refresh
*/
// a=xhr
// b='failure'
// c='Not Found'
})
.always(function(result) {
$('#lol-generate-form :input').removeAttr('disabled');
$('#lol-generate').click(sub);
$('#lol-generate-form-input-summoner-name').focus().select();
$('#div-lol-generate-form').slideDown();
});
return false;
}
$('#lol-generate-form').submit(sub);
$('#lol-generate').click(sub);
});
I have a jQuery script that is a search script but also contains functionality to resize an element to the (screen height - 40px) when the window is resized. However, I want to disable the resizing function when a search (AJAX query) is active. Does anyone know how I can do this?
My current code is:
$(document).ready(function(){
$(window).resize(function(){
if($(window).height()<1200){
$("#a").height($(window).height()-40);
}
});
$("form").submit(function(a){
a.preventDefault();
if($("#i").val().length>0){
$.ajax({
type:"get",
url:"search.php?q="+q,
dataType:"html",
success:function(a){
...
}
})
}
})
})
Use .on() and .off()
$(document).ready(function(){
function started(){
if($(window).height()<1200){
$("#a").height($(window).height()-40);
}
$(window).on("resize.name_space",started);
$("form").submit(function(a){
a.preventDefault();
if($("#i").val().length>0){
$(window).off("resize.name_space");
$.ajax({
type:"get",
url:"search.php?q="+q,
dataType:"html",
success:function(a){
$(window).on("resize.name_space",started); ...
}
})
}
})
})
var loading;
...
if($(window).height()<1200 && !loading){
...
loading = true;
$.ajax({
...
complete: function(){
loading = false;
}.
})
}
})
Try this, it adds a check in whilst the ajax is running and will stop the re-sizing from taking place
$(document).ready(function(){
//Create the variable
var check = false;
$(window).resize(function(){
//Is the ajax currently running? This if statement runs if the answer is no
if (check == false && $(window).height()<1200 ) {
$("#a").height($(window).height()-40);
}
});
$("form").submit(function(a){
a.preventDefault();
//Set the variable to true, this stops the resizing above ^^
check = true;
if($("#i").val().length>0){
$.ajax({
type:"get",
url:"search.php?q="+q,
dataType:"html",
success:function(a){
...
},
complete: function() {
//Set back to off once the ajax has finished
check = false;
}
})
}
})
})