Проблема с фильтрацией в JavaScript

317
29 августа 2017, 13:35

var human = document.getElementById("human"); 
var ul = document.getElementById('menuUL'); 
var li = ul.getElementsByTagName('li'); 
var a; 
 
human.onkeyup = function() { 
	var filter = human.value; 
	for(var i = 0; i < li.length; i++) { 
		a = li[i].getElementsByTagName("a")[0]; 
		if(a.innerHTML.toUpperCase().indexOf(filter) > -1) { 
			li[i].style.display = ''; 
		} 
		else { 
			li[i].style.display = 'none'; 
		} 
	} 
 
}
<div id="sorting"> 
	<input type="text" id="human" placeholder="Имя"> 
	<ul id="menuUL"> 
		<li class="header">A</li> 
		<li><a href="#">Aндрей</a></li> 
		<li><a href="#">Алексей</a></li> 
		<li><a href="#">Альдус</a></li> 
		<li class="header">Б</li> 
		<li><a href="#">Бахангин</a></li> 
		<li><a href="#">Борис</a></li> 
		<li><a href="#">Братислав</a></li> 
		<li class="header">В</li> 
		<li><a href="#">Валентин</a></li> 
		<li><a href="#">Володимир</a></li> 
		<li><a href="#">Вадим</a></li> 
	</ul> 
</div>

При вводе в input текст для фильтрации выводиться ошибка

Answer 1

Вот, исправил ваш код, вроде всё работает.

UPD: плюс я исправил ещё ваши косяки :

var filter = human.value.toUpperCase();

Нужно было так создать filter, что бы поиск работал правильней.

А сама ошибка, нужно было добавить if

if(a){
...Ваш код..
} 

human.onkeyup = function() { 
var human = document.getElementById("human"); 
var ul = document.getElementById('menuUL'); 
var li = ul.getElementsByTagName('li'); 
var a; 
var filter = human.value.toUpperCase(); 
	for(var i = 0; i < li.length; i++) { 
		a = li[i].getElementsByTagName("a")[0]; 
        if(a){ 
			if(a.innerHTML.toUpperCase().indexOf(filter) > -1) { 
				li[i].style.display = ""; 
			} 
		    else { 
				li[i].style.display = "none"; 
		    } 
        } 
	} 
 
}
<div id="sorting"> 
	<input type="text" id="human" placeholder="Имя"> 
	<ul id="menuUL"> 
		<li class="header">A</li> 
		<li><a href="#">Aндрей</a></li> 
		<li><a href="#">Алексей</a></li> 
		<li><a href="#">Альдус</a></li> 
		<li class="header">Б</li> 
		<li><a href="#">Бахангин</a></li> 
		<li><a href="#">Борис</a></li> 
		<li><a href="#">Братислав</a></li> 
		<li class="header">В</li> 
		<li><a href="#">Валентин</a></li> 
		<li><a href="#">Володимир</a></li> 
		<li><a href="#">Вадим</a></li> 
	</ul> 
</div>

Answer 2

разберем текскт ошибки:

{
  "message": "Uncaught TypeError: Cannot read property 'innerHTML' of undefined",
  "filename": "https://stacksnippets.net/js",
  "lineno": 38,
  "colno": 7
}

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

и даже указана строка, в которой произошла ошибка

    if(a.innerHTML.toUpperCase().indexOf(filter) > -1) {

соответственно, в каком-то случае a у нас может быть неопределенно.

Для начала ответим на вопрос: что такое a

a = li[i].getElementsByTagName("a")[0];

a - это ссылка внутри тега <li>

проблема в том, что НЕ В КАЖДОМ <li>...</li> есть ссылка

например

<li class="header">Б</li>

Соответственно,когда вы пытаетесь обратиться к ссылке внутри данного пункта списка, происходит ошибка, т.к. вы пытаетесь обратиться к объекту которого нет.

Что делать?

ответ простой:

поставить проверку перед тем как обращаться к данной переменной:

if (typeof a != 'undefined'){
   //...
}

В Вашем случае удобнее будет использовать условие от противного и наоборот пропустить даную итерацию цикла, если данный элемент неопределен: то есть:

    if(typeof a == 'undefined')
       continue;

И как справедливо заметил Alisher Yerkimbekov, у Вас недочёт в строке:

var filter = human.value;

Ошибка в том, что текст ссылок при проверке у Вас приводится к верхнему регистру, в то время как текст, который вы вводите остаётся без изменений. Для корректного поиска его стоит тоже привести к верхнему регистру

var filter = human.value.toUpperCase();

В ИТОГЕ:

var human = document.getElementById("human"); 
var ul = document.getElementById('menuUL'); 
var li = ul.getElementsByTagName('li'); 
var a; 
 
human.onkeyup = function() { 
	var filter = human.value.toUpperCase(); 
	for(var i = 0; i < li.length; i++) { 
		a = li[i].getElementsByTagName("a")[0]; 
		if(typeof a == 'undefined') 
		    continue; 
		if(a.innerHTML.toUpperCase().indexOf(filter) > -1) { 
			li[i].style.display = ''; 
		} 
		else { 
			li[i].style.display = 'none'; 
		} 
	} 
 
}
<div id="sorting"> 
	<input type="text" id="human" placeholder="Имя"> 
	<ul id="menuUL"> 
		<li class="header">A</li> 
		<li><a href="#">Aндрей</a></li> 
		<li><a href="#">Алексей</a></li> 
		<li><a href="#">Альдус</a></li> 
		<li class="header">Б</li> 
		<li><a href="#">Бахангин</a></li> 
		<li><a href="#">Борис</a></li> 
		<li><a href="#">Братислав</a></li> 
		<li class="header">В</li> 
		<li><a href="#">Валентин</a></li> 
		<li><a href="#">Володимир</a></li> 
		<li><a href="#">Вадим</a></li> 
	</ul> 
</div>

READ ALSO
Как заключить обширный html в переменную? [дубликат]

Как заключить обширный html в переменную? [дубликат]

На данный вопрос уже ответили:

202
Как в instantcms открыть права гостю

Как в instantcms открыть права гостю

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

225
Помогите довести до ума for

Помогите довести до ума for

Суть такая, извлекаю из бд многомерный массив далее проверяю на присутствие $users['tt'] !in_array($i, $users), если есть такой id ($users['tt']) то вставляю данные...

188
WordPress Methods

WordPress Methods

Что возвращает метод the_post_thumbnail() в wordpress если указать изображение которое не существует?

356