Javascript: Am I using onreadystatechange properly? - javascript

Bare in mind I am very new to JavaScript syntax, so please have patience.
I'm trying to use multiple onreadystatechange's as promises to catch what I return from express, but every time I do, both of them are getting called. Here is my code:
var ready = function(){
xhr.open('GET', 'getallbeertypes');
xhr.send(null);
xhr.onreadystatechange = function () {
var parent = document.getElementById('recipes');
var docfrag = document.createDocumentFragment();
if(xhr.status == 200){
var beerTypes = JSON.parse(xhr.responseText);
//loop through beerTypes to append a button to each list item
for (var beer = 0; beer < beerTypes.length; beer++){
//create necessary elements
var li = document.createElement('li');
var button = document.createElement('BUTTON');
//set text content to list item
li.textContent = beerTypes[beer].alias;
//append list item to button
button.appendChild(li);
// add onclick attribute
button.setAttribute("name", beerTypes[beer]._id);
button.setAttribute("onclick", "moreInfo(this.getAttribute('name'))");
//append button to document fragment
docfrag.appendChild(button);
}
//display on DOM element
parent.appendChild(docfrag);
}else{
// console.log(JSON.parse(xhr.responseText));
var header = document.createElement('h1');
header.textContent = "Something went wrong. Please try again later.";
docfrag.appendChild(header);
parent.appendChild(header);
}
}
}
ready();
So the above section of code works, and it displays each JSON object as a button in a list of items. When the button is clicked, the following function is supposed to run:
var moreInfo = function(_id){
xhr.open('GET', '/getuserrecipes/' + _id);
xhr.send();
xhr.onreadystatechange = function(){
console.log("is this running?");
console.log(JSON.parse(xhr.responseText));
}
}
I'm expecting the onclick attribute should only run the moreInfo function.
Whenever I click one of the buttons, the else statement in the ready function is somehow running and displays Something went wrong. Please try again later on the screen.
The only connection I can make is the onreadystatechange, but I don't really know if that's it.
How/why is the other function even being called and How can I stop it? All help is appreciated.

You should check for the state of the request. To do that, use readyState property. There are 5 states, integers from 0 to 4, and you want the last one, which is 4.
something like this:
if (xhr.readyState == 4 && xhr.status == 200){
...
}
Check this example.

Related

Ajax events error when sending multiple http request

when i'm try to get data for some html element from a website by ajax i added some events like xhr.onloadstart,xhr.onloadend to show the loader element before sending the request and adding the data after finishing the response and hide the loader
the problem is when i try to click on multiple elements after each other it's just stop working just display the load for some html elements and not given any data and that's happening just when i try to click on 3 or 4 element after each other directly - and when i click normally and wait for load it's working without any problems -- i don't know if the problem is with my code or the problem in ajax like it's cannot handle many requests at the same time ... Please anyone help me
i was working with jquery ajax and changed to the XMLHttpRequest() and the problem still the same
Here's my code
for(let q = 0; q < elem.length; q++) {
elem[q].addEventListener("click",function() {
let url = $(this).find(".elem").attr("href");
let _this = this;
let $this = $(this);
var xh = new XMLHttpRequest();
xh.onloadstart = function(bubbles) {
_this.getElementsByClassName("loader")[0].style.display = 'block';
}
xh.onreadystatechange = function(change) {
_this.getElementsByClassName("loader")[0].style.display = 'none';
}
xh.onloadend = function(data) {
console.log(data)
//result dom object
console.log($(data.currentTarget.responseText)[71].getElementsByClassName("row").length)
if($(data.currentTarget.responseText)[71].getElementsByClassName("row").length > 0) {
let row = $(data.currentTarget.responseText)[71].getElementsByClassName("row")[0].getElementsByClassName("row")[0];
let select_color = $(row).find("#container #color_select_options").attr("class","ElemData");
$this.append(select_color[0]);
//when user click again delete appended element and keep the first one
if($this.find(".ElemData").length > 1) {
for(o = 1; o < $this.find(".ElemData").length; o++) {
_this.getElementsByClassName("ElemData")[o].remove()
}
}
}
})
}

Javascript SELECT attribute's OPTION is not working inside any method

I am facing a strange problem. Please see my code clearly.
While I am calling my following function in the root of my js file it is smoothly working.
function setOptionValueWithNameAndOid(select, name, oid){
//here first parameter 'select' is my SELECT which is written in HTML and just pass the ID of that SELECT and 'name' and 'oid' is simple string
var option = document.createElement("option");
option.setAttribute("value", oid);
var textNode = document.createTextNode(name);
option.appendChild(textNode);
select.appendChild(option);
}
if I call this function in the body of my js file like
setOptionValueWithNameAndOid(select, name, oid)
So this is perfectly working. Select option is adding.
But problem occurs when I call this function inside any event or inside any function.
Please see this code carefully:
function loadNameOidSelect(url, select){
//here 'url' is my API url. and select is the same SELECT. just passing the id
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.onload = function() {
var data = JSON.parse(this.response);
if (request.status >= 200 && request.status < 400) {
data.forEach(dta => {
setOptionValueWithNameAndOid(select, dta.NAME, dta.OID); // from API i am getting 'name' and 'oid'
});
} else {
console.log('error');
}
}
request.send();
}
but now problem is if I call the same method inside this api calling no option is adding in my SELECT.
But If I call the same method in the page load with some static data it is perfectly working.
So can you please help me what actually problem?

How to access Dom elements inserted by XMLHttpRequest?

I am loading html files with an XMLHttpRequest and putting everything in the body tag into an unseen 'storage' div, and then into the page to be seen. That works well.
function getModule(module,callback) {
var modulePath = makeModulePath(module);
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 ) {
var el = document.getElementById('storage');
getContent(xhr.responseText, el);
callback(el);
}
};
xhr.open("GET", modulePath, true);
xhr.responseType = "";
xhr.send();
}
<span id="introCurrency" class="introCurrency"><p>Copper standard</p></span>
But, always a but right? But when I go to select part(.introCurrency) of that inserted text using document.getElementById('introCurrency') get an error saying 'introCurrency'[null] it is not an object. But querySelectorAll does locate it and I can work with it, but it is a little fudgey:
var aModule =
document.querySelectorAll('.introCurrency');
for (var i=aModule.length; i--;){
aModule[i].style.display = 'none';
}
I would much rather use document.getElementById. I hope someone can tell me what's going on. Thank you.

AJAX Won't Toggle Table on Odd Occurrences

Good afternoon everyone!
So I have a basic Web Application. There are three dropdown menus and each dropdown menu appears after the previous dropdown has been selected. Once the third dropdown is chosen, we display to the user the TransferGuide (display_guide.php).
display_guide.php is outputted via an AJAX request on transfer.php
When a user click on the table header it expands to display courses under the category... that looks like this:
Everything is fine and works perfect. Only problem is, when I go to my dropdown menus to change to a different combination of dropdown menus, my table no longer toggles. It changes to display the right information, but it refuses to toggle. And the weird thing is that this ONLY happens on odd instances. The table will toggle ONLY the 1st, 3rd, 5th time I change the combinations and not the 2nd, 4th and so forth.
Does anyone have any idea what could be the reason for this odd behavior?
Here is my code and thanks in advance! This is only the <script> portion of the entire HTML/PHP code that is responsible of displaying the display_guide.php on to the page. :)
transfer.php:
<!--
**************************
AJAX FOR DROP DOWN MENUS
**************************
-->
<script>
// 1. Create an XMLHTTPRequest Object (XHR)
// 2. onreadystatechange is a property of the XHR Object, where we can store
// our function to execute once we send our XHR object, this is an
// event handler.
// 3. Check if readyState (values 0 thru 4) and status (values 200 or 404)
// in which case response is ready, in responseText, so we can assign to
// inner part of HTML element with ID of uni or major or transfer_guide
// 4. Open request with specified properties, with ?cc= as GET
// 5. Send the request using the open() property
function loadUniDropDown(str) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4 && xhttp.status == 200) {
document.getElementById("uni").innerHTML = xhttp.responseText;
}
};
xhttp.open("GET", "uni.php?cc="+str, true);
xhttp.send();
}
function loadMajorDropDown(str2) {
var xhttp2 = new XMLHttpRequest();
xhttp2.onreadystatechange = function() {
if (xhttp2.readyState == 4 && xhttp2.status == 200) {
document.getElementById("major").innerHTML = xhttp2.responseText;
}
};
xhttp2.open("GET", "major.php?uni="+str2, true);
xhttp2.send();
}
function loadTransferGuide(str3) {
var xhttp3 = new XMLHttpRequest();
xhttp3.onreadystatechange = function() {
if (xhttp3.readyState == 4 && xhttp3.status == 200) {
document.getElementById("transfer_guide").innerHTML = xhttp3.responseText;
// HIDES THE ALL THE GENED COURSES AND NOT THE GENED CATEGORIES BY DEFAULT ON PAGE LOAD
$(document).ready(function(){
//$("thead").next().hide();
$(".genEdCategoryHeaders").nextUntil(".genEdCategoryHeaders").hide(); //hides everything so only the categories show
$(".CourseName").hide(); //hides all the course names
}
);
// ON HOVER OVER GENED COURSES DISPLAY COURSE NAME INSTEAD OF NUMBER
$(".hoverOnCourses").mouseover(
function(){
$(this).children(".CourseNumber").hide();
$(this).children(".CourseName").show();
$(this).children(".CourseName").css("background-color","gray"); //gives hover effect by changing the background color
$(this).children(".CourseName").children().css("color", "white");
}
);
$(".hoverOnCourses").mouseout(
function(){
$(this).children(".CourseName").hide();
$(this).children(".CourseNumber").show();
}
);
// $("body").on("mouseover", ".CourseNumber", function(){
// $(this).hide();
// $(this).next().show();
// $(this).next().css("background-color","gray");
// $(this).next().children().css("color", "white");
// }).on("mouseout", ".CourseName", function(){
// $(this).hide();
// $(this).prev().show();
// })
//--------------TOGGLE THE GENED COURSES----------------
$(document).on("click", "thead", function(){
//$(this).next(".genedcat").toggle();
$(this).nextUntil("thead").toggle();
}
);
}
}
xhttp3.open("GET", "display_guide.php?major="+str3, true);
xhttp3.send();
}
</script>
If you have posted some basic html regarding the structure it would have been easier but still from what you have posted i could figure out one reason
In your loadTransferGuide() function see all the stuff after document.getElementById("transfer_guide").innerHTML = xhttp3.responseText;
you are assigning all the event handlers for mouseover and click events inside it which may look okay since you would want to assign events to the content loaded dynamically but i think this is what is causing the trouble you see when the transfer guide html gets inserted and you assign events it will work the first time but if they get replaced/removed again the event handler too get destroyed so it will work alternate times but not always to fix that just remove the code to fix that use event delegation on them
$("body").on("mouseover",".hoverOnCourses",
function(){
$(this).children(".CourseNumber").hide();
$(this).children(".CourseName").show();
$(this).children(".CourseName").css("background-color","gray"); //gives hover effect by changing the background color
$(this).children(".CourseName").children().css("color", "white");
});
$("body").on("mouseout",".hoverOnCourses",
function(){
$(this).children(".CourseName").hide();
$(this).children(".CourseNumber").show();
}
);
and cut below code and paste it outside of that function in global scope
//--------------TOGGLE THE GENED COURSES----------------
$(document).on("click", "thead", function(){
//$(this).next(".genedcat").toggle();
$(this).nextUntil("thead").toggle();
}
);

can xmlhttpRequest response wait even after onload

I am loading a page through xmlHttpRequest and I am not getting one variable which come into existance after some miliseconds when page loading is done
so the problem is when xmlHttpRequest sends back the response I do not get that variable in it.
I want it to respond back even after onload.
var xhr = new XMLHttpRequest();
xhr.open("GET", event.url, true);
xhr.onload = function() {
callback(xhr.responseText);
};
xhr.onerror = function() { callback(); };
xhr.followRedirects = true;
xhr.send();
I tried setTimeOut but of no use because may be at that time call is finished
xhr.onload = function() {
console.log('wait for response');
setTimeout(function(){
callback(xhr.responseText);
},2000);
};
I tried readyStateChange , but no success
xhr.onreadystatechange = function () {
if(xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
console.log(xhr.responseText);
callback(xhr.responseText);
};
};
by the way, I am trying to load amazon signIn page
and the variable which is missing everytime is hidden Input Field metadata1,
I get all other hidden Input fields in response text , except input field, named "metadat1"
I'll be more than Happy, If anyone can help.
Thanks in advance
ohh Finally I did it,
I din't read any javascript, Instead I just extracted scripts which I received in xhr calls and executed it inside a hidden div, and here it is , I got that variable's value
abc(xhr.responseText);
function abc(xhrRes){
var dynamicElement = document.createElement('div');
dynamicElement.setAttribute("id", "xhrdiv");
dynamicElement.setAttribute("style", "display: none;");
dynamicElement.innerHTML = xhrRes;
document.body.appendChild(dynamicElement);
var scr = document.getElementById('xhrdiv').getElementsByTagName("script");
//5 scripts needed to generate the variable
for(i=0;i<5;i++){
eval(scr[i].innerHTML);
if( i+1 == 5){
var response = document.getElementById('xhrdiv').innerHTML;
return response; //and in this response variable I have every thing I needed from that page which I called through xmlhttp Req
}
}
}
---------------------Improved Version-----------------------
Instead of executing script through eval,
keep script content in a file AND Include it, as we normally include the script, that works better.
xhrRes = xhr.responseText;
var dynamicElement = document.createElement('div');
dynamicElement.setAttribute("id", "xhrDiv");
dynamicElement.setAttribute("style", "display: none;");
dynamicElement.innerHTML = xhrRes;
document.body.appendChild(dynamicElement);
var xhrDiv = document.getElementById('xhrDiv');
var newScript = document.createElement('script');
newScript.type = 'text/javascript';
newScript.src = JSfile;
xhrDiv.appendChild(newScript);
(it shows the edit is done my anonymous user, :( because I forgot to Login, while editing)
If the data doesn't exist until some time after the page has loaded then, presumably, it is being generated by JavaScript.
If you request the URL with XMLHttpRequest then you will get the source code of that page in the response. You will not get the generated DOM after it has been manipulated by JavaScript.
You need to read the JavaScript on the page you are requesting, work out how it is generating the data you want to read, and then replicate what it does with your own code.

Categories