Reputation: 230
I'm trying to make an interactive table-grid that when you resize the edges, the other tables will be resized too. So far, everything seems to work up until the point where in order to add a new column, you must click the button.
Expected behaviour:
If you try dragging the edges of the initial two columns, they work perfectly. However, if you add a new column by clicking on the button, the column gets added to the table, but does not match the behaviour of the other two. How can I get all columns added with a button to follow the same behaviour?
$(document).ready(function() {
AddListeners()
function AddListeners() {
var thElm;
var startOffsetX;
var startOffsetY;
Array.prototype.forEach.call(
document.querySelectorAll("table th"),
function(th) {
th.style.position = 'relative';
var grip = document.createElement('div');
grip.innerHTML = " ";
grip.style.top = 0;
grip.style.right = 0;
grip.style.bottom = 0;
grip.style.width = '5px';
grip.style.position = 'absolute';
grip.style.cursor = 'col-resize';
grip.addEventListener('mousedown', function(e) {
thElm = th;
startOffsetX = th.offsetWidth - e.pageX;
startOffsetY = th.offsetHeight - e.pageY;
});
th.appendChild(grip);
});
document.addEventListener('mousemove', function(e) {
if (thElm) {
thElm.style.width = startOffsetX + e.pageX + 'px';
thElm.style.height = startOffsetY + e.pageY + 'px';
}
});
document.addEventListener('mouseup', function() {
thElm = undefined;
});
};
})
var iter = 2;
function AddColumn() {
var myform = $('#myTable');
myform.find('tr').each(function() {
var trow = $(this);
iter += 1;
if (trow.index() === 0) {
trow.append('<th><div style="top: 0px; right: 0px; bottom: 0px; width: 5px; position: absolute; cursor: col-resize;"> </div>th ' + iter + '</th>');
} else {
trow.append('<td>th ' + iter + '</td>');
}
});
}
table {
border-width: 1px;
border-style: solid;
border-color: black;
border-collapse: collapse;
}
table td {
border-width: 1px;
border-style: solid;
border-color: black;
}
table th {
border-width: 1px;
border-style: solid;
border-color: black;
background-color: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<a onclick="AddColumn()">Add column</a>
<table id="myTable">
<thead>
<tr>
<th>th 1</th>
<th>th 2</th>
</tr>
</thead>
</table>
Upvotes: 2
Views: 76
Reputation: 586
Your code doesn't work because event listeners are only attached to the initial two columns when callback for $(document).ready
is called. A simple solution is calling
AddListeners()
each time when a new column is inserted, as shown below:
function AddListeners() {
var thElm;
var startOffsetX;
var startOffsetY;
Array.prototype.forEach.call(
document.querySelectorAll("table th"),
function(th) {
th.style.position = 'relative';
var grip = document.createElement('div');
grip.innerHTML = " ";
grip.style.top = 0;
grip.style.right = 0;
grip.style.bottom = 0;
grip.style.width = '5px';
grip.style.position = 'absolute';
grip.style.cursor = 'col-resize';
grip.addEventListener('mousedown', function(e) {
thElm = th;
startOffsetX = th.offsetWidth - e.pageX;
startOffsetY = th.offsetHeight - e.pageY;
});
th.appendChild(grip);
});
document.addEventListener('mousemove', function(e) {
if (thElm) {
thElm.style.width = startOffsetX + e.pageX + 'px';
thElm.style.height = startOffsetY + e.pageY + 'px';
}
});
document.addEventListener('mouseup', function() {
thElm = undefined;
});
};
$(document).ready(function() {
AddListeners();
})
var iter = 2;
function AddColumn() {
var myform = $('#myTable');
myform.find('tr').each(function() {
var trow = $(this);
iter += 1;
if (trow.index() === 0) {
trow.append('<th><div style="top: 0px; right: 0px; bottom: 0px; width: 5px; position: absolute; cursor: col-resize;"> </div>th ' + iter + '</th>');
} else {
trow.append('<td>th ' + iter + '</td>');
}
});
AddListeners();
}
table {
border-width: 1px;
border-style: solid;
border-color: black;
border-collapse: collapse;
}
table td {
border-width: 1px;
border-style: solid;
border-color: black;
}
table th {
border-width: 1px;
border-style: solid;
border-color: black;
background-color: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<a onclick="AddColumn()">Add column</a>
<table id="myTable">
<thead>
<tr>
<th>th 1</th>
<th>th 2</th>
</tr>
</thead>
</table>
This solution is ugly though, since it will redo the listener adding for early existed columns. A better solution would require you to decouple the event attaching procedure for each column from callback in AddListeners()
, and call it in Array.prototype.forEach.call
and AddColumn()
respectively. That's another question though.
Upvotes: 2