2

I have an array which looks somewhat like this:

arr = [
  ["10", "1", "1200", "630"],
  ["272", "45", "654", "654"],
  ["10", "139", "367", "372"],
  ["825", "134", "369", "371"]
];

The values inside of each array are params (x, y, width, height) for a div I want to render. So e.g. the first div should have the props:

left: 10,
top: 1,
width: 1200,
height: 630

My current implementation looks like this:

for (var i = 0; i < arr.length; i++) {
      $('<div/>', {
          class: 'class-' + i
        }).appendTo($('body'));
      for (var j = 0; j < arr[i].length; j++) {
            $('.class-' + i).css({
                position: 'absolute',
                left: arr[i][j],
                top: arr[i][j],
                width: arr[i][j],
                height: arr[i][j]
         });
     }
}

So in this case I would like to create 4 different divs for each array with the proper CSS styles given in each array. Unfortunately it is not working, because I face some issues with indexing.

Do you have an idea how to solve this?

Thanks!

2
  • "Because I face some issues with indexing." > What issues? What's happening, and what do you expect to happen? Commented Jan 11, 2018 at 8:30
  • share html and what result you want and what error you get? Commented Jan 11, 2018 at 8:33

6 Answers 6

3

The problem is with this part of code:

for (var j = 0; j < arr[i].length; j++) {
        $('.class-' + i).css({
            position: 'absolute',
            left: arr[i][j],
            top: arr[i][j],
            width: arr[i][j],
            height: arr[i][j]
        });
}

You have to set style of a given div only once. In your code it is setting css style for 4 times for every div which has class-i, where i= 1 to arr.length.

arr = [
       ["10px", "1px", "12", "63"],
       ["272px", "45px", "65", "65"],
       ["101px", "139px", "36", "37"],
       ["825px", "134px", "36", "31"]
     ];
for (var i = 0; i < arr.length; i++) {
        $('<div/>', {
            class: 'class-' + i
        }).appendTo($('body'));
        $('.class-' + i).css({
                position: 'absolute',
                left: arr[i][0],
                top: arr[i][1],
                width: arr[i][2],
                height: arr[i][3]
        });
}
div{
  background-color:red;
  border:1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Sign up to request clarification or add additional context in comments.

2 Comments

Hi Mihai! Thanks for your input - yours and ItsGregs solution both seem to work fine, but both do not recognize the left and top value. Do you have an idea why?
@Akr, have a look now. It seems you have to set value using px for top and left properties.
2

You can use .map(), pass an object to .css(). Note also, left and top values should have "px" concatenated to the numeric value

arr = [
  ["10px", "1px", "1200", "630"],
  ["272px", "45px", "654", "654"],
  ["10px", "139px", "367", "372"],
  ["825px", "134px", "369", "371"]
];
$("body")
  .append(
    arr.map(([left, top, width, height], i) =>
      $("<div>", {
        "class": "class-" + i,
        text: i,
        css: {left, top, width, height}
      }))
  );
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>

plnkr http://plnkr.co/edit/4DgX13CoQAy9QC8oUA1T?p=preview

4 Comments

Thanks, really elegant solution! Will consider this as well! Thanks for contributing!
@AKr I'd go so far as to avoid looping or forEach-ing without spending a good amount of time investigating map, reduce/recursion and filter
@AKr comment was too long but here are all the array functions
@HMR thanks! I will dive more into these functionalities. Thanks for pointing out!
1

You don't want to iterate a second time though it. In your first for loop, you get ["10", "1", "1200", "630"]. If you loop through it again, you get a single value. Here's what you're looking for - I'm a bit rusty with jQuery, you could probably optimize that.

for (var i = 0; i < arr.length; i++) {
    var parent =  $('<div/>', {
        class: 'class-' + i
    }).appendTo($('body'));
    $('.class-' + i).css({
        position: 'absolute',
        left: arr[i][0],
        top: arr[i][1],
        width: arr[i][2],
        height: arr[i][3]
    });
}

Comments

1

Here's a fiddle for you. Hope that helps.

var arr = [
       ["10", "1", "1200", "630"],
       ["272", "45", "654", "654"],
       ["10", "139", "367", "372"],
       ["825", "134", "369", "371"]
     ];
     
 arr.forEach(function(a) {
 	var div = $('<div/>').css({
    left: a[0],
    top: a[1],
    width:a[2],
    height: a[3]
  });
 	$('body').append(div);
 });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

2 Comments

I'll give you a +1 for effort but forEach mixes the side effect of adding divs to the dom with creating the div dom element. The answer of guest271314 uses map that returns an array of divs that you can then enter in the dom (side effect). If you want to split crating divs and doing something with them into separate functions then using map is better because it only creates the divs.
@HMR Thanks buddy :) It is a great suggestion to optimise my answers in future .
0

for (var i = 0; i < arr.length; i++) {
  $('<div/>', {
    class: 'class-' + i
  }).appendTo($('body'));
  $('.class-' + i).css({
    position: 'absolute',
    left: arr[i][0],
    top: arr[i][1],
    width: arr[i][2],
    height: arr[i][3]
  });

}

You only need one loop.

Comments

0

Here is an example using reduce and recursive function:

var arr = [
  ["10px", "1px", "1200", "630"],
  ["272px", "45px", "654", "654"],
  ["10px", "139px", "367", "372"],
  ["825px", "134px", "369", "371"]
];
var mapValuesToCss = ([left, top, width, height])=>
  Object.assign(
    {left,top}
    ,{
      width:width+"px",
      height:height+"px"
    }
  );
var addIndexAsContent = (value,index)=>value.html(index)
var createDivsReduce = css =>
  css.reduce(
    (divs,css)=>
      divs.concat(
        $(
          "<div>",
          css
        )
      )
    ,[]
  );
var createDivsRecursive = divs => css => {
  if(css.length===0){
    return divs;
  }
  return createDivsRecursive
    (divs.concat($("<div>",css[0])))
    (css.slice(1));//recursively call itself
}
//using reduce
$("body")
  .append(
    createDivsReduce(arr.map(mapValuesToCss))
    .map(addIndexAsContent)
  );
//recursively
$("body")
  .append(
    createDivsRecursive([])(arr.map(mapValuesToCss))
    .map(addIndexAsContent)
  );
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.