sorting an array of object by distance - javascript

I have a JSON array:
var details = [
{
'address':'Pantaloons,701-704, 7th Floor, Skyline Icon Business Park, 86-92 Off A. K. Road,Marol Village, Andheri East,Mumbai, Maharashtra 400059',
'lat':'19.099910',
'lng':'72.915373',
'time':'NA',
'sex':'Unisex',
'place':'mall'
},
{
'address':'Garodia Shopping Centre,Ghatkopar East,Mumbai, Maharashtra 400077',
'lat':'19.074185',
'lng':'72.908169',
'time':'NA',
'sex':'Male',
'place':'mall'
},
{
'address':'EF Mall,Andheri,Rambaug, MHADA Colony 20, Powai,Mumbai, Maharashtra 400076',
'lat':'19.119056',
'lng':'72.901324',
'time':'NA',
'sex':'Male',
'place':'mall'
},
];
which also have dynamic variable details.['distance'].Here getDistance() is haversine formula.
var dist = getDistance(lt,lg,lat,lng);
details[i]['distance'] = dist;
All these values in list gets displayed in div for which I want to sort the list by distance.
for (i = 0; i < details.length; i++) {
var add= details[i].address;
var lat = details[i].lat;
var lng = details[i].lng;
var time = details[i].time;
var latLng = new google.maps.LatLng(lat, lng);
var Gender = details[i].sex;
var type = details[i].place;
var dist = getDistance(lt,lg,lat,lng);
details[i]['distance'] = dist;
document.getElementById('list').innerHTML +='<p><img src="'+type+'.png" style="float:left;margin-right:5;"><div id="address"> ' + add +'</div><br><img style="height:30;float:right;" src="'+Gender+'.png" title="+Gender+"><a class="review" href="#">See Reviews</a>'+'<img style="float:right;margin-top:6;" src="write.png" title="Write a Review"><div id="time">Timings:'+ time +'</div>'+details[i].distance +'km'+'</p><hr/>';
}
My implementation is as follows
details.sort(function(a,b) { return parseFloat(a.distance) - parseFloat(b.distance) } );
However this only sorts values by distance and displays the other values of lists as it is like address,type(i.e it shows distance of some other address to some another address after sorting).The whole set of array must get sort without having wrong details.

var objs = [
{ first_nom: 'Lazslo', last_nom: 'Jamf' },
{ first_nom: 'Pig', last_nom: 'Bodine' },
{ first_nom: 'Pirate', last_nom: 'Prentice' }
];
for(var i=0; i<objs.length; i++){
objs[i]['distance'] = objs[i]['last_nom'];
}
function compare(a,b) {
if (a.distance < b.distance)
return -1;
if (a.distance > b.distance)
return 1;
return 0;
}
objs.sort(compare);
alert(JSON.stringify(objs));
out put: [{"first_nom":"Pig","last_nom":"Bodine","distance":"Bodine"},{"first_nom":"Lazslo","last_nom":"Jamf","distance":"Jamf"},{"first_nom":"Pirate","last_nom":"Prentice","distance":"Prentice"}]
DEMO

It's a bit hard to answer your question since there is no distance property in your array as pointed out by birdspider. In any case, your method should work. You can test this in the console.
var details = [{'distance':'24.1','b':99},{'distance':'-12.5','b':100},{'distance':'35.6','b':101}]
details.sort(function(a,b) { return parseFloat(a.distance) - parseFloat(b.distance) } )
Now check the details variable again and you'll see:
[{'distance':'-12.5','b':100},{'distance':'24.1','b':99},{'distance':'35.6','b':101}]

Related

How to display a result in .innerHTML from a chosen answer in an object

I want to make a website which asks some questions and then will generate 3 random locations based on the users answers. The part I am struggling with is getting the end result to output the locations based on the first question in the object which is:
const questions = [
{
"question": "What area of the world are you thinking of discovering next?",
"answer1": "Europe",
"answer1Array": "europeArray",
"answer2": "Asia",
"answer2Array": "asiaArray",
"answer3": "America",
"answer3Array": "americaArray",
"answer4": "Australasia",
"answer4Array": "australasiaArray"
},
let europeArray1 = ['Algarve - Portugal', 'Asturias and Covadonga - Spain', 'Mdina & Zebbug - Malta']
let asiaArray1 = ['Yakushima Island - Japan', 'Mount Wudang Shan - China', 'Bantayan Island - Philippines'] etc...
I have then created a function to give me back a random location:
let finalEuropeArray1 = europeArray1.sort(function() {
return 0.5 - Math.random();
});
and finally a function to output 3 results
function randomHoliday (array) {
if (array == europeArray1) {
return finalEuropeArray1.slice(europeArray1,3);
} else if (array == americaArray1) {
return finalAmericaArray1.slice(americaArray1,3);
} else if (array == asiaArray1 {
return finalAsiaArray1.slice(asiaArray1,3);
} else {
return finalAustralasiaArray1.slice(australasiaArray1,3);
}
I am able to return 3 separate values with a function calling the first element in each:
let resultA = function seperateArrayA (randomHoliday) {
return `1. ${randomHoliday[0]}`;}
let resultB = function seperateArrayB (randomHoliday) {
return `2. ${randomHoliday[1]}`;}
let resultC = function seperateArrayC (randomHoliday) {
return `3. ${randomHoliday[2]}`;}
but I do not know how to output this in my final .innerHTML based on the first question in the questions object. I can only get it to work by putting in a manual entry e.g. ${resultA(australasiaArray1)}
if(currentQuestion == totalQuestions) {
container.style.display = 'none';
result.innerHTML =
`<h1 class="final-score">Our Top 3 Recommendations:</h1>
<div class="summary">
<p><br></br></p>
<p>${resultA(australasiaArray1)}</p>
<p>${resultB(australasiaArray1)}</p>
<p>${resultC(australasiaArray1)}</p>
</div>
<button class="restart">Restart Quiz</button>
`
};
The setup can be simplified by using nested objects for related answers, checkout the demo below:
const questions = [
{
"question": "What area of the world are you thinking of discovering next?",
"answers": {
"Europe": {
"label": "Europe",
"locations": ['Algarve - Portugal', 'Asturias and Covadonga - Spain', 'Mdina & Zebbug - Malta']
},
"Asia": {
"label": "Asia",
"locations": ['Yakushima Island - Japan', 'Mount Wudang Shan - China', 'Bantayan Island - Philippines']
}
}
}
];
let getRandomLocationForAnswer = function (question, answer) {;
const possibleLocations = question.answers[answer].locations;
const randomIndex = Math.floor((Math.random()*possibleLocations.length));
return possibleLocations[randomIndex];
}
let buildSelect = function(questions){
return questions.map((question, index) => {
const possibleAnswers = Object.keys(question.answers);
return`<select class="question" data-question-index="${index}">${possibleAnswers.map(l => `<option value="${l}">${l}</option>`)}</select>`;
}).join('');
}
let showResults = function(questions, questionIndex, answer){
const question = questions[questionIndex];
document.querySelector('#results').innerHTML =
`<h1 class="final-score">Our Top 3 Recommendations:</h1>
<div class="summary">
<p><br></br></p>
<p>${getRandomLocationForAnswer(question, answer)}</p>
<p>${getRandomLocationForAnswer(question, answer)}</p>
<p>${getRandomLocationForAnswer(question, answer)}</p>
</div>
<button class="restart">Restart Quiz</button>
`
}
document.querySelector('#questions').innerHTML += buildSelect(questions);
document.querySelectorAll('.question').forEach(question => {
question.addEventListener('change', e => {
const select = e.currentTarget;
showResults(questions, parseInt(select.dataset.questionIndex), select.value);
});
});
<section id="questions">
</section>
<section id="results">
</section>
resultA, resultB, resultC are functions, not values. if you put them in the template you will get a function reference and not the result of the function. To get the result you need to call the function(which you do in the last code snippet).
in order to get it to work simply define variables and set them to the function result:
if(currentQuestion == totalQuestions) {
container.style.display = 'none';
var l_resultA = resultA(australasiaArray1)
...
result.innerHTML =
`<h1 class="final-score">Our Top 3 Recommendations:</h1>
<div class="summary">
<p><br></br></p>
<p>${l_resultA}</p>
....
</div>
<button class="restart">Restart Quiz</button>`
};

How to work with multidimensional-arrays in Javascript?

I'm trying to make a code that works like this:
Get number of teams (y) and number of players(x).
Get x names and x ranks.
Create balance teams based on the player ranks.
Each team should have x/y players.
Print each team separately.
I can't see where is my problem and why my code doesn't work. Hope you guys could help.
This is my code:
function step1() {
var teams = document.getElementById("teams").value;
var players = document.getElementById("players").value;
var main = document.getElementById("main");
main.innerHTML="";
for(var i=1;i<=players;i++){
main.innerHTML += "<input class='names' placeholder='Player "+i+"' type='text' style='width:100px'/> "+
"<input class='ranks' placeholder='Rank' type='text' style='width:40px'/><br/>";
}
main.innerHTML+="<br/><button onclick='buildTeams("+players+","+teams+")'>Build</button>";
}
function buildTeams(playersInt,teamsInt) {
var error=0;
var names = new Array(playersInt);
var ranks = new Array(playersInt);
var nameInp = document.getElementsByClassName("names");
var rankInp = document.getElementsByClassName("ranks");
for(var i=0;i<playersInt;i++) {
names[i] = nameInp[i].value;
}
for(var i=0;i<playersInt;i++) {
ranks[i] = rankInp[i].value;
}
var teams = new Array(teamsInt);
for(var i=0;i<teamsInt;i++) {
teams[i]=new Array(playersInt/teamsInt);
}
for(var i=0;i<(playersInt/teamsInt);i++) {
for(var j=0;j<teamsInt;j++) {
teams[i][j]=names[checkMvp(ranks)];
ranks[checkMvp(ranks)]=-1;
}
}
for(var i=0;i<teamsInt;i++) {
alert(teams[i]);
}
}
function checkMvp(ranks) {
var high= ranks[0];
var bpi=0;
for(var i=1;i<ranks.length;i++) {
if(ranks[i]>high) {
bpi=i;
}
}
return bpi;
}
<h2>Power Balance</h2>
<div id="main">
Number of teams:
<input type="text" id="teams" style="width:30px"/>
<br/><br/>
Number of players:
<input type="text" id="players" style="width:30px"/>
<br/><br/>
<p id="error"></p>
<input type="button" onclick="step1()" value="Next"/>
</div>
Check out my solution here. It should be working fine. You mistakenly swapped the logic in the loop for adding players to teams. Also, it's a good habit to use Array.prototype.push than to create new element using a loop function after creating the array with new Array(length).
function step1() {
var teams = document.getElementById("teams").value;
var players = document.getElementById("players").value;
var main = document.getElementById("main");
main.innerHTML="";
for(var i=1;i<=players;i++){
main.innerHTML += "<input class='names' placeholder='Player "+i+"' type='text' style='width:100px'/> "+
"<input class='ranks' placeholder='Rank' type='text' style='width:40px'/><br/>";
}
main.innerHTML+="<br/><button onclick='buildTeams("+players+","+teams+")'>Build</button>";
}
function buildTeams(playersInt,teamsInt) {
var error=0;
var names = [];
var ranks = [];
var nameInp = document.getElementsByClassName("names");
var rankInp = document.getElementsByClassName("ranks");
for(var i=0;i<playersInt;i++) {
names.push(nameInp[i].value);
}
for(var e=0;e<playersInt;e++) {
ranks.push(rankInp[e].value);
}
var teams = [];
for(var x=0;x<teamsInt;x++) {
teams.push([]);
}
for(var a=0;a<teamsInt;a++) {
for(var j=0;j<(playersInt/teamsInt);j++) {
console.log(teams[a]);
teams[a].push(names[checkMvp(ranks)]);
ranks[checkMvp(ranks)]=-1;
}
}
alert(teams);
for(var w=0;w<teamsInt;w++) {
alert(teams[w]);
}
}
function checkMvp(ranks) {
var high= ranks[0];
var bpi=0;
for(var i=1;i<ranks.length;i++) {
if(ranks[i]>high) {
bpi=i;
}
}
return bpi;
}

Angular JS: Multiple Data Bindings Into Table

Okay. I'm pulling together a data table that is going to look through majors and minors of a school. I'm running into issues of trying not to repeat myself in the data where every possible, but am not sure how to get the data pulled into the document, or even how to setup the data into the different arrays. Looking for some advice and help in whichever of these two areas I can find. When I search through docs and API's none of them seem to go deep enough into the data to really get what I'm looking to accomplish.
I have made a plunker to showcase my problem more clearly, or at least I hope to make it clearer.
http://plnkr.co/edit/2pDmQKKwjO6KVullgMm5?p=preview
EDIT:
It would even be okay with me if the degree each degree could be read as a boolean, and same with Education level. I'm just not sure how to go about it without repeating the whole line in a new table row. http://www.clemson.edu/majors
HERE IS THE HTML
<body ng-app="app">
<h2> Majors and Minors </h2>
<table ng-controller="MajorsCtrl">
<tbody>
<tr>
<th>Department</th>
<th>Major</th>
<th>Education Level</th>
<th>Location </th>
<th>Degree</th>
<th>Department Website </th>
</tr>
<tr ng-repeat="major in majors">
<td>{{major.Department}}</td>
<td>{{major.Major}}</td>
<td>{{major.EdLevel}}</td>
<td>{{major.Type}}</td>
<td>{{major.Degree}}</td>
<td>{{major.Website}}</td>
</tr>
</tbody>
</table>
</body>
HERE IS THE JS
var app = angular.module('app', []);
// Majors and Minors Data That will be injected into Tables
app.controller('MajorsCtrl', function($scope) {
// Heres where it gets tricky
// Now I have biology with four diff degree types
// Biology with 2 diff EdLevels
// How do I combine all of these into 1 Group without repeating
var majorsInfo = [
{
Department:'Statistics',
Major:'Applied Statitistics',
EdLevel:'Graduate',
Type:'Campus/Online',
Degree:'Graduate Certificate',
Website: 'http://biology.wvu.edu',
},
{
Department:'Biology',
Major:'Biology',
EdLevel:'Graduate',
Type:'Campus',
Degree:'PH.D' ,
Website: 'http://biology.wvu.edu',
},
{
Department:'Biology',
Major:'Biology',
EdLevel:'Graduate',
Type:'Campus',
Degree:'M.S' ,
Website: 'http://biology.wvu.edu',
},
{
Department:'Biology',
Major:'Biology',
EdLevel:'Undergraduate',
Type:'Campus',
Degree:'B.A.' ,
Website: 'http://biology.wvu.edu',
},
{
Department:'Biology',
Major:'Biology',
EdLevel:'Undergraduate',
Type:'Campus',
Degree:'B.S.' ,
Website: 'http://biology.wvu.edu',
},
];
$scope.majors = majorsInfo;
});
This seems to be a question about modeling the data. I took a few assumptions:
A department can offer multiple majors
A department has a website
Each major can offer one to many Educations (i.e. Education Level, On/Off Campus, Degree)
The department can offer multiple minors with the same data structure as majors
I modeled a set of "enums" and Programs/Departments after your data. I used enums for ease of updating the values in multiple locations:
app.factory("EducationEnums", function () {
var EdLevels = {
GRAD: "Graduate",
UGRAD: "Undergraduate"
};
var Types = {
CAMPUS: "Campus",
ONLINE: "Online",
HYBRID: "Campus/Online"
};
var Degrees = {
PHD: "PH.D",
MS: "M.S.",
BS: "B.S.",
BA: "B.A.",
GCERT: "Graduate Certificate"
};
return {
EdLevels: EdLevels,
Types: Types,
Degrees: Degrees
}
});
app.factory("Programs", function (EducationEnums) {
var EdLevels = EducationEnums.EdLevels;
var Types = EducationEnums.Types;
var Degrees = EducationEnums.Degrees;
return [
{
Department: "Biology",
Website: "http://biology.wvu.edu",
//Majors offered by department
Majors: [{
Major: "Biology",
Education: [
{
EdLevel: EdLevels.GRAD,
Type: Types.CAMPUS,
Degree: Degrees.PHD
},
{
EdLevel: EdLevels.GRAD,
Type: Types.CAMPUS,
Degree: Degrees.MS
},
{
EdLevel: EdLevels.UGRAD,
Type: Types.CAMPUS,
Degree: Degrees.BA
},
{
EdLevel: EdLevels.UGRAD,
Type: Types.CAMPUS,
Degree: Degrees.BS
}
]
}],
Minors: [{
//Minors can go here
}]
},
{
Department: "Statistics",
Website: "http://biology.wvu.edu",
Majors: [{
Major: "Applied Statistics",
Education: [
{
EdLevel: EdLevels.GRAD,
Type: Types.HYBRID,
Degree: Degrees.GCERT
},
{
EdLevel: EdLevels.UGRAD,
Type: Types.CAMPUS,
Degree: Degrees.BS
}
]
}],
Minors: [{
//Minors can go here
}]
}
]
});
Next, I made a Majors service that uses this Programs data to build ViewModels (to be bound to scope in the controllers). Here you can build your original table, or you can build a matrix (like the Clemson site):
app.service("Majors", function (Programs, EducationEnums) {
var Degrees = this.Degrees = EducationEnums.Degrees;
//Build ViewModel for all details
this.getMajorDetails = function () {
var arr = [];
var programLen;
var majorLen;
var eduLen;
for (var i = 0; i < (programLen = Programs.length); ++i) {
var p = Programs[i];
var dept = p.Department;
var ws = p.Website;
var Majors = p.Majors;
for (var j = 0 ; j < (majorLen = Majors.length); ++j) {
var maj = Majors[j].Major;
var edu = Majors[j].Education;
for (var k = 0; k < (eduLen = edu.length); ++k) {
arr.push({
Department: dept,
Major: maj,
EdLevel: edu[k].EdLevel,
Type: edu[k].Type,
Degree: edu[k].Degree,
Website: ws
});
}
}
}
return arr;
}
//Build ViewModel for Degrees offered (similar to Clemson)
this.getMajorMatrix = function () {
var arr = [];
var programLen;
var majorLen;
var eduLen;
for (var i = 0; i < (programLen = Programs.length); ++i) {
var p = Programs[i];
var Majors = p.Majors;
for (var j = 0; j < (majorLen = Majors.length); ++j) {
var maj = Majors[j].Major;
var edu = Majors[j].Education;
var obj = {
Major: maj
};
for (var k = 0; k < (eduLen = edu.length); ++k) {
var degree = edu[k].Degree;
if (degree === Degrees.PHD) {
obj.PHD = true;
}
else if (degree === Degrees.MS) {
obj.MS = true;
}
else if (degree === Degrees.BS) {
obj.BS = true;
}
else if (degree === Degrees.BA) {
obj.BA = true;
}
}
arr.push(obj);
}
}
return arr;
}
});
Your controller can just call the Majors service methods to bind the ViewModel to the $scope:
app.controller('MajorsCtrl', function($scope, Majors) {
$scope.majorDetails = Majors.getMajorDetails();
});
app.controller("MajorMatrixCtrl", function ($scope, Majors) {
$scope.Degrees = Majors.Degrees;
$scope.majorMatrix = Majors.getMajorMatrix();
});
Separting like this would allow you to later update the Programs factory to not just use static data, but could pull from a service via $http for instance. The Programs data can be manipulated to achieve your desired ViewModel through the Majors service (and Minors service if you choose to write a separate one).
Updated Plunkr

Javascript object oriented pirate translator

I need to make an object oriented pirate translator in javascript for my final, I have an idea and have some code but can't get it to output correctly on my page. I have it set up so you type the english phrase in one box and then in the other box it spits out the pirate version. I will not step through my array of objects. I will post code. Thanks for any help I can get!!!
var $ = function(id) { return document.getElementById(id); }
var Dictionary = [{
Greetings: {
hello:"ahoy",
hi:"yohoho",
pardon_me:"avast",
excuse_me:"arrr"
},
People: {
stranger:"scurvy",
sir:"matey",
madam:"proud beauty",
miss:"comely wench",
officer:"foul blaggart",
enemy:"scallywag"
},
Questions: {
where_is:"whar be",
can_you_help_me_find:"know ye",
is_that:"be that",
how_far_is_it_to:"how many leagues to"
},
Articles: {
the:"th",
a:"a briny",
any:"some godforsaken",
nearby:"broadside",
my:"me",
your:"yer"
},
Adjectives: {
old:"barnacle-covered",
attractive:"comely",
happy:"grog-filled"
},
Places: {
restroom:"head",
restaurant:"galley",
hotel:"fleabag inn",
mall:"market",
pub:"Skull & Scuppers",
bank:"buried trasure"
},
Desires: {
I_would_like_to:"I be needin to",
I_desire:"I have a fierce fire in me belly",
I_wish_I_knew_how_to:"I be hankerin to",
my_mother_told_me_to:"me dear ol mum, bless her black soul, tol me to",
my_companion_would_like_to:"me mate, ol Rumpot, wants to"
},
Actions: {
find:"come across",
take_a_nap:"have a bit of a lie down",
make_a_withdrawal:"seize all yer doubloons",
have_a_cocktail:"swill a pint or two of grog",
kill_him:"blow the man down",
frown:"hang the jib",
take_a_hike:"walk the plank"
},
}];
function Translate(text)
// Returns: a copy of text with English phrases replaced by piratey equivalents
{
for (var i = 0; i < Dictionary.length; i++) {
var toReplace = new RegExp("\\b"+Dictionary[i][0]+"\\b", "i");
var index = text.search(toReplace);
while (index != -1) {
text = text.replace(toReplace, Dictionary[x][y]);
index = text.search(toReplace);
}
}
text = text.replace(/\./g, function() {
return Math.random() < 0.5 ? ". arrrrrrrrr" : "."
});
return text.charAt(0).toUpperCase() + text.substring(1);
}
var clear_click = function() {
$("output1").value = "";
$("output2").value = "";
}
window.onload = function() {
$("clear").onclick = clear_click;
}
/*for (var x in Dictionary) {
for (var y in Dictionary[x])
console.log (y, Dictionary[x][y]);
}*/
HTML:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title> Pirate Translator </title>
<script src="js/test2.js"></script>
<link rel="stylesheet" href="css/normalize.css"/>
<link rel="stylesheet" href="css/styles.css"/>
</head>
<body>
<h1>Jacob's Pirate Translator</h1>
<p>Simply click on the buttons to translate<br />
words and/or phrases from English to pirate talk.
<hr />
<form name="TalkForm">
<table>
<tr><td align="center"><b>English</b>
<td>
<td align="center"><b>Pirate</b>
<tr><td><textarea name="English" id="output1" rows=12 cols=35 wrap="virtual"></textarea> </td>
<td align="center"> <br />
<input type="button" value="Translate --->"
onclick="document.TalkForm.Pirate.value =
Translate(document.TalkForm.English.value);"> </td>
<td><textarea name="Pirate" id="output2" rows=12 cols=35 wrap="virtual"></textarea> </td>
<input type="button" id="clear" value="clear">
</tr>
</table>
</form>
</body>
</html>
EDIT2: I've modified your Dictionary. If you follow the format of my Dictionary you can go as deep of arrays as you want. It should work. I've tested with your examples in all different kinds of orders and with text not found in the dictionary. Feel free to try it out.
And to add to the challenge, I made recursive functions. :D No for/while loops.
DEMO
var Dictionary = {
hello: "ahoy",
hi: "yohoho",
pardon: [1, {
me: "avast"
}],
excuse: [1, {
me: "arrr"
}],
stranger: "scurvy",
sir: "matey",
madam: "proud beauty",
miss: "comely wench",
officer: "foul blaggart",
enemy: "scallywag",
where: [1, {
is: "whar be"
}],
can: [4, {
you_help_me_find: "know ye"
}],
is: [1, {
that: "be that"
}],
how: [4, {
far_is_it_to: "how many leagues to"
}],
the: "th",
a: "a briny",
any: "some godforsaken",
nearby: "broadside",
my: "me",
your: "yer",
old: "barnacle-covered",
attractive: "comely",
happy: "grog-filled",
restroom: "head",
restaurant: "galley",
hotel: "fleabag inn",
mall: "market",
pub: "Skull & Scuppers",
bank: "buried trasure",
would: [1, {
like: "be needin"
}],
I: [
[1, {
desire: "I have a fierce fire in me belly"
}],
[5, {
wish_I_knew_how_to: "I be hankerin to"
}]
],
my: [
[4, {
mother_told_me_to: "me dear ol mum, bless her black soul, tol me to"
}],
[4, {
companion_would_like_to: "me mate, ol Rumpot, wants to"
}]
],
find: "come across",
take: [2, {
a_nap: "have a bit of a lie down"
}],
make: [2, {
a_withdrawal: "seize all yer doubloons"
}],
have: [2, {
a_cocktail: "swill a pint or two of grog"
}],
kill: [1, {
him: "blow the man down"
}],
frown: "hang the jib",
take: [2, {
a_hike: "walk the plank"
}]
};
function translate(text) {
var hop = 1;
var textToReturn = "";
//checking if the text is already split, if not we split
if (typeof text === 'string') {
text = text.split(' ');
}
if (text.length > 0) {
if (typeof Dictionary[text[0]] == 'undefined' || typeof Dictionary[text[0]] === 'string') {
textToReturn = (Dictionary[text[0]] || text[0]);
text = text.slice(hop, text.length);
} else {
var info = recursiveCheck(text, Dictionary[text[0]]);
textToReturn = (info.hop == 1) ? text[0] : info.text;
text = text.splice(info.hop, text.length);
}
if(text.length > 0)
{
textToReturn += ' ' + translate(text);
}
}
return textToReturn;
}
function recursiveCheck(text, arr)
{
var found = {hop:1, text: ''};
if(arr.length > 0)
{
if(typeof parseInt(arr[0]) === 'number' && text.length-1 >= arr[0])
{
var phrase = text.slice(1, arr[0]+1);
if(arr[1][phrase.join('_')])
{
found.hop = arr[0]+1;
found.text = arr[1][phrase.join('_')];
}
}
else
{
found = recursiveCheck(text, arr[0] || []);
if(found.hop == 1 && arr.length > 1)
{
found = recursiveCheck(text, arr.slice(1, arr.length));
}
}
}
return found;
}
var tra = document.getElementById('translate');
var pir = document.getElementById('pirate');
pir.disabled = true;
var eng = document.getElementById('english');
eng.onkeyup = function(){
pir.value = "";
}
tra.onclick = function () {
pir.value = translate(eng.value);
};
HERE is an example of a deep array if you want to go further with the dictionary:
...
I: [
[1, {
desire: [
[1,{ a: "I have a fierce fire in me belly"}],
[1,{ one: "I have one fierce fire in me belly"}]
}],
[5, {
wish_I_knew_how_to: "I be hankerin to"
}]
],
...
Of course I haven't tried it yet, but you can if you actually need it to work. Good luck.
EDIT: The point of this code is to show how to access your list. You don't seem to be using categories in your code, so why have them?
Your list looks a bit complex for a simple translation. Last I checked, dictionaries don't have categories.. Joke aside I've simplified your list.
var Dictionary = {
hello:"ahoy",
hi:"yohoho",
pardon_me:"avast",
excuse_me:"arrr",
stranger:"scurvy",
sir:"matey",
madam:"proud beauty",
miss:"comely wench",
officer:"foul blaggart",
enemy:"scallywag",
where_is:"whar be",
can_you_help_me_find:"know ye",
is_that:"be that",
how_far_is_it_to:"how many leagues to",
the:"th",
a:"a briny",
any:"some godforsaken",
nearby:"broadside",
my:"me",
your:"yer",
old:"barnacle-covered",
attractive:"comely",
happy:"grog-filled",
restroom:"head",
restaurant:"galley",
hotel:"fleabag inn",
mall:"market",
pub:"Skull & Scuppers",
bank:"buried trasure",
I_would_like_to:"I be needin to",
I_desire:"I have a fierce fire in me belly",
I_wish_I_knew_how_to:"I be hankerin to",
my_mother_told_me_to:"me dear ol mum, bless her black soul, tol me to",
my_companion_would_like_to:"me mate, ol Rumpot, wants to",
find:"come across",
take_a_nap:"have a bit of a lie down",
make_a_withdrawal:"seize all yer doubloons",
have_a_cocktail:"swill a pint or two of grog",
kill_him:"blow the man down",
frown:"hang the jib",
take_a_hike:"walk the plank"
};
function translate(text)
{
pir.value = Dictionary[text.split(' ').join('_')] || 'not found';
}
var tra = document.getElementById('translate');
var pir = document.getElementById('pirate');
pir.disabled = true;
var eng = document.getElementById('english');
tra.onclick = function(){ translate(eng.value) };
html:
<input id="english" type="text" placeholder="english"/>
<input id="pirate" placeholder="pirate"/>
<button id="translate">Translate</button>
I've simplified the code (by a lot) so I could get a simple working model.
Working jsfiddle: http://jsfiddle.net/Grimbode/f296h/2/

Making a quiz app, stuck on a function

I'm making a simple quiz app. But I'm stuck on ordering the functions.
Here is the code
// questions set
var qtnsSet = [
// format: [question, [comma, separated, options], index of correct ans. eg. 1]
["What is the full form of IP?", ["Internet Provider", "Internet Port", "Internet Protocol"], 2],
["Who is the founder of Microsoft?", ["Bill Gates", "Steve Jobs", "Steve Wozniak"], 0],
["Full name of IBM?", ["Internet Business Machine", "International Business Machine", "Indian Business Machine"], 1]
]
// init vars
var qtnNo = 0,
score = 0;
// define elements
var qtnContainer = $("qtn-container"),
optnsContainer = $("optns-container"),
submitBtn = $("submit-btn");
function $(id) { // Shortcut for document.getElementById
return document.getElementById(id);
}
function askQtn() { // ask question
var optns = qtnsSet[qtnNo][1], // options array
optnsHtml = "";
for (var optnNo = 0; optnNo < optns.length; optnNo++) {
optnsHtml += createOptnHtml(optnNo, optns[optnNo]);
}
qtnContainer.textContent = qtnsSet[qtnNo][0]; // question
optnsContainer.innerHTML = optnsHtml; // options
}
function createOptnHtml(optnNo, optn) { // create html elements for options
// eg. <li><input type='radio' name='optn' value='Option' id='optn-0'>
// <label for='optn-0'>Option</label></li>
return "<li><h3><input type='radio' name='optn' value='" + optn + "' id='optn-" + optnNo + "'>" +
" <label for='optn-" + optnNo + "'>" + optn + "</label></h3></li>";
}
function getGivenAns() { // get the answer given by user
var optns = document.getElementsByName("optn");
for (var optnNo = 0; optnNo < optns.length; optnNo++) {
if (optns[optnNo].checked) {
return optnNo; // index of the chosen answer
}
}
}
function checkAns() { // check if user's right or not
if (getGivenAns() == qtnsSet[qtnNo][2]) {
score += 6; // 6 points for right answer
}
}
function submitAns() {
if (qtnNo <= qtnsSet.length) {
if (getGivenAns()) {
checkAns();
qtnNo++;
askQtn();
} else {
alert("Please choose an answer.");
};
} else {
alert("Score: " + score);
};
}
window.addEventListener("load", askQtn, false);
submitBtn.addEventListener("click", submitAns, false);
I'm unable to configure the submitAns() function so that every thing works correctly.
How can I order the functions inside submitAns()?
getGivenAns()
Returns the index of the options, which can be 0 if the first option is selected which would evaluate to false here:
if (getGivenAns()) {
so just return true if an option is checked.
Also
if (qtnNo <= qtnsSet.length) {
Will be true after the last question it should just be
if (qtnNo < qtnsSet.length) {

Categories

Resources