Некорректная ширина, получаемая через element.offsetWidth / scrollWidth

146
19 апреля 2022, 15:50

Написал небольшой скрипт для горизонтальной прокрутки таблицы, который еще добавляет определенней класс, когда таблица полностью прокручена, но для того, чтобы он корректно работал, нужна фактическая ширина таблицы с учетом скролла (на ней стоит css свойство overflow-x: hidden;). Но браузер, по какой-то причине, передает размеры отличные от фактических. Причем, если долго перезагружать таблицу, то иногда передаются и корректные данные. Если через инспектор выбрать элемент, то ширина всегда корректная и неизменная. В чем может быть причина?

//Горизонтальная прокрутка таблицы
document.addEventListener('DOMContentLoaded', horizontalTableScrolling);
function horizontalTableScrolling (){
    const width = document.querySelector('.wires-table__shadow');
    const scrollWidth = document.querySelector('.table__main').scrollWidth;
    const buttons = document.querySelector('.wires-table__button-wrapper');
    addClasses()
    buttons.addEventListener('click', (e) => {
        if(e.target.attributes[1].value === 'right'){
            width.scrollLeft += 40
            addClasses()
        }else if(e.target.attributes[1].value === 'left'){
            width.scrollLeft -= 40
            addClasses()
        }
    })
    function addClasses() {
        console.log(scrollWidth, width.offsetWidth, width.scrollLeft);
        if(width.scrollLeft === 0){
            width.classList.add('wires-table__shadow_left');
            width.classList.remove('wires-table__shadow_center');
        }else if(scrollWidth - width.offsetWidth === width.scrollLeft){
            width.classList.remove('wires-table__shadow_center');
            width.classList.add('wires-table__shadow_right');
        }else{
            width.classList.add('wires-table__shadow_center');
            width.classList.remove('wires-table__shadow_right', 'wires-table__shadow_left');
        }
    }
    function scrollHorizontally(e) {
        e = window.event || e;
        let delta = Math.max(-1, Math.min(1, e.wheelDelta || -e.detail));
        document.querySelector('.wires-table__shadow').scrollLeft -= delta * 40;
        e.preventDefault();
        addClasses()
    }
    if (document.querySelector('.wires-table__shadow').addEventListener) {
        // IE9, Chrome, Safari, Opera
        document.querySelector('.wires-table__shadow').addEventListener('mousewheel', scrollHorizontally, false);
        // Firefox
        document.querySelector('.wires-table__shadow').addEventListener('DOMMouseScroll', scrollHorizontally, false);
    } else {
        // IE 6/7/8
        document.querySelector('.wires-table__shadow').attachEvent('onmousewheel', scrollHorizontally);
    }
};
Answer 1

Во-первых, замените offsetWidth на clientWidth.

Должно получиться как-то так:

if(e.target.scrollLeft >= e.target.scrollWidth - e.target.clientWidth - 1){
   width.classList.remove('wires-table__shadow_center');
   width.classList.add('wires-table__shadow_right');
}

Во-вторых, addClasses лучше запускать по событию scroll, а не по событию mousewheel.

Песочница https://jsfiddle.net/q1fos0ev/

READ ALSO
inputmask isComplete all class

inputmask isComplete all class

Подскажите пожалуйста, как я могу сделать проверку на заполненость всех полей которые имеют одинаковый класс с помощью плагина inputmask? Сейчас...

173
Почему не отправляются данные в ajax запросе?

Почему не отправляются данные в ajax запросе?

Написал ajax запрос для тестирования бэкаПри отправке запроса передаются только заголовки

176
Обращение к элементу в JavaScript

Обращение к элементу в JavaScript

В jQuery обращение к элементу происходит с помощью $('#id')onEventName()= {} или $('

258
Изменение стиля Чекбокса (Checkbox JS)

Изменение стиля Чекбокса (Checkbox JS)

Помогите, пожалуйста Делается тест, в рамках которого после нажатия кнопки происходит проверка корректности ответа и правильные ответы...

174