Prevent scroll reset in AJAX - javascript

I have a div container that gets its content modified every 3 seconds by a javascript function. The function is initially called by the onload event of the body tag.
function showNow(){
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) {
document.getElementById("txtHint").innerHTML = xmlhttp.responseText;
}
};
xmlhttp.open("GET", "tab.php", true);
xmlhttp.send();
setTimeout(showNow, 3000);
}
The content is being refreshed every 3 seconds. The only problem is that the scroll position is being reset and hence my page jumps back to beginning. This is affecting the usability highly.
Can anyone please suggest a solution?

I'm french so forgive me for my bad English
I had the same thing on my page : when I clicked on the link, the XHR request reseted my scroll on full top. I've found my mistake...a very stupid one...
Check your HTML, if your "onClick" is in a <a> tag, check you've not written <a href="#" onClick="myFunction()">...
That was my mistake, and just <a onClick="myFunction()"> don't reset the scroll x)
Hope I've helped you

You can use window.scrollTo(x, y) to set the position of scroll, for sample:
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("txtHint").innerHTML=xmlhttp.responseText;
window.scrollTo(0, 0); //stay on the top
}

Before the innerHTML is set, you could get the txtHint element's scrollTop property. Then, after the text is added, set that variable to scrollTop again.
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
var scroll = document.body.scrollTop;
document.getElementById("txtHint").innerHTML=xmlhttp.responseText;
document.body.scrollTop = scroll;
}

try adding
return false;
at end of the ajax request

Not sure this was answered completely.
I had the same problem, trying all solutions above did not solve it. What i found was that refreshing the innerHTML actually made the Scrollbar disappear for a very short period of time (because the entire page becomes a lot smaller in height as the content gets refreshed), subsequently when content reappears (and the Scrollbar) the browser has no way of knowing where he was before the call and hence scrolls all the way up.
My own solution was very simple and does not involve catching events etc..., I added a column which I filled with a spacer.gif the height of the div I intend to refresh. That way the entire page layout itself never actually gets distorted, the Scrollbar never disappear even a short period of time.
<table width="30%" border="0" align="center" cellpadding="0" cellspacing="0">
<tr>
<td>
<img src="/images/spacer.gif" width="0" height="170"/> <-- adding the extra column to keep the height always the same.
</td>
<td>
<div id="content">
<script>loadnewusermenu()</script> <-- content getting refreshed
</div>
</td>
</tr>
</table>
Hope it makes sense.
DjYoy

Related

Scroll to bottom of div after changing contents using Javascript

For some reason the methods to scroll to bottom of div are not working for me after refreshing its contents using Ajax.
I think the issue has something to do with how the DOM works--eg when it makes its changes, however, I don't know enough about javascript or the DOM to really understand how that would interfere with scrolling to bottom.
So I think the issue is when and how to call the methods rather than the methods themselves. Can anyone suggest a way to scroll to bottom after the refresh of div?
Methods to scroll to bottom I am trying:
Method 1:
var element = document.getElementById("chatBox");
element.scrollTop = element.scrollHeight;
Method 2:
document.getElementById('chatBox').scrollIntoView({ behavior: 'smooth', block: 'end' });
Method that refreshes div:
function refreshDiv() {
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)
{
alert("got 200");
document.getElementById("chatBox").innerHTML=xmlhttp.responseText;
alert("will now try to update Scroll");
//FOLLOWING HAS NO EFFECT POSSIBLY BECAUSE DOM HAS NOT YET RETURNED RESULTS
document.getElementById('chatBox').scrollIntoView({ behavior: 'smooth', block: 'end' });
}
}
xmlhttp.open("GET","refreshDiv.php,true);
xmlhttp.send();
return;
//THIS ALSO HAS NO EFFECT POSSIBLY AS IT IS AFTER RETURN
document.getElementById('chatBox').scrollIntoView({ behavior: 'smooth', block: 'end' });
}
What is the proper place to call scroll to bottom after refreshing div?
use this script to scroll to bottom of div
var objDiv = document.getElementById("your_div");
objDiv.scrollTop = objDiv.scrollHeight;

Refresh browser / link and still "hit" javascript-function

I have created a list through normal html which have this link to a "details" page. URL: index.php?page=userDetails&usersId=10. This may be changed if I get the correct solution for my challenge :)
At the "details page" I have made a dropdown which basicly insert (GET) a id to PHP and PHP generates content.
The dropdown looks like this
<select name="users" onchange="showUser(this.value)" class="selectpicker">
<option data-tokens="10" value="10">user-10</option>
<option data-tokens="41" value="41">user-41</option>
<option data-tokens="9" value="9">user-9</option>
<option data-tokens="8" value="8">User-8</option>
</select>
<!-- This is where PHP-content will be printed..... -->
<div id=\"txtHint\"><b>Person info will be listed here...</b></div>
Javascript looks like this (function showUser)
function showUser(
{
if(str == "")
{
document.getElementById("txtHint").innerHTML = "";
return;
}
else
{
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)
{
document.getElementById("txtHint").innerHTML = xmlhttp.responseText;
}
};
xmlhttp.open("GET","logic/do.php?action=ajaxReceive&input="+str,true);
xmlhttp.send();
}
}
The Id (from database) is received as $_GET[input] and everything actually works fine, and I can print ID at the moment.
My problem is 2 things:
1) When I refresh browser the ID is not stored. I suppose this can be done by cookie or session, but how do I keep the ID and "insert" it into the function so I stay on user 8, 10, 14 or what ever user I was looking at?
2) The same problem is the actual link where I link from one page to a whole other page. This is neccesary since I am no super-expert so I am reluctant to run everything as pure javascript/jQuery. I fix things best at PHP-side so sometimes I need a little breath :)
I hope you understand my probably rather basic problem...
I am looking forward to some input concerning my little challenge :)
Cheers Nikolaj
You could use window.onbeforeunload to execute a script/function before a page is unloaded. You could send the userID to your PHP script and let that store the userID.
HTML
<element onbeforeunload="yourFunction()">
Reference: http://www.w3schools.com/tags/ev_onbeforeunload.asp
Javascript
window.onbeforeunload = function() { /* Your function send to e.g. PHP here */ }
jQuery
$(window).on('beforeunload', function(){ /* Your function send to e.g. PHP here */ });

Getting "Cannot read property 'innerHTML' of null" but I have that id initiated

I have read on here that usually this problem comes up when the specific div isn't loaded yet or just isn't there. I have this code looping so even if it wasn't fully loaded the first time it will be by the next iteration. Also I for sure have a div with the id participants.
<div id="participants">
<div class="sectionhead wow bounceInUp" data-wow-duration="2s">
<span class="bigicon icon-user"></span>
<h3>Participants<h3>
<h4>Check out who has signed up already!</h4>
<hr class="separetor">
<div id"test" onload="updateVariables()">
</div>
</div>
</div>
<script>
setInterval(function(){
updateVariables();
},4000);
updateVariables = function() {
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)
{
var info = xmlhttp.responseText;
console.log(info);
var out = info.split("\n");
console.log(out[1]);
var outLen = out.length;
for(x = 0; x < outLen; x++){
document.getElementById("test").innerHTML += out[x];
document.getElementById("test").innerHTML += "<br>";
}
}
}
xmlhttp.open("GET","../php/tour.txt",true);
xmlhttp.send();
}
</script>
That's pretty simple. In your real page you have a simple typo mistake. Instead of
<div id"test" onload="updateVariables()">
You should have
<div id="test" onload="updateVariables()">
EDIT: the easiest way to locate such errors on your own is debugging. I consider at the moment that Chrome dev tools is the best option, however you can use dev tools F12 of any browser, since this problem is simple. I will demonstrate an example on Chrome.
In console you will see errors happening. To the right of the error you can see a link to the place in sources where it happens.
A click on (index):247 takes you there in debugger window. Where you can place a breakpoint. Once you hit the breakpoint you have very powerful tools provided by Chrome. You can add variables to watch list, you can execute any code in console, you can trace the DOM (Elements tab) at current moment.
The typo of interest can be easily located by copying the code you suppose is working to console document.getElementById("test").
Now you start getting puzzled what the heck it returns null instead of a div. You go to elements tab and search for test by Ctrl+F. You find the text in html however after roaming around with beer you notice that the id is actually not defined due to wrong syntax

AJAX including pages without loading

I'm having a challenge:
How do I reload a <div> on page using AJAX, without loading bars and without disappearing while the content is loaded.
I want to keep previously generated content as long as new content is loaded.
This is my script but when loading the content in a loop it blinks:
<script type="text/javascript">
function showCargo_34(urlparms)
{
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttpshowCargo_34=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttpshowCargo_34=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttpshowCargo_34.onreadystatechange=function()
{
if (xmlhttpshowCargo_34.readyState==4 && xmlhttpshowCargo_34.status==200)
{
document.getElementById("Cargo_34").innerHTML=xmlhttpshowCargo_34.responseText;
}
}
xmlhttpshowCargo_34.open("GET","modules/desktop/desktop/script_cargo.php?"+urlparms,true); // modules/catalogitem/script_categorylist.php?"+urlparms
xmlhttpshowCargo_34.send();
};
</script>
<div id="Cargo_34"></div>
<script>
function repeat_Cargo_34() {
showCargo_34('baseid=1&moduleid=10&gridmoduleid=133&speed=180&x=3&y=4');
setTimeout( repeat_Cargo_34, 20000);
};
repeat_Cargo_34();
</script>
I would use jquery for ajax. It is way faster and simplier.
Simple way
$("#element_id").load("http://url.com");
More advanced way you can find here
Also you were talking about keeping previoius content. Well just use += for innerHTML:
document.getElementById("Cargo_34").innerHTML += xmlhttpshowCargo_34.responseText;
If you dont want to use jquery I would suggest making a second ajax function and make the current function change an invisible div where you would echo the following line when the loading and changing is finished.
//Echo this once all data has been loaded and changed.
//$newurlPalms is what you would have echoed normally but in a urlpalm.
echo "<style onload='showCargo2($newurlpalms)'></style>";
//so make this only load and save all the data and then echo above line in
//a hidden div
function showcargo(urlpalms){ajaxcode}
//make this show the data in the right div.
function showcargo2(urlpalms){ajaxdoce}
like this it wont remove the data, and once the loading is complete the echo will cause the second function to run automatically which than is able to instantly shows the data.
Use jQuery's AJAX, it's more easy. Look at load() function and for example setInterval. e.g.:
setInterval(function(){ $('#div').load('file.html'); }, 5000}
in every 5 seconds it will load file.html to <div id="id">
That situation doesn't exists.
Explanation:
Standard html request call as it is in my question do not put content by innerHTML while is loaded. That means while content is loaded it will be displayed as it is until content is completed in JSON and ajax call function is done.
Error was in another part of code.

Refresh only one div with AJAX

I want to dynamically reload only one div in my page every five seconds. But in my response I get the content of the whole page... How can I get only the content of the specified div ?
<script>
function ajaxrefresh()
{
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)
{
//Here i want only the content for the div from the response
document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
}
else
{
//alert("state: "+xmlhttp.readyState)
//alert("status: "+xmlhttp.status)
}
}
xmlhttp.open("GET","http://${localHostAddress}:8080/adress",true);
xmlhttp.send();
var t=setTimeout(ajaxrefresh,5000);
}
window.load = ajaxrefresh();
</script>
Someone has already ask something like this on SO. Best voted-up is to create an invisible div in your page, and fill it with the AJAX response to be able to get back element you need with hiddenDiv.getElementById("myDiv").
As you can not use Jquery, I think your best bet is in response to ajax call return only the div contents from server side. this way your response size will be smaller and hence faster too...
if you can not change the response of request use below code
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
//Here i want only the content for the div from the response
var mydiv= document.getElementById("myDiv");
var doc=document.createElement("div");
doc.innerHTML=xmlhttp.responseText;
document.body.appendChild(doc); // Note append temp to document
mydiv.innerHTML=doc.getElementById("theDivYouWant")
.innerHTML;
document.body.removeChild(doc);// Note remove temp from document
May be you will get some idea from below script:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.0/jquery.min.js"></script>
<script type="text/javascript">
var auto_div_refresh = setInterval(function(){
$('#load_data').load('fb_count.php').fadeIn("slow");
}, 10000); // refresh every 10000 milliseconds
</script>
You could try something like this:
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
//Here i want only the content for the div from the response
var doc=document.createElement("div");
doc.innerHTML=xmlhttp.responseText;
document.getElementById("myDiv").innerHTML=doc.getElementsByTagName("div")[5]
.innerHTML
Here 5 is just a random number, if the div is always fixed you can use the number that the div is located and if it's not you need to loop through the divs and find the one you're looking for (maybe based on id).

Categories

Resources