Подтвердить что ты не робот

Горизонтальное обновление данных не работает над прокруткой

У меня есть большой массив, и мне нужно отобразить его в таблице. Вместо рендеринга всех элементов я обрабатываю только несколько элементов по горизонтали и по вертикали. Затем в прокрутке на основе прокрутки мыши произойдут ли значения вертикальной/горизонтальной корректировки таблицы. Но у меня две проблемы в этом

Вот проблемы с моим кодом

  • При прокрутке по горизонтали данные не обновляются.
  • Прокрутка по горизонтали также мерцает на экране.
  • Горизонтальные элементы не выравниваются должным образом.

Вот ссылка jsbin http://jsbin.com/oSOsIQe/2/edit

Вот код JS, я знаю, что код не чист, но я буду его чистить позже.

var $matrix = (function () {
function $matrix(data, holder, hidescrollbar, config) {
    var header_h = config.header || "150px";
    var data_h = config.header || "90px";
    !data && (function () {
        // Fake Data, will be removed later
        data = new Array(50000);
        for (var i = 0, l = data.length; i < l; i++) {
            var dummy = Math.random().toString(36).substring(5);
            var dum = [];
            for (var j = 0; j < 26; j++) {
                dum.push(dummy + i);
            }
            data[i] = dum;
        }
    }());
    hidescrollbar = hidescrollbar || false;
    var heightForcer = holder.appendChild(document.createElement('div'));
    heightForcer.id = "heightForcer";
    var view = null;
    //get the height of a single item
    var dimensions = (function () {
        //generate a fake item and calculate dimensions of our targets
        var div = document.createElement('div');
        div.style.height = "auto";
        div.innerHTML = "<div class='rowHeader'>fake</div><div class='rowData'>fake</div>";
        holder.appendChild(div);
        var output = {
            row: div.firstChild.offsetHeight,
            header: div.firstChild.offsetWidth,
            data: div.lastChild.offsetWidth
        }
        holder.removeChild(div);
        return output;
    })();

    function refreshWindow() {
        //remove old view
        if (view != null) {
            view.innerHTML = "";
        } else {
            //create new view
            view = holder.appendChild(document.createElement('div'));
        }
        var firstItem = Math.floor(holder.scrollTop / dimensions.row);
        var lastItem = firstItem + Math.ceil(holder.offsetHeight / dimensions.row) + 1;
        if (lastItem + 1 >= data.length) lastItem = data.length - 1;

        var hfirstItem = Math.floor(holder.scrollLeft / dimensions.data);
        var hlastItem = hfirstItem + Math.ceil(holder.offsetWidth / dimensions.data) + 1;
        if (hlastItem + 1 >= data[firstItem].length) hlastItem = data[firstItem].length - 1;

        //position view in users face
        view.id = 'view';
        view.style.top = (firstItem * dimensions.row) + 'px';
        view.style.left = (hfirstItem * dimensions.data) + 'px';
        var div;
        //add the items
        for (var index = firstItem; index <= lastItem; ++index) {
            div = document.createElement('div');
            var curData = data[index].slice(hfirstItem, hlastItem);
            div.innerHTML = '<div class="rowHeader">' + 
              curData.join('</div><div class="rowData">') +
            "</div>";
            div.className = "listItem";
            div.style.height = dimensions.row + "px";
            view.appendChild(div);
        }
        console.log('viewing items ' + firstItem + ' to ' + lastItem);
    }
    heightForcer.style.height = (data.length * dimensions.row) + 'px';
    heightForcer.style.width = (data[0].length * dimensions.data) + 'px';
    if (hidescrollbar) {
        //work around for non-chrome browsers, hides the scrollbar
        holder.style.width = (holder.offsetWidth * 2 - view.offsetWidth) + 'px';
    }
    refreshWindow();

    function delayingHandler() {
        //wait for the scroll to finish
        //setTimeout(refreshWindow, 10);
        refreshWindow();
    }
    if (holder.addEventListener) holder.addEventListener("scroll", delayingHandler, false);
    else holder.attachEvent("onscroll", delayingHandler);
}
return $matrix;
 }());

new $matrix(undefined, document.getElementById('listHolder'), false, {
  header: "150px",
  data: "90px",
  headerColumns: 2
});

Пожалуйста, помогите мне в этом.

4b9b3361

Ответ 1

РЕШЕНИЕ, концептуальное расширение моего ответа к аналогичному вопросу

CODE

function matrix(data, holder, config) {
    'use strict';

    //copy the config, substituting defaults
    config = {
        cellWidth : (config && config.cellWidth) || 150,
        rowHeight : (config && config.rowHeight) || 22,
    };

    if (!data) {
        //create 50000x26 array for data
        data = (function (length, depth) {
            var output = new Array(length);
            var startAt;

            for (var index = 0; index < length; ++index) {
                //var startAt = Math.random().toString(36).substring(5);
                var startAt = index + ':';
                output[index] = new Array(depth);

                for (var index2 = 0; index2 < depth; ++index2)
                    output[index][index2] = startAt + index2;
            }

            return output;
        })(50000, 26);
    }

    //guard against 0 length arrays
    if (data.length < 1 || data[0].length < 1)
        return;

    var areaForcer = holder.appendChild(holder.ownerDocument.createElement('div'));

    var view = null;
    function refreshWindow() {
        //remove old view
        if (view != null)
            view.innerHTML = "";
        //create new view
        else
            view = holder.appendChild(holder.ownerDocument.createElement('div'));

        var firstRow = Math.floor(holder.scrollTop / config.rowHeight);
        var lastRow = firstRow + Math.ceil(holder.offsetHeight / config.rowHeight) + 1;
        if (lastRow + 2 > data.length)
            lastRow = data.length - 1;

        var firstColumn = Math.floor(holder.scrollLeft / config.cellWidth);
        var lastColumn = firstColumn + Math.ceil(holder.offsetWidth / config.cellWidth) + 1;
        if (lastColumn + 2 > data[0].length)
            lastColumn = data[0].length - 1;

        //position view in users face
        view.id = 'view';
        view.style.top = (firstRow * config.rowHeight) + 'px';
        view.style.left = (firstColumn * config.cellWidth) + 'px';

        var row;
        var cell;
        //add the rows
        for (var index = firstRow; index <= lastRow; ++index) {
            row = view.ownerDocument.createElement('div');
            row.style.height = config.rowHeight - 2 + 'px';
            view.appendChild(row);

            //add the cells
            for (var index2 = firstColumn; index2 <= lastColumn; ++index2) {
                cell = row.ownerDocument.createElement('div');
                cell.className = 'listItem';
                cell.innerHTML = data[index][index2];
                cell.style.width = config.cellWidth - 2 + 'px';
                row.appendChild(cell);
            }
        }

        console.log('viewing items [' + firstRow + ':' + lastRow + '][' + firstColumn + ':' + lastColumn + ']');
    }

    areaForcer.style.height = (data.length * config.rowHeight) + 'px';
    areaForcer.style.width = (data[0].length * config.cellWidth) + 'px';

    refreshWindow();

    function delayingHandler() {
        //wait for the scroll to finish
        setTimeout(refreshWindow, 10);
    }

    if (holder.addEventListener)
        holder.addEventListener('scroll', delayingHandler, false);
    else
        holder.attachEvent('onscroll', delayingHandler);
}

matrix(null, document.getElementById('listHolder'), false);
html, body {
    width:100%;
    height:100%;
    padding:0;
    margin:0
}

body{
    overflow:hidden; 
}

.listItem {
    border : 1px solid gray;
    margin : 1px 0px;
    display : inline-block;
}

#listHolder {
    position:relative;
    height:100%;
    width:100%;
    background-color:#CCC;
    box-sizing:border-box;
    overflow:auto;
}

#view {
    position:absolute;
}

#view, #view * {
    overflow : hidden;
    white-space : nowrap;
}

#view > div {
    width : 100%;
}
<div id="listHolder"></div>

Просто некоторые вещи, чтобы очистить ваш код:

  • вы не используете объект в модуле OO, нет необходимости в новой/используйте функцию в качестве конструктора (и если хотите, запустите ее с помощью капитала)

  • в этот день и возраст компилятор может многое для нас сделать, нет оснований для использования имен типа "i" или "j", где "индекс" гораздо более понятен себе, а оператор if был сделан для того, что вы использовали для оператора и для (!data && /*set data*/, используйте if (!data) /*set data*/)

  • не использовать анонимные функции call-once, где они не требуются, их необходимо перекомпилировать каждый раз, когда запускается родительская функция

  • объявлять переменные за пределами циклов

  • не используйте random() (в этом случае), если код не работает, затрудняет просмотр происходящего

  • личное предпочтение посылает null функции вместо undefined и не называет функцию $matrix, когда матрица точно так же apt используйте комментарии!

  • личное предпочтение, если вы не знаете, что делаете, ++ x - это именно то, что вам нужно, а x ++ - небольшая трата ресурсов

  • потому что вы используете горизонтальную прокрутку, забудьте о скрытии полосы прокрутки

  • начать просто и не пытаться получить высоту, просто заставьте ее. такие вещи, как обнаружение высоты, являются тонкостями, зарезервированными для рабочих решений.

  • всегда использовать правильный отступ, даже если оператор if может быть записан на одной строке. Неважно, о ваших личных предпочтениях, потому что вы отправляете код в Интернете, ожидая, что другие люди помогут вам.

  • когда вы редактируете код, убедитесь, что вы обновили семантику. Например. элемент, называемый "heightForcer", теперь также манипулирует шириной, избегая этого, называя его "areaForcer"

Ответ 2

Я заметил, что ваш пример jsbin был слегка изменен и использует атрибут wheelDelta. Вот почему вы не можете различать обновление по горизонтали и по вертикали. Вам нужно использовать wheelDeltaX и wheelDeltaY, который будет зависеть от значения или нуля, в зависимости от того, прокручивается ли пользователь по вертикали или по горизонтали.

Кроме того, будьте осторожны, используя событие mousewheel, оно не соответствует стандартам, поэтому может вернуться, чтобы преследовать вас. Возможно, стоит взглянуть на источник JQuery, чтобы увидеть, как метод scroll() реализует эти обработчики. Я бы предположил, что есть таймер, который контролирует смещения прокрутки элемента, который запускает синтетические события, когда объект прокручивается. Но это полная дикая догадка. Как я уже сказал, вам лучше взглянуть на это.

Ответ 3

Проблема заключается в том, что вы подключаете событие onmousewheel к #foo, но не понимаете, что #foo имеет размер, который только содержит данные. Если вы сделаете следующее изменение (т.е. Возьмите #wrapper вместо #foo)

var listHold = document.getElementById('wrapper');

Вы заметите, что значение действительно обновляется.