I am puzzled about this. I have two XMLHttpRequests that operate on Select elements of my HTML file (each one operates on a different Select element right when the HTML file is loaded). I am using a callback function as was recommended on W3CSchools. If my variable xmlHttp is defined outside of my callback function, only the second request works, and the first one gets deleted before it has a chance to finish. If I put 'var' in front of it the same thing happens. However, if my variable is inside the function with 'var' in front of it, then absolutely nothing happens. I have narrowed it down to where to the line that says "HERE!!!!!" is where the program seems to hang. I know the loadXMLDoc function does not actually finish because when I put an alert outside of it, nothing happens. I am supposing it has something to do with the 'if' part and the program not being able to recognize xmlHTTP, even though it was locally defined. I am still pretty new to JavaScript and just want to be able to run multiple XMLHttpRequest objects at once without them getting in each other's way but also without the page hanging. Any ideas why this does not work?
HTML:
<form>
<select id="stateSelectCities">
<!-- Will be populated with MySQL -->
</select>
<select id="citySelect">
<option>Select a State</option>
</select>
<br />
<br />
<select id="stateSelectCounties">
<!-- Will be populated with MySQL -->
</select>
<select id="countySelect">
<option>Select a State</option>
</select>
<p id="xmltest"></p>
<p id="currentState"></p>
<p id="sc"></p>
<p id="rs"></p>
<p id="st"></p>
</form>
JavaScript:
<script type="text/javascript">
function loadXMLDoc(method, data, url, cfunc) {
var xmlHTTP = new XMLHttpRequest();
xmlHTTP.onreadystatechange = cfunc;
xmlHTTP.open(method, url, true);
if (data) {
xmlHTTP.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlHTTP.send(data);
} else {
xmlHTTP.send();
}
}
function returnStateListForCounties() {
loadXMLDoc('GET', null, "stateslist.xml", function() {
document.getElementById('countySelect').disabled = true;
if (xmlHTTP.readyState == 4 && xmlHTTP.status == 200) {
// Read the XML Data and Populate Counties States Menu
var response = xmlHTTP.responseXML;
var states = response.getElementsByTagName('state');
for (i = 0; i < states.length; i++) {
var option = document.createElement('option');
option.innerHTML = states[i].childNodes[0].nodeValue;
option.setAttribute('onmouseup', 'returnCounties(this.innerHTML)');
document.getElementById("stateSelectCounties").add(option);
}
}
//document.getElementById("sc").innerHTML = 'statusCode: ' + xmlHTTP.status;
//document.getElementById("rs").innerHTML = 'readyState: ' + xmlHTTP.readyState;
//document.getElementById("st").innerHTML = 'statusText: ' + xmlHTTP.statusText;
})
}
function returnStateListForCities() {
loadXMLDoc('GET', null, 'stateslist.xml', function() {
document.getElementById('citySelect').disabled = true;
// HERE!!!!!
if (xmlHTTP.readyState == 4 && xmlHTTP.status == 200) {
// Read the XML Data and Populate Cities States Menu
var response = xmlHTTP.responseXML;
var states = response.getElementsByTagName('state');
for (i = 0; i < states.length; i++) {
var option = document.createElement('option');
option.innerHTML = states[i].childNodes[0].nodeValue;
option.setAttribute('onmouseup', 'returnCities(this.innerHTML)');
document.getElementById("stateSelectCities").add(option);
}
}
document.getElementById("sc").innerHTML = 'statusCode: ' + xmlHTTP.status;
document.getElementById("rs").innerHTML = 'readyState: ' + xmlHTTP.readyState;
document.getElementById("st").innerHTML = 'statusText: ' + xmlHTTP.statusText;
})
}
//returnStateListForCounties();
returnStateListForCities();
</script>
The problem here is xmlHTTP variable which is defined inside loadXMLDoc function and try to use again inside returnStateListForCounties function, I'll do it like this:
function loadXMLDoc(method, data, url, cfunc) {
var xmlHTTP = new XMLHttpRequest();
xmlHTTP.onreadystatechange = function() {
if (xmlHTTP.readyState == 4 && xmlHTTP.status == 200)
{
cfunc(xmlHTTP.responseXML); //Call passed func with the resulting XML
}
};
xmlHTTP.open(method, url, true);
if (data) {
xmlHTTP.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlHTTP.send(data);
} else {
xmlHTTP.send();
}
}
This way you encapsulate the data recovery.
Related
I am creating a site for listing TV shows and I am using TVMaze api for it. I am beginner in working with JSON so maybe my problem is that, but here is the weird thing happening.
My table is generated with this code:
var keyword = "";
var $url = "";
$('#submit').on('click', function (e) {
//e.preventDefault();
keyword = $('#search').val();
window.sessionStorage['keyword'] = keyword;
});
if (!window.sessionStorage['keyword']) {
$url = " http://api.tvmaze.com/shows?page=1";
} else {
keyword = window.sessionStorage['keyword'].toString();
keyword = keyword.toLowerCase().replace(/\s/g, "");
$url = "http://api.tvmaze.com/search/shows?q=" + keyword;
//alert($url);
}
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
var $obj = JSON.parse(this.responseText);
for (var i = 0; i <= $obj.length - 1; i++) {
var $item = '<div> \
<div>\
<h2>' + $obj[i].name + '</h2> \
<div> ' + $obj[i].rating.average + ' </div>\
<p>' + $obj[i].summary + '</p>\
Track\
</div>\
</div>';
$('.show-items-container').append($item);
}
}
};
//alert($url);
xmlhttp.open("GET", $url, true);
xmlhttp.send();
So first it checks if there is keyword entered in a search bar and if there isn't it sends a request to the /page=1, and if there is a keyword entered, it should print the show. But, in my case, it reads to url like it is supposed to, but nothing shows up. And if I search that link in the browser it lists the correct show.
For example if I put 'kirby' in the search bar, it reads this url -> http://api.tvmaze.com/search/shows?q=kirby , but nothing shows in the table and there are no errors in the console. If you enter that same url in the browser, it works.
Can anyone tell me what the problem is?
Looks like onclick you are not making the xhr request. You call xmlhttp.open and xmlhttp.send outside of the click event so nothing happens on click. Also I noticed you were accessing the wrong property it should be $obj[i].show.___ vs $obj[i].___
var keyword = "";
var $url = "";
var xmlhttp = new XMLHttpRequest();
function makeRequest() {
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
// clear the current search results
$('.show-items-container').empty();
var $obj = JSON.parse(this.responseText);
for (var i = 0; i <= $obj.length - 1; i++) {
// make sure you access the correct property
var $item = `<div>
<div>
<h2> ${$obj[i].show.name} </h2>
<div> ${$obj[i].show.rating.average} </div>
<p> ${$obj[i].show.summary} </p>
Track
</div>
</div>`;
$('.show-items-container').append($item);
}
}
}
// make the xhr request on click
xmlhttp.open("GET", $url, true);
xmlhttp.send();
}
$('#submit').on('click', function(e) {
keyword = $('#search').val();
$url = "https://api.tvmaze.com/search/shows?q=" + keyword;
// call on click
makeRequest();
});
// call on page load
makeRequest();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id='search' />
<button type="button" id='submit'>Submit </button>
<div class="show-items-container">
</div>
I'm trying to use XML to get a list of cities from a website, then go through and add each of the cities to a datalist so that when I put in an input it will filter the cities in the list.
example of city list:
Aleppo
Alexandria
Alger
Almaty
Ankara
Anshan
Baghdad
Baku
Bandung
Bangalore
Bangkok
Barcelona
*[Each city name is on a new line]
current html:
<div id="namearea">
<h2>City Name:</h2>
<div>
<input id="citiesinput" list="cities">
<datalist id="cities"></datalist>
<button id="search">
Search
</button>
<span class="loading" id="loadingnames">
Loading...
</span>
</div>
</div>
current JS code:
window.onload = function() {
var request = new XMLHttpRequest();
request.onload = processCities;
request.open("GET", "url", true);
request.send();
};
Inspecting the page with Firebug shows that nothing is being added to the datalist, so I'm wondering what I'm doing wrong. I also tried using .responseText rather than .responeXML but it didn't make any difference.
[Fixed]
I changed the processCities() function to:
function processCities() {
var response = this.responseText;
var city = response.split("\n");
var options = "";
for(var i = 0; i < response.length; i++) {
options += "<option value='"+city[i]+"'>\n";
}
document.getElementById("cities").innerHTML = options;
}
This code seems to work.
Here is an example of making the request. If you really are getting XML, you'll have to parse it. It's better if you could get json.
var request = new XMLHttpRequest();
request.open('GET', '/my/url', true);
request.onload = function() {
if (request.status >= 200 && request.status < 400) {
// Success!
var data = JSON.parse(request.responseText);
} else {
// We reached our target server, but it returned an error
}
};
request.onerror = function() {
// There was a connection error of some sort
};
request.send();
I am trying to create an application that will show, and periodically change, a paragraph of text (like a news article or similar).
I want the data to come from an xml file so other people can add stories/remove old stories etc.
I'm trying to get my JavaScript to populate a single html field with data from an xml file. Then after a given time, for now we'll say 4 seconds, it will change to the next piece of data.
Below is a very crude version of what I've been trying to do:
HMTL:
<head>
<script src="script.js"></script>
</head>
<body>
<div id="text"></div>
</body>
XML:
<document>
<text>one</text>
<text>two</text>
<text>three</text>
</document>
JavaScript:
var timer = setInterval(addText,4000);
var xhttp = new XMLHttpRequest();
xhttp.onreadystaechange = function() {
if(this.readyState == 4 && this.status == 200) {
addText(this);
}
};
function addText(xml) {
var xmlDoc = xml.responseXML;
var count = 0;
var max = xmlDoc.GetElementsByTagName("text");
document.getElementById("text").innerHTML =
xmlDoc.getElementByTagName("text")[count].childNodes[0].nodeValue;
if (count < max.length) {
count++;
} else {
count = 0;
}
}
xhttp.open("GET", "XMLFile.xml",true);
xhttp.send();
The current problem I am experiencing is that the first xml field populates successfully, but then I get an error saying "Unable to get property 'responseXML' of undefined or null reference".
Ideally what I'd also like is for the xml document to be opened everytime the function occurs, so the application doesn't have to be restarted if extra data is added to the xml file - if that makes sense (and is possible)
You can place addText in the scope of onreadystatechange handler. Something like this.
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if(this.readyState == 4 && this.status == 200) {
var xmlDoc = this.responseXML;
var count = 0;
var xText = xmlDoc.getElementsByTagName("text");
var max = xText.length;
var docText = document.getElementById("text");
function addText() {
//docText, xText and count are available from parent scope
docText.innerHTML =
xText[(count++) % max].childNodes[0].nodeValue;
}
var timer = setInterval(addText,4000);
}
};
xhttp.open("GET", "XMLFile.xml",true);
xhttp.send();
In my code, when a select box is changed, a js function (ConfirmDelete) is called which asks the user if they are sure they want to change the select box. If the user selects no, it will return false and would normally stop the execution.
My problem is that I also have another AJAX/JS function defined after this that is waiting for the select box to be changed and if it is, it sends details to a php script which adds a record into a mysql database.
I'd like to know if there is anyway that I can stop the AJAX/JS code from running after a user has selected No.
The JS function
function ConfirmDelete()
{
var x = confirm("Are you sure?");
if (x)
return true;
else
return false;
}
The AJAX/JS function
$( ".dropdown" ).change(function() {
var request = new XMLHttpRequest();
var id = this.value;
var content = this.name;
request.open("POST", "samefile.php", true);
request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
request.onreadystatechange = function () {
if(request.readyState == 4 && request.status == 200) {
var return_data = request.responseText;
alert (return_data);
}
}
request.send("id="+id+"&content="+content);
window.location.reload();
window.location.reload();
}
);
The HTML Select box
<select class="dropdown" name="09:00-1-0-16-05-26" Onchange="return ConfirmDelete();">
<option class="co0es0sp1fd1oo0fs0" value="47">mike berry</option>
<option value="cancel-47">Cancel</option></select>
The order of the html is
JS Function defined in header
HTML code
AJAX/JS Script tag after
The AJAX/JS function
$( ".dropdown" ).change(function() {
if(!ConfirmDelete()) return; // right here, use this to confirm
var request = new XMLHttpRequest();
var id = this.value;
var content = this.name;
request.open("POST", "samefile.php", true);
request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
request.onreadystatechange = function () {
if(request.readyState == 4 && request.status == 200) {
var return_data = request.responseText;
alert (return_data);
}
}
request.send("id="+id+"&content="+content);
window.location.reload();
window.location.reload();
}
);
Adding onchange event directly in HTML does not solve the problem.
Use this instead;
So, I'm pulling a query from a php file using javascript, then publishing it to another javascript that will then put another php query in another text area.
In other words:
[input text area 1] -> [javascript live search] -> [Query results]
[Query results] -> [onClick event] -> [Load results in text area 2]
The idea is that live searches in one textarea will come out with its approximate match in another live.
However, when I try to load the data in the second textarea it comes out as raw data. I'm confused on how to view it properly.
HTML:
The first text area is the input with a function to call a script, which is here:
function showResult(str) {
if (str.length == 0) {
document.getElementById("livesearch").innerHTML = "";
document.getElementById("livesearch").style.border = "0px";
return;
}
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
} else {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
document.getElementById("livesearch").innerHTML = xmlhttp.responseText;
document.getElementById("livesearch").style.border = "1px solid #000";
}
}
xmlhttp.open("GET", "ajax-search.php?keyword=" + str, true);
xmlhttp.send();
}
The php returns the result:
echo '<li onclick="grabID('.$row['dir_id'].')" >'.$row['eng_dir'].'</li><br />';
Which then initiates a clicked event:
function grabID(num){
xmlhttp.open("GET","ajax-result.php?result="+num,true);
xmlhttp.send();
document.getElementById("output").innerHTML="Something here?!?!?!";
}
Once again the results from the other php are returned correctly. The problem is that because it's a loop, it returns a lot of results instead of just 1. I just want the 1 result that matches the ID of the previous search.