Javascript-форум (https://javascript.ru/forum/)
-   Events/DOM/Window (https://javascript.ru/forum/events/)
-   -   Выборка элементов querySelectorAll (https://javascript.ru/forum/events/71107-vyborka-ehlementov-queryselectorall.html)

рони 30.12.2017 23:20

Nlk,
может сделать рефакторинг, вернутся к минимальному макету и сформулировать задачу по новой, возможно дверь где-то рядом.

Nlk 31.12.2017 17:27

Цитата:

Сообщение от рони (Сообщение 474053)
Nlk,
может сделать рефакторинг, вернутся к минимальному макету и сформулировать задачу по новой, возможно дверь где-то рядом.

Спасибо.

Ребята, подскажите пожалуйста. Очень долго уже ломаю голову)
Проблема данного кода в том, что в некоторых браузерах, при единождом 'скроле' страницы, происходит сразу несколько событий. Поясню, в приведённом ниже коде при прокручивании страницы, должен активироваться последующийся блок кораллового цвета. Но в некоторых браузерах, при первом же 'скроле', у нас сразу активируется последний блок. По причине того, что за один 'скрол', класс .active успевает назначиться сразу всем последующим блокам, и остановиться на последнем.

<!DOCTYPE html><head><meta charset="UTF-8"><style>

body {min-height: 200vh;}
.page {height: 25vh; width: 100%; background: gray; border: 2px solid white;}
.active {background: coral;}

</style></head><body>
	
<section class="page"></section>
<section class="page"></section>
<section class="page"></section>
<section class="page"></section>

<script>'use strict';

window.addEventListener("DOMContentLoaded", function() {
	document.addEventListener("scroll", eventScroll);
	const pages = document.querySelectorAll(".page");
	let lastScrolled = 0;
	function showPage() {
		[].forEach.call(pages, function(el, i) {
			i == pageIndex ? el.classList.add("active") : el.classList.remove("active");
		});
	}
	let pageIndex = 0;
	showPage();
	function eventScroll() {
		let scrolled = window.pageYOffset || document.documentElement.scrollTop;
		if (scrolled < lastScrolled) {
			--pageIndex;
		} else {
			++pageIndex;
		};
		pageIndex < 0 && (pageIndex = 0);
		pageIndex > pages.length - 1 && (pageIndex = pages.length - 1);
		showPage();
		lastScrolled = scrolled;
	}
});

</script></body></html>

рони 31.12.2017 18:45

Цитата:

Сообщение от Nlk
Поясню, в приведённом ниже коде при прокручивании страницы, должен активироваться последующийся блок кораллового цвета.

как и прежде туманно ... может вам нужен блок который ближе всего к верхней части окна?
ссылка снова на плавный скролл при нажатии на кнопки клавиатуры(вниз, вверх)

рони 31.12.2017 18:55

Nlk,
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><style>

body {min-height: 200vh;}
.page {height: 25vh; width: 100%; background: gray; border: 2px solid white;}
.active {background: coral;}

</style></head><body>

<section class="page"></section>
<section class="page"></section>
<section class="page"></section>
<section class="page"></section>

<script>
window.addEventListener("DOMContentLoaded", function() {
  document.addEventListener("scroll", eventScroll);
  var pages = document.querySelectorAll(".page");
  function showPage(pageIndex) {
    [].forEach.call(pages, function(el, i) {
      i === pageIndex ? el.classList.add("active") : el.classList.remove("active");
    });
  }
  function eventScroll() {
    for (var i = 0; i < pages.length; i++) {
      if (0 < pages[i].getBoundingClientRect().top) {
        break;
      }
    }
    showPage(i);
  }
  eventScroll()
});
</script></body></html>

Nlk 31.12.2017 19:46

рони,
Заработало в Firefox, спасибо. Правда в Opera иногда прокручивает, но суть понятна спасибо большое, буду пробовать.

рони 31.12.2017 19:52

Nlk,
if (-100 < pages[i].getBoundingClientRect().top) эксперементируйте. :)

Nlk 03.01.2018 04:32

рони,
скажите пожалуйста, в приведённом ниже коде, помимо добавления класса к определённому элементу, можно ещё добавить другой класс к его двум соседним элементам справа и слева, используя методы nextElementSibling и previousElementSibling?

function showPage() {
		[].forEach.call(pages, function(el, i) {
			i == pageIndex ? el.classList.add("active") && el.nextElementSibling.classList.add("new") : el.classList.remove("active");
		});
	}

рони 03.01.2018 09:29

Nlk,
добавить можно, но как правильно отменить не знаю, алгоритм нужен или два цикла, первый для отмены всех классов второй для установки
function showPage() {
    [].forEach.call(pages, function(el, i, p) {
        el.classList.remove("active");
        el.classList.remove("new");
    });

    [].forEach.call(pages, function(el, i, p) {
     if(i == pageIndex ) {
        el.classList.add("active");
        el.nextElementSibling && el.nextElementSibling.classList.add("new");
        el.previousElementSibling  && el.previousElementSibling.classList.add("new");
        /* или так
           p[i-1] &&  p[i-1].classList.add("new");
           p[i+1] &&  p[i+1].classList.add("new");

         */
     }
    });
}

Nlk 03.01.2018 19:31

рони,
огромное вам спасибо. Извините что так часто обращаюсь к вам за помощью.
Но я снова с просьбой, когда я искал решение, касаемо уменьшения количества событий на один 'скрол' в браузере Mozilla. То натолкнулся на материал, про функцию debounce, которая не позволяет обработчику события выполниться более одного раза в заданный промежуток времени. Могу ли я проецировать это к своему коду и как?

В интернете мне попался такой пример, но я не понимаю как могу его использовать:
// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
function debounce(func, wait, immediate) {
	var timeout;
	return function() {
		var context = this, args = arguments;
		var later = function() {
			timeout = null;
			if (!immediate) func.apply(context, args);
		};
		var callNow = immediate && !timeout;
		clearTimeout(timeout);
		timeout = setTimeout(later, wait);
		if (callNow) func.apply(context, args);
	};
};

// Usage
var myEfficientFn = debounce(function() {
	// All the taxing stuff you do
}, 250);
window.addEventListener('resize', myEfficientFn);

рони 03.01.2018 19:45

Nlk,
var myEfficientFn = debounce(eventScroll, 250);
document.addEventListener("scroll", myEfficientFn );


Часовой пояс GMT +3, время: 02:23.