JS seems to stay in DOM on Ajax reloaded pages - javascript

OK this is an odd error, as it's the first ajax page without any complete reloads I'm creating it's an error I never had to face before... and even the Internet doesn't help me - as it doesn't seem to be an usual problem.
Let's get to the Problem step by step:
I have a page where the Ajax request is triggered by a function which simplified looks like this:
$("a[rel='tab']").live('click',function(e) {
pageurl = $(this).attr('href');
$.ajax({url:pageurl+'?rel=tab',success: function(data){
$('#content').html(data);
}});
if(pageurl!=window.location){
window.history.pushState({path:pageurl},'',pageurl);
}
e.preventDefault();
return false;
});
This is parsed by the PHP File and if the property is set the design won't be loaded but instead just the file itself gets loaded - easy hu?
OK, now the problem itself - it was obvious that the page became slower with the time but I didn't really bother at first as I thought it was some mistake in the designs javascripts - but it wasn't.
So I took a look at the firebug and what I've seen explained a lot -> The Requests stack up with every new page! Of course that would lead into an overkill... Well at first I thought it were just the "setInterval"'s and got a workaround running which resets them on each reload.
But that wasn't the only case they also seem to stack up in "scripts" as I don't think that's a plain history as just the reloaded scripts show up more than once!
Any hints in the right would be really helpfull as I am pretty much stuck here!

OK as it seems the issue is just related to the setInterval after all - After trying around for a while I came to the conclusion that this was the main problem, and it was just some kind of a loop in firebug itself.
However maybe someone gets stuck on the same issue so the solution is pretty much this way:
You have to:
1. Create an array where to store your Intervals
2. call your setIntervals this way
3. Reset them on each "new window"
var intervalArr = new Array();
function killIntervals(){
while(intervalArr.length > 0)
clearInterval(intervalArr.pop());
};
These are the array and the function
So these should be added in your AJAX Request function:
killIntervals();
intervalArr.push(setInterval (yourintervalfunction, 5000));
I hope this will come in handy for someone.

Related

window.location failing on Android Browser

I've run into this and while the internet seems to be full of answers and discussions on this issue nothing seems to be working.
I'm building a mobile web page where I run a jQuery JavaScript function off a submit button, it calls an AJAX query comes back does it's business and then I get to the dreaded:
window.location = "url";
Now I've personally tried every version of this I've seen deprecated or not:
window.location.href =
window.location.replace() --I know this is achieving something different
window.location.assign()
window.navigate()
document.location =
document.location.href =
document.location.replace()
document.location.assign()
In each instance my Android Browser version 5.5 just stops at the point it is supposed to move through to the next url. I'm using full urls from the "http://..." so not missing that.
In contrast Android Chrome is moving through like a champ. Same Phone. Have I missed some crucially important piece to the puzzle here to get this moving on Android Browser?
My searches online seem to only say that:
window.location.href = '';
...is the most technically correct, right now I'd settle for working rather than technically correct.
If anyone has any ideas or at least some avenues to go off and explore I'll get all over that first thing in the morning.
Thanks for any help you can offer.
I found that this was a result of a faulty AJAX call. The weird thing that was throwing me off was that some items would work within the call (even though the call failed) and some would not.
The answer in my own case was to fix the PHP that the AJAX was calling and then changing pages worked as I would expect it to.

Modernizr.load callback executing before loaded script

At a certain point on my javascript I have the following (using Modernizr 2.6.2):
Modernizr.load([{
load: '/path/file.js',
complete: function () {
//do stuff
}
}]);
It works great most of the time, except on IE8, about 1 time out of 3 it executes the callback first then the script being loaded. I am adding a break point on the callback and another inside file.js. Both scripts are being executed, just swapping the order at times.
I tried to isolate and reproduce the error, but I couldn't. It works fine every time when I have only this code on the page (using the exact same Modernizr file). For that reason I believe something else on my project could be interfering, but I have no clue on what to look next along the 10000 (really!) lines of js. Has anyone experienced anything similar or has any idea on what could cause this sort of behaviour?
I am not looking for a workaround for this specific case. This is one of many instances where I really would like to keep as is.
EDIT 1 - NEW INFO:
Using the network panel, I can see that two requests are being done (which is expected), but the first request always returns blank. The second request brings up the correct content. That works fine when the callback is executed after both requests are complete, but sometimes the callback is executed between the first (empty) and second request. That is when it crashes!
EDIT 2 - NEW INFO: Ok seems like I can reproduce it now. To be 100% sure on my assumptions I would have to know the javascript engine in deep, which I don't, so I could be dead wrong, but here is what I found:
Request file1.js and file2.js. If file2 finishes loading while the engine is busy executing file1's callback, file2 execution goes somewhere at the end of the queue, which means after file2's callback.
Try waiting for all of the files to load before firing the callbacks. Expand on the pattern below to suit your needs.
Modernizr.load([{
load: '/path/file.js',
complete: function () {
filesLoaded++;
checkStatus();
}
}]);
function checkStatus(){
if(filesLoaded == 2){
//do stuff
}else{
setTimeout(checkStatus, 100);
}
}
After doing some research on the subject, I think this issue may be more common than it seems at first, but has been overlooked because it is context dependent, and has different ways of being described:
Modernizr load [A, B] seems to execute B before A, how is this possible?
YepNopeJS: callback triggered before tiny JS file is fully loaded
https://github.com/SlexAxton/yepnope.js/issues/195
After reading this nice article (referenced on yepnope page), about the inconsistencies experienced on IE, I came up with a fix, which has been sent to yepnope maintainers via github:
http://github.com/SlexAxton/yepnope.js/pull/196
I don't know whether it is going to be accepted or not, but it solved my problem.
As editing a library may not always be a good idea, I would suggest the following workaround:
//instead of
complete:function(){
doStuff()
}
//try
complete:function(){
setTimeout(doStuff, 0);
}

Jquery load is working till I restart Wampserver, and then not anymore

I try to have some content loaded on Wordpress thanks to Jquery .load(). Sometimes, when my code is OK, it's not working anymore the day after...
I'm trying to narrow the causes. First I thought it was a syntax problem or a single/double quote mix up, but since it worked once, there is no reason syntax or error is involved.
I thought about bad cache settings but shift+F5 won't break my working code.
And now I just tried, with a perfectly working code, to close and restart WAMPserver. And Bingo, when I restart the server it's impossible to get my load function to work (the same from 1 min before...) !
EDIT: I just replaced the code (below) with the one I'm using now
$(document).ready(function(){
$.ajaxSetup({cache:false});
$("#portfolio-list li:not(#DrawerContainer)").click(function(){
var post_link = $(this)
//.parentsUntil(".ProjectWrap")
//.parent()
.find('.mosaic-backdrop')
.attr("href");
console.debug(post_link); //to get post_link info in the console
$('#DrawerContainer').remove(); // remove existing, if any
$('<li/>').attr('id', 'DrawerContainer').css({display: 'none'}).data('citem', this).html("loading...").load(post_link + " #container > * ").insertAfter(LastInRow).slideDown(500);
return false;
});
});
When the function isn't working, I try to remove the part .load(post_link + " #container > * "); and replace it with the part just after (a complete url). Usually it works and at least I can continue styling my page, but I have to fix the problem.
What can cause this weird behavior? Can WAMPserver rewrite something while closing?
Is there an option I could check?
Although this was solved in the question's comments, here is an answer for anybody skimming the page.
There is an issue with running ajax requests across different domains. Your WAMPserver does not like it and will stop it unless you tell it otherwise. Although you are working locally, WAMPserver thinks http://localhost/ is different to http://127.0.0.1/.
To get around this, in the file that handles your ajax add this:
<?php header('Access-Control-Allow-Origin: *'); ?>
Note, you can change the * for a URL too (e.g. http://127.0.0.1/
If that does not work, you may have to change settings on your server.

Supporting AJAX history button without going crazy

I used jQuery Address several times to support the back button in small asynchronous applications.
When all the AJAX requests do the same thing (that is, requesting a page asynchronously and replace an HTML element with the request) the implementation can be easy.
When the AJAX requests might do different things, let's say open an overlay in one case and change the content of the page entire page in another case, things become messy.
I ended up with some really crappy code for the fact that I had to go through a lot of if statements to analyze the hash value (#/somepage/someotherpage).
I always repeated to myself: there has to be a better way to do this.
Has anybody went through the same problem and can suggest a solution?
If not, check out my idea and tell me what you think.
My idea is to create an object which emulates the window.history object, but only for AJAX history, let's call it "ajaxhistory".
Each time a page is requested asynchronously something like this happens:
ajaxhistory[i] = {
url: 'here the url',
type: 'overlay'
otherusefulinfo: 'whatever'
}
i++
So, for example:
if(moving back or forward){
if(currenturl == ajaxhistory[i-1].url){
// i'm going back
// i'm able to know what type of action i should take thanks to
// ajaxhistory[i-1].type and ajaxhistory[i-1].otherusefulinfo
}
}
I like this idea because it would make my code much easier to read, mantain and change.
Suppose then I want to add new functionality... I can add a new type and I work with that, while normally I should edit a lot of crappy if statements.
What do you think? Would there be problems from a performance point of view?
Check out this work by Ben Alman
http://benalman.com/projects/jquery-bbq-plugin/
He has a plugin to help support back button.
Hope this is useful.
Bob
You can use html5 feature:
window.history.pushState({type: 'overlay'}, title, url), where first param is JS object.
You can access this object like that:
window.onpopstate = function(event) {
alert( event.state.overlay);
}
For more information, check https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history

jquery script is using to much memory

I have the code below on a social network site, it loads a file that shows users new notification messages if they exist.
Problem is when I leave the page open for a while, it eventually consumes too much memory on my PC and starts to make firefox non-responsive and throws an error message saying that memory is getting low and asking if I should abort the script or something along those line.
Is there a way to do what I have it doing but without using up so much memory over time?
<script type='text/javascript'>
$(document).ready(function(){
var updatenotification = function(){
$('#notificationcontainer')
.load('http://localhost/member/beta_new/notifications.inc.php')
.fadeIn("slow");
};
var auto_refresh = setInterval(function(){updatenotification();}, 60000);
updatenotification();
});
</script>
What exactly do you return. I'll assume it is a large ish dom fragment. You could change the code to just return a small json string, check if there is a valid new notification and then write some markup into the div rather than reloading it each time regardless if there are new notifications. Can you maybe show the markup that you are returning.
I am making a few too many assumptions without knowing exactly what your returning. If it is just a tiny html fragement I cant really see the issue. The script looks ok and should not be causing the issues you speak about.
Also remember that firebug does have big issues at the moment. There are some pretty nasty leaky bugs that cause the memory warning dialog when browsing heavyish ajax/js sites like StackOverflow, Netvibes. Your average user (I assume!) will not have firebug so will not see anything

Categories