How to access Dom elements inserted by XMLHttpRequest? - javascript

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.

Related

Javascript: Am I using onreadystatechange properly?

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.

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.

How should I create two object to do two different ajax calls?

I have:
var xhr = new XMLHttpRequest();
xhr.onload = function() {
if(xhr.status === 200) {
document.getElementById('content').innerHTML = xhr.responseText; // Update
}
};
xhr.open('GET', 'data/data-one.html', true); // Prepare the request
xhr.send(null);
Now I want to do the same thing for another link, so when the link is clicked, in the code above, data-one.html is inserted to the HTML container with an id of content in my html page.
Now lets image I have another link in my nav and want to do the same process for another html container with an id of content1 this time to insert data-two.html .
Do I have to create the httprequest in this file or another ajax file? Are the variables gonna be different?
I already tried with the same variable both in the same file and other files but I get an error saying the I can't set the innerHTML to Null. I can't find out why. Please help.
This code is just to get you started. It is very verbose and can be improved to reused. For the sake of clarity I decided to keep it simple though.
function reqListener1 () {
console.log("listener1 -- html echo", this.responseText);
}
function reqListener2 () {
console.log("listener2 -- json echo", this.responseText);
}
document.addEventListener("DOMContentLoaded", function () {
var url1 = "/echo/html/";
var url2 = "/echo/json/";
var oReq = new XMLHttpRequest();
oReq.addEventListener("load", reqListener1);
oReq.open("GET", url1);
oReq.send();
// you could use the same variable. but you'll need to instantiate a different object
var oReq2 = new XMLHttpRequest();
oReq2.addEventListener("load", reqListener2);
oReq2.open("GET", url2);
oReq2.send();
});
Demo: http://jsfiddle.net/pottersky/7dz8r19d/1/

Load an xhtml file to a div element using CORS and javascript

I want to load a page from another domain to a div element in my page. I'm using CORS and it works since it shows the file is loaded in console log but I cannot manage to add it to my div.
Here's my code to make it more clear:
<script type="text/javascript">
function createCORSRequest(method, url){
var xhr = new XMLHttpRequest();
if ("withCredentials" in xhr){
xhr.open(method, url, true);
} else if (typeof XDomainRequest !== "undefined"){
xhr = new XDomainRequest();
xhr.open(method, url);
} else {
xhr = null;
}
return xhr;
}
var request = createCORSRequest("get", "http://localhost:8080/test/header.xhtml");
if (request){
request.onreadystatechange = function() {
if (request.readyState === 4) {
if (request.status >= 200 && request.status < 400) {
var hpage = request.responseText;
document.getElementById("theader").innerHTML = hpage;
} else {
alert("An error occured! Request Status: +"request.status);
}
}
};
request.send();
}
</script>
<body>
<div id="theader"></div>
</body>
How do I display the loaded page in theader div?
UPDATE
I found out that this happens in firefox and chrome because I use localhost. It works in ie but it only loads the text without css and images. Any idea how can I load the whole page into the div?
I guess my question now will be does the page load with all resources in CORS like it does with iframe? If so how?
A div element is meant to contain only certain HTML elements: in a nutshell the elements that you can find in the body. But not all HTML elements, and in particular not a html or head element. This is why your code does not work.
To solve your problem you either need to use an iframe (but from your question it seems this is not what you want), or put the content of the body element in the div and parse the head and load it in the current head.
Something like that (not tested):
var hpage = document.createElement("html");
hpage.innerHtml = request.responseText;
//Below you might want to write more robust code
//depending on the content of the response and how much you trust it
var head = hpage.getElementsByTagName("head")[0];
var body = hpage.getElementsByTagName("body")[0];
document.getElementById("theader").innerHTML = body.innerHTML;
//Now iterates over the children of head to find
//the script and style elements, and you can append them to the head of the document
var currentHead = document.getElementsByTagName("head")[0];
var scripts = head.getElementsByTagName("script");
for (var i=0; i<scripts.length; i++) {
currentHead.appendChild(scripts[i]);
}
//same thing for style elements,
//you could even do that for all elements
//depending on what the response may contain

Replacing whole HTML content kills HEAD and BODY tags after HTTP Request!

After pressing a button, I'm sending the whole HTML content from a webpage (the part within the <html> tags) to a CGI script which manipulates the content and sends it back.
Now I'm trying to replace the existing content with the new one. Unfortunately after assignment, every single <head> or <body> tag (as well as the closing ones) will be killed.
By using some alerts I looked through the returning value as well as the original HTML stuff. Both are absolutely as expected.
But after the assignment there is some magic going on. Please help me to figure out what's going on.
Here is the used JavaScript code I used:
var originalBodyInnerHTML = document.body.innerHTML;
var htmlNode = document.getElementsByTagName('html')[0];
var post_parameters = encodeURIComponent(htmlNode.innerHTML);
makePOSTRequest("POST", "http://whatever.com/cgi-bin/doit.cgi", post_parameters, htmlNode);
function makePOSTRequest(method, url, parameters, htmlNode) {
var http_request = getRequestObj();
if (!http_request) {
alert('Cannot create XMLHTTP instance');
return false;
}
http_request.onreadystatechange = function()
{
if (http_request.readyState < 4)
{
var waitingPageBody = '< img src="/img/ajaxloader.gif" alt="in progress..."/>';
document.body.innerHTML = waitingPageBody;
}
else //if (http_request.readyState == 4)
{
if (http_request.status == 200)
{
alert('1response: ' + http_request.responseText);
alert('2innerhtml: ' + document.getElementsByTagName('html')[0].innerHTML);
document.getElementsByTagName('html')[0].innerHTML = http_request.responseText;
}//end of if (http_request.status == 200)
else
{//other http statuses
alert("There was a problem (" + http_request.statusText + ", " + http_request.status + ' error)');
bodyNode.innerHTML = originalBodyInnerHTML;
}
}//end of else if http_request.readyState == 4
}
http_request.open(method, url, true); //async
http_request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http_request.setRequestHeader("Accept", "application/atom+xml,application/xml,text/xml");
http_request.setRequestHeader("Connection", "close");
http_request.send(parameters);
}
function getRequestObj() {
var http_request = false;
if (window.XMLHttpRequest)
{ // Mozilla, Safari,...
http_request = new XMLHttpRequest();
if (http_request.overrideMimeType)
{
http_request.overrideMimeType('text/html');
}
}
else if (window.ActiveXObject)
{ // IE
try {
http_request = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e)
{
try {
http_request = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e) {}
}
}
return http_request;
}
This is a simple solution that worked for me. Just as a reference.
document.clear();
document.write(newHtml);
where newHtml is the complete html of new web page.
well, with this
document.getElementsByTagName('html')[0].innerHTML = http_request.responseText
you are replacing everything insidee the html, "killing" body, head and everything...
maybe you wanted
document.body.innerHTML = http_request.responseText
Also, I'd use jquery, it makes your life sooo much easier
You cannot do that. It's not possible to replace the contents of the whole html tag. You can get away with replacing only the contents of the body tag. The head element is kind of magical and browser generally don't support replacing it.
If you want to change the whole document, redirect to it.
If you want to change only parts of the head, try sending them in a different form (like JSON), and make appropriate changes using javascript APIs.
Thanks qbeuek for your answer!
To change only the header, Firefox in fact will allow something like this:document.getElementsByTagName('head')[0] += "e.g. some scripts"
But for Internet Explorer it is necessary to add each element separately to the DOM tree.
var script = document.createElement("script");
script.setAttribute('type','text/javascript');
objHead.appendChild(script);
However, it is really weird that Firefox behaves like this and not popup with some error...

Categories