JSON add value on click - javascript

I'm trying to make a site of restaurant and now doing some table reservation. So far have one problem:
I have a JSON of tables and want to add date (day/time) to it, when table was clicked.
The problem's next - when I click on some table, the date adds to all JSON elements. And I wand to add it only to the element I clicked.
Here is link to codepen:
https://codepen.io/wilchilly/pen/qBEvegW
(To see the result click on some table and open console)
My HTML:
<p class="href-to italic" id="showMore">Show tables</p>
<div class="wrapper" id="wrapper">
<div class="tables-wrapper" id="tables-wrapper"></div>
</div>
JS:
fetch('tables.json')
.then(response => response.json())
.then(json => {
const myJson = json;
let showTables = document.getElementById('showMore');
//show elements on page
function loadGoods(data) {
let out = '';
for (let key in data) {
if (data[key].isAvailable == false) {
out += '<div class="single-table not-available" data-name="' + data[key]['name'] + '" data-art="' + data[key]['id'] + '">';
out += '<h4>' + data[key]['name'] + '</h4>';
out += '<p>' + data[key]['location'] + '</p>';
out += '</div>';
} else {
out += '<div class="single-table" data-name="' + data[key]['name'] + '" data-art="' + data[key]['id'] + '">';
out += '<h4>' + data[key]['name'] + '</h4>';
out += '<p>' + data[key]['location'] + '</p>';
out += '</div>';
}
}
$('#tables-wrapper').html(out);
}
//set Date (day/time)
function setDate() {
for (let key in myJson) {
myJson[key]['date']['day'] = '10/02';
myJson[key]['date']['time'] = '20:00';
}
console.log(myJson);
}
showTables.addEventListener('click', function () {
loadGoods(myJson);
let singleTable = document.getElementsByClassName('single-table');
Array.from(singleTable).forEach(function (element) {
element.addEventListener('click', setDate);
});
});
})
JSON:
[
{
"id": 0,
"index": 0,
"name": "Table 1",
"capacity": 5,
"isAvailable": true,
"location": "Bar",
"date": {
"day": " ",
"time": ""
}
},
{
"id": 1,
"index": 1,
"name": "Table 2",
"capacity": 5,
"isAvailable": true,
"location": "Patio",
"date": {
"day": " ",
"time": " "
}
},
{
"id": 2,
"index": 2,
"name": "Table 3",
"capacity": 5,
"isAvailable": true,
"location": "Bar",
"date": {
"day": " ",
"time": " "
}
},
{
"id": 3,
"name": "Table 4",
"capacity": 6,
"isAvailable": true,
"location": "Inside",
"date": {
"day": " ",
"time": " "
}
}
]

I found a solution. This might be helpful for someone with a similar question.
function setDate() {
let inputDay = document.getElementById('form-data').value;
let inputTime = document.getElementById('form-time').value;
for (let i = 0; i < myJson.length; i++) {
if (this.getAttribute('data-art') == myJson[i].id) {
myJson[i]['date']['day'] = inputDay;
myJson[i]['date']['time'] = inputTime;
}
}
}

Just use the index from the iteration on table creation as id (or any attr you like) for example (you will probably need a classic for or a foreach) and then, in the event you attached pass the click event as param. Finally you just use the event.target to get the id (or the attr you choose) of the element and use it in the setDate func.

Related

Select filter hides all the items in the list

I am trying to create a select dropdown filter which dynamically gets its values and data from rest api.
Here is my code
HTML
<div class="container">
<select data-filter="season" class="filter_category_name filter form-control"></select>
<div class="listContent" id="listitem"></div>
</div>
JS
var data = [{
"category_name": "1",
"title": "One One",
"more": [{
"details": "some details"
}]
},
{
"category_name": "1",
"title": "One Two",
"more": [{
"details": "some details"
}]
},
{
"category_name": "2",
"title": "Two One",
"more": [{
"details": "some details"
}]
},
{
"category_name": "3",
"title": "Three One",
"more": [{
"details": "some details"
}]
}];
let listItems = "",
categoryAll = "";
for(var i = 0;i < data.length; i++) {
var title = data[i].title,
category_name = data[i].category_name;
listItems += "<a onclick='createAVideoContainer(" + i + ")'><div class='listItem'><p>" + title + "</p></div></div></a>";
if (categoryAll.indexOf("<option value='" + category_name + "'>" + category_name + "</option>") == -1) {
categoryAll += "<option value='" + category_name + "'>" + category_name + "</option>";
}
}
$("#listitem").html(listItems);
$(".filter_category_name").append(categoryAll);
var filtersObject = {};
$(".filter").on("change",function() {
var filterName = $(this).data("filter"),
filterVal = $(this).val();
if (filterVal == "") {
delete filtersObject[filterName];
} else {
filtersObject[filterName] = filterVal;
}
var filters = "";
for (var key in filtersObject) {
if (filtersObject.hasOwnProperty(key)) {
filters += "[data-"+key+"='"+filtersObject[key]+"']";
}
}
if (filters == "") {
$(".listItem").show();
} else {
$(".listItem").hide();
$(".listItem").hide().filter(filters).show();
}
});
But for some reason it hides all the items and nothing change after changing the options
I want to initially load all the items and then filter based on the option
I want the select element to dynamically create the options with the values of the category names like the first option should have the value of cars1 and display all the other objects with the same category_name.
Note: The entire code is wrapped inside an async function which renders on page load.
Here is a proper working js fiddle with the above problem
Based on your fiddle code, it would be better to filter the <a> items within the listItem area based on season, as that is the filter that is built, instead of trying to show/hide the entire listItem area.
The two minor code changes to achieve the desired result, is at these two code points:
Add a data-season reference here, to the <a> tags, with the category_name value:
listItems += '<a data-season="' + category_name + '" '
+ "onclick='createAVideoContainer(" + i + ")'><div class='listItem'><p>"
+ title + "</p></div></a>";
Change the filtering to filter on the <a> tags for the data-season that you build:
if (filters == "") {
$("a").show();
} else {
$("a").hide();
$("a").filter(filters).show();
}
Integrating those two changes into your fiddle example code, try the runnable example below:
var data = [
{
"category_name": "1",
"title": "One One",
"more": [
{
"details": "some details"
}
]
},
{
"category_name": "1",
"title": "One Two",
"more": [
{
"details": "some details"
}
]
},
{
"category_name": "2",
"title": "Two One",
"more": [
{
"details": "some details"
}
]
},
{
"category_name": "3",
"title": "Three One",
"more": [
{
"details": "some details"
}
]
},
];
let listItems = "",
categoryAll = "";
for(var i = 0; i < data.length; i++) {
var title = data[i].title,
category_name = data[i].category_name;
listItems += '<a data-season="' + category_name + '"'
+ "onclick='createAVideoContainer(" + i + ")'><div class='listItem'><p>"
+ title + "</p></div></a>";
if (categoryAll.indexOf("<option value='" + category_name + "'>" + category_name + "</option>") == -1) {
categoryAll += "<option value='" + category_name + "'>" + category_name + "</option>";
}
}
$("#listitem").html(listItems);
$(".filter_category_name").append(categoryAll);
var filtersObject = {};
//on filter change
$(".filter").on("change",function() {
var filterName = $(this).data("filter"),
filterVal = $(this).val();
if (filterVal == "") {
delete filtersObject[filterName];
} else {
filtersObject[filterName] = filterVal;
}
var filters = "";
for (var key in filtersObject) {
if (filtersObject.hasOwnProperty(key)) {
filters += "[data-"+key+"='"+filtersObject[key]+"']";
}
}
if (filters == "") {
$("a").show();
} else {
$("a").hide();
$("a").filter(filters).show();
}
});
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.1.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KyZXEAg3QhqLMpG8r+8fhAXLRk2vvoC2f3B09zVXn8CA5QIVfZOJ3BCsw2P0p/We" crossorigin="anonymous">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<div class="container">
<select data-filter="season" class="filter_category_name filter form-control"></select>
<div class="listContent" id="listitem">
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/#popperjs/core#2.9.3/dist/umd/popper.min.js" integrity="sha384-eMNCOe7tC1doHpGoWe/6oMVemdAVTMs2xqW4mwXrXsW0L84Iytr2wi5v2QjrP/xp" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.1.0/dist/js/bootstrap.min.js" integrity="sha384-cn7l7gDp0eyniUwwAZgrzD06kc/tftFf19TOAs2zVinnD/C7E91j9yyk5//jjpt/" crossorigin="anonymous"></script>
Here's the updated fiddle with the same change applied.

Why do I keep on getting null in the console log?

In the JS, I am creating an input element which will be nested inside a div with id "scripts" on the html. I attach a value to that input field via JS and later on I want to catch the value of the input in another JS function. The problem is that when I run the page in the inspect element I can see that there is a value in the input that I created, that input has id "spam_key", but the function that I have created to access and get the value out of the input element is not working properly. If I go to the console, and write console.log(str) I am getting null as result.
Here is what I have in the HTML:
<div id="scripts" name="scripts">
</div>
This is the HTML when I run the page and the input field is created:
<div id="scripts" name="scripts">
<input type="number" id="spam_key" value="239">
</div>
Now, this is my JS:
var c = 0;
var a;
var b;
function counter() {
return c++;
}
$(document).ready(function () {
var url = "https://graph.facebook.com/v3.2/...";
$.getJSON(url, function (data) {
var items = [];
$.each(data.data, function (i, obj) {
//$('#target').append($('<div/>', { id: 'dummy' + i }))
var text = '<p class="review_text">' + obj.review_text + '</p>'
var date = '<p class="date">' + obj.created_time + '</p>'
a = counter();
$("#carousel").find("[data-index='" + i + "']").append(text, date)
});
$('#scripts').append('<input type="number" id="spam_key" value= ' + a + '>');
});
});
And this is what I use to get the value of the input element:
var str;
$(document).ready(function () {
element = document.getElementById('spam_key');
if (element !== null) {
str = element.value;
}
else {
str = null;
}
});
Here the value of str should be appled:
$(document).ready(function () {
var wrapper = document.getElementById("carousel");
var myHTML = '';
for (b = 0; b <= str; b++) {
myHTML += '<div id="review" data-index=' + (b) + '></div>';
}
wrapper.innerHTML = myHTML
});
What I've done is to move the body of your input-retrieval-function from the second $(document).ready() to the callback function of your getJSON method after you've created the input element. This way we can make sure to access it after the element is created. I've also added a var str; to the global scope where you store the value.
Hope that helps.
var c = 0;
var a;
var b;
var str;
function counter() {
return c++;
}
$(document).ready(function () {
var url = "https://graph.facebook.com/v3.2/...";
$.getJSON(url, function (data) {
var items = [];
$.each(data.data, function (i, obj) {
//$('#target').append($('<div/>', { id: 'dummy' + i }))
var text = '<p class="review_text">' + obj.review_text + '</p>'
var date = '<p class="date">' + obj.created_time + '</p>'
a = counter();
$("#carousel").find("[data-index='" + i + "']").append(text, date)
});
$('#scripts').append('<input type="number" id="spam_key" value= ' + a + '>');
element = document.getElementById('spam_key');
if (element !== null) {
str = element.value;
}
else {
str = null;
}
var wrapper = document.getElementById("carousel");
var myHTML = '';
for (b = 0; b <= str; b++) {
myHTML += '<div id="review" data-index=' + (b) + '></div>';
}
wrapper.innerHTML = myHTML
});
});
Here is a sample from the JSON:
{
"data": [
{
"has_review": true,
"review_text": "Mng sum zadovolna se bese \ud83d\udc4c\ud83c\udffc",
"recommendation_type": "positive",
"created_time": "December 6, 2018",
"open_graph_story": {
"id": "1924663150981821",
"message": "Mng sum zadovolna se bese \ud83d\udc4c\ud83c\udffc",
"start_time": "December 6, 2018",
"type": "sellers.rates",
"data": {
"recommendation_type": "positive",
"review_text": "Mng sum zadovolna se bese \ud83d\udc4c\ud83c\udffc",
"is_hidden": false,
"language": "mk",
"seller": {
"id": "2075976265961628",
"title": "My Spa Home & Office Massage - \u041c\u0430\u0441\u0430\u0436\u0430 \u0432\u043e \u0432\u0430\u0448\u0438\u043e\u0442 \u0434\u043e\u043c \u0438\u043b\u0438 \u0440\u0430\u0431\u043e\u0442\u043d\u043e \u043c\u0435\u0441\u0442\u043e",
"type": "place",
"url": "https://www.facebook.com/myspamk/"
},
"has_review_update": false
}
},
"has_rating": false
},
{
"has_review": true,
"review_text": "\u041e\u0434\u043b\u0438\u0447\u043d\u043e \u0438\u0441\u043a\u0443\u0441\u0442\u0432\u043e. \u0420\u0435\u0442\u043a\u043e \u0441\u0430\u043a\u0430\u043c \u043c\u0430\u0441\u0430\u0436\u0438, \u0437\u0430\u0448\u0442\u043e \u043c\u0438 \u0441\u0435 \u043d\u0435\u043f\u0440\u0438\u0458\u0430\u0442\u043d\u0438 \u0447\u0435\u0441\u0442\u043e, \u043d\u043e, \u043e\u0432\u0430 \u0442\u043e\u043f\u043b\u043e \u0433\u043e \u043f\u0440\u0435\u043f\u043e\u0440\u0430\u0447\u0443\u0432\u0430\u043c! \u0411\u0440\u0430\u0432\u043e \u0434\u0435\u0447\u043a\u0438. \u2764",
"recommendation_type": "positive",
"created_time": "December 5, 2018",
"open_graph_story": {
"id": "1145960125557706",
"message": "\u041e\u0434\u043b\u0438\u0447\u043d\u043e \u0438\u0441\u043a\u0443\u0441\u0442\u0432\u043e. \u0420\u0435\u0442\u043a\u043e \u0441\u0430\u043a\u0430\u043c \u043c\u0430\u0441\u0430\u0436\u0438, \u0437\u0430\u0448\u0442\u043e \u043c\u0438 \u0441\u0435 \u043d\u0435\u043f\u0440\u0438\u0458\u0430\u0442\u043d\u0438 \u0447\u0435\u0441\u0442\u043e, \u043d\u043e, \u043e\u0432\u0430 \u0442\u043e\u043f\u043b\u043e \u0433\u043e \u043f\u0440\u0435\u043f\u043e\u0440\u0430\u0447\u0443\u0432\u0430\u043c! \u0411\u0440\u0430\u0432\u043e \u0434\u0435\u0447\u043a\u0438. \u2764",
"start_time": "December 5, 2018",
"type": "sellers.rates",
"data": {
"recommendation_type": "positive",
"review_text": "\u041e\u0434\u043b\u0438\u0447\u043d\u043e \u0438\u0441\u043a\u0443\u0441\u0442\u0432\u043e. \u0420\u0435\u0442\u043a\u043e \u0441\u0430\u043a\u0430\u043c \u043c\u0430\u0441\u0430\u0436\u0438, \u0437\u0430\u0448\u0442\u043e \u043c\u0438 \u0441\u0435 \u043d\u0435\u043f\u0440\u0438\u0458\u0430\u0442\u043d\u0438 \u0447\u0435\u0441\u0442\u043e, \u043d\u043e, \u043e\u0432\u0430 \u0442\u043e\u043f\u043b\u043e \u0433\u043e \u043f\u0440\u0435\u043f\u043e\u0440\u0430\u0447\u0443\u0432\u0430\u043c! \u0411\u0440\u0430\u0432\u043e \u0434\u0435\u0447\u043a\u0438. \u2764",
"is_hidden": false,
"language": "mk",
"seller": {
"id": "2075976265961628",
"title": "My Spa Home & Office Massage - \u041c\u0430\u0441\u0430\u0436\u0430 \u0432\u043e \u0432\u0430\u0448\u0438\u043e\u0442 \u0434\u043e\u043c \u0438\u043b\u0438 \u0440\u0430\u0431\u043e\u0442\u043d\u043e \u043c\u0435\u0441\u0442\u043e",
"type": "place",
"url": "https://www.facebook.com/myspamk/"
},
"has_review_update": false
}
},
"has_rating": false
},
{
"has_review": true,
"review_text": "The best massage in Skopje, highly recommend!",
"recommendation_type": "positive",
"created_time": "November 28, 2018",
"open_graph_story": {
"id": "10214943185147892",
"message": "The best massage in Skopje, highly recommend!",
"start_time": "November 28, 2018",
"type": "sellers.rates",
"data": {
"recommendation_type": "positive",
"review_text": "The best massage in Skopje, highly recommend!",
"is_hidden": false,
"language": "en",
"seller": {
"id": "2075976265961628",
"title": "My Spa Home & Office Massage - \u041c\u0430\u0441\u0430\u0436\u0430 \u0432\u043e \u0432\u0430\u0448\u0438\u043e\u0442 \u0434\u043e\u043c \u0438\u043b\u0438 \u0440\u0430\u0431\u043e\u0442\u043d\u043e \u043c\u0435\u0441\u0442\u043e",
"type": "place",
"url": "https://www.facebook.com/myspamk/"
},
"has_review_update": false
}
},
"has_rating": false
},

Wrap every new type child into one row

Every same child type should wrap in div. The problem is I am getting single array which contains all the children. So I am running loop over it and tried to create new div and close it when children type changed but it is not well written.
fiddle
var items = [{
"type": "child1",
"name": "1 "
}, {
"type": "child1",
"name": "1 "
}, {
"type": "child1",
"name": "1 "
}, {
"type": "child2",
"name": "2 "
}, {
"type": "child2",
"name": "2"
}, {
"type": "child3",
"name": "3 "
}, {
"type": "child3",
"name": "3 "
}, {
"type": "child3",
"name": "3"
}]
var child = "";
var html = ''
items.forEach(function(item) {
if (child !== item.type) {
html += '<div>'
}
html += '<div>' + item.name + ' </div>';
if (child !== item.type && child) {
html += '</div>'
}
child = item.type;
})
document.getElementById('html').innerHTML = html;
div { border:1px solid black }
<div id="html"></div>
what you should do, is when you check whether child is not the same with item.type, you should add a closing </div> and a new open <div>
items.forEach(function(item) {
if(child != item.type){
html += '</div>';
html += '<div>';
}
html += '<div>' + item.name + ' </div>';
child = item.type;
})
demo : https://jsfiddle.net/0sz9xpxq/2/
You can try this,
https://jsfiddle.net/trupti11/0sz9xpxq/4/
var html = '<div>';
items.forEach(function(item) {
if (child != item.type && child) {
html += '</div><div>'+ item.name;
}
else
{
html += item.name;
}
child = item.type;
})
html += '</div>';
Instead of messy text manipulation, you can use document.createElement to do it a lot cleaner. There's a great answer to this SO question that talks about the benefits of using createElement vs adding a string to innerHTML
var child = "";
var html = document.getElementById('html');
var node;
items.forEach(function(item) {
if (child !== item.type) {
if (node) {
html.appendChild(node);
}
node = document.createElement('div');
}
var newElem = document.createElement('div');
newElem.innerHTML = item.name;
node.appendChild(newElem);
child = item.type;
});
html.appendChild(node);
Fiddle

How to iterate JSON Array in Jquery

I have this below type of array. I want to iterate this array in JavaScript. How is this possible?
{
"result": true,
"data": [
{
"ID": 1,
"stage_ID": 1,
"badge_type_ID": 1,
"name": "Despertar da Força",
"description": "Fazer a primeira SuperAtividade",
"type": "",
"image_static": "url123.jpg",
"image_animated": "",
"SQL": "",
"published": 1
},
{
"ID": 2,
"stage_ID": 1,
"badge_type_ID": 1,
"name": "Super 3",
"description": "Fazer 3 SuperAtividades",
"type": "",
"image_static": "urlimage123.png",
"image_animated": "",
"SQL": "",
"published": 1
}
etc
I tried the following script and it is returning "undefined", "undefined".
$.getJSON('https://www.legiaodossuperpoderes.com.br/chronus/api/adm/badges', function(data) {
var output= "<ol>";
for (var i in data) {
output += "<li>" + data[i].ID + "</li>"
}
output+="</ol>";
document.getElementById("placeholder").innerHTML=output;
});
Any solutions ? Thanks!
You can try converting to Json Object
$.getJSON('https://www.legiaodossuperpoderes.com.br/chronus/api/adm/badges', function(data) {
var output= "<ol>";
var jsondata = $.JSON.parse(data); // Json object Convertion
for (var i in data) {
output += "<li>" + data[i].ID + "</li>"
}
output+="</ol>";
document.getElementById("placeholder").innerHTML=output;
});
You are trying to access an undefined property using data[i].ID .
When you are getting response from your getJSON() function then you need to call the response with a name and then you can access any inner property using this name .
Now if you want to iterate using data key/value on myResponse variable then you need to do this.
$.getJSON('https://www.legiaodossuperpoderes.com.br/chronus/api/adm/badges', function(myResponse) {
var output= "<ol>";
var dataCount = myResponse.data.length;
for (var i = 0; i < dataCount; i++) {
output += "<li>" + myResponse.data[i].ID + "</li>";
}
output+="</ol>";
document.getElementById("placeholder").innerHTML=output;
});

Array data wont display in a table

I have an ajax function which sends a get request to an api and returns data in the following format-
{
"firstname": "John",
"lastname": "Doe",
"email": "doej#gmail.com",
"subjects": [
{
"id": 1,
"name": "maths"
},
{
"id": 2,
"name": "chemistry"
}
]
},
I need to display this data in a table but am having trouble getting the subjects array to display correctly, ie as a list in one table cell. I have tried to put the array data into another table inside the main one but it's not working out. I presume I'm going very wrong somewhere in my iteration loops.
function getPeople() {
$.ajax({
type: "GET",
url: "http://example.com",
contentType: "application/json; charset=utf-8",
crossDomain: true,
dataType: "json",
success: function (data, status, jqXHR) {
// fill a table with the JSON
$("table.mytable").html("<tr><th></th><th>First Name</th><th>Last Name</th><th>Subjects</th></tr>" );
for (var i = 0; i < data.length; i++) {
for (var j = 0; j < data[i].subjects.length; j++) {
var subjects = data[i].subjects[j];
$("table.insidetable").append('<tr><td>' + subjects + 'tr><td>')
}
$("table.mytable").append('<tr><td><input type = "checkbox" id = '+data[i].id+'>' + "</td><td>" + data[i].firstname + "</td><td>" + data[i].lastname + "</td><td>" + "table.insidetable" + "</td></tr>");
}
},
error: function (jqXHR, status) {
// error handler
console.log(jqXHR);
alert('fail' + status.code);
}
});
}
Below is the working (tested) code.
var data = [{
"firstname": "John",
"lastname": "Doe",
"email": "doej#gmail.com",
"subjects": [
{
"id": 1,
"name": "maths"
},
{
"id": 2,
"name": "chemistry"
}
]
},
{
"firstname": "Steve",
"lastname": "Gentile",
"email": "steve#gmail.com",
"subjects": [
{
"id": 1,
"name": "history"
},
{
"id": 2,
"name": "geography"
}
]
}];
$("table.mytable").html("<tr><th></th><th>First Name</th><th>Last Name</th><th>Subjects</th></tr>");
for (var i = 0; i < data.length; i++) {
var subjectList = '';
for (var j = 0; j < data[i].subjects.length; j++) {
subjectList += '<li>' + data[i].subjects[j].name + '</li>';
}
$("table.mytable").append('<tr><td><input type="checkbox" id=' + i +'/></td><td>' + data[i].firstname + '</td><td>' + data[i].lastname + '</td><td><ul>' + subjectList + '</ul></td></tr>');
}
It seems there are many problems in below statement like,
Tags are not closed properly
Properties that do not exist are being used (data[i].id)
Single and Double quotes don't match
...
$("table.mytable").append('<tr><td><input type = "checkbox" id = '+data[i].id+'>' + "</td><td>" +data[i].firstname + "</td><td>" + data[i].lastname + "</td><td>" + "table.insidetable"+ "</td></tr>");
As a guess are you missing a '<'?
In the line:
$("table.insidetable").append('<tr><td>' + subjects + 'tr><td>')
Also
$("table.mytable").append('<tr><td><input type = "checkbox" id = '+data[i].id+'>' + "</td><td>" + data[i].firstname + "</td><td>" + data[i].lastname + "</td><td>" + "table.insidetable" + "</td></tr>");
I don't think you should be appending "table.insidetable"? This will be seen rendered as the value "table.insidetable" and not the contents of the table. I think this should rather be something like $("table.insidetable").val()

Categories