Loop through array and add to string based on count - javascript

I'm trying to loop through an array of items and build up a HTML structure based on what count we are at through the array.
It should wrap every item in a cell and every 4 items in a row and every 8 items in a column div.
Here is the JavaScript:
var html = ''; // for those that were asking where html was...
for(var i=0;i<response.length;i++)
{
// for first and every 8 items
if(i == 0 || i % 8 === 0)
{
console.log('columnstart');
html = html + '<div class="column">';
}
// for first and every 4 items
if(i == 0 || i % 5 === 0)
{
console.log('rowstart');
html = html + '<div class="row">';
}
// after every 4 items BUT NOT the first
if(i % 4 === 0 && i !== 0)
{
console.log('rowend');
html = html + '</div>';
}
// after every 8 items BUT NOT the first
if(i == response.length && i !== 0 || i % 7 === 0 && i !== 0)
{
console.log('columnend');
html = html + '</div>';
}
console.log('cell');
html = html + '<div class="cell"></div>';
}
and here is an example of how the HTML should be being rendered:
<div class="column">
<div class="row">
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
</div>
<div class="row">
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
</div>
</div>
<div class="column">
<div class="row">
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
</div>
<div class="row">
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
</div>
</div>
However it seems my counts are off...
Because I get the following in the console:
columnstart
rowstart
cell
cell
cell
cell
cell
rowend
rowstart
cell
cell
cell
columnend
columnstart
cell
rowend
cell
rowstart
cell
cell

Well, it seems there was a lot wrong with your logic, so I just rewrote the whole thing. Basically, treat the first and last element as special cases, that way the counting logic doesn't need to be as complicated.
See comments for more information:
var html = '';
for (var i = 0; i < response.length; i++) {
// If first element, open column and row and add first cell.
if (i == 0) {
html = html + '<div class="column">';
html = html + '<div class="row">';
html = html + '<div class="cell"></div>';
// If the first element, is also the last, then close row and column now.
if (i == response.length - 1) {
html = html + '</div>';
html = html + '</div>';
}
}
// If last element, add last cell and close row and column.
else if (i == response.length - 1) {
html = html + '<div class="cell"></div>';
html = html + '</div>';
html = html + '</div>';
}
// Otherwise, process based on count.
else {
// If end of row, then close row.
if (i % 4 == 0) {
html = html + '</div>';
}
// If end of column close column, open new column.
if (i % 8 == 0) {
html = html + '</div>';
html = html + '<div class="column">';
}
// If end of row, open new row.
if (i % 4 == 0) {
html = html + '<div class="row">';
}
// Insert the cell.
html = html + '<div class="cell"></div>';
}
}
Here is a working example

A couple of tyypos:
// for first and every 4 items
if(i == 0 || i % 5 === 0)
{
console.log('rowstart');
html = html + '<div class="row">';
}
should be:
// for first and every 4 items
if(i == 0 || i % 4 === 0)
{
console.log('rowstart');
html = html + '<div class="row">';
}
a typpo or two and an issue with logic and precedence:
// after every 8 items BUT NOT the first
if(i == response.length && i !== 0 || i % 8 === 0 && i !== 0)
{
console.log('columnend');
html = html + '</div>';
}
should be:
// after every 8 items BUT NOT the first
if(i === response.length - 1 || (i !== 0 && i % 8 === 0))
{
console.log('columnend');
html = html + '</div>';
}

for(var i=0;i<response.length;++i)
{
// for first and every 8 items
if(i % 8 == 0) {
console.log('columnstart');
html = html + '<div class="column">';
}
// for first and every 4 items
if(i % 4 == 0) {
console.log('rowstart');
html = html + '<div class="row">';
}
console.log('cell');
html = html + '<div class="cell"></div>';
// after every 4 items BUT NOT the first
if(i % 4 == 3) {
console.log('rowend');
html = html + '</div>';
}
// after every 8 items
if(i % 8 == 7) {
console.log('columnend');
html = html + '</div>';
}
}

Should be
for(var i=0;i<response.length;i++)
{
// Before 1st and every 8 cells
if(i % 8 == 0)
{
console.log('columnstart');
html = html + '<div class="column">';
}
// Before 1st and every 4 items
if(i % 4 == 0)
{
console.log('rowstart');
html = html + '<div class="row">';
}
console.log('cell');
html = html + '<div class="cell"></div>';
// after every 4th cell added
if(i % 4 == 3)
{
console.log('rowend');
html = html + '</div>';
}
// after every 8th cell added
if(i % 8 ==7)
{
console.log('columnend');
html = html + '</div>';
}
}

I'm afraid you misinterpreted the modulo (%) operator
i % 7==0 means that i is divisible by 7 what you want is i % 8==7
I always find it more clear with a switch statement:
while (response.length%8!=7)
response.push('');
var html='';
for(var i=0;i<response.length;i++)
{
switch (i%8) {
case 0: html = html + '<div class="column"><div class="row">'+response[i];break;
case 4: html = html + '</div><div class="row">'+response[i];break;
case 7: html = html + response[i]+'</div></div>';break;
default: html = html + response[i];
}
}

Related

Generate html in for each with closing tag every 4 loop

I'm trying to generate the following html :
<div class="row">
<div class="col-md-3"></div>
<div class="col-md-3"></div>
<div class="col-md-3"></div>
<div class="col-md-3"></div>
</div>
<div class="row">
<div class="col-md-3"></div>
<div class="col-md-3"></div>
<div class="col-md-3"></div>
<div class="col-md-3"></div>
</div>
<div class="row">
<div class="col-md-3"></div>
</div>
So I tried the following :
var response = '[{"id":7},{"id":10},{"id":15},{"id":11},{"id":14},{"id":9},{"id":8},{"id":12},{"id":1}]'
var json = $.parseJSON(response);
var add_html = "";
$(json).each(function (i, val) {
if (i % 4 == 0){
add_html += "<div class='row'>";
}
add_html = add_html + "<div class='col-md-3'></div>";
if (i % 4 == 0){
add_html = add_html + "</div>";
}
});
/*
if (i % 4 != 1){
add_html = add_html + "</div>";
}
*/
console.log(add_html)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
But doesn't output the desired result
Try like below. And check changes with comment.
There are two changes in your code.
You need to open your row div with i%4 == 0 and close it with i%4 == 3.
Once each loop complete you should check if (json.length - 1) % 4 != 3 then need to add </div>
var response = '[{"id":7},{"id":10},{"id":15},{"id":11},{"id":14},{"id":9},{"id":8},{"id":12},{"id":1}]'
var json = $.parseJSON(response);
var add_html = "";
$(json).each(function(i, val) {
if (i % 4 == 0) {
add_html += "<div class='row'>";
}
add_html = add_html + "<div class='col-md-3'></div>";
// Change 1 - Update condition here to compare with 3
if (i % 4 == 3) {
add_html += "</div>";
}
});
// Change 2 - Add additional condition
if ((json.length - 1) % 4 != 3) {
add_html += "</div>";
}
console.log(add_html)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Old version
Initialize add_html with opening row div.
When i % 4 == 3 which means it is forth index add closing div and open a new one.
Once each loop completes then add closing div.
Note - This has one bug. It will add extra <div class='row'></div> when json array is of json.length % 4 == 0 .
var response = '[{"id":7},{"id":10},{"id":15},{"id":11},{"id":14},{"id":9},{"id":8},{"id":12},{"id":1}]'
var json = $.parseJSON(response);
// Initialize your html with opening row div
var add_html = "<div class='row'>";
$(json).each(function(i, val) {
add_html = add_html + "<div class='col-md-3'></div>";
if (i % 4 == 3) { // <- Update condition here to compare with 3
// Close current row div and open new one
add_html += "</div>";
add_html += "<div class='row'>";
}
});
// End your html with closing row div
add_html = add_html + "</div>";
console.log(add_html)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
To achieve your goal you could batch the original array in to groups of 4 and then use map() to iterate through that and create the HTML you require:
var json = $.parseJSON('[{"id":7},{"id":10},{"id":15},{"id":11},{"id":14},{"id":9},{"id":8},{"id":12},{"id":1}]');
let perChunk = 4;
json = json.reduce((all, one, i) => {
const ch = Math.floor(i / perChunk);
all[ch] = [].concat((all[ch] || []), one);
return all
}, [])
let html = json.map(chunk => `<div class="row">${chunk.map(item => `<div class="col-md-3"></div>`).join('')}</div>`).join('');
console.log(html);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
var response = '[{"id":7},{"id":10},{"id":15},{"id":11},{"id":14},{"id":9},{"id":8},{"id":12},{"id":1}]'
var json = JSON.parse(response);
const add_html = json.map(() => '<div class="col-md-3"></div>').reduce((pre, cur) => {
const arr = pre[pre.length - 1];
if (arr.length >= 4) {
pre.push([cur])
} else {
arr.push(cur);
}
return pre;
}, [[]]).map(item => `<div class="row">${item.join('')}</div>`).join('')

Loop of html using javascript

i am new on using of JavaScript on looping of html. I have this code below that i am working at. In this problem of mine i have 2 loop the main and the card-body loop. As you can see in the code First I need to loop the main to create a card and then at the body i need also to loop it because of the data content. I have also working code below but as you can see at the card-body its not looping anymore but static data that I inputted.
Problem
for (var i = 0; i < dataLength; i++) {
var docsLength = data.data[i].resultData;
var title = data.data[i].resultData[i].Type.Description;
var card = '<div class="card"> <div class="card-header bg-success"><h3 class="card-title">' + title + ' </h3 ></div> <div class="card-body">'; for (var a = 0; a < 2; a++) { "a" } ' </div>' +
'</div >';
$("#card_documents > .card-body").append(card);
}
Working
for (var i = 0; i < dataLength; i++) {
var docsLength = data.data[i].resultData;
var title = data.data[i].resultData[i].Type.Description;
var card = '<div class="card"> <div class="card-header bg-success"><h3 class="card-title">' + title + ' </h3 ></div> <div class="card-body">' +
"asdasdasdasd" +
'</div > ' +
'</div >';
$("#card_documents > .card-body").append(card);
}
Is my syntax wrong?. Please help. Thanks
You can replace for (var a = 0; a < 2; a++) { "a" } with "a".repeat(2).
More info about repeat() here
Yes, your syntax is wrong. Specifically the way you're trying to use the for loop.
I would suggest building up the string in a variable.
Here is a stripped down version of how you might achieve that.
var card = '<div class="card">';
for (var a = 0; a < 2; a++) {
card += "a";
}
card += '</div>';
$("#card_documents > .card-body").append(card);

Dynamically adding elements with jquery error

Here is my fiddle : DEMO
According to data JSON, there are 2 "groups".
Each group has 2 "widgets" each.
Every widget has certain "controls"
Light/Brightness/Color controls can be there for Philips widget. They are associated with a switch/slider/color picker respectively.
for (var k = 0; k < data.groups[i].widgets[j].controls.length; k++) {
$("." + data.groups[i].name + " > .widgets-container > ." + data.groups[i].widgets[j].name + " > .widget-header > .widget-label > .row > .brandName").text(data.groups[i].widgets[j].brandName);
$("." + data.groups[i].name + " > .widgets-container > ." + data.groups[i].widgets[j].name + " > .widget-header > .widget-label > .row > .productName").text(data.groups[i].widgets[j].productName);
var controlDiv;
if (data.groups[i].widgets[j].controls[k].type === "SWITCH") {
controlDiv = lightControl();
} else if (data.groups[i].widgets[j].controls[k].type === "SLIDER") {
controlDiv = brightnessControl();
} else if (data.groups[i].widgets[j].controls[k].type === "PICKER") {
controlDiv = colorControl();
}
controlDiv = $(controlDiv).addClass(data.groups[i].widgets[j].controls[k].name);
$("." + data.groups[i].widgets[j].controls[k].name > ".control-name").text(data.groups[i].widgets[j].controls[k].name);
$("." + data.groups[i].name + " > .widgets-container").append(widgetDiv);
$(widgetDiv).append(controlDiv);
$(".container-box").append(groupDiv);
}
However, the elements are not getting appended as required from the JSON. Also, the labels for light/brightness/color control does not appear. Where am I going wrong?
Any help would be much appreciated.
Thank you.
here is the answer fiddle : AnswerFiddle
I fixed this issue by first creating DOM elements and then assigning/appending values to the DOM elements.
Earlier there was an issue because sometimes assigning of value would be attempted even before DOM element was created.
controlDiv = $(controlDiv).addClass("row " + (data.groups[i].widgets[j].controls[k].name).replace(/\s+/g, '-').toLowerCase()).prepend("<div class='col s7 controlName'>" + data.groups[i].widgets[j].controls[k].name + "</div>");
if (data.groups[i].widgets[j].controls[k].type === 'SWITCH') {
$(controlDiv).append('<div class="col s5 switch"><label>OFF<input type= "checkbox"><span class="lever"></span>ON</label></div>')
} else if (data.groups[i].widgets[j].controls[k].type === 'SLIDER') {
$(controlDiv).append('<div class="col s5 center-align"><img src="images/brightness.png"></div><p class="col s7 range-field"><input type="range" min = "0" max = "100"/></p><div class="col s5 brightness-percentage center-align">60%</div>')
} else if (data.groups[i].widgets[j].controls[k].type === 'PICKER') {
$(controlDiv).append('<input class="col s2" type="color" name="favcolor" value="#ff0000"><div class="col s3 colorHexValue center-align">#ff0000</div>')
} else if (data.groups[i].widgets[j].controls[k].type === 'GRAPH') {
$(controlDiv).html("<img src='images/graph.png'>");
} else if (data.groups[i].widgets[j].controls[k].type === 'DETECTOR') {
$(controlDiv).html("<img src='images/motion.png'>")
}
widgetDiv.append(controlDiv);
groupDiv.append(widgetDiv);
$(".container-box").append(groupDiv);

Create second or next <li> under default <li> after reload page | jQuery, LocalStorage

I try to create LocalStorage data for My Folder Creation .
HTML :
This is my default li. I call it All audience folder's
<!-- Result goes here -->
<ul class="nav">
<li>
<div class="zf-folder" style="width: 232px;">
<div class="_tabFolder _itemPosition" style="height: 50px;border-bottom:1px groove; user-select: none;">
<div class="_sideFolder"></div>
<div class="_iconText" style="width: 215px">
<div class="ellipsis">
<div class="_1i5w">
<div class="_icon-col">
</div>
</div>
All Audiences<span class="hyperspan" style="position:absolute; width:100%; height:100%; left:0; top:0;"></span>
</div>
</div>
</div>
</div>
</li>
</ul>
jQuery :
var count = 1;
$(".submitButton").click(function() {
let label = count++;
// make a function that returns the DOM with updated count
function getNewList(foldername) {
var addFolder = '<li>' +
'<div class="zf-folder" style="width: 232px;">' +
'<div class="_tabFolder _itemPosition" style="height: 50px;border-bottom:1px groove; user-select: none;">' +
'<div class="_sideFolder"></div>' +
'<div class="_iconText" style="width: 215px">' +
'<div class="ellipsis">' +
'<div class="_iconFolder">' +
'<div class="_icon-col">' +
'</div>' +
'</div>' +
'<a href="#folder' + label +
'" data-toggle="tab" style="text-decoration: none;">' +
foldername + '<span class="hyperspan" style="width:100%; height:100%; left:0; top:0;"></span></a>' +
'</div>' +
'</div>' +
'</div>' +
'</div>' +
'</li>';
return addFolder;
}
var inputan = $("#input_nameFolder").val();
// update the result array
var result = JSON.parse(localStorage.getItem("folderList"));
if (result == null) {
result = [];
}
let newfolderHTML = getNewList(inputan);
result.push({
folder: newfolderHTML
});
// save the new result array
localStorage.setItem("folderList", JSON.stringify(result));
// append the new li
$(".nav").append(newfolderHTML); // i want include myDiv
//clear input
$("#input_nameFolder").val('');
});
// on init fill the ul
var result = JSON.parse(localStorage.getItem("folderList"));
if (result != null) {
//get the nav reference in DOM
let nav = $(".nav");
//clear the html contents
nav.html('');
for (var i = 0; i < result.length; i++) {
var item = result[i];
$(".nav").append(item.folder);
}
}
How to adding new <li> tag under my default li (all audience)
after reload page/click run jsfiddle when user input a new value?
You can see after adding an input and reload web / jsfiddle, new input folder's (second li) overwrite all audience (first li).
JSFiddle
you just have to save the initial element upon initialization, see:
// on init fill the ul
var result = JSON.parse(localStorage.getItem("folderList"));
if (result != null) {
//get the nav reference in DOM
let nav = $(".nav");
//clear the html contents
nav.html('');
for (var i = 0; i < result.length; i++) {
var item = result[i];
$(".nav").append(item.folder);
}
} else {
//Save the "All Audiences" content upon empty folderList
let initialElement = [];
initialElement.push({
folder: $('ul.nav').html()
});
localStorage.setItem("folderList", JSON.stringify(initialElement));
}
See: JSFiddle

dynamic id selector not being called or instantiate

I am creating a jquery function, when I add new <tr id="select_row"> this tag with id will increase by one for example select_row1, select_row2, select_row3.
After the row has been increased I try to click on the checkbox but it does not trigger below as well as changing the value where id is #single_price0 and #total_price0
if ( ((meat_length == 1)&&(vege_length == 2)) || ((meat_length == 1)&&(vege_length == 1)) ) {};
var list = $('#add_order_table');
var initial = 0;
list.click(function(){
html = '<tr id="select-row'+initial+'">';
html += '<td class="col-md-7">';
//meat
html += '<div class="col-md-6">';
html += '<div class="checkbox"><label><input type="checkbox" name="meat'+initial+'[]" class="meat"> Black Pepper Fried Chicken</label></div>';
html += '<div class="checkbox"><label><input type="checkbox" name="meat'+initial+'[]" class="meat"> Pineapple Pork</label></div>';
html += '<div class="checkbox"><label><input type="checkbox" name="meat'+initial+'[]" class="meat"> Bitter Gourd with Dash Fish</label></div>';
html += '</div>';
//vege
html += '<div class="col-md-6">';
html += '<div class="checkbox"><label><input type="checkbox" name="vege'+initial+'[]" class="vege"> Garlic Bayam</label></div>';
html += '<div class="checkbox"><label><input type="checkbox" name="vege'+initial+'[]" class="vege"> Oyster Young Pakchoy</label></div>';
html += '</div>';
html += '</td>';
html += '<td class="col-md-1 text-center"><b><p>RM <span id="single_price'+initial+'">0.00</span></p><b></td>';
html += '<td class="col-md-2"><p><input id="qty'+initial+'"type="text" value="" name="demo" class="text-center qty_spinner"></p></td>';
html += '<td class="col-md-1 text-center"><b><p>RM <span id="total_price'+initial+'">0.00</span></p><b></td>';
html += '<td class="col-md-1 text-center"><p><button type="button" class="btn btn-danger" onclick="$(\'#select-row' + initial + '\').remove();">';
html += '<span class="glyphicon glyphicon-minus-sign" aria-hidden="true"></span>';
html += '</button></p></td>';
html += '</tr>';
$('#order_table tbody').append(html);
$('.qty_spinner').TouchSpin({
initval: 1,
min:1,
max:50,
buttondown_class: 'btn btn-danger',
buttonup_class: 'btn btn-primary',
});
var row = $("#select-row"+initial);
row.on('change',function(e){
var meat_length = $('input[class="meat"]:checked').length;
var vege_length = $('input[class="vege"]:checked').length;
if (meat_length == 0 || vege_length == 0) {
$("#single_price"+initial).text("0.00");
$("#total_price"+initial).text("0.00");
};
// 5.50 meal function
if ( ((meat_length == 1)&&(vege_length == 2)) || ((meat_length == 1)&&(vege_length == 1)) ) {
// set single price without parsing
$("#single_price"+initial).text("5.50");
//get single price with parsing
var single1 = parseFloat($("#single_price"+initial).text()).toFixed(2);
// get quantity value
var qty1 = parseInt($("#single_qty"+initial).val());
//single price multiply
var total = parseFloat(single1*qty1).toFixed(2);
$("#total_price"+initial).text(total);
};
// 6.00 meal function
if ( ((meat_length == 2)&&(vege_length == 1)) || (meat_length == 2) ) {
// set single price without parsing
$("#single_price"+initial).text("6.00");
//get single price with parsing
var single1 = parseFloat($("#single_price"+initial).text()).toFixed(2);
// get quantity value
var qty1 = parseInt($("#single_qty"+initial).val());
//single price multiply
var total = parseFloat(single1*qty1).toFixed(2);
$("#total_price"+initial).text(total);
};
});
initial++;
});
Wrap initial in a function, so it preserves the increment within the change function:
(function(initial) {
var row = $("#select-row"+initial);
row.on('change',function(e){
var meat_length = $('input[class="meat"]:checked').length;
var vege_length = $('input[class="vege"]:checked').length;
if (meat_length == 0 || vege_length == 0) {
$("#single_price"+initial).text("0.00");
$("#total_price"+initial).text("0.00");
};
// 5.50 meal function
if ( ((meat_length == 1)&&(vege_length == 2)) || ((meat_length == 1)&&(vege_length == 1)) ) {
// set single price without parsing
$("#single_price"+initial).text("5.50");
//get single price with parsing
var single1 = parseFloat($("#single_price"+initial).text()).toFixed(2);
// get quantity value
var qty1 = parseInt($("#single_qty"+initial).val());
//single price multiply
var total = parseFloat(single1*qty1).toFixed(2);
$("#total_price"+initial).text(total);
};
// 6.00 meal function
if ( ((meat_length == 2)&&(vege_length == 1)) || (meat_length == 2) ) {
// set single price without parsing
$("#single_price"+initial).text("6.00");
//get single price with parsing
var single1 = parseFloat($("#single_price"+initial).text()).toFixed(2);
// get quantity value
var qty1 = parseInt($("#single_qty"+initial).val());
//single price multiply
var total = parseFloat(single1*qty1).toFixed(2);
$("#total_price"+initial).text(total);
};
});
})(initial);

Categories

Resources