I am trying to update a feed when a user gets to the bottom of the page and add the new content. It for some reason is not returning the content at all.
Here is my jquery/javascript
$(window).scroll(function(){
if($(window).scrollTop() + $(window).height() > $(document).height() - 650){
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
document.getElementById("thumbs").innerHTML = xmlhttp.responseText;
}
else {
document.getElementById("thumbs").innerHTML = "Error Occurred.";
}
}
xmlhttp.open("GET", "include/update-gamer-feed-curl.php", true);
xmlhttp.send();
}
});
The php file already works because it gets the first ten items already and I am just calling it again to get the data to reload into the screen so I can prepare to append what is needed once I get more elements.
It is telling me the xmlhttp is depreciated. I have also tried using
$.ajax({url: "include/update-gamer-feed-curl.php", success: function(result)
{
$("#thumbs").append(result);
}
but this doesnt work either. I know it is in this because if I put the string test in the append element where result is it appends the test string.
clearTimeout($.data(this, 'scrollTimer'));
$.data(this, 'scrollTimer', setTimeout(function() {
if($(window).scrollTop() + $(window).height() > $(document).height() - 650){
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", "/echo/json/", true);
xmlhttp.send();
xmlhttp.onreadystatechange = function() {
if(xmlhttp.readyState == 4){
if (xmlhttp.status == 200) {
document.getElementById("thumbs").innerHTML = xmlhttp.responseText;
}
else{
console.log("Error: rState=" + xmlhttp.readyState + ", status=" + xmlhttp.status);
}
}
}
}
}, 250));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
It seems the request is repeated too much. A timer of 250ms helped some, but still, the innerHTML is overwritten too fast. So I also change so that innerHTML is written to if success, but console gets the error. readyState 1,2,3 is repeated many many times when scrolling, and causes many errors. Avoided by checking readtState == 4 first.
Here are the description of the readystates
0=The current object is not initialized (the open method has not been
called yet).
1=The request is opened, but the send method has not been called yet.
2=The request is sent but no data has been received yet.
3=A part of the data has been received, but it is not yet available.
4=All data is available.
Make sure readyState == 4 first, and then checks the status. And by moving open and send above onreadystatechange, you avoid readystate errors 0 and 1.
Related
I have the following generic Ajax response writer which I recently added some logic to, in order to dynamically parse the results for script objects, and run them when I find them using jQuery.globalEval().
Here is the code:
//Generic Results Writter method for Ajax Calls
function writeAjaxResponse(targetId, response) {
document.getElementById(targetId).innerHTML = response;
try {
var dom = $j(response);
dom.find('script').each( function(){
$j.globalEval(this.text || this.textContent || this.innerHTML || '');
});
} catch (e) {
console.error("Error parsing for script reloads: "+e);
}
}
This solution works very nicely the first time its called. However writeAjaxResponse(targetId, response); is called each time a user loads some dynamic Ajax content. And unfortunately after the first time, the scripts are no longer loaded. To be clear, after the server side generated page is loaded, there are numerous links on the page which the users may click, which invoke this handler for the Ajax response.
No error occurs, and no console.error() is written.. The Ajax data loads as normal, its just that the scripts in the response are no longer loaded.
In debugging, $j.globalEval is still getting called and this.text still has the script content in it, and the data looks correct, but still no joy.
Any light someone could shed on this would be very much appreciated!
Adding main ajax call for GET for reference:
function doAjaxGet(targetId, getUrl, handler) {`
var xmlhttp;
if (window.XMLHttpRequest) {
// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();
} else {
// code for IE6, IE5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
try {
handler(targetId, xmlhttp.response);
}
catch (err) {
alert("Failed calling handler, detail: " + err + " Got responseText: " + xmlhttp.responseText);
}
}
}
xmlhttp.open("GET", getUrl, true);
xmlhttp.send(null);
}
I am ganging my head against the wall for 3 hours now. I have this code:
function showpctask() {
if (window.XMLHttpRequest) {
// code for IE7+, Firefox, Chrome, Opera, Safari
var xmlhttp = new XMLHttpRequest();
} else {
// code for IE6, IE5
var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
document.getElementById("pcactivitytask").innerHTML = xmlhttp.responseText;
}
};
xmlhttp.open("GET","showpctask.php"+,true);
xmlhttp.send();
}
that opens up a php file inside a div (id = pcactivitytask). That php file builds a 'select'
I also have this function right here:
function setpctaskwidth() {
var maxtaskwidth = 0;
$("div .pcactivitytask").each(function(){
c_width = parseInt($(this).width());
if (c_width > maxtaskwidth) {
maxtaskwidth = c_width;
}
});
alert (maxtaskwidth);
}
that will show me the max width of all elements with the the class of "pcactivitytask". Yes, the select created by the previous script has that class. If I call both these function it will NOT include the width of the NEWLY created select..... I need to run it AGAIN 'manuall'. I need my script to "onclick" BOTH build the NEW select AND include it in finding the max width by the second script. Thank you.
XMLhttprequest works asynchronously, meaning it does not happen in order.
that is why you have the xmlhttp.onreadystatechange callback function, that only runs once the request is finished
you do not specify how you call these two functions but I would expect to see the call to setpctaskwidth() inside the onreadystatechange function like this:
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
document.getElementById("pcactivitytask").innerHTML = xmlhttp.responseText;
setpctaskwidth();
}
};
be advised that if the response includes images or other external resources (fonts etc) that don't already exist in the page you might get a different size than the actual final size (it will measure the size before the image is loaded)
i have a span with the same value..
echo "<span id='msgNotif1' class='badge' style='position:relative;right:5px;bottom:10px;'>".$number."</span>";
where $number have a value..
and my js code is..
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var val = xmlhttp.responseText;
//alert(val);
document.getElementById("msgNotif1").innerHTML = val;
//document.getElementById("msgNotif2").innerHTML = val;
alert(val);
//document.getElementById("msgNotif3").innerHTML = xmlhttp.responseText;
}
}
xmlhttp.open("GET", "some page", true);
xmlhttp.send();
the problem is the value still remains and do not change,
trying to uncomment the first alert shows an alert with the right value, but when i try to comment it the second alert never executed, giving me an idea that the document.getelementbyid().innerhtml is the one that is not working, been with this for a few hours,
any help will be appreciated.
thanks in advance
Your error message Cannot set property 'innerHTML' of null" means that:
document.getElementById("msgNotif1")
is returning null. That can happen for several possible reasons:
There is no element in your page with id="msgNotif1".
You are calling this code before your document has finished loading and thus the element with id="msgNotif1" has not yet loaded. This can commonly happen if you execute your code in the <head> section of the document rather than at the very end of <body> or in response to the DOMContentLoaded event.
Your content is dynamically loaded (not in the original page HTML) and you are calling document.getElementById("msgNotif1") before your dynamic content has been loaded.
You have some HTML errors which are preventing the proper parsing of your HTML that contains the element with id="msgNotif1".
For a general purpose description of how to run Javascript after the current page has been loaded without using a framework like jQuery, see this answer: pure JavaScript equivalent to jQuery's $.ready() how to call a function when the page/dom is ready for it
You are receiving this error in your console because it doesn't exist at the time your script is running. This can be caused if the element hasn't been loaded when your script is running, if your IDs aren't the same, or if the element doesn't exist in your html. If you are referencing the element before it loads, add a function that executes when your page loads.
You can use JQuery
$(document).ready(function(){
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var val = xmlhttp.responseText;
//alert(val);
document.getElementById("msgNotif1").innerHTML = val;
//document.getElementById("msgNotif2").innerHTML = val;
alert(val);
//document.getElementById("msgNotif3").innerHTML = xmlhttp.responseText;
}
}
xmlhttp.open("GET", "some page", true);
xmlhttp.send();
});
or with pure Javascript to create the event.
window.onload = function(){
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var val = xmlhttp.responseText;
//alert(val);
document.getElementById("msgNotif1").innerHTML = val;
//document.getElementById("msgNotif2").innerHTML = val;
alert(val);
//document.getElementById("msgNotif3").innerHTML = xmlhttp.responseText;
}
}
xmlhttp.open("GET", "some page", true);
xmlhttp.send();
};
Valid points have been brought up in that doing Ajax requests with pure Javascript takes much more code than if you were to use JQuery. This is the reason why I (and many others) use JQuery for all the Ajax requests performed. JQuery has many methods for Ajax that will save a lot of time and code and in the long run will reduce your file size by a few bytes since, with JQuery, the code is reused.
I understand that jQuery will not run when the DOM content is being loaded via AJAX. But I'm confused as to the reason why. My understanding was that the DOM elements didn't exist at the time the jQuery was initiated therefore it won't find the correct IDs or classes.
But I have a situation where the jQuery is only called AFTER all the content has been loaded via AJAX. yet it still does not work.
Here is my code. I am trying to get the function decorateGains() to run after AJAX completes.
loadData('7-days'); // Runs the default AJAX for 7 days
function loadData(type){
var xmlhttp;
if (window.XMLHttpRequest){xmlhttp=new XMLHttpRequest();}
else{xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");}
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200){document.getElementById("home-table").innerHTML=xmlhttp.responseText;}
}
xmlhttp.open("GET","actions/get-data-"+type+".php",true);
xmlhttp.send();
decorateGains();
}
You can see that I am including a call to the function decorateGains() right at the end of the loadData() function.
The decorateGains() function does run, as I can see my console message. However it does not do the task that it should.
function decorateGains() {
console.log('here');
$(".gains").each(function() {
var num = +($(this).text());
if (num > 0) {
console.log('here');
$(this).addClass("positive");
}
if (num < 0) {
console.log('here');
$(this).addClass("negative");
}
});
}
(The script searches for all elements with a class of .gains and adds a new class of positive or negative depending on the content of the element. Essentially it decorates the .gains element to be red or green depending on whether the number is negative or positive).
This is because the AJAX call is asynchronous. The request has not been completed (and therefore the new content has not been appended to the DOM) when you call your decorateGains() function. You need to place the call to the function inside the onreadystatechange handler, after setting the innerHTML:
loadData('7-days'); // Runs the default AJAX for 7 days
function loadData(type) {
var xmlhttp;
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
} else {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
document.getElementById("home-table").innerHTML = xmlhttp.responseText;
decorateGains(); // <-- move this in here
}
}
xmlhttp.open("GET", "actions/get-data-" + type + ".php", true);
xmlhttp.send();
}
I'm trying to have a div refresh after a callback using ajax functions. Basically, I want /includes/view_game/achievements.inc.php to be reloaded in the div #achievements_tab. The callback (I didn't include it in codes below) works well and triggers the AchievementRefresh function found below (the opacity of the div changes to 0.5, but it remains like this and the refresh is not made).
Those two functions are used for another similar ajax refresh on my site that works well. So I tried to modify the code, but since it's for a slightly different purpose, maybe I have the wrong approach.
function AjaxPost(url, success_function) {
xmlHttp = GetXmlHttpObject();
if (xmlHttp == null) {
alert("Your browser doesn't support AJAX. You should upgrade it!")
return
}
xmlHttp.onreadystatechange = success_function;
xmlHttp.open("POST", url, true);
xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
}
This AjaxPost function is used in the other function below:
function AchievementRefresh() {
div('achievements_tab').style.opacity = 0.5;
div('highscore_pages').innerHTML = '<img src="'+site_url+'/images/loader.gif" />';
AjaxPost(site_url+"/includes/view_game/achievements.inc.php?", '',
function () {
div('achievements_tab').innerHTML = xmlHttp.responseText;
div('achievements_tab').style.opacity = 1;
}
)
}
Use load
$('#achievements_tab').load('/includes/view_game/achievements.inc.php');
See: http://api.jquery.com/load/
Edit
E.g.
function AchievementRefresh() {
$('#achievements_tab').css('opacity', 0.5);
$('#highscore_pages').html('<img src="'+site_url+'/images/loader.gif" />');
$('#achievements_tab').load('/includes/view_game/achievements.inc.php')
.success(function() {
$('#achievements_tab').css('opacity', 1);
});
}
Try this.
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4) {
if(xmlhttp.status == 200) {
div('achievements_tab').innerHTML = xmlHttp.responseText;
div('achievements_tab').style.opacity = 1;
}
}
};`
Name and id is example.
Also, some changes:
AjaxPost(site_url+"/includes/view_game/achievements.inc.php");
var params= 'name'+encodeURIComponent(name)+'&id='+encodeURIComponent(id)
Parameters shouldn't be in URL.
xmlhttp.send(params);