Last active
January 4, 2021 18:18
-
-
Save amorkovin/358eeebe6ea9e22d4f4cba3ae26362c3 to your computer and use it in GitHub Desktop.
Кнопки для горизонтальной прокрутки таблицы
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// HTML | |
<div class="trading-page__pricing-table-wrap table-wrap"> | |
<div class="table-wrap__inner"> | |
<table> | |
... | |
</table> | |
</div> | |
</div> | |
// CSS | |
.table-wrap { | |
position: relative; | |
} | |
.table-wrap__inner { | |
width: 100%; | |
height: 100%; | |
overflow: scroll; | |
} | |
.table-wrap table { | |
width: 100%; | |
} | |
.table-wrap .arrow-scroll { | |
position: absolute; | |
top: 0; | |
left: 0; | |
bottom: 0; | |
width: 20px; | |
background: Silver; | |
opacity: 0.3; | |
text-indent: -9999px; | |
border: none; | |
} | |
.table-wrap .arrow-scroll:active { | |
opacity: 1; | |
} | |
.table-wrap .arrow-scroll::before { | |
content: '<'; | |
text-indent: 0; | |
color: DimGrey; | |
position: absolute; | |
top: 50%; | |
left: 50%; | |
transform: translateY(-50%) translateX(-50%); | |
} | |
.table-wrap .arrow-scroll.arrow-right { | |
left: auto; | |
right: 0; | |
} | |
.table-wrap .arrow-scroll.arrow-right::before { | |
content: '>'; | |
} | |
//JS | |
document.addEventListener("DOMContentLoaded", function () { | |
const initializedTables = manTableScrollInit(); | |
manTablesScrollInitAfterResizeBrowsr(initializedTables); | |
listenResizeBrowser(manTablesScrollInitAfterResizeBrowsr, initializedTables); | |
}); | |
function manTableScrollInit() { | |
const initializedTables = []; | |
const tables = document.querySelectorAll('.table-wrap table'); | |
if (tables.length) { | |
tables.forEach((tableItem) => { | |
const tableHeight = tableItem.clientHeight; | |
const inner = tableItem.parentElement; | |
// Прячу стандартную полосу горизонтальной прокрутки (она прячется за границами блока inner) | |
inner.style.height = tableHeight + 'px'; | |
const arrowLeft = document.createElement('button'); | |
arrowLeft.classList.add('arrow-scroll'); | |
arrowLeft.classList.add('arrow-left'); | |
arrowLeft.textContent = 'To the left'; | |
const arrowRight = document.createElement('button'); | |
arrowRight.classList.add('arrow-scroll'); | |
arrowRight.classList.add('arrow-right'); | |
arrowRight.textContent = 'To the right'; | |
inner.append(arrowLeft); | |
inner.append(arrowRight); | |
if (inner.scrollLeft === 0) { | |
arrowLeft.style.display = 'none'; | |
} else { | |
arrowLeft.style.display = 'block'; | |
} | |
if (inner.scrollWidth === inner.clientWidth) { | |
arrowRight.style.display = 'none'; | |
} else { | |
arrowRight.style.display = 'block'; | |
} | |
// Прослушиваю клики по кнопкам | |
arrowLeft.addEventListener('click', (e) => { | |
manSingleScrollBtnClick(e); | |
}); | |
arrowRight.addEventListener('click', (e) => { | |
manSingleScrollBtnClick(e); | |
}); | |
listenerScrollBarBrowserScrollTable(tableItem); | |
listenerWindowResizeForTableScroll(tableItem); | |
initializedTables.push(tableItem); | |
}); | |
} | |
return initializedTables; | |
} | |
function manTablesScrollInitAfterResizeBrowsr(initializedTables) { | |
if (!initializedTables.length) { | |
return; | |
} | |
initializedTables.forEach(tableItem => { | |
const wrapper = tableItem.parentElement; | |
const scrollRightBtn = tableItem.parentElement.querySelector('.arrow-right'); | |
const tableHeight = tableItem.clientHeight; | |
// Прячу стандартную полосу горизонтальной прокрутки (она прячется за границами блока inner) | |
wrapper.style.height = tableHeight + 'px'; | |
if (wrapper.scrollWidth === wrapper.clientWidth) { | |
scrollRightBtn.style.display = 'none'; | |
} else { | |
scrollRightBtn.style.display = 'block'; | |
} | |
}); | |
} | |
// Прослушиваю прокрутку в таблице (в том числе и стандартными свойствами браузера, не только моими кнопками) | |
function listenerScrollBarBrowserScrollTable(tableItem) { | |
const wrapper = tableItem.parentElement; | |
let last_known_scroll_position = 0; | |
let ticking = false; | |
function doSomething() { | |
manSingleScrollToggleBtn(tableItem); | |
} | |
wrapper.addEventListener('scroll', function (e) { | |
last_known_scroll_position = window.scrollY; | |
if (!ticking) { | |
window.requestAnimationFrame(function () { | |
doSomething(last_known_scroll_position); | |
ticking = false; | |
}); | |
ticking = true; | |
} | |
}); | |
} | |
// Прослушиваю изменение ширины окна браузера | |
function listenerWindowResizeForTableScroll(tableItem) { | |
(function () { | |
const throttle = function (type, name, obj) { | |
obj = obj || window; | |
let running = false; | |
const func = function () { | |
if (running) { | |
return; | |
} | |
running = true; | |
requestAnimationFrame(function () { | |
obj.dispatchEvent(new CustomEvent(name)); | |
running = false; | |
}); | |
}; | |
obj.addEventListener(type, func); | |
}; | |
/* init - you can init any event */ | |
throttle("resize", "optimizedResize"); | |
})(); | |
// handle event | |
window.addEventListener("optimizedResize", function () { | |
const wrapper = tableItem.parentElement; | |
const scrollRightBtn = tableItem.parentElement.querySelector('.arrow-right'); | |
if (wrapper.scrollWidth === wrapper.clientWidth) { | |
scrollRightBtn.style.display = 'none'; | |
} else { | |
scrollRightBtn.style.display = 'block'; | |
} | |
}); | |
} | |
// Прокручиваю таблицу при клике на кнопку прокрутки | |
function manSingleScrollBtnClick(e) { | |
const btn = e.currentTarget; | |
const table = btn.parentElement.querySelector('table'); | |
const inner = table.parentElement; | |
if (btn.classList.contains('arrow-left')) { | |
inner.scrollLeft = inner.scrollLeft - 30; | |
} | |
if (btn.classList.contains('arrow-right')) { | |
inner.scrollLeft = inner.scrollLeft + 30; | |
} | |
// Отображаю и прячу кнопки прокрутки в процессе прокрутки | |
manSingleScrollToggleBtn(table); | |
} | |
// Отображаю и прячу кнопки прокрутки в процессе прокрутки | |
function manSingleScrollToggleBtn(table) { | |
const scrollLeftBtn = table.parentElement.querySelector('.arrow-left'); | |
const scrollRightBtn = table.parentElement.querySelector('.arrow-right'); | |
const inner = table.parentElement; | |
const right_width = inner.scrollWidth - inner.scrollLeft - inner.clientWidth; | |
if (right_width === 0) { | |
scrollRightBtn.style.display = 'none'; | |
} else { | |
scrollRightBtn.style.display = 'block'; | |
} | |
if (inner.scrollLeft === 0) { | |
scrollLeftBtn.style.display = 'none'; | |
} else { | |
scrollLeftBtn.style.display = 'block'; | |
} | |
} | |
// Данную функцию я обычно сохраняю в другой файл и отправляю в нее все, что должно запуститься в момент изменения размеров окна браузера. | |
// listenResizeBrowser(manTablesScrollInitAfterResizeBrowsr, initializedTables); | |
// Прослушиваю изменение ширины окна браузера | |
function listenResizeBrowser(startFunctionNameAfterResize, args = false) { | |
(function() { | |
const throttle = function(type, name, obj) { | |
obj = obj || window; | |
let running = false; | |
const func = function() { | |
if (running) { return; } | |
running = true; | |
requestAnimationFrame(function() { | |
obj.dispatchEvent(new CustomEvent(name)); | |
running = false; | |
}); | |
}; | |
obj.addEventListener(type, func); | |
}; | |
/* init - you can init any event */ | |
throttle("resize", "optimizedResize"); | |
})(); | |
// handle event | |
window.addEventListener("optimizedResize", function() { | |
if (args !== false) { | |
startFunctionNameAfterResize(args); | |
} else { | |
startFunctionNameAfterResize(); | |
} | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment