JQuery parseJSON and populate a second selection box - javascript

What i would like to happen is when i select an item from the first selection box, the 2nd selection box populates from a parseJSON.
I have 2 selection boxes: #web and #cats
web: has (at the moment) 3 options - All Websites (value=0), Website 1 (value=1) and Website 2 (value=2)
When i select from #web i should only get the categories for that particular website, however in PHP i have already considered "All Websites" and it duplicates the categories into each web object, but i also added "All Websites" to the json array, so that if it is reselected the selection box will repopulate.
This is the PHP Function (To create the JSON):
function catWebMix($user) {
$categories = getCategories($user);
$webAll = array('ID'=>0, 'WebID'=>'All', 'WebName'=>'All Websites');
$webSites = getWebsites($user);
array_unshift($webSites,$webAll);
$output = array();
foreach ($webSites as $k => $v) {
$output[$k] = $v;
foreach ($categories as $key => $value) {
if ($value['WebID'] == '0') {
$value['WebID'] = $v['ID'];
$output[$k]['Category'][] = $value;
} else if ($value['WebID'] == $v['ID']) {
$output[$k]['Category'][] = $value;
}
}
}
return array($output, json_encode($output));
exit;
}
I assign a variable to Smarty.
$webCats = catWebMix($user);
$smarty->assign('webCats', $webCats);
I then call it in JQuery. This is my failed attempt at creating the selection boxes change, im unsure on how to do it.
<script type="text/javascript">
var obj = $.parseJSON({$webCats[1]});
$('#web').on('change', function () {
var web = $(this).val();
$.each(obj, function () {
if (web == obj.ID) {
$.each(obj.Category, function (i,v) {
$('#cats').append("<option>"+v[3]+"</option>");
});
}
});
});
</script>
What i want it to do:
Remove all option attributes in #cats
Repopulate #cats with the data from the parseJson, based on the value from #web. #web value = (first) ID in JSON.
Place Category.ID as value for option, and Category.CatTitle as text
The json array looks like the following:
[
{
"ID": 0,
"WebID": "All",
"WebName": "All Websites",
"Category": [
{
"ID": "1",
"WebID": 0,
"CatTitle": "Category 1"
}
]
},
{
"ID": "1",
"WebID": "web1",
"WebName": "Website 1",
"Category": [
{
"ID": "1",
"WebID": "1",
"CatTitle": "Category 1"
},
{
"ID": "2",
"WebID": "1",
"CatTitle": "Category 2"
}
]
},
{
"ID": "2",
"WebID": "web2",
"WebName": "Website 2",
"Category": [
{
"ID": "1",
"WebID": "2",
"CatTitle": "Category 1"
}
]
}
]
Thanks for any help!

I did it! This was the code i used in case others have issues.
<script type="text/javascript">
var webCats = {$webCats[1]};
$('#web').on('change', function () {
var web = $(this).val();
$.each(webCats, function (k, o) {
if (web == o.ID) {
$('#cats option').remove();
$.each(o.Category, function (i, v) {
$('#cats').append("<option value=\""+v.ID+"\">"+v.CatTitle+"</option>");
});
}
});
});
</script>

Related

get previous json item in Json

I have a JSON file titled stuff.json. I am trying to get the previous json item given a certain item. For example, if I am given the key ["also-random-here"], how do I get the previous JSON item "sample-name"?
My JSON data looks as follows:
{
"random-name-here": {
"name": "name is item1"
},
"sample-name": {
"name": "name is item2"
},
"also-random-here": {
"name": "name is item3"
}
}
try this
var names={
"random-name-here": {
"name": "name is item1"
},
"sample-name": {
"name": "name is item2"
},
"also-random-here": {
"name": "name is item3"
}
};
var prevName= findPrevName(names, "also-random-here") ;
function findPrevName(item, key) {
var prevName;
for (const property in item)
{
if(property==key) break;
prevName=property;
};
return { [prevName]: item[prevName]};
};

Javascript Push to Array if Condition is Met

I have the following Foods Object:
var Foods = {
"Fruits": [{
"id": "1",
"Name": "Granny Smith",
"Category": "1"
}, {
"id": "2",
"Name": "Raspberries",
"Category": "1"
}
],
"Potatoes": [{
"id": "3",
"Name": "Maris Piper",
"Category": "2"
}, {
"id": "4",
"Name": "Charlotte",
"Category": "2"
}]
}
What I would like to do is only push the produce that matches an id passed by a link.
Get Foods
This is what I have tried so far:
function getCat (id){
result = [];
for(let item in Foods) {
if(Foods[item].id == id) {
data[item].foreach(v=>result.push("<div class='box'><h2>" +
data[key].Name + "<br></div>"));
}
}
}
display();
function display() {
alert(result);
}
So if a user hits the link (which has an id of 2), the result array should contain "Charlotte" and "Maris Piper" but I am just drawing a blank.
Any help appreciated.
Cheers
Youre quite close, however theres a slight problem:
for(let item in Foods) {
console.log(Foods[item]);
/*
[{
"id": "1",
"Name": "Granny Smith",
"Category": "1"
}, {
"id": "2",
"Name": "Raspberries",
"Category": "1"
}
]
*/
So youre iterating over the categories, which are arrays.
Foods[item].id
is undefined as its an array and not a product. So we need to iterate the array to, e.g.
var result=[];
Object.values(Foods).forEach(function(category){
category.forEach(function(product){
if(product.id===id){
result.push(product);
}
});
});
Run
But if youre doing this quite often, it might be easier to create one product array once:
var products = Object.values(Foods).reduce((arr,cat)=>arr.concat(cat),[]);
So you can simply filter this whenever someone clicks a button:
var result = products.filter(product=>product.id === id);
Run
You're somewhat on the right track, but what's data? Why are you not doing anything with result? And you should be looking at the Category property rather than ID.
This'll work:
function getCat(id) {
let result = [];
for (let item in Foods) {
if (Foods.hasOwnProperty(item)) {
Foods[item].forEach((food) => {
if (food.Category == id) {
result.push(food);
}
});
}
}
console.log(result);
}
First of all result array should be at global scope so that you can access it in another function, And in object you are having categories then each category has some data in array so after iterating over object, you need to iterate the items from array as well to get the value. Check the below code.
var result = [];
function getCat(id){
for(let item in Foods) {
var foodItem = Foods[item];
for(let i=0; i<foodItem.length; i++){
if(foodItem[i].id == id) {
result.push("<div class='box'><h2>" + foodItem[i].Name + "<br></div>"));
}
}
}
}
function display() {
alert(result);
}
display();
Iterator is wrong. You should do it like this:
function getCat(id){
result = [];
for(let item in Foods) {
Foods[item].forEach(function(each){
if(each.id == id) { // you cmpare to the wrong target
// do something
}
});
}
}

Loading data from JSON file into Tree with checkboxes

I am trying to create a expanding tree for my web application but I am not able to bring data from a JSON file to dynamically fill the tree. I found this code from another post on SOF.
Here is my JSON file called tree_data.json :
{
"Data": {
"id": "0",
"title": "root-not displayed",
"children": {
"id": "1",
"title": "Option 1",
"children": {
"id": "11",
"title": "Option 11",
"children": {
"id": "111",
"title": "Option 111",
"id": "112",
"title": "Option 112"
}
}
}
}
}
Here is javascript code imbedded within HTML:
$.getJSON("tree_data.json", function(treedata) ){
//$.each(treedata.data, function(i, field){
$(function () {
addItem($('#root'), treedata); //first call to add item which passes the main parent/root.
$(':checkbox').change(function () {
$(this).closest('li').children('ul').slideToggle();
});
$('label').click(function(){
$(this).closest('li').find(':checkbox').trigger('click');
});
});//}
function addItem(parentUL, branch) {
for (var key in branch.children) { //for each key in child in data
var item = branch.children[key]; //assign each child in variable item
$item = $('<li>', { //jquery object
id: "item" + item.id
});
$item.append($('<input>', { //add check boxes
type: "checkbox",
id: "item" + item.id,
name: "item" + item.id
}));
$item.append($('<label>', { //add labels to HTML. For every id, display its title.
for: "item" + item.id,
text: item.title
}));
parentUL.append($item);
if (item.children) {
var $ul = $('<ul>', {
style: 'display: none'
}).appendTo($item);
$item.append();
addItem($ul, item); //recursive call to add another item if there are more children.
}
}
}}
I need a lot of help changing this code in order grab the JSON data and creating the tree. Any help would be very appreciated. Thank you.
First of all, you have to encapsulate every children object in a json array, so you can have single or multiple object in each children (like 111 and 112). So change the json to be like that:
{
"Data": {
"id": "0",
"title": "root-not displayed",
"children": [{
"id": "1",
"title": "Option 1",
"children": [{
"id": "11",
"title": "Option 11",
"children": [{
"id": "111",
"title": "Option 111"
},
{
"id": "112",
"title": "Option 112"
}]
}]
}]
}
}
Now, there is a working code base (with working example):
$(function () {
var treedata = JSON.parse('{"Data": {"id": "0","title": "root-not displayed","children": [{ "id":"1","title":"Option 1","children": [{"id": "11","title": "Option 11","children": [{"id": "111","title": "Option 111"},{"id": "112","title": "Option 112"}]}]}]}}'); //JUST FOR MOCKUP THE JSON CALL
addItem($('#root'), treedata.Data); //first call to add item which passes the main parent/root.
$(':checkbox').change(function () {
$(this).closest('li').children('ul').slideToggle();
});
$('label').click(function(){
$(this).closest('li').find(':checkbox').trigger('click');
});
});//}
function addItem(parentUL, branch) {
$.each(branch.children, function(i){
var item = branch.children[i]; //assign each child in variable item
$item = $('<li>', { //jquery object
id: "item" + item.id
});
$item.append($('<input>', { //add check boxes
type: "checkbox",
id: "item" + item.id,
name: "item" + item.id
}));
$item.append($('<label>', { //add labels to HTML. For every id, display its title.
for: "item" + item.id,
text: item.title
}));
parentUL.append($item);
if (item.children) {
var $ul = $('<ul>', {
}).appendTo($item);
addItem($ul, item); //recursive call to add another item if there are more children.
}
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="root">
</div>
Now just use your getJSON instead of my mockup data and you will be fine i hope :)

Manipulating javascript object with underscore

I have a Javascript object with a format like below
"items":
{
"Groups":[
{
"title":"group 1",
"SubGroups":[
{
"title":"sub1",
"id" : "1",
"items":[
{
"title":"Ajax request 1",
},
{
"title":"Ajax request 2",
}
]
},
{
"title":"sub2",
"id" : "2",
"items":[
{
"title":"Ajax request 3",
},
{
"title":"Ajax request 4",
}
]
}
]
}
]
There are n 'Groups', n 'subGroups' and n 'items'.
What I want to do firstly is get all the items from a particular group based on id. This is achieved using:
_.each(items.Groups, function(o) {
result = _.where(o.SubGroups, {
'id': '1'
});
});
which returns
"items":[{"title":"Ajax request 1",},{"title":"Ajax request 2",}]
Then I want to get the rest of the data, excluding the items and parent group I have just retrieved.
I tried this:
_.each(items.Groups, function(o) {
arr = _.without(o.SubGroups, _.findWhere(o.SubGroups, {id: '2'}));
});
But this only returns me the items like this:
{
"title":"sub2",
"id" : "2",
"items":[{"title":"Ajax request 3"},{"title":"Ajax request 4",}]
}
whereas what I need is this:
"items":
{
"Groups":[
{
"title":"group 1",
"SubGroups":[
{
"title":"sub2",
"id" : "2",
"items":[
{
"title":"Ajax request 3",
},
{
"title":"Ajax request 4",
}
]
}
]
}
]
Just try this:
_.each(items.Groups, function(o) {
arr = _.without(o, _.findWhere(o.SubGroups, {id: '2'}));
});
o should be enough => you want to get Groups and not SubGroups.
Following is a pure JS implementation:
JSFiddle.
var data = {
"Groups": [{
"title": "group 1",
"SubGroups": [{
"title": "sub1",
"id": "1",
"items": [{
"title": "Ajax request 1",
}, {
"title": "Ajax request 2",
}]
}, {
"title": "sub2",
"id": "2",
"items": [{
"title": "Ajax request 3",
}, {
"title": "Ajax request 4",
}]
}]
}]
}
var items = [];
var group = [];
data.Groups.forEach(function(o) {
var _tmp = JSON.parse(JSON.stringify(o));
_tmp.SubGroups = [];
o.SubGroups.forEach(function(s) {
if (s.id == "1") {
items.push(s.items);
} else {
_tmp.SubGroups.push(s);
group.push(_tmp)
}
});
});
function printObj(label, obj) {
document.write(label + "<pre>" + JSON.stringify(obj, 0, 4) + "</pre>")
}
printObj("group", group);
printObj("items", items);
Using underscore and using your logic to filter all subgroups:
//array to store subgroup with ID 1
var results = [];
var d = _.each(data.items.Groups, function(o) {
result = _.where(o.SubGroups, {
'id': '1'
});
//add to results array
results.push(result);
});
//make a clone of the earlier object so that you get the parent structure.
var data1 = _.clone(data);
//set the filtered results to the group
data1.items.Groups = results;
//your data as you want
console.log(data1)
Working code here

Creating dynamic select forms based on selection

I am working on a small project.
The initial select form has N options.
Making a selection will pop up another select form based on what it is.
Example: Choose a pet: dog, cat (Chooses dog), displays types of dogs.
I am doing this using JSON and JS but im not sure I have the correct understanding of how things should be working.
What my thought process is for this, when a selection is made.. send that string to a method and then search the JSON object for that string, pull that data and create the new select.
However, it doesnt appear to be working and I think my lack of knowledge with both is hindering my progress here.
JSON
var obj = {
"option":[
{
"text":"Choose Team",
"value":"choose"
},
{
"text":"Eagles",
"value":"d"
},
{
"text":"Falcons",
"value":"c"
},
{
"text":"Browns",
"value":"b"
}
],
"Eagles":[
{
"text":"Choose Player",
"value":"Choose"
},
{
"text":"Eagles",
"value":"d"
},
{
"text":"Falcons",
"value":"c"
},
{
"text":"Browns",
"value":"b"
}
]
};
And then the JS function that creates a new select box based on the selection string
function changeSelect(select){
var test = select.options[select.selectedIndex].text;
for(var i = 0; i < obj.test.length; i++){
var objOption = document.createElement( 'option' );
objOption.setAttribute( 'value', obj.test[i].value);
objOption.appendChild( document.createTextNode( obj.test[i].text) );
}
}
Is there a reason obj.Eagles[i].text will create my new select form with the correct values but obj.test[i].text doesn't work? (Text is a variable with the String "Eagles" assigned to it)
try this... I had to change the data slightly.
(function(select1, select2) {
select1 = document.getElementById(select1);
select2 = document.getElementById(select2);
var obj = {
"option": [{
"text": "Choose Team",
"value": "choose"
}, {
"text": "Eagles",
"value": "Eagles"
}, {
"text": "Falcons",
"value": "Falcons"
}, {
"text": "Browns",
"value": "Browns"
}],
"Eagles": [{
"text": "Choose Player",
"value": "Choose"
}, {
"text": "Agholor, Nelson",
"value": "d"
}, {
"text": "Ajirotutu, Seyi",
"value": "c"
}, {
"text": "Bradford, Sam",
"value": "b"
}]
};
function populateSelect(select, data) {
for (var i = 0, objOption, element; element = data[i++];) {
objOption = document.createElement('option');
objOption.value = element.value;
objOption.innerHTML = element.text;
select.appendChild(objOption);
}
}
function changeSelect2(event) {
var test = event.target.value,
innerArray = obj[test];
select2.options.length = 0;
if (innerArray) {
populateSelect(select2, innerArray);
}
}
populateSelect(select1, obj.option);
select1.addEventListener("change", changeSelect2, false);
})("select1", "select2");
<select id="select1"></select>
<select id="select2"></select>

Categories

Resources