1

I am creating a jQuery to optimize table structure by removing all the extra rows and columns that:

  • a) contain less than 2 child elements
  • b) contain duplicate container (.column can't have child .column, .row can't have child .row)

I still didn't get it working, it runs in 6 steps (visible in the comments).

What is necessary to turn the #example into #solution?

var selection;
//1. Select all rows and columns
selection = $('#example').find('.row, .column');
//2. Deselect rows and columns with more than 1 child
selection = selection.not('.row:has(div:nth-of-type(2)), .column:has(div:nth-of-type(2))');
//3. Deselect rows and columns that contain cells
selection = selection.not('.row:has(.cell:nth-of-type(1)), .column:has(.cell:nth-of-type(1))');
//4. Remove redundant divs
console.log(selection);
//selection.css('border', '1px yellow solid');//paint them yellow (for testing)
selection.children().first().unwrap();
//5. Select duplicate rows and columns
selection = $('#example').find('.row:has(.row), .column:has(.column)');
//6. Remove redundant divs since first removal
selection.children().first().unwrap();
.grid {
  display: flex;
  min-height: 5px;
}
.row {
  display: flex;
  flex-grow: 1;
  border: 1px solid red;
}
.cell {
  flex-grow: 1;
  flex-basis: 20px;
  border: 1px solid green;
}
.column {
  display: flex;
  flex-grow: 1;
  flex-direction: column;
  border: 1px solid blue;
}
.row,
.column,
.cell {
  margin: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<span>Example</span>
<div id="example" class="grid">
  <div class="column">
    <div class="row">
      <div class="column">
        <div class="row">
          <div class="column">
            <div class="cell">
            </div>
          </div>
        </div>
      </div>
      <div class="column">
        <div class="row">
          <div class="cell">
          </div>
          <div class="cell">
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

<span>Solution</span>
<div id="solution" class="grid">
  <div class="row">
    <div class="cell">
    </div>
    <div class="cell">
    </div>
    <div class="cell">
    </div>
  </div>
</div>
Peter G.
  • 7,816
  • 20
  • 80
  • 154

2 Answers2

1

Based on the formula you have given, try this demo

$('#example').find('.column').each(function(){
   $(this).find(".column").each(function(){
     $(this).unwrap();
   });
   if ($(this).children().size() < 2 && $(this).find(".cell").size() == 0 )
   {
      $(this).remove();
   }
});

$('#example').find('.row').each(function(){
   $(this).find(".row").each(function(){
     $(this).unwrap();
   });
   if ($(this).children().size() < 2 && $(this).find(".cell").size() == 0 )
   {
      $(this).remove();
   }
});
gurvinder372
  • 66,980
  • 10
  • 72
  • 94
  • +1 for the overall approach, one small mistake in the Fiddle that a `.column` contains one `.row` element, which it is not allowed to. https://jsfiddle.net/piglin/uguz7dtk/1/ – Peter G. Mar 08 '16 at 11:28
  • @PeterGerhat thanks. What should happen to the column which has a row element? – gurvinder372 Mar 08 '16 at 11:31
  • `.column` that contains single `.row` should be removed. Removing the `.column` will leave duplicate `.row` container, which should also be removed. Then both a) and b) are met. Here is an example https://jsfiddle.net/piglin/uguz7dtk/3/ – Peter G. Mar 08 '16 at 11:43
0

This is a solution to updated version of the constraints, constraint A was reduced to minimum to provide an even better result (it is possible to reduce this example to bare minimum of one row).

//Constraint A
$('#example').find('.row, .column').each(function() {
  if ($(this).children().size() < 2) {
    $(this).children().first().unwrap();
  }
});

//Constraint B
$('#example').find('.column').each(function() {
  if ($(this).parent().hasClass('column')) {
    $(this).children().first().unwrap();
  }
});
$('#example').find('.row').each(function() {
  if ($(this).parent().hasClass('row')) {
    $(this).children().first().unwrap();
  }
});
.row {
  display: flex;
  flex-grow: 1;
  border: 1px solid red;
}
.cell {
  flex-grow: 1;
  flex-basis: 20px;
  border: 1px solid green;
}
.column {
  display: flex;
  flex-grow: 1;
  flex-direction: column;
  border: 1px solid blue;
}
.row,
.column,
.cell {
  margin: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<span>Solution</span>
<div id="example" class="row">
  <div class="column">
    <div class="row">
      <div class="column">
        <div class="row">
          <div class="column">
            <div class="cell">
            </div>
          </div>
        </div>
      </div>
      <div class="column">
        <div class="row">
          <div class="cell">
          </div>
          <div class="cell">
          </div>
        </div>
      </div>
    </div>
  </div>
</div>
Peter G.
  • 7,816
  • 20
  • 80
  • 154
  • Yes, it works. It maintains structure even of complex flexbox grids. I also decided to simplify condition A because it was creating invisible rows/columns containing single cell. – Peter G. Mar 09 '16 at 09:45