Управление DOM с помощью JavaScript в современных браузерах и IE 11+
Предположим, что мы хотим изменить размер любого столбца следующей таблицы:
<table id="resizeMe" class="table">
...
</table>
Для каждого столбца мы вставляем div
элемент, указывающий, что размер соответствующего столбца можно изменить. Элемент resizer
расположен абсолютно внутри столбца. Стили CSS для них будут такими:
.table th {
position: relative;
}
.resizer {
/* Displayed at the right side of column */
position: absolute;
top: 0;
right: 0;
width: 5px;
cursor: col-resize;
user-select: none;
}
Чтобы создать изменяющие размеры и добавить их в столбцы, мы должны выполнить запрос и выполнить цикл по всем столбцам:
// Query the table
const table = document.getElementById('resizeMe');
// Query all headers
const cols = table.querySelectorAll('th');
// Loop over them
[].forEach.call(cols, function(col) {
// Create a resizer element
const resizer = document.createElement('div');
resizer.classList.add('resizer');
// Set the height
resizer.style.height = `${table.offsetHeight}px`;
// Add a resizer element to the column
col.appendChild(resizer);
// Will be implemented in the next section
createResizableColumn(col, resizer);
});
Мы собираемся реализовать функцию createResizableColumn
, которая принимает два параметра:
col
который представляет заголовок таблицыresizer
который представляет элемент resizer в столбцеЧтобы позволить пользователю изменить размер col, мы должны обработать три события:
mousedown
на изменение размера: отслеживать текущую позицию мышиmousemove
у document: вычислить, насколько далеко была перемещена мышь, и отрегулировать ширину столбцаmouseup
у document: Удалить обработчики событийdocumentconst createResizableColumn = function(col, resizer) {
// Track the current position of mouse
let x = 0;
let w = 0;
const mouseDownHandler = function(e) {
// Get the current mouse position
x = e.clientX;
// Calculate the current width of column
const styles = window.getComputedStyle(col);
w = parseInt(styles.width, 10);
// Attach listeners for document's events
document.addEventListener('mousemove', mouseMoveHandler);
document.addEventListener('mouseup', mouseUpHandler);
};
const mouseMoveHandler = function(e) {
// Determine how far the mouse has been moved
const dx = e.clientX - x;
// Update the width of column
col.style.width = `${w + dx}px`;
};
// When user releases the mouse, remove the existing event listeners
const mouseUpHandler = function() {
document.removeEventListener('mousemove', mouseMoveHandler);
document.removeEventListener('mouseup', mouseUpHandler);
};
resizer.addEventListener('mousedown', mouseDownHandler);
};
Мы можем немного улучшить пользовательский опыт. Когда пользователь наводит курсор мыши или щелкает по нему, он может быть выделен. Чтобы продемонстрировать идею самым простым способом, мы добавляем сплошную границу к селектору :hover
:
.resizer:hover, .resizing {
border-right: 2px solid blue;
}
Класс resizing
добавляется к Resizer в то время как пользователь нажимает и тащит Resizer:
const mouseDownHandler = function(e) {
...
resizer.classList.add('resizing');
};
const mouseUpHandler = function() {
...
resizer.classList.remove('resizing');
};