Changing the class of divs in a pattern using jQuery

Viewed 69

I have a blog layout I'm working on (bootstrap) and I've hit a snag.

I need the first two divs to be col-md-3 (NORMAL), then the following 2 divs col-md-6 (WIDE), then it needs to make the next 4 divs as col-md-3 (NORMAL), then the next 2 divs col-md-6(WIDE) and so on, so forth.

I've tried [this method in codepen][1], which works (code below) but is obviously not the most efficient way to do it - I'm fairly new to jQuery, so would appreciate any help you can offer!

HTML:

  <div class="container">
  <div class="row" id="blog">
    <div>Normal</div>
    <div class="">Normal</div>
    <div class="">Wide</div>
    <div class="">Wide</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Wide</div>
    <div class="">Wide</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Wide</div>
    <div class="">Wide</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Wide</div>
    <div class="">Wide</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Wide</div>
    <div class="">Wide</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Wide</div>
    <div class="">Wide</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
  </div>
</div>

jQuery used:

$("#blog div").each(function(i) {
var newClass = 'col-md-3 red';
if (i == 2) newClass = 'col-md-6 blue';
if (i == 3) newClass = 'col-md-6 blue';
if (i == 8) newClass = 'col-md-6 blue';
if (i == 9) newClass = 'col-md-6 blue';
if (i == 14) newClass = 'col-md-6 blue';
if (i == 15) newClass = 'col-md-6 blue';
if (i == 20) newClass = 'col-md-6 blue';
if (i == 21) newClass = 'col-md-6 blue';
if (i == 26) newClass = 'col-md-6 blue';
if (i == 27) newClass = 'col-md-6 blue';
if (i == 32) newClass = 'col-md-6 blue';
if (i == 33) newClass = 'col-md-6 blue';
$(this).addClass(newClass);
});
4 Answers

Here's a solution that iterates through each of the divs and selects the appropriate class based on its position in a pattern array. It's not a heck of a lot more compact than what you've already got BUT it has the significant advantage of not requiring you to manually fix your JavaScript if you change the number of divs or the pattern itself. Using this approach you can simply change the items in the pattern array and get a different result immediately.

elements = $("#blog").children();
pattern = ['col-md-3','col-md-3',
          'col-md-6','col-md-6',
          'col-md-3', 'col-md-3'];
  pattern_val = 0;
  for (var i=0;i<elements.length;i++) {
    if (pattern_val < 6) {
      $(elements[i]).addClass(pattern[pattern_val]);
      pattern_val += 1;
    }
    else {
      pattern_val = 0;
      $(elements[i]).addClass(pattern[pattern_val]);
      pattern_val += 1;
    }
};

Here's a CodePen example of it in action.

You can do it using .not() and .filter()

$('#blog div').addClass('col-md-3 red')         // add red class to all the divs
  .not(':lt(2)')                                // exclude the first two Normal elements
  .filter(function(i){                          // filter to get the Wide elements
    return (i % 6 == 0) || ( (i % 6) - 1 == 0)  // filter every 6 element and the element next of it
  }).addClass('col-md-6 blue');                 // add the class to the Wide elements
.red{
  background : red;
}
.blue{
  background : blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
  <div class="row" id="blog">
    <div>Normal</div>
    <div class="">Normal</div>
    <div class="">Wide</div>
    <div class="">Wide</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Wide</div>
    <div class="">Wide</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Wide</div>
    <div class="">Wide</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Wide</div>
    <div class="">Wide</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Wide</div>
    <div class="">Wide</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Wide</div>
    <div class="">Wide</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
  </div>
</div>

use the text method to get the content of the current element.

$("#blog div").each(function(i) {
    var newClass = 'col-md-3 red';
    var text = $(this).text();
    if (text == "Wide") {
        newClass = 'col-md-6 blue';
    }
    $(this).addClass(newClass);
}

And this decision is from me. Objects and keys are involved here. Each object (class) is assigned corresponding keys (index).

let obj = {
  "col-md-3": [1, 2, 5, 6, 7, 8, 11, 12, 13, 14, 17, 18, 19, 20, 23, 24, 25, 26, 29, 30, 31, 32, 35, 36],
  "col-md-6": [3, 4, 9, 10, 15, 16, 21, 22, 27, 28, 33, 34]
}

let objKeys = Object.keys(obj),
    objValues = Object.values(obj);

let nodes = document.querySelectorAll("#blog div");

for (var i = 0; i < nodes.length; i++) {            
    let index = objValues.findIndex(id => id.indexOf(i + 1) > -1)
    
    if (index > -1) {
        nodes[i].classList.add(objKeys[index]);
    }
}

$(nodes).each(function(i) {
  $(this).addClass(obj[i]);
});
.col-md-3, 
.col-md-6 {
  border: 1px solid green;
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
  <div class="row" id="blog">
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Wide</div>
    <div class="">Wide</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Wide</div>
    <div class="">Wide</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Wide</div>
    <div class="">Wide</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Wide</div>
    <div class="">Wide</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Wide</div>
    <div class="">Wide</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
    <div class="">Wide</div>
    <div class="">Wide</div>
    <div class="">Normal</div>
    <div class="">Normal</div>
  </div>
</div>

Related