Слияние новой функции фильтра с существующим разбиением на страницы и фильтром jQuery/Javascript

У меня возникла проблема с моей новой функцией фильтрации таблиц. Проблема возникает при выборе предложения для фильтрации. Вместо того, чтобы отображать строки из всех фильтруемых данных внутри таблицы, фильтр фильтрует видимые строки только за вычетом данных спрятанное разбиением на страницы.

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

У меня также есть другая фильтрующая функция для фильтрации по "Свободным телефонам", которая была объединена с моим методом разбивки на страницы (ниже).

Как я могу объединить этот фильтр (раскрывающийся) с моим фильтром "Бесплатные трубки" (один флажок) и методом разбивки на страницы, так что, когда я выбираю параметр для фильтрации по фильтру, он обрабатывает все данные внутри таблицы а не только видимые строки, отображаемые разбиением на страницы.

https://jsfiddle.net/51Le6o06/48/

В приведенной выше скрипте показаны обе функции фильтрации, работающие бок о бок, но они плохо работают вместе.

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

Вот jQuery и Javascript для каждой из функций.

Это новый фильтр, который не работает хорошо.

$(document).ready(function() {
    $('.filter-gift').each(filterItems);
});

function filterItems(e) {
    var items = [];
    var table = '';
    tableId = $(this).parent().parent().attr('tag')

      var listItems = "";
        listItems += "<option value=''> -Select- </option>";
        $('div[tag="' + tableId + '"] table.internalActivities .information').each(function (i) {
            var itm = $(this)[0].innerText;
            if ($.inArray(itm, items) == -1) {
                items.push($(this)[0].innerText);
                listItems += "<option value='" + i + "'>" + $(this)[0].innerText + "</option>";
            }
        });

    $('div[tag="' + tableId+ '"] .filter-gift').html(listItems);

    $('.filter-gift').change(function () {
    if($(this).val()!= "") {
        var tableIdC = $(this).parent().parent().attr('tag');

        var text = $('div[tag="' + tableIdC + '"] select option:selected')[0].text.replace(/(\r\n|\n|\r| |)/gm, "");;
            $('div[tag="' + tableIdC + '"] .product-information-row').each(function (i) {
                if ($(this).text().replace(/(\r\n|\n|\r| |)/gm, "") == text) {
                    $(this).show();
                    $(this).prev().show();
                    $(this).next().show();
                }
                else {
                    $(this).hide();
                    $(this).prev().hide();
                    $(this).next().hide();
                }
            }); 
            } else {
            $(this).parent().parent().find('table tr').show();
            }
        });     
}

Это функция фильтрации и разбиения на страницы, которую я хочу объединить с указанной выше функцией (работаю).

jQuery.fn.sortPaging = function(options) {
    var defaults = {
        pageRows: 2
    };
    var settings = $.extend(true, defaults, options);
    return this.each(function() {

        var container = $(this);
        var tableBody = container.find('.internalActivities > tbody');
        var dataRows = [];
        var currentPage = 1;
        var maxPages = 1;
        var buttonMore = container.find('.seeMoreRecords');
        var buttonLess = container.find('.seeLessRecords');
        var buttonFree = container.find('.filter-free');
        var tableRows = [];
        var maxFree = 0;
        var filterFree = buttonFree.is(':checked');
        function displayRows() {
            tableBody.empty();
            var displayed = 0;
            $.each(dataRows, function(i, ele) {
                if( !filterFree || (filterFree && ele.isFree) ) {
                    tableBody.append(ele.thisRow).append(ele.nextRow);
                    displayed++;
                    if( displayed >= currentPage*settings.pageRows ) {
                        return false;
                    };
                };
            });
        };
        function checkButtons() {
            buttonLess.toggleClass('element_invisible', currentPage<=1);
            buttonMore.toggleClass('element_invisible', filterFree ? currentPage>=maxFreePages : currentPage>=maxPages);
        };
        function showMore() {
            currentPage++;
            displayRows();
            checkButtons();
        };
        function showLess() {
            currentPage--;
            displayRows();
            checkButtons();
        };
        function changedFree() {
            filterFree = buttonFree.is(':checked');
            if( filterFree && currentPage>maxFreePages ) {
                currentPage=maxFreePages;
            };
            displayRows();
            checkButtons();
        };

        tableBody.find('.product-data-row').each(function(i, j) {
            var thisRow = $(this);
            var nextRow = thisRow.next();
            var amount = parseFloat(thisRow.find('.amount').text().replace(/£/, ''));
            var isFree = thisRow.find('.free').length;
            maxFree += isFree;
            dataRows.push({
                amount: amount,
                thisRow: thisRow,
                nextRow: nextRow,
                isFree: isFree
            });
        })

        dataRows.sort(function(a, b) {
            return a.amount - b.amount;
        });
        maxPages = Math.ceil(dataRows.length/settings.pageRows);
        maxFreePages = Math.ceil(maxFree/settings.pageRows);

        tableRows = tableBody.find("tr");

        buttonMore.on('click', showMore);
        buttonLess.on('click', showLess);
        buttonFree.on('change', changedFree);

        displayRows();
        checkButtons();

    })

};

$('.sort_paging').sortPaging();

Цели

  • Сделайте работу фильтра с работой с разбиением на страницы.
  • Сделайте фильтр одновременно с фильтром "Бесплатная трубка".

Ответ 1

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

function onFilterChange() {
    filterProducts();
    resetPagination();
    showNextPage();
}

также улучшите структуру данных:

если вы используете html в качестве источника данных, используйте атрибуты в своих основных объектах, что упростит их поиск. используйте несколько тегов tbody для группировки ваших trs:

<tbody freeTv='false' freeHandset='false' cost='200'>
    <tr>
        <td>content of product 1</td>
    </tr>
    <tr>
        <td>description of product 1</td>
    </tr>
</tbody>
<tbody freeTv='true' freeHandset='false' cost='300'>
    <tr>
        <td>content of product 2</td>
    </tr>
    <tr>
        <td>description of product 2</td>
    </tr>
</tbody>

Я предпочитаю добавлять классы к своим элементам, а не удалять/добавлять весь элемент. имейте в виду, что это вызовет беспорядок, если вы планируете использовать nth-css-styling. если вам не нужен этот отличный, хорошо отлаживаемый способ добавления взаимодействия:

function filterProducts() {
    $('tbody').addClass('filtered');
    // ... some domain-specific magic here ...
    $('tbody[freeTv="true"]').removeClass('filtered');
}

теперь вам просто нужно определение .filtered css, например:

.filtered { display: none; }

для разбивки на страницы вы можете действовать аналогичным образом. сначала скройте все (опять же с помощью css .paged { display: none; }):

function resetPagination() {
    $('tbody').addClass('paged');
    $('tbody.filtered').removeClass('paged');
}

затем покажите нужные вам (первые 10 выгружаемых страниц):

function showNextPage() {
    $('tbody.paged').slice(0, 10).removeClass('paged');
}

https://jsfiddle.net/g9zt0fan/

Ответ 2

Я решил проблему самостоятельно, начиная с нуля и используя библиотеку datatables. Я все еще работаю над этим, но код намного проще справиться.

Единственная проблема, с которой я сталкиваюсь сейчас, - это изменить стиль разбивки на страницы.

https://jsfiddle.net/6k0bshb6/16/

// This function is for displaying data from HTML "data-child-value" tag in the Child Row.
function format(value) {
      return '<div>Hidden Value: ' + value + '</div>';
  }

// Initialization of dataTable and settings.
  $(document).ready(function () {
      var dataTable = $('#example').DataTable({
       bLengthChange: false,
       "pageLength": 5,
       "pagingType": "simple",
       "order": [[ 7, "asc" ]],
       "columnDefs": [
            {
                "targets": [ 5 ],
                "visible": false,
                "searchable": true
            },
            {
                "targets": [ 6 ],
                "visible": false,
                "searchable": true
            },
            {
                "targets": [ 7 ],
                "visible": false,
                "searchable": true
            }
        ],

// Dropdown filter function for dataTable from hidden column number 5 for filtering gifts.
       initComplete: function () {
            this.api().columns(5).every(function () {
                var column = this;
                var select = $('<select><option value="">Show all</option></select>')
                    .appendTo($("#control-panel").find("div").eq(1))
                    .on('change', function () {
                    var val = $.fn.dataTable.util.escapeRegex(
                    $(this).val());
                    column.search(val ? '^' + val + '$' : '', true, false)
                        .draw();
                });
                column.data().unique().sort().each(function (d, j) {
                    select.append('<option value="' + d + '">' + d + '</option>')
                });
            });
        }
    });

// This function is for handling Child Rows.
    $('#example').on('click', 'td.details-control', function () {
          var tr = $(this).closest('tr');
          var row = dataTable.row(tr);

          if (row.child.isShown()) {
              // This row is already open - close it
              row.child.hide();
              tr.removeClass('shown');
          } else {
              // Open this row
              row.child(format(tr.data('child-value'))).show();
              tr.addClass('shown');
          }
    });

// Checkbox filter function below is for filtering hidden column 6 to show Free Handsets only.
    $('#checkbox-filter').on('change', function() {
        dataTable.draw();
    });

    $.fn.dataTable.ext.search.push(
      function( settings, data, dataIndex ) {
        var target = '£0.00';
        var position = data[6]; // use data for the position column
        if($('#checkbox-filter').is(":checked")) {
            if (target === position) {
            return true;
         }
         return false;
        }
        return true;
      }
    );
});