Using jQuery and Math.random() to select nested objects properties - javascript

I'm creating a random quote machine that will present a random quote from various philosophers.
I have an object literal with nested objects containing philosophers and their quotes. Using jQuery functions and Math.random(), how can I select a random quote from my object literal structure? Is there a better way to organize the data?
I've started with a jQuery closure that will display a designated quote that I'd like to modify using Math.random().
Looking for explanations to solutions as I'm a beginner. Thanks in advance.
Example object literal:
var quotes =
{
awatts: {
name: "Alan Watts",
quote: "The only way to make sense out of change is to plunge into it, move with it, and join the dance."
},
etolle: {
name: "Eckhart Tolle",
quote: "Realize deeply that the present moment is all you ever have."
},
tmckenna: {
name: "Terrence Mckenna",
quote: "“The cost of sanity in this society, is a certain level of alienation” "
}
};
Example jQuery functions with single quote selected:
$(document).ready(function() {
$('.mybutton').click(function() {
$('#quote').html(quotes.awatts.quote);
});
});

The structure of the data seems fine. You could use an array, but an object isn't a problem.
You'd get the keys from the object, and then pick a random key
var quotes = {
awatts: {
name: "Alan Watts",
quote: "The only way to make sense out of change is to plunge into it, move with it, and join the dance."
},
etolle: {
name: "Eckhart Tolle",
quote: "Realize deeply that the present moment is all you ever have."
},
tmckenna: {
name: "Terrence Mckenna",
quote: "“The cost of sanity in this society, is a certain level of alienation” "
}
};
$('.mybutton').click(function() {
var keys = Object.keys(quotes);
var rand = keys[Math.floor(Math.random() * keys.length)];
$('#quote').html(quotes[rand].quote);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class="mybutton">Quote</button>
<br><br>
<div id="quote"></div>

If you can make your quotes object an array, the following would do the trick. Change your array
var quotes = [
{
name: "Alan Watts",
quote: "The only way to make sense out of change is to plunge into it, move with it, and join the dance."
},
{
name: "Eckhart Tolle",
quote: "Realize deeply that the present moment is all you ever have."
},
{
name: "Terrence Mckenna",
quote: "“The cost of sanity in this society, is a certain level of alienation” "
}
];
Set the max and min (to set the upper and lower limits for the random number)
var max = quotes.length, min = 0;
Generate a random number
var rand = Math.random() * (max - min) + min;
On the click event use the random number to choose your random quote
$('#quote').html(quotes[rand]quote);
I have not tested the code. Hope this will get you going :-)

Related

Why won't my code invoke this method of the object?

There is an event handler in the body tag.
<body onload="hangmanGame.populateQuestions();">
It is supposed to get a random position of the array...
const hangmanGame = {
obtainRandom(x) {
return Math.floor(Math.random() * Math.floor(x));
},
populateQuestions() {
let randNum = obtainRandom(5);
let numToPopulate = stemQuestions[randNum];
console.log(randNum);
console.log(numToPopulate);
},
stemQuestions : ['What do roots of a quadratic equation represent in a parabola?',
'What is a chemical process where a solid turns into a gas without going through a liquid stage',
'What is the name of the peculiar kind of inheritance pertinent to JavaScript?',
'What is the product of mass and velocity?',
'What is acceleration with respect to velocity?'],
stemAnswers : ['intercepts','sublimation','prototype','momentum','derivative']
}
But according to the console, both values are undefined...
Can you please give me some insight?
obtainRandom and stemQuestions are properties of hangmanGame, so in order to refer to them from inside populateQuestions you need to use this:
populateQuestions() {
let randNum = this.obtainRandom(5);
let numToPopulate = this.stemQuestions[randNum];
console.log(randNum);
console.log(numToPopulate);
}

Can Repeater Model execute JAVASCRIPT?

I have an XmlListModel in QML
XmlListModel {
id: model
source: "qrc:/Config/myConfig.xml"
query: "/levels/level"
XmlRole { name: "levName"; query: "#levName/string()" }
XmlRole { name: "from"; query: "from/number()" }
XmlRole { name: "to"; query: "to/number()" }
}
that reads this XML file
<levels parId = "3">
<level levelName = "level1">
<from>0</from>
<to>1</to
</level>
<level levelName = "level2">
<from>1</from>
<to>2</to>
</level>
</levels>
I also have a text element:
Text {
id: myText
x: 0; y:0
text: ""
}
I need to iterate through the XmlListModel in order to assign to myText.text the right level on the basis of what I found in myList.get(3).value, where myList is a ListModel.
Example:
if myList.get(3).value is between 0 (included) and 1 (excluded) I have to set myText.text = "level1", if it is between 1 (included) and 2 (excluded) I have to set myText.text = "level2", and so on...
Any suggestion?
Unfortunately you can't query your XmlListModel in O(1) like give me the value, where x is between role from and role to.
Good for you, you have an ordered list, so you can perform a binary search on your XmlListModel. The algorithm basically goes like this:
You first check whether your search value is by coincidence the one in the middle. If it is smaller, you search in the middle of the lower half, if it is larger, you search in the upper half... and so on.
With this you can find your value in O(log n) where n is the number of entries in your XmlListModel.
https://en.wikipedia.org/wiki/Binary_search_algorithm
If you have this implemented, to work on your model - either in JavaScript or in C++ or Python... you can have it like this:
Text {
text: binarySearch(model, myList.get(3).value).levName
}
When you implement this algorithm, make sure to deal with the gaps.

Unexpected Type Error - Javascript, multidimensional arrays

I'm learning to code Javascript. I'm trying to create a random quote generator. The idea is that I have a method that creates a multidimensional array, with each element array having a quote and the author's name. This method returns the multidimensional array.
I assign this returned multidimensional array to a variable and pick a random element array. It gives me an "Unexpected Type Error" in the console.
<script>
var colors = ['#16a085', '#27ae60', '#2c3e50', '#f39c12', '#e74c3c', '#9b59b6',
'#FB6964', '#342224', '#472E32', '#BDBB99', '#77B1A9', '#73A857'];
console.log("Hi!");
function getQuote(){
var quotesAndAuthors =
[
['But suicides have a special language. Like carpenters, they want to know "which tools", they never ask "why build"', "Anne Sexton"],
['Here is the world. Beautiful and terrible things will happen. Dont be afraid', 'Frederick Buechner'],
['All grown-ups were once children, but only a few of them remember it', 'Alexander de Saint-Exupery'],
['It was love at first sight, at last sight, at ever ever sight', 'Vladimir Nabokov'],
['A paradise the color of hell flames, but a paradise nonetheless', 'Vladimir Nabokov'],
['There is nothing like the deep breaths after laughing that hard. Nothing in the world like a sore stomach for the right reasons','Stephen Chbosky'],
['And then suddenly, something is over','Louise Gluck'],
['Adventure is out there!', 'Up (Pixar)'],
['The strong do what they can, and the weak suffer what the must', 'Thucydides'],
['But who prays for Satan? Who, in eighteen centuries, has had the common humanity to pray for the one sinner that needed it most?', 'Mark Twain'],
['I stopped explaining myself when I realized people only understand from their level of perception', 'Unknown'],
['Unexpressed emotions will never die. They are buried alive and will come forth in uglier ways', 'Sigmund Freud'],
['Genius might be the ability to say a profound thing in a simple way', 'Charles Bukowski']
];
return quotesAndAuthors;
}
function generate(){
var pickColor = Math.floor(Math.random * colors.length);
$('html body').animate({
backgroundColor: colors[pickColor]
}, 1000);
$('#text #author').animate({
color: colors[pickColor]
}, 500);
$('.buttons').animate({
backgroundColor: colors[pickColor]
},500);
var quotes = getQuote();
var n = Math.floor(Math.random * quotes.length);
var quoteText = quotes[n][0];
var quoteAuthor = quotes[n][1];
$('#text').text(quoteText);
$('#author').text(quoteAuthor);
}
$(document).ready(function(){
generate();
alert("Testing");
$('#quoteButton').on('click', generate());
});
</script>
Also, suggestions on how to store quotes more effectively would be appreciated.
random is a function and not a property. You should use paranthesis like
var n = Math.floor(Math.random() * quotes.length);
Also while adding event listeners, you should not use paranthesis, as this will call the method before even click event. Just give the function name.
$('#quoteButton').on('click', generate);
Also it's better to use arrary of objects in your case as below:
var quotesAndAuthors = [
{
"quote" : "But suicides have a special language",
"athour" : "Anne Sexton"
},
{
"quote" : "All grown-ups were once children",
"athour" : "Alexander de Saint-Exupery"
}
];
And you can access the quote as below using either of the method:
console.log(quotesAndAuthors[0]["quote"]);
console.log(quotesAndAuthors[0].quote);
.random is not a property of the Math object.
Math.random() is a method.
You wanted to call Math.random() because that's a function (note the parenthesis). That was generating your error.

random quote without back to back

I'm trying to pull a random quote from an array. I need to display an initial quote and then get a new one, no same two quotes back to back. Here's what I got.
$(document).ready(function() {
var quoter = [{
quote: "I drink to make other people more interesting.",
author: "Ernest Hemingway"
}, {
quote: "Alcohol may be man's worst enemy, but the bible says love your enemy.",
author: "Frank Sinatra"
}, {
quote: "Reality is an illusion created by a lack of alcohol.",
author: "N.F. Simpson"
},{
quote: "Time is never wasted when you’re wasted all the time.",
author: "Catherine Zandonella"
},{
quote: "I feel bad for people who don’t drink. When they wake up in the morning, that’s as good as they’re going to feel all day.",
author: "Frank Sinatra"
}];
var randomQuote = Math.floor(Math.random() * quoter.length);
//$(function () {
//Set Original Quote
$('#quoteText').text(quoter[randomQuote].quote);
$('#authorText').text(quoter[randomQuote].author);
//});
$('#btnNew').click(function(evt) {
//prevent browser's default action
evt.preventDefault();
//getting a new random number to attach to a quote and setting a limit
var sourceLength = quoter.length;
var randomNumber = Math.floor(Math.random() * sourceLength);
//set a new quote
//while ( randomNumber <= sourceLength ) {
while (randomNumber === randomNumber){
var newQuoteText = quoter[randomNumber].quote;
var newQuoteGenius = quoter[randomNumber].author;
var timeAnimation = 500;
var quoteContainer = $('#quoteContainer');
//fade out animation with callback
quoteContainer.fadeOut(timeAnimation, function() {
//set text values
$('#quoteText').text(newQuoteText);
$('#authorText').text(newQuoteGenius);
//console.log(quoteText,authorText);
//fadein animation.
quoteContainer.fadeIn(timeAnimation);
});
break;
}; //end while loop
}); //end btnNew function
}); //end document ready
I need to do this by using a while loop. I can't figure out how to store the random quote (array value) and then compare it to the new random one to get a different random on if it's the same.
The HTML is here:
<div id="quoteContainer">
<p><span id="quoteText"></span><Br/></p>
—<span id="authorText"> </span>
</div>
You can have a simple variable store the previous value, then check to see if the random number is the same as the last time.
$(document).ready(function(){
//....your current above code
var lastQuote = randomQuote;
$(button).click(function(){
var thisQuote = Math.floor(Math.random() * sourceLength);
//This will only be entered if the two are equal
//The while loop ensures that if you get a new random number
//it won't be the same
while(thisQuote == lastQuote){
thisQuote = Math.floor(Math.random() * sourceLength);
}
//If you make it here a unique number has been found
lastQuote = thisQuote;
});
});
Your approach might result in an infinite loop. Won't happen, because the random-number generator is not perfect but it can be done easier:
Either shuffel the array and go down linearly (or construct a fancy generator if you want) or just delete every quote that has been shown already.

One array or many? (hash table)

I've an array that is being used to store the conversion factors for a conversion program I'm currently working on.
A short Example:
var Length =
{
"lengthsA" :
{
"inch" : 0.0254,
"yard" : 0.9144,
"mile" : 1609.344,
"foot" : 0.3048,
"metres": 1
}}
This will become much bigger and there are many more of them.
It seems I have two options. I can either declare many arrays, one for each conversion type and in the function use and if else to dictate which one should be called upon for the conversion. The alternative is to use one huge array that stores everything. This would nullify the need for an if else and also remove the need to declare many arrays but at the cost of combining everything into what could become one big mess.
I'm in favour of the first option, mainly because I like modularity and it'd be easier for debugging / editing.
I'm also concerned about speed and access time. With one large array would there be an impact seeing as I'm using keys to determine what values are called. Key above would be "lengthsA"
Thanks.
If I were doing this project, I'd definitely use a hierarchical structure. I might start with something like this:
var conversions = {
length : {
lengthsA : {
inch : 0.0254,
yard : 0.9144,
mile : 1609.344,
foot : 0.3048,
metres: 1
},
lengthsB : {
. . .
}
},
mass : {
},
. . .
}
The structure is: conversions.<category>.<conversion_group>.<unit_name>. It's probably as easy to maintain as any other structure.
You might consider adding a property reference that would indicate the name of the unit that should be the reference (e.g., reference : "metres" in the case of lengthsA). I'd also be more consistent about unit names ("inch" is singular; "metres" is plural). Depending on your application, you might also want to have each conversion be a structure with a value and an uncertainty. (Some conversion factors are exact; others are not.)
Hard to say without knowing all the details of your program, but I wouldn't use hierarchical objects for storing units, but rather a flat array, similar to a SQL table:
units = [
{ category: "length", name: "inch" , value: 0.0254 },
{ category: "length", name: "yard" , value: 0.9144 },
{ category: "length", name: "mile" , value: 1609.344 },
{ category: "length", name: "foot" , value: 0.3048 },
{ category: "length", name: "meter", value: 1 }
]
You will need a couple of utility functions to find items in this table (like getUnitsByCategory), but once you've got it, you'll find this structure much easier to work with. Uniformity is the king!
if you define variable for javascript so..
var inch=0.0254,
yard=0.9144
youcan write
<option>inch</option>
and acces it with
window[document.select.textContent]
it's much faster but the code would be much longer.
In your case the readability is more important
so yes create a multidiminsional object.(groups)
it's also easier to access the values.
obj={
"length":{
inches:0.0254,
miles:1609.344,
},
"weight":{
kg:1
}
}
so you can access it by
obj.length.inches
or
obj['length']['inches']
and write
window.onload=function(){
var obj={
length:{
inches:0.0254,
miles:1609.344,
}
}
var select1=document.createElement('select'),
select2=null,
f=document.createDocumentFragment(),
input=document.createElement('input'),
convert=document.createElement('button');
for(var a in obj.length){
f.appendChild(document.createElement('option')).textContent=a;// easyway to access
}
select1.appendChild(f);
select2=select1.cloneNode(true);
input.type='text';
convert.textContent='Convert';
convert.addEventListener('click',function(e){
console.log(
input.value,
obj.length[select1.textContent],// easyway to access
obj.length[select2.textContent]// easyway to access
)
},false);
var bdy=document.body
bdy.appendChild(input);
bdy.appendChild(select1);
bdy.appendChild(select2);
bdy.appendChild(convert);
}

Categories

Resources