Как можно сделать линию привязанную к ячейке таблицы с возможностью кастомизации по сторонам?
Я делаю сайт для себя, как пет-проект, а точнее - календарь для методики Scrum. Подглядел на одном из сайтов хорошую идею реализации планировки в плане визуала, а именно - линию.
Я сделал скелет сайта, сделал таблицу и всё такое, добавил линию, написал код на JS, но он работает не так, как я хотел.
Задача заключается в следующем: Есть 12 ячеек, (24, учитывая ещё месяцы года), и в нижних 12-и (которые изначально пустые) мне нужно добавить линию, которая имеет два свойства:
- При наведении на ячейку появляется эта самая линия в полупрозрачном стиле, затем пропадает, если не подтвердить появление (при помощи ЛКМ);
- В ином случае - если уже произошло подтверждение - линия должна сохраниться и стать непрозрачной, а так же получить возможность кастомизации по сторонам (в ширину, соответственно).
По итогу, из моего кода вышло так:
- Во-первых, линия появляется изначально вне зависимости от действий пользователя;
- Во-вторых, она передаёт смысл одной из задумок (наводка на неё, действительно делает её непрозрачной), однако она по-прежнему, после того, как убирается курсор остается полупрозрачной и так же не фиксируется;
- Помимо этого она сама находится под ячейками, а не внутри неё.
const table = document.getElementById('table');
const tds = table.getElementsByTagName('td');
for (let i = 0; i < tds.length; i++) {
const td = tds[i];
const line = document.createElement('div');
line.id = `line-${i}`;
line.style.height = '5px'; // Высота линии линии
line.style.backgroundColor = 'gray'; // Цвет линии
line.style.opacity = '0.5'; // Начальная прозрачность линии
let isResizing = false;
let initialWidth;
td.appendChild(line);
td.addEventListener('mouseover', () => {
line.style.opacity = '0.5'; // Линия становится полупрозрачной при наведении
});
td.addEventListener('mouseleave', () => {
if (!isResizing) {
line.style.opacity = '0'; // Линия исчезает при покидании ячейки, если не происходит изменение размера
}
});
line.addEventListener('mousedown', (event) => {
isResizing = true;
initialWidth = line.offsetWidth;
line.style.opacity = '1'; // Линия становится непрозрачной при нажатии
});
document.addEventListener('mousemove', (event) => {
if (isResizing) {
const newWidth = initialWidth + (event.clientX - event.pageX);
line.style.width = `${newWidth}px`;
}
});
document.addEventListener('mouseup', () => {
isResizing = false;
if (td.nextElementSibling) {
td.nextElementSibling.firstChild.style.opacity = '0.5';
}
});
}
/* Основные стили */
body {
font-family: sans-serif;
margin: 0;
padding: 0;
}
header {
background-color: #f0f0f0;
padding: 20px;
text-align: center;
}
header img {
max-width: 200px;
height: auto;
}
.container {
display: flex;
max-width: 1000px;
margin: 0 auto;
padding: 20px;
}
.sidebar {
width: 250px;
background-color: #eee;
padding: 20px;
}
.sidebar ul {
list-style: none;
padding: 0;
}
.sidebar li {
margin-bottom: 10px;
}
.sidebar a {
display: block;
padding: 10px;
text-decoration: none;
color: #333;
}
.sidebar a:hover {
background-color: #ddd;
}
.main-content {
flex: 1;
padding: 20px;
}
h2 {
font-size: 24px;
margin-bottom: 20px;
}
table {
border-collapse: collapse;
width: 100%;
}
th,
td {
border: 1px solid #ddd;
padding: 8px;
}
/* Стили для отдельных разделов */
#chronology {
/* ... */
}
#backlog {
/* ... */
}
#board {
/* ... */
}
#calendar {
/* ... */
}
#list {
/* ... */
}
#goals {
/* ... */
}
/* Добавьте стили для каждого раздела, как описано в HTML-коде */
#line {
background-color: #000;
height: 5px;
transform: translateY(-50%);
border-radius: 2px;
cursor: pointer;
opacity: 0.5;
}
#line:hover {
cursor: pointer;
opacity: 0.5;
}
#line:active {
resize: both;
opacity: 1;
}
#line:active {
z-index: 100;
/* Переместить линию наверх */
cursor: move;
}
.editable:hover #line {
opacity: 0.5;
/* Полупрозрачность линии при наведении на ячейку */
}
.editable:active #line {
opacity: 1;
/* Полная непрозрачность линии при нажатии на ячейку */
}
<header>
<img src="logo.png" alt="Логотип компании">
</header>
<div class="container">
<div class="sidebar">
<ul>
<li><a href="#chronology">Хронология</a></li>
<li><a href="#backlog">Бэклог</a></li>
<li><a href="#board">Доска</a></li>
<li><a href="#calendar">Календарь</a></li>
<li><a href="#list">Список</a></li>
<li><a href="#goals">Цели</a></li>
</ul>
</div>
<div class="main-content">
<div id="chronology">
<h2>Хронология</h2>
<table id="table">
<tr>
<th>Спринты</th>
<th>Январь</th>
<th>Февраль</th>
<th>Март</th>
<th>Апрель</th>
<th>Май</th>
<th>Июнь</th>
<th>Июль</th>
<th>Август</th>
<th>Сентябрь</th>
<th>Октябрь</th>
<th>Ноябрь</th>
<th>Декабрь</th>
</tr>
<tr>
<td><input type="text" placeholder="Введите задачу спринта"></td>
<td class="editable"></td>
<td class="editable"></td>
<td class="editable"></td>
<td class="editable"></td>
<td class="editable"></td>
<td class="editable"></td>
<td class="editable"></td>
<td class="editable"></td>
<td class="editable"></td>
<td class="editable"></td>
<td class="editable"></td>
<td class="editable"></td>
<td class="editable"></td>
<tr>
<td colspan="12">
<div id="line"></div>
</td>
</tr>
</table>
</div>
</div>
</div>