Select option issue - javascript

I created a small code that for some strange reason it works badly.
With the first var declare variables, but it is just to let you see for what they are, aren't declared there. Opt is an array containing all the values ​​read from a file, alunno is a select , and trovata it's a counter that tells me how many rows there are.
Everything so far works fine, but in the while loop, where am I going to perform the adding in the select if I have for example two values ​​to be loaded, the first option is replaced with the second so instead of finding myself:
John, Antoine in the select, I find:
Antoine, Antoine.
Which is quite strange considering that John is added initially, but then is replaced by the last value.
What's wrong with this code?
var opt, elaborazione;
var alunno = document.getElementById('alunno');
var trovata = 0;
while(true)
{
opt = new Option();
elaborazione = v[count].split(";");
elaborazione = elaborazione.slice(0,2);
elaborazione = elaborazione.join(" ");
opt.text = elaborazione;
alunno.add(opt);
trovata--;
if(trovata == 0){break;}
}
more details:
while(!flow.AtEndOfStream)
{
var lettura = flow.ReadLine();
opts = lettura.split(';');
count++;
v[count] = lettura;
}

You are not changing count in the loop:
while(true)
{
opt = new Option();
elaborazione = v[count].split(";"); //The count is the same here
//...
trovata--;
if(trovata == 0){break;}
}
Thus you always use the last item of v, which is always the same.

Related

createElement creates infinite loop

I'm really new to javascript, and coding in general, and I can't understand why this causes an infinite loop:
let newTr = document.createElement('tr');
If I take it out, the webpage loads fine, but if I leave it in, the webpage never fully loads and my browser uses 50% of my CPU.
Here's the rest of my code:
// client-side js
// run by the browser each time your view template referencing it is loaded
console.log('hello world :o');
let arrPfcCases = [];
// define variables that reference elements on our page
const tablePfcCases = document.getElementById("tablePfcCases");
const formNewPfcCase = document.forms[0];
const caseTitle = formNewPfcCase.elements['caseTitle'];
const caseMOI = formNewPfcCase.elements['caseMOI'];
const caseInjuries = formNewPfcCase.elements['caseInjuries'];
// a helper function to call when our request for case is done
const getPfcCaseListener = function() {
// parse our response to convert to JSON
arrPfcCases = JSON.parse(this.responseText);
// iterate through every case and add it to our page
for (var i = 0; i = arrPfcCases.length-1;i++) {
appendNewCase(arrPfcCases[i]);
};
}
// request the dreams from our app's sqlite database
const pfcCaseRequest = new XMLHttpRequest();
pfcCaseRequest.onload = getPfcCaseListener;
pfcCaseRequest.open('get', '/getDreams');
pfcCaseRequest.send();
// a helper function that creates a list item for a given dream
const appendNewCase = function(pfcCase) {
if (pfcCase != null) {
tablePfcCases.insertRow();
let newTr = document.createElement('tr');
for (var i = 0; i = pfcCase.length - 1; i++) {
let newTd = document.createElement('td');
let newText = document.createTextNode(i.value);
console.log(i.value);
newTd.appendChild(newText);
newTr.appendChild(newTd);
}
tablePfcCases.appendChild(newTr);
}
}
// listen for the form to be submitted and add a new dream when it is
formNewPfcCase.onsubmit = function(event) {
// stop our form submission from refreshing the page
event.preventDefault();
let newPfcCase = [caseTitle, caseMOI, caseInjuries];
// get dream value and add it to the list
arrPfcCases.push(newPfcCase);
appendNewCase(newPfcCase);
// reset form
formNewPfcCase.reset;
};
Thanks!
P.S. There are probably a ton of other things wrong with the code, I just can't do anything else until I figure this out!
As an explanation, in your code
i = pfcCase.length - 1
assigned the value of pfcCase.length - 1 to i. The syntax of that part of the loop should be
an expression to be evaluated before each loop iteration. If this expression evaluates to true, statement is executed.
The evaluation of your code made no sense.
Evaluating
i < pfCase.length
before each iteration to check that the current index is less than the length of the array, however, works correctly.
Here is no conditional statement here. In this statement you are assigning pfcCase length minus 1 to the I variable.
for (var i = 0; i = pfcCase.length - 1; i++) {
You have to compare the i variable to the length of the pfcCase minus 1.
This should work.
for (var i = 0; i < pfcCase.length - 1; i++) {
noticed something else
This line does not do what you think it dose.
let newText = document.createTextNode(i.value);
i is just the index i.e. a number. It does not have the value property.
This is what you are looking to do.
let newText = document.createTextNode(pfcCase[i].value);
my preference (forEach)
I prefer using the array forEach method. It’s cleaner and less prone to mistakes.
pfcCase.forEach( function(val){
let newTd = document.createElement('td');
let newText = document.createTextNode(val.value);
console.log('The array element is. '. val.value, ' The value is. ', val.value);
newTd.appendChild(newText);
newTr.appendChild(newTd);
});

Why is this JavaScript looping twice in Zapier?

Here is a video that shows what I'm struggling with.
Here is a high level description of the process, followed by the actual JavaScript code I've written.
PROCESS
I built 2 Zaps that each run like this:
STEP 1 - Trigger (Cognito Form, which has repeating sections)
STEP 2 - JavaScript Code (which creates an Array of the form fields for ONE of the repeating sections, and separates them into individual strings using .split)
STEP 3 - Action (creates a ZOHO CRM Task for each string)
The first Zap runs on one of the sections of the form (Visits with Sales), and the second zap runs on a different section of the form (Visits without Sales). Each of these Zaps works fine on their own so I know the code is good, but I want to combine the two Zaps into one by combining the code.
I tried to combine by making five steps:
Trigger - Code1 - Zoho1 - Code2 - Zoho2
but the Zoho2 Tasks were each repeated
I then tried to re-order the five steps:
Trigger - Code1 - Code2 - Zoho1 - Zoho2
but now Zoho1 Tasks AND Zoho2 tasks were duplicated.
Finally I tried to combine ALL the JavaScript code into one:
Tigger - CombinedCode1+2 - Zoho 1 - Zoho2
but only the strings from Arrays in "Code2" are available to me when I go to map them in Zoho1.
CODE:
if (inputData.stringVSAccount == null) {
var listVSAccountArray = [];
var listVSUnitsArray = [];
var listVSPriceArray = [];
var listVSNotesArray = [];
var listVSVisitCallArray = [];
} else {
var listVSAccountArray = inputData.stringVSAccount.split(",");
var listVSUnitsArray = inputData.stringVSUnits.split(",");
var listVSPriceArray = inputData.stringVSPrice.split(",");
var listVSNotesArray = inputData.stringVSNotes.split(",");
var listVSVisitCallArray = inputData.stringVSVisitCall.split(",");
}
var output = [];
var arrayNos = listVSAccountArray.length;
var i = 0;
do {
var thisItemVSAccount = new String(listVSAccountArray[i]);
var thisItemVSUnits = new String(listVSUnitsArray[i]);
var thisItemVSPrice = new String(listVSPriceArray[i]);
var thisItemVSNotes = new String(listVSNotesArray[i]);
var thisItemVSVisitCall = new String(listVSVisitCallArray[i]);
var thisItemObj = {};
thisItemObj.itemVSAccount = thisItemVSAccount;
thisItemObj.itemVSUnits = thisItemVSUnits;
thisItemObj.itemVSPrice = thisItemVSPrice;
thisItemObj.itemVSNotes = thisItemVSNotes;
thisItemObj.itemVSVisitCall = thisItemVSVisitCall;
output.push({ thisItemObj });
i++;
} while (i < arrayNos);
//This is where the second zaps code is pasted in the combined version
if (inputData.stringOVAccount == null) {
var listOVAccountArray = [];
var listOVNotesArray = [];
var listOVVisitCallArray = [];
} else {
var listOVAccountArray = inputData.stringOVAccount.split(",");
var listOVNotesArray = inputData.stringOVNotes.split(",");
var listOVVisitCallArray = inputData.stringOVVisitCall.split(",");
}
var output = [];
var arrayNos = listOVAccountArray.length;
var i = 0;
do {
var thisItemOVAccount = new String(listOVAccountArray[i]);
var thisItemOVNotes = new String(listOVNotesArray[i]);
var thisItemOVVisitCall = new String(listOVVisitCallArray[i]);
var thisItemObj = {};
thisItemObj.itemOVAccount = thisItemOVAccount;
thisItemObj.itemOVNotes = thisItemOVNotes;
thisItemObj.itemOVVisitCall = thisItemOVVisitCall;
output.push({ thisItemObj });
i++;
} while (i < arrayNos);
I just started learning JavaScript this week, and sense that I am missing something obvious, perhaps a set of brackets. Thanks for any assistance
David here, from the Zapier Platform team. You're running into a confusing and largely undocumented feature where items after a code step run for each item returned. This is usually desired behavior - when you return 3 submissions you want to create 3 records.
In your case, it's also running subsequent unrelated actions multiple times, which sounds like it's undesired. In that case, it might be easier to have 2 zaps. Or, if "Zoho2" only ever happens once, put it first and let the branch happen downstream.
Separately, I've got some unsolicited javascript advice (since you mentioned you're a beginner). Check out Array.forEach (docs), which will let you iterate through arrays without having to manage as many variables (your own i every time). Also, try to use let and const over var when possible - it keeps your variables scoped as small as possible so you don't accidentally leak values into other areas.
​Let me know if you've got any other questions!
Just a note - you are declaring the same array variable output in both segments of your code block - the second declaration will be ignored.
Use the .forEach() method to iterate over your arrays, it will significantly cleanup you code. You also don't need to painstakingly construct the objects to be pushed into the output arrays.
This may not fix your issue but the code is far easier on the eye.
var listVSAccountArray = [],
listVSUnitsArray = [],
listVSPriceArray = [],
listVSNotesArray = [],
listVSVisitCallArray = [],
output = [];
if (typeof inputData.stringVSAccount === 'string') {
listVSAccountArray = inputData.stringVSAccount.split(',');
listVSUnitsArray = inputData.stringVSUnits.split(',');
listVSPriceArray = inputData.stringVSPrice.split(',');
listVSNotesArray = inputData.stringVSNotes.split(',');
listVSVisitCallArray = inputData.stringVSVisitCall.split(',');
}
// iterate over the array using forEach()
listVSAccountArray.forEach(function(elem, index){
// elem is listVSAccountArray[index]
output.push({
itemVSAccount: elem,
itemVSUnits: listVSUnitsArray[index],
itemVSPrice: listVSPriceArray[index],
itemVSNotes: listVSNotesArray[index],
itemVSVisitCall: listVSVisitCallArray[index]
})
})
//This is where the second zaps code is pasted in the combined version
var listOVAccountArray = [],
listOVNotesArray = [],
listOVVisitCallArray = [],
output_two = []; // changed the name of the second output array
if (typeof inputData.stringOVAccount === 'string') {
listOVAccountArray = inputData.stringOVAccount.split(',');
listOVNotesArray = inputData.stringOVNotes.split(',');
listOVVisitCallArray = inputData.stringOVVisitCall.split(',');
}
// iterate over the array using forEach()
listOVAccountArray.forEach(function(elem, index){
// elem is listOVAccountArray[index]
output_two.push({
itemOVAccount: elem,
itemOVNotes: listOVNotesArray[index],
itemOVVisitCall: listOVVisitCallArray[index]
});
});

TypeError: 'undefined' is not an object in Javascript

I have a piece of Javascript code that assigns string of values to a string array.
Unfortunately if I try to add more than one string to the array, my UI simulator(which runs on JS code) closes unexpectedly. I have tried debugging but I cannot find anything. I am attaching that piece of code where the issue is. may be you guys could find some flaw? On the pop up button click the values I selcted on the UI should get stored in the array and I have a corressponding variable on the server side to handle this string array.
_popupButtonClick: function (button) {
var solutions = this._stateModel.get('solutionName');
var i;
var solutionsLength = solutions.length;
var selectedSolution = [solutionsLength];
this.clearPopupTimer();
if (button.position === StatusViewModel.ResponseType.Ok) {
for(i=0;i<solutionsLength;i++)
{
if(this._list.listItems[i].selected)
{
selectedSolution[i] = this._list.listItems[i].options.value;
}
}
this._stateModel.save({
selectedsolutions: selectedSolution,
viewResponse: StatusViewModel.ResponseType.Ok
});
} else {
this._stateModel.save({
viewResponse: StatusViewModel.ResponseType.Cancel
});
}
}
Change
var selectedSolution = [solutionsLength];
to
var selectedSolution = [];
This makes your array have an extra item that might be causing a crash.
Also,
you have an
if(this._list.listItems[i].selected)
{
selectedSolution[i] = this._list.listItems[i].options.value;
}
But no corresponding else, so your array has undefined values for i which are not entering the if.
Maybe adding an empty string might solve it:
if(this._list.listItems[i].selected)
{
selectedSolution[i] = this._list.listItems[i].options.value;
}
else
{
selectedSolution[i] = "";
}
The code is looking fine but there seems to be a piece of code which can cause error. For example, you are assigning var selectedSolution = [solutionsLength]; and for example solutionsLength is 5 then your loop runs for 5 times
for(i=0;i<solutionsLength;i++) // runs for 5 times
{
if(this._list.listItems[i].selected)
{
// but selectedSolution = [5]; which is on 0th index and from 1st to 4th index it is undefined
selectedSolution[i] = this._list.listItems[i].options.value;
}
}
So you can try to use push() like
selectedSolution.push(this._list.listItems[i].options.value);
and on initialization change it like,
var selectedSolution = [];
Hopefully this will solve your problem.
var selectedSolution = [solutionsLength];
keeps the value in the selectedSolution variable.
var selectedSolution = [3];
selectedSolution[0] gives the values as 3
So make it simple
var selectedSolution = [];

JavaScript stop referencing object after pass it to a function

I know JavaScript passes Objects by reference and thus I'm having a lot of trouble with the following code:
function doGradeAssignmentContent(dtos) {
var x = 5;
var allPages = [];
var stage = new App.UI.PopUpDisplay.PopUpStageAssignmentGrader(null, that);// pass launch element
for(var i = 0; i < dtos[0].result.students.length; ++i) {
var pagesSet = [];
for(var j = 0; j < dtos[0].result.questions.length; ++j) {
var questionObject = jQuery.extend(true, {}, new Object());
questionObject = dtos[0].result.questions[j];
if(dtos[0].result.students[i].answers[j].assignmentQuestionId === questionObject.questionId) {// expected, if not here something is wrong
questionObject.answer = dtos[0].result.students[i].answers[j].studentAnswer;
questionObject.pointsReceived = dtos[0].result.students[i].answers[j].pointsReceived;
} else {
var theAnswer = findAssociatedStudentAnswer(questionObject.questionId, dtos[0].result.students[i].answers[j]);
if(theAnswer !== null) {
questionObject.answer = theAnswer.studentAnswer;
questionObject.pointsReceived = theAnswer.pointsReceived;
} else {
alert("Unexpected error. Please refresh and try again.");
}
}
pagesSet[pagesSet.length] = new App.UI.PopUpDisplay.StageAssignmentGradingPages[dtos[0].result.questions[j].questionType.charAt(0).toUpperCase() + dtos[0].result.questions[j].questionType.slice(1) + "QuestionAssignmentGradingPage"](j + 1, questionObject);
}
var studentInfo = {};
studentInfo.avatar = dtos[0].result.students[i].avatar;
studentInfo.displayName = dtos[0].result.students[i].displayName;
stage.addPageSet(pagesSet, studentInfo);
}
stage.launch();
}
First let me show you what the result (dtos) looks like so you can better understand how this function is parsing it:
The result (dtos) is an Object and looks something like:
dtos Array
dtos[0], static always here
dtos[0].result, static always here
dtos[0].questions Array
dtos[0].questions.index0 - indexN. This describes our Questions, each one is an Object
dtos[0].students Array
dtos[0].students[0]-[n].answers Array. Each student array/Object has an Answers array. Each student will have as many elements in this answers Array that there were questions in dtos[0].questions. Each element is an Object
Now what we do in this here is create this Object stage. Important things here are it has an array called "this.studentsPages". This array will ultimately have as many entries as there were students in dtos[0].students.
So we loop through this for loop disecting the dtos array and creating a pagesSet array. Here comes my problem. On the first iteration through the for loop I create this questionObject element. I also have tried just doing var questionObject = {}, but what you see now was just an attempt to fix the problem I was seeing, but it didn't work either.
So at the end of the first iteration of the outer for loop I call stage.addPageSet, this is what happens here:
var pageObject = [];
pageObject["questions"] = pageSet;
pageObject["displayName"] = studentInfo.displayName;
this.studentsPages[this.studentsPages.length] = pageObject;
if(this.studentsPages.length === 1) {// first time only
for(var i = 0; i < pageSet.length; ++i) {
this.addPage(pageSet[i]);
}
}
The important thing to take notice of here is where I add pageObject on to this.studentsPages which was an empty array before the first call. pageObject now has pageSet plus a little bit more information. Remember, pageSet was an Object and thus passed by reference.
On the next iteration of the for loop, when I hit this line:
questionObject.answer = dtos[0].result.students[i].answers[j].studentAnswer;
It goes wrong. This changes the local copy of questionObject, BUT it also changes the copy of questionObjec that was passed to addPageSet and added to the studentsPages array in the first iteration. So, if I only had 2 students coming in, then when all is said and done, studentsPages hold 2 identical Objects. This should not be true.
The problem is questionObject in the doGradeAssignmentContent function is keeping a reference to the Object created on the previous iteration and then overrides it on all subsequent iterations.
What can I do to fix this?
Thanks for the help!
With out having looked at it too closely I believe you need to change the following:
// Before:
var questionObject = jQuery.extend(true, {}, new Object());
questionObject = dtos[0].result.questions[j];
// After:
var questionObject = jQuery.extend(true, {}, dtos[0].result.questions[j]);
I didn't look too closely if there are other instances in the code where this needs to be applied, but the core concept is to utilize jQuery's deep copy to generate a duplicate of the object you do not wish to retain a reference to.

Looping over array and comparing to regex

So, I'll admit to being a bit of a JS noob, but as far as I can tell, this should be working and it is not.
Background:
I have a form with 3 list boxes. The list boxes are named app1, db1, and db2. I'm using javascript to allow the user to add additional list boxes, increasing the name tag for each additional select box.
When I add additional app named boxes, the value increments properly for each additional field. If I try to add addtional db named selects, it fails to recognize the 2nd tag on the first loop through the array. This causes me to end up with 2 elements named db2. On each subsequent tag, it is recognized properly and is properly incremented.
Here is the HTML for the db1 tag:
<select name="db1">
*options*
</select>
And db2:
<select name="db2">
*options*
</select>
The tags are identical. Here is the function that I am using to figure out the next number in the sequence (note: tag is either app or db, tags is an array of all select tag names in the DOM, if I inspect tags, it gives me ['app1', 'db1', 'db2', '']):
function return_select_name(tag, tags) {
matches = new Array();
var re = new RegExp(tag + "\\d+", "g");
for (var i = 0; i < tags.length; i++) {
var found = re.exec(tags[i]);
if (found != null) {
matches.push(found[0]);
}
}
matches = matches.sort();
index = parseInt(/\d+/.exec(matches.last())) + 1;
index = tag + index;
return index;
}
If I add an app tag, it will return 'app2'. If I search for a db tag, it will return 'db2' on the first time through, db3 on the 2nd, etc, etc.
So basically, I'm sure I'm doing something wrong here.
I'd handle it by keeping a counter for db and a counter for app to use to generate the names.
var appCounter = 1;//set this manually or initialize to 0 and
var dbCounter = 2;//use your create function to add your elements on pageload
Then, when you go to create your next tag, just increment your counter and use that as the suffix for your name:
var newAppElement = document.createElement('select');
newAppElement.name = 'app' + (++appCounter);
..
// --OR for the db element--
var newDbElement = document.createElement('select');
newDbElement.name = 'db' + (++dbCounter );
..
The problem you are getting is that regex objects are stateful. You can fix your program by putting the regex creation inside the loop.
function return_select_name(tag, tags) {
matches = new Array();
// <-- regex was here
for (var i = 0; i < tags.length; i++) {
var re = new RegExp(tag + "\\d+", "g"); //<--- now is here
var found = re.exec(tags[i]);
if (found != null) {
matches.push(found[0]);
}
}
matches = matches.sort();
index = parseInt(/\d+/.exec(matches[matches.length-1])) + 1; //<--- I dont think matches.last is portable, btw
index = tag + index;
return index;
}
In any case, if I were to do this myself, I would probably prefer to avoid the cmplicated text matching and just store the next tag indices in a variable or hash map.
Another suggestion: if you put parenthesis in your regex:
// /tag(\d+)/
var re = new RegExp(tag + "(\\d+)", "g");
Then you can use found[1] to get your number directly, without the extra step afterwards.
I know this has already been answered, but I put this together as a proof of concept.
http://jsfiddle.net/zero21xxx/LzyTf/
It's an object so you could probably reuse it in different scenarios. Obviously there are ways it could be improved, but I thought it was cool so I thought I would share.
The console.debug only works in Chrome and maybe FF.

Categories

Resources