jQuery - Iterating JSON Object To Find Element - javascript

SITUATION:
I have dynamic json object data and need to use it to find element.
Example:
[
{ "tag": "article",
"id": "post-316",
"order": "0" },
{ "tag": "div",
"class": "entry-content",
"order": "0" }
]
Its length, keys and values can change anytime based on user request.
I need to use that data to dynamically find the specified element in a web page. The first set of strings will be the data for parent element, which will be used to initialize the search, and the last one will be the target children.
PURPOSE:
So, from json example above, I want to find an element with:
class name entry-content, tag name div, index 0 inside of parent with id post-316
by converting that json data in such kind of format or may be simpler and or better:
// because the parent already have attribute id, so no need to check other info of this element
var elem = $("#post-316").find(".entry-content");
if(elem.prop("tagName") == "div" ) {
elem.css("background", "#990000");
}
PROGRESS:
I tried using jquery $.each() method but can't discover myself the way to achieve that purpose.
Here is the code where I currently stuck on:
var json = $.parseJSON(theJSONData);
$.each(json, function(i, e){
$.each(e, function(key, data){
alert(i + " " + key + " " + data);
if(json.length - i == 1) {
alert("target " + data);
}
if(json.length - i == json.length) {
alert("parent " + data);
}
}
);
});
QUESTIONS:
Is it possible to achieve the PURPOSE from that kind of JSON data using iteration?
If it is possible, how to do it?
If not, what the way I can use?

You can use a format so the script knows what to get:
var data = {
'id': '#',
'class': '.'
};
var json = JSON.parse(theJSONData);
$.each(json, function (a) {
$.each(data, function (b) {
if (a[b]) {
$(data[b] + a[b])[+a['order']]; // Element
}
});
});
If you are sure about the data you are getting (As in it is class, or data, and it will have a tag name):
var json = JSON.parse(theJSONData),
last = document;
$.each(json, function (a) {
var selector = (a['id']) ? '#'+a['id'] : '.'+a['class'];
last = $(last).find(a['tag']+selector)[+a['order']]; // Element
});

Related

Vaadin Combo-Box: Using value property to pass the index of a selected item

I am trying to discern the index # of the pattern selected in the Combo-box. I need to pass this index value in order for another function to read from a file at the correct location. Essentially, selecting the a pattern in the combobox will let me do a lookup for specifications associated with the selected pattern based on the index. To the best of my knowledge the Vaadin Combobox does not have an index associated with the combobox items, but you are able to pass a different value than the displayed label: https://vaadin.com/docs/-/part/elements/vaadin-combo-box/vaadin-combo-box-basic.html (see: Using Objects as Items). This is solution I am trying to implement, however it gets tricky because I am dynamically populating the combobox items from a JSON file.
The code to dynamically populate the items:
paver = document.querySelector('#paver');
//alert('script executed');
patterns = [];
familyind=y;
$.getJSON('menu.json').done(function(data){
//alert('getJSON request succeeded!');
family = (data.gui[x].family[y].display);
for(ind = 0; ind < data.gui[x].family[y].pattern.length; ind++){
var patternLbl = data.gui[x].family[y].pattern[ind].name;
var patternObj = '{ pattern: { label: "' + patternLbl + '", value: ' + ind + ' } }';
patterns[ind] = patternObj;
}
document.getElementById("cb1").items=patterns;
})
.fail(function(jqXHR, textStatus, errorThrown)
{
alert('getJSON request failed! ' + textStatus);
})
.always(function() { }};
HTML for the ComboBox
<div id="patternSelect">
<template is="dom-bind" id="paver">
<div class="fieldset">
class="patterns" items="[[patterns]]" item-label-path="pattern.label" item-value-path="pattern.value"></vaadin-combo-box>
</div>
</template>
</div>
The output I get when I try to execute this is that the entire constructed string gets assembled into my selection choices. Theoretically, this should not have happened because the item-value-path and item-label-path were specified when declaring the combobox.
Screenshot of Output
It says: { pattern: { label: "A-3 Piece Random", value: 0 } }
WORKING TOWARDS A SOLUTION SECTION:
___________(April 27, 7:00pm)___________
Suggested solution to use,
var patternObj = { pattern: { label: patternLbl, value: ind } };
works fine in displaying labels:
However, I am using a trigger to detect when the value in the combo-box is changed and return the new value. Here is the code for the trigger:
// select template
var paver = document.querySelector('#paver');
// define the ready function callback
paver.ready = function () {
// use the async method to make sure you can access parent/siblings
this.async(function() {
// access sibling or parent elements here
var combobox = document.querySelector('#cb1')
combobox.addEventListener('value-changed', function(event) {
// FOR REFERENCE LOG ERRORS, THIS COMMENT IS ON HTML:215
console.log(event.detail.value);
patval = event.detail.value;
console.log(patval)
// Do stuff with fetched value
});
});
};
I have made the suggested change to using a 'value-changed' trigger. It works very well with two slight issues. First, it returns each of the console log calls twice (not sure why twice). Second, when I select the first combo-box item it returns my values but does not set the label as selected. This is not an issue with the other combo-box items, but the first item needs to be selected twice to have the label set. Please watch this short video for a demonstration: https://youtu.be/yIFc9SiSOUM. This graphical glitch would confuse the user as they would think they did not select a pattern when they know they had. Looking for a solution to make sure the label is set when the first item is selected.
You are setting a currently a String to patternObj while you should be setting an Object.
Try using either var patternObj = JSON.parse('{ pattern: { label: "' + patternLbl + '", value: ' + ind + ' } }'; or even simpler:
var patternObj = { pattern: { label: patternLbl, value: ind } };
Also, I would recommend initializing the patterns = [] inside the done callback to make sure you're not leaving any old items in the patterns when the data changes.

Parsing JSON to something usable

I know there are 1 million and 1 questions on this, but I cannot seem to find an answer.
I am receiving data via PHP as such
echo json_encode($result);
From a typical MYSQL query.
I get the result back like this in the console.
[{"id" : "1", "name" : "bob"}]
I am trying to use $.each to iterate through this so I can process my results but I only get errors, undefineds or 0[object Object].. things like that.
My goal is to append each value to a input box (retrieving data from a table to put into an edit box).
$.post('getstuff.php', { id : id } function(data){
$.each(data), function(k,v){
$('input[name= k ]').val(v);
});
});
As you can see i was hoping it was as simple as a key=>value pair but apparantly not. I have tried parsing, stringifiying.. really I am lost at this point. I also cannot tell $.post that I am using JSON because I am using a more arbitrary function, but am just posting that as my example.
Edit
var retrievedData = JSON.parse(data);
$.each(retrievedData, function(k,v){
for (var property in retrievedData) {
if (retrievedData.hasOwnProperty(property)) {
console.log(k);
console.log(v);
console.log(property);
//$('input[name= k ]').val(v);
}
}
});
In your second code sample, retrievedData is an array, which you iterate using jQuery $each...
$.each(retrievedData, function(k, v) {
OK so far. But then you try to iterate retrievedData again like an object, which it isn't. This is why you are getting undefined messages in the console
for (var property in retrievedData) {
if (retrievedData.hasOwnProperty(property)) {
console.log(k);
console.log(v);
console.log(property);
//$('input[name= k ]').val(v);
}
}
On the inner loop you should be iterating v not retrievedData. On each pass of $each v will be an object.Try this:
$.each(retrievedData, function(k,v){
for (var key in v) {
if (v.hasOwnProperty(key)) {
console.log("key: " + key);
console.log("value: " + v[key]);
}
}
});
You should do some type checking that v is an object first and catch any errors.
Use either :
$.ajax({
'dataType' : 'json'
});
Or
$.getJSON
Or if you want to use $.post, just do in your success function :
var good_data = JSON.parse(data);
$.each(good_data, function(k,v) {
$('input[name= k ]').val(v);
});
Answering your question based on your comments on other answer.
My assumption is you are getting data as JSON,if not you need to parse it,for that you can use JSON.parse(string).
Here I'm using Underscore.js
var data=[{"id" : "1", "name" : "bob"}]
$(data).each(function(ind,obj){
var keys=_.keys(obj);
$(keys).each(function(i,ke){
console.log(ke)
console.log(obj[ke]);
})
});
Here is JSFiddle of working code
First you need to define you're expecting JSON in your POST request - http://api.jquery.com/jQuery.post/
Then you need to iterate through the response.
$.post('getstuff.php', { id : id } function(data){
//Assuming you get your response as [{"id" : "1", "name" : "bob"}], this is an array
//you need to iterate through it and get the object and then access the attributes in there
$.each(data), function(item){
$('input[name=' + item.name + ']').val(item.id);
});
}, 'json');
EDIT
If you want to iterate over the properties of the objects returned, you need to put another loop inside the $.each
for (var property in item) {
if (object.hasOwnProperty(property)) {
// do stuff
}
}
More about it here - Iterate through object properties
EDIT 2
To address the solution you've posted. You've used the wrong variable names. Here's a working fiddle - http://jsfiddle.net/EYsA5/
var $log = $('#log');
var data = '[{"id" : "1", "name" : "bob"}]'; //because we're parsing it in the next step
var retrievedData = JSON.parse(data);
for (var parentProp in retrievedData) { //this gets us each object in the array passed to us
if (retrievedData.hasOwnProperty(parentProp)) {
var item = retrievedData[parentProp];
for (var property in item) { //this gives us each property in each object
if (item.hasOwnProperty(property)) {
console.log(item[property]);
$log.prepend("<br>");
$log.prepend("Property name is - " + property);
$log.prepend("<br>");
$log.prepend("Value of property is - " + item[property]);
//do stuff
}
}
}
};

How to loop through JSON file using jQuery

I am trying loop through the following JSON file below:
{
"statements": [{
"subject": "A"
}, {
"predicate": "B"
}, {
"object": "C"
}, {
"subject": "D"
}, {
"predicate": "E"
}, {
"object": "F"
}]
}
As you can see, there are two subjects, two predicates and two objects. I would like to get, for instance, the value "predicate":"E". How can I do this using jQuery or D3 Javascript library. My code below retrieves the first subject "subject":"A".
$.each(data.statements[0], function(i, v){
console.log(v.uriString);
});
or in D3 (I do not know how to do this in D3):
d3.json("folder/sample.json", function(error, graph)
{ // Code is here for getting data from JSON file }
Could anyone please help me loop through the JSON file above and retrieve some particular data either with jQuery or D3 Javascript. Thank you for your help in advance.
Try this:
$(data.statements).each(function (i) {
var d = data.statements[i];
$.each(d, function (k, v) { //get key and value of object
$("body").append("<p>"+k + ":" + v+"</p>");
});
})
Fiddle here.
The reason why your code returns the first item is beacuse you selected it with data.statments[0] and afterwards loop over that one item.
With jQuery you can use the grep-method like this:
var arrayWithItem = jQuery.grep(data.statements, function( obj ) {
return obj.predicate == "E";
});
You can read more about the grep-method here
With D3js I'm not sure, I guess you have to loop through it with an if-statement.

How to write JSON with jQuery?

I have this currencies.json file:
{
"USD": {
"ValueUSD": 325.33,
"ValueEUR": 344.55,
"PreviousValueUSD": 324.55,
"PreviousValueEUR": 354.55,
},
"EUR": {
"ValueUSD": 325.33,
"ValueEUR": 344.55,
"PreviousValueUSD": 324.55,
"PreviousValueEUR": 354.55,
}
}
I need to parse it into "#content" using jQuery. Can someone help me with a code to do this? I think jSONP is needed because the feed is from another server.
Example for output needed:
<div class="currency">USD, 325.33, 344.55, 324.55, 354.55</div>
<div class="currency">EUR, 325.33, 344.55, 324.55, 354.55</div>
// you will get from server
var obj = $.parseJSON(data); // data contains the string
for (var key in obj) {
$('<div class="currency" />')
.html(key + ', ' + $.map(obj[key], function(val) { return val; })
.join(', ')).appendTo('body');
}
HERE is the code.
$.parseJSON is used to parse the string into the object.
Then for each currency inside object use .map() to map the values.
Join the values into a string separated by ,, append into the div and a currency name.
Resulting div append to the body.
Update (see comments):
If you want to retrieve this data cross-domain use:
$.getJSON('www.domain.com/currencies.json?callback=?', function(data) {
for (var key in data) {
$('<div class="currency" />')
.html(key + ', ' + $.map(data[key], function(val) { return val; })
.join(', ')).appendTo('body');
}
});
Something like this should help (the data parsed from your JSON above is held in the data variable):
var $body = $("body"),
key,
$div,
txt,
innerKey;
for (key in data) {
if (data.hasOwnProperty(key)) {
$div= $("<div></div").addClass("currency");
txt = [key, ", "];
for (innerKey in data[key]) {
if (data[key].hasOwnProperty(innerKey)) {
txt.push(data[key][innerKey]);
txt.push(", ");
}
}
// Remove the trailing comma
txt.pop();
// Set the HTML content of the div and then add to the body
$div.html(txt.join("")).appendTo($body);
}
}
Here's a working example jsFiddle.
well you can access things like:
data.USD.ValueUSD will get you 325.33 so you can do something liek this. pass your data object that you get from your ajax call in ur success func to call this function:
function populateContent(data){
var $currencyDiv = $('<div class="currency"></div>'),
$currencyDiv2 = $currencyDiv.clone();
$currencyDiv.html("USD, "+data.USD.ValueUSD + ", " + data.USD.ValueEUR + ", " + data.USD.PreviousValueUSD + ", " + data.USD.PreviousValueEUR);
//do the same for currencydiv2
//append your new content divs wherever you want
$('body').append($currencyDiv);
}
A more puristic approach that could also help you understand how to iterate through objects (and is browser native and therefore not relying on jQuery)
for(var data in #YOUR_JSON_DATA# ){ // iterate through the JSON nodes
var tmp = data; // store the current node in temporary variable
for(var val in json[data]){ // iterate through the current nodes' children
tmp += ", " + json[data][val]; // this is how you access multidimensional objects. format your output as you like
}
alert(tmp); // see the output. here you could use jquery to write this into your page.
}

How can I "filter" JSON for unique key name/value pairs?

I've got some JSON data that is giving me a list of languages with info like lat/lng, etc. It also contains a group value that I'm using for icons--and I want to build a legend with it. The JSON looks something like this:
{"markers":[
{"language":"Hungarian","group":"a", "value":"yes"},
{"language":"English", "group":"a", "value":"yes"},
{"language":"Ewe", "group":"b", "value":"no"},
{"language":"French", "group":"c", "value":"NA"}
]}
And I want to "filter" it to end up like this:
{"markers":[
{"group":"a", "value":"yes"},
{"group":"b", "value":"no"},
{"group":"c", "value":"NA"}
]}
Right now I've got this, using jQuery to create my legend..but of course it's pulling in all values:
$.getJSON("http://127.0.0.1:8000/dbMap/map.json", function(json){
$.each(json.markers, function(i, language){
$('<p>').html('<img src="http://mysite/group' + language.group + '.png\" />' + language.value).appendTo('#legend-contents');
});
});
How can I only grab the unique name/value pairs in the entire JSON object, for a given pair?
I'd transform the array of markers to a key value pair and then loop that objects properties.
var markers = [{"language":"Hungarian","group":"a", "value":"yes"},
{"language":"English", "group":"a", "value":"yes"},
{"language":"Ewe", "group":"b", "value":"no"},
{"language":"French", "group":"c", "value":"NA"}];
var uniqueGroups = {};
$.each(markers, function() {
uniqueGroups[this.group] = this.value;
});
then
$.each(uniqueGroups, function(g) {
$('<p>').html('<img src="http://mysite/group' + g + '.png\" />' + this).appendTo('#legend-contents');
});
or
for(var g in uniqueGroups)
{
$('<p>').html('<img src="http://mysite/group' + g + '.png\" />' + uniqueGroups[g]).appendTo('#legend-contents');
}
This code sample overwrites the unique value with the last value in the loop. If you want to use the first value instead you will have to perform some conditional check to see if the key exists.
How about something more generic?
function getDistinct(o, attr)
{
var answer = {};
$.each(o, function(index, record) {
answer[index[attr]] = answer[index[attr]] || [];
answer[index[attr]].push(record);
});
return answer; //return an object that has an entry for each unique value of attr in o as key, values will be an array of all the records that had this particular attr.
}
Not only such a function would return all the distinct values you specify but it will also group them if you need to access them.
In your sample you would use:
$.each(getDistinct(markers, "group"), function(groupName, recordArray)
{ var firstRecord = recordArray[0];
$('<p>').html('<img src="http://mysite/group' + groupName+ '.png\" />' + firstRecord.value).appendTo('#legend-contents');
}
See this-
Best way to query back unique attribute values in a javascript array of objects?
You just need a variation that checks for 2 values rather than 1.
var markers = _.uniq( _.collect( markers , function( x ){
return JSON.stringify( x );
}));
reference

Categories