So I'm currently working with the PokeAPI to make a functional Pokedex.
Pokemon can have 1+ types, so I wrote an if statement to deal with that possibility by using the hasOwnProperty selector.
if (data.hasOwnProperty("types[1].type.name")) {
type.innerHTML = "Types: " + data.types[0].type.name + ", " + data.types[1].type.name;
} else {
type.innerHTML = "Type: " + data.types[0].type.name;
}
However, the code doesn't seem to work, and it defaults to the "else" portion of the if statement. Could anyone pinpoint the error in my code? Thanks!
This is an example of what the types object looks like:
"types": [
{
"slot": 2,
"type": {
"url": "https://pokeapi.co/api/v2/type/3/",
"name": "flying"
}
},
{
"slot": 1,
"type": {
"url": "https://pokeapi.co/api/v2/type/10/",
"name": "fire"
}
}
]
What you probably want to use is map, which will convert your array of objects into an array of names quite easily. You can just use this: 'Types: ' + data.types.map(t => t.type.name).join(', ') to get the snippet you want to add to the HTML. This is much simpler than mucking around with lengths or hasOwnProperty.
const data = {"types": [{"slot": 2, "type": {"name": "flying", "url": "https://pokeapi.co/api/v2/type/3/"}}, {"slot": 1, "type": {"name": "fire", "url": "https://pokeapi.co/api/v2/type/10/"}}]}
const run = document.getElementById('run')
const types = document.getElementById('types')
run.addEventListener('click', evt => {
types.innerHTML = 'Types: ' + data.types.map(t => t.type.name).join(', ')
})
<p id="types">(empty until you click "Run")</p>
<button id="run">Run</button>
When you click the button in that snippet, the data is mapped to get the names, and they're joined into your expected string. Now, if your array has three elements, or seventeen, this will continue to work.
Credit to Calvin Nunes,
Instead of using hasOwnProperty() which does not work when there are a variable number of types in the types object, it's easier to just check if there is more than 1 types with if (data.types.length > 1){}.
You're checking a string for data.hasOwnProperty
I think this might work for you:
if (data.hasOwnProperty(types[1].type.name)) {
type.innerHTML = "Types: " + data.types[0].type.name + ", " + data.types[1].type.name;
} else {
type.innerHTML = "Type: " + data.types[0].type.name;
}
This checks the actual value of types[1].type.name and not the string "types[1].type.name". Hope that helps...
Related
At this moment I'm trying to create a json like this.
[
{"name": "set registry key right",
"win_acl": {
"path": "HKCU:\\Bovine\\Key",
"user": "BUILTIN\\Users",
"rights": "EnumerateSubKeys",
"type": "allow",
"state": "present",
"inherit": "ContainerInherit, ObjectInherit",
"propagation": "None"
}
},
{
"name": "Remove FullControl AccessRule for IIS_IUSRS",
"win_acl": {
"path": "C:\\inetpub\\wwwroot\\MySite",
"user": "IIS_IUSRS",
"rights": "FullControl",
"type": "allow",
"state": "absent",
"inherit": "ContainerInherit, ObjectInherit",
"propagation": "None"
}
}
]
I want to create it dynamically trough javascript.
This is what I have now:
function GenerateYaml(btn) {
$('#generatedYamlTextField').removeAttr("hidden");
var id = btn.replace("generateBtn", "");
var moduleName = $("#formpanel" + id).attr("data-title-caption");
//Looping trough panels
$("#formpanel" + id).each(function () {
var json = "[\n{\n\"name\":\"" + "module beschrijving" + "\",\n";
json += "\"" + moduleName + "\": {\n";
//Looping through labels in the panel to create the object
$('label').each(function (index, value) {
var is_last_item = (index == ($('label').length - 1));
if (!is_last_item) {
json += "\"" + value.innerText + "\":"+"\"textboxvalue\",\n";
} else {
json += "\"" + value.innerText + "\":"+"\"textboxvalue\"\n";
}
});
json += "}\n},]\n";
$("#yamltextfield").append(json);
});
}
This is what I get from above code in my textarea:
[
{
"name":"module beschrijving",
"win_acl_inheritance_module": {
"path":"textboxvalue",
"reorganize":"textboxvalue",
"state":"textboxvalue"
}
},]
My problem is that I have multiple panels and I want to add them in the same array so that I get it like the json I showed in the first place.
I hope you guys could help me out. Thanks in advance.
Greetings,
Mouaad
Don't form the json string manually. Just compose your objects, put them in an array, say arr and you can get the json string by:
JSON.stringify(arr);
I want to convert JSON to HTML to display it on website. I've googled, and this error occurs when when json is a string, and first I need to parse. But when I use JSON.parse, the console says it is already an object (Unexpected token o in JSON at position 1).
$(document).ready(function() {
$("#getMessage").on("click", function() {
$.getJSON("http://quotes.rest/qod.json", function(json) {
var html = "";
json.forEach(function(val) {
var keys = Object.keys(val);
html += "<div class = 'blabla'>";
keys.forEach(function(key) {
html += "<b>" + key + "</b>: " + val[key] + "<br>";
});
html += "</div><br>";
});
$(".message").html(html);
});
});
});
json is an object, not an array. You can use forEach only on arrays.
As you have done already, you can iterate over the object's keys like this:
Object.keys(json).forEach(function(key) {
var value = json[key];
...
});
In addition to what everyone else said, it appears that the JSON response does not look like you think it does.
var json = {
"success": {
"total": 1
},
"contents": {
"quotes": [{
"quote": "It's not whether you get knocked down, it...s whether you get up.",
"length": "65",
"author": "Vince Lombardi",
"tags": [
"failure",
"inspire",
"learning-from-failure"
],
"category": "inspire",
"date": "2016-08-09",
"title": "Inspiring Quote of the day",
"background": "https://theysaidso.com/img/bgs/man_on_the_mountain.jpg",
"id": "06Qdox8w6U3U1CGlLqRwFAeF"
}]
}
};
var messageEl = document.querySelector('.message');
messageEl.innerText = json.contents.quotes[0].quote;
<div class="message"></div>
$.getJson already transforms a JSON object into a javascript object, so you would not need to parse it again.
However, your problem starts with forEach, which is an Array method, not an Object method, therefor it will not work in your use case.
var jsonKeys = Object.keys(json); jsonKeys.forEach(...) will work, as Object.keys returns an array of Object keys.
Related Retrieve two lists, sort and compare values, then display all the results
The question in the related post was how to combine two lists and sort them. The code referenced each item on each list. So, when I got the result, I could manipulate it.
The best solution used console.log(JSON.stringify(result,null,2)); to return the result, nicely combined and sorted.
Trouble for me is being able to translate that back into something I can work with. I can get the result into a variable and display it on the page, but it's the raw output : [ { "Title": "apple", "Type": "rome", "State": null }, ...
Have tried 'JSON.parse(result);' where result is the variable that is used to handle the combination and sorting of the two lists. All that gives is an invalid character error on the line. Also looked at the 'replace' option. That just confused me, tmi. Tried setting a variable directly on the result (so those who know are laughing) 'var foo = result;' That returns object, object.
The desired end result would be to end up with each item separate so I can put them in a table (or a list) on my html page with blanks in any column where there is no data.
I know there has to be a simple, easy way to do this without 200 lines of transformation code. But I can't find a clear example. Everything I'm seeing is for +experts or uses a super simple array that's typed into the code.
Is there a way to attach something like this (from my original) to the result instead of using JSON.stringify? What other step(s) am I missing in being able to extract the fields from JSON.stringify using JSON.parse?
}).success(function (data) {
var title = '';
var type = '';
$.each(data.d.results,
function (key, value) {
title += "Title: " + value.Title + "<br/>";
type += "Type: " + value.Type + "<br/>";
});
$("#tdtitle").html(title);
$("#tdtype").html(type);
Terry, you wrote: "All that gives is an invalid character error on the line"? Then result is not a valid json. Test it here: http://jsonlint.com/, fix it, then try again.
var data = {
d:{
results: [
{ "Title": "apple", "Type": "rome", "State": null },
{ "Title": "grape", "Type": "fruit", "State": null }
]
}
};
var title = '';
var type = '';
$.each(data.d.results, function (index, value) {
title += "Title: " + value.Title + "<br/>";
type += "Type: " + value.Type + "<br/>";
});
alert(title + type);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
I am trying to loop over an object and check if a certain property is inside any other certain parts of the object. I am trying to see if the first level.parentSearch is inside any of the other firstlevel.filters array (of objects).
So my object looks like this for example :
var currentfilters = [{
"id": "topics",
"name": "Topics",
"filters": [{
"id": "isSubTopic",
"label": "isSubTopic",
"search": "isSubTopic",
"num": 15
}]
}, {
"id": "isSubTopic",
"name": "isSubTopic",
"parentSearch": "isSubTopic",
"filters": [{
"id": "subtopicFilter",
"label": "subtopicFilter",
"search": "subtopicFilter",
"num": 2
}, {
"id": "subtopicFilter1",
"label": "subtopicFilter1",
"search": "subtopicFilter1",
"num": 2
}]
}, {
"id": "notSubTopic",
"name": "notSubTopic",
"parentSearch": "uniueParentSearch",
"filters": [{
"id": "notSubTopic1",
"label": "notSubTopic1",
"search": "notSubTopic1",
"num": 5
}]
}
];
So what I am trying to achieve is to loop over this object and modify it a little bit (if necessary) and return it. What I am trying to do is check the first level if the .parentSearch property is inside any of the other objects .filter array as a .search property. So in this example isSubTopic would be what I am looking for, because it is inside the Topics filters array.
This is my first time trying these kind of problem, so if I am missing anything please let me know. I figured since I want to return a modified object, it would be good to reduce this object and check inside. The part I am struggling with is the bit that checks if my current parentSearch (in the reduce loop) is in any other objects filter array (under the .search property). I have lodash to mess around with so I have tried both _.find and _.has, but I think I am not approaching this correctly. Any/all input would be greatly appreciated!
Here is what I was trying it with : https://jsfiddle.net/0fttkyey/32/
function checkIfSubtopic(memo, value, key) {
if(value.parentSearch) {
//check if value.parentSearch is in any of the value.filters
console.log("find?", _.find(currentfilters, value.parentSearch));
if(_.find(currentfilters, value.parentSearch)){
console.log("is subtopic?");
} else {
console.log("not sub topic");
}
}
return memo;
}
Interestingly, your currentfilters is not the same in the jsfiddle you provide, so it gives no result.
If I understand correctly, what you try to achieve is:
For each "filter" in currentfilters array, check if parentSearch member is truthy.
If so, loop through all other filters.
For each of these filters, loop through its filters array member.
If the search member of one of the objects in this filters array is equal to parentSearch value, keep the current "filter".
So you have 3 nested loops.
The 2 outer loops iterate over the same currentfilters array, except that the 2nd (inner) one skips the filter which parentSearch value is being searched for.
As soon as parentSearch value is found, break loops 2 and 3 (the 2 inner-most) and go to next item of 1st (outer-most) loop.
Without using lodash and building a new result array (instead of modifying currentfilters array in place which may yield unexpected results), you would have for example:
var i = 0,
j,
ifiltermax = currentfilters.length,
currentParentSearch,
currentFiltersArray,
k,
result = [];
for (; i < ifiltermax; i += 1) { // Loop 1.
currentParentSearch = currentfilters[i].parentSearch;
if (currentParentSearch) { // If `parentSearch` is truthy.
loop_j: for (j = 0; j < ifiltermax; j += 1) { // Loop 2.
if (j != i) { // Skip current filter which `parentSearch` is being searched for.
currentFiltersArray = currentfilters[j].filters;
for (k = 0; k < currentFiltersArray.length; k += 1) { // Loop 3.
if (currentFiltersArray[k].search === currentParentSearch) {
result.push(currentfilters[i]); // Keep current "filter".
console.log("Found " + currentParentSearch + " (from item #" + i + ") in item #" + j + ", filter #" + k);
break loop_j; // Break loops 2 and 3.
}
}
console.log("Did not find " + currentParentSearch + " (from item #" + i + ") in any other filter.");
}
}
}
}
console.log(result);
Updated jsfiddle: https://jsfiddle.net/0fttkyey/71/ (with currentfilters from the question above, instead of the one in jsfiddle version 32).
I am pulling data from a JSON array similar to as follows:
"abridged_directors": [{
"name": "Bill",
"id": "742790769",
"characters": ["Flint Lockwood"]
}, {
"name": "Anna",
"id": "162654477",
"characters": ["Sam Sparks"]
}, {
"name": "James",
"id": "162656402",
"characters": ["Tim Lockwood"]
}, {
"name": "Will",
"id": "770670480",
"characters": ["Chester V"]
}, {
"name": "Kristen",
"id": "770792145",
"characters": ["Barb"]
}],
I am using a loop to correctly display the result.
What I am looking for is:
Bill, Ann, James, Will & Kristen
Instead I am getting:
Bill, Ann, James, Will, & Kristen
For the second last name I do not want a comma and the following if else statement should cover that but it doesn't seem to be working?
for (var i = 0;i < data.abridged_directors.length; i++){
if(i != 0 && i == data.abridged_directors.length-1){
// and the position of the character is greater than 0
$(document.body).append('& ' + data.abridged_directors[i].name + '<br>');
}
else if(i != data.abridged_directors.length-1 || i != data.abridged_directors.length-2){
$(document.body).append(data.abridged_directors[i].name + ', ');
}
else
$(document.body).append(data.abridged_directors[i].name + '<br>');
}
I have been looking at this for a good while now and making changes but nothing seems to work. It is possibly something small I'm not seeing so sorry if that turns out to be the case!
I'd like to offer a little cleaner method (imho). Instead of looping through and appending, try joining an array of the names and just replacing the last comma. See code:
var names = [];
for (var i = 0;i < data.abridged_directors.length; i++)
{
names.push(data.abridged_directors[i].name);
}
$(document.body).append(names.join(', ').replace(/(.*),(.*)$/, "$1 & $2"));
Here's a jsfiddle: http://jsfiddle.net/zYdH9/
If you are supporting only IE9+, then you can use a map to do this. The key thing here is a separation of duties. It makes it easier to understand. If you need IE9- support, then you can do this with a for loop. See ezekielDFM's solution.
[editted to include ezekielDFM regex command - much more cleaner solution]
Pseudo Code:
Build your data up first (map command)
Format your data (join command)
Fix formatting (replace command)
Javascript
var string_directors = data.abridged_directors
.map(function(director) {
return director.name;
})
.join(', ')
.replace(/(.*),(.*)$/, '$1 & $2');
The || in the else if should be &&.
i know you get the answer, but i spend some time with solution...kkk
Hope Help someone:
$(json).each(function(i){
$("#result").append(this.name);
if(j-2 == i)
$("#result").append(" & ");
else{
if(!(j-1 == i))
$("#result").append(", ");}
});
http://jsfiddle.net/Z5L4E/