Добавление / удаление Javascript EventListener не работает во время выполнения в пользовательских функциях jQuery - PullRequest
0 голосов
/ 11 марта 2019

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

<div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
<div class="snippet-code">
<pre class="snippet-code-js lang-js prettyprint-override"><code>var apprange = function () {
	function initAndSetupTheSliders(rangeValue, disabled = false,limitValue) {
		var inputs = [].slice.call(document.querySelectorAll('.range-slider input'));
		inputs.forEach(function (input) {return input.setAttribute('value', rangeValue);});
		inputs.forEach(function (input) {return apprange.updateSlider(input,limitValue, disabled);});
				// Cross-browser support where value changes instantly as you drag the handle, therefore two event types.
		if(!disabled){
############## Following two lines are not working as it should. ############
			inputs.forEach(function (input) {return input.addEventListener('input', eventHandler(input, limitValue, disabled));});
			inputs.forEach(function (input) {return input.addEventListener('change', eventHandler(input, limitValue, disabled));});
############# Code end ##################
		}else{
		inputs.forEach(function (input) {return input.removeEventListener('input', eventHandler(input, limitValue, disabled));});
		inputs.forEach(function (input) {return input.removeEventListener('change', eventHandler(input, limitValue, disabled));});
					console.log('#### 2');
				}
				
			}
			function eventHandler(input,limitValue, disabled){
				return apprange.updateSlider(input,limitValue, disabled);
			}
			function updateSlider(element, limitValue, disabled) {
				
			  if (element) {
				  
					var parent = element.parentElement,
					lastValue = parent.getAttribute('data-slider-value');

					if (lastValue === element.value) {
						return; // No value change, no need to update then
					}

					parent.setAttribute('data-slider-value', element.value);
					var $thumb = parent.querySelector('.range-slider__thumb'),
					$bar = parent.querySelector('.range-slider__bar'),
					$thumbLine = parent.querySelector('.range-slider__line'),
					pct = element.value * ((parent.clientHeight - $thumb.clientHeight) / parent.clientHeight);
																	pctLimitLine = limitValue * ((parent.clientHeight - $thumb.clientHeight) / parent.clientHeight);
					$thumb.style.bottom = pct + '%';
					$thumbLine.style.bottom = pctLimitLine + 7 + '%';
					$bar.style.height = 'calc(' + pct + '% + ' + $thumb.clientHeight / 2 + 'px)';
					$thumb.textContent = element.value + '';
																	
					document.getElementById('range').value = element.value;
					
					/* Emoticons Margins */
					if(disabled && false){
						var sliderHeight = parent.clientHeight;
						var multiplier = sliderHeight / 100;
						var UpperRegionHeight = (100 - limitValue) * multiplier;
						var LowerRegionHeight = sliderHeight - UpperRegionHeight;
						
						document.getElementsByClassName('icon_max_smily')[0].setAttribute("style", "height:"+UpperRegionHeight+"px");
						document.getElementsByClassName('icon_high_smily')[0].setAttribute("style", "height:"+(LowerRegionHeight/3)+"px");
						document.getElementsByClassName('icon_medium_smily')[0].setAttribute("style", "height:"+(LowerRegionHeight/3)+"px");
						document.getElementsByClassName('icon_low_smily')[0].setAttribute("style", "height:"+(LowerRegionHeight/3)+"px");
						if(document.getElementsByClassName('icon_max_smily')[1] !== undefined){
							document.getElementsByClassName('icon_max_smily')[1].setAttribute("style", "height:"+UpperRegionHeight+"px");
							document.getElementsByClassName('icon_high_smily')[1].setAttribute("style", "height:"+(LowerRegionHeight/3)+"px");
							document.getElementsByClassName('icon_medium_smily')[1].setAttribute("style", "height:"+(LowerRegionHeight/3)+"px");
							document.getElementsByClassName('icon_low_smily')[1].setAttribute("style", "height:"+(LowerRegionHeight/3)+"px");	
						}
						apprange.HighlightSmiley(limitValue, element.value);
					}
			  }
			}
			function HighlightSmiley(limitValue, selectedValue){
				if(selectedValue >= limitValue){
					console.log('if');
					document.getElementsByClassName('icon_max_smily')[0].querySelector('img').setAttribute("width", "70px");
					if(document.getElementsByClassName('icon_max_smily')[1] !== undefined){
						document.getElementsByClassName('icon_max_smily')[1].querySelector('img').setAttribute("width", "70px");
					}
				}else{
					var limitMultiplier = limitValue/3;
					if(selectedValue >= 0 && selectedValue < limitMultiplier){
						document.getElementsByClassName('icon_low_smily')[0].querySelector('img').setAttribute("width", "70px");
						if(document.getElementsByClassName('icon_low_smily')[1] !== undefined){
							document.getElementsByClassName('icon_low_smily')[1].querySelector('img').setAttribute("width", "70px");
						}
					}else if(selectedValue >= limitMultiplier && selectedValue < 2*limitMultiplier){
						document.getElementsByClassName('icon_medium_smily')[0].querySelector('img').setAttribute("width", "70px");
						if(document.getElementsByClassName('icon_medium_smily')[1] !== undefined){
							document.getElementsByClassName('icon_medium_smily')[1].querySelector('img').setAttribute("width", "70px");
						}
					}else if(selectedValue >= 2*limitMultiplier && selectedValue < limitValue){
						document.getElementsByClassName('icon_high_smily')[0].querySelector('img').setAttribute("width", "70px");
						if(document.getElementsByClassName('icon_high_smily')[1] !== undefined){
							document.getElementsByClassName('icon_high_smily')[1].querySelector('img').setAttribute("width", "70px");
						}
					}
				}
			}

			function removeEventHandler(){

			}
			return {
					initAndSetupTheSliders: initAndSetupTheSliders,
					updateSlider: updateSlider,
					HighlightSmiley: HighlightSmiley,
					eventHandler: eventHandler};
	}();
	
    *, *:before, *:after {
      box-sizing: border-box;
    }

    html,
    body {
      height: 100%;
    }

    body {
      margin: 0;
      background: #3D3D4A;
      color: white;
      min-height: 400px;
      font-family: sans-serif;
    }

    .info {
      position: absolute;
      top: 0;
      left: 0;
      padding: 10px;
      opacity: .5;
    }

    .container {
      padding-top: 40px;
      position: relative;
      display: inline-block;
      top: 100%;
      left: 50%;
      transform: translate(-50%, -100%);
      padding-bottom: 20px;
    }
    @media (min-height: 500px) {
      .container {
        position: absolute;
        top: 50%;
        transform: translate(-50%, -50%);
        padding-bottom: 0;
      }
    }

    .range-slider {
      display: inline-block;
      width: 40px;
      position: relative;
      text-align: center;
      height: 300px;
      max-height: 100%;
    }
    .range-slider:before {
      position: absolute;
      top: -2em;
      left: .5em;
      content: attr(data-slider-value) "%";
      color: white;
      font-size: 90%;
    }
    .range-slider__thumb {
      position: absolute;
      left: 5px;
      width: 30px;
      height: 30px;
      line-height: 30px;
      background: white;
      color: #777;
      font-size: 50%;
      box-shadow: 0 0 0 4px #3D3D4A;
      border-radius: 50%;
      pointer-events: none;
    }
    .range-slider__bar {
      left: 12px;
      bottom: 0;
      position: absolute;
      background: linear-gradient(to left, #ffc000 37%, #c64e13 50%);
      pointer-events: none;
      width: 18px;
      border-radius: 10px;
    }
    .range-slider input[type=range][orient=vertical] {
      position: relative;
      margin: 0;
      height: 100%;
      width: 100%;
      display: inline-block;
      position: relative;
      writing-mode: bt-lr;
      -webkit-appearance: slider-vertical;
    }
    .range-slider input[type=range][orient=vertical]::-webkit-slider-runnable-track, .range-slider input[type=range][orient=vertical]::-webkit-slider-thumb {
      -webkit-appearance: none;
    }
    .range-slider input[type=range][orient=vertical]::-webkit-slider-runnable-track {
      border: none;
      background: #343440;
      width: 18px;
      border-color: #343440;
      border-radius: 10px;
      box-shadow: 0 0 0 2px #3D3D4A;
    }
    .range-slider input[type=range][orient=vertical]::-moz-range-track {
      border: none;
      background: #343440;
      width: 18px;
      border-color: #343440;
      border-radius: 10px;
      box-shadow: 0 0 0 2px #3D3D4A;
    }
    .range-slider input[type=range][orient=vertical]::-ms-track {
      border: none;
      background: white;
      width: 18px;
      border-color: #343440;
      border-radius: 10px;
      box-shadow: 0 0 0 2px #3D3D4A;
      color: transparent;
      height: 100%;
    }
    .range-slider input[type=range][orient=vertical]::-ms-fill-lower, .range-slider input[type=range][orient=vertical]::-ms-fill-upper, .range-slider input[type=range][orient=vertical]::-ms-tooltip {
      display: none;
    }
    .range-slider input[type=range][orient=vertical]::-webkit-slider-thumb {
      width: 30px;
      height: 30px;
      opacity: 0;
    }
    .range-slider input[type=range][orient=vertical]::-moz-range-thumb {
      width: 30px;
      height: 30px;
      opacity: 0;
    }
    .range-slider input[type=range][orient=vertical]::-ms-thumb {
      width: 30px;
      height: 30px;
      opacity: 0;
    }

    .theme1 {
      background: linear-gradient(pink, deeppink);
    }

    .theme2 {
      background: linear-gradient(tomato, red);
    }

    .theme3 {
      background: linear-gradient(yellow, orange);
    }
    <div class="container">

      <div class="range-slider">
        <input type="range" orient="vertical" min="0" max="100" />
        <div class="range-slider__bar"></div>
        <div class="range-slider__thumb"></div>
      </div>
    </div>

1 Ответ

1 голос
/ 11 марта 2019

Я думаю, вы не понимаете, как работают функции, когда они передаются в качестве параметров - вы делаете то же самое и с addEventListener, и с forEach. Возьмите одну строку вашего решения:

inputs.forEach(function (input) {return input.setAttribute('value', '50');});

Это создает N функций (по одной для каждого из inputs), которые все делают одно и то же: принимают элемент ввода и устанавливают атрибут value этого элемента равным 50. Поскольку все они выполняют одно и то же, вы можете так же хорошо, скажи,

inputs.forEach(fixIt);
function fixIt(input) {
    input.setAttribute('value', '50');
}

То же самое относится и к addEventListener, но обработчики событий уже имеют доступ к элементу, который вызвал их через evt.target. Вместо

element.addEventListener('input', function (evt) {return app.updateSlider(element);});

Вы можете сказать,

element.addEventListener('input', eventHandler);
function eventHandler(evt) {
    app.updateSlider(evt.target);
}

Тогда становится просто сказать,

element.removeEventListener('input', eventHandler);

Наконец, похоже, что все inputs инициализируются одинаково, поэтому вы можете использовать одну и ту же функцию для их инициализации:

(function initAndSetupTheSliders() {
    var inputs = [].slice.call(document.querySelectorAll('.range-slider input'));
    inputs.forEach(function (input) {return input.setAttribute('value', '50');});
    inputs.forEach(function (input) {return app.updateSlider(input);});
    // Cross-browser support where value changes instantly as you drag the handle, therefore two event types.
    inputs.forEach(function (input) {return input.addEventListener('input', function (element) {return app.updateSlider(input);});});
    inputs.forEach(function (input) {return input.addEventListener('change', function (element) {return app.updateSlider(input);});});
})();

становится:

function initSlider(element) {
    element.setAttribute('value', '50');
    app.updateSlider(element);
    element.addEventListener('input', function (evt) {return app.updateSlider(element);});
    element.addEventListener('change', function (evt) {return app.updateSlider(element);});
}

document.querySelectorAll('.range-slider input')).forEach(initSlider);

Так что все вместе, чтобы избежать анонимных функций и добавить возможность отключить слайдер, у вас будет:

function initSlider(element) {
    element.setAttribute('value', '50');
    app.updateSlider(element);
    element.addEventListener('input', eventHandler);
    element.addEventListener('change', eventHandler);
}

document.querySelectorAll('.range-slider input').forEach(initSlider)

function eventHandler(evt) {
    return app.updateSlider(evt.target);
}

function unInitSlider(element) {
    element.removeEventListener('input', eventHandler);
    element.removeEventListener('change', eventHandler);
}

unInitSlider(document.querySelectorAll('.range-slider input')[1]);
...