I'm quite new to web dev and am giving my very first steps in AJAX functions and HTTP requests.
I only know vanilla JS, CSS and HTML. I also know very very little about regExps so would really appreciate if answers could respect this.
I'm developing a simple quiz game where I fetch Q&As from opentdb. The data is saved in an array of questions with the following format (notice the ' on correct-answer):
[..., {
category: "Entertainment: Film",
type: "multiple",
difficulty: "medium",
question: "What Queen song plays during the final fight scene of the film "Hardcore Henry"?",
correct_answer: "Don't Stop Me Now",
incorrect_answers: [
"Brighton Rock",
"Another Bites the Dust",
"We Will Rock You"
]
}, ...]
After having successfully fetched the data the first thing I do is to put all the correct answers in an array which I use later to compare with the user's selected answer. My array of correct answers, in this example would be something like (again notice the '):
[... ,"Don't Stop Me Now", ...]
When I render the questions and answers to the DOM, by creating the necessary elements and using innerHTML everything shows up well on the browser (i.e. instead of ' I get the actual '.
However, later, when I'm collecting the user's selected answer with:
const selectedAnswer = event.currentTarget.innerHTML
I get "Don't Stop Me Now" and when I compare this with my array of correct answers, I get something like:
"Don't Stop Me Now" === "Don't Stop Me Now"
which returns false when, in fact should be true because is the correct answer...
How do I solve this?
Well ' is a HTML Entity. So I create a new element, then set its innerHTML property to the text with the HTML entity then compare it's innerText with the user's input.
const text = "Don't Stop Me Now";
const checkAnswer = (correct, input) => Object.assign(document.createElement('span'), { innerHTML: correct }).innerText == input;
console.log(checkAnswer(text, "Don't Stop Me Now"));
' is HTML Entity code for '. so if this only what you concern, you could try to map that array first and replace/convert that HTML Entity code into character, like this:
[... ,"Don't Stop Me Now", ...].map(item => item.replace(/'/g, "'"));
You could try using backticks instead of the HTML code for '.
[... ,`Don't Stop Me Now`, ...]
Related
I have an array of objects that is basically like this.
const characters = [
{
id: 1
name: batman
biography: {
born-in: gotham
good-or-bad: good
}
stats: {
strength: 85
speed: 90
intelligence: 95
}
}
{
id: 2
name: superman
biography: {
born-in: krypton
good-or-bad: good
}
stats: {
strength: 90
speed: 85
intelligence: 80
}
}
{
id: 3
name: joker
biography: {
born-in: gotham
good-or-bad: bad
}
stats: {
strength: 70
speed: 95
intelligence: 100
}
}
]
Then, after mapping and displaying the objects in my page, I add a button that allows the user to mark the character as a favorite. The user can only add up to 6 favorites.
const [favorites, setFavorites = useState([]);
const addFavorite = () => {
favorites.length === 6 ?
console.log("favorites' list is full!") :
setFavorites(favorites.concat(character))
}
{characters.map((character)=>{
const {props} = character;
return (
<div>{props}</div>
<button onClick={addFavorite}>add to favorites</button>
);
})}
Now, what I want to do (and I don't know how to, after many attempts)
preventing the user to add the same character twice to favorites. (I have tried with favorites.contains(character)? or favorites.contains({character})? but it didn't work.)
if the character is already a favorite, make the button change to a button that removes the favorite instead (changing both the function and the button text.)(I have no idea how to do this).
Make an average score of all favorites' each stat. (For example, with your chosen favorites your average speed is xxx and your average strength is xxx).
Last, but not least, favorites list must have up to 3 good characters and 3 bad characters. So, if the good or bad characters in the favorites' list are already 3, user cannot choose another good or bad character as favorite. I also don't know how to proceed with this one.
I'm working in a school project and I found my way through most of it, but I realise I still have things to learn, mostly about object props and how to access to them. Thank you. If anything is not clear, please say so and I will add the required data.
So, since you've already figured it out yourself, here is the detailed explanation.
find is a function ( or what fancy developers like to say a higher order function ) available for javascript arrays that accepts a function which must return a boolean value i.e., either true or false.
---Quick detour---
A function which must return a boolean value is called a predicate, and this is exactly what's available in the IDE hints if you hover over find
---Detour end---
It accepts multiple parameters, with only the predicate being mandatory, and the rest are optional, i'm skipping all the optional ones, so that's your homework, read the docs or the articles at the end of this answer.
As you can read in the hint itself, it will call the predicate, once for each element in the array, until it can find one which will return true & return the value of the element, undefined otherwise.
Which means : that the first parameter in the predicate is going to be your object and the same predicate will be executed on it for all the elements.
Now observe your solution carefully:
find( savedChar => savedChar.id === character.id )
savedChar is one of the objects in the array, and it needs to be compared with the character object, and id which is the short form of identity will always find it accurately.
Finally, quick answers to your problems.
Use find to see if the character is already available, if yes, simply don't add it in your collection.
This will require you to change your render logic, find if the object is in the favorites and render it differently.
just like find, there is a method called reduce, why don't you give it a shot? but that might be a little difficult, so you can use a simple for loop instead.
find(savedChar => savedChar["good-or-bad"]) <- what would this result? figure it out.
And for more reading material :
https://medium.com/swlh/array-helper-methods-in-es6-28fc5e5a5dc9
same but more detailed :
https://codeburst.io/learn-and-understand-es6-helpers-easily-d41401184487
I'm currently working on some practice for JavaScript and am really confused about what I am to do here. Any help would be appreciated!
Define a method named orderOfAppearance() that takes the name of a role as an argument and returns that role's order of appearance. If the role is not found, the method returns 0. Ex: orderOfAppearance("Elizabeth Swann") returns 3. Hint: A method may access the object's properties using the keyword this. Ex: this.title accesses the object's title property.
// Code will be tested with different roles and movies
let movie = {
title: "Pirates of the Caribbean: At World's End",
director: "Gore Verbinski",
composer: "Hans Zimmer",
roles: [ // Roles are stored in order of appearance
"Jack Sparrow",
"Will Turner",
"Elizabeth Swann",
"Hector Barbossa"
],
orderOfAppearance: function(role) {
/* Your solution goes here */
if (!(role in this.roles)) {
return 0;
}
return this.role;
/*Solution ends here */
}
};
A doubly linked list has 2 links. Let's use common sense for a moment instead of blind deferral to whatever you think your TA said: "Doubly linked list" obviously implies "2 links", otherwise that'd be an extremely silly name, no?
So, there must be 2 links. You seem to be under the impression that 'you must not have a pointer to the tail' implies 'there must be only one link'. That can't be right, what with 'doubly linked list' and all.
The right answer is presumably that each node has 2 links, but these links aren't 'head and tail', but 'next' and 'previous'.
For a ringed list (where moving forward from the last element gets you back to the first, and moving backwards from the first element gets you to the last), the last node's "next" link goes back to the first node, and conversely, the first node's "previous" link goes to the last (so it points at the same thing a hypothetical 'tail' would point to).
However, that'd be only true for the first node in your linked list structure (that would be the only node for which 'prev' points at the tail).
Your TA either means 'have next/prev links, not next/tail links' as per above, or has no idea what they are talking about. Let's give em the benefit of the doubt ;) – as it's homework I'll leave the actual writing of the data structure, using a definition of DoublyLinkedNode<T> that includes fields DoublyLinkedNode<T> next, prev;, as an exercise for you.
What I was looking for was to refer to the last use first.getPrev(), since its a circle the last is before the first.
I have the same question. This is found in a zybooks online textbook. The textbook's portion of JavaScript is horrible!! It explains little about what we need to do to solve the questions posed. I have been so frustrated and had to look to online sources to try to solve the problems in the book. Was there a solution to this question?
Define a method named orderOfAppearance() that takes the name of a role as an argument and returns that role's order of appearance. If the role is not found, the method returns 0. Ex: orderOfAppearance("Elizabeth Swann") returns 3. Hint: A method may access the object's properties using the keyword this. Ex: this.title accesses the object's title property.
// Code will be tested with different roles and movies
let movie = {
title: "Pirates of the Caribbean: At World's End",
director: "Gore Verbinski",
composer: "Hans Zimmer",
roles: [ // Roles are stored in order of appearance
"Jack Sparrow",
"Will Turner",
"Elizabeth Swann",
"Hector Barbossa"
],
orderOfAppearance: function(role) {
\\your solution goes here
return this.roles;
}
};
I entered return this.roles; but everything else in the code came from the computer. the answer comes up wrong and says:
Testing orderOfAppearance("Elizabeth Swann")
Yours and expected differ. See highlights below.
Yours
Jack Sparrow,Will Turner,Elizabeth Swann,Hector Barbossa
Expected
3
I also entered:
return this.roles[3]
but that gives Hector Barbossa. I don't know what to do!
If the role is not found, the method returns 0. Ex: orderOfAppearance("Elizabeth Swann") returns 3.
You can use .indexOf() to get the index of the role passed to the orderOfAppearance() method and then add 1 to it. .indexOf() will return -1 if the role is not found and it will become 0 after adding 1.
let movie = {
title: "Pirates of the Caribbean: At World's End",
director: 'Gore Verbinski',
composer: 'Hans Zimmer',
roles: ['Jack Sparrow', 'Will Turner', 'Elizabeth Swann', 'Hector Barbossa'],
orderOfAppearance: function(role) {
return this.roles.indexOf(role) + 1
},
}
console.log(movie.orderOfAppearance('Jack Sparrow'))
console.log(movie.orderOfAppearance('Will Turner'))
console.log(movie.orderOfAppearance('Elizabeth Swann'))
console.log(movie.orderOfAppearance('Hector Barbossa'))
console.log(movie.orderOfAppearance('Something that does not exist in roles'))
I need to use a Zapier webhook to take some incoming JSON data, which contains an array of items, loop that array and do an action for each element.
Here's a sample of incoming JSON data:
{
"first_name": "Bryan",
"last_name": "Helmig",
"age": 27,
"data": [
{
"title": "Two Down, One to Go",
"type": "Left"
},
{
"title": "Talk the Talk",
"type": "Right"
},
{
"title": "Know the Ropes",
"type": "Top"
}
]
}
The size of the array will be dynamic.
The problem is that when I import this data in the hook, it gives me
data
title: Two Down, One to Go
type: Left
title: Talk the Talk
type: Right
title: Know the Ropes
type: Top
So, basically it says that data is just a big string of all this stuff together.
Can anyone help me figure out if it's possible to have a Zap loop over this and do something, e.g., insert data into a sheet, for ever item in the array? I'm aware of the "Code" actions, I've chosen JavaScript, which I could parse out the string, but that doesn't seem efficient. Plus, in reality, there will be a lot of data in the objects inside the JSON array.
EDIT: SOLVED! ANSWER BELOW
So, the first part is to Catch Raw Hook for a trigger. It's the normal "Webhooks", but you have to click to show the less common variations. With the Catch Raw Hook, your data will not be turned automatically turned into variables via the Zapier app, you'll have the raw JSON data.
Once you have the raw JSON, in my case, you'll have an action, and this will be the "Code" action. I'm using JavaScript. In my template, I'm grabbing the entire JSON string (your whole imported JSON is a string right now, not an object, so we can't use "." (dot) notation to access parts of it).
You'll need to JSON.parse() the string in the code. But first, let me explain that Zapier has a pre-defined variable called inputData that you'll use in your code. Then in the top of the "Edit Template" section of your "Code" Action, you'll see you can name the variable of that JSON string you imported.
Now the fun part! In the code, you'll type:
// of course, you can change the variables to what you want
// but 'inputData' is unique, can't change that
const myData = JSON.parse(inputData.rawJsonData);
So, my raw data is a string, it's not JSON yet, so this line of code makes it a JSON object. And now, as an object we can loop over it or .map or access 'this.that' or whatever you want.
The next important thing to mention about "Code" in Zapier, is that to get your stuff out, you return. So, in the next few lines, I'm going to return a .map function that returns each item in an array. And it's tough to grasp how Zapier treats this, but it actually runs the next "Action" you create (e.g. adding a row to a sheet) for each time you loop in that .map. So, let's take a look below:
return myData.data.map(item => {
return item;
});
If you remember, I had an array called "data" in my raw JSON I listed in the original question. It will loop over that array and since I'm returning, then it will perform an "Add Row to Sheet" (in my case) for each loop, thus, inserting all of my data as multiple rows in my spreadsheet.
So the finished code:
const myData = JSON.parse(inputData.rawJsonData);
return myData.data.map(item => {
return item;
});
Long story short, I'm making a real estate agent chatbot and I just implemented a filter allowing the user to search within a range of numbers (e.g. at least one bedroom, under $2500). In order to do this, I made an entity_range composite entity composed of the range type (e.g. at most, exactly) and the entity itself (unit-currency for price, plus some custom entities like the number of bedrooms). Prior to creating entity_range, the entities themselves worked fine. But now, it seems as though the entity part of entity_range is undefined. See a sample of my code below:
function get_count(req, res) {
console.log("price: " + req.queryResult.parameters["entity_range"]["unit-currency"])
var price, beds, baths, num_filter_funct
if(req.queryResult.parameters["entity_range"]["unit-currency"] != undefined) {
price = req.queryResult.parameters["entity_range"]
console.log("price: " + price)
} else {
console.log("could not find parameter")
}
Before creating entity_range, my code looked exactly the same, except without ["entity_range"] between parameters and ["unit-currency"]. Anyway, this code logs:
price: undefined
could not find parameter
after the input "How many for $2500," with the following diagnostic info:
...
"queryResult": {
"queryText": "how many for $2500",
"parameters": {
"entity_range": [
{
"unit-currency": {
"amount": 2500,
"currency": "USD"
}
}
]
}...
So the entity "unit-currency" is recognized by Dialogflow, but not by my program. entity_range does allow users to not specify a range, so that's not the issue:
see screenshot here.
I would greatly appreciate any advice you have to offer!
That JSON shows entity_range being an array instead of an object. an object.
parameters.entity_range[0][“unit-currency”] should work. Note the [0]. You’ll also want to add some checks before this to make sure enitiy_range exists and it’s length is > 0.
And this part is just a guess but perhaps you mistakenly clicked the “Is List” box for this parameter in dialogflow? I’m checking it would probably make it be an object instead of an array and your existing code would work.
I'm currently building a tool for the card game Hearthstone. If you're familiar with the game it's basically a tool that allows you to add your in game deck to a list so that you can monitor what cards you have left at all times along with the chance of drawing X card etc. Nothing too fancy but since I am a huge novice to the world of web development I'm using it as an exercise to help me learn more.
Anyway on to my problem!
At the moment I have a JSON database that has every card in hearthstone along with all of the different parameters associated with each card such as name, cost, playerClass etc.
I have figured out how to retrieve objects from the database but only via the name, since that's what players will use to search for the card they want to add to their deck.The problem I have at the moment is that the name of the card is a child of the card object which is itself a child of the card set object (basic, classic, naxx, gvg etc)
I would like to get ALL of the card data back when I search for it by name but try as I might, I can't figure out how to talk to a parent object via it's child.
to start with here is the search function from the users input:
$.getJSON("json/AllSets.json",function(hearthStoneData){
$('.submit').click(function(){
var searchValue = $('#name').val();
var returnValue = getObjects(hearthStoneData, "name", searchValue);
console.log(hearthStoneData);
console.log(returnValue);
});
});
and here is the request from the database:
function getObjects(obj, key, val) {
var objects = [];
for (var i in obj) {
if (!obj.hasOwnProperty(i)) continue;
if (typeof obj[i] == 'object') {
objects = objects.concat(getObjects(obj[i], key, val));
} else if (i == key && obj[key].toLowerCase() == val.toLowerCase()) {
objects.push(obj[i]);
}
}
return objects;
}
And finally here is an example of one of the JSON cards I am trying to talk to.
{
"id":"EX1_066","name":"Acidic Swamp Ooze",
"type":"Minion",
"faction":"Alliance",
"rarity":"Common",
"cost":2,
"attack":3,
"health":2,
"text":"<b>Battlecry:</b> Destroy your opponent's weapon.",
"flavor":"Oozes love Flamenco. Don't ask.",
"artist":"Chris Rahn",
"collectible":true,
"howToGetGold":"Unlocked at Rogue Level 57.",
"mechanics":["Battlecry"]}
So the output im getting when I console log is something like this:
Object {Basic: Array[210], Classic: Array[387], Credits: Array[17], Curse of Naxxramas: Array[160], Debug: Array[58]…}
Basic: Array[210]
[0 … 99]
6: Object
artist: "Howard Lyon"
collectible: true
cost: 2
faction: "Neutral"
flavor: "This spell is much better than Arcane Implosion."
howToGet: "Unlocked at Level 1."
howToGetGold: "Unlocked at Level 28."
id: "CS2_025"
name: "Arcane Explosion"
playerClass: "Mage"
rarity: "Free"
text: "Deal $1 damage to all enemy minions."
type: "Spell"
As you can see, there are several nested arrays before you actually get to the card. I can sort of visualise in my head what I think needs to be done but I definitely dont feel certain. Also alot of the syntax has been copy/pasted and modified to suit my needs, I'm still a total beginner with this stuff and really have no idea how I would write a fix to this problem myself.
Any help is hugely appreciated.
Thanks
I think there's a problem with how the data is stored:
Every object needs to have a unique id
Every Child object needs to return a reference to the parentId. This needs to be stored on insert or creation of the child object.
There needs to be a way to look up any object by id