| 
	| 
	
	| 
		
	| 
			
			 
			
				02.03.2020, 14:21
			
			
			
		 |  
	| 
		
			
			| Интересующийся       |  | 
					Регистрация: 16.09.2013 
						Сообщений: 28
					 
		
 |  |  
	| 
				Остановка одного из нескольких интервалов
			 Здравствуйте. Помогите пожалуйста. Обидно осознавать, но похоже своим мозгом я это уже не осилю. Всю ночь потратил на попытки    .
 
На странице имеется три блока с баннерами (.banners). Хочу добавить автолисталку для них, чтобы они менялись через определённый интервал.
 
Делаю вот так:
 
var interval, timer = 1000;
function startInterval(e) {            
    var cur = parseInt(e.find('.banner.visible').attr('id').replace(/\D+/g,""));
    var col = e.find('.banner').length;
    interval = setInterval(function(){   
       if (cur < col) {cur++} else {cur = 1}  
           e.find('.banner').removeClass('visible');
           e.find('.banner#banner'+cur).addClass('visible'); 
        },timer);
};        
$('.banners').each(function(){startInterval($(this));});
Всё круто, всё листается. Но мне нужно сделать, чтобы при наведении мыши это перелистывание останавливалось в соответствующем блоке с баннерами. И соответственно запускалось  когда мышки на баннере нет. 
 
Этот код не помогает в этом (
 
$('.banners').mouseenter(function(){clearInterval(interval);}); 
$('.banners').mouseleave(function(){startInterval();});
Ну тут понятно, что он запуститься не сможет, так как не ясно к какому блоку баннеров относится startInterval(); после mouseleave.
 
Но оно даже не останавливается при mouseenter и clearInterval не срабатывает.
 
Подумал, что в коде непонятно какой именно интервал останавливать. Стал копать в сторону идентификации интервалов, чтобы при попытке остановки обращаться более адресно.  
Намутил вот такое:
 
var interval = [], timer = 1000;
function startInterval(e,i) {            
    var cur = parseInt(e.find('.banner.visible').attr('id').replace(/\D+/g,""));
    var col = e.find('.banner').length;
    i = setInterval(function(){   
       if (cur < col) {cur++} else {cur = 1}  
           e.find('.banner').removeClass('visible');
           e.find('.banner#banner'+cur).addClass('visible'); 
        },timer);
};   
for(var i = 0; i < $('.banners').length; i++) { 
    interval[i] = 'interval'+i;
    $('.banners').eq(i).attr('data',i);
    startInterval($('.banners').eq(i),interval[i]);                        
}
$('.banners').mouseenter(function(){
    var i = $(this).attr('data');
    clearInterval(interval[i]);
});
$('.banners').mouseleave(function(){
    var i = $(this).attr('data');
    startInterval($(this),interval[i]);
});
Но тоже никаких результатов. ((( Листание так и не останавливается при наведении. И я даже не знаю, запустилось ли бы оно если бы остановилось.
 
Кароче я уже обессилен. Понимаю, что вроде задача простая, а я не могу её решить. От этого грустно. Но надо что-то решать, ибо работа стоит.
			
			
	
			
			
			
			
			
				  |  |  
	| 
		
	| 
			
			 
			
				02.03.2020, 15:16
			
			
			
		 |  
	| 
		
			
			| Профессор       |  | 
					Регистрация: 04.12.2012 
						Сообщений: 3,841
					 
		
 |  |  
	| Используете более осмысленные названия переменных, не стал разбираться, что у вас в коде происходит. 
Пример управляемого интервала:
 
<div><input type="number" readonly value="0"/></div>
<button type="button" data-action="pause">Pause</button>
<button type="button" data-action="resume">Resume</button>
<button type="button" data-action="destroy">Destroy</button>
<script>
var controlledInterval = function (callback, delay) {
    var args = [].slice.call(arguments, 2);
    
    var stepsPerLoop = 50,
        loopDelay = delay / stepsPerLoop,
        counter = 0,
        pause = false,
        timeout;
        
    timeout = setTimeout(function tik() {
        if (!pause) {
            counter += loopDelay;
        }
        
        if (counter >= delay) {
            callback.apply(window, args);
            
            counter = 0;
        }
        
        timeout = setTimeout(tik, loopDelay);
    }, loopDelay);
    
    return {
        pause: function () {
            pause = true;
        },
        resume: function () {
            pause = false;
        },
        destroy: function () {
            clearTimeout(timeout);
        }
    };
};
var input = document.querySelector('input'),
    interval = controlledInterval(function () {
        input.value = +input.value + 1;
    }, 1000);
document.querySelectorAll('[data-action]').forEach(function (node) {
    node.addEventListener('click', function () {
    	interval[this.dataset.action]();
    });
});
</script>
			
			
	
			
			
			
			
			
				  |  |  
	| 
		
	| 
			
			 
			
				02.03.2020, 15:31
			
			
			
		 |  
	| 
		
			|  | Профессор       |  | 
					Регистрация: 27.05.2010 
						Сообщений: 33,150
					 
		
 |  |  
	| 
				смена блоков с паузой при наведении курсора на родителя
			 imhateb,
 
<!DOCTYPE html>
<html>
<head>
  <title>Untitled</title>
  <meta charset="utf-8">
  <style type="text/css">
   .banners{
       height: 100px;
       width: 200px;
       border: 4px solid #FF4500;
       border-radius: 4px;
       margin: 10px;
   }
   .banners .item{
       display: none;
        height: 100%;
   }
   .banners .item.visible{
       display:  block;
   }
   .banners .item:nth-child(1){
        background-color: #0000FF;
   }
   .banners .item:nth-child(2){
        background-color: #FF0000;
   }
   .banners .item:nth-child(3){
        background-color: #808080;
   }
   .banners .item:nth-child(4){
        background-color: #FFFF00;
   }
   .banners .item:nth-child(5){
        background-color: #FF00FF;
   }
  </style>
   <script>
 document.addEventListener( "DOMContentLoaded" , function() {
 const pause = 1200;
 const pauseItem = ({timer}) => clearTimeout(timer);
 const showItem = banner => {
 pauseItem(banner);
 const children  = banner.children;
 const len = children.length;
 let index = [...children].indexOf(banner.querySelector(".visible")|| banner.lastElementChild);
 children[index].classList.remove("visible");
 index = ++index % len;
 children[index].classList.add("visible");
 banner.timer = setTimeout(showItem.bind(null, banner), pause);
 };
 for( const banner of document.querySelectorAll(".banners")) {
 banner.addEventListener("mouseleave", showItem.bind(null, banner));
 banner.addEventListener("mouseenter", pauseItem.bind(null, banner));
 showItem(banner);
 };
 });
  </script>
</head>
<body>
<div class="banners">
    <div class="item">01</div>
    <div class="item">02</div>
    <div class="item">03</div>
    <div class="item">04</div>
    <div class="item">05</div>
</div>
<div class="banners">
    <div class="item">01</div>
    <div class="item">02</div>
    <div class="item">03</div>
    <div class="item">04</div>
    <div class="item">05</div>
</div>
<div class="banners">
    <div class="item">01</div>
    <div class="item">02</div>
    <div class="item">03</div>
    <div class="item">04</div>
    <div class="item">05</div>
</div>
</body>
</html>
 
			
			
	
			
			
			
			
			
				  |  |  
	| 
		
	| 
			
			 
			
				02.03.2020, 15:56
			
			
			
		 |  
	| 
		
			
			| Интересующийся       |  | 
					Регистрация: 16.09.2013 
						Сообщений: 28
					 
		
 |  |  
	| рони, 
Спасибо большое. Это действительно то что нужно. Почти. 
 
Подскажите пожалуйста, как написать, чтобы вот тут 
 
const len = children.length;
 
cчитались только дети с классом .banner?
 
Просто внутри блока .banners есть ещё два блока (со стрелочками) и их учитывать не надо.
 
Сейчас у меня после последнего баннера показывается пустой блок. 			 Последний раз редактировалось imhateb, 02.03.2020 в 16:08.
 |  |  
	| 
		
	| 
			
			 
			
				02.03.2020, 16:11
			
			
			
		 |  
	| 
		
			|  | Профессор       |  | 
					Регистрация: 27.05.2010 
						Сообщений: 33,150
					 
		
 |  |  
	| imhateb,
  
const children  = banner.querySelectorAll(".banner");
       const len = children.length;
       let index = [...children].indexOf(banner.querySelector(".visible")|| children[len - 1]);
 |  |  
	| 
		
	| 
			
			 
			
				02.03.2020, 16:16
			
			
			
		 |  
	| 
		
			
			| Интересующийся       |  | 
					Регистрация: 16.09.2013 
						Сообщений: 28
					 
		
 |  |  
	| рони, спасибо. Я уже разобрался кажись)) 
Сделал вот так:
 
const children  = banner.getElementsByClassName('banner');
const len = children.length;
И всё заработало как надо. 
рони , огромное Вам спасибо за помощь. Даже не знаю как выразить свою признательность. Вы супер!   |  |  
	| 
		
	| 
			
			 
			
				02.03.2020, 16:58
			
			
			
		 |  
	| 
		
			
			| Интересующийся       |  | 
					Регистрация: 16.09.2013 
						Сообщений: 28
					 
		
 |  |  
	| Эмм, рони , неловко так. Только заметил, что не совсем всё гладко получилось. 
 
При наведении мыши баннеры останавливаются - с этим Ок. 
 
Но вот при mouseleave сразу происходит смена баннера - моментально. А должен запуститься интервал. Потому как на сайте эта резкая смена баннеров при отводе мышки смотрится очень убого и совсем не так как надо.
 
Я попробовал сделать вот так: вместо 
 
banner.addEventListener("mouseleave", showItem.bind(null, banner));
написал 
 
banner.addEventListener("mouseleave", function(){setTimeout(showItem.bind(null, banner), pause) });
Это вроде бы помогло, и после mouseleave баннер меняется не сразу, а с нужной задержкой. Т.е. то что я и хотел. 
 
Но тут вылезла другая проблема. Если несколько раз быстро подёргать мышку на блок с баннерами и обратно, то происходит лютая дичь. Спустя установленный интервал баннеры начинают очень быстро сменяться кратно количеству зафиксированных mouseenter'ов. 
 
Как это победить? Баннеры у меня не картинки, а блоки с текстом и ссылками. Допускаю, что подобные сценарии с многократным попаданием мыши на баннер будут весьма частым явлением.
			
			
	
			
			
			
			
			
				  |  |  
	| 
		
	| 
			
			 
			
				02.03.2020, 17:12
			
			
			
		 |  
	| 
		
			|  | Профессор       |  | 
					Регистрация: 27.05.2010 
						Сообщений: 33,150
					 
		
 |  |  
	| imhateb,
  
banner.addEventListener("mouseleave", () => {
 pauseItem(banner);
 banner.timer = setTimeout(showItem.bind(null, banner), pause)
 });
 			 Последний раз редактировалось рони, 02.03.2020 в 17:18.
				Причина: pauseItem добавил
 |  |  
	| 
		
	| 
			
			 
			
				02.03.2020, 17:18
			
			
			
		 |  
	| 
		
			
			| Интересующийся       |  | 
					Регистрация: 16.09.2013 
						Сообщений: 28
					 
		
 |  |  
	| рони, хочется Вас расцеловать. Спасибо огромнейшее! |  |  
	| 
		
	| 
			
			 
			
				03.03.2020, 01:50
			
			
			
		 |  
	| 
		
			
			| Профессор       |  | 
					Регистрация: 04.12.2012 
						Сообщений: 3,841
					 
		
 |  |  
	| 
<!DOCTYPE html>
<html>
<head>
<title>Untitled</title>
<meta charset="utf-8">
<style type="text/css">
    .banners{
       height: 100px;
       width: 200px;
       border: 4px solid #FF4500;
       border-radius: 4px;
       margin: 10px;
    }
    .banners .item{
       display: none;
        height: 100%;
    }
    .banners .item.visible{
       display:  block;
    }
    .banners .item:nth-child(1){
        background-color: #0000FF;
    }
    .banners .item:nth-child(2){
        background-color: #FF0000;
    }
    .banners .item:nth-child(3){
        background-color: #808080;
    }
    .banners .item:nth-child(4){
        background-color: #FFFF00;
    }
    .banners .item:nth-child(5){
        background-color: #FF00FF;
    }
</style>
<script>
    document.addEventListener('DOMContentLoaded', function() {
        var controlledInterval = function(callback, delay) {
            var args = [].slice.call(arguments, 2);
            var stepsPerLoop = 50,
                loopDelay = delay / stepsPerLoop,
                counter = 0,
                pause = false,
                timeout;
            timeout = setTimeout(function tik() {
                if (!pause) {
                    counter += loopDelay;
                }
                if (counter >= delay) {
                    callback.apply(window, args);
                    counter = 0;
                }
                timeout = setTimeout(tik, loopDelay);
            }, loopDelay);
            return {
                pause: function() {
                    pause = true;
                },
                resume: function() {
                    pause = false;
                },
                destroy: function() {
                    clearTimeout(timeout);
                }
            };
        };
        document.querySelectorAll('.banners').forEach(function(container) {
            var items = container.querySelectorAll('.item'),
                activeItemIndex = -1;
            var showNextItem = function() {
                if (items[activeItemIndex]) {
                    items[activeItemIndex].classList.remove('visible');
                }
                activeItemIndex = ++activeItemIndex % items.length;
                items[activeItemIndex].classList.add('visible');
            };
            showNextItem();
            var interval = controlledInterval(showNextItem, 1000);
            container.addEventListener('mouseenter', interval.pause);
            container.addEventListener('mouseleave', interval.resume);
        });
    });
</script>
</head>
<body>
    <div class="banners">
        <div class="item">01</div>
        <div class="item">02</div>
        <div class="item">03</div>
        <div class="item">04</div>
        <div class="item">05</div>
    </div>
    <div class="banners">
        <div class="item">01</div>
        <div class="item">02</div>
        <div class="item">03</div>
        <div class="item">04</div>
        <div class="item">05</div>
    </div>
    <div class="banners">
        <div class="item">01</div>
        <div class="item">02</div>
        <div class="item">03</div>
        <div class="item">04</div>
        <div class="item">05</div>
    </div>
</body>
</html>
			
			
	
			
			
			
			
			
				  |  |  |  |