 
			
				29.10.2018, 01:00
			
			
			
		  
	 | 
 
	
		
		
		
			  | 
			
			
				
				
				 Профессор 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 06.08.2017 
					
					
					
						Сообщений: 473
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	| 
	
	
		
		
			
			 
				Редактор и html-таблица
			 
			
		
		
		
		Здравствуйте! 
Расширяю функционал редактора, чтоб в модальном окне удобно заполнять таблицы. 
Основное получилось быстро написать, а вот на целый день застрял с объединением ячеек таблицы.
 Не знаю как выделять ячейки таблицы, чтоб мышкой с нажатой левой клавишей можно было выделять ячейки, а потом нажав кнопку "Объединить ячейки" они объединились.
 
Накидал вот такое, знаю что не правильно. У меня пока нет идей как это сделать. Не могу выделить ячейки, чтоб дойти до того какой атрибут ставить colspan или rowspan.
 
<style>td.cell__active {background:#7fffd4}table, th, td{min-width:50px;border:solid 1px #ccc} th, td{min-width:50px;min-height:15px}button{margin-top:10px}</style>
<table contenteditable="true">
	<tbody>
		<tr><td></td><td></td><td></td><td></td></tr>
		<tr><td></td><td></td><td></td><td></td></tr>
		<tr><td></td><td></td><td></td><td></td></tr>
		<tr><td></td><td></td><td></td><td></td></tr>
	</tbody>
</table>
<button id="margeTd">Объединить ячейки</button>
<script>
  let table = document.querySelector('table');
  // Добавить класс ячейкам таблицы
  table.addEventListener('mouseover', function(e) {
      if (e.target.tagName == 'TD') {
          e.target.className = 'cell__active';
      }
  });
  // Объединение ячеек таблицы
  document.querySelector('#margeTd').addEventListener('click', function () {
      let marg = table.querySelectorAll('td.cell__active');
      if (marg.length > 1) {
          for (let i = 0; i < marg.length; i++) {
              i == 0 ? marg[i].setAttribute('colspan', marg.length, 0) : marg[i].remove();
          }
      }
  });
</script>
Может кто накинет идею, как мне выделить ячейки. Тестово поставил - мышкой поводить добавляет класс и по классу объединяет. Но это неправильно.  
		
	
		
		
		
		
		
		
	
		
			
			
	
			
			
			
			
			
				 
			
			
			
			
			
			
				
			
			
			
		 
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				29.10.2018, 03:14
			
			
			
		  
	 | 
 
	
		
		
		
			
			| 
			
				
				
				 Профессор 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 14.01.2015 
					
					
					
						Сообщений: 12,989
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	
	
	
		
		
		
		
		
	
 
	| 
		
			Сообщение от MC-XOBAHCK
			
		
	 | 
 
	| 
		выделять ячейки, а потом нажав кнопку "Объединить ячейки" они объединились
	 | 
 
	
 
 Проще выделить строку, хотя можно и несколько ячеек в строке так как посчитать будет не сложно, а вот со столбцами не так просто.  
		
	
		
		
		
		
		
		
	
		
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				29.10.2018, 04:12
			
			
			
		  
	 | 
 
	
		
		
		
			  | 
			
			
				
				
				 Профессор 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 06.08.2017 
					
					
					
						Сообщений: 473
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	
	
	
		
		
		
		
		
	
 
	
		
			Сообщение от laimas
			 
		
	 | 
 
	| 
		Проще выделить строку, хотя можно и несколько ячеек в строке так как посчитать будет не сложно, а вот со столбцами не так просто.
	 | 
 
	
 
 В HTML можно объединять соседние ячейки. Точнее не объединять (объединять нельзя), а задавать размеры для отдельных ячеек при помощи атрибутов colspan или rowspan. Объединять можно уже при помощи js.
 
Проблема в том, что у меня нет идеи как выделять ячейки, при этом нужно выделять прямоугольной областью не вылазя за пределы tbody, thead, tfooter.
 
При объединении по горизонтали моё решение подходит, а вот в высоту пока только мысли проставить атрибуты с номерами строк или может по родителю ячеек как то можно. 
Но я не могу выделить ячейки, поэтому в высоту пока не развиваю идею.  
		
	
		
		
		
		
		
		
	
		
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				29.10.2018, 05:58
			
			
			
		  
	 | 
 
	
		
		
		
			
			| 
			
				
				
				 Профессор 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 14.01.2015 
					
					
					
						Сообщений: 12,989
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	
	
	
		
		
		
		
		
	
 
	| 
		
			Сообщение от MC-XOBAHCK
			
		
	 | 
 
	| 
		объединять нельзя
	 | 
 
	
 
 Можно.
 
	
 
	| 
		
			Сообщение от MC-XOBAHCK
			
		
	 | 
 
	| 
		задавать размеры для отдельных ячеек при помощи атрибутов colspan или rowspan
	 | 
 
	
 
 Это как раз и есть указание, что данная ячейка равна N ячеек в строке или столбце, то есть в данной ячейке объединены N ячеек.
 
Откройте любое ПО, которое может создавать таблицы, объединять ячейки, тот же Word. Сохраните код как html и посмотрите структуру таблицы с объединенными ячейками, в особенности если в строке есть объединение в столбце. Это даст понимание того, что при объединении ячеек столбца не все так просто будет как с объединением в строке.  
		
	
		
		
		
		
		
		
	
		
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				29.10.2018, 09:17
			
			
			
		  
	 | 
 
	
		
		
		
			  | 
			
			
				
				
				 Профессор 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 27.05.2010 
					
					
					
						Сообщений: 33,150
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	| 
	
	
		
		
			
			 
				выделятор блоков и обьединение ячеек
			 
			
		
		
		
		MC-XOBAHCK, 
макет, обьединение ячеек(mergeTd) расчитано на первый клик!!!(требует доработки). 
выделить ячейки и нажать кнопку
 
<!DOCTYPE html>
<html>
<head>
  <title>Untitled</title>
  <meta charset="utf-8">
  <style type="text/css">
   table{
           height: 250px;
           width: 250px;
           border-collapse: separate;
       }
   td{
      border: 1px #0000CD solid;
      background-color: #800080;
   }
   td.sel{
    opacity:.6;
  }
  #line{
    position:absolute;
    width:0px;
    height:0px;
    background:rgba(0,90,255,0.25);
    border:1px solid rgba(0,114,255,0.5);
    box-sizing:border-box;
  }
  </style>
    <script>
window.addEventListener("DOMContentLoaded", function() {
    var target = document.createElement("div"),
        x, y;
    target.id = "line";
    document.addEventListener("mousedown", function(e) {
        if (e.which > 1) return;
        x = e.pageX;
        y = e.pageY;
        document.body.appendChild(target);
        selectBlock();
        document.addEventListener("mousemove", move, false);
        return false
    }, false);
    function move(e) {
        e.preventDefault();
        target.style.width = Math.abs(e.pageX - x) + "px";
        target.style.height = Math.abs(e.pageY - y) + "px";
        target.style.left = (e.pageX < x ? e.pageX : x) + "px";
        target.style.top =
            (e.pageY < y ? e.pageY : y) + "px";
        selectBlock(true)
    }
    document.addEventListener("mouseup", function() {
        target.style.width = "0px";
        target.style.height = "0px";
        document.removeEventListener("mousemove", move);
        target.parentNode && document.body.removeChild(target)
    });
    function collisionDetection(x1, y1, w1, h1, x2, y2, w2, h2) {
        return x1 < x2 + w2 && y1 < y2 + h2 && x1 + w1 > x2 && y1 + h1 > y2
    }
    function coordinate(el) {
        var pos = el.getBoundingClientRect(),
            top = pos.top,
            left = pos.left,
            right = pos.right,
            bottom = pos.bottom,
            height = bottom - top,
            width = right - left;
        return [left,
            top, width, height
        ]
    }
    function selectBlock(add) {
        [].forEach.call(document.querySelectorAll("td"), function(el) {
            var data = coordinate(el).concat(coordinate(target)),
                modify = add && collisionDetection.apply(null, data) ? "add" : "remove";
            el.classList[modify]("sel")
        })
    }
    function mergeTd(event) {
        var tds = document.querySelectorAll("td.sel"),
            len = tds.length,
            colspan = 1,
            parent;
        if (len) {
            [].forEach.call(tds, function(el, i) {
                if (i) {
                    var elParent = el.parentNode;
                    parent == elParent && colspan++;
                    elParent.removeChild(el)
                } else parent = el.parentNode
            });
            tds[0].colSpan = colspan;
            tds[0].rowSpan = len / colspan
        }
    }
    document.querySelector(".merge").addEventListener("mousedown", mergeTd)
});
</script>
</head>
<body>
<table>
    <tbody>
        <tr><td></td><td></td><td></td><td></td></tr>
        <tr><td></td><td></td><td></td><td></td></tr>
        <tr><td></td><td></td><td></td><td></td></tr>
        <tr><td></td><td></td><td></td><td></td></tr>
    </tbody>
</table>
<input name="" type="button" value="go" class="merge">
</body>
</html>
 
		
	
		
		
		
		
		
		
		
						  
				
				Последний раз редактировалось рони, 29.10.2018 в 09:20.
				
				
			
		
		
	
		
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				29.10.2018, 18:03
			
			
			
		  
	 | 
 
	
		
		
		
			  | 
			
			
				
				
				 Профессор 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 06.08.2017 
					
					
					
						Сообщений: 473
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	| 
	
	
		
		
		
		
		 рони, Спасибо вам! 
Вижу выделение ячеек происходит так как нужно, и вижу баг, что вы указали как требует доработки. 
 
Я с утра приболел, вот начинаю приходить в себя и разбирать код. 
Я код понимаю, но не весь. Если можно - есть вопросы. 
 
В строке 33 создаётся элемент - createElement. Это прямоугольник области выделения мышью? 
 
37 строка if (e.which > 1) return; - я правильно понял - это условие останавливает выполнение функции если код клавиши > 1 ? То есть вместе с событием mousedown это и есть нажатая левая кнопка мыши. 
		
	
		
		
		
		
		
		
		
						  
				
				Последний раз редактировалось MC-XOBAHCK, 29.10.2018 в 18:08.
				
				
			
		
		
	
		
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				29.10.2018, 18:05
			
			
			
		  
	 | 
 
	
		
		
		
			  | 
			
			
				
				
				 Профессор 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 27.05.2010 
					
					
					
						Сообщений: 33,150
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	
	
	
		
		
		
		
		MC-XOBAHCK, 
 да и да    
		
	
		
		
		
		
		
		
	
		
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				29.10.2018, 18:13
			
			
			
		  
	 | 
 
	
		
		
		
			  | 
			
			
				
				
				 Профессор 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 27.05.2010 
					
					
					
						Сообщений: 33,150
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	
	
	
		
		
		
		
		MC-XOBAHCK,
 
	
 
	| 
		
			Сообщение от ruslan_mart
			
		
	 | 
 
	| 
		рони, по правой кнопке мыши выделение тоже срабатывает и при отпускании не убирается. Нужно сделать дополнительную проверку event.which
	 | 
 
	
 
   https://javascript.ru/forum/misc/519...tml#post343149 
		
	
		
		
		
		
		
		
	
		
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				29.10.2018, 21:52
			
			
			
		  
	 | 
 
	
		
		
		
			  | 
			
			
				
				
				 Профессор 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 06.08.2017 
					
					
					
						Сообщений: 473
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	
	
	
		
		
		
		
		
	
 
	
		
			Сообщение от рони
			 
		
	 | 
 
	| 
		да и да
	 | 
 
	
 
 Ещё раз большое вам СПАСИБИЩЕ! Я разобрался с вашим кодом.
 
Получается, что выделение ячеек вы реализовали, а нужно доработать последнюю функцию - вот эту:
 
function mergeTd(event) {
    var tds = document.querySelectorAll("td.sel"),
        len = tds.length,
        colspan = 1,
        parent;
    if (len) {
        [].forEach.call(tds, function (el, i) {
            if (i) {
                var elParent = el.parentNode;
                parent == elParent && colspan++;
                elParent.removeChild(el)
            } else parent = el.parentNode
        });
        tds[0].colSpan = colspan;
        tds[0].rowSpan = len / colspan
    }
}
document.querySelector("#margeTd").addEventListener("mousedown", mergeTd);
1. У функции принимающий параметр event можно убрать или лучше оставить? Я понимаю так, что он вообще не нужен и никакие события в функции не отслеживаются. Работа происходит только с массивом выделенных ячеек.
 
2. Последние две строчки функции
 
tds[0].colSpan = colspan;
tds[0].rowSpan = len / colspan
 
Это тоже самое что:
 
tds[0].setAttribute('colspan', colspan, 0);
tds[0].setAttribute('rowspan', len / colspan, 0);
?
 
3. Идея как считать высоту и ширину для объединённой ячейки у меня появилась. Буду пробовать. Нужно немного посидеть поисследовать. Думаю у меня должно получиться, основная логика всё таки уже написана.
 
4. А вот что мне сложно будет доработать, это сделать правильное выделение. Вот только что обнаружил возможность вот такого выделения ячеек:
 
<style>table, th, td{min-width:50px;min-height:100px;border:solid 1px #ccc} th, td{min-width:50px;min-height:15px}</style>
<table>
    <tr><td></td><td></td><td></td></tr>
    <tr><td></td><td></td><td rowspan="2" style="background:red"></td></tr>
    <tr><td></td><td style="background:red"></td></tr>
</table>
вот же блин...  
		
	
		
		
		
		
		
		
	
		
			
			
	
			
			
			
			
			
				 
			
			
			
			
			
			
				
			
			
			
		 
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				29.10.2018, 22:29
			
			
			
		  
	 | 
 
	
		
		
		
			  | 
			
			
				
				
				 Профессор 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 27.05.2010 
					
					
					
						Сообщений: 33,150
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	
	
	
		
		
		
		
		MC-XOBAHCK, 
 да 
1.можно убрать 
2.свойство и атрибут, в данном случае изменение свойства равно назначению атрибута, такое не всегда, например свойство value можно изменить, атрибут останется прежним. подробнее тут
 https://learn.javascript.ru/attribut...nachenie-value
3.  удачи!!! 
4. не знаю, выбор за вами, смотря какой нужен результат.  
		
	
		
		
		
		
		
		
	
		
		
	
	
	 | 
 
 
	 
		 | 
 
 
 
 |  
  |