Фильтр таблицы. Как удалить элемент из массива?
Изучаю JavaScript.
Решил создать фильтр для таблицы, неопределенного размера (наподобие того что есть в Excel). Не удается удалить параметр из массива. После первого клика по фильтру, параметр успешно добавляется в массив (добавление параметров вроде бы работает), второй щелчок по этому же параметру удаляет его из массива, но остается длинна i-того массива равной единице. Последующие щелчки в этом же столбце творят ужас. Не пойму что я делаю не правильно. Подскажите пожалуйста как решить данную проблему. Вот сам код, который подробно прокомментировал: <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/html"> <head lang="ru"> <meta charset="UTF-8"> <title>First</title> <link rel="stylesheet" href="style.css"/> <style> table { border-collapse: collapse; font-family: "Arial", sans-serif; font-size: 0.9em; margin: 50px; position: relative; } td { border: 1px solid black; width: 150px; padding: 5px; } thead { background-color: coral; font-weight: bold; } .select-group { font-weight: normal; font-style: italic; display: none; position: absolute; background-color: burlywood; width: 150px; padding: 5px; border: 1px solid black; top: 33px; } td:hover > .select-group { display: block; } thead:hover { cursor: pointer; } .second-name { left: 0; } .first-name { left: 161px; } .otch { left: 322px; } .select-item { padding: 5px 0; border-bottom: 1px solid black; } .select-item:hover { background-color: darkkhaki; } span { background-color: #fff; padding: 3px; width: 144px; display: block; } label { display: block; } </style> <script type="text/javascript"> var selectGroup = document.getElementsByClassName("select-group"), tr = document.querySelectorAll("tbody tr"), tHead = document.getElementsByTagName("thead"), colParam = new Array(selectGroup.length),// массив в котором будут храниться параметры выбора numParam = 0; function show() { // переберем блоки с input'ами for (var i = 0; i < selectGroup.length; i++) { // теперь переберем сами input'ы в этих блоках for (var j = 0; j < selectGroup[i].querySelectorAll("input").length; j++) { //создадим переменную в которой будет хранится один input var hasChecked = selectGroup[i].querySelectorAll("input")[j]; //если input выбран if (hasChecked.checked) { то если массив с параметрами пуст if (colParam[i] == undefined || colParam[i].length == 0) { /*то создадим i-тым (i - это номер столбца) элементом массив в который занесем значение выбранного input'а*/ colParam[i] = new Array(hasChecked.value); } else { //если массив с параметрами не пуст, то переберем его for (var r = 0; r < colParam[i].length; r++) { if (colParam[i][r] != hasChecked.value) { /* r - номер параметрам в i-том столбце и если значения выбранного input'а нет в массиве с параметрами, то заносим это значение*/ colParam[i].push(hasChecked.value); } else { break; } } } } else { /*вот тут у меня и начинается беда Проверяем не пуст ли массив с параметрами */ if (colParam[i] != undefined) { //если не пуст то переберем все его значения for (var v = 0; v < colParam[i].length; v++) { if (colParam[i][numParam] == hasChecked.value) { // и если значение есть в массиве, то удаляем его colParam[i].splice(v, 1); } else { break; } } } else { break; } } } } } //Функция запускается по клику на шапке таблицы tHead[0].addEventListener("click", show); </script> </head> <body> <table> <thead> <tr> <td> <span>Фамилия</span> <div class="select-group second-name"> <label><input class="select-item col11" type="checkbox" value="Епихин">Епихин</label> <label><input class="select-item col11" type="checkbox" value="Буртовой">Буртовой</label> </div> </td> <td> <span>Имя</span> <div class="select-group first-name"> <label><input class="select-item col11" type="checkbox" value="Александр">Александр</label> <label><input class="select-item col11" type="checkbox" value="Евгений">Евгений</label> <label><input class="select-item col11" type="checkbox" value="Сергей">Сергей</label> </div> </td> <td> <span>Отчество</span> <div class="select-group otch"> <label><input class="select-item col11" type="checkbox" value="Валерьевич">Валерьевич</label> <label><input class="select-item col11" type="checkbox" value="Олегович">Олегович</label> <label><input class="select-item col11" type="checkbox" value="Анатольевич">Анатольевич</label> </div> </td> </tr> </thead> <tbody> <tr> <td class="col1">Епихин</td> <td class="col2">Александр</td> <td class="col3">Валерьевич</td> </tr> <tr> <td class="col1">Буртовой</td> <td class="col2">Евгений</td> <td class="col3">Олегович</td> </tr> <tr> <td class="col1">Епихин</td> <td class="col2">Александр</td> <td class="col3">Анатольевич</td> </tr> <tr> <td class="col1">Епихин</td> <td class="col2">Сергей</td> <td class="col3">Валерьевич</td> </tr> <tr> <td class="col1">Буртовой</td> <td class="col2">Александр</td> <td class="col3">Олегович</td> </tr> </tbody> </table> </body> </html> P.S. Если не правильно или неудобно оформил тему то скажите как исправить. |
leshiple,
строка 140 цикл в никуда??? 145 для удаления есть splice |
Цитата:
мой вариант на сон грядущий, код жутковат, но вроде бы работает :) <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/html"> <head lang="ru"> <meta charset="UTF-8"> <title>First</title> <link rel="stylesheet" href="style.css"/> <style> table { border-collapse: collapse; font-family: "Arial", sans-serif; font-size: 0.9em; margin: 50px; position: relative; } td { border: 1px solid black; width: 150px; padding: 5px; } thead { background-color: coral; font-weight: bold; } .select-group { font-weight: normal; font-style: italic; display: none; position: absolute; background-color: burlywood; width: 150px; padding: 5px; border: 1px solid black; top: 33px; } td:hover > .select-group { display: block; } thead:hover { cursor: pointer; } .second-name { left: 0; } .first-name { left: 161px; } .otch { left: 322px; } .select-item { padding: 5px 0; border-bottom: 1px solid black; } .select-item:hover { background-color: darkkhaki; } span { background-color: #fff; padding: 3px; width: 144px; display: block; } label { display: block; } </style> <script type="text/javascript"> document.addEventListener("DOMContentLoaded", function () { function closest (elem, selector) { while (elem && elem.tagName != selector) { elem = elem.parentNode; } return elem; } Array.prototype.map.call(document.querySelector("table").querySelectorAll("input[type=checkbox"), function (inp) { inp.checked = true; }); document.querySelector("table").addEventListener("click", function (event) { var target = event.target; if ( target.type && target.type == "checkbox" ) { var td = closest(target, "TD"); var index = td.cellIndex; var inps = td.querySelectorAll("input:checked"); var vals = Array.prototype.map.call(inps, function (inp) { return inp.value; }); var trs = this.querySelector("tbody").querySelectorAll("tr"); Array.prototype.map.call(trs, function (tr ) { if ( !tr.isHiddenByCol ) tr.isHiddenByCol = []; if ( vals.indexOf(tr.cells[index].innerHTML) == -1 ) { tr.style.display = "none"; if ( tr.isHiddenByCol.indexOf(index) == -1 ) tr.isHiddenByCol.push(index); } else if ( tr.isHiddenByCol.indexOf(index) != -1 ) { tr.isHiddenByCol.splice(tr.isHiddenByCol.indexOf(index), 1); if ( tr.isHiddenByCol.length == 0 ) { tr.style.display = ""; } } }); } }); }); </script> </head> <body> <table> <thead> <tr> <td> <span>Фамилия</span> <div class="select-group second-name"> <label><input class="select-item col11" type="checkbox" value="Епихин">Епихин</label> <label><input class="select-item col11" type="checkbox" value="Буртовой">Буртовой</label> </div> </td> <td> <span>Имя</span> <div class="select-group first-name"> <label><input class="select-item col11" type="checkbox" value="Александр">Александр</label> <label><input class="select-item col11" type="checkbox" value="Евгений">Евгений</label> <label><input class="select-item col11" type="checkbox" value="Сергей">Сергей</label> </div> </td> <td> <span>Отчество</span> <div class="select-group otch"> <label><input class="select-item col11" type="checkbox" value="Валерьевич">Валерьевич</label> <label><input class="select-item col11" type="checkbox" value="Олегович">Олегович</label> <label><input class="select-item col11" type="checkbox" value="Анатольевич">Анатольевич</label> </div> </td> </tr> </thead> <tbody> <tr> <td class="col1">Епихин</td> <td class="col2">Александр</td> <td class="col3">Валерьевич</td> </tr> <tr> <td class="col1">Буртовой</td> <td class="col2">Евгений</td> <td class="col3">Олегович</td> </tr> <tr> <td class="col1">Епихин</td> <td class="col2">Александр</td> <td class="col3">Анатольевич</td> </tr> <tr> <td class="col1">Епихин</td> <td class="col2">Сергей</td> <td class="col3">Валерьевич</td> </tr> <tr> <td class="col1">Буртовой</td> <td class="col2">Александр</td> <td class="col3">Олегович</td> </tr> </tbody> </table> </body> </html> |
рони,
Спасибо за подсказку. В строках 117 и 140 были циклы в никуда. Исправил. Невнимательность и запутался в коде. В строке 145 delete заменил на splice. bes, Спасибо за критику. А как его сделать менее жутковатым? Каждое действие сделать отдельной функцией, и в функции show() вызывать их? Или использовать другие конструкции? |
Цитата:
как сделать менее жутковатым - оптимизировать, например, у меня заменить this.querySelector("tbody").querySelectorAll("tr");на this.querySelectorAll("tbody tr"); + важна сама идея вычислений, моя чую не совсем хороша :) |
bes,
Можете свой код показать? |
Цитата:
|
bes,
Туплю. Можешь вкратце прокомментировать свой код? Я не совсем понимаю как он работает. |
Цитата:
для хранения информации о том, что строка скрыта посредством фильтра в определённом столбце, для неё задаётся свойство-массив, в котором хранятся индексы этих столбцов, если индекса столбца в этом свойстве-массиве строки нет, то фильтр этого столбца на эту строку не распространяется |
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/html"> <head lang="ru"> <meta charset="UTF-8"> <title>First</title> <style> table { border-collapse: collapse; font-family:"Arial", sans-serif; font-size: 0.9em; margin: 50px; position: relative; } td { border: 1px solid black; width: 150px; padding: 5px; } thead { background-color: coral; font-weight: bold; } .select-group { font-weight: normal; font-style: italic; display: none; position: absolute; background-color: burlywood; width: 150px; padding: 5px; border: 1px solid black; top: 33px; } td:hover > .select-group { display: block; } thead:hover { cursor: pointer; } .second-name { left: 0; } .first-name { left: 161px; } .otch { left: 322px; } .select-item { padding: 5px 0; border-bottom: 1px solid black; } .select-item:hover { background-color: darkkhaki; } span { background-color: #fff; padding: 3px; width: 144px; display: block; } label { display: block; } </style> </head> <body> <table> <thead> <tr> <td> <span>Фамилия</span> <div class="select-group second-name"> <label> <input class="select-item col11" type="checkbox" value="Епихин" data-type="surname">Епихин</label> <label> <input class="select-item col11" type="checkbox" value="Буртовой" data-type="surname">Буртовой</label> </div> </td> <td> <span>Имя</span> <div class="select-group first-name"> <label> <input class="select-item col11" type="checkbox" value="Александр" data-type="name">Александр</label> <label> <input class="select-item col11" type="checkbox" value="Евгений" data-type="name">Евгений</label> <label> <input class="select-item col11" type="checkbox" value="Сергей" data-type="name">Сергей</label> </div> </td> <td> <span>Отчество</span> <div class="select-group otch"> <label> <input class="select-item col11" type="checkbox" value="Валерьевич" data-type="middle">Валерьевич</label> <label> <input class="select-item col11" type="checkbox" value="Олегович" data-type="middle">Олегович</label> <label> <input class="select-item col11" type="checkbox" value="Анатольевич" data-type="middle">Анатольевич</label> </div> </td> </tr> </thead> <tbody> <tr> <td class="col1">Епихин</td> <td class="col2">Александр</td> <td class="col3">Валерьевич</td> </tr> <tr> <td class="col1">Буртовой</td> <td class="col2">Евгений</td> <td class="col3">Олегович</td> </tr> <tr> <td class="col1">Епихин</td> <td class="col2">Александр</td> <td class="col3">Анатольевич</td> </tr> <tr> <td class="col1">Епихин</td> <td class="col2">Сергей</td> <td class="col3">Валерьевич</td> </tr> <tr> <td class="col1">Буртовой</td> <td class="col2">Александр</td> <td class="col3">Олегович</td> </tr> </tbody> </table> <script> window.onload = function () { var cache = { surname: {}, name: {}, middle: {} }, s, n, m, tr, tbl = document.querySelector("table"), dataTr = tbl.querySelectorAll("tbody tr"); for (var i = 0; i < dataTr.length; ++i) { tr = dataTr[i]; s = tr.cells[0].innerHTML; n = tr.cells[1].innerHTML; m = tr.cells[2].innerHTML; if (!cache.surname.hasOwnProperty(s)) { cache.surname[s] = []; tbl.querySelector("input[data-type=surname][value='" + s + "']").checked = true; } if (!cache.name.hasOwnProperty(n)) { cache.name[n] = []; tbl.querySelector("input[data-type=name][value='" + n + "']").checked = true; } if (!cache.middle.hasOwnProperty(m)) { cache.middle[m] = []; tbl.querySelector("input[data-type=middle][value='" + m + "']").checked = true; } cache.surname[s].push(tr); cache.name[n].push(tr); cache.middle[m].push(tr); } tbl.onclick = function (e) { var el = e ? e.target : window.event.srcElement; if (el.tagName != "INPUT" || el.type != 'checkbox') return; var type = cache[el.getAttribute('data-type')][el.value]; for (var i = 0; i < type.length; ++i) { type[i].style.display = el.checked ? "" : "none"; } } }; </script> </body> </html> еще вариант, но и он далек от идеала. Не совсем понятна логика. Переключение Имя,фамилия, отчество. Какой порядок должен быть |
Плагин для фильтрации строк таблиц
:write:
заголовки делаются стандартно - строки 77 - 84 добавлен параметр исключения колонок из фильтрации - это массив с номерами исключаемых колонок, либо ничего не указывайте. Пример: Фильтр для таблицы
<!DOCTYPE HTML> <html> <head> <title>Untitled</title> <meta charset="utf-8"> <style type="text/css"> body{height:1000px;background:#FF8C00;font-family:Georgia,"Times New Roman",Times,serif;letter-spacing:1px} .zebra select{margin:0px auto;width:100%;background:#CCC;color:#FFF} .zebra select option {color: #ff0;background: #000;} .zebra select option:nth-of-type(1) {color: #FFFFFF;background: #000;} .zebra td{border:1px solid #555555;color:#FFF;padding:5px;text-align:left;background:#000} .zebra tr:nth-child(2n) td{background:#383838} .zebra thead td:hover{background-image:-webkit-gradient(linear,top,bottom,color-stop(0,#E6E6FA),color-stop(1,#696969));background-image:-ms-linear-gradient(top,#E6E6FA,#696969);background-image:-o-linear-gradient(top,#E6E6FA,#696969);background-image:-moz-linear-gradient(top,#E6E6FA,#696969);background:-webkit-linear-gradient(top,#E6E6FA,#696969);background:linear-gradient(to bottom,#E6E6FA,#696969)} .zebra thead tr td{padding:5px;font-weight:bold;background-image:-webkit-gradient(linear,top,bottom,color-stop(0,#000000),color-stop(1,#CCCCCC));background-image:-o-linear-gradient(top,#000000,#CCCCCC);background-image:-moz-linear-gradient(top,#000000,#CCCCCC);background-image:-webkit-linear-gradient(top,#000000,#CCCCCC);background:linear-gradient(to bottom,#000000,#CCCCCC)} .zebra tbody tr:hover td{background-image:-webkit-gradient(linear,left,right,color-stop(0,#D2691E),color-stop(1,#DEB887));background-image:-ms-linear-gradient(left,#D2691E,#DEB887);background-image:-o-linear-gradient(left,#D2691E,#DEB887);background-image:-moz-linear-gradient(left,#D2691E,#DEB887);background:-webkit-linear-gradient(left,#D2691E,#DEB887);background:linear-gradient(to right,#D2691E,#DEB887)} table.zebra{border-collapse:collapse;border-spacing:0;box-shadow:0 2px 1px 5px rgba(242,242,242,0.1);width:700px;margin:0px auto} </style> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> <script> $(function () { $("table").tablework([0,2]); //указать исключаемые колонки и без параметров }); $.fn.tablework = function(arr) { return this.each(function() { var $table = $(this), $trs = $table.find("tbody tr"), $thead = $table.find('thead'); $thead.length || ($thead = $('<thead/>').prependTo($table)); var $tr = $('<tr/>').prependTo($thead), hide = {}; $("td", $trs.first()).each(function(indx, element) { var options = [$('<option/>', { 'text': 'Без выбора' })], $td = $trs.find(":nth-child(" + (indx + 1) + ")"), temp = {}; $td.each(function(i, el) { var text = $(el).text(); temp[text] || ( options.push($('<option/>', { 'text': text })), temp[text] = true ); }); var $select = $('<select/>', { multiple: "multiple", html: options, 'change': function() { var val = $(this).val() || []; hide[indx] = []; this.selectedIndex && $td.each(function(i, el) { $.inArray($(el).text(), val) == -1 && hide[indx].push($trs[i]) }); var trs = []; for (var k in hide) $.merge(trs, hide[k]); $.unique(trs); $trs.show(); $(trs).hide() } }); var td = $('<td/>').appendTo($tr); if(!arr || $.inArray(indx, arr)==-1 ) td.append($select); }); }); }; </script> </head> <body> <br> <table class="zebra" > <thead> <tr> <th>№</th> <th>Title 1</th> <th>Title 2</th> <th>Title 3</th> </tr> </thead> <tbody> <tr><td>1</td> <td class="col1">Епихин</td> <td class="col2">Александр</td> <td class="col3">Валерьевич</td> </tr> <tr> <td>2</td> <td class="col1">Буртовой</td> <td class="col2">Евгений</td> <td class="col3">Олегович</td> </tr> <tr><td>3</td> <td class="col1">Епихин</td> <td class="col2">Александр</td> <td class="col3">Анатольевич</td> </tr> <tr> <td>4</td> <td class="col1">Епихин</td> <td class="col2">Сергей</td> <td class="col3">Валерьевич</td> </tr> <tr><td>5</td> <td class="col1">Буртовой</td> <td class="col2">Александр</td> <td class="col3">Олегович</td> </tr> </tbody> </table> </body> </html> |
Цитата:
|
Цитата:
Но он прост, в нем видны повторяющиеся блоки и понятно, что надо оптимизировать |
bes,
Благодарю за разъяснения, но для меня подобные конструкции пока еще сложные. Особенно строки с прототипирование и их методами. Poznakomlus, Спасибо что уделил внимание. Оказывается у одной задачи есть много решений. У тебя не совсем правильно работает код. Например если снять выделение с одной фамилии и со всех отчеств, а потом начать отмечать отчества, то появятся строки с фамилией которая не выбрана. рони, Спасибо, круто. Но тут нет возможности множественного выбора. Мой код в сравнении с вашими слишком примитивный. Пойду читать матчасть. |
Цитата:
<select multiple>...</select> |
Цитата:
var trs = this.querySelectorAll("tbody tr"); Array.prototype.map.call(trs, function (tr ) { если бы querySelectorAll возвращал обычный массив, то можно было бы сделать так trs.map(function (tr) { иначе приходится вызывать этот метод в контексте trs посредством call или apply итого: остаётся только понять что такое map :) https://developer.mozilla.org/ru/doc...ects/Array/map |
:write: добавил множественный выбор в плагин фильтрации строк таблицы ... Ctrl и Shift ... смотреть 11 пост ... для любого количества строк,колонок и самих таблиц
|
bes,
То есть метод map пройдет по массиву trs и и выполнит функцию function (tr) для каждого элемента массива на подобии цикла, а параметр tr и будет элементом массива trs и результатом будет новый массив в который под соответствующими индексами добавятся результаты выполнения функции function (tr)? |
Цитата:
на попадание в результирующий массив влияет наличие return в теле callback-функции, если return-а нет, то туда попадут одни undefined-ы + callback-функции можно передать ещё пару параметров помимо ссылки на текущий элемент |
Это круто.
var arr = [1, 2, 3]; arr = arr.map(function (el) { el++; return el; }); alert(arr); bes, если я правильно понял статью, ссылку на которую вы мне дали, то Array.prototype можно заменить на [] |
Цитата:
// мини j :-) function $(name, element) { var el = (element || document).querySelectorAll(name); return el ? (el.length > 1 ? Array.apply(null, el) : el[0]) : []; } |
Цитата:
var arr = [1, 2, 3]; var arr1 = ["a", "b", "c"]; var mas = arr1.map.call(arr, function (el) { return el; }); alert(mas); |
if (!Array.prototype.map) { Array.prototype.map = function (fn, scope) { var tmp = []; for (var i = 0, len = this.length; i < len; ++i) { tmp.push(fn.call(scope, this[i], i, this)); } return tmp; } } var arr = [1, 2, 3]; var arr1 = ["a", "b", "c"]; var mas = arr1.map.call(arr, function (el) { return el; }); alert(mas); var sas = arr.map(function (el) { return ++el; }); alert(sas);:dance: |
bes, зачем здесь:
var mas = arr1.map.call(arr, function (el) { return el; }); arr1? Чем он "лучше" чем Array.prototype или []? Он же никак никак не влияет на выполнение функции и к нему внутри функции кроме как по имени не обратишься. Или я ошибаюсь? Poznakomlus на developer.mozilla.org я прочитал что твоя первая конструкция в посте №23 это полифилл. Как я могу проверить работоспособность твоего кода (в каких случаях метод map будет отсутствовать)? Мне нужен старый браузер или в коде как-то объявить версию языка? |
Цитата:
Цитата:
для проверки убери проверку на существование, метод map будет переопределён |
Я думал что к этому массиву можно обратиться внутри функции через this
|
Цитата:
|
Чтобы установить свой контекст нужно третьим аргументом у метода call установить необходимый объект.
Я хочу посредством этой конструкции сложить элементы двух массивов без цикла. |
Цитата:
навскиду можно так var arr1 = [1, 2, 3]; var arr2 = ["a", "b", "c"]; var result = arr1.map(function (val, index) { return val + arr2[index]; }); alert(result); |
bes,
Да, у map. Проглядел. Спасибо. |
Часовой пояс GMT +3, время: 06:45. |