Trouble looping through an object name - javascript

I'm new to javascript and I'm trying to create a dynamic list of quiz questions in business catalyst. With the way BC is set up you can use {tags} to place user-created information on a page.
That said I'm trying to generate a list of quiz questions based on user selected values. I have created an object, "Question", and placed the necessary properties with their values into the newly defined objects below.
In my code I am currently trying to:
1 - Define the Question object class
2 - Define the 15 possible quiz questions
3 - Write a for loop that will write each question based on a key value from the previous question.
The funciton/for loop I've written will ultimately do this:
Write question 1
if question1 key has a value of 'Yes' then write question 2
if question2 has a key value of 'Yes' then write question 3
etc etc until there are either no more yes's or question 15 has been written.
When I try to execute my code below I get the error 'Uncaught ReferenceError: question is not defined' Can someone help me understand what I'm doing wrong? Thank you for any and all help!
NOTE: TO SAVE SPACE I HAVE ONLY INCLUDED THREE QUESTION VARIABLES. IN MY ACTUAL CODE I HAVE DEFINED 15 QUESTION OBJECTS.
<script>
function Question (questionNumber, questionText, answerType, answerA, answerB, answerC, answerD, correctAnswer, visualRef, refKey, nextQ, qTextField, aTypeField, mcAField, mcBField, mcCField, mcDField, mcUserAnswer, tfUserAnswer, sRatings, sSAnswer, passFail) {
this.questionNumber = questionNumber;
this.questionText = questionText;
this.answerType = answerType;
this.answerA = answerA;
this.answerB = answerB;
this.answerC = answerC;
this.answerD = answerD;
this.true = "True";
this.false = "False";
this.correctAnswer = correctAnswer;
this.visualRef = visualRef;
this.refKey = refKey;
this.nextQ = nextQ;
this.qTextField = qTextField;
this.aTypeField = aTypeField;
this.mcAField = mcAField;
this.mcBField = mcBField;
this.mcCField = mcCField;
this.mcDField = mcDField;
this.mcUserAnswer = mcUserAnswer;
this.tfUserAnswer = tfUserAnswer;
this.sRatings = sRatings;
this.sSAnswer = sSAnswer;
this.passFail = passFail;
this.createQuestion = function() {
document.write("This is writing question " + this.questionNumber );
};
};
var question1 = new Question("1", "{tag_q-question_1}", "{tag_q-answer-type_1}", "{tag_q-text-answer_101}", "{tag_q-text-answer_102}", "{tag_q-text-answer_103}", "{tag_q-text-answer_104}", "{tag_q-multichoice-answer_1}{tag_q-t/f-answer_1}", "{tag_q-visual-reference_1}", "{tag_q-youtube_1}{tag_q-vimeo_1}{tag_q-image_1_value}", "{tag_q-next-question_1}", "CAT_Custom_13", "CAT_Custom_11", "CAT_Custom_14", "CAT_Custom_15", "CAT_Custom_16", "CAT_Custom_17", "CAT_Custom_7", "CAT_Custom_8", "CAT_Custom_9", "CAT_Custom_10", "CAT_Custom_12");
var question2 = new Question("2", "{tag_q-question_2}", "{tag_q-answer-type_2}", "{tag_q-text-answer_201}", "{tag_q-text-answer_202}", "{tag_q-text-answer_203}", "{tag_q-text-answer_204}", "{tag_q-multichoice-answer_2}{tag_q-t/f-answer_2}", "{tag_q-visual-reference_2}", "{tag_q-youtube_2}{tag_q-vimeo_2}{tag_q-image_2_value}", "{tag_q-next-question_2}", "CAT_Custom_19", "CAT_Custom_20", "CAT_Custom_22", "CAT_Custom_23", "CAT_Custom_24", "CAT_Custom_25", "CAT_Custom_21", "CAT_Custom_26", "CAT_Custom_27", "CAT_Custom_28", "CAT_Custom_29");
var question3 = new Question("3", "{tag_q-question_3}", "{tag_q-answer-type_3}", "{tag_q-text-answer_301}", "{tag_q-text-answer_302}", "{tag_q-text-answer_303}", "{tag_q-text-answer_304}", "{tag_q-multichoice-answer_3}{tag_q-t/f-answer_3}", "{tag_q-visual-reference_3}", "{tag_q-youtube_3}{tag_q-vimeo_3}{tag_q-image_3_value}", "{tag_q-next-question_3}", "CAT_Custom_30", "CAT_Custom_31", "CAT_Custom_33", "CAT_Custom_34", "CAT_Custom_35", "CAT_Custom_36", "CAT_Custom_32", "CAT_Custom_37", "CAT_Custom_38", "CAT_Custom_39", "CAT_Custom_40");
for (var i = 1; i <= 15; i++) {
if (question[i].prototype.nextQ === "Yes") {
question[i].createQuestion();
} else {
question1.createQuestion();
};
}
</script>

You have created 3 individual objects and you are trying to access them as an array however they are individuals not an array.
Try this
var question = new Array();
question[1] = new Question("1", "{tag_q-question_1}", "{tag_q-answer-type_1}", "{tag_q-text-answer_101}", "{tag_q-text-answer_102}", "{tag_q-text-answer_103}", "{tag_q-text-answer_104}", "{tag_q-multichoice-answer_1}{tag_q-t/f-answer_1}", "{tag_q-visual-reference_1}", "{tag_q-youtube_1}{tag_q-vimeo_1}{tag_q-image_1_value}", "{tag_q-next-question_1}", "CAT_Custom_13", "CAT_Custom_11", "CAT_Custom_14", "CAT_Custom_15", "CAT_Custom_16", "CAT_Custom_17", "CAT_Custom_7", "CAT_Custom_8", "CAT_Custom_9", "CAT_Custom_10", "CAT_Custom_12");
question[2] = new Question("2", "{tag_q-question_2}", "{tag_q-answer-type_2}", "{tag_q-text-answer_201}", "{tag_q-text-answer_202}", "{tag_q-text-answer_203}", "{tag_q-text-answer_204}", "{tag_q-multichoice-answer_2}{tag_q-t/f-answer_2}", "{tag_q-visual-reference_2}", "{tag_q-youtube_2}{tag_q-vimeo_2}{tag_q-image_2_value}", "{tag_q-next-question_2}", "CAT_Custom_19", "CAT_Custom_20", "CAT_Custom_22", "CAT_Custom_23", "CAT_Custom_24", "CAT_Custom_25", "CAT_Custom_21", "CAT_Custom_26", "CAT_Custom_27", "CAT_Custom_28", "CAT_Custom_29");
question[3] = new Question("3", "{tag_q-question_3}", "{tag_q-answer-type_3}", "{tag_q-text-answer_301}", "{tag_q-text-answer_302}", "{tag_q-text-answer_303}", "{tag_q-text-answer_304}", "{tag_q-multichoice-answer_3}{tag_q-t/f-answer_3}", "{tag_q-visual-reference_3}", "{tag_q-youtube_3}{tag_q-vimeo_3}{tag_q-image_3_value}", "{tag_q-next-question_3}", "CAT_Custom_30", "CAT_Custom_31", "CAT_Custom_33", "CAT_Custom_34", "CAT_Custom_35", "CAT_Custom_36", "CAT_Custom_32", "CAT_Custom_37", "CAT_Custom_38", "CAT_Custom_39", "CAT_Custom_40");
for (var i = 1; i <= 3; i++) {
if (question[i].nextQ === "Yes") {
question[i].createQuestion();
} else {
question[1].createQuestion();
};
}

Related

How to get name and values from a javascript object into a new list?

I have this JavaScript object which is a collection of multiple lists(I believe). I need to create a select dropdown with the name being the name of the list, and a number of boxes with background color as per that name. Like this:
I am able to parse that object to get all the names of the colors, but I can't find a way to parse the names and the list of values it holds. This is how I tried :
var
YlGn3 = ['#f7fcb9', '#addd8e', '#31a354'],
YlGn4 = ['#ffffcc', '#c2e699', '#78c679', '#238443'],
YlGn5 = ['#ffffcc', '#c2e699', '#78c679', '#31a354', '#006837'];
var brewer = Object.freeze({
YlGn3: YlGn3,
YlGn4: YlGn4
});
var office = Object.freeze({
YlGn5: YlGn5
});
var colorschemes = {
brewer: brewer,
office: office
};
var scheme_list = [];
for (i in colorschemes){
for(j in colorschemes[i]){
console.log(j);
scheme_list.push(j);
}
}
I was thinking of creating a new object and append every color, along with the list of colors, so I can parse it again to create an option element with it. But, I am not able to figure out the best way to do that. Is this the correct approach ?
You use Object.values along with forEach multiple times.
Object.values(colorschemes).forEach(obj=>Object.entries(obj).forEach(([name,colors])=>{
const arr = [];
colors.forEach(color=>arr.push(color));
scheme_list.push([name, arr]);
}));
var
YlGn3 = ['#f7fcb9', '#addd8e', '#31a354'],
YlGn4 = ['#ffffcc', '#c2e699', '#78c679', '#238443'],
YlGn5 = ['#ffffcc', '#c2e699', '#78c679', '#31a354', '#006837'];
var brewer = Object.freeze({
YlGn3: YlGn3,
YlGn4: YlGn4
});
var office = Object.freeze({
YlGn5: YlGn5
});
var colorschemes = {
brewer: brewer,
office: office
};
var scheme_list = [];
Object.values(colorschemes).forEach(obj=>Object.entries(obj).forEach(([name,colors])=>{
const arr = [];
colors.forEach(color=>arr.push(color));
scheme_list.push([name, arr]);
}));
console.log(scheme_list);

Split a JSON array into JS variables - Bixby

So I have a API outputting JSON to my JS code (http://api.opentripmap.com/0.1/ru/places/bbox?lon_min=-123.049641&lat_min=37.550392&lon_max=-122.049641&lat_max=38.550392&kinds=foods&format=geojson&apikey=5ae2e3f221c38a28845f05b685eac8210f10fb196793a9d4f6653c25).
However it contains a JSON Array that looks like this- "coordinates": [ -122.510216, 37.769474 ]
Is there a way to split it into separate JS variables like one variable for the left side and another for the right side. At the moment the array is causing my code to crash as it can only accept one input in each slot.
Sorry If this is a simple question, I haven't been able to solve this yet...
EDIT:
Sorry for the terrible question layout. I have tried to splice and splitting the array with no success (splicing lead to a whole load of undefined errors).
My current code is
module.exports.function = function findLunch(myLocation) {
var loc_long_max = Number(myLocation.longitude) //grab longitude from user
var loc_lat_min = Number(myLocation.latitude) //grab latitude from User
var loc_long_min = loc_long_max - 0.5;
var loc_lat_max = loc_lat_min + 0.5;
var url_all = "http://api.opentripmap.com/0.1/ru/places/bbox?lon_min=" + loc_long_min + "&lat_min=" + loc_lat_min + "&lon_max=" + loc_long_max + "&lat_max=" + loc_lat_max + "&kinds=foods&format=geojson&apikey=5ae2e3f221c38a28845f05b685eac8210f10fb196793a9d4f6653c25"
var results = http.getUrl(url_all, { format: 'json' }); //gets json info from url_all.
console.log(results.features[rand].properties.name)
//console.log(results.feautres[rand].properties.rate)
console.log(results.features[rand].geometry.coordinates)
//console.log(results);
for (var i = rand; i < results.features.length; i++) {
console.log(results.features[rand].properties.name)
console.log(results.features[rand].properties.rate)
var businesses = {
name: results.features[rand].properties.name,
rating:results.features[rand].properties.rate,
coordinates: results.features[rand].geometry.coordinates
}
}
return businesses
So the coordinates need to be split and then be in the businesses var which is then outputted to Bixby....
EDIT 2 : Fixed it - thanks everyone for the help!
Thanks!
Not sure if this is smth you're asking but you can use destructuting assignment to assign items in an array to variables:
const coordinates = [ -122.510216, 37.769474 ];
const [coordinateOne, coordinateTwo] = coordinates;
console.log(coordinateOne) // -122.510216
console.log(coordinateTwo) // 37.769474
You can use destructuring to assign the first and second elements of the array to variables in a simple way:
const coordinates = [-122.510216, 37.769474];
const [left, right] = coordinates;
console.log(left);
console.log(right);

Check if a value exists in two or more arrays [duplicate]

This question already has answers here:
How do I check if an array includes a value in JavaScript?
(60 answers)
Closed 4 years ago.
I'm trying to check user input value against two or arrays to see if the value inputed by the user equals a value in one of the arrays. Based on which array the input value equals to, I want to display a specific alert message.
So far I have this:
var zip = document.getElementById('zip').value;
var zone1 = ['11220', '11223', '11224', '11225', '11226','11228'];
var zone2 = ['10038', '10001'];
So if the user enters ZIP code 11220, I would like to display a message: "Price: $50". If the user enters 10038, I would like the message "Price: $75".
What's the easiest and most efficient way to do this?
I had a similar task recently that I solved like this.
Adjust the code to do what you need to whatever element in the function passed to forEach.
var zone1 = ['11220', '11223', '11224', '11225', '11226','11228'],
zone2 = ['10038', '10001'],
zones = [[zone1, 50], [zone2, 75], ]
.map(([zone, price]) => [new Set(zone), price]);
var userValue = '11220';
zones
.filter(([zone, price]) => zone.has(userValue))
.map(([zone, price]) => price)
.forEach((price) => console.log(`Price: $${price}`))
var userValue = '10001';
zones
.filter(([zone, price]) => zone.has(userValue))
.map(([zone, price]) => price)
.forEach((price) => console.log(`Price: $${price}`))
//Handle bad values, too, by defining a function
function getPrices(value){
return zones
.filter(([zone, price]) => zone.has(value))
.map(([zone, price]) => price)
}
var someNonExistentValue = 'xxx';
results = getPrices(someNonExistentValue);
if (results.length){
results.forEach(foundItem => console.log(foundItem));
} else {
console.log('No items found!');
}
OUTPUT:
Price: $50
Price: $75
No items found!
You need to Google questions and try to form your own solution. Only when you have an persistent error in your code should you ask about it. Here's a freebie:
if(zone1.indexOf(zip)!==-1){alert("Price: $50");}
elseif(zone2.indexOf(zip)!==-1){alert("Price: $75");}
If you want most efficient, then you should not work with arrays, but with a plain object, keyed by the zip codes (or use a ES6 Map):
var zones = {
11220: 1, 11223: 1, 11224: 1, 11225: 1, 11226: 1, 11228: 1,
10038: 2, 10001: 2
};
var messages = ["Unknown", "Price $50", "Price $75"];
var zip = document.getElementById('zip');
var msg = document.getElementById('msg');
zip.oninput = function() {
msg.textContent = messages[zones[this.value] || 0];
};
Zip: <input id="zip">
<div id="msg"></div>
Try this
var zip = document.getElementById('zip').value;
var zone1 = ['11220', '11223', '11224', '11225', '11226','11228'];
var zone2 = ['10038', '10001']
if(zone1.includes(zip))
alert("Price: $50");
else if (zone2.includes(zip))
alert("Price: $75");
You can simply use Array.prototype.indexOf method to check if a value exists as an array element.
var zone1 = ['11220', '11223', '11224', '11225', '11226', '11228'];
var zone2 = ['10038', '10001'];
document.getElementById('zip').addEventListener('change', (e) => {
if (e.target.value.length === 5) {
if (checkExists(e.target.value, zone1)) {
console.log(`${e.target.value} found in zone1`);
} else if (checkExists(e.target.value, zone2)) {
console.log(`${e.target.value} found in zone2`);
} else {
console.log(`${e.target.value} not in any zone!`);
}
}
});
function checkExists(needle, haystack) {
return haystack.indexOf(needle) > -1;
}
Enter a zip code then click outside the textfield to validate<br>
<input id="zip" type="text">

JavaScript database correlation

I've been trying to 'correlate' between user picked answers and an object property name so that if the two matches then it will display what is inside.
My program is a recipe finder that gives back a recipe that consists of the ingredients the user picked.
my code currently looks like:
//property are the ingredients and the value are the recipes that contain those ingredients. The map is automatically generated
``var map = {
"pork" : [recipe1, recipe2, ...],
"beef" : [],
"chicken" :[],
}
//this gets the user pick from the dom
var cucumber = specificVegetable[7];
var lemon = specificFruits[0];
//Then this code finds the intersection of the recipe(recipes that use more than one ingredients)
function intersect(array1, array2)
{
return array1.filter(function(n) {
return array2.indexOf(n) != -1
});
}
var recipiesWithLemon = map["lemon"]; **// makes the lemon object is map**
var recipiesWithCucumber = map["cucumber"]; **// makes the cucumber object in map**
//Here is where I am stuck
function check(){
var both = intersect(recipiesWithLemon, recipiesWithCucumber);
if ( cucumber.checked && lemon.checked){
for (var stuff in map){
if(stuff="cucumber" && stuff="lemon"){
return both;
}
}
}
}
check();
so basically what I tried to do was I made my intersect and then if user pick is lemon and cucumber then look at the properties in the map object. if the name of the property equals to the exact string then return both. That was the plan but the code does not work and I'm not sure how to fix it.
My plan is to write code for every possible outcome the user may makes so I need to find the correlation between the user pick and the map which stores the recipe. I realize this is not the most effective way but I'm stumped on how to do it another way.
Thanks for the help.
Im using the open source project jinqJs to simplify the process.
I also changed your map to an array of JSON objects. If you must have the map object not as an array, let me know. I will change the sample code.
var map = [
{"pork" : ['recipe1', 'recipe2']},
{"beef" : ['recipe3', 'recipe4']},
{"peach" :['recipe5', 'recipe6']},
{"carrot" :['recipe7', 'recipe8']}
];
var selectedFruit = 'peach';
var selectedVeggie = 'carrot';
var selections = [selectedFruit, selectedVeggie];
var result = jinqJs().from(map).where(function(row){
for(var f in row) {
if (selections.indexOf(f) > -1)
return true;
}
return false;
}).select();
document.body.innerHTML += '<pre>' + JSON.stringify(result, null, 2) + '</pre><br><br>';
<script src="https://rawgit.com/fordth/jinqJs/master/jinqjs.js"></script>

Prototypes etc in Angular JS [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
Should you you use classes, prototypes etc in Angular JS? I learned Angular JS before I learned Javascript (bad idea). Now I've started to read some about OOP in javascript. I'm very confused at the moment.
I have an example. It's a service. It has some data from server and some input from user. It runs som logic and populate the object which is then viewed for the user.
Option 1. Just an object. I've removed most of the code so it's more a pseudo code. This is the way you see in most examples and tutorials.
angular.module('calculationServices', ['ngResource']).
factory('CalculationFactory', function(UnitsFactory){
var calculations = {
mainCalculation: function(sizes, pipe, temperature){
if(sizes === null || temperature === null){
return;
}
var rawness = pipe.rawness;
var mediaDensity = temperature.density;
var results = [],
nrOfSizes = sizes.length;
for(var i = 0;i<nrOfSizes;i++){
var flow = this.input.flow.valueInSIunit;
var velocitySiUnit = this.velocityFN(sizes[i].innerdiameter/1000,flow);
var pressureDropInSiUnit = this.pressureDropFN(velocitySiUnit,mediaDensity, frictionFactor, sizes[i].innerdiameter/1000);
results.push({
size:sizes[i].nominalsize
innerDiameter:sizes[i].innerdiameter,
velocity:{
siUnit:velocitySiUnit,
userUnit:velocityUserUnit
}
});
}
return results;
},
powerFN: function(flow, cp, density, deltaT){
var power = flow * cp * deltaT * density;
return power;
},
velocityFN: function(innerDiameter, flow){
var area = Math.PI * Math.pow((innerDiameter) * 0.5 ,2);
return flow / area;
},
input: { //Input is hooked up to my $scope
flow:{
valueInSIunit: 0.00075,
value:0.75,
unit: 'l/s'
}
},
};
return calculations;
})
})
Option 2 Or. should I use classes, instantiating, prototypes etc. Something like this:
factory('CalculationFactory', function(UnitsFactory){
function PipeCalculations(params){
this.flow = params.flow;
this.pipe = params.pipe;
this.sizes = params.sizes;
}
PipeCalculations.prototype.velocityFN = function(flow, innerDiameter){
var area = Math.PI * Math.pow((innerDiameter) * 0.5 ,2);
return flow / area;
}
PipeCalculations.prototype.createPipeCalculationObjects = function(sizes){
var results = [];
var nrOfSizes = sizes.length;
var velocitySiUnit = this.velocityFN(sizes[i].innerdiameter/1000,flow);
for(var i = 0;i<nrOfSizes;i++){
results.push({
size:sizes[i].nominalsize,
velocity:{
siUnit:velocitySiUnit
}
});
}
return results;
};
var pipeCalculations = new PipeCalculations({
flow: { //Should this be hooked up directly to my scope?
valueInSiUnit: 55,
valueInUserUnit: 0.75
},
pipe: 0, //Data feed from controller
sizes: 0
});
pipeCalculations.velocity = pipeCalculations.velocityFN(pipeCalculations.flow.valueInSiUnit, 25);
pipeCalculations.output = pipeCalculations.createPipeCalculationObjects(pipeCalculations.sizes);
return pipeCalculations;
})
Is there a clear right and wrong here? I did option one first. It was very easy and everything worked smoothly. But it didn't feel quite "OOP". However, option 2 is much harder for me because it's difficult to find decent examples. Also, with option one I can simply attach my scope to my model and everything is updated automatically. But how do i do it correctly with option 2? Should i instantiate from my controller?

Categories

Resources