2014-02-02 5 views
6

Простая таблица html с значениями NxM. Целью является объединение равных ячеек в столбце с jQuery. Обратите внимание, что в одной строке нет дубликатов.Слияние равных ячеек таблицы с jQuery

У меня есть, как скрыть равные ячейки, но есть ли способ объединить ячейку с данными с пустой ячейкой в ​​одном?

HTML:

<table border="1" id="testTable"> 
<tr> 
    <td>First</td> 
    <td>A</td> 
    <td>A</td> 
</tr> 
<tr> 
    <td>First</td> 
    <td>A</td> 
    <td>B</td> 
</tr> 
<tr> 
    <td>Second</td> 
    <td>V</td> 
    <td>S</td> 
</tr> 
<tr> 
    <td>Third</td> 
    <td>D</td> 
    <td>H</td> 
</tr> 
<tr> 
    <td>Third</td> 
    <td>E</td> 
    <td>E</td>  
</tr> 
</table> 

ЯШ:

var seenArray = {}; 
$('#testTable td').each(function() 
{ 
    var index = $(this).index(); 
    var txt = $(this).text(); 
    if (seenArray[index] === txt) 
    { 
     $(this).text(''); //I think here should be "marging" 
    } 
    else 
    { 
     seenArray[index] = txt; 
    } 
}); 

jsFiddle

P.S. Еще одна вещь, данные, первоначально извлекается в JSon массив, то я .parseJSON() первый и положить данные в таблицу, используя:

for (var i = 0; i < obj.length; i++) 
{ 
    tr = $('<tr/>'); 
    tr.append("<td>" + obj[i]['columnA'] + "</td>"); 
    tr.append("<td>" + obj[i]['columnB'] + "</td>"); 
    tr.append("<td>" + obj[i]['columnC'] + "</td>"); 
    $('#testTable').append(tr); 
} 

UPD

alFReD NSH сделал хорошее решение для 2-х клеток. Here - его решение. Но, если будет более двух равных ячеек.

+0

Итак, здесь «Первый» и «А» должны быть одной ячейкой? –

+0

«Первый» и пустая ячейка под ним должна быть объединена. Пожалуйста, проверьте jsfiddle –

ответ

6

Если я получаю то, что вы имеете в виду здесь, это мой отредактированную версию: http://jsfiddle.net/djhU7/4/

Так вместо $(this).text('') я сделал это:

$($this.parent().prev().children()[index]).attr('rowspan', 2); 
    $this.hide(); 

То, что я сделал, был ли я установить rowspan первой ячейки до 2. Этот атрибут «будет указывать, сколько строк будет продолжаться». который сделает вышеприведенную ячейку вдвое большей, и я спрятал ячейку с дублирующейся информацией, чтобы лишняя ячейка исчезла. Обратите внимание, что удаление ячейки разрушит проверку индекса для следующей ячейки. Это было просто быстрое и грязное решение, но атрибут должен использоваться где-то для его достижения.

Вот еще одна версия, которая устанавливает rowspan во время ввода ячеек в таблицу, помимо того факта, что она работает с тремя повторяющимися ячейками и более, она также быстрее, поскольку она позволяет избежать повторного рендеринга таблицы (хотя она может быть оптимизирована больше, но я не думаю, что в данный момент вы хотите заботиться о нем, преждевременная оптимизация есть корень всех зол!): http://jsfiddle.net/g7uY9/1/

for (var i = 0; i < obj.length; i++) { 


    tr = $('<tr/>'); 

    addColumn(tr, 'columnA', i); 
    addColumn(tr, 'columnB', i); 
    addColumn(tr, 'columnC', i); 
    $('#testTable').append(tr); 

} 

function addColumn(tr, column, i) { 
    var row = obj[i], 
     prevRow = obj[i - 1], 
     td = $('<td>' + row[column] + '</td>'); 
    if (prevRow && row[column] === prevRow[column]) { 
     td.hide(); 
    } else { 
     var rowspan = 1; 
     for (var j = i; j < obj.length - 1; j++) { 
      if (obj[j][column] === obj[j + 1][column]) { 
       rowspan++; 
      } else { 
       break; 
      } 
     } 
     td.attr('rowspan', rowspan); 
    } 

    tr.append(td); 
} 
+0

У вас все получилось. Спасибо, товарищ. –

+1

Появилась ошибка, когда второй ячейки не слились, я просто исправил, используя 'hide' вместо' remove'. –

+0

Да, я заметил, что. –

5

Пожалуйста найти улучшенный ответ на ваш запрос с строки развернуть/свернуть. Вот моя скрипка:

function MergeGridCells() 
{ 
    var dimension_cells = new Array(); 
    var dimension_col = null; 

    var i = 1; 
    // First, scan first row of headers for the "Dimensions" column. 
    $("#mytable").find('th').each(function() { 
     if ($(this).text() == 'Id') { 
      dimension_col = i; 
     } 
     i++; 
    }); 

    // first_instance holds the first instance of identical td 
    var first_instance = null; 
    var rowspan=1; 
    // iterate through rows 
    $("#mytable").find('tr.parent-grid-row').each(function() { 

     // find the td of the correct column (determined by the dimension_col set above) 
     var dimension_td = $(this).find('td.parent-grid-column:nth-child(' + dimension_col + ')'); 

     if (first_instance == null) { 
      // must be the first row 
      first_instance = dimension_td; 
     } else if (dimension_td.text() == first_instance.text()) { 
      // the current td is identical to the previous 
      // remove the current td 
      dimension_td.remove(); 
      ++rowspan; 
      // increment the rowspan attribute of the first instance 
      first_instance.attr('rowspan', rowspan); 
     } else { 
      // this cell is different from the last 
      first_instance = dimension_td; 
      rowspan=1; 
     } 
    }); 
} 

Jquery Cell Merging

+1

Кажется, классно, а также комплекс для такой простой задачи , Но вот ваш +1 –

1

Мне очень понравилось Farid первое решение, но мне нужно, чтобы выбрать диапазон строк и столбцы, которые он будет применяться, поэтому я сделал несколько изменений (в том числе возможность слияния более чем 2 клеток).http://jsfiddle.net/djhU7/72/

function Merge_cells($id_table,$lin_ini,$lin_fim,$array_col=array()){ 

$colunas=""; 
for($k=0;$k<count($array_col);$k++) $colunas=$colunas . " col =='$array_col[$k]' ||"; 
if(count($array_col)>0) $colunas="(".substr($colunas,0,-3).") &&";  

echo "<script> 
$('#$id_table td').each(function() 
{ 
    var \$this = $(this); 
    var col = \$this.index();     
    var txt = \$this.text();     
    var row = $(this).parent()[0].rowIndex; 

    //define the interval of lines and columns it will look at 
    if((col==0 || col==1 || col==2) row>=firstRow && row<=lastRow){ 
     span=1; 
     cell_above = $(\$this.parent().prev().children()[col]); 

     //look for cells one above another with the same text 
     while(cell_above.text()=== txt){     //if the text is the same 
      span+=1;          //increase the span 
      cell_above_old = cell_above;     //store this cell 
      cell_above = $(cell_above.parent().prev().children()[col]); //and go to the next cell above 
     } 

     //if there are at least two columns with the same value, set a new span to the first and hide the other 
     if(span>1) { 
      console.log(span); 
      $(cell_above_old).attr('rowspan',span); 
      \$this.hide(); 
     }    
    } 
}); 

     </script>"; 
} 
1

Вот работоспособная версия carla's answer:

function SummerizeTable(table) { 
 
    $(table).each(function() { 
 
    $(table).find('td').each(function() { 
 
     var $this = $(this); 
 
     var col = $this.index(); 
 
     var html = $this.html(); 
 
     var row = $(this).parent()[0].rowIndex; 
 
     var span = 1; 
 
     var cell_above = $($this.parent().prev().children()[col]); 
 

 
     // look for cells one above another with the same text 
 
     while (cell_above.html() === html) { // if the text is the same 
 
     span += 1; // increase the span 
 
     cell_above_old = cell_above; // store this cell 
 
     cell_above = $(cell_above.parent().prev().children()[col]); // and go to the next cell above 
 
     } 
 

 
     // if there are at least two columns with the same value, 
 
     // set a new span to the first and hide the other 
 
     if (span > 1) { 
 
     // console.log(span); 
 
     $(cell_above_old).attr('rowspan', span); 
 
     $this.hide(); 
 
     } 
 
     
 
    }); 
 
    }); 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<button onclick="SummerizeTable('#table1')">Summerize</button> 
 
<table id="table1" border="1" cellspacing="0" > 
 
    <thead> 
 
    <tr> 
 
     <th>State</th> 
 
     <th>City</th> 
 
     <th>Street</th> 
 
    </tr> 
 
    </thead> 
 
    <tbody> 
 
    <tr> 
 
     <td>VT</td> 
 
     <td>Burlington</td> 
 
     <td>Elm</td> 
 
    </tr> 
 
    <tr> 
 
     <td>NY</td> 
 
     <td>Manhattan</td> 
 
     <td>Main</td> 
 
    </tr> 
 
    <tr> 
 
     <td>NY</td> 
 
     <td>Manhattan</td> 
 
     <td>Oak</td> 
 
    </tr> 
 
    <tr> 
 
     <td>NY</td> 
 
     <td>Albany</td> 
 
     <td>State</td> 
 
    </tr> 
 
    </tbody> 
 
</table>

+0

** Примечание **: комментарии говорят «если текст тот же», но функция фактически сравнивает вывод '.html()', который может отличаться способами, которые должны быть прозрачными для пользователя (из-за разных атрибутов или скрытых полей или текстовых идентификаторов). Поэтому было бы лучше сравнить [обрезанный] (https://api.jquery.com/jQuery.trim/) [текст] (https://api.jquery.com/jQuery.trim/) каждого ' 'like this' $ .trim ($ this.text()) ' – KyleMit

1

Я продлил решение Карлу. С двумя функциями мы можем объединить по горизонтали или по вертикали и исключить или включить ячейки для объединения. попробуйте рабочий образец. https://jsfiddle.net/bn3u63pe

/* 
* merge horizontally 
* ex) autoMergeByCol('theTable', 2, 0, 0); 
*/ 
function autoMergeByCol(tableId 
     , rowStartIndex // zero or positive 
     , colStart  // zero or positive 
     , colEnd  // equals to colStart or greater than colStart or negative to go to the end of cols 
     ) { 
    /* 
    console.log('autoMergeByCol tableId=' + tableId 
     + ', rowStartIndex=' + rowStartIndex 
     + ', colStart=' + colStart 
     + ', colEnd=' + colEnd 
    ); 
    */ 
    var trArr = $('#' + tableId).find('tr');  // rows array 
    for(var rowIndex = rowStartIndex ; rowIndex < trArr.length ; rowIndex++) { 
    var tdArr = $(trArr[rowIndex]).find('td'); // cols array of the row 
    if(colEnd < 0) colEnd = tdArr.length - 1;  // if colEnd is negative, process at the end of the cols; 
     for(var colIndex = colStart ; colIndex < tdArr.length && colIndex <= colEnd ; colIndex++) { 
      var span = 1; 
      var theCell = $(tdArr)[colIndex]; 
      if($(theCell).attr('rowspan')) {continue;} 
      var cellNext = $($(theCell).parent().children()[colIndex + span]);  
      while(cellNext != undefined 
        && $(theCell).text() == $(cellNext).text() 
        && colIndex + span <= colEnd) { 
       span++; 
       cellNext.hide(); 
       cellNext = $($(cellNext).parent().children()[colIndex + span]);  
      } 
      if(span > 1) $(theCell).attr('colspan', span); 
     } 
    } 
} 

/* 
* merge vertically 
* ex) autoMergeByCol('theTable', 2, 0, 0); 
*/ 
function autoMergeByRow(tableId 
     , rowStartIndex // zero or positive 
     , colStart  // zero or positive 
     , colEnd  // equals to colStart or greater than colStart or negative 
     ) { 
    /* 
    console.log('autoMergeByRow tableId=' + tableId 
     + ', rowStartIndex=' + rowStartIndex 
     + ', colStart=' + colStart 
     + ', colEnd=' + colEnd 
    ); 
    */ 
    var trArr = $('#' + tableId).find('tr');   // rows array 
    for(var rowIndex = rowStartIndex ; rowIndex < trArr.length ; rowIndex++) { 
     var tdArr = $(trArr[rowIndex]).find('td'); // cols array of the row 
     if(colEnd < 0) colEnd = tdArr.length - 1;  // if colEnd is negative, process at the end of the cols; 
     for(var colIndex = colStart ; colIndex < tdArr.length && colIndex <= colEnd ; colIndex++) { 
      var span = 1; 
      var theCell = $(tdArr)[colIndex]; 
      if($(theCell).attr('colspan')) {continue;} 
      var cellBelow = $($(theCell).parent().next().children()[colIndex]);   
      while(cellBelow != undefined 
        && $(theCell).text() == $(cellBelow).text()) { 
       span++; 
       cellBelow.hide(); 
       cellBelow = $($(cellBelow).parent().next().children()[colIndex]);   
      } 
      if(span > 1) $(theCell).attr('rowspan', span);   
     } 
    } 
} 
Смежные вопросы