I'm very new with coding javascript and also with json data.
I have this code and first of all i want to Group by "week" but i only want to sum the column "resultat"
The column "Start" do i want to show the first value, and in the column "Slut" i want to show the latest value.
Is this possible? And if, do anyone have any suggestions how?
As i sad i'm really new so i'm totaly lost :)
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>
var request = new XMLHttpRequest();
request.open("GET", "/weekresult.json", false);
request.overrideMimeType("application/json");
request.send(null);
var jsonData, i, j, x = "";
var jsonData = JSON.parse(request.responseText);
console.log(jsonData);
x += "<table style='border:1px SOLID black;'>";
x += "<tr><th style='background:silver;'>Vecka</th><th style='background:silver;'>Öppning</th><th style='background:silver;'>Stängning</th><th style='background:silver;'>Resultat</th><th style='background:silver;'>Procent</th></tr>";
for (i in jsonData.vecka) {
x += "<tr>";
x += "<td style='text-align:center;width:20%;'>" + jsonData.vecka[i].week + "</td>";
x += "<td style='text-align:center;width:20%;'>" + jsonData.vecka[i].start + " SEK</td>";
x += "<td style='text-align:center;width:20%;'>" + jsonData.vecka[i].slut + " SEK</td>";
x += "<td style='text-align:center;width:20%;'>" + jsonData.vecka[i].resultat + " SEK</td>";
x += "<td style='text-align:center;width:20%;'>" + jsonData.vecka[i].procent + "%</td>";
x += "</tr>";
}
x += "</table>";
document.getElementById("demo").innerHTML = x;
</script>``
This is the code that does what you are looking for. It does not generate any DOM Elements, however it takes care of all the logic except for "percent" as you did not specify what is supposed to happen to that value.
To summarize:
Create an Array that holds all the "groups"
Fill that Array with the grouped weeks. If a week is already tracked, add its value to the tracking objects data-Array, else create a new Group.
Now just iterate through every group, display the groups week value and perform the logic to finding the min (start), max (slut) and summed (resultat) values. All of that can be done with the reduce method.
Log/Display the results.
const { vecka } = { "vecka": [{ "week": "20-15", "start": 1000, "slut": 1019, "resultat": "19", "procent": "1.90" }, { "week": "20-15", "start": 1019, "slut": 1036, "resultat": "17", "procent": "1.67" }, { "week": "20-15", "start": 1036, "slut": 1060, "resultat": "24", "procent": "2.32" }, { "week": "20-15", "start": 1060, "slut": 1090, "resultat": "30", "procent": "2.83" }, { "week": "20-16", "start": 1090, "slut": 1121, "resultat": "31", "procent": "2.84" }] };
const sets = [];
for (let set of vecka) {
// Find week if it is already tracked
const trackedWeek = sets.filter(w => w.time == set.week)[0];
if (!trackedWeek) {
// If week is not already being tracked, create a new entry
sets.push({ time: set.week, data: [set]});
} else {
// If week is already being tracked, add data to week
trackedWeek.data.push(set);
}
};
for (let set of sets) {
// Find start
const start = set.data.reduce((min, { start }) => {
if (!min) return start;
return min > start ? start : min;
}, null);
// Find end
const end = set.data.reduce((max, { slut }) => {
if (!max) return slut;
return max < slut ? slut : max;
}, null);
// Accumulate resultat
const resultat = set.data.reduce((acc, { resultat }) => (acc += parseInt(resultat)), 0);
console.log("week: ", set.time);
console.log("start: ", start);
console.log("slut: ", end);
console.log("resultat: ", resultat);
}
Hope this helps. Take a look at Arrays and Objects and their methods. That is usually all you need to perform these kinds of manipulations.
Related
I have
"resource_ratio": [
[
"Barbara",
"Ben",
"Anne",
"John",
"Cindy",
"Nick",
"Lex",
"Edd",
"Eric",
"Jacky",
"Paul"
],
[
0.11974110032362459,
0.037756202804746494,
0.23516720604099245,
0.10895361380798274,
0.10140237324703344,
0.03559870550161812,
0.02912621359223301,
0.08737864077669903,
0.02481121898597627,
0.1186623516720604,
0.10140237324703344
]
]
this 2 dim array that I want to display on HTML page using javascript
and then get the result back in JSON from after clicking a button.
For now, I displayed the values of resource_raio using this
var resourceRatioBoxTag = new Array();
var resourceRatioTag = new Array();
for (var i = 0; i < selectedData.resource_ratio.length; i++) {
//selectedData.resource_ratio[1][0]
resourceRatioBoxTag[i] = "<input id='resourceRatio[" + i + "]' name='resourceRatio'>";
for (var j = 0; j < selectedData.resource_ratio[i].length; j++) {
resourceRatioBoxTag[i] += "<input type='text' id='resourceRatio[" + i + "][" + j + "]' value='" + selectedData.resource_ratio[i][j] + "' name='" + i + "'>";
}
resourceRatioBoxTag[i] += "</input>";
$("#resourceRatioDiv").append(resourceRatioBoxTag[i]);
}
which gave me result of one single array with all the values inside like [val1, val2, val3]
And when I do
var dataBox = $('#inputDataForm').serializeObject();
the JSON result
It's not in form of
"resource_ratio": [
[
"Barbara",
"Ben",
"Anne",
"John",
"Cindy",
"Nick",
"Lex",
"Edd",
"Eric",
"Jacky",
"Paul"
],
[
0.11974110032362459,
0.037756202804746494,
0.23516720604099245,
0.10895361380798274,
0.10140237324703344,
0.03559870550161812,
0.02912621359223301,
0.08737864077669903,
0.02481121898597627,
0.1186623516720604,
0.10140237324703344
]
]
as I wanted it to be. So I've tried changing the name of the input of array values (Since I've learned that SerializeObject group values by the name of input) and made something like this
for (var i = 0; i < selectedData.resource_ratio.length; i++) {
//selectedData.resource_ratio[1][0]
resourceRatioBoxTag[i] = "<p id='resourceRatio[" + i + "]' name='resourceRatio'>";
for (var j = 0; j < selectedData.resource_ratio[i].length; j++) {
resourceRatioBoxTag[i] += "<input type='text' id='resourceRatio[" + i + "][" + j + "]' value='" + selectedData.resource_ratio[i][j] + "' name='" + i + "'>";
}
resourceRatioBoxTag[i] += "</p>";
$("#resourceRatioDiv").append(resourceRatioBoxTag[i]);
}
(Its the same code except I changed the p tag to input tag]
which gave me serialized values of
"0": [
"Barbara",
"Ben",
"Anne",
"John",
"Cindy",
"Nick",
"Lex",
"Edd",
"Eric",
"Jacky",
"Paul"
],
"1": [
"0.11974110032362459",
"0.037756202804746494",
"0.23516720604099245",
"0.10895361380798274",
"0.10140237324703344",
"0.03559870550161812",
"0.02912621359223301",
"0.08737864077669903",
"0.02481121898597627",
"0.1186623516720604",
"0.10140237324703344"
]
which is ALMOST same as how I want it to be, except it's not INSIDE the resource_ratio values, it's grouped by [0] and [1] (following by the input name).
What should I do to get my resourceRatio[i][j] values inside [i] which is inside the resourceRatio key? I'm sorry if my question is so confusing
the serializeObject is a plug in of jquery I used. It's this:
$.fn.serializeObject = function () {
var o = {};
var a = this.serializeArray();
$.each(a, function () {
if (o[this.name]) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
o[this.name].push(this.value || '');
} else {
o[this.name] = this.value || '';
}
});
return o;
};
The easiest way to convert a value to JSON is to use JSON.stringify:
let dataAsString = JSON.stringify( myObject )
This will break if your object has any circular references. That won't be a problem if your data is a typical piece of business data.
And then to convert it back:
let data = JSON.parse( dataAsString )
Unless you have a very special reason for doing so, I'd recommend that you always use this built-in capability instead of something from a library like jQuery.
const obj = {
"urls": [{
"url": "youtube.com",
"category": ["react js", "javascript"]
},
{
"url": "facebook.com",
"category": ["react js", "javascript"]
}
]
}
const loop = (a) => {
for (let j = 0; j < a.length; j++) {
console.log(a[j].url);
}
return;
}
for (let i in obj) {
console.log(i + " " + loop(obj[i]));
}
The output is:
"youtube.com"
"facebook.com"
"urls undefined"
Why does the loop function get executed first? It should only run inside the second loop:
for(let i in obj){
console.log(i + " " + loop(obj[i]) );
}
I want to be able to output:
urls : youtube.com reactjs,javascript
With short code often the easiest thing to do to debug it is to just do a basic walkthrough of your code by hand to see if it's really doing what you want it to.
You'll notice that the second loop simply performs:
console.log("urls" + " " + loop(obj["urls"]) );
This will result in loop being called:
console.log(obj["urls"][0].url);
console.log(obj["urls"][1].url);
return; // returns undefined
Which will output:
youtube.com
facebook.com
Only then (after the first two logs from inside the loop call) will the initial console.log take place with the return value of loop:
console.log("urls" + " " + undefined /*loop(obj["urls"])*/ );
Giving your last line of output:
urls undefined
As for why loop gets called before the console.log("urls" + ...), think about it, how can console.log know what to output, if to output it it needs to have called loop? loop has to come first.
It sounds like you were trying to do something like this:
const obj = {
"urls": [{
"url": "youtube.com",
"category": ["react js", "javascript"]
},
{
"url": "facebook.com",
"category": ["react js", "javascript"]
}
]
}
// Constructs a string representation of the list of categories
const loop = (a) => {
o = "";
for (let j = 0; j < a.category.length; j++) {
o += "," + a.category[j];
}
return o.substring(1);
}
// Call loop for each url in obj
for (let i in obj.urls) {
console.log("urls : " + obj.urls[i].url + " " + loop(obj.urls[i]));
}
This can be tidied up using join instead of your loop function and by using Array.prototype.forEach:
const obj = {
"urls": [{
"url": "youtube.com",
"category": ["react js", "javascript"]
},
{
"url": "facebook.com",
"category": ["react js", "javascript"]
}
]
}
// Call loop for each url in obj
obj.urls.forEach(urlObj => {
console.log("urls : " + urlObj.url + " " + urlObj.category.join(","));
});
I have a WooCommerce webshop, which sends the created orders to a Google Spreadsheet using a webhook. I managed to make it work, except for one (crucial) step: I cannot seem to properly loop through the meta data of the line items.
To give a bit more context here: its a webshop that sells cakes and pies etc (the line items). One order can have multiple products, and every product can have multiple meta data. For example: Product (line item): Cake , meta data: cake (key) size: (value) small, (key) text on cake: (value) Blue text, (key) text on cake text: "Hello World" (value).
What I need to achieve is the following example of the order in the spreadsheet (simplified):
Name, email address, pick up date, pick up time, pick up location, order
Joe Deer, joe#deer.com, 10/10/2020, 10:00,Bakery,1 x Red Velvet Cake, Small cake, Blue text on cake, "Hello World". 1 x Turtle Cake, Large Cake no text on cake.
Please find an example of the JSON Object below for an overview. The name of the Object is myData, and therefore he line items can be accessed using myData.line_items.
"line_items": [
{
"id": 61458,
"name": "Cupcake Mix 12 stuks",
"product_id": 627,
"variation_id": 0,
"quantity": 1,
"tax_class": "gereduceerd-tarief",
"subtotal": "27.52",
"subtotal_tax": "2.48",
"total": "27.52",
"total_tax": "2.48",
"taxes": [
{
"id": 2,
"total": "2.477064",
"subtotal": "2.477064"
}
],
"meta_data": [
{
"id": 540340,
"key": "Vanilla Buttercream Cupcake",
"value": "yes"
},
{
"id": 540341,
"key": "Vanilla Confetti Cupcake",
"value": "yes"
},
What I (believe that I) need to achieve is to add a loop within the loop that iterates through the meta_data of the line_items object. However, I tried it (using the code below), but couldn't make it work.
//this is a function that fires when the webapp receives a GET request
function doGet(e) {
return HtmlService.createHtmlOutput("request received");
Logger.log('GET received at: ' + timestamp);
}
//this is a function that fires when the webapp receives a POST request
function doPost(e) {
var myData = JSON.parse([e.postData.contents]);
var order_number = myData.number;
var order_created = myData.date_created;
var order_status = myData.status;
var product_name = myData.line_items[0].name;
var product_qty = myData.line_items[0].quantity;
var product_total = myData.line_items[0].total;
var order_total = myData.total;
var billing_email = myData.billing.email;
var billing_first_name = myData.billing.first_name;
var billing_last_name = myData.billing.last_name;
var payment_method = myData.payment_method_title;
var shipping_method = myData.shipping_lines[0].method_title;
var pick_up_location = myData.meta_data[0]["value"];
var pick_up_date = myData.meta_data[1]["value"];
var pick_up_time = myData.meta_data[2]["value"];
var pick_up_time_array = pick_up_time.split(" - ");
var pick_up_time_start = pick_up_time_array[0];
var pick_up_time_end = pick_up_time_array[1];
var shipping_total = myData.shipping_lines[0].total;
var lineitems=""
for (i in myData.line_items)
{
var product_name = myData.line_items[i].name;
var itemName = myData.line_items[i].name;
var quantity = myData.line_items[i].quantity;
for (j in myData.line_items[1][j]) {
var decorationitems = "Item: " + myData.line_items[1][j].key + " Optie: " + myData.line_items[1][j].value + '\n';
var decoration = decoration+decorationitems;
}
var product_items = quantity + " x " + itemName + '\n' + decoration + '\n';
var lineitems = lineitems+product_items;
}
var timestamp = new Date();
var sheetActive = SpreadsheetApp.openById("<ID>");
var sheet = sheetActive.getSheetByName("<NAME>");
sheet.appendRow([timestamp,order_number,order_created,product_name,product_qty,product_total,order_total,billing_email,billing_first_name,billing_last_name,payment_method,shipping_method,pick_up_location,pick_up_date,pick_up_time,pick_up_time_start,pick_up_time_end,shipping_total,lineitems]);
}
Could you guys help me out with the part of the for loop? I sincerely hope that I made my question clear. If you have any further questions, please let me know!
Here is a loop that iterates through the meta_data of the line_items object, based on the code you supplied.
var lineitems="";
var decoration = "";
for (var i in myData.line_items)
{
var product_name = myData.line_items[i].name;
var itemName = myData.line_items[i].name;
var quantity = myData.line_items[i].quantity;
var metaData = myData.line_items[i].meta_data;
for (var j in metaData)
{
for (var key in metaData[j])
{
var decorationitems = "Item: " + key + " Optie: " + metaData[j][key] + '\n';
decoration = decoration + decorationitems;
}
}
var product_items = quantity + " x " + itemName + '\n' + decoration + '\n';
lineitems = lineitems + product_items;
}
I need to sort an object by the value to an object inside it.
is it possible to sort without converting it to an array first ?
I create this object by checking if 3 other arrays have its own property and adding it all to one object.
I have tried sorting function inside and out side of for/in loop.
//how i created the object
var htmlDep = document.getElementById("departmentTable")
var tableElem = document.createElement("table");
var tdList = "";
tableElem.innerHTML = "<tr><th class='avdeling'>Avdeling</th><th class='avdeling'>Aktiv Ansatt</th><th class='avdeling'>Ny Ansatt</th><th class='avdeling'>Sluttet Ansatt</th></tr>"
var obj = {}
var distribution = ["manager", "salesMan", "consultant"]
for (var i = 0; i < distribution.length; i++) {
var work = distribution[i];
obj[work] = {
active: 0,
notActive: 0,
quit: 0
} // using 0 as default
if (active.hasOwnProperty(work)) {
obj[work].active = active[work]
}
if (notActive.hasOwnProperty(work)) {
obj[work].notActive = notActive[work]
}
if (quit.hasOwnProperty(work)) {
obj[work].quit = quit[work]
}
tdList += "<tr><td>" + work + "</td>" + "<td>" + obj[work].active + "</td>" + "<td>" + obj[work].notActive + "</td>" + "<td>" + obj[work].quit + "</td></tr>"
}
tableElem.innerHTML += tdList;
htmlDep.appendChild(tableElem)
//Object example
obj = {
manager: {
active: 450,
notActive: 20,
quit: 0
},
salesMan: {
active: 150,
notActive: 5,
quit: 3
},
ceo: {
active: 50,
notActive: 55,
quit: 0
},
consultant: {
active: 5,
notActive: 72,
quit: 30
}
}
<div id="departmentTable">
</div>
I want to sort the object by the notActive value from high to low inside HTML table
I'm having trouble with a JavaScript array adding an extra undefined object after pushing some strings to the array.
$(function() {
var formTagArr = [];
$( "button", "#start-button" ).click(function() {
$.getJSON('http://127.0.0.1:8000/some_url/', function(data) {
formTagArr.push(buildForm(data));
console.log(formTagArr);
displayForm(formTagArr);
});
return false;
});
function buildForm(data) {
for (var i = 0; i < data.length; i++) {
var html = "";
var questionsTags = "<fieldset><p>" + data[i].question + "</p>";
var answersTags = "";
for (j = 0; j < data[i].answers.length; j++) {
answersTags += "<input type='radio' name='" + data[i].qid +
"' value='" + data[i].answers[j] + "' /" + ">" +
data[i].answers[j] + "\n";
}
html = questionsTags + answersTags + "</fieldset>";
formTagArr.push(html);
}
}
function displayForm(arr) {
if (arr.length === 0) {
return false;
}
var info = arr.pop();
$("#question-form").append(info[0]);
}
});
/some_url/ returns this JSON:
[{"qid": 4, "question": "How many legs does a spider have?", "answers": ["4", "6", "8", "10"]}, {"qid": 2, "question": "When did Nigeria become a republic?", "answers": ["1960", "1961", "1962", "1963"]}, {"qid": 1, "question": "When did Nigeria gain independence?", "answers": ["1960", "1961", "1962", "1963"]}, {"qid": 3, "question": "How many days are in a leap year?", "answers": ["360", "362", "365", "366"]}]
and console.log(formTagArr); in the code above returns:
["<fieldset><p>How many l...e='10' />10\n</fieldset>", "<fieldset><p>When did N...963' />1963\n</fieldset>", "<fieldset><p>When did N...963' />1963\n</fieldset>", "<fieldset><p>How many d...'366' />366\n</fieldset>", undefined]
Because of this, displayForm() fails since info is undefined. Of course I could just use a conditional to skip the undefined object but I want to know exactly how the undefined object got there in the first place.
What did i do wrong?
formTagArr.push(buildForm(data));
Your buildForm function doesn't return anything and the above code try to push the result of that function into the array. A function without a return statement would end up as undefined.
Seems like it should only be
buildForm(data)
As this function already pushed to the formTagArr array.
jsfiddle
You needed to remove the formTagArr.push call and also in the displayForm call change the line to this: $("#question-form").html(info);