요약:
나는 현재 브라우저에서 불가능한 범위 / 슬라이더 상호 작용에 일관되게 응답 할 수있는 jQuery가없는 브라우저 간 데스크탑 및 모바일 기능을 제공합니다. 기본적으로 모든 브라우저가 IE11의 on("change"...이벤트 on("change"...또는 이벤트에 대해 에뮬레이션하도록 강제 on("input"...합니다. 새로운 기능은 ...
function onRangeChange(r,f) {
var n,c,m;
r.addEventListener("input",function(e){n=1;c=e.target.value;if(c!=m)f(e);m=c;});
r.addEventListener("change",function(e){if(!n)f(e);});
}
... r범위 입력 요소이며 f청취자입니다. 리스너는 범위 / 슬라이더 값을 변경하는 모든 상호 작용 후에 호출되지만 현재 슬라이더 위치에서의 초기 마우스 또는 터치 상호 작용을 포함하여 또는 슬라이더의 한쪽 끝에서 벗어날 때 해당 값을 변경하지 않는 상호 작용 후에는 호출되지 않습니다.
문제:
2016 년 6 월 초 현재, 브라우저마다 범위 / 슬라이더 사용에 응답하는 방식이 다릅니다. 다섯 가지 시나리오가 관련됩니다.
- 현재 슬라이더 위치에서 초기 마우스 다운 (또는 터치 시작)
- 새로운 슬라이더 위치에서 초기 마우스 다운 (또는 터치 시작)
- 슬라이더를 따라 1 또는 2 이후의 후속 마우스 (또는 터치) 움직임
- 슬라이더의 한쪽 끝을지나 1 또는 2 이후의 후속 마우스 (또는 터치) 이동
- 최종 마우스 업 (또는 터치 엔드)
다음 표는 응답하는 위의 시나리오와 관련하여 적어도 3 개의 서로 다른 데스크탑 브라우저의 동작이 어떻게 다른지 보여줍니다.

해결책:
이 onRangeChange기능은 범위 / 슬라이더 상호 작용에 일관되고 예측 가능한 크로스 브라우저 응답을 제공합니다. 다음 표에 따라 모든 브라우저가 작동하도록합니다.

IE11에서이 코드는 기본적으로 모든 현상이 현상에 따라 작동 할 수 있도록합니다. 즉, "change"표준 방식으로 이벤트가 작동 하도록 허용 하며 "input"이벤트는 결코 발생하지 않으므로 관련이 없습니다. 다른 브라우저에서는 "change"이벤트가 효과적으로 묵음 처리됩니다 (추가적이고 때로는 준비되지 않은 이벤트가 발생하지 않도록). 또한 "input"이벤트는 범위 / 슬라이더의 값이 변경 될 때만 리스너를 시작합니다. 일부 브라우저 (예 : Firefox)의 경우 위 목록의 시나리오 1, 4 및 5에서 리스너가 효과적으로 침묵하기 때문에이 문제가 발생합니다.
(시나리오 1, 4 및 / 또는 5에서 리스너를 활성화해야하는 경우 "mousedown"/ "touchstart", "mousemove"/ "touchmove"및 / 또는 "mouseup"/ "touchend"이벤트를 통합 할 수 있습니다. 이러한 솔루션은이 답변의 범위를 벗어납니다.)
모바일 브라우저의 기능 :
데스크톱 브라우저에서는이 코드를 테스트했지만 모바일 브라우저에서는 테스트하지 않았습니다. 그러나이 페이지의 또 다른 대답에서 MBourne은 여기에서 내 솔루션이 "... 모든 브라우저에서 작동하는 것으로 보입니다 (Win 데스크톱 : IE, Chrome, Opera, FF; Android Chrome, Opera 및 FF, iOS Safari) " . (MBourne 감사합니다.)
용법:
이 솔루션을 사용하려면 onRangeChange자신의 코드에 위의 요약 (간체 / 최소화) 또는 아래의 데모 코드 스 니펫 (기능적으로 동일하지만 더 자명 한)의 함수를 포함 시키십시오. 다음과 같이 호출하십시오.
onRangeChange(myRangeInputElmt, myListener);
where myRangeInputElmt는 원하는 <input type="range">DOM 요소이며 -like 이벤트에서 myListener호출하려는 리스너 / 핸들러 함수 "change"입니다.
청취자는 원하는 경우 매개 변수가 없거나 event매개 변수를 사용할 수 있습니다. 즉, 필요에 따라 다음 중 하나가 작동합니다.
var myListener = function() {...
또는
var myListener = function(evt) {...
( input요소 에서 이벤트 리스너 제거 (예 :) 사용 removeEventListener)는이 답변에서 다루지 않습니다.
데모 설명 :
아래 코드 스 니펫에서이 함수 onRangeChange는 범용 솔루션을 제공합니다. 나머지 코드는 그 사용법을 보여주는 예제 일뿐입니다. 로 시작하는 모든 변수 my...는 범용 솔루션과 관련이 없으며 데모를 위해서만 존재합니다.
데모 범위 / 슬라이더 값뿐만 아니라 시간 기준 횟수 방송 "change", "input"커스텀 "onRangeChange"이벤트를 소성 한 (행 각각 A, B 및 C). 다른 브라우저에서이 스 니펫을 실행할 때 범위 / 슬라이더와 상호 작용할 때 다음 사항에 유의하십시오.
- IE11에서는 위의 시나리오 2와 3에서 행 A와 C의 값이 모두 변경되지만 행 B는 변경되지 않습니다.
- Chrome과 Safari에서 행 B와 C의 값은 시나리오 2와 3에서 모두 변경되지만 행 A는 시나리오 5에서만 변경됩니다.
- Firefox에서 행 A의 값은 시나리오 5에 대해서만 변경되고 행 B는 5 개의 시나리오 모두에 대해 변경되며 행 C는 시나리오 2와 3에 대해서만 변경됩니다.
- 위의 모든 브라우저에서 C 행 (제안 된 솔루션)의 변경 사항은 동일합니다 (예 : 시나리오 2 및 3).
데모 코드 :
// main function for emulating IE11's "change" event:
function onRangeChange(rangeInputElmt, listener) {
var inputEvtHasNeverFired = true;
var rangeValue = {current: undefined, mostRecent: undefined};
rangeInputElmt.addEventListener("input", function(evt) {
inputEvtHasNeverFired = false;
rangeValue.current = evt.target.value;
if (rangeValue.current !== rangeValue.mostRecent) {
listener(evt);
}
rangeValue.mostRecent = rangeValue.current;
});
rangeInputElmt.addEventListener("change", function(evt) {
if (inputEvtHasNeverFired) {
listener(evt);
}
});
}
// example usage:
var myRangeInputElmt = document.querySelector("input" );
var myRangeValPar = document.querySelector("#rangeValPar" );
var myNumChgEvtsCell = document.querySelector("#numChgEvtsCell");
var myNumInpEvtsCell = document.querySelector("#numInpEvtsCell");
var myNumCusEvtsCell = document.querySelector("#numCusEvtsCell");
var myNumEvts = {input: 0, change: 0, custom: 0};
var myUpdate = function() {
myNumChgEvtsCell.innerHTML = myNumEvts["change"];
myNumInpEvtsCell.innerHTML = myNumEvts["input" ];
myNumCusEvtsCell.innerHTML = myNumEvts["custom"];
};
["input", "change"].forEach(function(myEvtType) {
myRangeInputElmt.addEventListener(myEvtType, function() {
myNumEvts[myEvtType] += 1;
myUpdate();
});
});
var myListener = function(myEvt) {
myNumEvts["custom"] += 1;
myRangeValPar.innerHTML = "range value: " + myEvt.target.value;
myUpdate();
};
onRangeChange(myRangeInputElmt, myListener);
table {
border-collapse: collapse;
}
th, td {
text-align: left;
border: solid black 1px;
padding: 5px 15px;
}
<input type="range"/>
<p id="rangeValPar">range value: 50</p>
<table>
<tr><th>row</th><th>event type </th><th>number of events </th><tr>
<tr><td>A</td><td>standard "change" events </td><td id="numChgEvtsCell">0</td></tr>
<tr><td>B</td><td>standard "input" events </td><td id="numInpEvtsCell">0</td></tr>
<tr><td>C</td><td>new custom "onRangeChange" events</td><td id="numCusEvtsCell">0</td></tr>
</table>
신용:
여기서 구현은 주로 내 것이지만 MBourne의 대답 에서 영감을 얻었습니다 . 다른 답변은 "입력"및 "변경"이벤트를 병합 할 수 있으며 결과 코드는 데스크톱 및 모바일 브라우저 모두에서 작동 할 것이라고 제안했습니다. 그러나이 답변의 코드를 사용하면 숨겨진 "추가"이벤트가 발생하며 그 자체로 문제가 발생하며 발생하는 이벤트는 브라우저마다 다릅니다. 내 구현은 이러한 문제를 해결합니다.
키워드 :
JavaScript 입력 유형 범위 슬라이더 이벤트 변경 입력 브라우저 호환성 크로스 브라우저 데스크탑 모바일 no-jQuery
onchange발생하지 않습니다. 이 질문을 찾은 것은 해당 문제를 해결하는 데있었습니다.