I have this problem, so I want to return the value received after an XMLHTTPRequest(), is this possible? If not, how would I go about achieving the same general idea? Here's what I have so far (It is obviously not working).
function something(url) {
var temp = getPage(url);
console.log(temp);
}
function getPage(url) {
var x = new XMLHTTPRequest();
x.onload = function() {
var html = x.responseText;
//CODE TO PARSE HTML TEXT
var variable = SOMETHING PARSED FROM HTML
return variable;
}
x.open("GET", url);
x.send();
}
This is the programming paradigm that every new javascript developer has to deal with.
Because of the asynchronous nature of javascript, functions tend not to pass values back via return statements, but instead the values are passed back via callback methods.
function something(url) {
getPage(url, function(temp) {
console.log(temp);
});
}
function getPage(url, callback) {
var x = new XMLHTTPRequest();
x.onload = function() {
var html = x.responseText;
//CODE TO PARSE HTML TEXT
var variable = SOMETHING PARSED FROM HTML
callback(variable);
}
x.open("GET", url);
x.send();
}
Related
I'am trying to parse site. The site (i suppose) using scripts and data bases to load data from (dynamically?). And this is my problem... I am trying to grab data through C# (unfortunately i don't have access to code right now) or JS. And it seems like either C# and JS, get only template of the site, but don't wait until all scripts executed. So this is my question, is there any way to get ALL html source? Maybe call scripts somehow. Or make a request, wait for 10 seconds, and then write source html data into variable?
Here is my JS code.
function request(link)
{
var xhr = new XMLHttpRequest();
xhr.open('GET', link, true);
xhr.onreadystatechange = function() .
{console.log(xhr.readyState);};
xhr.send();
let data = xhr.responseText;
var tempDiv = document.createElement('div');
tempDiv.innerHTML = data.replace(/<script(.|\s)*?\/script>/g,
'');
return tempDiv;
}
function loadFile(url, timeout, callback)
{
var args = Array.prototype.slice.call(arguments, 3);
var xhr = new XMLHttpRequest();
xhr.ontimeout = function () {
console.error("The request for " + url + " timed out.");
};
xhr.onload = function() {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
callback.apply(xhr, args);
} else {
console.error(xhr.statusText);
}
}
};
xhr.open("GET", url, true);
xhr.timeout = timeout;
xhr.send(null);
let data = xhr.responseText;
return data;
}
function showMessage (message) {
console.log(message + this.responseText);
}
function include(scriptUrl)
{
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", scriptUrl);
xmlhttp.onreadystatechange = function()
{
if ((xmlhttp.status == 200) && (xmlhttp.readyState == 4))
{
eval(xmlhttp.responseText);
}
};
xmlhttp.send();
let data = JSON.parse(xmlhttp.responseText);
var tempDiv = document.createElement('div');
tempDiv.innerHTML = data.replace(/<script(.|\s)*?\/script>/g,
'');
return tempDiv;
}
All this functions do not work as i want.
This isn't really practical - you're trying to load an HTML page, all associated scripts, then run them on the HTML page as if they were in a proper browser environment, but within your current browser session.
This sort of thing is feasible with the jsdom library if you were running on the server-side (NodeJS), because it simulates browser behaviour: https://github.com/jsdom/jsdom. So you could do
JSDOM.fromURL("https://example.com/", { runScripts: "dangerously" }).then(dom => {
console.log(dom.serialize()); //turn the page back into HTML
});
...to get the whole thing.
So i keep getting [object Object] where actually the result of a query should be. My question is, whether my callback is incorrect, because I have a hard time understanding it, but think i did it correct.
HTML-part:
<button type="button" id="input_search" onclick="getSearchFromSQL()">Search</button>
JS-part:
function getSearchFromSQL() {
document.getElementById('output').innerHTML = contents;
}
getSearchAsync(function (result) {
contents = result;
});
function getSearchAsync(callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', 'test123.sqlite3', true);
xhr.responseType = 'arraybuffer';
xhr.onload = function (e) {
var uInt8Array = new Uint8Array(this.response);
db = new SQL.Database(uInt8Array);
callback(db.exec("SELECT * FROM data"));
};
xhr.send();
}
I want to add, that my IDE tells me, that "SQL" is not declared as a global variable - not sure if there is a problem, since sql.js is implemented in the html-file.
I have 5 drop down lists which is dynamic in nature. But the only problem is all the option values are being fetched from mysql database and i really want the user to know that the query is happening at the backend and he should wait by displaying a gif or a line saying "loading.. " .
I've been looking all over for this and similar questions have been posted by others but i don't seem to get it working . Please help me out. Can somebody please give a easy solution?
Thanks.
I've placed an example here:
http://jsfiddle.net/cMEaM/embedded/result/
I've kept as much of the existing code the same so you should still recognise it. The getXMLHTTP function is the same:
function getXMLHTTP() {
//function to return the xml http object
var xmlhttp = false;
try {
xmlhttp = new XMLHttpRequest();
} catch (e) {
try {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
try {
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e1) {
xmlhttp = false;
}
}
}
return xmlhttp;
}
There's a new sendGet function to handle the XHR request, which takes success and error callbacks.
function sendGet(url, onSuccess, onError) {
var req = getXMLHTTP();
var method = "GET";
if (req) {
req.onreadystatechange = function() {
if (req.readyState == 4) {
// only if "OK"
if (req.status == 200) {
onSuccess(req);
} else {
onError(req);
}
}
}
req.open(method, url, true);
req.send(data);
}
}
I borrow a throbber from Wikipedia to display when the data is loading.
var throbberHtml = "<img src='http://upload.wikimedia.org/wikipedia/en/2/29/Throbber-Loadinfo-292929-ffffff.gif'>";
And these are the new getXXX functions which replace the <select> with the throbber while the data is loading:
function getState(countryId) {
var div = document.getElementById('statediv');
var oldInnerHTML = div.innerHTML;
var onSuccess = function(req) {
div.innerHTML = req.responseText;
};
var onError = function(req) {
div.innerHTML = oldInnerHTML;
alert("There was a problem while using XMLHTTP:\n" + req.statusText);
};
div.innerHTML = throbberHtml;
sendGet("findState.php?country=" + countryId, onSuccess, onError);
}
function getCity(countryId, stateId) {
var div = document.getElementById('citydiv');
var oldInnerHTML = div.innerHTML;
var onSuccess = function(req) {
div.innerHTML = req.responseText;
};
var onError = function(req) {
div.innerHTML = oldInnerHTML;
alert("There was a problem while using XMLHTTP:\n" + req.statusText);
};
div.innerHTML = throbberHtml;
sendGet("findCity.php?country=" + countryId + "&state=" + stateId,
onSuccess, onError);
}
There are other improvements that could be made, but I tried to keep in the sprit of your existing code as much as possible.
E.g. you can see that most of code in the getXXX functions is the same, so you could refactor these to use mostly the same code. Also, using a JS framework such as jQuery will replace the XHR code with better, more cross-browser compatible code. It's usually always better to avoid reinventing the wheel when it comes to code!
And you may possibly decide that sending the HTML for a <select> tag is not the best data format for the XHR. You might go with JSON which would decouple your presentation from the data.
hello i have problem to parse xml..
i have xml like this :
<tejemahan>
<kategori> komputer </kategori>
<hasil> aplikasi komputer </hasil>
</terjemahan>
Edited:
xml above I get in that way :
var url="http://localhost:8080/inlinetrans/api/translate/"+userSelection+"/"+hasilStemSel+"/"+hasilStem;
var client = new XMLHttpRequest();
client.open("GET", url, false);
client.setRequestHeader("Content-Type", "text/plain");
client.send(null);
if(client.status == 200)
alert("the request success"+client.responseText);
else
alert("the request isn't success"+client.status+""+client.statusText)
}
and this is my code to parse an xml file above :
this.loadXML = function (){
var url = http://localhost:8080/coba/api/artikan/"+sel+"/"+hasilStemSel+"/"+hasilStem
xmlDoc=document.implementation.createDocument("","",null);
xmlDoc.load("url");
xmlDoc.onload= this.readXML;
}
this.readXML = function() {
alert(xmlDoc.documentElement.tagName);
alert(xmlDoc.documentElement.childNodes[0].tagName);
alert(xmlDoc.documentElement.childNodes[1].tagName);
alert(xmlDoc.documentElement.childNodes[0].textContent);
alert(xmlDoc.documentElement.childNodes[1].textContent);
}
i can execute this code
xmlDoc=document.implementation.createDocument("","",null);
xmlDoc.load("url");
but why i can't execute this code
xmlDoc.load = this.readXML ???
Try putting the onload handler assignment before the load() call. If you call load() first, the onload event will happen before you have assigned a handler to handle it. Like this:
xmlDoc=document.implementation.createDocument("","",null);
xmlDoc.onload= this.readXML;
xmlDoc.load("url");
Firstly, I second David Dorward's suggestion: use XMLHttpRequest instead, which will work in all major browsers. Code is below.
Secondly, your readXML function is flawed, since most browsers will include whitespace text nodes within the childNodes collection, so xmlDoc.documentElement.childNodes[0] will actually be a text node and have no tagName property. I would suggest using getElementsByTagName() or checking the nodeType property of each node as you iterate over childNodes.
Thirdly, your XML is not valid: the <tejemahan> and </terjemahan> do not match, although this may be a typo in your question.
var url = "http://localhost:8080/coba/api/artikan/"+sel+"/"+hasilStemSel+"/"+hasilStem;
var readXML = function(xmlDoc) {
alert(xmlDoc.documentElement.tagName);
var kategori = xmlDoc.getElementsByTagName("kategori")[0];
alert(kategori.tagName);
};
var createXmlHttpRequest = (function() {
var factories = [
function() { return new XMLHttpRequest(); },
function() { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); },
function() { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); },
function() { return new ActiveXObject("Microsoft.XMLHTTP"); }
];
for (var i = 0, len = factories.length; i < len; ++i) {
try {
if ( factories[i]() ) {
return factories[i];
}
}
catch (e) {}
}
})();
var xmlHttp = createXmlHttpRequest();
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
readXML(xmlHttp.responseXML);
}
};
xmlHttp.open("GET", url, true);
xmlHttp.send(null);
I have a site that loads information using the XMLHttpRequest when a user clicks a link. The system works well but I would like to be able to execute JavaScript gathered in this process.
This is a problem as I would like to download the scripts 'on demand' if it were, rather than loading them all when the page is loaded.
Thanks for any help
I believe the recommended solution is something like this:
function include(scriptUrl)
{
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", scriptUrl);
xmlhttp.onreadystatechange = function()
{
if ((xmlhttp.status == 200) && (xmlhttp.readyState == 4))
{
eval(xmlhttp.responseText);
}
};
xmlhttp.send();
}
Or something like it.
However, be wary of this approach. It's vulnerable to cross-site scripting, which can open you (and your users) up to all sorts of nastiness. You'll want to take suitable precautions.
Recently I found the answer (It works in Chrome, in another browsers it was not tested).
You can create dataURL string and put it into src attribute of script element.
var xhr = XMLHttpRequest(),
doc = document;
xhr.open('GET', pathToJSFile, true);
xhr.onload = function () {
var script = doc.createElement('script'),
base64 = 'data:application/javascript;base64,';
try {
base64 += btoa(data.responseText);
} catch (e) {
// script file may contain characters that not included in Latin1
var symbols = data.responseText.split('');
for (var i = 0, l = symbols.length; i < l; i++) {
var symbol = symbols[i];
// here we are trying to find these symbols in catch branch
try {
btoa(symbol);
} catch (e) {
var code = symbol.charCodeAt(0).toString(16);
while (code.length < 4) {
code = '0' + code;
}
// replace original symbol to unicode character
symbols[i] = '\\u' + code;
}
}
// create new base64 string from string with replaced characters
base64 += btoa(symbols.join(''));
} finally {
script.src = base64;
// run script
doc.body.appendChild(script);
}
};
xhr.send();
You can subscribe to xhr.onprogress to show progress bar.
Update. You can download your script file as blob, and then create blob-url.
var xhr = XMLHttpRequest(),
doc = document;
xhr.responseType = 'blob';
xhr.open('GET', pathToJSFile, true);
xhr.onload = function () {
var script = doc.createElement('script'),
src = URL.createObjectURL(xhr.response);
script.src = src;
doc.body.appendChild(script);
};
xhr.send();
You can run script downloaded in form of a string using
eval()
However I would recommend you to add new
<script src='..'></script>
to your document and have a callback which will be called when it will be downloaded. There are many utils and jquery plug-ins for that.
I had the challenge on a mobile web-project, the magic was to set "overrideMimeType".
This has been verified to work on Android 4.1 to Android 6.0.
var head = document.getElementsByTagName('head');
var injectedScript = document.createElement('script');
head[0].appendChild(injectedScript);
var myRequest = new XMLHttpRequest();
myRequest.onreadystatechange = function() {
if (myRequest.readyState == 4 && myRequest.status == 200) {
injectedScript.innerHTML = myRequest.responseText;
//run a function in the script to load it
}
};
function start(){
myRequest.open('GET', 'javascript-url-to-download', true);
myRequest.overrideMimeType('application/javascript');
myRequest.send();
}
start();
You would need to use eval to parse the javascript from the XHR, note that this is EXTREMELY dangerous if you don't have absolute trust in the source of the javascript.