As part of a joomla site, I have a fair number (>20) of quite long arrays (~50 elements) of English sentences located in several files. These arrays are to be accessed by jquery click events which will display the sentences as examples of English word use.The click event functionality which generates the array indices for individual sentences is working. I want to namespace the arrays using a module pattern. According to
http://www.2ality.com/2011/04/modules-and-namespaces-in-javascript.html, module definitions can be spread over several locations. This would be very useful from the point of view of module scalability. I've modified a module from the above article, thus:
var namespace = function() {
var index = 2; // for example
var arr = ["the boy is going home",
"You and I are friends",
"He has a book of mine"];
return {
get values() {
return arr[index];
}
};
}();
console.log(namespace.values);
This works as far as it goes. However, I want to pass an array index to the module and have it return the corresponding text. How can this be done?
var namespace = function() {
var arr = ["the boy is going home",
"You and I are friends",
"He has a book of mine"];
return {
values: function(index) {
return arr[index];
}
};
}();
console.log(namespace.values(1));
So when the IIFE returns the objet properties for namespace, we make values a function (method) and pass in the index. Once the IIFE executes you could think of it like this;
var namespace = {
values: function(index) {
return arr[index];
}
}
but with the initialised arr array.
Try this:
namespace = function() {
this.index = 2; // for example
this.arr = ["the boy is going home",
"You and I are friends",
"He has a book of mine"];
};
namespace.prototype.getValueAt = function(index){
return this.arr[index];
};
console.log(namespace.getValueAt(0));
Related
I'm trying to create a timed quiz for a bootcamp challenge I'm taking. I'm stuck on a part where I need to get access of my "questions" array, in which contains 5 "question" objects and an "answers" array inside each object as well as another key named correctAnsw which contains the correct answer to the question, as seen in the code below(i've snipped it down to just one of the questions/answers but there are currently 5.) I'm not sure if this is even the correct way of storing my questions for my quiz but this is what I've done so I'd like to know if this is bad practice or not.
The issue I'm facing right now is I need to dynamically create li objects which contain the "answers" to my question so then I can move on and do things like checking if it's the correct answer etc.
var questions = [
{
question: "What is a string in javascript?",
answers: [
"Something that lets you put words",
"Something that lets numbers",
"A type of function",
"A property of the DOM"
],
correctAnsw: "Something that lets you put words"
}];
function renderQuestions(){
questionTitle.innerHTML = "";
questionChoices.innerHTML = "";
for(var o in questions){
let qst = document.createElement("li");
questionChoices.append(qst);
qst.innerHTML = questions[o]; }
}
Currently this just displays li's with [object Object].
I'm really not sure where to go from here so any help would be appreciated. thanks. also don't pay too much attention to the content of the questions lol I will revist this once I've finished what I need to do
Is this what you want ?
forEach is easiest way to loop throw an nested array.
var questions = [
{
question: "What is a string in javascript?",
answers: [
"Something that lets you put words",
"Something that lets numbers",
"A type of function",
"A property of the DOM"
],
correctAnsw: "Something that lets you put words"
},
{
question: "What is an array of objects in javascript?",
answers: [
"Something that lets you put words",
"Something that lets numbers",
"A type of function",
"A property of the DOM"
],
correctAnsw: "Something that lets you put objects on array"
}
];
function renderQuestions(){
questions.forEach(function (qst) {
let questionTitle = document.createElement("h3");
questionTitle.innerHTML = qst.question;
document.getElementById("questions").appendChild(questionTitle);
qst.answers.forEach(answer => {
// Create an "li" node:
let node = document.createElement("li");
let textnode = document.createTextNode(answer);
node.appendChild(textnode);
document.getElementById("questions").appendChild(node);
//questionChoices.append(qst);
})
});
}
renderQuestions();
<div id='questions' >
</div>
function renderQuestions(){
questionTitle.innerHTML = "";
questionChoices.innerHTML = "";
for(var o in questions){
let qst = document.createElement("li");
qst.innerHTML = questions[o].question;
questionChoices.append(qst);
}
}
questions[o] is an object and not a string.
When an object is converted to string, it becomes [object, object]. So you will have to specify a string property inside it.
If you are trying to create answers inside the qst?
the you would have to loop for the answers array and create the elements.
function renderQuestions(){
questionTitle.innerHTML = "";
questionChoices.innerHTML = "";
for (var o in questions) {
questionTitle.innerHTML = questions[o].question
questions[o].answers.forEach(ans => {
let qst = document.createElement("li");
qst.innerHTML = ans;
questionChoices.append(qst);
})
}
}
But remember, it will change the questionTitle on each iteration and add all the options together.
If this is to display individually, then the code needs to add all elements dynamically as,
var questions = [
{
question: "What is a string in javascript?",
answers: [
"Something that lets you put words",
"Something that lets numbers",
"A type of function",
"A property of the DOM"
],
correctAnsw: "Something that lets you put words"
}
];
function renderQuestions() {
const q = document.getElementById('questions')
for (var o in questions) {
const questionTitle = document.createElement('div');
const questionChoices = document.createElement('ul');
questionTitle.innerHTML = questions[o].question
questions[o].answers.forEach(ans => {
let qst = document.createElement("li");
qst.innerHTML = ans;
questionChoices.appendChild(qst);
})
q.appendChild(questionTitle)
q.appendChild(questionChoices)
}
}
renderQuestions();
<div id="questions"></div>
I agree with the last answer. You probably thought that by typing questions[0] you're accessing the object keys you've created, but thats not the case.
You've created an array of objects, with just one object in this case. So questions[0] is the entire object, you have to loop through it as Mohan showed you.
Let me know if it helped. Happy coding!
How could I rewrite this code to object javascript. Since Array usage is prohibed, I can only use objects here. Insted of pushing values to array, I would like to push this values into objects.
var container = [];
document.addEventListener("submit", function(e){
e.preventDefault();
});
window.addEventListener("load",function(){
var submit = document.getElementsByClassName("btn-primary");
submit[0].addEventListener("click",add,false);
document.getElementById("pobrisi").addEventListener("click",deleteAll,false);
var dateElement = document.getElementById('datum');
dateElement.valueAsDate = new Date();
var today = new Date();
var dd = today.getDate();
var mm = today.getMonth()+1;
var yyyy = today.getFullYear();
if(dd<10){
dd='0'+dd
}
if(mm<10){
mm='0'+mm
}
today = yyyy+'-'+mm+'-'+dd;
dateElement.setAttribute("min",today);
});
function add() {
var title = document.getElementById("title").value;
var type = document.getElementById("type").value;
var datum = document.getElementById("datum").value.split("-");
datum = datum[2]+". "+datum[1]+". "+datum[0];
var data = new Book(title,type,datum);
container.push(data.add());
display();
}
function display(data) {
var destination = document.getElementById("list");
var html = "";
for(var i =0;i <container.length; i++) {
html +="<li>"+container[i]+"</li>";
}
destination.innerHTML = html;
}
function deleteAll(){
container=[];
document.getElementById("list").innerHTML="";
}
Wondering if is possible to write this code whitout any array usage.
initial remarks
The problem here, in my estimation, is that you haven't learned the fundamentals of data abstraction yet. If you don't know how to implement an array, you probably shouldn't be depending on one quite yet. Objects and Arrays are so widespread because they're so commonly useful. However, if you don't know what a specific data type is affording you (ie, what convenience does it provide?), then it's probable you will be misusing the type
If you take the code here but techniques like this weren't covered in your class, it will be obvious that you received help from an outside source. Assuming the teacher has a curriculum organized in a sane fashion, you should be able to solve problems based on the material you've already covered.
Based on your code, it's evident you really have tried much, but why do you think that people here will come up with an answer that your teacher will accept? How are we supposed to know what you can use?
a fun exercise nonetheless
OK, so (we think) we need an Array, but let's pretend Arrays don't exist. If we could get this code working below, we might not exactly have an Array, but we'd have something that works like an array.
Most importantly, if we could get this code working below, we'd know what it takes to make a data type that can hold a dynamic number of values. Only then can we begin to truly appreciate what Array is doing for us.
// make a list
let l = list(1) // (1)
// push an item on the end
l = push(l, 2) // (1 2)
// push another item on the end
l = push(l, 3) // (1 2 3)
// display each item of the list
listeach(l, function (x) {
console.log(x)
})
// should output
// 1
// 2
// 3
runnable demo
All we have to do is make that bit of code (above) work without using any arrays. I'll restrict myself even further and only use functions, if/else, and equality test ===. I see these things in your code, so I'm assuming it's OK for me to use them too.
But am I supposed to believe your teacher would let you write code like this? It works, of course, but I don't think it brings you any closer to your answer
var empty = function () {}
function isEmpty (x) {
return x === empty
}
function pair (x,y) {
return function (p) {
return p(x,y)
}
}
function head (p) {
return p(function (x,y) {
return x
})
}
function tail (p) {
return p(function (x,y) {
return y
})
}
function push (l, x) {
if (isEmpty(l))
return list(x)
else
return pair(head(l), push(tail(l), x))
}
function list (x) {
return pair(x, empty)
}
function listeach (l, f) {
if (isEmpty(l))
return null
else
(f(head(l)), listeach(tail(l), f))
}
// make a list
let l = list(1) // (1)
// push an item on the end
l = push(l, 2) // (1 2)
// push another item on the end
l = push(l, 3) // (1 2 3)
// display each item of the list
listeach(l, function (x) {
console.log(x)
})
closing remarks
It appears as tho you can use an Object in lieu of an Array. The accepted answer (at this time) shows a very narrow understanding of how an object could be used to solve your problem. After this contrived demonstration, are you confident that you are using Objects properly and effectively?
Do you know how to implement an object? Could you fulfill this contract (below)? What I mean by that, is could you write the functions object, set, and get such that the following expressions evaluated to their expected result?
In case it's not obvious, you're not allowed to use Object to make it happen. The whole point of the exercise is to make a new data type that you don't already have access to
m = object() // m
set(m, key, x) // m
get(m, key) // x
set(m, key2, y) // m
get(m, key2) // y
set(m, key3, set(object(), key4, z)) // m
get(get(m, key3), key4) // z
I'll leave this as an exercise for you and I strongly encourage you to do it. I think you will learn a lot in the process and develop a deep understanding and appreciation for what higher-level data types like Array or Object give to you
Since this is a homework I feel like I shouldn't solve it for you, but rather help you in the right direction.
Like Slasher mentioned you can use objects
With JavaScript object one book would look something like
const book = {
title: 'my awesome title',
type: 'novel'
};
book is the object
title is a property with a value 'my awesome title'
type is a property with a value 'novel'
But objects can also have other objects as values. Something like
const BookShelf= {
Book1: {
Title: 'my awesome title',
Type: 'novel'
},
Book2: {
Title: 'my horrible title',
Type: 'sci-fi'
}
};
You can reference the books in the bookshelf in two ways
const book1 = BookShelf.Book1 // Returns the book1 object
const title1 = Book1.Title; // Get the title
const sametitle = BookShelf.Book1.Title // Returns title for book1, same as above.
You can also use brackets:
const book1 = BookShelf['Book1'];
const title1 = BookShelf['Book1']['Title];
You can even make new properties on a object like this:
const Book3 = {
Title: 'running out of ideas'
Type: 'memoir'
};
BookShelf['Book3'] = Book3;
Now the BookShelf has a Book3 property. So your BookShelf object looks like
const BookShelf= {
Book1: {
Title: 'my awesome title',
Type: 'novel'
},
Book2: {
Title: 'my horrible title',
Type: 'sci-fi'
},
Book3 = {
Title: 'running out of ideas'
Type: 'memoir'
};
};
That should get you started :)
JavaScript Objects is a good way to go
1- define a new object:
var myVar = {};
or
var myVar = new Object();
2- usage
// insert a new value, it doesn't matter if the value is a string or int or even another object
// set a new value
myVar.myFirstValue="this is my first value";
// get existing value and do what ever you want with it
var value = myVar.myFirstValue
i have looked for an answer to this, but im also not sure im using the correct wording to give me a good search result. So without further adoo.
I am trying to make a random name generator in JavaScript, and I don't want a 300 line switch if it can be avoided. No Jquery if it can be avoided, mainly as i want to learn how to code in JS, for no other reason than that. But if i have to use Jquery, so be it. Learning and all.
The idea is that the script will take the race, gender, then randomly select the first name, surname and proffesion from an array. I can get this to work in IF statements and switches. But I want to try it on as little code as possible. The example below is for humans, but the idea is to pretty much use any fantasy race... dwarves, elves... yes its for dungeons and dragons. Maybe later on use JSON for the array data, but that's later.
var HumanFemale = ["Diane","Laura","Amy"];
var HumanMale = ["Steve","Dave","Tony"];
var HumanS = ["Druss","Hale","Taylor"];
var Proff = ["Theif","Mercenary","Soldier"];
function chargen(race,gender){
var x = race.concat(gender);
var xs= race.concat('S');
document.getElementById("OutputR").innerHTML= race;
document.getElementById("OutputG").innerHTML= gender;
document.getElementById("OutputF").innerHTML= x[Math.floor(Math.random()*x.length)];
document.getElementById("OutputS").innerHTML=xs[Math.floor(Math.random()*xs.length)];
document.getElementById("OutputJ").innerHTML=Proff[Math.floor(Math.random()*Proff.length)];
}
Maybe I need dynamic variables, but i'm not sure how to convert text into a var name.
Thanks
I think an object probably makes your life a little easier, but the idea is generally the same as what you appear to have.
In JavaScript you can reference a property of an object like an array. This means that if you have a property name that can be variable, you can use the array convention to fetch the property instead of the "." convention.
Here's an example:
var example = {
"first": "hello",
"second": "world"
}
//Using dot-notation
alert(example.first); //alerts "hello"
alert(example.second) //alerts "world"
//Using array-notation
alert(example["first"]); //alerts "hello"
alert(example["second"]); //alerts "world"
Now, if the property we want is variable, we can't use the dot-notation, but we can use the array-notation:
var prop_name = "second";
//Using dot-notation
alert(example.prop_name); //throws an error (undefined property)
//Using array-notation
alert(example[prop_name]); //alerts "world"
So, if you create essentially a dictionary object, you may find it's easier/more concise to complete your task:
var dict = {
"Human": {
"Male": ["Steve", "Dave", "Tony"],
"Female": ["Diane", "Laura", "Amy"],
"Surname": ["Druss", "Hale", "Taylor"]
},
"Elf": {
"Male": [/* names */],
"Female": [/* names */],
"Surname": [/*names */]
}
}
function rand_attributes(race, gender) {
var first_name_index = Math.floor(Math.random() * dict[race][gender].length),
last_name_index = Math.floor(Math.random() * dict[race]["Surname"].length),
first_name = dict[race][gender][first_name_index],
last_name = dict[race]["Surname"][last_name_index];
//Now first_name and last_name each contain random values
//Do what you need to with those values from here
}
That code is untested, but it should at least conceptually work out.
Here's what I crudely chucked together.
var Proff=["Theif","Mercenary","Soldier"];
var CharacterName={};
CharacterName['human']={};
CharacterName['human']['female'] = new Array('Diane','Laura','Amy');
CharacterName['human']['male'] = new Array('Steve','Dave','Tony');
CharacterName['human']['surname'] = new Array('Druss','Hale','Taylor');
//just add more stuff here!
document.getElementById('OutputR').innerHTML= 'boo';
function chargen(race,gender){
document.getElementById('OutputR').innerHTML= race;
document.getElementById('OutputG').innerHTML= gender;
document.getElementById('OutputF').innerHTML= grabrandom(CharacterName[race][gender]);
document.getElementById('OutputS').innerHTML= grabrandom(CharacterName[race]['surname']);
document.getElementById('OutputJ').innerHTML= grabrandom(Proff);
}
function grabrandom(arrayofvalues){
return arrayofvalues[Math.floor(Math.random()*arrayofvalues.length)];
}
chargen('human','female');
It's nothing special and a couple of bits could be sharpened, but it's functional and gives you the idea on how it could be done.
The solution i got, heavily based on xjstratedgebx's responce.
var names = {
"Human": {
"Female": ["Diane","Laura","Amy"],
"Male": ["Steve","Dave","Tony"],
"Surname": ["Hall","Young","Taylor"]
}
}
function namegen(race,gender){
var firstname = names[race][gender][Math.floor(Math.random() * names[race][gender].length)];
var lastname = names[race]["Surname"][Math.floor(Math.random() * names[race]["Surname"].length)];
document.getElementById("OutputR").innerHTML= "Human";
document.getElementById("OutputG").innerHTML= "Female";
document.getElementById("OutputF").innerHTML= firstname;
document.getElementById("OutputS").innerHTML= lastname;
}
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>
I wish to grab content from various sources, using different API calls, and collate them all into an object or array with the same format. I am getting stuck with javascript arrays and objects, and none of the examples I find seem to do what I want to do. This is the format I want to store. This is pseudo coded for an example of what I want to achieve
var content = new Object();
getTweets();
getSoundCloud();
display();
function getTweets() {
//first result
content.type = "tweet
content.text = "the text of the tweet"
content.image = "the image from the tweet"
return content;
}
function getSoundCloud() {
//second result
content.type = "soundcloud
content.text = "the name of the song"
content.image = "the image of the song"
return content;
}
function display() {
//for each content
{
$("#container").append(content.text);
}
}
The first result is generated by one function call, and the Second result is generated by a different function call.
I want these functions to add all of the content together into the same format object. Once the object is populated, I wish to iterate it in a different function and display on the screen.
How do I make this object? I have tried it but the data is always the same, ie, overwritten with the same values. In php this would be an associative array perhaps or something like
I want to have an object for each piece of content I have, and can loop through it
content[0].type = "tweet"
content[1].type = "coundcloud"
Any suggestions with examples would be great.
Many Thanks
When you have many of something you should immediately think
I need to store these things in an array.
When your "things" are complex and have various properties/ state, you should immediately think:
I need to create an object to store them.
... so what would be best here is an array of objects. Each function will create objects and add them to content, which we'll switch to an array:
var content = []; // Array
getTweets();
getSoundCloud();
display();
function getTweets() {
var tweet = {}; // This is an object
tweet.type = "tweet";
tweet.text = "The text of the tweet";
tweet.image = "The image of the tweet";
content.push(tweet); // add the object to the array.
}
function getSoundCloud() {
var soundcloudThing = {};
soundcloudThing.type = "soundcloud"
soundcloudThing.text = "the name of the song"
soundcloudThing.image = "the image of the song"
content.push(soundcloudThing);
}
Now when it comes to showing this content, as have an array; the obvious thing to do here is iterate over it;
function display() {
for (var i=0;i<content.length;i++)
{
$("#container").append(content[i].text);
// You can also use content[i].image and content[i].type in here
}
}
Note that [] and {} is literal notation for creating arrays and objects. It's use is favoured over new Array() and new Object().
I have done an example here: http://jsfiddle.net/pdXsA/2/
var content = [];
content.push(getTweets());
content.push(getSoundCloud());
display();
function getTweets() {
return{
type : "tweet",
text : "the text of the tweet",
image : "the image from the tweet"
};
}
function getSoundCloud() {
return{
type : "soundcloud",
text : "the name of the song",
image : "the image of the song"
};
}
function display() {
content.forEach(function(item){
$("#container").append(item.text +"<br/>");
});
}
content should be an array of objects, each function adds its object into the content array :
var content = []; // empty array
getTweets();
getSoundCloud();
display();
function getTweets() {
content.push ({ //first result
type: "tweet",
text: "the text of the tweet",
image: "the image from the tweet"
});
}
function getSoundCloud() {
content.push ({ //second result
type: "soundcloud",
text: "the name of the song",
image: "the image of the song"
});
}
function display() {
content.forEach (v) {
// code to format the object v appropriately
var vtext = v.type + ' : ' + v.text;
$("#container").append(vtext);
}
}
Actually, just sussed it out like this
var content = {
text: this.text.linkify().linkuser().linktag(),
image: this.profile_image_url,
type: 'tweet'
};
arrayContent.push(content);
I can now loop through it, and each Content and display it!