JSON-array and forEach issue - javascript

So... The problem I have according to the console is:
"Uncaught TypeError: Cannot read property 'title' of undefined
at custom.js:42, at Array.forEach (), at custom.js:39"
How is "title" undefined? What's wrong with my .forEach? (sad noises)
Example of first of six objects in the JSON-array I've built:
var newReleases = [
{
"title":"Honor - Defending the motherland",
"author":"Mark Thomas",
"genre":"Fiction",
"description":"In legislation and formal documents the suffix shire was generally not used: for example, Bedfordshire was referred to as the administrative county of Bedford and the Northamptonshire council as the county council of Northampton.The 1888 Act did not contain a list of administrative counties: it was not until 1933 and the passing of a new Local Government Act."},
For loop with forEach function:
for (var i = 0; i < 6; i++){
newReleases.forEach (function (newReleases) {
var bookTitle = document.getElementsByClassName('card-header')
var t = document.createTextNode(newReleases[i].title);
bookTitle.appendChild(t);
var bookAuthor = document.getElementsByClassName('card-title')
var a = document.createTextNode(newReleases[i].authors);
bookAuthor.appendChild(a);
var cardGenre = document.getElementsByClassName("card-subtitle");
var genre = document.createTextNode(newReleases[i].genre);
cardGenre.appendChild(genre);
var cardDescr = document.getElementsByClassName('card-text');
var p = document.createTextNode(newReleases[i].description);
cardDescr.appendChild(p);
}) //end of forEach
} // end of for-loop

Use either for or forEach(), not both.
for (var i = 0; i < newReleases.length; i++) {
var bookTitle = document.getElementsByClassName('card-header')[0]
var t = document.createTextNode(newReleases[i].title);
bookTitle.appendChild(t);
var bookAuthor = document.getElementsByClassName('card-title')[0]
var a = document.createTextNode(newReleases[i].authors);
bookAuthor.appendChild(a);
var cardGenre = document.getElementsByClassName("card-subtitle")[0];
var genre = document.createTextNode(newReleases[i].genre);
cardGenre.appendChild(genre);
var cardDescr = document.getElementsByClassName('card-text')[0];
var p = document.createTextNode(newReleases[i].description);
cardDescr.appendChild(p);
}
or
newReleases.forEach(function(release) {
var bookTitle = document.getElementsByClassName('card-header')[0]
var t = document.createTextNode(release.title);
bookTitle.appendChild(t);
var bookAuthor = document.getElementsByClassName('card-title')[0]
var a = document.createTextNode(release.authors);
bookAuthor.appendChild(a);
var cardGenre = document.getElementsByClassName("card-subtitle")[0];
var genre = document.createTextNode(release.genre);
cardGenre.appendChild(genre);
var cardDescr = document.getElementsByClassName('card-text')[0];
var p = document.createTextNode(release.description);
cardDescr.appendChild(p);
});
When you use forEach() you don't need to subscript the array variable, you just use the parameter to the callback function.

Related

Reading values from input fields created in an array with document.createElement()

I'm trying to build a table that the user can hit "new line" to create a new row of the table. I do this by foo.push(document.createElement("INPUT"));
function newLine() {
sArr.push(document.createElement("INPUT"));
sArr[sArr.length-1].setAttribute("type", "text");
document.body.appendChild(sArr[sArr.length-1]);
gArr.push(document.createElement("INPUT"));
gArr[gArr.length-1].setAttribute("type", "text");
document.body.appendChild(gArr[gArr.length-1]);
tArr.push(document.createElement("INPUT"));
tArr[tArr.length-1].setAttribute("type", "text");
document.body.appendChild(tArr[tArr.length-1]);
//alert(sArr.length+", "+gArr.length+", "+tArr.length);
var x = document.createElement("br");
document.body.appendChild(x);
}
function calc(){
var temp = 0;
var total = 0;
for(i = 0; i<sArr.length; i++){
total = total + calc2(i);
}
var o = document.getElementById("output");
o.value = total;
}
function calc2(i){
alert(i);
var s = document.getElementById(sArr[i]);
var g = document.getElementById(gArr[i]);
var t = document.getElementById(tArr[i]);
var VO2walkmin = 3.28;
var VO2rest = 3.05;
var C1 = 0.32;
var C2 = 0.19;
var C3 = 2.66;
var Cdecline = 0.73;
var s2 = s.value;
var g2 = g.value;
var t2 = t.value;
var negGrade = g.value;
if(g2 < 0){g2 = 0};
VO2move = ((C1 * g2)+VO2walkmin)+((1+(C2*g2))*(C3*(s2^2)));
VO2inc = VO2rest+(t2*VO2move);
VO2dec = VO2rest+(Cdecline*(t2*VO2move))
//var o = document.getElementById("output");
return VO2inc;
}
When run, I get the error:
Uncaught TypeError: Cannot read property 'value' of null
from line 66. Specifically, this line:
var s2 = s.value;
I'm struggling to find my mistake here... and all help is appreciated.
You create a new element, but it has no ID. And so you can't fetch it by ID. The result of document.getElementById(sArr[i]) will be null.
Check this answer to see how ID can be assigned to a newly created element:
Create element with ID
There's no need to use document.getElementById. sArr[i] is the input element itself, not its ID, so you can just read its value directly.
var s = sArr[i];
var g = gArr[i];
var t = tArr[i];

TypeError: Cannot read property "length" from undefined variables

I have worked with code that pulls table information off a site and then places into Google Sheets. While this had worked great for months, it has come to my attention that is has randomly stopped working.
I am getting the message "TypeError: Cannot read property "length" from undefined." From code:
for (var c=0; c<current_adds_array.length; c++) {
I have done extensive searching but cannot come to conclusion as to what is wrong.
Full code seen here:
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Get Data')
.addItem('Add new dispatch items','addNewThings')
.addToUi();
}
function addNewThings() {
// get page
var html = UrlFetchApp.fetch("#").getContentText();
// bypass google's new XmlService because html isn't well-formed
var doc = Xml.parse(html, true);
var bodyHtml = doc.html.body.toXmlString();
// but still use XmlService so we can use getDescendants() and getChild(), etc.
// see: https://developers.google.com/apps-script/reference/xml-service/
doc = XmlService.parse(bodyHtml);
var html = doc.getRootElement();
// a way to dig around
// Logger.log(doc.getRootElement().getChild('form').getChildren('table'));
// find and dig into table using getElementById and getElementsByTagName (by class fails)
var tablecontents = getElementById(html, 'formId:tableExUpdateId');
// we could dig deeper by tag name (next two lines)
// var tbodycontents = getElementsByTagName(tablecontents, 'tbody');
// var trcontents = getElementsByTagName(tbodycontents, 'tr');
// or just get it directly, since we know it's immediate children
var trcontents = tablecontents.getChild('tbody').getChildren('tr');
// create a nice little array to pass
var current_adds_array = Array();
// now let's iterate through them
for (var i=0; i<trcontents.length; i++) {
//Logger.log(trcontents[i].getDescendants());
// and grab all the spans
var trcontentsspan = getElementsByTagName(trcontents[i], 'span');
// if there's as many as expected, let's get values
if (trcontentsspan.length > 5) {
var call_num = trcontentsspan[0].getValue();
var call_time = trcontentsspan[1].getValue();
var rptd_location = trcontentsspan[2].getValue();
var rptd_district = trcontentsspan[3].getValue();
var call_nature = trcontentsspan[4].getValue();
var call_status = trcontentsspan[5].getValue();
//saveRow(call_num, call_time, rptd_location, rptd_district, call_nature, call_status);
current_adds_array.push(Array(call_num, call_time, rptd_location, rptd_district, call_nature, call_status));
}
}
saveRow(current_adds_array);
}
//doGet();
function saveRow(current_adds_array) {
// load in sheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
// find the current last row to make data range
var current_last_row = sheet.getLastRow();
var current_last_row_begin = current_last_row - 50;
if (current_last_row_begin < 1) current_last_row_begin = 1;
if (current_last_row < 1) current_last_row = 1;
//Logger.log("A"+current_last_row_begin+":F"+current_last_row);
var last_x_rows = sheet.getRange("A"+current_last_row_begin+":F"+current_last_row).getValues();
var call_num, call_time, rptd_location, rptd_district, call_nature, call_status;
// iterate through the current adds array
for (var c=0; c<current_adds_array.length; c++) {
call_num = current_adds_array[c][0];
call_time = current_adds_array[c][1];
rptd_location = current_adds_array[c][2];
rptd_district = current_adds_array[c][3];
call_nature = current_adds_array[c][4];
call_status = current_adds_array[c][5];
// find out if the ID is already there
var is_in_spreadsheet = false;
for (var i=0; i<last_x_rows.length; i++) {
//Logger.log(call_num+" == "+last_15_rows[i][0]);
if (call_num == last_x_rows[i][0] && call_time != last_x_rows[i][1]) is_in_spreadsheet = true;
}
Logger.log(is_in_spreadsheet);
//Logger.log(last_15_rows.length);
if (!is_in_spreadsheet) {
Logger.log("Adding "+call_num);
sheet.appendRow([call_num,call_time,rptd_location,rptd_district,call_nature,call_status]);
}
}
}
function getElementById(element, idToFind) {
var descendants = element.getDescendants();
for(i in descendants) {
var elt = descendants[i].asElement();
if( elt !=null) {
var id = elt.getAttribute('id');
if( id !=null && id.getValue()== idToFind) return elt;
}
}
}
function clearRange() {
//replace 'Sheet1' with your actual sheet name
var sheet = SpreadsheetApp.getActive().getSheetByName('Sheet1');
sheet.getRange('A2:F').clearContent();}
function getElementsByTagName(element, tagName) {
var data = [];
var descendants = element.getDescendants();
for(i in descendants) {
var elt = descendants[i].asElement();
if( elt !=null && elt.getName()== tagName) data.push(elt);
}
return data;
}
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getRange("C:C");
range.setValues(range.getValues().map(function(row) {
return [row[0].replace(/MKE$/, " Milwaukee, Wisconsin")];
}));
Please be careful when instantiating a new array. You are currently using var current_adds_array = Array(). You're not only missing the new keyword, but also, this constructor is intended to instantiate an Array with an Array-like object.
Try changing this to var current_adds_array = []

Nested Loop Javascript

can someone please let me know, whats wrong with the format of my nested loop. i dont seem to be getting it to loop correctly. the values that are the same are not being generated together.
for (var field in Itemlist) {
for (var field in EstItems){
console.log(Itemlist[field].item_id, EstItems[field].zoho_id);
if (EstItems[field].zoho_id == Itemlist[field].item_id) {
console.log("We are In");
var id = EstItems[field].itemID;
var itemID = EstItems[field].zoho_id;
var barcode = EstItems[field].barcode;
//var EstBarcode = EstItems[field].itemID;
var description = EstItems[field].description;
var cost = EstItems[field].cost;
var shippingCost = "500";
var clearingCharges = "";
var quantityOrdered = 1;
//var quantityRecvd = EstItems[field].itemID;
//var quantityRTD = EstItems[field].itemID;
var selected = 0;
var totalcost = (cost*quantityOrdered)+parseFloat(shippingCost);
var categoryID = 0;
}
}
}
You have a scope problem introduced by overwriting a previous variable.
for (var field in Itemlist) {
// `field` here is a property from ItemList
for (var field in EstItems){
// `field` here is a property from EstItems
// Any attempt to access the `field` var from the outer loop will fail, as it has been overwritten.
}
}
Rename field for either loop.

how to retrieve object from sqLite query? having problems

I am querying a local database and trying to retrieve my data in a form of array of objects to be able to manipulate them in another stage.
Below is my code and the scope I can access my object in and where I fail to access the object.
function setStageOneup(){
var teams = localStorage.teamsUp;
var tournament_id = 1;
var statement = "SELECT * FROM teams WHERE t_id= '"+tournament_id+"';";
localStorage.teamsUp = "";
var team_array = {};
var myTest = callBack(function(val){
var team = {};
for(var i = 0; i < val.rows.length; i++)
{
// teams_array[i]['id'] = val.rows.item(i).id
//console.log(val.rows.item(i).text)
team.id = val.rows.item(i).id;
team.t_id = val.rows.item(i).t_id;
team.m_t_id = val.rows.item(i).m_t_id;
team.name = val.rows.item(i).name;
team.weight = val.rows.item(i).weight;
team.goals = val.rows.item(i).goals;
team.win = val.rows.item(i).win;
team.draw = val.rows.item(i).draw;
team.lost = val.rows.item(i).lost;
team.misc = val.rows.item(i).misc;
team_array[i] = team;
console.log(team); // I am able to hee the output here
}
console.log(team_array); // I am able to hee the output here
},statement);
console.log(team_array); // I am unable to see here even though the variable is decleared in this scope
}
Thank you, if I missed anything please let me know.

Get Unique values during Loop

I am looping through an array and getting the data that I need.
for (var i = 0; i < finalArray.length; i++) {
var merchName = finalArray[i].merchName;
var amName = finalArray[i].amName;
var amEmail = finalArray[i].amEmail;
var txnID = finalArray[i].transID;
var transAccount = finalArray[i].transAccount;
}
What I am trying to do at this point is only show unique data in the loop.
For example var transAccount could be in the array 5 times. I only one to display that in my table once. How can I go about accomplishing this ?
Final Array is constructed like so; just as an object:
finalArray.push({
transID: tmpTrans,
transAccount: tmpAccount,
amEmail: amEmail,
merchName: merchName,
amPhone: amPhone,
amName: amName
});
var allTransAccount = {};
for (var i = 0; i < finalArray.length; i++) {
var merchName = finalArray[i].merchName;
var amName = finalArray[i].amName;
var amEmail = finalArray[i].amEmail;
var txnID = finalArray[i].transID;
var transAccount = finalArray[i].transAccount;
if(allTransAccount[finalArray[i].transAccount]) {
var transAccount = '';
}
else {
allTransAccount[transAccount] = true;
}
}
var merhcData = {};
var amName = {};
// and so on
for (var i = 0; i < finalArray.length; i++) {
merchData[finalArray[i].merchName] = finalArray[i].merchName;
amName[finalArray[i].amName] = finalArray[i].amName;
// and so on
}
If you are sure, that data in merchName will never be equal amName or other field - you can use one data object instead of several (merchData, amName...)
What you want is likely a Set. (see zakas for ES6 implementation. To emulate this using javascript, you could use an object with the key as one of your properties (account would be a good bet, as aperl said) which you test before using your raw array.
var theSet={};
for (var i = 0; i < finalArray.length; i++) {
var transAccount = finalArray[i].transAccount;
var merchName = finalArray[i].merchName;
var amName = finalArray[i].amName;
var amEmail = finalArray[i].amEmail;
var txnID = finalArray[i].transID;
if(!theSet[transAccount]){
//add to your table
theSet[transAccount]===true;
}
This will prevent entries of duplicate data.

Categories

Resources