这是一个表格,您可以单击并向下拖动到rowspan。我添加了函数removeCellSpan()以将跨区单元格还原为其默认值。对于$ thisCell,它可以成功地将rowspan设置为0,并将td元素追加到跨越的相应行。问题是这些新附加的元素无法被表的其余部分识别,因此无法突出显示。似乎所有的列都被偏移1.我错过了什么?
编辑:片段很长,但它完美地说明了问题。单击“+”按钮在计划中添加约会,右键单击以删除约会。当您尝试在同一部分中再次安排相同的约会时,会出现问题。
function addAppt() {
$('td').css('cursor', 'cell');
$('textarea').css('cursor', 'cell');
var $table = $("#myTable tbody");
var $rows = $table.children("tr");
var $cells = $table.find("td");
var numCells = $cells.length;
var numRows = $rows.length;
var numCols = numCells / numRows; // skip row headings
// track which columns have rowspans by setting to 1
var matrix = new Array(numRows).fill(new Array(numCols).fill(0));
var matrix = new Array(numRows);
// init 2d matrix
for (var i = 0; i < 5; i++) {
matrix[i] = new Array(numCols);
}
//matrix[1][3] = 1; // test blocking cell
var startCol, startRow, endRow, lastValidCell;
var cellDown, cellOver, cellUp;
var mouseDown = false;
// used mouse event code from http://stackoverflow.com/a/19164149/1544886
$cells.on('mousedown touchstart', function(event) {
var cellPos;
cellDown = this;
event.preventDefault();
mouseDown = true;
cellPos = findCell(cellDown);
if (cellPos) {
startCol = cellPos.col;
startRow = endRow = cellPos.row;
highlightCells();
} else {
clearHighlights();
}
});
$cells.on('mousemove touchmove', function(event) {
event.preventDefault();
if (mouseDown && cellOver != this) {
var cellPos;
cellOver = this;
cellPos = findCell(cellOver);
if (cellPos) {
// limit to starting column only
if (cellPos.col === startCol) {
endRow = cellPos.row;
highlightCells();
}
}
}
});
$cells.on('mouseup touchend', function(event) {
var cellPos;
event.preventDefault();
cellUp = this;
cellPos = findCell(cellUp);
if (cellPos && cellUp === lastValidCell) {
createCellSpan();
}
});
$(window.document).on('mouseup touchend', function(event) {
mouseDown = false;
//cellDown = cellOver = null;
clearHighlights();
});
function findCell(cell) {
var col, row;
$cells.each(function(idx, el) {
if (cell === el) {
col = idx % numCols;
row = Math.floor(idx / numCols);
if (matrix[row][col] === 1) { // a rowspan already exists for this cell
//console.log('found', row, col);
col = null;
}
return false;
}
});
return (col != null) ? {
col: col,
row: row
} : null;
}
function highlightCells() {
clearHighlights();
if (endRow >= startRow) {
for (var row = startRow; row <= endRow; row++) {
if (matrix[row][startCol] !== 1) { // rowspan doesn't already exists for this cell
var $thisCell = $cells.eq(row * numCols + startCol);
$thisCell.addClass('highlight');
lastValidCell = $thisCell[0];
} else {
endRow = row - 1; // found a blocking cell
return false;
}
}
} else {
for (var row = startRow; row >= endRow; row--) {
if (matrix[row][startCol] !== 1) { // rowspan doesn't already exists for this cell
var $thisCell = $cells.eq(row * numCols + startCol);
$thisCell.addClass('highlight');
lastValidCell = $thisCell[0];
} else {
endRow = row + 1; // found a blocking cell
return false;
}
}
}
}
function clearHighlights() {
$cells.removeClass('highlight');
}
function createCellSpan() {
var sRow = Math.min(startRow, endRow);
var eRow = Math.max(startRow, endRow);
var rowSpan = eRow - sRow + 1;
for (var row = eRow; row >= sRow; row--) {
var $thisCell = $cells.eq(row * numCols + startCol);
if (row === sRow)
$thisCell.attr('rowspan', rowSpan).addClass('spanned');
else
$thisCell.remove();
matrix[row][startCol] = 1; // mark these cells as blocked
}
/*for (var row = sRow; row <= eRow; row++) {
var $thisCell = $cells.eq(row * numCols + startCol);
$thisCell.addClass('spanned');
matrix[row][startCol] = 1; // mark these cells as blocked
} */
}
function removeCellSpan() {
var sRow = Math.min(startRow, endRow);
var eRow = Math.max(startRow, endRow);
var rowSpan = eRow - sRow + 1;
for (var row = eRow; row >= sRow; row--) {
var $thisCell = $cells.eq(row * numCols + startCol);
var $thisRow = $('tbody tr').eq(row);
if (row === sRow) {
$thisCell.attr('rowspan', 0).removeClass('spanned');
console.log("Span Removed.");
matrix[row][startCol] = 0; // mark this cell as empty
} else {
$thisRow.append('<td><textarea cols="20" rows="5" class="appt-text"></textarea></td>');
matrix[row][startCol] = 0; // mark these cells as empty
}
}
}
$(document).on("contextmenu", "td", function(e) {
e.preventDefault();
if ($(this).hasClass('spanned') === false) {
console.log("This cell is not spanned.");
return false;
} else {
removeCellSpan();
}
});
}
#control-panel p {
display: inline;
font-size: 14px;
}
table {
font-family: Arvo, Arial, sans-serif;
border-collapse: separate !important;
border-top: 2px solid #4DC7E8;
border-left: 2px solid #4DC7E8;
border-radius: 6px;
}
.days-of-the-week th {
width: 160px;
padding-top: 10px;
padding-bottom: 10px;
text-align: center;
border-right: 2px solid #4DC7E8;
border-bottom: 2px solid #4DC7E8;
border-radius: 6px;
}
tr td, th {
border-right: 2px solid #4DC7E8;
border-bottom: 2px solid #4DC7E8;
border-radius: 6px;
}
td {
height: 50px;
}
.days-of-the-week .time-col {
width: 80px;
}
tbody th {
text-align: right;
padding: 5px 3px;
}
.highlight {
background-color: rgba(255, 108, 78, 0.3);
}
.spanned {
background-color: green;
}
.appt-text {
background-color: inherit;
border: 0px;
width: 100%;
height: 100%;
outline: none;
cursor: default;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="row" id="control-panel">
<button onclick="addAppt()" id="add-appt" title="Add Appointment">+</button>
<p>= Add Appointment</p>
</div>
<div class="row text-center">
<table id="myTable">
<thead>
<tr class="days-of-the-week">
<th scope="col" class="time-col"></th>
<th scope="col">Sunday</th>
<th scope="col">Monday</th>
<th scope="col">Tuesday</th>
<th scope="col">Wednesday</th>
<th scope="col">Thursday</th>
<th scope="col">Friday</th>
<th scope="col">Saturday</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row" class="rowHdr">10:00am</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">10:30am</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">11:00am</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">11:30am</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">12:00pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">12:30pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">1:00pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">1:30pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">2:00pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">2:30pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">3:00pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">3:30pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">4:00pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">4:30pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">5:00pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">5:30pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">6:00pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">6:30pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">7:00pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">7:30pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">8:00pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">8:30pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">9:00pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">9:30pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">10:00pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
</tbody>
</table>
</div>
我必须将我的所有代码都包含在代码段中才能运行。但它完美地说明了这个问题。
答案 0 :(得分:1)
我做了很多改变。细节太多了,但我希望你能比较之前和之后看看它们是什么。
关键一点,我选择使用display:none
隐藏单元格,而不是删除它们。这样可以在删除rowspan时更轻松地将它们带回来。
function addAppt() {
$('td').css('cursor', 'cell');
$('textarea').css('cursor', 'cell');
var $table = $("#myTable tbody");
var $rows = $table.children("tr");
var $cells = $table.find("td");
var numCells = $cells.length;
var numRows = $rows.length;
var numCols = numCells / numRows; // skip row headings
// track which columns have rowspans by setting to 1
var matrix = new Array(numRows).fill(new Array(numCols).fill(0));
var matrix = new Array(numRows);
// init 2d matrix
for (var i = 0; i < numRows; i++) {
matrix[i] = new Array(numCols);
}
//matrix[1][3] = 1; // test blocking cell
var startCol, startRow, endRow, lastValidCell;
var cellDown, cellOver, cellUp;
var mouseDown = false;
// used mouse event code from http://stackoverflow.com/a/19164149/1544886
$cells.on('mousedown touchstart', function(event) {
var cellPos;
if (event.which !== 1) return; // only continue if left mouse button
cellDown = this;
event.preventDefault();
mouseDown = true;
cellPos = findCell(cellDown);
if (cellPos) {
startCol = cellPos.col;
startRow = endRow = cellPos.row;
highlightCells();
} else {
clearHighlights();
}
});
$cells.on('mousemove touchmove', function(event) {
event.preventDefault();
if (mouseDown && cellOver != this) {
var cellPos;
cellOver = this;
cellPos = findCell(cellOver);
if (cellPos) {
// limit to starting column only
if (cellPos.col === startCol) {
endRow = cellPos.row;
highlightCells();
}
}
}
});
$cells.on('mouseup touchend', function(event) {
var cellPos;
if (event.which !== 1) return; // only continue if left mouse button
event.preventDefault();
cellUp = this;
cellPos = findCell(cellUp);
if (cellPos && cellUp === lastValidCell) {
createCellSpan();
}
});
$(window.document).on('mouseup touchend', function(event) {
mouseDown = false;
//cellDown = cellOver = null;
clearHighlights();
});
function findCell(cell, ignore) {
var col, row;
ignore = ignore | true; // set ignore to true if we haven't provided this optional param
$cells.each(function(idx, el) {
if (cell === el) {
col = idx % numCols;
row = Math.floor(idx / numCols);
if (!ignore && matrix[row][col] === 1) { // a rowspan already exists for this cell
//console.log('found', row, col);
col = null;
}
return false;
}
});
return (col != null) ? {
col: col,
row: row
} : null;
}
function highlightCells() {
clearHighlights();
if (endRow >= startRow) {
for (var row = startRow; row <= endRow; row++) {
if (matrix[row][startCol] !== 1) { // rowspan doesn't already exists for this cell
var $thisCell = $cells.eq(row * numCols + startCol);
$thisCell.addClass('highlight');
lastValidCell = $thisCell[0];
} else {
endRow = row - 1; // found a blocking cell
return false;
}
}
} else {
for (var row = startRow; row >= endRow; row--) {
if (matrix[row][startCol] !== 1) { // rowspan doesn't already exists for this cell
var $thisCell = $cells.eq(row * numCols + startCol);
$thisCell.addClass('highlight');
lastValidCell = $thisCell[0];
} else {
endRow = row + 1; // found a blocking cell
return false;
}
}
}
}
function clearHighlights() {
$cells.removeClass('highlight');
}
function createCellSpan() {
var sRow = Math.min(startRow, endRow);
var eRow = Math.max(startRow, endRow);
var rowSpan = eRow - sRow + 1;
for (var row = eRow; row >= sRow; row--) {
var $thisCell = $cells.eq(row * numCols + startCol);
if (row === sRow)
$thisCell.attr('rowspan', rowSpan).addClass('spanned');
else
$thisCell.css('display','none'); // hide instead of removing
//$thisCell.remove();
matrix[row][startCol] = 1; // mark these cells as blocked
}
/*for (var row = sRow; row <= eRow; row++) {
var $thisCell = $cells.eq(row * numCols + startCol);
$thisCell.addClass('spanned');
matrix[row][startCol] = 1; // mark these cells as blocked
} */
}
function removeCellSpan(cell) {
var sRow, eRow;
var $thisCell = $(cell);
var rowSpan = $thisCell.attr('rowspan') - 1;
var cellPos = findCell(cell, true);
if (cellPos) {
startCol = cellPos.col;
sRow = cellPos.row;
eRow = cellPos.row + rowSpan;
var $currentCells = $table.find("td");
// add back missing cells
for (var row = sRow; row <= eRow; row++) {
if (row === sRow) {
var $thisCell = $cells.eq(row * numCols + startCol);
$thisCell.attr('rowspan', 1).removeClass('spanned');
} else {
var $thisCell = $currentCells.eq(row * numCols + startCol);
$thisCell.css('display','table-cell');
}
matrix[row][startCol] = 0; // mark this cell as empty
}
}
}
$(document).on("contextmenu", "td", function(e) {
e.preventDefault();
if ($(this).hasClass('spanned') === false) {
console.log("This cell is not spanned.");
return false;
} else {
removeCellSpan(this);
}
});
}
#control-panel p {
display: inline;
font-size: 14px;
}
table {
font-family: Arvo, Arial, sans-serif;
border-collapse: separate !important;
border-top: 2px solid #4DC7E8;
border-left: 2px solid #4DC7E8;
border-radius: 6px;
}
.days-of-the-week th {
width: 160px;
padding-top: 10px;
padding-bottom: 10px;
text-align: center;
border-right: 2px solid #4DC7E8;
border-bottom: 2px solid #4DC7E8;
border-radius: 6px;
}
tr td,
th {
border-right: 2px solid #4DC7E8;
border-bottom: 2px solid #4DC7E8;
border-radius: 6px;
}
td {
height: 50px;
}
.days-of-the-week .time-col {
width: 80px;
}
tbody th {
text-align: right;
padding: 5px 3px;
}
.highlight {
background-color: rgba(255, 108, 78, 0.3);
}
.spanned {
background-color: green;
}
.appt-text {
background-color: inherit;
border: 0px;
width: 100%;
height: 100%;
outline: none;
cursor: default;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="row" id="control-panel">
<button onclick="addAppt()" id="add-appt" title="Add Appointment">+</button>
<p>= Add Appointment</p>
</div>
<div class="row text-center">
<table id="myTable">
<thead>
<tr class="days-of-the-week">
<th scope="col" class="time-col"></th>
<th scope="col">Sunday</th>
<th scope="col">Monday</th>
<th scope="col">Tuesday</th>
<th scope="col">Wednesday</th>
<th scope="col">Thursday</th>
<th scope="col">Friday</th>
<th scope="col">Saturday</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row" class="rowHdr">10:00am</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">10:30am</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">11:00am</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">11:30am</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">12:00pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">12:30pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">1:00pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">1:30pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">2:00pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">2:30pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">3:00pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">3:30pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">4:00pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">4:30pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">5:00pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">5:30pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">6:00pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">6:30pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">7:00pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">7:30pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">8:00pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">8:30pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">9:00pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">9:30pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
<tr>
<th scope="row" class="rowHdr">10:00pm</th>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
<td rowspan=""><textarea cols="20" rows="5" class="appt-text"></textarea></td>
</tr>
</tbody>
</table>
</div>