I'm having difficulty generating a json object in the below format from the data below. Fiddle
[ { Invoice:
{
headers: { date: "15-01-2020", buyer: "McDonalds", order: "145632"},
items: { name: "Big Mac", quantity: "5", rate: "20.00"},
items: { name: "Small Mac", quantity: "10", rate: "10.00"}
}
}
, { Invoice: { // Other invoices go here, I've used just one for this example} }
]
<div class="invoice">
<div class="header">
<div contenteditable data="date">15-Jan-2020</div>
<div contenteditable data="buyer">McDonalds</div>
<div contenteditable data="order">145632</div>
</div>
<div class="item">
<div contenteditable data="name">Big Mac</div>
<div contenteditable data="quantity">5</div>
<div contenteditable data="rate">20.00</div>
</div>
<div class="item">
<div contenteditable data="name">Small Mac</div>
<div contenteditable data="quantity">10</div>
<div contenteditable data="rate">10.00</div>
</div>
</div>
<button>Loop</button>
jQuery
var button = $("button")
button.on("click",function() {
jsonObj =[];
$('.invoice>.header>div, .invoice>.item>div').each(function(index,item) {
console.log($(this).parent().attr('class'));
console.log($(this).attr('data'),$(this).text());
q = {}
q ['header'] = $(this).parent().attr('class');
q [$(this).attr('data')] = $(this).text();
jsonObj.push(q);
});
console.log(jsonObj);
console.log(JSON.stringify(jsonObj));
});
I current end up with an object like this where the keys are repeated everywhere. How can I get this right?
[ { "header": "header", "date": "15-Jan-2020"}
, { "header": "header", "buyer": "McDonalds"}
, { "header": "header", "order": "145632"}
, { "header": "item", "name": "Big Mac"}
, { "header": "item", "quantity": "5"}
, { "header": "item", "rate": "20.00"}
, { "header": "item", "name": "Small Mac"}
, { "header": "item", "quantity": "10"}
, { "header": "item", "rate": "10.00"}
]
In your example, you have an object with two same keys:
"items":{
"name":"Big Mac",
"quantity":"5",
"rate":"20.00"
}
"items":{
"name":"Small Mac",
"quantity":"10",
"rate":"10.00"
}
This won't work, because you can only have one, so you need to change the value of items
key to an array of objects:
"items":[
{
"name":"Big Mac",
"quantity":"5",
"rate":"20.00"
},
{
"name":"Small Mac",
"quantity":"10",
"rate":"10.00"
}
]
The iteration code may look like this:
const jsonObj = [];
$('.invoice').each((index, item) => {
const invoice = {
header: {},
items: []
};
$(item).find('.header > div').each((index, item) => {
const key = $(item).attr('data');
invoice.header[key] = $(item).text();
});
$(item).find('.item').each((index, item) => {
const itemObj = {};
$(item).find('div').each((index, item) => {
const key = $(item).attr('data');
itemObj[key] = $(item).text();
});
invoice.items.push(itemObj);
});
jsonObj.push({
Invoice: invoice
});
});
The main difference from your version is that it iterates through the dom step by step. First, through each invoice, then through each header of the invoice and each item. This way it's easy to build the desired structure.
Here's the jsfiddle link: https://jsfiddle.net/tara5/tanb174h/
Pure JS code for this:
Remarks : I have changed:
<div ... data="..."> ... </div>
to
<div ... data-ref="..."> ... </div>
to be conform with HTML directives (see https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/data-* )
const jsonObj = []
, inVoices = document.querySelector('.invoice')
, subDivOf = (parent,query) => [...parent.querySelectorAll(query)]
, dataElms = (ac,el)=>{ac[el.dataset.ref]=el.textContent;return ac }
;
Loop.onclick=_=>
{
jsonObj.push( { Invoice: getInVoicesValues() } )
console.clear()
console.log( jsonObj )
}
function getInVoicesValues()
{
const headers = subDivOf(inVoices,'.header>div').reduce(dataElms,{})
, items = subDivOf(inVoices,'.item').reduce((accI,itm)=>
{
accI.push( subDivOf(itm, 'div').reduce(dataElms,{}))
return accI
},[])
;
return { headers, items }
}
.as-console-wrapper {
max-height: 100% !important;
width: 50% !important;
top: 0;
left: 50% !important;
}
<div class="invoice">
<div class="header">
<div contenteditable data-ref="date">15-Jan-2020</div>
<div contenteditable data-ref="buyer">McDonalds</div>
<div contenteditable data-ref="order">145632</div>
</div>
<div class="item">
<div contenteditable data-ref="name">Big Mac</div>
<div contenteditable data-ref="quantity">5</div>
<div contenteditable data-ref="rate">20.00</div>
</div>
<div class="item">
<div contenteditable data-ref="name">Small Mac</div>
<div contenteditable data-ref="quantity">10</div>
<div contenteditable data-ref="rate">10.00</div>
</div>
</div>
<button id="Loop">Loop</button>
.........................run snippets full screen for better view
second method
const jsonObj = [];
const inVoicesElms = document.querySelectorAll('.invoice div');
Loop.onclick=_=>
{
jsonObj.push( { Invoice: getInVoicesValues() } )
console.clear()
console.log( jsonObj )
}
function getInVoicesValues()
{
let rep = { headers:{}, items:[] }
, cur = null
;
inVoicesElms.forEach(el =>
{
if (el.matches('.header'))
{
cur = rep.headers
}
else if (el.matches('.item'))
{
cur = {}
rep.items.push(cur)
}
else // (el.matches('[contenteditable]'))
{
cur[el.getAttribute('data')] = el.textContent
}
})
return rep
}
.as-console-wrapper { max-height: 100% !important; width: 50% !important;
top: 0; left: 50% !important;
}
<div class="invoice">
<div class="header">
<div contenteditable data="date">15-Jan-2020</div>
<div contenteditable data="buyer">McDonalds</div>
<div contenteditable data="order">145632</div>
</div>
<div class="item">
<div contenteditable data="name">Big Mac</div>
<div contenteditable data="quantity">5</div>
<div contenteditable data="rate">20.00</div>
</div>
<div class="item">
<div contenteditable data="name">Small Mac</div>
<div contenteditable data="quantity">10</div>
<div contenteditable data="rate">10.00</div>
</div>
</div>
<button id="Loop">Loop</button>
Firebase Cloud Functions: PubSub, "res.on is not a function"
TypeError: Cannot read properties of undefined (reading 'createMessageComponentCollector')
I have a div which contains a table for tabs in my site navigationI have the div set to overflow when in mobile like this:
I have 12 images for example and on image click I want to hide the 11 other images and increase the clicked upon image to full screen
I have a page that can have the same article twice or more in it i have an ajax search in this page ,when i do the search with the name of article it shows twice if there is two of it in this page , so i want to remove the duplicate and to display every article...