I'm a beginner with JavaScript and query. I have an html form where the user can add or remove a group of fields. The group of fields contains 1 select and 3 inputs. The group of fields added have the same name of the previouses and so on.
What I'm trying to do is retrieve the value creating a structure like this.
{
"colture1": [{
"code_app": "A2",
"long": "1",
"lat": "103"
}, {
"code_app": "B34",
"long": "11",
"lat": "12"
}],
"colture2": [{
"code_app": "GH3456",
"long": "55",
"lat": "90"
}]
// ....and so on
}
If the user selects a colture that already exist in the object, I'd like to add the others value in the same key as you can see in "colture1". My problem is here, I can't create an array where I can add the others value, now my function override the preovious values, It writes the last one values and it doesn't create an array.
This is my function
$('#create_json').on("click", function(e) {
const json_data = {};
var cat = "";
for (const input of document.querySelectorAll(".card[mainBlock] select, .card[mainBlock] input")) {
if (input.tagName === 'SELECT') {
cat = input.value;
} else {
(json_data[cat] = json_data[cat] || {})[input.name] = input.value;
}
}
console.log(JSON.stringify(json_data));
})
Here I can put a demo here https://jsfiddle.net/ou7h4f2m/3/. Thank you in advance
It is probably easier if you would deal with one section in each outer loop iteration (just on .card[mainBlock]), and then use an inner loop for processing the category and properties:
$('#create_json').on("click", function (e) {
const data = {};
for (const section of document.querySelectorAll(".card[mainBlock]")) {
const cat = section.querySelector("select").value;
const obj = Object.assign(...Array.from(section.querySelectorAll("input"), input =>
({ [input.name]: input.value })
));
(data[cat] = data[cat] || []).push(obj);
}
console.log(JSON.stringify(data));
});
I would not call your main variable json_data. It does not represent JSON, but a JavaScript object. JSON is what you get from calling JSON.stringify.
Related
I trying to push data to a 3rd party webservice, specifically converting the xml request to a json one (for use with node soap).
Here is an example of the raw xml request that works fine:
<EformData>
<EformFields>
<FieldName>txt_customername</FieldName>
<FieldValue>Scott</FieldValue>
</EformFields>
<EformFields>
<FieldName>txt_organisation</FieldName>
<FieldValue>My Orginisation</FieldValue>
</EformFields>
<EformFields>
<FieldName>txt_address</FieldName>
<FieldValue>My Address</FieldValue>
</EformFields>
<EformFields>
<FieldName>txt_telnumber</FieldName>
<FieldValue>123456</FieldValue>
</EformFields>
</EformData>
The problem i'm having is trying to convert these duplicate nodes into an object, the new object data is being overwritten with the last request.
Here's what i have so far:
var formValues = {
"txt_customername": "Scott",
"txt_organisation": "My Orginisation",
"txt_address": "My Address",
"txt_telnumber": "123456"
}
// Container
var EformData = {
"EformFields": {
}
};
// populate the object
for (var key in formValues) {
EformData.EformFields.FieldName = [key];
EformData.EformFields.FieldValue = formValues[key];
}
As you can see below, only the last request is stored in the object, the others are overwritten:
<EformData>
<EformFields>
<FieldName>txt_telnumber</FieldName>
<FieldValue>123456</FieldValue>
</EformFields>
</EformData>
Is it possible to build an object in such a way to match the orginal duplicate xml node data?
The data structure of your json should be that EformData has an array of EformFields objects, which has the properties of FieldName and FieldValue.
var formValues = {
"txt_customername": "Scott",
"txt_organisation": "My Orginisation",
"txt_address": "My Address",
"txt_telnumber": "123456"
}
// Container
var EformData = {
"EformFields": []
};
// populate the object
for (var key in formValues) {
EformData.EformFields.push({
"FieldName": key,
"FieldValue": formValues[key]
});
}
In your array, only 0th index is populated always and hence it is overrided when on the next iteration add an index for the array iteration as follows
// Container
var EformData = {
"EformFields": [
]
};
// populate the object
int i=0;
for (key in formValues) {
EformData.EformFields[i].FieldName = [key];
EformData.EformFields[i].FieldValue = formValues[key];
i++;
}
My code reads data somewhere and then adds them as values to properties in an object. I made a for loop to iterate over the items in the list so they can each belong in their own cute little object but here is a problem: sometimes there's no value to a property and I wan't to know what I can do to intercept that before it finishes being declared to the property. Maybe replace the empty string with a word or something.
Here is an example code and lets say the title on iteration #3 is going to be an empty "" string. how do I intercept that?
var counter = 0;
for (var i = 0; i < nyData.results.length; i++) {
if (_.indexOf(uniqueItems, nyData.results[i].id)) {
continue;
}
if (!_.indexOf(uniqueItems, nyData.results[i].id)) {
var index = i;
counter++;
let putParams = {
TableName: "Articles",
Item: {
"title": nyData.results[i].title,
"date": nyData.results[i].published_date,
"abstract": nyData.results[i].abstract,
"source": nyData.results[i].source,
"views": nyData.results[i].views,
"author": nyData.results[i].byline,
"section": nyData.results[i].section,
"category": nyData.results[i].des_facet,
"organizations": nyData.results[i].org_facet,
"people_involved": nyData.results[i].per_facet,
"country_subject": nyData.results[i].geo_facet,
"id": nyData.results[i].id,
}
}
db.put(putParams, function(err) {});
}
}
console.log(`Total of ${counter} new articles were inserted into database.`);
callback(null);
if( myVar) {
}
will only be true, if the variable is not:-
Empty
Null
undefined
0
false
....and a few more.
I have a JSON object which looks like this:
var JSON = {
"implants":[{
"familyId": "3",
"reference": "1234",
"quantity": "3"
},{
"familyId": "2",
"reference": "3456",
"quantity": "1"
}]
}
I'm building a function which searches whether an implant with the given "reference" is already in the array. If it's not, it just gets added to the array. Easy. If it is in the array, then I want to add the new quantity to the existing quantity and then update the array.
function returnTheseImplantsWhere(key1,key2){
return function(el){
if(el[key1]==key2) {
return el;
}
}
}
var activeCaseImplants = JSON.parse(getLocal("activeCaseImplants"));
var existingImplant = activeCaseImplants.implants.filter(returnTheseImplantsWhere("reference", window.currentImplantRef));
if(existingImplant.length) {
//previously added implant
newImplantQty = Number(existingImplant[0].quantity) + Number($("#qty").val());
existingImplant.quantity = newImplantQty;
} else {
//new implant
}
My question relates to the "previously added implant" section of the above code (which all works as expected). I now have the updated quantity, but I can I determine which object within the activeCaseImplants.implants array needs it's quantity updated? I feel like I could make use of indexOf somewhere around the line beginning with var existingImplant = ... but I'm not sure where or how. Any ideas?
So, I have access to a JSON-file and I'm supposed to list a few items in a neat fashion. The JSON-file is however written in a way I'm not familiar with. I have the following code:
function readFile(file) {
var rawFile = new XMLHttpRequest();
rawFile.open("GET", file, false);
rawFile.onreadystatechange = function ()
{
if (rawFile.readyState === 4 && rawFile.status === 200)
{
window.openedFile = JSON.parse(rawFile.responseText);
console.log(JSON.stringify(openedFile, undefined, 4));
createList();
}
};
rawFile.send();
}
function createList() {
var table = document.createElement('table');
var body = document.createElement('tbody');
for (var i = 0; i < openedFile.sites.length; i++) {
var item = document.createElement('tr');
var colSite = document.createElement('td');
colSite.appendChild(document.createTextNode(openedFile.sites[i].name));
item.appendChild(colSite);
body.appendChild(item);
}
table.appendChild(body);
document.getElementById('list').appendChild(table);
}
..and it does not work as it claims the array "sites" is empty. The result from the JSON-file in the output in the console gives (with slight modifications in the variable names):
{
"sites": {
"1007": {
"id": 1007,
"name": "Location B",
"devices": {
"p3": {
"name": "p3",
"version": "5"
}
}
},
"1337": {
"id": 1337,
"name": "Location A",
"devices": {
"p2": {
"name": "p2",
"version": "5"
},
"p1": {
"name": "p1",
"version": "5"
}
}
}
},
}
If I change the JSON-file and add [] brackets after sites and remove "1007" and "1337" it looks like I'm used to (as an ordinary array), and it works. I'm pretty sure I'm not allowed to do this however and I get the same problem again when trying to extract information about the devices. I would appreciate any help on this matter. And to clarify, I'm trying to avoid changing the JSON-file, if there is some other solution.
The numerals 1007 and 1337 are properties of the object sites. Use a for-in loop to iterate through the object properties.
var sites = openedFile.sites;
for(var site in sites){
console.log("Key: ", site);
console.log("Value: ", sites[site]);
}
Sites is an object, not an array, so you need to iterate over the object's properties, not the elements of the array.
In order to get a list of those properties, you can use Object.keys(). That gives you an array of the property names.
Once you have that array, you iterate over it and each time use the current element, which is the name of the property of the original object.
For example, this works (just console logging the object name, the extraction you've already got):
function createList2() {
var len = Object.keys(openedFile.sites); //get array of property keys
for (var i of len) { //iterate over the array of property keys
console.log(openedFile.sites[i].name); /*retrieve properties by key from original object */
}
}
How would you get the value of assocIMG by key matching the key eg
if I have a var 11786 I want it to return media/catalog/product/8795139_633.jpg
var spConfig = {
"attributes": {
"125": {
"id": "125",
"code": "pos_colours",
"label": "Colour",
"options": [{
"id": "236",
"label": "Dazzling Blue",
"price": "0",
"oldPrice": "0",
"products": ["11148"]
}, {
"id": "305",
"label": "Vintage Brown",
"price": "0",
"oldPrice": "0",
"products": ["11786", "11787", "11788", "11789", "11790", "11791", "11792", "11793"]
}]
}
}
};
var assocIMG = // Added - Removed { here, causes issues with other scripts when not working with a configurable product.
{
11786: 'media/catalog/product/8795139_633.jpg',
11787: 'media/catalog/product/8795139_633.jpg',
}
Above is the objects I am working with and below is my current jQuery. Help would be greatly appreciated.
$('#attribute125').change(function() {
var image = $(this).val();
$.each(spConfig.attributes, function() {
prods = $(this.options).filter( function() { return this.id == image; } )[0].products[0];
alert(prods);
});
});
You can use bracket notation to get object members by their keys. You have the variable prods containing a string ("11786"), and the object assocIMG with various keys. Then just use
assocIMG[prods]
to get the property value 'media/catalog/product/8795139_633.jpg' which is associated with that key.
Note that you should always use strings as keys in your object literal, IE does not support numbers there:
var assocIMG = {
"11786": 'media/catalog/product/8795139_633.jpg',
"11787": 'media/catalog/product/8795139_633.jpg'
};
Another improvement to your script would be not to loop through the spConfig.attributes each time, and potentially execute your action multiple times if an image is contained in more than one attribute. Instead, build a hash object out of it, where you can just look up the respective product id.
var productById = {};
$.each(spConfig.attributes, function() {
$.each(this.options, function() {
var id = this.id;
productsById[i] = this.products[0];
});
});
$('#attribute').change(function() {
var id = this.value;
var prod = productById[id];
var image = assocIMG[prod];
$("#product_img").attr("src", image);
});
You should not use numbers as object keys (in their start). If you want to get the value associated with the 11786 integer key, you will need to use this syntax:
assocIMG["11786"] or assocIMG[11786]
Not
assocIMG.11786
The first thing that you need to do is to create your keys as strings, since you would have:
var assocIMG = {
"11786": 'media/catalog/product/8795139_633.jpg',
"11787": 'media/catalog/product/8795139_633.jpg',
}
But even doing this, you won't be able to access the field using assocIMG.11786 and the first valid sintax that I presented will still work. The correct approach would be:
var assocIMG = {
id11786: 'media/catalog/product/8795139_633.jpg',
id11787: 'media/catalog/product/8795139_633.jpg',
}
Or
var assocIMG = {
"id11786": 'media/catalog/product/8795139_633.jpg',
"id11787": 'media/catalog/product/8795139_633.jpg',
}
Note that the keys are now starting with letters, not numbers. And now, you will can access the 11786 field as assocIMG.id11786 or assocIMG["id11786"], not assocIMG[id11786]
To Get the Value from object by matching key I ended up with the following
$.each(assocIMG, function(index, value) {
if(index == prods) {
var image_path = value;
$("#product_img").attr("src", image_path);
//alert(image_path);
}