javascript/jquery: on click copy relevant array items to new array - javascript

I think I'm missing an obvious answer. I have an array of arrays, like this
var arraylist = [
{
"id" = 0,
"title" = "title number 1",
"info" = "some info etc 1"
},
{
"id" = 1,
"title" = "title number 2",
"info" = "some info etc 2"
},
]
...etc. And a function that makes some html from each array, which is appended to a ul element.
function makeBox(){
for (i = 0; i < arraylist.length; i++ ) {
var boxHTML = '<li id="' + arraylist[i].id + '">'
+ '<div>' + arraylist[i].title + '</div>'
+ '</li>'
$('ul').append(boxHTML);
};
};
Now using a click function, on clicking the 'li' I want the relevant array from arraylist to be copied to a new array.
newArrayList = []
So clicking on li #0 would copy the first array from 'arraylist' to the 'newArrayList'.
I will then be making different HTML from 'newArrayList' using different values. So in the makeBox function I won't show the value "info", but when I make HTML from newArrayList I will.
I could use innerHTML to get the data back out of the HTML to the newArrayList, but would have to append "info" to a hidden span, or something. This seems like the long way round. So what's the easy way?
I'm just learning so go easy on me. Also did a good search and couldn't find the answer. If it's already there please direct me politely.

So a few notes:
It's not an array of arrays. It's an array of objects. The [ ] block
is an array. The { } is an object.
The $('ul') will select ALL uls on the page, not necessarily just the
one you intend.
The object structure is incorrect, it should be using colon (:) rather
than equal (=) characters. It should look more like this:
var arraylist = [{
"id": 0,
"title": "title number 1",
"info": "some info etc 1"
}, {
"id": 1,
"title": "title number 2",
"info": "some info etc 2"
}]
Here is a modified version of your function.
function makeBox(){
var $ul = $('ul.from_array_one');
for (var i = 0; i < arraylist.length; i++) {
var item = arraylist[i];
var $boxHTML = $('<li id="' + item.id + '">' + item.title + '</li>');
$boxHTML.click(onSelectItem(item));
$ul.append($boxHTML);
};
};
Where a new function exists accepting the array object item, such as:
function onSelectItem( item ){
return function(){
var $ul2 = $('ul.from_array_two');
var $boxHTML2 = $('<li id="' + item.id + '">' + item.info + '</li>');
$ul2.append($boxHTML2);
}
}

Shaun's solution should work when implemented correctly (one point for your effort).
Here is another way.
I modified your (OP's) function so can be reused for other array of same types. Since you're learning, I encourage you to read up on DRY principle a.k.a. "don't repeat yourself". Adhering to this principle while designing your code, will help you write code that is more reusable resulting in shorter code, in the longer run a more maintainable code base. And in the process you will become an even better coder.
var arraylist = [
{
"id": 0,
"title": "title number 1",
"info": "some info etc 1"
},
{
"id" : 1,
"title": "title number 2",
"info": "some info etc 2"
},
];
var newArrayList = [];
///
function makeBox(arrayToMake, ulToAppendTo, liClass){
for (i = 0; i < arrayToMake.length; i++ ) {
var boxHTML = '<li class="'+liClass+'" id="' + arrayToMake[i].id + '">'
+ '<div>' + arrayToMake[i].title + '</div>'
+ '</li>'
$(ulToAppendTo).append(boxHTML);
};
};
var firstListClass = "first_list_item";
var secondListClass = "second_list_item";
makeBox(arraylist,'.ul_one',firstListClass);
$("."+firstListClass).click(function(){
copyArray(arraylist,newArrayList);
makeBox(newArrayList,'.ul_two',secondListClass);
});
function copyArray(sourceArray, targetArray)
{
sourceArray.forEach(function(item){
//for demo purpose only
item.title="new title " + item.id;
targetArray.push(item);
});}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>first array result</p>
<ul class='ul_one'></ul>
<p>new array result</p>
<ul class='ul_two'></ul>

Related

How to traverse through an array of JSON in javascript? and use it to populate <option> element

I have this array of JSON and I want to loop through them and use it to fill up my option element.
Sample Array:
var myOptionData = [
{fooValue:"1", fooText:"option A"},
{fooValue:"2", fooText:"option B"},
{fooValue:"3", fooText:"option C"}
]
I did use this method:
var fields="";
fields += "</select >";
fields += "<option value='0'></option>";
$.each(myOptionData , function (key, value) {
fields += "<option value=" + value.fooValue + ">" + value.fooText + "</option>";
});
fields += "</select >";
//But I want to make it more flexible, so that I can reuse it in making another <option> from another array of JSON, like this scenario:
var myNewOptionData = [
{myValue:"5", myText:"option E"},
{myValue:"6", myText:"option F"},
{myValue:"7", myText:"option G"},
{myValue:"8", myText:"option H"}
]
//Now I cannot use the method above
Simply turn the whole operation into a function:
function mkSelect(data){
return "<select><option value='0'></option>"
+ data.map(o=>{
let [val,txt]=Object.values(o);
return "<option value=" + val + ">" + txt + "</option>"}).join("")
+ "</select >";
}
const myOptionData = [
{fooValue:"1", fooText:"option A"},
{fooValue:"2", fooText:"option B"},
{fooValue:"3", fooText:"option C"}
],
myNewOptionData = [
{myValue:"5", myText:"option E"},
{myValue:"6", myText:"option F"},
{myValue:"7", myText:"option G"},
{myValue:"8", myText:"option H"}
];
document.querySelector("#frm").innerHTML=mkSelect(myOptionData)+"<br>"
+mkSelect(myNewOptionData);
<form id="frm"></form>
The function should be improved, as it momentarily relies on the sequence of the properties of object o. Maybe the property names could be checked for containing "Value" and "Text"?
Here is a slight variation of my snippet, checking for parts of the property names. Now the order of the given option properties is immaterial and a selected option can also be defined by providing a property that contains "select" in its name:
function mkSelect(data){
const arr=data.map(o=>Object.fromEntries(Object.entries(o).map(([k,v])=>
[k.replace(/.*value.*/i,"val") // generate an object with standardised key names:
.replace(/.*text.*/i,"txt") // ===> val, txt and sel
.replace(/.*select.*/i,"sel"),
v])));
return "<select><option value='0'></option>" // build the actual select element:
+arr.map(o=>`<option value="${o.val}"${o.sel?` selected="${o.sel}"`:""}>${o.txt}</option>`).join("")+"</select>"
}
const myOptionData = [
{fooValue:"1", fooText:"option A"},
{fooValue:"2", fooText:"option B", thisIsSelected: true},
{fooValue:"3", fooText:"option C"},
{thisTextIsGreatToo:"option D", andValueThis:"4"}
],
myNewOptionData = [
{myValue:"5", myText:"option E"},
{myValue:"6", myText:"option F"},
{myValue:"7", myText:"option G"},
{selectThis: 1, myLastText:"option H", myLastValue:"8"}
];
document.querySelector("#frm").innerHTML=mkSelect(myOptionData)+"<br>"+mkSelect(myNewOptionData)
<form id="frm"></form>
Generally when making a function you should expect to receive parameters with defined keys. There's nothing wrong with requiring objects within lists to have fooValue & fooText. However if you want to make it property-independent:
function createSelect(options, valueName, textName) {
const select = `<select><option value='0'></option>
${options.map(option => `<option value="${option[valueName]}">${option[textName]}</option>`)}
</select>`;
return select;
}
console.log(
createSelect([{randomValue: 1, randomName: 'Go select!'}], 'randomValue', 'randomName')
);
Note how jQuery isn't necessary in this case.
Map is a function that transforms every item on your list (without modifying it)
Also if you want to 'just specify the keys once and then reuse' you can create partially applied functions:
const createSelect = (valueName, textName) => (options)=> {
return `<select><option value='0'></option>
${options.map(option => `<option value="${option[valueName]}">${option[textName]}</option>`)}
</select>`;
}
const fooList = [{fooValue: 1, fooName: 'Foo select!'}];
const fooSelect = createSelect('fooValue', 'fooName');
console.log(
fooSelect(fooList)
);
const barList = [{barValue: 2, barName: 'Bar select!'}];
const barSelect = createSelect('barValue', 'barName');
console.log(
barSelect(barList)
);

Setting HTML text using a loop

I'm currently running a REST query against a SharePoint list and I'm trying to display the results with a $().text() script. I have it working but would think there's a more efficient way. I have many fields I need to set but they're sequentially numerical and just think there should be a better way. Example below:
$('#div1Id').text(data.d.results[0].slot1);
$('#div2Id').text(data.d.results[0].slot2);
$('#div3Id').text(data.d.results[0].slot3);
Etc x20 fields...
I tried below, but I'm sure for reasons that are obvious to you all that know what you're doing this didn't work. The "divId" loads fine but the dataId shows the text "data.d.results[0].slot1"/2/3/etc instead of the actual data.d.results:
for (i=1;i<21;i++){
var divId = "#div"+i+"Id";
var dataId = "data.d.results[0].slot"+i;
$('+divId+').text(dataId);
}
Based on what your first example was doing, I think you want this:
for (i = 1; i < 21; i++) {
var divId = "#div" + i + "Id";
// access the value from the "slot#" property of the object
var data = data.d.results[0]['slot' + i];
// get the correct div based on the id and then
// set its text to the value
$(divId).text(data);
}
You could try the forEach method, or as already mentioned, get rid of the quotes in "data.d.results[0].slot"
var data = [{
"id": 1,
"Name": "Some Title 1",
"number": "Number 1"
}, {
"id": 2,
"Name": "Some Title 2",
"number": "Number 2"
}, {
"id": 3,
"Name": "Some Title 3",
"number": "Number 3"
}];
//data.d.results[0] << you'd use this
data.forEach(elem => {
document.getElementById("entries").innerHTML += elem.Name +"<br/>";
});
<div id="entries"></div>

create json array and append objects in it from form

At this moment I'm trying to create a json like this.
[
{"name": "set registry key right",
"win_acl": {
"path": "HKCU:\\Bovine\\Key",
"user": "BUILTIN\\Users",
"rights": "EnumerateSubKeys",
"type": "allow",
"state": "present",
"inherit": "ContainerInherit, ObjectInherit",
"propagation": "None"
}
},
{
"name": "Remove FullControl AccessRule for IIS_IUSRS",
"win_acl": {
"path": "C:\\inetpub\\wwwroot\\MySite",
"user": "IIS_IUSRS",
"rights": "FullControl",
"type": "allow",
"state": "absent",
"inherit": "ContainerInherit, ObjectInherit",
"propagation": "None"
}
}
]
I want to create it dynamically trough javascript.
This is what I have now:
function GenerateYaml(btn) {
$('#generatedYamlTextField').removeAttr("hidden");
var id = btn.replace("generateBtn", "");
var moduleName = $("#formpanel" + id).attr("data-title-caption");
//Looping trough panels
$("#formpanel" + id).each(function () {
var json = "[\n{\n\"name\":\"" + "module beschrijving" + "\",\n";
json += "\"" + moduleName + "\": {\n";
//Looping through labels in the panel to create the object
$('label').each(function (index, value) {
var is_last_item = (index == ($('label').length - 1));
if (!is_last_item) {
json += "\"" + value.innerText + "\":"+"\"textboxvalue\",\n";
} else {
json += "\"" + value.innerText + "\":"+"\"textboxvalue\"\n";
}
});
json += "}\n},]\n";
$("#yamltextfield").append(json);
});
}
This is what I get from above code in my textarea:
[
{
"name":"module beschrijving",
"win_acl_inheritance_module": {
"path":"textboxvalue",
"reorganize":"textboxvalue",
"state":"textboxvalue"
}
},]
My problem is that I have multiple panels and I want to add them in the same array so that I get it like the json I showed in the first place.
I hope you guys could help me out. Thanks in advance.
Greetings,
Mouaad
Don't form the json string manually. Just compose your objects, put them in an array, say arr and you can get the json string by:
JSON.stringify(arr);

How do I load every section of a JSON file that has objects of objects?

My JSON file looks like the following:
[{ "articles": [
{ "1": { "sections":
[ {"1": "Lots of stuff here."} ]
}
},
{ "2": { "sections":
[ {"1": "And some more text right here"} ]
}
}
}]
The basic premise is that it has one element in the overall array called "articles", which is equal to an array of "sections".
In other words, it's a constitution, so it looks like this:
Article X
-Section A
-Section B
-Section C
Article Z
...
I want to be able to pull out each article and load it into
<div class="alert text-black" id="article">
<p class="lead" id="articleHeader"><strong>Article 1</strong></p>
<dl>
<dt id="article_section">Section 1</dt>
<dd id="article_sectionINFO">this stuff belongs to section 1</dd>
</dl>
</div>
and this is the script I have so far:
var loadEvents = function(d){
$.each(d, function(i){
var articleN = i;
var articleID = "article" + i;
var articleHeaderID = "articleHeader" + i;
var articleHeader = "<p class='lead' id='articleHeader'><strong>Article " + i + "</strong></p>";
var mySections = new Array();
$.each(d, function(i){
var sectionN = i;
var sectionID = "article" + articleN + "section" + sectionN;
var sectionINFO = sectionID + "INFO";
mySections[k] =
"<dt id='" + sectionID +"'> Section " + sectionN + "</dt>" +
"<dd id='" + sectionINFO +"'>" + d[sectionN].
})
$("#eventHolder").append(new_block(articleID, articleHeaderID, articleHeader)); //to call the new element
})}
$.getJSON('data/constitution.json', loadConstitution);
Basically, I just want to be able to reproduce a larger box (as shown in the <html> code above) for each article, with a list (<dl></dl>) for each section. How do I access the data from the JSON file correctly?
As you have an array that contains an object that contains the article property that is an array that contains articles, you need to get down to that property to loop through them. Use two properties in the callback function so that you can access the article object:
$.each(d[0].articles, function(i, article) {
As each item is an object that contains a sections property that is an array that contains the sections, you need to get down to that property in each item. Use a different index variable for the sections, so that you still can access the i variable used for the article index:
var mySections = article.sections;
$.each(mySections, function(j, section) {
Inside that loop, j is the index of the section, section is the section string, and i is still then index of the article.
That should get you on the right track with the looping, the rest is mostly just using the right variable for each value.

How to find the right Json object

I am new to Json and trying to load a part of a Json object. The structure is:
{
"Monday": {
"title": "Magic Monday",
"text": "On Magic Monday, all the food disappears.",
"image": "images/special.jpg",
"color": "red"
},
"Tuesday": {
"title": "Twofer Tuesday",
"text": "Two vegetables for the price of one!.",
"image": "images/special.jpg",
"color": "green"
}
}
I have a variable, weekDay, which I am going to use to find the right object. When this is found, I want to use the value of title and text in my HTML.
So far I have the code:
$.getJSON('data/specials.json', function (data) {
$.each(data, function (entryIndex, entry) {
var html = '<h4>' + entry['title'] + '</h4>';
html += '<p>' + entry['text'] + '</p>';
$('#details').append(html);
});
});
But I do not know, how to only get the title and the text from the object with the right weekday.
Thanks in advance :)
If you have
var weekDay = "Tuesday";
then you can simply use
var entry = data[weekDay];
and then
var title = entry.title;
or
var title = entry['title'];
This document explains how you access object properties.

Categories

Resources