stop ForEach loop from running code 5 times per item - javascript

I would like my code to insert 1 document per every item in the loop, however it keeps inserting 5 of each one. I've been at this for hours and it's 3:41am, please help.
The code is cluttered so simply put, the loop will scan a list of categories and use the index of that category to extract other data that goes with it like how many points the person made in that category, on what day, etc.
I am using nodejs and what you will see below is a method on one of my Schema's that I called in my router.js file.
Yes, I have read over 15 question here I thought might help but not in the coding language I'm using and not with the exact issue.
The for loop build the point object which I'm trying to save in the student's profile.
//the for loop should build something like this
{ date: '9/13/2017',
category:"Participation",
specification:"Pitchball Game",
points:150
}
Js file:
StudentSchema.statics.givePoints = function (pt_obj, cb){
var leng =pt_obj.category.length;
var i=0;
var rsc = 'r' + pt_obj.room + '-' + pt_obj.seat;
Student.findOne( {rscombo: rsc }, function (err, student){
if ( err || !student){
console.log('not a student');
}
else{
pt_obj.category.forEach(function( cat, ind){
if(cat != '' && cat != null && cat != undefined && cat != '--select--'){
var pts = Number(pt_obj.pts[ind]);
student.points.push({ date: pt_obj.date[ind], category: cat, specification : pt_obj.specification[ind], points:Number(pt_obj.pts[ind]), sysdate:pt_obj.date[ind] });
if(cat != 'Purchase'){
ptMonth = Number(pt_obj.date[ind].slice( 0, pt_obj.date[ind].indexOf('/') ) );
var query ={starlight:pts, balance:pts};
var trailMe = 'lightTrails' + ptMonth + '.';
var trailCat;
var hightrail= trailMe + '0';
query[hightrail]=pts;
switch (cat){
case 'Behavior':
trailCat= trailMe + '1';
query[trailCat]=pts;
console.log(trailCat);
break;
case 'Contest':
trailCat= trailMe + '2';
query[trailCat]=pts;
console.log(trailCat);
break;
case 'Game':
trailCat= trailMe + '3';
query[trailCat]=pts;
console.log(trailCat);
break;
case 'High Score':
trailCat= trailMe + '4';
query[trailCat]=pts;
console.log(trailCat);
break;
case 'Participation':
trailCat= trailMe + '5';
query[trailCat]=pts;
console.log(trailCat);
break;
case 'Wage':
trailCat= trailMe + '6';
query[trailCat]=pts;
console.log(trailCat);
break;
}
console.log('attacking query \n' + query);
//always add it to the starlight, highlight as well as specific category
Student.update( { rscombo : rsc } , { $inc: query }, function (err, student){
if(err || !student){
console.log('update unsuccessful');
} });
} else{
var pts = Number(pt_obj.pts[ind]);
Student.update( { rscombo : rsc } , { $inc: { balance: pts} }, function (err){
if(err){
console.log('update unsuccessful');
}
} );
}
}
if( leng-1 == i){
student.save(cb);
}else{
student.save(function(err){
if(err){
console.log(err);
}
})
}
i++;
});
}
});
return Student.findOne( { rscombo: 'r' + pt_obj.room + '-' + pt_obj.seat}, cb);
}

I think you have to build the point object in the loop, but push it after the loop ends.

Thanks Amor, what you said got me to thinking and I switch my code so that my forEach is on the outside and the findOne method is in the inside. It seems to have worked. Thank you so much.
pt_obj.category.forEach(cat, ind){
Student.findOne({}, function (){
})
}

Related

In Google Docs under script control, can a paragraph inserted automatically after the insertion of a table be addressed programmatically?

I have a Google Docs document with a PARAGRAPH followed by a TABLE followed by a TABLE. Visually there is a PARAGRAPH between the two TABLEs. Programatically, however, using the following code, the run log demonstrates that there is no PARAGRAPH, viz
[1] PARAGRAPH {'LEFT_TO_RIGHT' : true, 'LINE_SPACING' : 1.15, 'SPACING_AFTER' : 0, 'SPACING_BEFORE' : 0, 'INDENT_FIRST_LINE' : 0, 'INDENT_END' : 0, 'INDENT_START' : 0}
[1/1] TEXT {} perth influencer
[2] TABLE {'BORDER_WIDTH' : 1, 'BORDER_COLOR' : '#000000'}
[3] TABLE {'BORDER_WIDTH' : 1, 'BORDER_COLOR' : '#000000'} Keyword Research Volume
...
According to the Google Apps Script documentation for appendTable:
This method will also append an empty paragraph after the table, since Google Docs documents cannot end with a table.
This paragraph can be seen with the eyes but the script as it stands cannot "see" it. That is, stepping through the child elements of the document's body fails to detect the presence of the automatically-inserted paragraph. This is a problem because I want to reduce the point size of that paragraph.
This may be a known limitation of Google Docs via Google Apps Script. Or it may be my bad code, so below are the functions that I base my assertion on. They do nothing other than report on what they find but even so, maybe I'm missing something.
The output above was generated by coding LogChildren with a parameter of type GoogleAppsScript.Document.Body and referring to the body of the generated document.
String.prototype.quoted = function () {
return "'" + this.replace(/'/g,"\\'") + "'";
}
Number.prototype.quoted = function () {
return String(this);
}
Boolean.prototype.quoted = function () {
return this ? "true" : "false";
}
function getInnerText(child) {
switch (child.getType().toString()) {
case "BODY_SECTION":
return child.asBody().getText();
break;
case "EQUATION":
return child.asEquation().getText();
break;
case "EQUATION_FUNCTION":
return child.asEquationFunction().getText();
break;
case "FOOTER_SECTION":
return child.asFooterSection().getText();
break;
case "FOOTNOTE_SECTION":
return child.asFootnoteSection().getText();
break;
case "HEADER_SECTION":
return child.asHeaderSection().getText();
break;
case "LIST_ITEM":
return child.asListItem().getText();
break;
case "PARAGRAPH":
return "";
break;
case "TABLE":
return child.asTable().getText();
break;
case "TABLE_CELL":
return child.asTableCell().getText();
break;
case "TABLE_OF_CONTENTS":
return child.asTableOfContents().getText();
break;
case "TABLE_ROW":
return child.asTableRow().getText();
break;
case "TEXT":
return child.asText().getText();
break;
case "PAGE_BREAK":
return "";
break;
case "INLINE_IMAGE":
return child.asInlineImage().getLinkUrl();
break;
default:
return child.asText().getText();
break;
}
}
function getStyles(child) {
const attribs = child.getAttributes();
const attribList = [];
for (let att in attribs) {
try {
if (null !== attribs[att])
attribList.push(att.quoted() + " : " + attribs[att].quoted());
}
catch (E) { }
}
return "{" + attribList.join(", ") + "}";
}
function LogChild(index, child) {
Logger.log("[%s] %s %s %s", index, child.getType().toString(), getStyles(child), getInnerText(child));
}
function LogChildren(body) {
function LogDeeper(cc, child) {
const childCount = child.getNumChildren();
for (let c = 0; c < childCount; c++) {
LogChild(String(cc) + "/" + String(c + 1), child.getChild(c));
}
}
const childCount = body.getNumChildren();
for (let c = 0; c < childCount; c++) {
const child = body.getChild(c);
LogChild(String(c + 1), child);
if (isParagraph(child)) {
LogDeeper(c + 1, child.asParagraph());
}
else if (isListItem(child)) {
LogDeeper(c + 1, child.asListItem());
}
}
}
function isPageBreak(elem) {
return elem.getType() === DocumentApp.ElementType.PAGE_BREAK;
}
function isText(elem) {
return elem.getType() === DocumentApp.ElementType.TEXT;
}
function isParagraph(elem) {
return elem.getType() === DocumentApp.ElementType.PARAGRAPH;
}
function isListItem(elem) {
return elem.getType() === DocumentApp.ElementType.LIST_ITEM;
}
function isTable(elem) {
return elem.getType() === DocumentApp.ElementType.TABLE;
}
Use google-docs-api 's Document#get to retrieve the document structure and if there is a intervening paragraph recorded between the two tables, issue UpdateParagraphStyleRequest to modify that paragraph.
You can access the api from apps script through Advanced Google services

Cannot read property length of undefined - Javascript

I'm new in javascript the main goal of this code is to type a question in the textbox the browser will check the question if it was in the switches statements and get the answer than write it on the paragraph's id="lable".
The function randomArray(z)-line[8]- return a random array value .
What's hapenning : Typed :"undefined" on the paragraph which has "lable" as an id .
.........................
The HTML code :
<body>
<img src="Alexs_face.png">
<p style="border:2px black solid; margin:100px 400px 50px 400px">Ask me !</p>
<p id="lable"></p>
<input id="input" type="text" autocomplete="off">
<input id="send" type="button" onclick="dosome()" value="Send">
<input id="delete" type="button" onclick="deleteVal()" value="Delete"></body>
The Javascript:
var greating , userName;
var firstHello = [[greating+userName+", How can I help you ?" ], ["Hi "+userName+" how can i help ?"] ,[ greating+", how can i help ?"]];
dosome () ;
function randomArray (z) {
var index = Math.floor(Math.random() * z.length);
return z[index];
};
function getVal() {
write(randomArray (firstHello)); /* <------ trying to write a radom value from the firstHello array
*/
var ask = document.getElementById("input").value;
return ask ;}
var ask = getVal();
function write (x){
var lable = document.getElementById("lable").innerHTML = x;
return lable ;
};
//Capitalize the first letters func :
function capitalize(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
//..............
//............................... you can ignore this function
function dosome () {
var ask = getVal();
var question = ask.split(" ");
var date = new Date().toTimeString().split(" ")[0]; ;
var userName ="Med" ;
//5// give you different "greatings" according to ur time
if (date >= "06:00:00" && date <="11:00:00"){
greating = "Good morning ";
var alertTime=""
}
else if (date >= "11:00:00" && date <= "15:00:00"){
greating = "Good afternoon ";
var alertTime=""
}
else if (date >= "15:00:00" && date <="22:00:00"){
greating = "Good evening ";
var alertTime=""
}
else {
greating = " You should have some sleep !";
var alertTime = greating ;
};
//5//end
//
if (question[0] === "what"){
switch ( question[1]){
case "time":
switch (question[2]){
case "is":
switch (question[3]){
case "it":
write("The time is :"+date+alertTime);
break;
default:
};
break;
default:
} ;
break;
case "is":
switch (question[2]){
case "your" :
switch (question[3]){
case "name":
write("Alex !");
break;
case "father":
write("Medardo Erabti , he made me !");
break;
default:
};
break;
case "my":
switch (question[3]){
case "name":
write("Alex !");
break;
default:
};
break;
default:
};
break;
default: write("unknown");
};}
else if (question[0] === "my"){
switch (question[1]){
case "name":
switch(question[2]){
case "is":
userName = capitalize(question[3]);;
alert("Your name is saved, "+userName);
break;
default:
};
break;
default:
};
}
else if (question[0] === "should" || "could" || "may" || "can" ) {
switch (question[1]) {
case "i" :
switch(question[2]){
case "sleep":
write("Sure ! you can sleep if you want to !!");
break;
default:
}
break;
default:
};
}
if (question[0] === "who"){
switch (question[1]){
case "are":
write ("I'm Alex !");
break;
case "am":
write ("My leader !");
default:
}
};
return userName,greating ;
};
function deleteVal () {
var x = document.getElementById("lable").innerHTML = "" ;
return x ;
};
What I have tried:
Tried to disable the 'z' parametr in the function 'randomArray(z)' and replace it with the name of the array "firstHello" , Its type "undefined in the paragraf that has "lable" as an id .
In the dosome function you create a local variable named userName, the same as the global variable. The local variable will shadow the global variable for the code inside the function, so the global variable will still be undefined after calling the function.
Notes about the code in the randomArray function:
You are using Math.floor instead of Math.random.
Don't use Math.round when creating an integer random number, that will make the first and last number occur half as often as the other numbers. Use Math.floor instead.
Your loop goes two items beyond the last item in the array.
You don't need to loop at all to get an item with a specific index.
Here is code that just shows the modified randomArray function and code to call it:
var greating = 'Hello', userName = 'sir';
var firstHello = [
[ greating + " " + userName + ", How can I help you ?" ],
[ "Hi " + userName + " how can i help ?" ],
[ greating + ", how can i help ?" ]
];
function randomArray(z) {
var index = Math.floor(Math.random() * z.length);
return z[index];
}
console.log(randomArray(firstHello));

Why isn't my program assigning variables to the object, and then calculating from it?

This assignment is to take a pizza order and build one. Once the pizza is assembled, it should calculate the total cost of the pizza and spit out the total answer. I've played around on JsFiddle.net for two days now and can't figure out why it won't get past the interrogate function and move on to the calculate. I've entered in a couple alert statements here and there and still can't figure out what's going on. My best guess is either that 'myPizza' properties are not being assigned or that they are not being shared by the other functions. I know the second possibility could not be true because 'myPizza' is a global object with global properties.
recycle = true;
var ingrediants = ['pepperoni ', 'sausage ', 'avocado ', 'chicken ', 'mushrooms ', 'anchovies ', 'bacon ', 'pineapple ', 'beeswax '];
var toppings=[];
var i = -1;
var myPizza= {
size:"",
toppings:[],
stuffCrust:false,
sodaSide: false
};
var greeting = function () {
wantPizza = prompt("Hello! Welcome to Sean's Pizza Shack! Would you like to order a pizza?(Yes or No?)").toLowerCase();
if (wantPizza === 'yes') {
return true;
} else {
alert("Okay then, Get out of my pizza shop because I have customers waiting");
return false;
}
};
var interrogate = function () {
myPizza.size = prompt("Okay sir/Ma'am, Would you like a Small, Medium, Large, or extra Large?(XL)").toLowerCase();
myPizza.toppings = prompt("Alright! So what would you like on your " + myPizza.size + " pizza?" + " We have " + ingrediants).toLowerCase();
do {
i = i + 1;
myPizza.toppings+= toppings[i] =prompt(ingrediants + " Please type one ingrediant at a time to add to your pizza! or you may enter 'ALL' to add all toppings or press OK without entry to stop adding toppings").toLowerCase();
} while (toppings[i] !== "");
//LOOP TO DECIDE IF NEED TO PUSH ALL INGREDIENTS
for (k = 0; k <toppings.length; k++) {
if (toppings[k] === 'all') {
toppings = [];
toppings.push(ingrediants);
} else {
toppings.length -= 1; // IF NOT ALL INGREDIENTS, SUBTRACT '' FROM ADD INGREDIENTS //LOOP
}
}
alert("So you would like " + myPizza.toppings + " on your pizza!");
alert("Okay so i have a " + myPizza.size + " pizza, with " + myPizza.toppings + "!");
myPizza.stuffCrust = prompt("Do you want your pizza to have extra delicious stuffed cheesy crust?($4.00)").toLowerCase();
if(myPizza.stuffCrust==='yes') {
myPizza.stuffCrust=true;
}
myPizza.sodaSide = prompt("Would you like a 2 Liter soda with that for an extra $2.00?");
if(myPizza.sodaSide=== yes) {
myPizza.sodaSide=true;
}
alert(myPizza.sodaSide);
alert(myPizza.toppings);
alert(myPizza.stuffCrust);
alert(myPizza.toppings.length);
};
var up= {
total:0,
Sm:9.00,
Med:12.00,
Lrg: 15.00,
XL: 18.00,
Top: myPizza.toppings.length*1.00,
Stuff:4.00,
Soda: 2.00,
add: function(input) {
total+=input;
}
};
var calculate= function() {
switch(myPizza.size) {
case 'small': up.add(up.Sm);break;
case 'medium': up.add(up.Med);break;
case 'large': up.add(up.Lrg);break;
case 'XL': up.add(up.XL);break;
}
if(myPizza.toppings.length>0) {
up.add(up.Top);
} if (myPizza.stuffCrust) {
up.add(up.Stuff);
} if (myPizza.sodaSide) {
up.add(up.Soda);
}
alert("Okay, looks like your order comes to "+ up.total);
};
var main= function () {
if (greeting() === true) {
interrogate();
calculate();
}
};
main();
in the statement:
if(myPizza.sodaSide=== yes) {
myPizza.sodaSide=true;
}
you need to have yes in quotes:
if(myPizza.sodaSide=== 'yes') {
myPizza.sodaSide=true;
}

converting javascript array into html table in new window on click

I am creating data visualizations, and I have a button that will execute a JavaScript function and extract the first five rows from specified columns of data based on the user's selection:
getselection.onclick = function()
{
visual.Document.selection.getselection(
"City", \\identifies the selection
"Users", \\identifies the table
["Name", "Phone", "Zipcode"], \\identifies the columns
5,
function(args)
{
log(dump(args, "visual.Document.selection.getselection", 2));
});
};
The resulting output looks like this:
[Name]
0: xxxxx
1: xxxxx
2: xxxxx
[Phone]
0: xxxxx
1: xxxxx
What I would like to do is to display the results of the users selection in an HTML table in a new window that opens upon click. I have seen a suggestions for doing something similar to this, but for some reason I can't seem to get them to work. Here is what I have so far:
function getSelMarking() {
visual.Document.selection.getMarking(
"city",
"Users",
["Name", "phone", "Zipcode"],
5,
function(args) {
var UserIDs=dump(args);
HTMLstring='<HTML>\n';
HTMLstring+='<HEAD>\n';
HTMLstring+='<TITLE>New Document</TITLE>\n';
HTMLstring+='</HEAD>\n';
HTMLstring+='<BODY>\n';
HTMLstring+='<P>Hello World</P>\n';
HTMLstring+='<table>\n';
HTMLstring+='<tr>\n';
HTMLstring+='<td>'+UserIDs+'</td>\n';
HTMLstring+='<td>'+UserIDs+'</td>\n';
HTMLstring+='<td>'+UserIDs+'</td>\n';
HTMLstring+='</tr>\n';
HTMLstring+='</table>\n';
HTMLstring+='</BODY>\n';
HTMLstring+='</HTML>';
newwindow=window.open();
newdocument=newwindow.document;
newdocument.write(HTMLstring);
newdocument.close();
}
);
}
Thats as far as I've gotten. I am completely stuck on this - maybe I just don't have a good understanding of how the functions work? Regardless, thank you to anyone who can lend any type of assistance here.
i forgot to include the breakdown of the dump() function:
var dump = function(obj, name, indent, depth) {
if (depth > MAX_DUMP_DEPTH) {
return indent + name + ": <Maximum Depth Reached>\n";
}
if (typeof(obj) == "object") {
var child = null;
var output = name + "\n";
indent += "\t";
for (var item in obj) {
try {
if (item.charAt(0) == '_') {
continue;
}
child = obj[item];
} catch (e) {
child = "<Unable to Evaluate>";
}
if (typeof child == "object") {
output += dump(child, item, indent, depth + 1);
} else if (typeof(child) == "function") {
var functionName = String(child);
functionName = functionName.substring(0, functionName.indexOf("{", 0) -
10}
output += "\t" + item + ": " + functionName + "\n";
} else {
var value = "";
if (child == null) {
value = "[null]";
} else {
value = child;
}
output += "\t" + item + ": " + value + "\n";
}
}
return output + "\n";
} else {
return obj;
}
};
I found the answer to my own question. the difficulty here was caused my lack of understanding as to how javascript handled arrays. sorry everyone.

JavaScript & jQuery Function Error

I am making a generic text validation function with jQuery. I made the function text and I pass the id,requirement,expression,offset,limit into the function. The way I have made it is to help me run the function easily on single input change and on the submit of the whole form. I have made the function but I can't get it to run.
var Val = {
'text' : function(event, ident,req,regexp,offset,limit) {
var ele = $(document.getElementById(ident));
if(req == 1 && ele.val().length < 1) {
Val.errors = true;
$("#"+ident+"Error").html("Please enter your " + ele.attr("title"));
$("#"+ident+"Error").show("fast");
} else if(ele.val().length <= offset || ele.val().length > limit) {
Val.errors = true;
$("#"+ident+"Error").html(ele.attr("title") + " should be between " +offset+ " & " +limit+ " charecters long");
$("#"+ident+"Error").show("fast");
} else if(regexp != null) {
switch (regexp) {
case 'text':
var regEx = /^([a-zA-Z]+)$/; break;
case 'number':
var regEx = /^([0-9]+)$/; break;
case 'email':
var regEx = /^([A-Za-z0-9_\-\.])+\#([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/; break;
case 'date':
var regEx = /^([123]0|[012][1-9]|31)-(0[1-9]|1[012])-(19[0-9]{2}|2[0-9]{3})$/; break;
case 'alphanum':
var regEx = /^([a-zA-Z0-9._-]+)$/; break;
default:
var regEx = /^([a-zA-Z0-9._-]+)$/; break;
}
if(!regEx.test(ele.val())) {
Val.errors = true;
$("#"+ident+"Error").html(ele.attr("title") + " is not valid");
$("#"+ident+"Error").show("fast");
}
}
},
'send' : function (){
if(!Val.errors) {
$('#form').submit();
}
}
}
The calling code of the function:
$(document).ready(function(){
$('#send').click(function(){
Val.text('test', 1, 'email', 10, 50);
Val.send();
});
$('#test').bind('change', Val.text);
$('#test').trigger('change', ['test', 1, 'email', 10, 50]);
});
I know I haven't yet used the expressions but I will once I see it working.
Appreciate all the help...
Thanks!
I made it work. Once the script worked properly no trigger was required. I was able to just call simply inside the change event.
$('#emailID').change(function(){
Val.text('emailID', 1, 'email', 10, 100);
});
Thanks everyone for the help anyway.

Categories

Resources