I tried to run this but it doesn't work.
It is intended to return a variable assigned inside a function, that was passed as callback to sendRequest(), which is retrieving data from the Internet through XMLHttpRequest asynchronously.
Can anyone tell me why this is not working and always returning ""?
function sendRequest(requestCode, args, callback){
var req = requestEngineUrl + "?req=" + requestCode + ";" + args;
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function(){
if(xmlHttp.readyState == 4)
{
if(callback != null){
callback(xmlHttp.responseText);
}
}
};
xmlHttp.open("GET", req, true);
xmlHttp.send(null);
}
this.assembleProcess = function(){
if(!isNull(this.id) && !isNull(this.titles)){
var titles = this.titles;
var id = this.id;
c = "";
sendRequest('304', id,
function(result){
var res = result.split("/");
var title = res[0];
var possibilities = res[1];
var fcontent = title + '<br><div>';
if(titles.length != possibilities){
console.log("WARNING: [SURVEYCARD].titles has not the same length as possibilities");
}
for(i = 0; i < possibilities; i++){
fcontent += '<div><a onclick="sendRequest("301",' + id + ',' + i + ',null)">' + titles[i] + '</a></div>';
}
fcontent += '</div>';
c = fcontent;
});
return c;
}
As an XMLHttpRequest is async, you should write an async function for that matter, like this
this.assembleProcess = function(callback){
if(!isNull(this.id) && !isNull(this.titles)){
var titles = this.titles;
var id = this.id;
c = "";
sendRequest('304', id,
function(result){
var res = result.split("/");
var title = res[0];
var possibilities = res[1];
var fcontent = title + '<br><div>';
if(titles.length != possibilities){
console.log("WARNING: [SURVEYCARD].titles has not the same length as possibilities");
}
for(i = 0; i < possibilities; i++){
fcontent += '<div><a onclick="sendRequest("301",' + id + ',' + i + ',null)">' + titles[i] + '</a></div>';
}
fcontent += '</div>';
c = fcontent;
callback(c)
});
}
and then, instead of using this.assembleProcess as a function with a result, you should pass a function as parameter:
Instead of
console.log(this.assembleProcess);
do this
this.assembleProcess(function(c){console.log(c)});
Related
I'm really new to Javascript and pretty much copied most of the code and modified it a bit. Sometimes I'm getting an error putted into a cell and sometimes the correct values. Do you know what is the issue?
for (p=3; p < 19; p=p+3){
var Value = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1").getRange(9,p);
var outputValue = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1").getRange(counter.getValue(),(3 + a));
outputValue.setValue(Value.getValue());
a = a +1;}
I'm adding the whole code as well for reference:
function getData() {
var queryString = Math.random();
var i;
for (i=2; i < 8; i++) {
var AddressColumn = SpreadsheetApp.getActiveSheet().getRange("W1").getColumn();
//if (ValueCrypto>0)
var cellFunction1 = '=Value(Replace(IMPORTXML("' + SpreadsheetApp.getActiveSheet().getRange(i,AddressColumn).getValue() + '?' + queryString + '","'+ SpreadsheetApp.getActiveSheet().getRange(1,AddressColumn).getValue() + '"),1,1,))*X1';
SpreadsheetApp.getActiveSheet().getRange(i,3).clearContent(); // You can also use range.setFormula("");
SpreadsheetApp.flush();
SpreadsheetApp.getActiveSheet().getRange(i,3).setValue(cellFunction1);
var cellFunction2 = '=Value(Replace(IMPORTXML("' + SpreadsheetApp.getActiveSheet().getRange(i,AddressColumn).getValue() + '?' + queryString + '","'+ SpreadsheetApp.getActiveSheet().getRange(1,AddressColumn).getValue() + '"),1,1,))';
SpreadsheetApp.getActiveSheet().getRange(i,8).clearContent(); // You can also use range.setFormula("");
SpreadsheetApp.flush();
SpreadsheetApp.getActiveSheet().getRange(i,8).setValue(cellFunction2);
}
//var cellFunction2 = '=IMPORTXML("' + SpreadsheetApp.getActiveSheet().getRange('A4').getValue() + '?' + queryString + '","'+ SpreadsheetApp.getActiveSheet().getRange('A5').getValue() + '")';
//SpreadsheetApp.getActiveSheet().getRange('C2').setValue(cellFunction2);
counter2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1").getRange("A12").getValue();
SpreadsheetApp.getActiveSheet().getRange("A12").setValue(counter2+1)
if (counter2 = 3) {recordValue();}
}
function recordValue() {
SpreadsheetApp.getActiveSheet().getRange("A12").setValue(0);
var counter = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1").getRange("A13");
//console.log(counter)
var dateCell = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1").getRange(counter.getValue(),2);
dateCell.setValue(new Date());
//const errorValues = ["#N/A", "#REF", "#ERROR!"];
var a = 0;
for (p=3; p < 19; p=p+3){
var Value = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1").getRange(9,p);
var outputValue = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1").getRange(counter.getValue(),(3 + a));
outputValue.setValue(Value.getValue());
a = a +1;
}
var TotalValue = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1").getRange("R2");
var outputTotalValue = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1").getRange(counter.getValue(),17);
outputTotalValue.setValue(TotalValue.getValue());
var TotalValue2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1").getRange("R5");
var outputTotalValue2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1").getRange(counter.getValue(),18);
outputTotalValue2.setValue(TotalValue2.getValue());
counter.setValue(counter.getValue() + 1);
if(counter.getValue() > 300){counter.setValue("14");}}
I've a problem with an if statement, where I want to check the value against a regExp. But I get "data[key].name is not a function", how do I go about to fix this issue?
document.querySelector('#search').onkeyup = function() {
var searchField = document.querySelector('#search').value;
var myExp = new RegExp(searchField, "i");
var request = new XMLHttpRequest();
request.open('GET', 'allCountries.json', true);
request.onreadystatechange = function() {
if ((request.readyState === 4) && (request.status === 200)) {
var data = JSON.parse(request.responseText);
var output = '<ul class="searchresult">';
for(var key in data) {
if(data[key].name(myExp) != -1 || data[key].code(myExp) != -1) {
output += '<li>' + data[key].name + ' - ' + data[key].code +
'</li>';
}
}
output += '</ul>';
document.querySelector('#update').innerHTML = output;
}
};
request.send();
};
If you want to check if a String matches a RegEx pattern, use the String#match() function:
Change your if statement to
if (data[key].name.match(myExp) || data[key].code.match(myExp)) {
var myExp = new RegExp("something.*[23]", "i");
var data = {a:{name:"something1", code:"somethingElse1"}, b:{name:"something2", code:"somethingElse2"}, c:{name:"something3", code:"somethingElse3"}}
var output = '<ul class="searchresult">';
for (var key in data) {
if (data[key].name.match(myExp) || data[key].code.match(myExp)) {
output += '<li>' + data[key].name + ' - ' + data[key].code +
'</li>';
}
}
output += '</ul>';
document.querySelector('#update').innerHTML = output;
<div id="update"></div>
If name and code are strings you should test your regex this way:
if(myExp.test(data[key].name) || myExp.test(data[key].code))
I am working in a javascript function that takes all of the id's from a HTML table and sends each iteration of a loop and sends the info to a PLSQL procedure to update. I concat a number on each id to make each one unique. If I add an alert in the loop and click through one by one it works. If I let it go on its own with no alert it skips some iterations. Is there something that I am doing wrong?
function process_update() {
var nDataCount = document.getElementById("v_nDataCount").value;
var p_cc_no = document.getElementById("p_cc_no").value;
var p_orient = document.getElementById("p_orient").value;
var p_ot = document.getElementById("p_ot").value;
var p_buy = document.getElementById("p_buy").value;
var x = 0;
if (nDataCount == 0) {
x = 0;
} else {
x = 1;
}
for (i = nDataCount; i >= x; i--) {
var p_pc_no = ("p_pc_no[" + i + "]");
var p_pc_no2 = document.getElementById(p_pc_no).value;
var p_tm_name = ("p_tm_name[" + i + "]");
var p_tm_name2 = document.getElementById(p_tm_name).value;
var p_tm_no = ("p_tm_no[" + i + "]");
var p_tm_no2 = document.getElementById("p_tm_no").value;
var p_status = ("p_status[" + i + "]");
var p_status2 = document.getElementById(p_status).value;
var p_hrs_per_week = ("p_hrs_per_week[" + i + "]");
var p_hrs_per_week2 = document.getElementById(p_hrs_per_week).value;
var p_shift = ("p_shift[" + i + "]");
var p_shift2 = document.getElementById(p_shift).value;
var p_open = ("p_open[" + i + "]");
var p_open2 = document.getElementById(p_open).value;
var p_vacant = ("p_vacant[" + i + "]");
var p_vacant2 = document.getElementById(p_vacant).value;
var p_comments = ("p_comments[" + i + "]");
var p_comments2 = document.getElementById(p_comments).value;
var p_delete = ("p_delete[" + i + "]");
var p_delete2 = document.getElementById(p_delete).value;
window.location.href = "https://server.server.com/db/schema.package.p_process2?p_cc_no=" + p_cc_no + "&p_pc_no=" + p_pc_no2 + "&p_tm_name=" + p_tm_name2 + "&p_tm_no=" + p_tm_no2 + "&p_status=" + p_status2 + "&p_hrs_per_week=" + p_hrs_per_week2 + "&p_shift=" + p_shift2 + "&p_open=" + p_open2 + "&p_vacant=" + p_vacant2 + "&p_comments=" + p_comments2 + "&p_delete=" + p_delete2 + "&p_orient=" + p_orient + "&p_ot=" + p_ot + "&p_buy=" + p_buy + "";
}
Try the below code. I am using an AJAX GET request within the loop with request params, so as to not change the interface as much as possible. It uses only plain JS since I am not sure if you have jquery.
The actual changes start from line 48. Of course, I could test this code only in a limited way, so it might have possible bugs (please let me know). Also this can be possibly refined further, but as a quick fix it should do.
A word of caution: This could make a lot of calls in quick succession. So if you have too many loop iterations you might end up bringing down the server. Use wisely! :-) There should be some kind of batching to avoid this, but that will need the call interface to be changed.
Lines 48-61: I am creating a plain JS object out of all your parameters. The key is parameter name, value is the value to be passed.
Line 63: Here I am defining a self-invoking function, which makes the AJAX call in its body. This way, even though AJAX is asynchronous in nature, it will run in sync with the for loop outside.
Line 64-66: I am serializing the object created in the loop, into query parameters.
Lines 68,69: Framing the URL to which request will be made.
Lines 71-77: Actually making the request. This is just boilerplate AJAX-invoking code you can find anywhere (jQuery would've made life so much simpler :-)).
function process_update(){
var nDataCount = document.getElementById("v_nDataCount").value;
var p_cc_no = document.getElementById("p_cc_no").value;
var p_orient = document.getElementById("p_orient").value;
var p_ot = document.getElementById("p_ot").value;
var p_buy = document.getElementById("p_buy").value;
var x = 0;
if (nDataCount == 0) {
x = 0;
} else {
x = 1;
}
for (i = nDataCount; i >= x; i--) {
var p_pc_no = ("p_pc_no[" + i + "]");
var p_pc_no2 = document.getElementById(p_pc_no).value;
var p_tm_name = ("p_tm_name[" + i + "]");
var p_tm_name2 = document.getElementById(p_tm_name).value;
var p_tm_no = ("p_tm_no[" + i + "]");
var p_tm_no2 = document.getElementById("p_tm_no").value;
var p_status = ("p_status[" + i + "]");
var p_status2 = document.getElementById(p_status).value;
var p_hrs_per_week = ("p_hrs_per_week[" + i + "]");
var p_hrs_per_week2 = document.getElementById(p_hrs_per_week).value;
var p_shift = ("p_shift[" + i + "]");
var p_shift2 = document.getElementById(p_shift).value;
var p_open = ("p_open[" + i + "]");
var p_open2 = document.getElementById(p_open).value;
var p_vacant = ("p_vacant[" + i + "]");
var p_vacant2 = document.getElementById(p_vacant).value;
var p_comments = ("p_comments[" + i + "]");
var p_comments2 = document.getElementById(p_comments).value;
var p_delete = ("p_delete[" + i + "]");
var p_delete2 = document.getElementById(p_delete).value;
var dataObj = {p_cc_no:p_cc_no,
p_pc_no:p_pc_no2,
p_tm_name:p_tm_name2,
p_tm_no:p_tm_no2,
p_status:p_status2,
p_hrs_per_week:p_hrs_per_week2,
p_shift:p_shift2,
p_open:p_open2,
p_vacant:p_vacant2,
p_comments:p_comments2,
p_delete:p_delete2,
p_orient:p_orient,
p_ot:p_ot,
p_buy:p_buy};
(function(paramsObj){
var paramsStr = Object.keys(paramsObj).map(function(key) {
return key + '=' + paramsObj[key];
}).join('&');
var url = "https://server.server.com/db/schema.package.p_process2?";
url += paramsStr;
var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
xhr.open('GET', url);
xhr.onreadystatechange = function() {
if (xhr.readyState>3 && xhr.status==200) {/*Handle Call Success*/};
};
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xhr.send();
})(dataObj);
}
}
I'm trying to create a weather app, sending Ajax requests to OpenWeatherMap. I've got an error in w.getWeatherFunc, when I'm giving the function sendRequest the parameter of w.weather and then giving the same parameter to the function displayFunc, which I'm calling next.
Here is what I've got in the console:
Uncaught TypeError: Cannot read property 'weather' of undefined
at displayFunc (weather.js:46)
at weather.js:78
How can I fix this and make it work?
function Weather () {
var w = this;
var weatherUrl = 'http://api.openweathermap.org/data/2.5/weather?';
var appid = '&appid=c0a7816b2acba9dbfb70977a1e537369';
var googleUrl = 'https://maps.googleapis.com/maps/api/geocode/json?address=';
var googleKey = '&key=AIzaSyBHBjF5lDpw2tSXVJ6A1ra-RKT90ek5bvQ';
w.demo = document.getElementById('demo');
w.place = document.getElementById('place');
w.description = document.getElementById('description');
w.temp = document.getElementById('temp');
w.humidity = document.getElementById('humidity');
w.getWeather = document.getElementById('getWeather');
w.addCityBtn = document.getElementById('addCity');
w.rmCityBtn = document.getElementById('rmCity');
w.icon = document.getElementById('icon');
w.wind = document.getElementById('wind');
w.time = document.getElementById('time');
w.lat = null;
w.lon = null;
w.cityArray = [];
w.weather = null;
function sendRequest (url, data) {
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.send();
request.onreadystatechange = function() {
if (request.readyState == 4 && request.status == 200) {
data = JSON.parse(request.responseText);
console.log(data);
return data;
} else {
console.log(request.status + ': ' + request.statusText);
}
}
}
function displayFunc (obj) {
console.log('obj ' + obj);
w.icon.src = 'http://openweathermap.org/img/w/' + obj.weather[0].icon + '.png';
var timeNow = new Date();
var hours = timeNow.getHours();
var minutes = timeNow.getMinutes() < 10 ? '0' + timeNow.getMinutes() : timeNow.getMinutes();
w.time.innerHTML = hours + ':' + minutes;
w.place.innerHTML = 'Place: ' + obj.name;
w.description.innerHTML = "Weather: " + obj.weather[0].description;
w.temp.innerHTML = "Temperature: " + w.convertToCels(obj.main.temp) + "°C";
w.humidity.innerHTML = "Humidity: " + obj.main.humidity + '%';
w.wind.innerHTML = 'Wind: ' + obj.wind.speed + ' meter/sec';
}
w.convertToCels = function(temp) {
var tempC = Math.round(temp - 273.15);
return tempC;
}
w.getWeatherFunc = function() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(location){
w.lat = location.coords.latitude;
w.lon = location.coords.longitude;
var url = weatherUrl + 'lat=' + w.lat + '&lon=' + w.lon + appid;
var result = sendRequest(url, w.weather);
console.log(result);
displayFunc(result);
});
} else {
alert('Browser could not find your current location');
}
}
w.addCityBtn.onclick = function() {
var newCity = prompt('Please insert city', 'Kiev');
var gUrl = googleUrl + newCity + googleKey;
var newCityWeather = null;
sendRequest(url, newCityWeather);
var location = newCityWeather.results[0].geometry.location;
var newUrl = weatherUrl + 'lat=' + location.lat + '&lon=' + location.lng + appid;
sendRequest(newUrl, w.weather);
displayFunc(newCity);
w.cityArray.push(newCity);
}
window.onload = w.getWeatherFunc;
setInterval(function() {
w.getWeatherFunc();
}, 900000);
}
Your ajax return returns into the browsers engine. As its async you need to create a callback:
function sendRequest(url,data,callback){
//if the data was received
callback(data);
}
Use like this
sendRequest("yoururl",data,function(data){
displayFunc(data);
});
The first time you pass the obj to the function it will save it one scope higher. after that, if you don;t pass the object the one you saved earlier will be used.
var objBkp;
function displayFunc (obj) {
if(undefined === obj) obj = objBkp;
else objBkp = obj;
// rest of code here
}
In your sendRequest you are passing only the value of w.weather, not its reference. JavaScript doesn't pass variables by value or by reference, but by sharing. So if you want to give the value to your variable you should do this inside your function sendRequest:
request.onreadystatechange = function() {
if (request.readyState == 4 && request.status == 200) {
w.weather = JSON.parse(request.responseText);
console.log(data);
return data;
} else {
console.log(request.status + ': ' + request.statusText);
}
}
Also, if you are using the attributes, you don't have to pass them in the function as arguments. Besides that fact, it would be good if you also create get() and set()
What does the console.log(result); in getWeatherFunc gives you?
The problem as I see it is that in the displayFunc the parameter passed is undefined.
I want to loop an httprequest every 5 seconds.
Here is my code :
var xmlhttp2 = new XMLHttpRequest();
var url2 = "http:...";
xmlhttp2.onreadystatechange = function() {
if (xmlhttp2.readyState == 4 && xmlhttp2.status == 200) {
var response2 = xmlhttp2.responseText;
var response2 = xmlhttp2.responseText;
var json2 = JSON.parse(response2);
for (var i = 2; i < json2.length; i++){
document.getElementById('table2').innerHTML += '<tr><td>' + json2[i].nm + '</td><td>' + json2[i].id + '</td><td id="uid_'+i+'">' + json2[i].stn + '</td></tr>';
}
}
xmlhttp2.open("GET", url2, true);
xmlhttp2.send();
I tried to put this whole code in a function and called
setInterval(myFunction,5000);
This works. However the table is displaying several times.
I tried
setInterval("xmlhttp2.send();",5000);
and this doesn't work. The request is made only once.
Any advice ?
Thank you
You can clear the table before populating it with the server response
Answer
var xmlhttp2 = new XMLHttpRequest();
var url2 = "http:...";
xmlhttp2.onreadystatechange = function() {
if (xmlhttp2.readyState == 4 && xmlhttp2.status == 200) {
var response2 = xmlhttp2.responseText;
var response2 = xmlhttp2.responseText;
var json2 = JSON.parse(response2);
var table = document.getElementById('table2');
table.innerHTML = '';
for (var i = 2; i < json2.length; i++){
table.innerHTML += '<tr><td>' + json2[i].nm + '</td><td>' + json2[i].id + '</td><td id="uid_'+i+'">' + json2[i].stn + '</td></tr>';
}
}
xmlhttp2.open("GET", url2, true);
xmlhttp2.send();
Use setInterval(myFunction,5000); to make periodic request.
Edited
var xmlhttp2 = new XMLHttpRequest();
var url2 = "http:...";
xmlhttp2.onreadystatechange = function() {
if (xmlhttp2.readyState == 4 && xmlhttp2.status == 200) {
var response2 = xmlhttp2.responseText;
var response2 = xmlhttp2.responseText;
var json2 = JSON.parse(response2);
var tableBody = document.getElementById('table2Body');
tableBody.innerHTML = '';
for (var i = 2; i < json2.length; i++){
tableBody.innerHTML += '<tr><td>' + json2[i].nm + '</td><td>' + json2[i].id + '</td><td id="uid_'+i+'">' + json2[i].stn + '</td></tr>';
}
}
xmlhttp2.open("GET", url2, true);
xmlhttp2.send();