I've got a chat function in my website for two users to chat with each other, and I'm using JavaScript, AJAX, and PHP for it.
At the moment, it won't refresh the chat area automatically unless I submit a reply to the chat or refresh the page. I can't figure out why.
JavaScript Function
function checkReply(threadid) {
// XMLHttpRequest
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
document.getElementById("chatwrap").innerHTML = xmlhttp.responseText;
setInterval(checkReply(threadid), 10000);
}
}
xmlhttp.open("GET","inc/chatreply.php?chatid="+ threadid,true);
xmlhttp.send();
}
The event handler is on the <div> the responseText will end up in:
<div id="chatwrap" onload="checkReply('.$threadid.')"></div>
$threadid is a GET variable set at the top of the page:
$threadid = (int)$_GET['chatid'];
UPDATE
Seeing that you were in a PHP state already, the syntax was correct.
The problem is that the div doesn't possess an onload event. You'll have to attach it to the body tag, or include a script in the head or below the div, as it will only execute after the div has been rendered.
You're not including the PHP variable correctly. At the moment you are passing the string .$threadid. to the checkReply function. You will have to drop into PHP mode again before using this syntax by using the delimiters <?php & ?>.
<div id="chatwrap" onload="checkReply(<?php echo $threadid; ?>)"></div>
This should work better.
Related
I have developed a very simple Chome extension that exposes a single toolbar button. When the button is clicked, the page content is POSTed to the server using XMLHttpRequest and then the innerHtml of the <html> element is replaced by the new content returned from the server.
For some reason this prevents <select> elements from expanding. I have verified this by disabling the extension which makes then work again.
Any ideas why this might be happening and how to fix it? The code is below for reference:
chrome.extension.onMessage.addListener(
function (request, sender, sendResponse) {
if (request.msg == "get_content") {
xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4) {
if (xmlhttp.status == 200) {
document.getElementsByTagName('html')[0].innerHTML =
xmlhttp.responseText;
} else {
alert('Cannot reach russiangram.com');
}
}
}
xmlhttp.open("POST", "https://russiangram.com/translate/Default.aspx", true);
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlhttp.send(document.getElementsByTagName('html')[0].innerHTML);
sendResponse({ data: 'success' });
}
});
At a guess I would say where you are replacing the contents of the documents HTML tag that you are possibly also replacing any associated JS/CSS references that were originally on that page as well.
Maybe as a test instead of replacing the contents of the HTML tag, add a new DIV element or something to the page and target that instead. That should hopefully allow you see whether or not the select functionality still works.
In the website I am working on, the content is loaded with Ajax, along with any JavaScript included. I am doing this because all the pages are of the same layout, but only the content is the different.
The problem is when a "content" has JavaScript in it, I was afraid the script will continue executing even after new content has been loaded. So I made this test to make sure.
First a main page that will load 2 other pages :
<script src="scripts/jquery.min.js"></script>
<script>
function loadPage1(){
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4 && xhttp.status == 200) {
response = xhttp.responseText;
$("#content").remove();
$("#mainContent").append(response);
}
};
xhttp.open("GET", "page1.html", true);
xhttp.send();
}
function loadPage2(){
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4 && xhttp.status == 200) {
response = xhttp.responseText;
$("#content").remove();
$("#mainContent").append(response);
}
};
xhttp.open("GET", "page2.html", true);
xhttp.send();
}
</script>
<button onclick="loadPage1()">Load page 1</button>
<button onclick="loadPage2()">Load page 2</button>
<div id="mainContent">
</div>
And then the 2 pages with JavaScript content, basically just spamming the console with "I am page x" every second.
Page 1:
<div id="content">
<h1>Page 1</h1>
<script type="text/javascript">
setInterval(function(){
console.log("I am page 1");
},1000);
</script>
</div>
Page 2:
<div id="content">
<h1>Page 2</h1>
<script type="text/javascript">
setInterval(function(){
console.log("I am page 2");
},1000);
</script>
</div>
The Ajax loads fine, I can see the h1 changing from Page 1 to Page 2. But in the console, I can see that the first script is still spamming even after the content has been removed.
Is there a way to prevent such behavior? Preferably while keeping each script in it's proper place, and not by moving all scripts to the "main page" .
EDIT: To avoid confusion, setInterval() is not the main problem, it's merely an example. I'm asking how do you usually deal with such a problem with Ajax and JavaScript
Even though the 1st <script> block has been replaced, you see the console logs because of the way javascript works.
Your anonymous function
function(){
console.log("I am page 1");
}
will live on and keep executing till you call clearInterval or move away from this page.
This is also the case when you add a click handlers eg $('#some_button').on("click",function(evt){/*do something*/});
Even if you have a variable declared, like <script>var x='data1';</script>
and then you delete the enclosing <script> tag, the variable x will continue to exist.
In both cases, the references to the functions and variables are stored somewhere. References to the setInterval, and click handler function are held by the event handlers. A reference to any var and function you declare is held in the window object (unless you use a closure).
In your newly loaded script, you could re-assign stuff: the behavior of a function will be the last loaded behavior. Any calls made to that function will execute the new instructions because they too have now been assigned to the window object(scope).
In summary,
You will need to clear interval
The functions and vars you declare will exist till you change them
Re:Question in comment
oh, so If I declare a new behavior for a function, it wouldn't give me an error like it would with static programming languages. It 2ould save me a lot of work if I can keep the namings the same. I guess all I need to do is clearInterval, and keep whatever functions as they are.
Right but rather than draw a parallel to other programming languages, try and see these as instructions that are interpreted immediately when you inject the script tag into the DOM. So, what you are doing is actually just re-assigning the properties of the window object. To understand this better, open the developer console on chrome and run these in order:
window.hasOwnProperty("xy")
var xy=1
window.hasOwnProperty("xy")
window.xy
xy="foo"
typeof window.xy
typeof window
This should help you understand how the JavaScript engine is treating your code.
You removed/replaced the content, not the script, you are still on the same page. also you only load new data into that page, so your script is still running in that page unless its stopped explicitly or when the page reloads.
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 */ });
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.
I have a multi-level drop down menu (done using HTML + CSS) that I want to put on a number of different pages. In the future I will need to update this menu and change its contents, so I have saved the HTML in its own file so that I can roll out the changes to all the pages at once (instead of having to go through each page and repeatedly paste in the changed list items).
I have tried using iframe, but this cuts off the menu items with its limited height (setting a manual height that's big enough would leave tons of blank space, of course):
<iframe height="100%" src="menu.html" frameborder="no" width="100%" scrolling="no"></iframe>
I also tried using embed (this looks fine until you mouse over the menu items -- it just scrolls within the frame):
<embed type="text/html" src="menu.html" width="100%" height="100%"></embed>
The menu functions fine when the code is simply dumped into the individual pages I need it on, so I know that's not the issue. It's the embedding and calling it from its own HTML file that is the problem. Is there a simple way to do this that will allow the drop-down menu to appear as it should?
I should mention that while I have my IT department's blessing to do this, this is a project that they aren't supporting. I can only edit the HTML of my webpages in the body, and not the head. The exception being HTML pages I upload as files (like the menu code). So there are some constraints.
Well here is a bit of a long winded javascript approach that might keep your IT guys happy:
window.onload = new Function("load('embed-me.html','content')"); // Replace with URL of your file and ID of div you want to load into.
function ahah(url, target) {
document.getElementById(target).innerHTML = ' Fetching data...';
if (window.XMLHttpRequest) {
req = new XMLHttpRequest();
} else if (window.ActiveXObject) {
req = new ActiveXObject("Microsoft.XMLHTTP");
}
if (req != undefined) {
req.onreadystatechange = function() {ahahDone(url, target);};
req.open("GET", url, true);
req.send("");
}
}
function ahahDone(url, target) {
if (req.readyState == 4) { // only if req is "loaded"
if (req.status == 200) { // only if "OK"
document.getElementById(target).innerHTML = req.responseText;
} else {
document.getElementById(target).innerHTML=" AHAH Error:\n"+ req.status + "\n" +req.statusText;
}
}
}
function load(name, div) {
ahah(name,div);
return false;
}
Not written by me(LINK) (I just added the run on page load bit).
Tested and working (in Chrome at least). Though your site will have no menu if the user has javascript disabled!
EDIT:
Example...
<body>
<script type="text/javascript" src="embed-me.js"></script> <!-- load the javascript -->
<div id="content"></div> <!-- html will be embedded here -->
</body>
I use the following php code and works very nice. It doesn't even show when you check the source code online.
<?php include("menu.php"); ?>
Use php Include !!
Okay first.. copy the menu code and save it on to a file called menu-1.php
then whenever you want to use your menu; just type the following code:
<?php include("menu-1.php"); ?>
This is a good way to do menu's because every time you need to update your menu, you wont have to update every single page, just update your menu-1.php
P.S. PHP might not show up on your local machine unless you are using wamp or xamp