Cannot read property length of undefined - Javascript - 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));

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

stop ForEach loop from running code 5 times per item

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 (){
})
}

Mars to Rover on JavaScript. I need to be able to tell a series of commands to the rover and execute them in sequence.

I am working on Mars to Rover program with JavaScript and I already finished iteration 1 that allows my rover to move to all directions in 2 dimensions (x,y). Now it comes iteration #2 where I need to be able to tell a series of commands to the rover and execute them in sequence.
Please give me some insights of how you would do iteration 2.
This is my current code:
// --------- Mars Rover Kata: Iteration #1 ------------ \\
// ------------------- User Experience using Console --------- \\
var promptSay = "Play with the Console!\nW = UP \nS = DOWN \nD = RIGHT \nA = LEFT";
var gridEdge = "You can\'go there! \n\nPlease notice that you are playing with an imaginary grid and the farest you can go is 9 steps";
var wrongInput = "---WRONG INPUT!--- Please use a correct input i. e. : \nW = UP \nS = DOWN \nD = RIGHT \nA = LEFT";
// Object Definition: (Vars inside a Var , may have functions) \\
var AJRover = {
position : [0, 0],
invalidInput: function(notright) { // Notification for invalid Input
alert(notright);
this.move(prompt(wrongInput));
},
invalidKey: function(message) { // Notification if you reach grid's edge
alert(message);
this.move(prompt(promptSay));
},
move: function(moveRover) { //Directions
switch(moveRover.toLowerCase()) {
case 'w':
this.goDirection("up");
break;
case 's':
this.goDirection("down");
break;
case 'd':
this.goDirection("right");
break;
case 'a':
this.goDirection('left');
break;
default:
this.invalidInput(wrongInput);
}
},
goDirection: function(direction) { //Directions Functions
switch(direction) {
case 'up':
if (this.position[1] >= -9 && (this.position[1] + 1) <= 9) {
this.position[1]++;
break;
} else {
this.invalidKey(gridEdge);
break;
}
case 'down':
if (this.position[1] <= 9 && (this.position[1] -1 ) >= -9) { // this needs to go back and stop at -9
this.position[1]--;
break;
} else {
this.invalidKey(gridEdge);
break;
}
case 'right':
if (this.position[0] >= -9 && (this.position[0] + 1) <= 9) {
this.position[0]++;
break;
} else {
this.invalidKey(gridEdge);
break;
}
case 'left':
if (this.position[0] <= 9 && (this.position[0] -1) >= -9) {
this.position[0]--;
break;
} else {
this.invalidKey(gridEdge);
break;
}
}
}
};
// ---- object END ----- \\\
// 1- This function calls the object move (this.move)
// 2- Sends the alert to prompts the var promptSay
// 3- Expects input to decide the output
while (true) { //This code block allows user move the rover on mars by interacting with console
var entry = prompt(promptSay);
AJRover.move(entry);
console.log('You are now at position: ', AJRover.position);
}
In browse environment, this cannot be done by interacting with console.
What you have to do is utilize event listeners. Here is an example how it could be done by binding them on document body.
const W_KEY = 119;
const A_KEY = 97;
const S_KEY = 115;
const D_KEY = 100;
document.body.addEventListener("keypress", function(e) {
let entry = null;
switch(e.keyCode) {
case W_KEY:
entry = "w";
break;
case A_KEY:
entry = "a";
break;
case S_KEY:
entry = "s";
break;
case D_KEY:
entry = "d";
break;
}
if(entry) {
console.log("Key " + entry + " was pressed!");
AJRover.move(key);
}
}

if/else statement not registering if

My code seems to log the if statement as false, even though if I console.log the conditions it returns as true. Why is it doing that? (the code , that is not working is indicated by error not bypassing.)
function StaffMember(name,discountPercent){
this.name = name;
this.discountPercent = discountPercent;
}
function Stock(item){
this.item = item;
}
//Global Variables
var staffMembers = {};
var sally = new StaffMember("Sally",0.05);
staffMembers['sally'] = sally;
var bob = new StaffMember("Bob",0.10);
staffMembers['bob'] = bob;
var me = new StaffMember("Aaron",0.20);
staffMembers['me'] = me;
//item variables
var eggs = new Stock("Eggs");
var milk = new Stock("Milk");
var magazine = new Stock("Magazine");
var chocolate = new Stock("Chocolate");
//item Objects
var Stock = {};
Stock['eggs'] = eggs;
Stock['milk'] = milk;
Stock['magazine'] = magazine;
Stock ['chocolate'] = chocolate;**
var cashRegister = {
total:0,
lastTransactionAmount: 0,
add: function(itemCost){
this.total += (itemCost || 0);
this.lastTransactionAmount = itemCost;
},
scan: function(item,quantity){
switch (item){
case "eggs": this.add(0.98 * quantity); break;
case "milk": this.add(1.23 * quantity); break;
case "magazine": this.add(4.99 * quantity); break;
case "chocolate": this.add(0.45 * quantity); break;
}
return true;
},
voidLastTransaction : function(){
this.total -= this.lastTransactionAmount;
this.lastTransactionAmount = 0;
},
// Create a new method applyStaffDiscount here
applyStaffDiscount : function(employee){
this.total -= this.total*(employee.discountPercent);
}
};
$(document).ready(function(){
$('#target2').hide();
$('#check').on('click', function(e){
e.preventDefault();
var item = $('#item').val();
var quantity = $('#quantity').val();
var staff = $('#staff').val();
cashRegister.scan(item, quantity);
//ERROR IN CODE NOT BYPASSING
if(item === Stock['item'] && quantity > 0) {
cashRegister.scan(item, quantity);
}
///
else {
alert("This Item Does Not Exist!");
}
if(staff.length > 0 && typeof staffMembers[staff] !='undefined'){
cashRegister.applyStaffDiscount(staffMembers[staff]);
}
var output = document.getElementById("result");
result.innerHTML = 'Your bill is ' + cashRegister.total.toFixed(2);
$('#target2').fadeIn(5000)
// .animate({opacity: 0.5}, 3000)
.fadeOut(5000);
});
$('#target').submit(function(){
var info = $(this).serializeJSON();
console.log(info);
var data = JSON.parse('[info]');
console.log(data);
return false;
});
});
Stock['item'] is going to return undefined because Stock['item'] is not declared. You declare Stock['milk'], Stock['magazine'],Stock['eggs'], and Stock['chocolate'], but not Stock['item']. If you were trying to use it as a variable, you should remove the quotes.
You are also overwriting your "Stock" function with a "Stock" object, which is not causing trouble right now but it could cause issues later down the line. You should rename those to be different if possible.
Try using Stock[item] !== undefined && quantity > 0 in place of your current if expression
You did not post your HTML or a working fiddle, but my guess is your if statement should be:
if(item === Stock[item] && quantity > 0) {
cashRegister.scan(item, quantity);
}
Stock['item'] returns undefined as you're not calling it either with an object context like obj.Stock() or after using bind or call, so this is undefined. It's not returning anything either, so no assignment is made. I'm assuming $('#item').val() also. $('#item') is most likely null, triggering a runtime error and stopping your if sentence.

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