Comparing Objects in Array - javascript
Ok so Im building a product sorting watch and this is what I have so far.
jQuery(document).ready(function() {
// starter jQuery file
/* Watches Array */
var watchesArray = [
{
model: "Swim",
image:"",
price: 149.99,
sports:["Swimming"],
touchScreen:false,
GPS:false,
heartRateMonitor:false,
hrZoneTraining:false,
caloriesBurned:true,
distance:true,
pace:true,
multisport:false,
swimMetrics:true,
memory:"Up to 30 workouts",
virtualPartner:false,
virtualRacer:false,
paceAlert:false,
timeDistanceAlert:false,
hydrationAlert:false,
rechargeableBattery:false,
waterResistant:"Up to 50 meters",
syncWithComputer:true,
other:"",
},
{
model: "FR 10",
image:"fr_10.jpg",
price: 129.99,
sports:["Running"],
touchScreen:false,
GPS:true,
heartRateMonitor:false,
hrZoneTraining:false,
caloriesBurned:false,
distance:true,
pace:true,
multisport:false,
swimMetrics:false,
memory:"Up to 7 workouts",
virtualPartner:false,
virtualRacer:false,
paceAlert:false,
timeDistanceAlert:false,
hydrationAlert:false,
rechargeableBattery:true,
waterResistant:"Up to 50 meters",
syncWithComputer:false,
other:"-Virtual Pacer(compares running pace to target)</br>-Walk/Run feature",
checkBox:"<input type='checkbox' name='he' value='jk' id='compare'>"
},
{
model: "FR 15",
image:"fr_15.jpg",
price: 199.99,
sports:["Running"],
touchScreen:false,
GPS:true,
heartRateMonitor:true,
hrZoneTraining:true,
caloriesBurned:true,
distance:true,
pace:true,
multisport:false,
swimMetrics:false,
memory:"Up to 7 workouts",
virtualPartner:false,
virtualRacer:false,
paceAlert:false,
timeDistanceAlert:false,
hydrationAlert:false,
rechargeableBattery:true,
waterResistant:"Up to 50 meters",
syncWithComputer:false,
other:"-Virtual Pacer (compares running pace to target) </br>Walk/Run feature</br>-Activity",
},
{
model: "FR 220",
image:"fr_220.jpg",
price: 299.99,
sports:["Running"],
touchScreen:false,
GPS:true,
heartRateMonitor:true,
hrZoneTraining:true,
caloriesBurned:true,
distance:true,
pace:true,
multisport:false,
swimMetrics:false,
memory:"200 hours of data",
virtualPartner:false,
virtualRacer:false,
paceAlert:true,
timeDistanceAlert:false,
hydrationAlert:true,
rechargeableBattery:true,
waterResistant:"Up to 50 meters",
syncWithComputer:true,
other:"-Walk/Run feature</br>-Interval Training",
},
{
model: "FR 620",
image:"fr_620.jpg",
price: 449.99,
sports:["Running"],
touchScreen:true,
GPS:true,
heartRateMonitor:true,
hrZoneTraining:true,
caloriesBurned:true,
distance:true,
pace:true,
multisport:false,
swimMetrics:false,
memory:"200 hours of data",
virtualPartner:true,
virtualRacer:false,
paceAlert:true,
timeDistanceAlert:true,
hydrationAlert:true,
rechargeableBattery:true,
waterResistant:"Up to 50 meters",
syncWithComputer:true,
other:"-VO2 Max</div></br>-Walk/Run feature</br>-Interval Training",
},
{
model: "FR 310 XT",
image:"",
price: 349.99,
sports:["Multisport"],
touchScreen:false,
GPS:true,
heartRateMonitor:true,
hrZoneTraining:true,
caloriesBurned:true,
distance:true,
pace:true,
multisport:true,
swimMetrics:false,
memory:"1000 laps",
virtualPartner:true,
virtualRacer:true,
paceAlert:true,
timeDistanceAlert:true,
hydrationAlert:true,
rechargeableBattery:true,
waterResistant:"Up to 50 meters",
syncWithComputer:true,
other:"-Interval Training",
},
{
model: "FR70",
image:"",
price: 149.99,
sports:["Fitness"],
touchScreen:false,
GPS:false,
heartRateMonitor:true,
hrZoneTraining:true,
caloriesBurned:true,
distance:true,
pace:true,
multisport:false,
swimMetrics:false,
memory:"Up to 20 hrs of data",
virtualPartner:true,
virtualRacer:false,
paceAlert:true,
timeDistanceAlert:true,
hydrationAlert:false,
rechargeableBattery:false,
waterResistant:"Up to 50 meters",
syncWithComputer:true,
other:"-Interval Training",
},
];
/* End Watch Array */
/* different sports arrays filtered */
var runningArray = watchesArray.filter(function(watch) {
return watch.sports.indexOf('Running') !== -1;
});
var swimmingArray = watchesArray.filter(function(watch) {
return watch.sports.indexOf('Swimming') !== -1;
});
var multisportArray = watchesArray.filter(function(watch) {
return watch.sports.indexOf('Multisport') !== -1;
});
var fitnessArray = watchesArray.filter(function(watch) {
return watch.sports.indexOf('Fitness') !== -1;
});
function compare() {
if ($('#page-2 div:nth-of-type(1)').hasClass('running-category')) {
var sportArray = runningArray;
}
if ($('#page-2 div:nth-of-type(2)').hasClass('swimming-category')) {
var sportArray = swimmingArray;
}
if ($('#page-2 div:nth-of-type(3)').hasClass('multisport-category')) {
var sportArray = multisportArray;
}
if ($('#page-2 div:nth-of-type(4)').hasClass('fitness-category')) {
var sportArray = fitnessArray;
}
var sportArrayLength = $(sportArray).length;
for (var i = 0; i < sportArrayLength; i++) {
var watchModel = "<div class='watch-model'>"+sportArray[i].model+"</div>",
watchImage = "<div class='watch-image'>"+sportArray[i].image+"</div>",
watchPrice = "<div class='watch-price'>$"+sportArray[i].price+"</div>",
watchSports = "<div class='watch-sports'>"+sportArray[i].sports+"</div>",
watchTouch = "<div class='watch-touch'>"+sportArray[i].touchScreen+"</div>",
watchGPS = "<div class='watch-gps'>"+sportArray[i].GPS+"</div>",
watchHeart = "<div class='watch-heart'>"+sportArray[i].heartRateMonitor+"</div>",
watchHRZone = "<div class='watch-zone'>"+sportArray[i].hrZoneTraining+"</div>",
watchCalories = "<div class='watch-calories'>"+sportArray[i].caloriesBurned+"</div>",
watchDistance = "<div class='watch-distance'>"+sportArray[i].distance+"</div>",
watchPace = "<div class='watch-pace'>"+sportArray[i].pace+"</div>",
watchMultiSport = "<div class='watch-swim-metrics'>"+sportArray[i].multisport+"</div>",
watchSwimMetrics = "<div class='watch-multi'>"+sportArray[i].multisport+"</div>",
watchMemory = "<div class='watch-memory'>"+sportArray[i].memory+"</div>",
watchVirtualPartner = "<div class='watch-virtual-partner'>"+sportArray[i].virtualPartner+"</div>",
watchVirtualRacer = "<div class='watch-virtual-racer'>"+sportArray[i].virtualRacer+"</div>",
watchPaceAlert = "<div class='watch-pace-alert'>"+sportArray[i].paceAlert+"</div>",
watchTimeDistanceAlert = "<div class='watch-time-distance-alert'>"+sportArray[i].timeDistanceAlert+"</div>",
watchHydrationAlert = "<div class='watch-hydration'>"+sportArray[i].hydrationAlert+"</div>",
watchRechargeable = "<div class='watch-rechargeable'>"+sportArray[i].rechargeableBattery+"</div>",
watchWaterResistance = "<div class='watch-water-resistance'>"+sportArray[i].waterResistant+"</div>",
watchSync = "<div class='watch-syncs'>"+sportArray[i].syncWithComputer+"</div>",
watchOther = "<div class='watch-other'>"+sportArray[i].other+"</div>",
watchesTotal ="<div class='item-container'>"+ watchModel + watchImage + watchPrice + watchSports + watchTouch + watchGPS + watchHeart + watchHRZone + watchCalories + watchDistance + watchPace + watchMultiSport + watchSwimMetrics + watchMemory + watchVirtualPartner + watchVirtualRacer + watchPaceAlert + watchTimeDistanceAlert + watchHydrationAlert + watchRechargeable + watchWaterResistance + watchSync + watchOther+"</div>"
;
$('.comparison-container').append(watchesTotal);
// alert(watchModel)
}
} //end function
$("#page-4 .continue-button").click(function() {
$('.comparison-container').empty();
compare();
});
//var inArray = $.inArray(true, watchesArray[0].multisport)
// alert(inArray)
}); // ready method
So the flow is basically click a sport, filter through the array and make new array with only those items that have that sport, then select a som features that you which to have and when click continue those items that meet the criteria are displayed.
For the last part which is where I am stuck is that when those watches are displayed I have to be able to select a checkbox of those products that interest me so I can then continue and have those selected watches display with all of their details. So basically I need to figure out how to compare two objects from an array by selecting the ones that I want from the page.
On Page 3 you basically have a list of the array items and a compare checkbox under each one.I just need to be able to pass on those products that were selected to the next page
how to compare two objects from an array
Use JSON.stringify to compare the literals:
var foo = [{"1":2},{"1":3},{"2":3},{"1":2}];
var bar = JSON.stringify(foo[0]) === JSON.stringify(foo[1]);
var baz = JSON.stringify(foo[0]) === JSON.stringify(foo[3]);
Use an array as the second param to guarantee ordering of the key enumeration:
(JSON.stringify({a: 1, b: 2}, ["a","b"]) === JSON.stringify({b: 2, a: 1}, ["a","b"]))
Related
How to turn number into star rating while Ajax success using JavaScript, jQuery in Spring Boot?
I am working on a spring boot web application. I have a page where I need to show star rating system. Number of rating is stored in database. Format is: 1, 1.5, 2, 2.5...up to 5. I want to convert these numbers into stars. How should I do that after getting ajax response success from MySql DB. function getreview() { var productid = document.getElementById('pid').value; var url = "/api/getcustomerreview"; $.post(url, { productid : productid, }, function(data, status) { if (data.status == "OK") { if (data.statusCode == 1) { var div = "", des = ""; var list = data.response; var listlength = list.length; if(listlength > 0){ for(var i = 0; i < listlength; i++) { var rating = list[i].reviewrating; var stars = ""; console.log("Customer review rating: "+rating); // for product id 15 there is rating number 5 and 4 div = div + "<div class=\"row\"><div class=\"col-lg-7\"><div class=\"review-wrapper\"><div class=\"single-review\"><div class=\"review-img\">" +"<img src=\"public/web/assets/images/1.png\" alt=\"\"/></div><div class=\"review-content\">" +"<div class=\"review-top-wrap\"><div class=\"review-left\"><div class=\"review-name\">" +"<h4>"+list[i].customername+"</h4></div><div class=\"rating-product\"><i class=\"ion-android-star\"></i>" +"</div></div><div class=\"review-left\">Reply</div>" +"</div><div class=\"review-bottom\"><p>"+list[i].reviewmessage+"</p></div></div></div>" +"<div class=\"single-review child-review\"><div class=\"review-img\">\<img src=\"public/web/assets/images/2.png\" alt=\"\"/>\</div>" +"<div class=\"review-content\"><div class=\"review-top-wrap\"><div class=\"review-left\"><div class=\"review-name\">" +"<h4>"+list[i].customername+"</h4></div><div class=\"rating-product\"><i class=\"ion-android-star\"></i>" +"</div></div><div class=\"review-left\">Reply</div>" +"</div><div class=\"review-bottom\"><p>"+list[i].reviewmessage+"</p></div></div></div>" +"</div></div></div>"; document.getElementById('des-details3').innerHTML = div; } } } else { var error = data.responseMessage; swal(error, "", "error"); } } else { var error = data.responseMessage; swal(error, "", "error"); } }); } Below is div tag is to display star according to rating number that has been stored in database. <div class=\"rating-product\"><i class=\"ion-android-star\"></i></div>
You can simply use for-loop with rating as counter end value then on each iteration append your icon in some variable using += and finally append this inside html which is already generated . Demo Code : var div = "", des = ""; //just for demo var list = [{ "customername": "abc", "reviewmessage": "Good", "reviewrating": 4.5 }, { "customername": "xyz", "reviewmessage": "Very good", "reviewrating": 5 }, { "customername": "xyz", "reviewmessage": "Very good", "reviewrating": 3.5 }] //data.response; var listlength = list.length; if (listlength > 0) { for (var i = 0; i < listlength; i++) { var rating = parseInt(list[i].reviewrating); var stars = ""; //loop through rating...no for (var j = 1; j <= rating; j++) { stars += '<i class="fas fa-star" style="color:gold"></i>'; //append new star on each iteration.. } //check if there is `.` in number..means .5 if (list[i].reviewrating.toString().indexOf('.') != -1) { //half star stars += '<i class="fas fa-star-half-alt" style="color:gold"></i>' } //pass them here div = div + "<div class=\"row\"><div class=\"col-lg-7\"><div class=\"review-wrapper\"><div class=\"single-review\"><div class=\"review-img\">" + "<img src=\"public/web/assets/images/1.png\" alt=\"\"/></div><div class=\"review-content\">" + "<div class=\"review-top-wrap\"><div class=\"review-left\"><div class=\"review-name\">" + "<h4>" + list[i].customername + "</h4></div><div class=\"rating-product\">" + stars + "</div></div><div class=\"review-left\">Reply</div>" + "</div><div class=\"review-bottom\"><p>" + list[i].reviewmessage + "</p></div></div></div>" + "<div class=\"single-review child-review\"><div class=\"review-img\">\<img src=\"public/web/assets/images/2.png\" alt=\"\"/>\</div>" + "<div class=\"review-content\"><div class=\"review-top-wrap\"><div class=\"review-left\"><div class=\"review-name\">" + "<h4>" + list[i].customername + "</h4></div><div class=\"rating-product\">" + stars + "</div></div><div class=\"review-left\">Reply</div>" + "</div><div class=\"review-bottom\"><p>" + list[i].reviewmessage + "</p></div></div></div>" + "</div></div></div>"; document.getElementById('des-details3').innerHTML = div; } } <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" integrity="sha512-iBBXm8fW90+nuLcSKlbmrPcLa0OT92xO1BIsZ+ywDWZCvqsWgccV3gFoRBv0z+8dLJgyAHIhR35VZc2oM/gI1w==" crossorigin="anonymous" referrerpolicy="no-referrer" /> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/fontawesome.min.css" integrity="sha512-OdEXQYCOldjqUEsuMKsZRj93Ht23QRlhIb8E/X0sbwZhme8eUw6g8q7AdxGJKakcBbv7+/PX0Gc2btf7Ru8cZA==" crossorigin="anonymous" referrerpolicy="no-referrer" /> <div id="des-details3"> </div> Other way you can use star-rating-svg plugin to achieve this . So, you just need to initialize them with the value of rating . Demo Code : var div = "", des = ""; //just for demo var list = [{ "customername": "abc", "reviewmessage": "Good", "reviewrating": 4.5 }, { "customername": "xyz", "reviewmessage": "Very good", "reviewrating": 5 }, { "customername": "xyz", "reviewmessage": "Very good", "reviewrating": 3.5 }] //data.response; var listlength = list.length; if (listlength > 0) { $("#des-details3").empty() for (var i = 0; i < listlength; i++) { var rating = parseFloat(list[i].reviewrating); div = "<div class=\"row\"><div class=\"col-lg-7\"><div class=\"review-wrapper\"><div class=\"single-review\"><div class=\"review-img\">" + "<img src=\"public/web/assets/images/1.png\" alt=\"\"/></div><div class=\"review-content\">" + "<div class=\"review-top-wrap\"><div class=\"review-left\"><div class=\"review-name\">" + "<h4>" + list[i].customername + "</h4></div><div class=\"rating-product\"></div></div><div class=\"review-left\">Reply</div>" + "</div><div class=\"review-bottom\"><p>" + list[i].reviewmessage + "</p></div></div></div>" + "<div class=\"single-review child-review\"><div class=\"review-img\">\<img src=\"public/web/assets/images/2.png\" alt=\"\"/>\</div>" + "<div class=\"review-content\"><div class=\"review-top-wrap\"><div class=\"review-left\"><div class=\"review-name\">" + "<h4>" + list[i].customername + "</h4></div><div class=\"rating-product\"></div></div><div class=\"review-left\">Reply</div>" + "</div><div class=\"review-bottom\"><p>" + list[i].reviewmessage + "</p></div></div></div>" + "</div></div></div>"; $("#des-details3").append(div) //append your div //then intialize your rating... $("#des-details3 .row:last .rating-product").starRating({ initialRating: rating, strokeColor: '#894A00', strokeWidth: 10, starSize: 25 }); } } .rating-product { pointer-events: none/*use this if you don't want user to change rating*/ } <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/star-rating-svg#3.5.0/src/css/star-rating-svg.css"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/star-rating-svg#3.5.0/src/jquery.star-rating-svg.js"></script> <div id="des-details3"> </div>
Use array.fill() then convert the array to text: const s5 = ["\u2606", "\u2606","\u2606", "\u2606", "\u2606"]; s5.fill('\u2B50',0,rating); s5text = s5.join("");
Why do I get result as unordered list instead of ordered list?
So I have my code here that was supposed to produce an ordered list for every array of objects but instead it shows result as bullets as in unordered list and I don't understand which part went wrong as I used <ol> instead of <ul>. Please help! function onloadFunction() { var properties = [{ unitNo: "C-8-1", owner: "Foo Yoke Wai" }, { unitNo: "C-3A-3A", owner: "Chia Kim Hooi" }, { unitNo: "B-18-8", owner: "Heng Tee See" }, { unitNo: "A-10-10", owner: "Tang So Ny" }, { unitNo: "B-19-10", owner: "Tang Xiao Mi" }, ]; var idk = document.getElementById("wrapper"); var myList = "<ol>"; for (var i = 0; i < properties.length; i++) { wrapper.innerHTML += "<li>" + properties[i].unitNo + ": " + properties[i].owner + "</li>"; } myList += "</ol>"; } <html> <body onload="onloadFunction()"> <head></head> <div id="wrapper"></div> </body> </html>
The structure defined by myList with the <ol> elements is never actually added to the document. If you concatenate the <ol>, then the <li> entries, then </ol> all to wrapper.innerHTML then it should work. For example something like... var myList = "<ol>"; for (var i = 0; i < properties.length; i++) { myList += "<li>" + properties[i].unitNo + ": " + properties[i].owner + "</li>"; } myList += "</ol>"; wrapper.innerHTML = myList;
If you would check your structure in dev tools you would see there was no ol element in finale result. So you can create it: var myList = document.createElement("ol"); Then fill it with li: myList.innerHTML And then insert it: idk.insertAdjacentElement("afterbegin", myList); function onloadFunction() { var properties = [{ unitNo: "C-8-1", owner: "Foo Yoke Wai" }, { unitNo: "C-3A-3A", owner: "Chia Kim Hooi" }, { unitNo: "B-18-8", owner: "Heng Tee See" }, { unitNo: "A-10-10", owner: "Tang So Ny" }, { unitNo: "B-19-10", owner: "Tang Xiao Mi" }, ]; var idk = document.getElementById("wrapper"); var myList = document.createElement("ol"); for (var i = 0; i < properties.length; i++) { myList.innerHTML += "<li>" + properties[i].unitNo + ": " + properties[i].owner + "</li>"; } idk.insertAdjacentElement("afterbegin", myList); } <html> <body onload="onloadFunction()"> <head></head> <div id="wrapper"></div> </body> </html>
What you are trying to do is adding the innerHTML of wrapper directly as a list. You need to concat your data into li that will concat with your ol and at last add in DOM. function onloadFunction() { var properties = [{ unitNo: "C-8-1", owner: "Foo Yoke Wai" }, { unitNo: "C-3A-3A", owner: "Chia Kim Hooi" }, { unitNo: "B-18-8", owner: "Heng Tee See" }, { unitNo: "A-10-10", owner: "Tang So Ny" }, { unitNo: "B-19-10", owner: "Tang Xiao Mi" }, ]; var idk = document.getElementById("wrapper"); var myList = "<ol>"; for (var i = 0; i < properties.length; i++) { myList += "<li>" + properties[i].unitNo + ": " + properties[i].owner + "</li>"; } myList += "</ol>"; wrapper.innerHTML = myList; } window.onload = onloadFunction; <div id="wrapper"></div>
You need to loop first then place the concatenated value into the wrapper... If you look closely at your code when you inspect the parsed code in the browser inspector, you'll see that only the list items make it into the code. Then look at your myList variable, you never add that to the DOM. So by concatenating the variable and then adding it once you have the entire string added, you'll get the ordered list parent elements as they are intended. function onloadFunction() { var properties = [{ unitNo: "C-8-1", owner: "Foo Yoke Wai" }, { unitNo: "C-3A-3A", owner: "Chia Kim Hooi" }, { unitNo: "B-18-8", owner: "Heng Tee See" }, { unitNo: "A-10-10", owner: "Tang So Ny" }, { unitNo: "B-19-10", owner: "Tang Xiao Mi" }, ]; var idk = document.getElementById("wrapper"); var myList = "<ol>"; for (var i = 0; i < properties.length; i++) { myList += "<li>" + properties[i].unitNo + ": " + properties[i].owner + "</li>"; } myList += "</ol>"; wrapper.innerHTML = myList; } <html> <body onload="onloadFunction()"> <head></head> <div id="wrapper"></div> </body> </html>
JSON result value as key in JavaScript/jQuery
I have a JSON result where I want to create an accordion menu, I want one value of similar results as title of those similar rows, please check below to see what I did. Suppose a I have below JSON object var items = [ {label: "TY2021H", name: "10-Yr T-Notes", value: "TY2021H"}, {label: "TY2020Z-TY2021H", name: "10-Yr T-Notes Spread", value: "TY2020Z-TY2021H"}, {label: "TY2021H-TY2021M", name: "10-Yr T-Notes Spread", value: "TY2021H-TY2021M"}, {label: "TY2020Z-2*TY2021H+TY2021M", name: "10-Yr T-Notes Butterfly", value: "TY2020Z-2*TY2021H+TY2021M"}] The related part of my JS code is as follow: var myUL = $("#accordion"); myUL.empty(); var currentName = ""; for (var i = 0; i <= items.length - 1; i++) { var label = items[i].label; if (items[i].name != currentName) { currentName = items[i].name; list += '<a href="#demo' + i + '" class="list-group-item list-group-item-info" data-toggle="collapse" data-parent="#accordion">' + currentName + ' <span id="opnClsSign" class="glyphicon glyphicon-menu-down"></span></a>'; list += '<div class="collapse in" id="demo' + i + '">'; } list += '' + label + ""; } list += "</div>"; myUL.append(list); Part of my HTML div <div class="list-group panel" id="accordion"></div> Result I get now What I expect
Code indentation can help in a situation like this. Your last two lines should be inside the loop for the code to make sense. In every iteration, you must close the div and add the code to myUL: var items = [ {label: "TY2021H", name: "10-Yr T-Notes", value: "TY2021H"}, {label: "TY2020Z-TY2021H", name: "10-Yr T-Notes Spread", value: "TY2020Z-TY2021H"}, {label: "TY2021H-TY2021M", name: "10-Yr T-Notes Spread", value: "TY2021H-TY2021M"}, {label: "TY2020Z-2*TY2021H+TY2021M", name: "10-Yr T-Notes Butterfly", value: "TY2020Z-2*TY2021H+TY2021M"}] var myUL = $("#accordion"); myUL.empty(); var currentName = ""; for (var i = 0; i <= items.length - 1; i++) { var label = items[i].label; var list = ''; if (items[i].name != currentName) { currentName = items[i].name; list += '<a href="#demo' + i + '" class="list-group-item list-group-item-info" data-toggle="collapse" data-parent="#accordion">' + currentName + ' <span id="opnClsSign" class="glyphicon glyphicon-menu-down"></span></a>'; list += '<div class="collapse in" id="demo' + i + '">'; } list += '' + label + ""; list += "</div>"; myUL.append(list); } <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <div class="list-group panel" id="accordion"></div> Also, you needed to define list.
I resolved the issue my self, and I have added the final source code into this pen: [https://codepen.io/rafihaidari/pen/ExyBGVK]
JQuery adding and saving data input in row
I am having trouble saving the new row. When i click on add person I am able to input the data, however, i am not sure how to save it and add a new row. I know i have to make a function for the save button to work however i am stuck on how to make it work. I have tried a few times but to no avail. var isNewLineToggled = false; var isAscending = { name : false, lastName: false, dob: false }; $(".main").append("<input placeholder='search by name' class='search'/><br/><br/>") $(".main").append("<button onclick=addPerson()>add a person</button><br/><br/>") var table = $(".main").append("<table></table>"); var thead = '<thead><tr></tr></thead>'; table.append(thead); var header = [ { title: 'Name', sortBy: 'name'}, { title: 'Last Name', sortBy: 'lastName'}, { title: 'Date of birth', sortBy: 'dob'} ].map( function(header) { var sortButton = '<button id="' + header.sortBy + '" onclick=sortRows("'+ header.sortBy + '")>/\\</button>'; $('thead').append('<th>' + header.title + ' ' + sortButton + '</th>'); } ) var tbody = "<tbody></tbody>"; var data = [ {name: 'Peter', lastName: 'Petterson', dob: '13/12/1988'}, {name: 'Anna', lastName: 'Jones', dob: '06/02/1968'}, {name: 'John', lastName: 'Milton', dob: '01/06/2000'}, {name: 'James', lastName: 'White', dob: '30/11/1970'}, {name: 'Luke', lastName: 'Brown', dob: '15/08/1999'} ]; $('.search').change(function(event) { searchedName = event.target.value; }) table.append(tbody); data.map( function(row, i) { $('tbody').append( '<tr><td>' + row.name + '</td><td>' + row.lastName + '</td><td>' + row.dob + '</td><td><button onclick=editRow('+i+')>edit</button><button>delete</button></td></tr>' ) } ) var editableRow = "<td><input/></td><td><input/></td><td><input type='date'/></td><td><button onclick=saveRow()>save</button></td>"; var addPerson = function() { isNewLineToggled = !isNewLineToggled; if (isNewLineToggled) { $('tbody').prepend('<tr>' + editableRow + '</tr>') } else { $('tbody > tr:first-child').remove(); } } var editRow = function(rowNumber) { var name = $('tbody > tr:nth-child('+(rowNumber + 1)+') > td:first-child').text(); var lastName = $('tbody > tr:nth-child('+(rowNumber + 1)+') > td:nth-child(2)').text(); var dob = $('tbody > tr:nth-child('+(rowNumber + 1)+') > td:nth-child(3)').text(); $('tbody > tr:nth-child('+(rowNumber + 1)+')').html(editableRow2); $('tbody > tr:nth-child('+(rowNumber + 1)+') > td:first-child > input').val(name); $('tbody > tr:nth-child('+(rowNumber + 1)+') > td:nth-child(2) > input').val(lastName); }
You can add row like this, two small changes: $(".main").append("<button class='add'>add a person</button><br/><br/>") Remove inline event handler, no need for it. And your function could be: $('body').on('click','.add', function() { //you will need event delegation, because of dynamically added elements isNewLineToggled = !isNewLineToggled; if (isNewLineToggled) { $('tbody').prepend('<tr>' + editableRow + '</tr>') } else { $('tbody > tr:first-child').remove(); } }); Since your editableRow variable isn't defined, i've used just one cell with text for demo: https://jsfiddle.net/2c97auey/1/ P.S. Your editableRow should have input(s) values, properly placed in cells. Shouldn't be too hard.
How to separate items rendered from .getJSON by category prop
I've got a menu of coffee, for example, each with it's own parentCategory and I want to render them on the page like so but I'm not entirely sure where to start: category title item item item item category title item item My data model looks like this: { "menuItems": [ { "index": 0, "parentCategory": "Americanos", "calories": 234, "name": "Caffè Americano", "photos": { "squareThumb": "http://www.starbucks.com/assets/67c30b9dacd4406db797b1690ac22475.jpg" } }, { "index": 0, "parentCategory": "Lattes", "calories": 234, "name": "Caffè Latte", "photos": { "squareThumb": "http://www.starbucks.com/assets/aee68ca3048142f38741f20b30b7a581.jpg" } }, { "index": 0, "parentCategory": "Mochas", "calories": 234, "name": "Caffè Mocha", "photos": { "squareThumb": "http://www.starbucks.com/assets/bc15a5ca9d744b66bda07254f2f50013.jpg" } }... and my current script looks like so: $.getJSON('menu.json', function(drinks) { var getMenuItem = drinks.menuItems; var sortedArray = getMenuItem.sort(function(a,b){ return a.parentCategory > b.parentCategory ?1 :-1 }) var output = ""; for (var i in sortedArray) { output += "<div class='menuItem'><p>" + drinks.menuItems[i].name + "</p><img src='" + drinks.menuItems[i].photos.squareThumb + "'/></div>"; } document.getElementById("demo").innerHTML=output; });
Keep the latest category in a variable. Whenever the category changes, start a new <div> for the category. var last_cat = null; var output = ""; for (var i in sortedArray) { var item = sortedArray[i]; if (item.parentCategory != last_cat) { if (last_cat) { // close the previous category output += "</div>"; } output += "<div class='category'><p>" + item.parentCategory + "</p>"; last_cat = item.parentCategory; } output += "<div class='menuItem'><p>" + item.name + "</p><img src='" + item.photos.squareThumb + "'/></div>"; } if (last_cat) { output += "</div>"; }